Coverage for src/fastapi_cloud_cli/commands/deploy/wait.py: 100%

89 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-11-09 00:25 +0000

1import contextlib 2lcmcncocpcqcrc

2import time 2lcmcncocpcqcrc

3from itertools import cycle 2lcmcncocpcqcrc

4from textwrap import dedent 2lcmcncocpcqcrc

5 

6import typer 2lcmcncocpcqcrc

7from httpx import HTTPError 2lcmcncocpcqcrc

8from rich.text import Text 2lcmcncocpcqcrc

9from rich_toolkit import RichToolkit 2lcmcncocpcqcrc

10 

11from fastapi_cloud_cli.api import ( 2lcmcncocpcqcrc

12 SUCCESSFUL_STATUSES, 

13 APIClient, 

14 BuildFailure, 

15 DeploymentStatus, 

16 StreamLogError, 

17 TooManyRetriesError, 

18) 

19from fastapi_cloud_cli.commands.deploy.cloud import CreateDeploymentResponse 2lcmcncocpcqcrc

20from fastapi_cloud_cli.utils.build_logs import print_build_error 2lcmcncocpcqcrc

21from fastapi_cloud_cli.utils.cli import FastAPIRichToolkit 2lcmcncocpcqcrc

22from fastapi_cloud_cli.utils.execution import is_ci_enabled 2lcmcncocpcqcrc

23 

24# The build finished but we couldn't confirm the deployment came up. Distinct 

25# from 1 so scripts can tell "still verifying" from "failed". 

26UNCONFIRMED_EXIT_CODE = 3 2lcmcncocpcqcrc

27 

28# (bullet emoji, message) — the emoji replaces the progress animation 

29WAITING_MESSAGES = [ 2lcmcncocpcqcrc

30 ("🚀", "Preparing for liftoff! Almost there..."), 

31 ("👹", "Sneaking past the dependency gremlins... Don't wake them up!"), 

32 ("🤏", "Squishing code into a tiny digital sandwich. Nom nom nom."), 

33 ("🐱", "Removing cat videos from our servers to free up space."), 

34 ("🐢", "Uploading at blazing speeds of 1 byte per hour. Patience, young padawan."), 

35 ("🔌", "Connecting to server... Please stand by while we argue with the firewall."), 

36 ( 

37 "💥", 

38 "Oops! We've angered the Python God. Sacrificing a rubber duck to appease it.", 

39 ), 

40 ("🧙", "Sprinkling magic deployment dust. Abracadabra!"), 

41 ("👀", "Hoping that @tiangolo doesn't find out about this deployment."), 

42 ("🍪", "Cookie monster detected on server. Deploying anti-cookie shields."), 

43] 

44 

45LONG_WAIT_MESSAGES = [ 2lcmcncocpcqcrc

46 ( 

47 "😅", 

48 "Well, that's embarrassing. We're still waiting for the deployment to finish...", 

49 ), 

50 ("🤔", "Maybe we should have brought snacks for this wait..."), 

51 ("🥱", "Yawn... Still waiting..."), 

52 ("🤯", "Time is relative... Especially when you're waiting for a deployment..."), 

53] 

54 

55 

56def _verify_deployment( 2lcmcncocpcqcrc

57 toolkit: RichToolkit, 

58 client: APIClient, 

59 deployment: CreateDeploymentResponse, 

60) -> None: 

61 failed_status: str | None = None 2|bj C D E F G H I J K L M N O a P Q c R S k T ~bs $ % ' ( ) * + , - . / : ; d = ? l @ [ t ] acu ^ _ ` { | } ~ abbbcbdbebfbe gbhbm ibjbv kbbcw lbmbnbobpbqbrbsbtbubvbwbxbf ybzbn AbBbx Cb}bo U V W X Y Z 0 1 2 3 4 5 6 b 7 8 g 9 ! p # ccy DbEbFbGbHbIbJbKbLbMbNbObPbh QbRbq SbTbz UbdcA VbWbXbYbZb0b1b2b3b4b5b6b7bi 8b9br !b#bB $b

62 unconfirmed = False 2|bj C D E F G H I J K L M N O a P Q c R S k T ~bs $ % ' ( ) * + , - . / : ; d = ? l @ [ t ] acu ^ _ ` { | } ~ abbbcbdbebfbe gbhbm ibjbv kbbcw lbmbnbobpbqbrbsbtbubvbwbxbf ybzbn AbBbx Cb}bo U V W X Y Z 0 1 2 3 4 5 6 b 7 8 g 9 ! p # ccy DbEbFbGbHbIbJbKbLbMbNbObPbh QbRbq SbTbz UbdcA VbWbXbYbZb0b1b2b3b4b5b6b7bi 8b9br !b#bB $b

