superset-showtime 0.1.0__tar.gz

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.

Files changed (30) hide show
  1. superset_showtime-0.1.0/.claude/settings.local.json +24 -0
  2. superset_showtime-0.1.0/.github/workflows/showtime-cleanup.yml +40 -0
  3. superset_showtime-0.1.0/.github/workflows/showtime.yml +185 -0
  4. superset_showtime-0.1.0/.gitignore +149 -0
  5. superset_showtime-0.1.0/.pre-commit-config.yaml +19 -0
  6. superset_showtime-0.1.0/CLAUDE.md +185 -0
  7. superset_showtime-0.1.0/Makefile +54 -0
  8. superset_showtime-0.1.0/PKG-INFO +391 -0
  9. superset_showtime-0.1.0/README.md +326 -0
  10. superset_showtime-0.1.0/dev-setup.sh +42 -0
  11. superset_showtime-0.1.0/pypi-push.sh +24 -0
  12. superset_showtime-0.1.0/pyproject.toml +140 -0
  13. superset_showtime-0.1.0/requirements-dev.txt +178 -0
  14. superset_showtime-0.1.0/requirements.txt +63 -0
  15. superset_showtime-0.1.0/showtime/__init__.py +21 -0
  16. superset_showtime-0.1.0/showtime/__main__.py +8 -0
  17. superset_showtime-0.1.0/showtime/cli.py +1361 -0
  18. superset_showtime-0.1.0/showtime/commands/__init__.py +1 -0
  19. superset_showtime-0.1.0/showtime/commands/start.py +40 -0
  20. superset_showtime-0.1.0/showtime/core/__init__.py +1 -0
  21. superset_showtime-0.1.0/showtime/core/aws.py +758 -0
  22. superset_showtime-0.1.0/showtime/core/circus.py +285 -0
  23. superset_showtime-0.1.0/showtime/core/config.py +152 -0
  24. superset_showtime-0.1.0/showtime/core/emojis.py +86 -0
  25. superset_showtime-0.1.0/showtime/core/github.py +214 -0
  26. superset_showtime-0.1.0/showtime/data/ecs-task-definition.json +59 -0
  27. superset_showtime-0.1.0/tests/__init__.py +1 -0
  28. superset_showtime-0.1.0/tests/unit/__init__.py +1 -0
  29. superset_showtime-0.1.0/tests/unit/test_circus.py +157 -0
  30. superset_showtime-0.1.0/uv.lock +2 -0
