|
11 | 11 | import time |
12 | 12 |
|
13 | 13 | import boto3 |
| 14 | +from rich.console import Console |
| 15 | +from rich.progress import Progress, SpinnerColumn, TextColumn, TimeElapsedColumn |
14 | 16 |
|
15 | 17 |
|
16 | 18 | def run_command(cmd, check=True): |
@@ -104,76 +106,108 @@ def upload_to_s3(bucket_name): |
104 | 106 |
|
105 | 107 | def find_pipeline_execution_by_version(pipeline_name, version_id, max_wait=300): |
106 | 108 | """Find pipeline execution that corresponds to specific S3 version ID""" |
107 | | - print(f"Finding pipeline execution for version: {version_id}") |
| 109 | + console = Console() |
| 110 | + console.print(f"[cyan]Finding pipeline execution for version:[/cyan] {version_id}") |
108 | 111 |
|
109 | 112 | codepipeline = boto3.client("codepipeline") |
110 | 113 | start_time = time.time() |
111 | 114 |
|
112 | | - while time.time() - start_time < max_wait: |
113 | | - try: |
114 | | - response = codepipeline.list_pipeline_executions( |
115 | | - pipelineName=pipeline_name, maxResults=10 |
116 | | - ) |
117 | | - |
118 | | - for execution in response["pipelineExecutionSummaries"]: |
119 | | - execution_id = execution["pipelineExecutionId"] |
120 | | - |
121 | | - # Get execution details to check source version |
122 | | - details = codepipeline.get_pipeline_execution( |
123 | | - pipelineName=pipeline_name, |
124 | | - pipelineExecutionId=execution_id |
| 115 | + with Progress( |
| 116 | + SpinnerColumn(), |
| 117 | + TextColumn("[progress.description]{task.description}"), |
| 118 | + TimeElapsedColumn(), |
| 119 | + console=console, |
| 120 | + transient=False, |
| 121 | + ) as progress: |
| 122 | + |
| 123 | + task = progress.add_task("[yellow]Searching for pipeline execution...", total=None) |
| 124 | + |
| 125 | + while time.time() - start_time < max_wait: |
| 126 | + try: |
| 127 | + response = codepipeline.list_pipeline_executions( |
| 128 | + pipelineName=pipeline_name, maxResults=10 |
125 | 129 | ) |
126 | 130 |
|
127 | | - # Check if this execution matches our version ID |
128 | | - for artifact in details["pipelineExecution"].get("artifactRevisions", []): |
129 | | - if artifact.get("revisionId") == version_id: |
130 | | - print(f"✅ Found matching execution: {execution_id}") |
131 | | - return execution_id |
| 131 | + for execution in response["pipelineExecutionSummaries"]: |
| 132 | + execution_id = execution["pipelineExecutionId"] |
| 133 | + |
| 134 | + # Get execution details to check source version |
| 135 | + details = codepipeline.get_pipeline_execution( |
| 136 | + pipelineName=pipeline_name, |
| 137 | + pipelineExecutionId=execution_id |
| 138 | + ) |
| 139 | + |
| 140 | + # Check if this execution matches our version ID |
| 141 | + for artifact in details["pipelineExecution"].get("artifactRevisions", []): |
| 142 | + if artifact.get("revisionId") == version_id: |
| 143 | + progress.update(task, description="[green]✅ Found matching execution!") |
| 144 | + console.print(f"[green]✅ Found matching execution:[/green] {execution_id}") |
| 145 | + return execution_id |
| 146 | + |
| 147 | + elapsed = int(time.time() - start_time) |
| 148 | + progress.update(task, description=f"[yellow]Waiting for pipeline trigger ({elapsed}s)...") |
132 | 149 |
|
133 | | - except Exception as e: |
134 | | - print(f"Error finding execution: {e}") |
135 | | - |
136 | | - time.sleep(10) |
137 | | - |
138 | | - print(f"❌ Could not find pipeline execution for version {version_id}") |
| 150 | + except Exception as e: |
| 151 | + progress.update(task, description=f"[red]Error: {str(e)[:50]}...") |
| 152 | + console.print(f"[red]Error finding execution: {e}[/red]") |
| 153 | + |
| 154 | + time.sleep(10) |
| 155 | + |
| 156 | + progress.update(task, description="[red]❌ No matching execution found") |
| 157 | + console.print(f"[red]❌ Could not find pipeline execution for version {version_id}[/red]") |
139 | 158 | return None |
140 | 159 |
|
141 | 160 |
|
142 | 161 | def monitor_pipeline_execution(pipeline_name, execution_id, max_wait=7200): |
143 | | - """Monitor specific pipeline execution until completion""" |
144 | | - print(f"Monitoring execution: {execution_id}") |
| 162 | + """Monitor specific pipeline execution until completion with live progress""" |
| 163 | + console = Console() |
| 164 | + console.print(f"[cyan]Monitoring pipeline execution:[/cyan] {execution_id}") |
145 | 165 |
|
146 | 166 | codepipeline = boto3.client("codepipeline") |
147 | | - wait_time = 0 |
148 | 167 | poll_interval = 30 |
149 | 168 |
|
150 | | - while wait_time < max_wait: |
151 | | - try: |
152 | | - response = codepipeline.get_pipeline_execution( |
153 | | - pipelineName=pipeline_name, |
154 | | - pipelineExecutionId=execution_id |
155 | | - ) |
156 | | - |
157 | | - status = response["pipelineExecution"]["status"] |
158 | | - print(f"Pipeline execution {execution_id}: {status}") |
159 | | - |
160 | | - if status == "Succeeded": |
161 | | - print("✅ Pipeline completed successfully!") |
162 | | - return True |
163 | | - elif status in ["Failed", "Cancelled", "Superseded"]: |
164 | | - print(f"❌ Pipeline failed with status: {status}") |
165 | | - return False |
166 | | - elif status == "InProgress": |
167 | | - print(f"⏳ Pipeline still running... ({wait_time}s elapsed)") |
| 169 | + with Progress( |
| 170 | + SpinnerColumn(), |
| 171 | + TextColumn("[progress.description]{task.description}"), |
| 172 | + TimeElapsedColumn(), |
| 173 | + console=console, |
| 174 | + transient=False, |
| 175 | + ) as progress: |
| 176 | + |
| 177 | + task = progress.add_task("[yellow]Pipeline executing...", total=None) |
| 178 | + |
| 179 | + wait_time = 0 |
| 180 | + while wait_time < max_wait: |
| 181 | + try: |
| 182 | + response = codepipeline.get_pipeline_execution( |
| 183 | + pipelineName=pipeline_name, |
| 184 | + pipelineExecutionId=execution_id |
| 185 | + ) |
168 | 186 |
|
169 | | - except Exception as e: |
170 | | - print(f"Error checking pipeline status: {e}") |
171 | | - |
172 | | - time.sleep(poll_interval) |
173 | | - wait_time += poll_interval |
174 | | - |
175 | | - print(f"❌ Pipeline monitoring timed out after {max_wait} seconds") |
176 | | - return False |
| 187 | + status = response["pipelineExecution"]["status"] |
| 188 | + elapsed_mins = wait_time // 60 |
| 189 | + |
| 190 | + if status == "Succeeded": |
| 191 | + progress.update(task, description="[green]✅ Pipeline completed successfully!") |
| 192 | + console.print("[green]✅ Pipeline completed successfully![/green]") |
| 193 | + return True |
| 194 | + elif status in ["Failed", "Cancelled", "Superseded"]: |
| 195 | + progress.update(task, description=f"[red]❌ Pipeline failed: {status}") |
| 196 | + console.print(f"[red]❌ Pipeline failed with status: {status}[/red]") |
| 197 | + return False |
| 198 | + elif status == "InProgress": |
| 199 | + progress.update(task, description=f"[yellow]⏳ Pipeline running ({elapsed_mins}m elapsed)...") |
| 200 | + |
| 201 | + except Exception as e: |
| 202 | + progress.update(task, description=f"[red]Error: {str(e)[:50]}...") |
| 203 | + console.print(f"[red]Error checking pipeline status: {e}[/red]") |
| 204 | + |
| 205 | + time.sleep(poll_interval) |
| 206 | + wait_time += poll_interval |
| 207 | + |
| 208 | + progress.update(task, description=f"[red]❌ Timeout after {max_wait//60} minutes") |
| 209 | + console.print(f"[red]❌ Pipeline monitoring timed out after {max_wait} seconds[/red]") |
| 210 | + return False |
177 | 211 |
|
178 | 212 |
|
179 | 213 | def monitor_pipeline(pipeline_name, version_id, max_wait=7200): |
|
0 commit comments