63 

64 with toolkit.progress( 2|bj C D E F G H I J K L M N O a P Q c R S k T ~bs $ % ' ( ) * + , - . / : ; d = ? l @ [ t ] acu ^ _ ` { | } ~ abbbcbdbebfbe gbhbm ibjbv kbbcw lbmbnbobpbqbrbsbtbubvbwbxbf ybzbn AbBbx Cb}bo U V W X Y Z 0 1 2 3 4 5 6 b 7 8 g 9 ! p # ccy DbEbFbGbHbIbJbKbLbMbNbObPbh QbRbq SbTbz UbdcA VbWbXbYbZb0b1b2b3b4b5b6b7bi 8b9br !b#bB $b

65 title="Verifying deployment...", 

66 inline_logs=True, 

67 done_emoji="✅", 

68 ) as progress: 

69 try: 2|bj C D E F G H I J K L M N O a P Q c R S k T ~bs $ % ' ( ) * + , - . / : ; d = ? l @ [ t ] acu ^ _ ` { | } ~ abbbcbdbebfbe gbhbm ibjbv kbbcw lbmbnbobpbqbrbsbtbubvbwbxbf ybzbn AbBbx Cb}bo U V W X Y Z 0 1 2 3 4 5 6 b 7 8 g 9 ! p # ccy DbEbFbGbHbIbJbKbLbMbNbObPbh QbRbq SbTbz UbdcA VbWbXbYbZb0b1b2b3b4b5b6b7bi 8b9br !b#bB $b

70 final_status = client.poll_deployment_status(deployment.id) 2|bj C D E F G H I J K L M N O a P Q c R S k T ~bs $ % ' ( ) * + , - . / : ; d = ? l @ [ t ] acu ^ _ ` { | } ~ abbbcbdbebfbe gbhbm ibjbv kbbcw lbmbnbobpbqbrbsbtbubvbwbxbf ybzbn AbBbx Cb}bo U V W X Y Z 0 1 2 3 4 5 6 b 7 8 g 9 ! p # ccy DbEbFbGbHbIbJbKbLbMbNbObPbh QbRbq SbTbz UbdcA VbWbXbYbZb0b1b2b3b4b5b6b7bi 8b9br !b#bB $b

71 except (TimeoutError, TooManyRetriesError, StreamLogError): 2|bP ~b= acgbbcyb}b7 ccQbdc8b

72 progress.metadata["done_emoji"] = "⚠️" 2P = gbyb7 Qb8b

73 progress.current_message = ( 2P = gbyb7 Qb8b

74 f"Could not confirm deployment status. " 

75 f"Check the dashboard: [link={deployment.dashboard_url}]{deployment.dashboard_url}[/link]" 

76 ) 

77 unconfirmed = True 2P = gbyb7 Qb8b

78 else: 

79 if final_status in SUCCESSFUL_STATUSES: 2j C D E F G H I J K L M N O a Q c R S k T s $ % ' ( ) * + , - . / : ; d ? l @ [ t ] u ^ _ ` { | } ~ abbbcbdbebfbe hbm ibjbv kbw lbmbnbobpbqbrbsbtbubvbwbxbf zbn AbBbx Cbo U V W X Y Z 0 1 2 3 4 5 6 b 8 g 9 ! p # y DbEbFbGbHbIbJbKbLbMbNbObPbh Rbq SbTbz UbA VbWbXbYbZb0b1b2b3b4b5b6b7bi 9br !b#bB $b

80 progress.current_message = "Ready the chicken! 🐔" 2C D E F G H I J K L M N O a Q c R S T $ % ' ( ) * + , - . / : ; d ? l @ [ ] ^ _ ` { | } ~ abbbcbdbebfbe hbm ibjbkblbmbnbobpbqbrbsbtbubvbwbxbf zbn AbBbCbU V W X Y Z 0 1 2 3 4 5 6 b 8 g 9 ! # DbEbFbGbHbIbJbKbLbMbNbObPbh Rbq SbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7bi 9br !b#b$b

81 else: 

82 progress.metadata["done_emoji"] = "❌" 1jkstuvwxopyzAB

83 progress.current_message = "Deployment failed" 1jkstuvwxopyzAB

84 

85 failed_status = DeploymentStatus.to_human_readable(final_status) 1jkstuvwxopyzAB

86 

