superset-showtime 0.2.9__py3-none-any.whl → 0.4.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of superset-showtime might be problematic. Click here for more details.

showtime/core/aws.py CHANGED
@@ -11,7 +11,7 @@ from dataclasses import dataclass
11
11
  from pathlib import Path
12
12
  from typing import Any, Dict, List, Optional
13
13
 
14
- import boto3
14
+ import boto3 # type: ignore[import-untyped]
15
15
 
16
16
 
17
17
  @dataclass
@@ -36,7 +36,12 @@ class EnvironmentResult:
36
36
  class AWSInterface:
37
37
  """AWS ECS/ECR client replicating current GHA logic"""
38
38
 
39
- def __init__(self, region: str = None, cluster: str = None, repository: str = None):
39
+ def __init__(
40
+ self,
41
+ region: Optional[str] = None,
42
+ cluster: Optional[str] = None,
43
+ repository: Optional[str] = None,
44
+ ):
40
45
  self.region = region or os.getenv("AWS_REGION", "us-west-2")
41
46
  self.cluster = cluster or os.getenv("ECS_CLUSTER", "superset-ci")
42
47
  self.repository = repository or os.getenv("ECR_REPOSITORY", "superset-ci")
@@ -55,24 +60,23 @@ class AWSInterface:
55
60
  pr_number: int,
56
61
  sha: str,
57
62
  github_user: str = "unknown",
58
- feature_flags: List[Dict[str, str]] = None,
63
+ feature_flags: Optional[List[Dict[str, str]]] = None,
59
64
  image_tag_override: Optional[str] = None,
60
65
  force: bool = False,
61
66
  ) -> EnvironmentResult:
62
67
  """
63
- Create ephemeral environment with blue-green deployment support
64
-
65
- Blue-Green Steps:
66
- 1. Check if ECR image exists
67
- 2. Create Show object for consistent naming
68
- 3. Check for existing services (blue)
69
- 4. Create new service with SHA (green)
70
- 5. Wait for deployment stability
71
- 6. Get public IP and return for traffic switching
68
+ Create ephemeral environment (replaces any existing service with same name)
69
+
70
+ Steps:
71
+ 1. Create task definition with feature flags
72
+ 2. Delete any existing service with same name (clean slate)
73
+ 3. Create fresh ECS service
74
+ 4. Deploy and wait for stability
75
+ 5. Health check and return IP
72
76
  """
73
77
  from datetime import datetime
74
78
 
75
- from .circus import Show
79
+ from .show import Show
76
80
 
77
81
  # Create Show object for consistent AWS naming
