The priority-based runner orchestration ("traffic-control") lived as a large
inline-bash step in ci.yml — a two-pass preemption + hold-back script that was
effectively untestable in YAML. Move it into .github/scripts/traffic_control.py,
structured as a pure decision CORE + a thin gh-I/O SHELL:
* Pure functions (no network/clock/subprocess), unit-testable in isolation:
- effective_priority(pr): lowest-numbered P0-P9, default P5; broken OR draft => 10.
- runs_to_cancel(this_pr, all_prs, self_run_id): PASS 1 — run ids to cancel,
empty unless THIS PR is P0; only strictly-lower running/queued runs; never self
(by number or run id), never equal-or-higher.
- wait_blockers(this_pr, all_prs): PASS 2 — yield to any strictly-higher PR with
an active/queued run, and to same-level peers ordered ahead (running-first,
then oldest createdAt). Empty => proceed.
* Shell (run_live): gathers the snapshot via gh, applies cancels, runs the bounded
hold-back poll loop; always exits 0. --dry-run feeds the core a snapshot JSON and
prints decisions with zero network.
* No jq/bash dependency (cross-platform, per the repo's Python-stdlib convention).
ci.yml's traffic-control job now checks out the repo and runs the module. Job
permissions gain `contents: read` (for checkout) alongside the existing
`actions: write` / `pull-requests: read`; env and downstream `needs:` wiring
unchanged; step stays `continue-on-error`.
33 stdlib unittest cases cover priority resolution, P0-only preemption, the
self/main/equal-or-higher invariants, and the same-level running-first/oldest
ordering.
Behaviour is preserved except the ticket's refinements: (1) drafts now count as
P10 (bottom); (2) an explicit same-level running-first-then-oldest tiebreaker; and
(3) per the ticket's order-of-operations, ONLY P0 preempts — the old bash also let
any higher-priority PR cancel a `broken` target's run, which no longer happens
(a broken/draft run is only cancelled by a P0, via the same strictly-lower rule).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
51 lines
670 B
Plaintext
51 lines
670 B
Plaintext
# Built application files
|
|
*.apk
|
|
*.aar
|
|
*.ap_
|
|
*.aab
|
|
|
|
# Files for the ART/Dalvik VM
|
|
*.dex
|
|
|
|
# Java class files
|
|
*.class
|
|
|
|
# Generated files
|
|
bin/
|
|
gen/
|
|
out/
|
|
release/
|
|
|
|
# Gradle files
|
|
.gradle/
|
|
build/
|
|
|
|
# Local configuration file (sdk path, etc)
|
|
local.properties
|
|
|
|
# Secrets (OAuth client ids, signing, etc.) — never commit
|
|
secrets.properties
|
|
*.keystore
|
|
*.jks
|
|
|
|
# Log Files
|
|
*.log
|
|
|
|
# Android Studio / IntelliJ
|
|
.idea/
|
|
*.iml
|
|
.DS_Store
|
|
captures/
|
|
.externalNativeBuild/
|
|
.cxx/
|
|
|
|
# Kotlin
|
|
.kotlin/
|
|
|
|
# Python (dev/CI helper scripts under .github/scripts, .claude/…)
|
|
__pycache__/
|
|
*.pyc
|
|
|
|
# Claude Code — personal settings (the shared settings.json IS committed)
|
|
.claude/settings.local.json
|