87 if unconfirmed: 2j C D E F G H I J K L M N O a P Q c R S k T s $ % ' ( ) * + , - . / : ; d = ? l @ [ t ] u ^ _ ` { | } ~ abbbcbdbebfbe gbhbm ibjbv kbw lbmbnbobpbqbrbsbtbubvbwbxbf ybzbn AbBbx Cbo U V W X Y Z 0 1 2 3 4 5 6 b 7 8 g 9 ! p # y DbEbFbGbHbIbJbKbLbMbNbObPbh QbRbq SbTbz UbA VbWbXbYbZb0b1b2b3b4b5b6b7bi 8b9br !b#bB $b

88 raise typer.Exit(UNCONFIRMED_EXIT_CODE) 2P = gbyb7 Qb8b

89 

90 if failed_status is not None: 2j C D E F G H I J K L M N O a Q c R S k T s $ % ' ( ) * + , - . / : ; d ? l @ [ t ] u ^ _ ` { | } ~ abbbcbdbebfbe hbm ibjbv kbw lbmbnbobpbqbrbsbtbubvbwbxbf zbn AbBbx Cbo U V W X Y Z 0 1 2 3 4 5 6 b 8 g 9 ! p # y DbEbFbGbHbIbJbKbLbMbNbObPbh Rbq SbTbz UbA VbWbXbYbZb0b1b2b3b4b5b6b7bi 9br !b#bB $b

91 toolkit.print_line() 1jkstuvwxopyzAB

92 toolkit.print( 1jkstuvwxopyzAB

93 f"Oh no! Deployment failed: {failed_status}. " 

94 f"Check out the logs at [link={deployment.dashboard_url}]{deployment.dashboard_url}[/link]", 

95 emoji="😔", 

96 ) 

97 raise typer.Exit(1) 1jkstuvwxopyzAB

98 

99 toolkit.print_line() 2C D E F G H I J K L M N O a Q c R S T $ % ' ( ) * + , - . / : ; d ? l @ [ ] ^ _ ` { | } ~ abbbcbdbebfbe hbm ibjbkblbmbnbobpbqbrbsbtbubvbwbxbf zbn AbBbCbU V W X Y Z 0 1 2 3 4 5 6 b 8 g 9 ! # DbEbFbGbHbIbJbKbLbMbNbObPbh Rbq SbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7bi 9br !b#b$b

100 toolkit.print( 2C D E F G H I J K L M N O a Q c R S T $ % ' ( ) * + , - . / : ; d ? l @ [ ] ^ _ ` { | } ~ abbbcbdbebfbe hbm ibjbkblbmbnbobpbqbrbsbtbubvbwbxbf zbn AbBbCbU V W X Y Z 0 1 2 3 4 5 6 b 8 g 9 ! # DbEbFbGbHbIbJbKbLbMbNbObPbh Rbq SbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7bi 9br !b#b$b

101 f"Your app is ready at [link={deployment.url}]{deployment.url}[/link]" 

102 ) 

103 

104 

105def _wait_for_deployment( 2lcmcncocpcqcrc

106 toolkit: FastAPIRichToolkit, 

107 client: APIClient, 

108 app_id: str, 

109 deployment: CreateDeploymentResponse, 

110) -> None: 