78
82
  show = Show(
@@ -126,22 +130,21 @@ class AWSInterface:
126
130
  if not task_def_arn:
127
131
  return EnvironmentResult(success=False, error="Failed to create task definition")
128
132
 
129
- # Step 3: Blue-Green Logic - Check for existing services
130
- print(f"🔍 Checking for existing services for PR #{pr_number}")
133
+ # Step 3: Clean slate - Delete any existing service with this exact name
134
+ print(f"🔍 Checking for existing service: {service_name}")
131
135
  existing_services = self._find_pr_services(pr_number)
132
136
 
133
- if existing_services:
134
- print(
135
- f"📊 Found {len(existing_services)} existing services - starting blue-green deployment"
136
- )
137
- for svc in existing_services:
138
- print(f" 🔵 Blue: {svc['service_name']} ({svc['status']})")
137
+ for existing_service in existing_services:
138
+ if existing_service["service_name"] == service_name:
139
+ print(f"🗑️ Deleting existing service: {service_name}")
140
+ self._delete_ecs_service(service_name)
141
+ break
139
142
 
140
- # Step 4: Create new green service
141
- print(f"🟢 Creating green service: {service_name}")
143
+ # Step 4: Create fresh service
144
+ print(f"🆕 Creating service: {service_name}")
142
145
  success = self._create_ecs_service(service_name, pr_number, github_user, task_def_arn)
143
146
  if not success:
144
- return EnvironmentResult(success=False, error="Green service creation failed")
147
+ return EnvironmentResult(success=False, error="Service creation failed")
145
148
 
146
149
  # Step 5: Deploy task definition to green service
147
150
  success = self._deploy_task_definition(service_name, task_def_arn)
@@ -254,7 +257,8 @@ class AWSInterface:
254
257
  return None
255
258
 
256
259
  eni = eni_response["NetworkInterfaces"][0]
257
- return eni.get("Association", {}).get("PublicIp")
260
+ public_ip = eni.get("Association", {}).get("PublicIp")
261
+ return str(public_ip) if public_ip else None
258
262
 
259
263
  except Exception:
260
264
  return None
@@ -336,7 +340,7 @@ class AWSInterface:
336
340
  task_def_arn = response["taskDefinition"]["taskDefinitionArn"]
337
341
 
338
342
  print(f"✅ Created task definition: {task_def_arn}")
339
- return task_def_arn
343
+ return str(task_def_arn)
340
344
 
341
345
  except Exception as e:
342
346
  print(f"❌ Task definition creation failed: {e}")
showtime/core/github.py CHANGED
@@ -7,7 +7,7 @@ and circus tent emoji state synchronization.
7
7
 
8
8
  import os
9
9
  from dataclasses import dataclass
10
- from typing import Dict, List, Optional
10
+ from typing import Any, Dict, List, Optional
11
11
 
12
12
  import httpx
13
13
 
@@ -23,7 +23,9 @@ class GitHubError(Exception):
23
23
  class GitHubInterface:
24
24
  """GitHub API client for circus tent label operations"""
25
25
 
26
- def __init__(self, token: str = None, org: str = None, repo: str = None):
26
+ def __init__(
27
+ self, token: Optional[str] = None, org: Optional[str] = None, repo: Optional[str] = None
28
+ ):
27
29
  self.token = token or self._detect_token()
28
30
  self.org = org or os.getenv("GITHUB_ORG", "apache")
29
31
  self.repo = repo or os.getenv("GITHUB_REPO", "superset")
@@ -120,16 +122,17 @@ class GitHubInterface:
120
122
  def get_latest_commit_sha(self, pr_number: int) -> str:
121
123
  """Get the latest commit SHA for a PR"""
122
124
  pr_data = self.get_pr_data(pr_number)
123
- return pr_data["head"]["sha"]
125
+ return str(pr_data["head"]["sha"])
124
126
 
125
- def get_pr_data(self, pr_number: int) -> dict:
127
+ def get_pr_data(self, pr_number: int) -> Dict[str, Any]:
126
128
  """Get full PR data including description"""
127
129
  url = f"{self.base_url}/repos/{self.org}/{self.repo}/pulls/{pr_number}"
128
130
 
129
131
  with httpx.Client() as client:
130
132
  response = client.get(url, headers=self.headers)
131
133
  response.raise_for_status()
132
- return response.json()
134
+ result: Dict[str, Any] = response.json()
135
+ return result
133
136
 
134
137
  def get_circus_labels(self, pr_number: int) -> List[str]:
135
138
  """Get only circus tent emoji labels for a PR"""
@@ -149,7 +152,7 @@ class GitHubInterface:
149
152
  # Search for PRs with any circus tent labels
150
153
  params = {
151
154
  "q": f"repo:{self.org}/{self.repo} is:pr 🎪",
152
- "per_page": 100,
155
+ "per_page": "100",
153
156
  } # Include closed PRs
154
157
 
155
158
  with httpx.Client() as client:
@@ -205,6 +208,7 @@ class GitHubInterface:
205
208
  return False # Label doesn't exist
206
209
  else:
207
210
  response.raise_for_status()
211
+ return False # Should never reach here
208
212
 
209
213
  def cleanup_sha_labels(self, dry_run: bool = False) -> List[str]:
210
214
  """Clean up all circus tent labels with SHA patterns from repository"""
@@ -5,10 +5,9 @@ Centralized PR comment functions with type hints and clean formatting.
5
5
  """
6
6
 
7
7
  import os
8
- import textwrap
9
8
  from typing import Dict, List, Optional
10
9
 
11
- from .circus import Show
10
+ from .show import Show
12
11
 
13
12
  # AWS Console URL constants
14
13
  BASE_AWS_URL = "https://us-west-2.console.aws.amazon.com/ecs/v2/clusters/superset-ci/services"
@@ -42,7 +41,7 @@ def _create_header_links(sha: str) -> Dict[str, str]:
42
41
  Returns:
43
42
  Dict with showtime_link, gha_link, commit_link
44
43
  """
45
- from .circus import short_sha
44
+ from .show import short_sha
46
45
 
47
46
  repo_path = get_repo_path()
48
47
  return {
@@ -60,13 +59,7 @@ def _format_comment(header: str, bullets: List[str]) -> str:
60
59
  bullets: List of bullet point strings (without •)
61
60
  """
62
61
  bullet_text = "\n".join(f"• {bullet}" for bullet in bullets)
63
- return textwrap.dedent(
64
- f"""
65
- {header}
66
-
67
- {bullet_text}
68
- """
69
- ).strip()
62
+ return f"{header}\n\n{bullet_text}"
70
63
 
71
64
 
72
65
  def get_commit_url(repo_path: str, sha: str) -> str:
@@ -182,7 +175,7 @@ def rolling_start_comment(current_show: Show, new_sha: str) -> str:
182
175
  current_show: Current Show object with SHA and IP
183
176
  new_sha: New environment SHA (full SHA, will be truncated)
184
177
  """
185
- from .circus import short_sha
178
+ from .show import short_sha
186
179
 
187
180
  links = _create_header_links(new_sha)
188
181
  header = f"🎪 {links['showtime_link']} is updating {current_show.short_sha}→{short_sha(new_sha)} on {links['gha_link']} for {links['commit_link']}"
@@ -223,7 +216,7 @@ def rolling_failure_comment(current_show: Show, new_sha: str, error: str) -> str
223
216
  new_sha: Failed new environment SHA (full SHA, will be truncated)
224
217
  error: Error message describing what went wrong
225
218
  """
226
- from .circus import short_sha
219
+ from .show import short_sha
227
220
 
228
221
  links = _create_header_links(new_sha)
229
222
  header = f"🎪 {links['showtime_link']} failed updating to {short_sha(new_sha)} on {links['gha_link']} for {links['commit_link']}"