@@ -0,0 +1,24 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Read(//Users/max/code/superset/.github/workflows/**)",
5
+ "Bash(showtime stop:*)",
6
+ "Bash(python:*)",
7
+ "Bash(uv pip install:*)",
8
+ "Bash(aws configure:*)",
9
+ "Bash(env)",
10
+ "Bash(unset:*)",
11
+ "Bash(aws sts:*)",
12
+ "WebSearch",
13
+ "Bash(git add:*)",
14
+ "Bash(git commit:*)",
15
+ "Bash(ruff check:*)",
16
+ "Bash(pytest:*)",
17
+ "Bash(make test:*)",
18
+ "Bash(uv pip compile:*)",
19
+ "Bash(chmod:*)"
20
+ ],
21
+ "deny": [],
22
+ "ask": []
23
+ }
24
+ }
@@ -0,0 +1,40 @@
1
+ name: 🎪 Showtime Cleanup
2
+
3
+ # Scheduled cleanup of expired environments
4
+ on:
5
+ schedule:
6
+ - cron: '0 */6 * * *' # Every 6 hours
7
+
8
+ # Manual trigger for testing
9
+ workflow_dispatch:
10
+ inputs:
11
+ max_age_hours:
12
+ description: 'Maximum age in hours before cleanup'
13
+ required: false
14
+ default: '48'
15
+
16
+ jobs:
17
+ cleanup-expired:
18
+ name: Clean up expired showtime environments
19
+ runs-on: ubuntu-latest
20
+
21
+ permissions:
22
+ contents: read
23
+ pull-requests: write
24
+
25
+ steps:
26
+ - name: Install Superset Showtime
27
+ run: |
28
+ pip install superset-showtime
29
+
30
+ - name: Cleanup expired environments
31
+ env:
32
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
34
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
35
+ AWS_REGION: ${{ vars.AWS_REGION || 'us-west-2' }}
36
+ GITHUB_ORG: ${{ github.repository_owner }}
37
+ GITHUB_REPO: ${{ github.event.repository.name }}
38
+ run: |
39
+ MAX_AGE="${{ github.event.inputs.max_age_hours || '48' }}"
40
+ python -m showtime cleanup --older-than "${MAX_AGE}h"
@@ -0,0 +1,185 @@
1
+ name: 🎪 Superset Showtime Environment Manager
2
+
3
+ # Trigger on circus tent labels
4
+ on:
5
+ pull_request_target:
6
+ types: [labeled, unlabeled, synchronize, closed]
7
+
8
+ jobs:
9
+ # Job 1: Check for showtime triggers and extract SHA
10
+ evaluate-triggers:
11
+ name: Evaluate showtime triggers
12
+ runs-on: ubuntu-latest
13
+ permissions:
14
+ pull-requests: write
15
+ outputs:
16
+ should-build: ${{ steps.eval-triggers.outputs.should-build }}
17
+ should-cleanup: ${{ steps.eval-triggers.outputs.should-cleanup }}
18
+ sha: ${{ steps.get-sha.outputs.sha }}
19
+ env:
20
+ DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
21
+ DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
22
+
23
+ steps:
24
+ - name: Check for showtime trigger labels
25
+ id: eval-triggers
26
+ run: |
27
+ if [[ "${{ github.event_name }}" == "pull_request_target" && "${{ contains(github.event.label.name, '🎪 trigger-start') }}" == "true" ]]; then
28
+ echo "should-build=true" >> $GITHUB_OUTPUT
29
+ elif [[ "${{ github.event_name }}" == "synchronize" ]]; then
30
+ echo "should-build=true" >> $GITHUB_OUTPUT
31
+ elif [[ "${{ github.event.action }}" == "closed" ]]; then
32
+ echo "should-build=false" >> $GITHUB_OUTPUT
33
+ echo "should-cleanup=true" >> $GITHUB_OUTPUT
34
+ else
35
+ echo "should-build=false" >> $GITHUB_OUTPUT
36
+ fi
37
+
38
+ - name: Get PR SHA
39
+ id: get-sha
40
+ if: steps.eval-triggers.outputs.should-build == 'true'
41
+ uses: actions/github-script@v7
42
+ with:
43
+ github-token: ${{ secrets.GITHUB_TOKEN }}
44
+ script: |
45
+ const prSha = context.payload.pull_request.head.sha;
46
+ console.log(`PR SHA: ${prSha}`);
47
+ core.setOutput("sha", prSha);
48
+
49
+ # Job 2: Build Docker image (from original ephemeral-env.yml)
50
+ docker-build:
51
+ concurrency:
52
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}-build
53
+ cancel-in-progress: true
54
+ needs: evaluate-triggers
55
+ if: needs.evaluate-triggers.outputs.should-build == 'true'
56
+ name: Build ephemeral environment image
57
+ runs-on: ubuntu-24.04
58
+ env:
59
+ DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
60
+ DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
61
+
62
+ steps:
63
+ - name: "Checkout ${{ github.ref }} ( ${{ needs.evaluate-triggers.outputs.sha }} )"
64
+ uses: actions/checkout@v4
65
+ with:
66
+ ref: ${{ needs.evaluate-triggers.outputs.sha }}
67
+ persist-credentials: false
68
+
69
+ - name: Setup Docker Environment
70
+ uses: ./.github/actions/setup-docker
71
+ with:
72
+ dockerhub-user: ${{ secrets.DOCKERHUB_USER }}
73
+ dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
74
+ build: "true"
75
+ install-docker-compose: "false"
76
+
77
+ - name: Setup supersetbot
78
+ uses: ./.github/actions/setup-supersetbot/
79
+
80
+ - name: Build ephemeral env image
81
+ env:
82
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
83
+ run: |
84
+ supersetbot docker \
85
+ --push \
86
+ --load \
87
+ --preset ci \
88
+ --platform linux/amd64 \
89
+ --context-ref "${{ needs.evaluate-triggers.outputs.sha }}" \
90
+ --extra-flags "--build-arg INCLUDE_CHROMIUM=false"
91
+
92
+ - name: Configure AWS credentials
93
+ uses: aws-actions/configure-aws-credentials@v4
94
+ with:
95
+ aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
96
+ aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
97
+ aws-region: us-west-2
98
+
99
+ - name: Login to Amazon ECR
100
+ id: login-ecr
101
+ uses: aws-actions/amazon-ecr-login@v2
102
+
103
+ - name: Tag and push image to ECR
104
+ env:
105
+ ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
106
+ ECR_REPOSITORY: superset-ci
107
+ IMAGE_TAG: apache/superset:${{ needs.evaluate-triggers.outputs.sha }}-ci
108
+ PR_NUMBER: ${{ github.event.pull_request.number }}
109
+ run: |
110
+ docker tag $IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:pr-$PR_NUMBER-ci
111
+ docker push -a $ECR_REGISTRY/$ECR_REPOSITORY
112
+
113
+ # Job 3: Handle showtime operations (our new logic)
114
+ showtime-handler:
115
+ needs: [evaluate-triggers, docker-build]
116
+ if: needs.evaluate-triggers.outputs.should-build == 'true'
117
+
118
+ concurrency:
119
+ group: showtime-${{ github.event.pull_request.number || github.run_id }}
120
+ cancel-in-progress: true
121
+
122
+ name: Process showtime operations
123
+ runs-on: ubuntu-latest
124
+
125
+ permissions:
126
+ contents: read
127
+ pull-requests: write
128
+
129
+ steps:
130
+ - name: Install Superset Showtime
131
+ run: |
132
+ pip install superset-showtime
133
+
134
+ - name: Process circus triggers
135
+ env:
136
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
137
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
138
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
139
+ AWS_REGION: us-west-2
140
+ GITHUB_ORG: ${{ github.repository_owner }}
141
+ GITHUB_REPO: ${{ github.event.repository.name }}
142
+ GITHUB_ACTOR: ${{ github.actor }}
143
+ run: |
144
+ python -m showtime handle-trigger ${{ github.event.pull_request.number }}
145
+
146
+ - name: Handle synchronize events (new commits)
147
+ if: github.event_name == 'synchronize'
148
+ env:
149
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
150
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
151
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
152
+ AWS_REGION: us-west-2
153
+ GITHUB_ORG: ${{ github.repository_owner }}
154
+ GITHUB_REPO: ${{ github.event.repository.name }}
155
+ GITHUB_ACTOR: ${{ github.actor }}
156
+ run: |
157
+ python -m showtime handle-sync ${{ github.event.pull_request.number }}
158
+
159
+ # Job 4: Immediate cleanup when PR is closed/merged
160
+ pr-cleanup:
161
+ needs: evaluate-triggers
162
+ if: needs.evaluate-triggers.outputs.should-cleanup == 'true'
163
+ name: Clean up closed PR environment
164
+ runs-on: ubuntu-latest
165
+
166
+ permissions:
167
+ contents: read
168
+ pull-requests: write
169
+
170
+ steps:
171
+ - name: Install Superset Showtime
172
+ run: |
173
+ pip install superset-showtime
174
+
175
+ - name: Clean up closed PR
176
+ env:
177
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
178
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
179
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
180
+ AWS_REGION: us-west-2
181
+ GITHUB_ORG: ${{ github.repository_owner }}
182
+ GITHUB_REPO: ${{ github.event.repository.name }}
183
+ GITHUB_ACTOR: ${{ github.actor }}
184
+ run: |
185
+ python -m showtime stop ${{ github.event.pull_request.number }} --force
@@ -0,0 +1,149 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ *.manifest
31
+ *.spec
32
+
33
+ # Installer logs
34
+ pip-log.txt
35
+ pip-delete-this-directory.txt
36
+
37
+ # Unit test / coverage reports
38
+ htmlcov/
39
+ .tox/
40
+ .nox/
41
+ .coverage
42
+ .coverage.*
43
+ .cache
44
+ nosetests.xml
45
+ coverage.xml
46
+ *.cover
47
+ *.py,cover
48
+ .hypothesis/
49
+ .pytest_cache/
50
+ cover/
51
+
52
+ # Translations
53
+ *.mo
54
+ *.pot
55
+
56
+ # Django stuff:
57
+ *.log
58
+ local_settings.py
59
+ db.sqlite3
60
+ db.sqlite3-journal
61
+
62
+ # Flask stuff:
63
+ instance/
64
+ .webassets-cache
65
+
66
+ # Scrapy stuff:
67
+ .scrapy
68
+
69
+ # Sphinx documentation
70
+ docs/_build/
71
+
72
+ # PyBuilder
73
+ .pybuilder/
74
+ target/
75
+
76
+ # Jupyter Notebook
77
+ .ipynb_checkpoints
78
+
79
+ # IPython
80
+ profile_default/
81
+ ipython_config.py
82
+
83
+ # pyenv
84
+ .python-version
85
+
86
+ # pipenv
87
+ Pipfile.lock
88
+
89
+ # poetry
90
+ poetry.lock
91
+
92
+ # pdm
93
+ .pdm.toml
94
+
95
+ # PEP 582
96
+ __pypackages__/
97
+
98
+ # Celery stuff
99
+ celerybeat-schedule
100
+ celerybeat.pid
101
+
102
+ # SageMath parsed files
103
+ *.sage.py
104
+
105
+ # Environments
106
+ .env
107
+ .venv
108
+ env/
109
+ venv/
110
+ ENV/
111
+ env.bak/
112
+ venv.bak/
113
+
114
+ # Spyder project settings
115
+ .spyderproject
116
+ .spyproject
117
+
118
+ # Rope project settings
119
+ .ropeproject
120
+
121
+ # mkdocs documentation
122
+ /site
123
+
124
+ # mypy
125
+ .mypy_cache/
126
+ .dmypy.json
127
+ dmypy.json
128
+
129
+ # Pyre type checker
130
+ .pyre/
131
+
132
+ # pytype static type analyzer
133
+ .pytype/
134
+
135
+ # Cython debug symbols
136
+ cython_debug/
137
+
138
+ # PyCharm
139
+ .idea/
140
+
141
+ # VS Code
142
+ .vscode/
143
+
144
+ # macOS
145
+ .DS_Store
146
+
147
+ # Showtime specific
148
+ .showtime/
149
+ config.yml
@@ -0,0 +1,19 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v4.5.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ - id: check-added-large-files
9
+ - id: check-merge-conflict
10
+ - id: check-toml
11
+ - id: debug-statements
12
+ - id: mixed-line-ending
13
+
14
+ - repo: https://github.com/astral-sh/ruff-pre-commit
15
+ rev: v0.1.9
16
+ hooks:
17
+ - id: ruff
18
+ args: [--fix]
19
+ - id: ruff-format
@@ -0,0 +1,185 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ Superset Showtime is a Python CLI tool for managing Apache Superset ephemeral environments using **circus tent emoji labels** as a state management system on GitHub PRs. The system replaces complex GitHub Actions scripts with a simple CLI that uses GitHub labels for ACID-like state transactions.
8
+
9
+ ## Development Commands
10
+
11
+ ### Essential Commands
12
+ ```bash
13
+ # Development setup
14
+ uv pip install -e ".[dev]" # Install with dev dependencies
15
+ make pre-commit # Setup pre-commit hooks
16
+ make test # Run tests
17
+ make lint # Run ruff + mypy
18
+
19
+ # Testing circus tent functionality
20
+ python -m showtime --help # Shows complete workflow tutorial
21
+ python -m showtime labels # Complete label reference
22
+ python -m showtime list # List all environments (requires GITHUB_TOKEN)
23
+ python -m showtime test-lifecycle 1234 # Full workflow simulation
24
+
25
+ # Test with real GitHub PRs safely
26
+ export GITHUB_TOKEN=xxx
27
+ showtime start 34809 --dry-run-aws --aws-sleep 5 # Mock AWS, real GitHub labels
28
+ showtime status 34809 # Check environment status
29
+ showtime stop 34809 --force # Clean up test labels
30
+ ```
31
+
32
+ ### Testing Single Components
33
+ ```bash
34
+ pytest tests/unit/test_circus.py # Test label parsing
35
+ pytest tests/unit/test_circus.py::test_show_properties -v # Single test
36
+ python -c "from showtime.core.circus import Show; show = Show(pr_number=1234, sha='abc123f', status='running'); print(show.to_circus_labels())" # Quick circus label test
37
+ ```
38
+
39
+ ## Architecture Overview
40
+
41
+ ### Core State Management Pattern
42
+ The system uses **GitHub labels as a distributed state machine**:
43
+ - **Trigger labels** (`🎪 trigger-start`) - Commands added by users, processed and removed by CLI
44
+ - **State labels** (`🎪 🚦 abc123f running`) - Per-SHA status managed by CLI
45
+ - **No external database** - All state reconstructed from GitHub labels
46
+
47
+ ### Key Classes and Responsibilities
48
+
49
+ #### `Show` (showtime/core/circus.py:16)
50
+ Represents a single ephemeral environment with per-SHA state:
51
+ - **Properties**: `aws_service_name`, `aws_image_tag` for deterministic AWS naming
52
+ - **Methods**: `to_circus_labels()` creates per-SHA format labels
53
+ - **Parsing**: `from_circus_labels()` reconstructs from GitHub labels
54
+
55
+ #### `PullRequest` (showtime/core/circus.py:121)
56
+ Container parsing all shows from a PR's labels:
57
+ - **Properties**: `current_show`, `building_show`, `circus_labels`
58
+ - **State reconstruction**: Parses all environments from labels
59
+ - **Factory method**: `from_id()` loads real GitHub data
60
+
61
+ #### `GitHubInterface` (showtime/core/github.py:23)
62
+ GitHub API operations with emoji label support:
63
+ - **Authentication**: Auto-detects `GITHUB_TOKEN` or `gh auth token`
64
+ - **Label operations**: Handles emoji encoding for GitHub API
65
+ - **Discovery**: `find_prs_with_shows()` searches for circus tent labels
66
+
67
+ #### `AWSInterface` (showtime/core/aws.py:35)
68
+ Replicates current GitHub Actions AWS logic:
69
+ - **Naming**: Uses same deterministic patterns as current GHA
70
+ - **Operations**: `create_environment()`, `delete_environment()` mirror existing workflows
71
+ - **Network config**: Same subnets/security groups as production
72
+
73
+ ### Label Format Design
74
+
75
+ #### Per-SHA State Labels
76
+ ```bash
77
+ 🎪 🚦 {sha} {status} # 🎪 🚦 abc123f running
78
+ 🎪 🌐 {sha} {ip-dashes} # 🎪 🌐 abc123f 52-1-2-3
79
+ 🎪 📅 {sha} {timestamp} # 🎪 📅 abc123f 2024-01-15T14-30
80
+ 🎪 ⌛ {sha} {ttl} # 🎪 ⌛ abc123f 24h
81
+ 🎪 🤡 {sha} {username} # 🎪 🤡 abc123f maxime
82
+ 🎪 ⚙️ {sha} {config} # 🎪 ⚙️ abc123f alerts,debug
83
+ ```
84
+
85
+ #### Pointer Labels (No Value)
86
+ ```bash
87
+ 🎪 🎯 {sha} # Active environment pointer
88
+ 🎪 🏗️ {sha} # Building environment pointer
89
+ ```
90
+
91
+ ### GitHub Actions Integration
92
+
93
+ #### Current Integration Points
94
+ - **`.github/workflows/circus.yml`** - Main workflow replacing `ephemeral-env.yml`
95
+ - **`.github/workflows/circus-cleanup.yml`** - Scheduled cleanup replacing manual processes
96
+ - **Security model**: `pull_request_target` + PyPI install (no PR code execution)
97
+
98
+ #### CLI Commands Called by GHA
99
+ - `showtime handle-trigger {pr-number}` - Process trigger labels
100
+ - `showtime handle-sync {pr-number}` - Handle new commits
101
+ - `showtime cleanup --older-than 48h` - Scheduled cleanup
102
+
103
+ ## Important Implementation Details
104
+
105
+ ### Authentication Pattern
106
+ ```python
107
+ # Priority order for credentials:
108
+ github = GitHubInterface() # Auto-detects GITHUB_TOKEN or gh CLI
109
+ # No config files - environment variables only
110
+ ```
111
+
112
+ ### Dry-Run Testing Strategy
113
+ The CLI has comprehensive dry-run support for safe testing:
114
+ ```bash
115
+ --dry-run-aws # Skip AWS operations, use mock data
116
+ --dry-run-github # Skip GitHub operations, show what would happen
117
+ --aws-sleep N # Sleep N seconds to simulate AWS timing
118
+ ```
119
+
120
+ ### AWS Resource Naming
121
+ Must maintain compatibility with existing Superset infrastructure:
122
+ - **ECS Service**: `pr-{pr_number}-{sha}` (e.g., `pr-1234-abc123f`)
123
+ - **ECR Image**: `pr-{pr_number}-{sha}-ci`
124
+ - **Network**: Same subnets/security groups as current production setup
125
+
126
+ ### State Recovery Pattern
127
+ Since the CLI is stateless, it always reconstructs state from GitHub labels:
128
+ ```python
129
+ pr = PullRequest.from_id(pr_number, github) # Reads all labels
130
+ show = pr.current_show # Finds active environment
131
+ # All state comes from parsing circus tent emoji labels
132
+ ```
133
+
134
+ ## Critical Development Notes
135
+
136
+ ### Label Operations Must Be Atomic
137
+ GitHub label operations are the "database transactions" - handle carefully:
138
+ ```python
139
+ # Remove trigger immediately after processing
140
+ github.remove_label(pr_number, trigger_label)
141
+ # Update state labels atomically
142
+ github.remove_circus_labels(pr_number)
143
+ for label in new_labels:
144
+ github.add_label(pr_number, label)
145
+ ```
146
+
147
+ ### Per-SHA Format Required
148
+ All new state labels must include SHA for multi-environment support:
149
+ ```python
150
+ # Correct: Per-SHA format
151
+ f"🎪 🚦 {sha} running" # Status per environment
152
+ f"🎪 🌐 {sha} {ip}" # IP per environment
153
+
154
+ # Incorrect: Global format (legacy)
155
+ "🎪 🚦 running" # Which environment??
156
+ ```
157
+
158
+ ### Testing Against Real PRs
159
+ The CLI can safely test against real Superset PRs:
160
+ ```bash
161
+ # Test label management without AWS costs
162
+ showtime start 34809 --dry-run-aws
163
+ # Removes test labels when done
164
+ showtime stop 34809 --force
165
+ ```
166
+
167
+ ## Current Implementation Status
168
+
169
+ ### ✅ Working (Tested)
170
+ - GitHub API integration with apache/superset
171
+ - Circus tent emoji label parsing and creation
172
+ - CLI commands: `list`, `status`, `start/stop` (with dry-run)
173
+ - Beautiful help system that teaches label workflow
174
+ - Comprehensive dry-run testing framework
175
+
176
+ ### 🚧 Partially Implemented
177
+ - AWS operations (class exists, logic written, needs testing)
178
+ - Per-SHA label parsing (designed, needs full implementation)
179
+ - Trigger processing (framework exists, needs completion)
180
+
181
+ ### 📋 Not Implemented
182
+ - Rolling update logic for zero-downtime
183
+ - Real AWS integration testing
184
+ - Feature flag configuration via labels
185
+ - GitHub Actions workflow deployment
@@ -0,0 +1,54 @@
1
+ .PHONY: help install install-dev test test-cov lint format clean pre-commit
2
+
3
+ help: ## Show this help message
4
+ @echo 'Usage: make <target>'
5
+ @echo ''
6
+ @echo 'Available targets:'
7
+ @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " %-15s %s\n", $$1, $$2}' $(MAKEFILE_LIST)
8
+
9
+ install: ## Install package dependencies
10
+ uv pip install -e .
11
+
12
+ install-dev: ## Install package with development dependencies
13
+ uv pip install -e ".[dev]"
14
+
15
+ test: ## Run tests
16
+ pytest
17
+
18
+ test-cov: ## Run tests with coverage
19
+ pytest --cov=showtime --cov-report=term-missing --cov-report=html
20
+
21
+ lint: ## Run linting
22
+ ruff check .
23
+ mypy showtime
24
+
25
+ format: ## Format code
26
+ ruff format .
27
+ ruff check --fix .
28
+
29
+ clean: ## Clean up build artifacts
30
+ rm -rf build/
31
+ rm -rf dist/
32
+ rm -rf *.egg-info/
33
+ rm -rf htmlcov/
34
+ rm -rf .coverage
35
+ rm -rf .pytest_cache/
36
+ rm -rf .mypy_cache/
37
+ find . -type d -name __pycache__ -exec rm -rf {} +
38
+ find . -type f -name "*.pyc" -delete
39
+
40
+ pre-commit: ## Install pre-commit hooks
41
+ pre-commit install
42
+
43
+ pre-commit-run: ## Run pre-commit hooks on all files
44
+ pre-commit run --all-files
45
+
46
+ build: ## Build package
47
+ uv build
48
+
49
+ publish: ## Publish to PyPI (use with caution)
50
+ uv build
51
+ uvx twine upload dist/*
52
+
53
+ circus: ## Quick test of circus emoji parsing
54
+ python -c "from showtime.core.circus import parse_circus_labels; print(parse_circus_labels(['🎪 🚦 running', '🎪 🎯 abc123f']))"