111 messages = cycle(WAITING_MESSAGES) 2Gc|bj C %bD E F G 'bH I J *bK L M N O a P Q c sctcecR S k T Ic~bs $ +b% ' ( ) ,b* + , ]b- . / : ; d = ? l wcxcgc@ [ t ] Jcacu ^ -b_ ` { | .b} ~ ab^bbbcbdbebfbe gbhbm yczchcibjbv kbKcbcw lb/bmbnbobpb:bqbrbsb_btbubvbwbxbf ybzbn AcBcicAbBbx CbHc}bo U (bV W X Y )bZ 0 1 ;b2 3 4 5 6 b 7 8 g ucvcfc9 ! p # Lcccy Db=bEbFbGbHb?bIbJbKb`bLbMbNbObPbh QbRbq CcDcjcSbTbz UbMcdcA Vb@bWbXbYbZb[b0b1b2b{b3b4b5b6b7bi 8b9br EcFckc!b#bB $b

112 

113 time_elapsed = 0.0 2Gc|bj C %bD E F G 'bH I J *bK L M N O a P Q c sctcecR S k T Ic~bs $ +b% ' ( ) ,b* + , ]b- . / : ; d = ? l wcxcgc@ [ t ] Jcacu ^ -b_ ` { | .b} ~ ab^bbbcbdbebfbe gbhbm yczchcibjbv kbKcbcw lb/bmbnbobpb:bqbrbsb_btbubvbwbxbf ybzbn AcBcicAbBbx CbHc}bo U (bV W X Y )bZ 0 1 ;b2 3 4 5 6 b 7 8 g ucvcfc9 ! p # Lcccy Db=bEbFbGbHb?bIbJbKb`bLbMbNbObPbh QbRbq CcDcjcSbTbz UbMcdcA Vb@bWbXbYbZb[b0b1b2b{b3b4b5b6b7bi 8b9br EcFckc!b#bB $b

114 

115 started_at = time.monotonic() 2Gc|bj C %bD E F G 'bH I J *bK L M N O a P Q c sctcecR S k T Ic~bs $ +b% ' ( ) ,b* + , ]b- . / : ; d = ? l wcxcgc@ [ t ] Jcacu ^ -b_ ` { | .b} ~ ab^bbbcbdbebfbe gbhbm yczchcibjbv kbKcbcw lb/bmbnbobpb:bqbrbsb_btbubvbwbxbf ybzbn AcBcicAbBbx CbHc}bo U (bV W X Y )bZ 0 1 ;b2 3 4 5 6 b 7 8 g ucvcfc9 ! p # Lcccy Db=bEbFbGbHb?bIbJbKb`bLbMbNbObPbh QbRbq CcDcjcSbTbz UbMcdcA Vb@bWbXbYbZb[b0b1b2b{b3b4b5b6b7bi 8b9br EcFckc!b#bB $b

116 

117 last_message_changed_at = time.monotonic() 2Gc|bj C %bD E F G 'bH I J *bK L M N O a P Q c sctcecR S k T Ic~bs $ +b% ' ( ) ,b* + , ]b- . / : ; d = ? l wcxcgc@ [ t ] Jcacu ^ -b_ ` { | .b} ~ ab^bbbcbdbebfbe gbhbm yczchcibjbv kbKcbcw lb/bmbnbobpb:bqbrbsb_btbubvbwbxbf ybzbn AcBcicAbBbx CbHc}bo U (bV W X Y )bZ 0 1 ;b2 3 4 5 6 b 7 8 g ucvcfc9 ! p # Lcccy Db=bEbFbGbHb?bIbJbKb`bLbMbNbObPbh QbRbq CcDcjcSbTbz UbMcdcA Vb@bWbXbYbZb[b0b1b2b{b3b4b5b6b7bi 8b9br EcFckc!b#bB $b

118 

119 with ( 2Gc|bj C %bD E F G 'bH I J *bK L M N O a P Q c sctcecR S k T Hc}bo U (bV W X Y )bZ 0 1 ;b2 3 4 5 6 b 7 8 g ucvcfc9 ! p #

120 toolkit.progress( 

121 "Checking the status of your deployment", 

122 inline_logs=True, 

123 lines_to_show=20, 

124 # Keep the log panel replaceable by a diagnosis, but retain CI logs. 

125 preserve_logs=is_ci_enabled(), 

126 emoji="👀", 

127 done_emoji="🚀", 

128 ) as progress, 

129 ): 

130 build_complete = False 2Gc|bj C %bD E F G 'bH I J *bK L M N O a P Q c sctcecR S k T Ic~bs $ +b% ' ( ) ,b* + , ]b- . / : ; d = ? l wcxcgc@ [ t ] Jcacu ^ -b_ ` { | .b} ~ ab^bbbcbdbebfbe gbhbm yczchcibjbv kbKcbcw lb/bmbnbobpb:bqbrbsb_btbubvbwbxbf ybzbn AcBcicAbBbx CbHc}bo U (bV W X Y )bZ 0 1 ;b2 3 4 5 6 b 7 8 g ucvcfc9 ! p # Lcccy Db=bEbFbGbHb?bIbJbKb`bLbMbNbObPbh QbRbq CcDcjcSbTbz UbMcdcA Vb@bWbXbYbZb[b0b1b2b{b3b4b5b6b7bi 8b9br EcFckc!b#bB $b

131 build_failed = False 2Gc|bj C %bD E F G 'bH I J *bK L M N O a P Q c sctcecR S k T Ic~bs $ +b% ' ( ) ,b* + , ]b- . / : ; d = ? l wcxcgc@ [ t ] Jcacu ^ -b_ ` { | .b} ~ ab^bbbcbdbebfbe gbhbm yczchcibjbv kbKcbcw lb/bmbnbobpb:bqbrbsb_btbubvbwbxbf ybzbn AcBcicAbBbx CbHc}bo U (bV W X Y )bZ 0 1 ;b2 3 4 5 6 b 7 8 g ucvcfc9 ! p # Lcccy Db=bEbFbGbHb?bIbJbKb`bLbMbNbObPbh QbRbq CcDcjcSbTbz UbMcdcA Vb@bWbXbYbZb[b0b1b2b{b3b4b5b6b7bi 8b9br EcFckc!b#bB $b

132 build_error: BuildFailure | None = None 2Gc|bj C %bD E F G 'bH I J *bK L M N O a P Q c sctcecR S k T Ic~bs $ +b% ' ( ) ,b* + , ]b- . / : ; d = ? l wcxcgc@ [ t ] Jcacu ^ -b_ ` { | .b} ~ ab^bbbcbdbebfbe gbhbm yczchcibjbv kbKcbcw lb/bmbnbobpb:bqbrbsb_btbubvbwbxbf ybzbn AcBcicAbBbx CbHc}bo U (bV W X Y )bZ 0 1 ;b2 3 4 5 6 b 7 8 g ucvcfc9 ! p # Lcccy Db=bEbFbGbHb?bIbJbKb`bLbMbNbObPbh QbRbq CcDcjcSbTbz UbMcdcA Vb@bWbXbYbZb[b0b1b2b{b3b4b5b6b7bi 8b9br EcFckc!b#bB $b

133 

134 try: 2Gc|bj C %bD E F G 'bH I J *bK L M N O a P Q c sctcecR S k T Ic~bs $ +b% ' ( ) ,b* + , ]b- . / : ; d = ? l wcxcgc@ [ t ] Jcacu ^ -b_ ` { | .b} ~ ab^bbbcbdbebfbe gbhbm yczchcibjbv kbKcbcw lb/bmbnbobpb:bqbrbsb_btbubvbwbxbf ybzbn AcBcicAbBbx CbHc}bo U (bV W X Y )bZ 0 1 ;b2 3 4 5 6 b 7 8 g ucvcfc9 ! p # Lcccy Db=bEbFbGbHb?bIbJbKb`bLbMbNbObPbh QbRbq CcDcjcSbTbz UbMcdcA Vb@bWbXbYbZb[b0b1b2b{b3b4b5b6b7bi 8b9br EcFckc!b#bB $b

135 for log in client.stream_build_logs(deployment.id): 2Gc|bj C %bD E F G 'bH I J *bK L M N O a P Q c sctcecR S k T Ic~bs $ +b% ' ( ) ,b* + , ]b- . / : ; d = ? l wcxcgc@ [ t ] Jcacu ^ -b_ ` { | .b} ~ ab^bbbcbdbebfbe gbhbm yczchcibjbv kbKcbcw lb/bmbnbobpb:bqbrbsb_btbubvbwbxbf ybzbn AcBcicAbBbx CbHc}bo U (bV W X Y )bZ 0 1 ;b2 3 4 5 6 b 7 8 g ucvcfc9 ! p # Lcccy Db=bEbFbGbHb?bIbJbKb`bLbMbNbObPbh QbRbq CcDcjcSbTbz UbMcdcA Vb@bWbXbYbZb[b0b1b2b{b3b4b5b6b7bi 8b9br EcFckc!b#bB $b

136 time_elapsed = time.monotonic() - started_at 2|bj C %bD E F G 'bH I J *bK L M N O a P Q c ecR S k T ~bs $ +b% ' ( ) ,b* + , ]b- . / : ; d = ? l gc@ [ t ] acu ^ -b_ ` { | .b} ~ ab^bbbcbdbebfbe gbhbm hcibjbv kbbcw lb/bmbnbobpb:bqbrbsb_btbubvbwbxbf ybzbn icAbBbx Cb}bo U (bV W X Y )bZ 0 1 ;b2 3 4 5 6 b 7 8 g fc9 ! p # ccy Db=bEbFbGbHb?bIbJbKb`bLbMbNbObPbh QbRbq jcSbTbz UbdcA Vb@bWbXbYbZb[b0b1b2b{b3b4b5b6b7bi 8b9br kc!b#bB $b

137 

138 if log.type == "message": 2|bj C %bD E F G 'bH I J *bK L M N O a P Q c ecR S k T ~bs $ +b% ' ( ) ,b* + , ]b- . / : ; d = ? l gc@ [ t ] acu ^ -b_ ` { | .b} ~ ab^bbbcbdbebfbe gbhbm hcibjbv kbbcw lb/bmbnbobpb:bqbrbsb_btbubvbwbxbf ybzbn icAbBbx Cb}bo U (bV W X Y )bZ 0 1 ;b2 3 4 5 6 b 7 8 g fc9 ! p # ccy Db=bEbFbGbHb?bIbJbKb`bLbMbNbObPbh QbRbq jcSbTbz UbdcA Vb@bWbXbYbZb[b0b1b2b{b3b4b5b6b7bi 8b9br kc!b#bB $b

139 progress.log(Text.from_ansi(log.message.rstrip())) 2|bj C %bD E F G 'bH I J *bK L M N O a P Q c R S k T ~bs $ +b% ' ( ) ,b* + , ]b- . / : ; d = ? l @ [ t ] acu ^ -b_ ` { | .b} ~ ab^bbbcbdbebfbe gbhbm ibjbv kbbcw lb/bmbnbobpb:bqbrbsb_btbubvbwbxbf ybzbn AbBbx Cb}bo U (bV W X Y )bZ 0 1 ;b2 3 4 5 6 b 7 8 g 9 ! p # ccy Db=bEbFbGbHb?bIbJbKb`bLbMbNbObPbh QbRbq SbTbz UbdcA Vb@bWbXbYbZb[b0b1b2b{b3b4b5b6b7bi 8b9br !b#bB $b

140 

141 if log.type == "complete": 2|bj C %bD E F G 'bH I J *bK L M N O a P Q c ecR S k T ~bs $ +b% ' ( ) ,b* + , ]b- . / : ; d = ? l gc@ [ t ] acu ^ -b_ ` { | .b} ~ ab^bbbcbdbebfbe gbhbm hcibjbv kbbcw lb/bmbnbobpb:bqbrbsb_btbubvbwbxbf ybzbn icAbBbx Cb}bo U (bV W X Y )bZ 0 1 ;b2 3 4 5 6 b 7 8 g fc9 ! p # ccy Db=bEbFbGbHb?bIbJbKb`bLbMbNbObPbh QbRbq jcSbTbz UbdcA Vb@bWbXbYbZb[b0b1b2b{b3b4b5b6b7bi 8b9br kc!b#bB $b

142 build_complete = True 2|bj C D E F G H I J K L M N O a P Q c R S k T ~bs $ % ' ( ) * + , - . / : ; d = ? l @ [ t ] acu ^ _ ` { | } ~ abbbcbdbebfbe gbhbm ibjbv kbbcw lbmbnbobpbqbrbsbtbubvbwbxbf ybzbn AbBbx Cb}bo U V W X Y Z 0 1 2 3 4 5 6 b 7 8 g 9 ! p # ccy DbEbFbGbHbIbJbKbLbMbNbObPbh QbRbq SbTbz UbdcA VbWbXbYbZb0b1b2b3b4b5b6b7bi 8b9br !b#bB $b

143 progress.title = "Build complete!" 2|bj C D E F G H I J K L M N O a P Q c R S k T ~bs $ % ' ( ) * + , - . / : ; d = ? l @ [ t ] acu ^ _ ` { | } ~ abbbcbdbebfbe gbhbm ibjbv kbbcw lbmbnbobpbqbrbsbtbubvbwbxbf ybzbn AbBbx Cb}bo U V W X Y Z 0 1 2 3 4 5 6 b 7 8 g 9 ! p # ccy DbEbFbGbHbIbJbKbLbMbNbObPbh QbRbq SbTbz UbdcA VbWbXbYbZb0b1b2b3b4b5b6b7bi 8b9br !b#bB $b

144 break 2|bj C D E F G H I J K L M N O a P Q c R S k T ~bs $ % ' ( ) * + , - . / : ; d = ? l @ [ t ] acu ^ _ ` { | } ~ abbbcbdbebfbe gbhbm ibjbv kbbcw lbmbnbobpbqbrbsbtbubvbwbxbf ybzbn AbBbx Cb}bo U V W X Y Z 0 1 2 3 4 5 6 b 7 8 g 9 ! p # ccy DbEbFbGbHbIbJbKbLbMbNbObPbh QbRbq SbTbz UbdcA VbWbXbYbZb0b1b2b3b4b5b6b7bi 8b9br !b#bB $b

145 

146 if log.type == "failed": 2|bj C %bD E F G 'bH I J *bK L M N O a P Q c ecR S k T ~bs $ +b% ' ( ) ,b* + , ]b- . / : ; d = ? l gc@ [ t ] acu ^ -b_ ` { | .b} ~ ab^bbbcbdbebfbe gbhbm hcibjbv kbbcw lb/bmbnbobpb:bqbrbsb_btbubvbwbxbf ybzbn icAbBbx Cb}bo U (bV W X Y )bZ 0 1 ;b2 3 4 5 6 b 7 8 g fc9 ! p # ccy Db=bEbFbGbHb?bIbJbKb`bLbMbNbObPbh QbRbq jcSbTbz UbdcA Vb@bWbXbYbZb[b0b1b2b{b3b4b5b6b7bi 8b9br kc!b#bB $b

147 build_failed = True 2%b'b*bec+b,b]bgc-b.b^bhc/b:b_bic(b)b;bfc=b?b`bjc@b[b{bkc

148 build_error = None 2%b'b*bec+b,b]bgc-b.b^bhc/b:b_bic(b)b;bfc=b?b`bjc@b[b{bkc

149 

150 with contextlib.suppress(HTTPError): 2%b'b*bec+b,b]bgc-b.b^bhc/b:b_bic(b)b;bfc=b?b`bjc@b[b{bkc

151 build_error = client.get_deployment(deployment.id).failure 2%b'b*bec+b,b]bgc-b.b^bhc/b:b_bic(b)b;bfc=b?b`bjc@b[b{bkc

152 

153 progress.transient = build_error is not None 2%b'b*bec+b,b]bgc-b.b^bhc/b:b_bic(b)b;bfc=b?b`bjc@b[b{bkc

154 # the headline comes from the title once there are log 

155 # lines, and from current_message when there are none 

156 progress.title = "Build failed" 2%b'b*bec+b,b]bgc-b.b^bhc/b:b_bic(b)b;bfc=b?b`bjc@b[b{bkc

157 progress.current_message = "Build failed" 2%b'b*bec+b,b]bgc-b.b^bhc/b:b_bic(b)b;bfc=b?b`bjc@b[b{bkc

158 progress.metadata["done_emoji"] = "❌" 2%b'b*bec+b,b]bgc-b.b^bhc/b:b_bic(b)b;bfc=b?b`bjc@b[b{bkc

159 break 2%b'b*bec+b,b]bgc-b.b^bhc/b:b_bic(b)b;bfc=b?b`bjc@b[b{bkc

160 

161 if time_elapsed > 30: 2|bj C %bD E F G 'bH I J *bK L M N O a P Q c R S k T ~bs $ +b% ' ( ) ,b* + , ]b- . / : ; d = ? l @ [ t ] acu ^ -b_ ` { | .b} ~ ab^bbbcbdbebfbe gbhbm ibjbv kbbcw lb/bmbnbobpb:bqbrbsb_btbubvbwbxbf ybzbn AbBbx Cb}bo U (bV W X Y )bZ 0 1 ;b2 3 4 5 6 b 7 8 g 9 ! p # ccy Db=bEbFbGbHb?bIbJbKb`bLbMbNbObPbh QbRbq SbTbz UbdcA Vb@bWbXbYbZb[b0b1b2b{b3b4b5b6b7bi 8b9br !b#bB $b

162 messages = cycle(LONG_WAIT_MESSAGES) 1adefbhi

163 

164 if (time.monotonic() - last_message_changed_at) > 2: 2|bj C %bD E F G 'bH I J *bK L M N O a P Q c R S k T ~bs $ +b% ' ( ) ,b* + , ]b- . / : ; d = ? l @ [ t ] acu ^ -b_ ` { | .b} ~ ab^bbbcbdbebfbe gbhbm ibjbv kbbcw lb/bmbnbobpb:bqbrbsb_btbubvbwbxbf ybzbn AbBbx Cb}bo U (bV W X Y )bZ 0 1 ;b2 3 4 5 6 b 7 8 g 9 ! p # ccy Db=bEbFbGbHb?bIbJbKb`bLbMbNbObPbh QbRbq SbTbz UbdcA Vb@bWbXbYbZb[b0b1b2b{b3b4b5b6b7bi 8b9br !b#bB $b

165 emoji, title = next(messages) 1acdlemfnbghqir

166 progress.metadata["emoji"] = emoji 1acdlemfnbghqir

167 progress.title = title 1acdlemfnbghqir

168 

169 last_message_changed_at = time.monotonic() 1acdlemfnbghqir

170 

171 except (StreamLogError, TooManyRetriesError, TimeoutError) as e: 2GcsctcIcwcxcJcyczcKcAcBcHcucvcLcCcDcMcEcFc

172 progress.set_error( 2sctcwcxcyczcAcBcucvcCcDcEcFc

173 dedent(f""" 

174 [error]Build log streaming failed: {e}[/] 

175 

176 Unable to stream build logs. Check the dashboard for status: [link={deployment.dashboard_url}]{deployment.dashboard_url}[/link] 

177 """).strip() 

178 ) 

179 

180 raise typer.Exit(1) from None 2sctcwcxcyczcAcBcucvcCcDcEcFc

181 

182 if build_failed: 2|bj C %bD E F G 'bH I J *bK L M N O a P Q c ecR S k T ~bs $ +b% ' ( ) ,b* + , ]b- . / : ; d = ? l gc@ [ t ] acu ^ -b_ ` { | .b} ~ ab^bbbcbdbebfbe gbhbm hcibjbv kbbcw lb/bmbnbobpb:bqbrbsb_btbubvbwbxbf ybzbn icAbBbx Cb}bo U (bV W X Y )bZ 0 1 ;b2 3 4 5 6 b 7 8 g fc9 ! p # ccy Db=bEbFbGbHb?bIbJbKb`bLbMbNbObPbh QbRbq jcSbTbz UbdcA Vb@bWbXbYbZb[b0b1b2b{b3b4b5b6b7bi 8b9br kc!b#bB $b

183 if build_error is not None: 2%b'b*bec+b,b]bgc-b.b^bhc/b:b_bic(b)b;bfc=b?b`bjc@b[b{bkc

184 print_build_error(toolkit, build_error) 2%b'b+b,b-b.b/b:b(b)b=b?b@b[b

185 toolkit.print_line() 2%b'b+b,b-b.b/b:b(b)b=b?b@b[b

186 message = "Check out the logs at" 2%b'b+b,b-b.b/b:b(b)b=b?b@b[b

187 else: 

188 toolkit.print_line() 2*bec]bgc^bhc_bic;bfc`bjc{bkc

189 message = "Oh no! Something went wrong. Check out the logs at" 2*bec]bgc^bhc_bic;bfc`bjc{bkc

190 toolkit.print( 2%b'b*bec+b,b]bgc-b.b^bhc/b:b_bic(b)b;bfc=b?b`bjc@b[b{bkc

191 f"{message} [link={deployment.dashboard_url}]{deployment.dashboard_url}[/link]", 

192 emoji="👀" if build_error is not None else "😔", 

193 ) 

194 raise typer.Exit(1) 2%b'b*bec+b,b]bgc-b.b^bhc/b:b_bic(b)b;bfc=b?b`bjc@b[b{bkc

195 

196 if build_complete: 2|bj C D E F G H I J K L M N O a P Q c R S k T ~bs $ % ' ( ) * + , - . / : ; d = ? l @ [ t ] acu ^ _ ` { | } ~ abbbcbdbebfbe gbhbm ibjbv kbbcw lbmbnbobpbqbrbsbtbubvbwbxbf ybzbn AbBbx Cb}bo U V W X Y Z 0 1 2 3 4 5 6 b 7 8 g 9 ! p # ccy DbEbFbGbHbIbJbKbLbMbNbObPbh QbRbq SbTbz UbdcA VbWbXbYbZb0b1b2b3b4b5b6b7bi 8b9br !b#bB $b

197 toolkit.print_line() 2|bj C D E F G H I J K L M N O a P Q c R S k T ~bs $ % ' ( ) * + , - . / : ; d = ? l @ [ t ] acu ^ _ ` { | } ~ abbbcbdbebfbe gbhbm ibjbv kbbcw lbmbnbobpbqbrbsbtbubvbwbxbf ybzbn AbBbx Cb}bo U V W X Y Z 0 1 2 3 4 5 6 b 7 8 g 9 ! p # ccy DbEbFbGbHbIbJbKbLbMbNbObPbh QbRbq SbTbz UbdcA VbWbXbYbZb0b1b2b3b4b5b6b7bi 8b9br !b#bB $b

198 

199 _verify_deployment(toolkit=toolkit, client=client, deployment=deployment) 2|bj C D E F G H I J K L M N O a P Q c R S k T ~bs $ % ' ( ) * + , - . / : ; d = ? l @ [ t ] acu ^ _ ` { | } ~ abbbcbdbebfbe gbhbm ibjbv kbbcw lbmbnbobpbqbrbsbtbubvbwbxbf ybzbn AbBbx Cb}bo U V W X Y Z 0 1 2 3 4 5 6 b 7 8 g 9 ! p # ccy DbEbFbGbHbIbJbKbLbMbNbObPbh QbRbq SbTbz UbdcA VbWbXbYbZb0b1b2b3b4b5b6b7bi 8b9br !b#bB $b