Repository navigation
CC-19: Swift compile gate (hosted macOS CI + ruleset handoff) #236
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -55,8 +55,73 @@ concurrency: | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | ||
|
|
||
| jobs: | ||
| await-swift-ci: | ||
| if: github.event.repository.fork == false && github.event_name == 'push' | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 90 | ||
| permissions: | ||
| checks: read | ||
| contents: read | ||
| steps: | ||
| - name: Wait for Swift CI compile checks on this commit | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| REPO: ${{ github.repository }} | ||
| SHA: ${{ github.sha }} | ||
| run: | | ||
| set -euo pipefail | ||
| required_checks=("Mac package build and test" "iOS companion compile") | ||
| deadline=$(( $(date +%s) + 5100 )) | ||
| while [ "$(date +%s)" -lt "$deadline" ]; do | ||
| payload="$(gh api "repos/${REPO}/commits/${SHA}/check-runs?per_page=100")" | ||
|
jaywedgeworth22 marked this conversation as resolved.
Comment on lines
+75
to
+76
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The check-runs poll in while [ "$(date +%s)" -lt "$deadline" ]; do
pending=0
failed=0
for check_name in "${required_checks[@]}"; do
enc_name=$(printf '%s' "$check_name" | python3 -c 'import sys,urllib.parse;print(urllib.parse.quote(sys.stdin.read(),safe=""))')
payload="$(gh api "repos/${REPO}/commits/${SHA}/check-runs?per_page=100&check_name=${enc_name}")"Prompt for LLMTalk to Kody by mentioning @kody Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction. |
||
| pending=0 | ||
| failed=0 | ||
| for check_name in "${required_checks[@]}"; do | ||
| conclusion="$(printf '%s' "$payload" | python3 -c ' | ||
| import json, sys | ||
| name = sys.argv[1] | ||
| data = json.load(sys.stdin) | ||
| matches = [r for r in data.get("check_runs", []) if r.get("name") == name] | ||
| if not matches: | ||
| print("missing") | ||
| else: | ||
| print(matches[0].get("conclusion") or "pending") | ||
| ' "$check_name")" | ||
| case "$conclusion" in | ||
| success) ;; | ||
| failure|cancelled|timed_out|action_required|stale) | ||
| echo "::error::Swift CI check '${check_name}' concluded ${conclusion} on ${SHA}" | ||
| failed=1 | ||
| ;; | ||
| missing|pending|""|null) | ||
| pending=1 | ||
| ;; | ||
| *) | ||
| pending=1 | ||
| ;; | ||
| esac | ||
| done | ||
| if [ "$failed" -eq 1 ]; then | ||
| exit 1 | ||
| fi | ||
| if [ "$pending" -eq 0 ]; then | ||
| echo "Swift CI compile checks succeeded on ${SHA}" | ||
| exit 0 | ||
| fi | ||
| echo "Waiting for Swift CI on ${SHA}..." | ||
| sleep 30 | ||
| done | ||
| echo "::error::Timed out waiting for Swift CI compile checks on ${SHA}" | ||
| exit 1 | ||
|
|
||
| release: | ||
| if: github.event.repository.fork == false | ||
| needs: await-swift-ci | ||
| # always() is required so release still runs when await-swift-ci is skipped | ||
| # (pull_request / workflow_dispatch); without it GitHub treats skipped needs as failure. | ||
| if: >- | ||
| always() && | ||
| github.event.repository.fork == false && | ||
| (needs.await-swift-ci.result == 'success' || needs.await-swift-ci.result == 'skipped') | ||
|
jaywedgeworth22 marked this conversation as resolved.
|
||
| runs-on: macos-latest | ||
| timeout-minutes: 60 | ||
| env: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| # 2026-10-15 — CC-19: Swift compile gate (hosted macOS CI + ruleset handoff) | ||
|
|
||
| ## Summary | ||
|
|
||
| CodeCaps had hosted Swift CI (`.github/workflows/swift-ci.yml`) but ruleset | ||
| `default-main-protection` (id `24433457`) did not require any status checks, | ||
| so merges and Sparkle releases could proceed while compile jobs were still | ||
| queued. CC-19 wires the lane for a real gate: one macOS runner per pull | ||
| request, Mac Release waits for the same compile checks on `main`, and this | ||
| document gives Jay the exact check names to add in GitHub (admin-only). | ||
|
|
||
| ## What changed | ||
|
|
||
| - **Swift CI** — stay on `macos-latest` (Swift 6 toolchain required by | ||
| `sentry-cocoa` 9.30.x), cancel stale pull-request runs, run `companion` | ||
| only after `package` (`needs:`) so a PR never holds two macOS runners at | ||
| once. Explicit job `name:` values match the contexts GitHub reports for | ||
| required checks. | ||
| - **Mac Release (Sparkle)** — new `await-swift-ci` job on `ubuntu-latest` | ||
| polls until `package` and `companion` succeed on the merge commit (or fails | ||
| closed if either fails, is cancelled, or times out). The release job | ||
| `needs: await-swift-ci`, closing the race where Sparkle published while | ||
| companion was still running. | ||
| - **This rollout** — owner steps for ruleset required checks (not applied in | ||
| CI; Jay has the admin grant). | ||
|
|
||
| ## Verification (agents) | ||
|
|
||
| ```bash | ||
| python3 -c "import yaml; yaml.safe_load(open('.github/workflows/swift-ci.yml'))" | ||
| python3 -c "import yaml; yaml.safe_load(open('.github/workflows/mac-release.yml'))" | ||
| ``` | ||
|
|
||
| Hosted macOS compile is validated on the pull request’s Swift CI run after push. | ||
|
|
||
| ## Required status checks (Jay — after this is on `main`) | ||
|
|
||
| Ruleset: **Settings → Rules → Rulesets → `default-main-protection`** | ||
| (`24433457`) → add a **Require status checks to pass** rule. | ||
|
|
||
| Require these **job** contexts (not the workflow title `Swift CI`): | ||
|
|
||
| | Context | Workflow | What it proves | | ||
| | --- | --- | --- | | ||
| | `Mac package build and test` | Swift CI | `swift build`, `swift test`, native UI fixture render | | ||
| | `iOS companion compile` | Swift CI | Companion XcodeGen build, simulator smoke, Mac widget target | | ||
| | `gitleaks` | Secret scanning | Secret scan on the PR commit range | | ||
|
|
||
| **Order of operations:** land this PR and confirm at least one green Swift CI | ||
| on `main` **before** ticking the two Swift contexts required. If macOS hosted | ||
| runners are backlogged, a required check that has not started yet blocks every | ||
| pull request — fix queue health first, then enable the Swift contexts. | ||
|
|
||
| Optional strictness: leave **Require branches to be up to date before merging** | ||
| off unless you want merge-queue semantics; Swift CI already runs on the head | ||
| commit. | ||
|
|
||
| Confirm live contexts: | ||
|
|
||
| ```bash | ||
| gh api repos/Simple-With-Us/CodeCaps/rulesets/24433457 \ | ||
| --jq '.rules[] | select(.type=="required_status_checks")' | ||
| ``` | ||
|
|
||
| After you add the rule, the same command should list the three contexts above | ||
| under `parameters.required_status_checks` (or `contexts`, depending on API | ||
| shape). | ||
|
|
||
| Do **not** require workflow names (`Swift CI`, `Secret scanning`). Require the | ||
| **job** names exactly as in the table. | ||
|
|
||
| ## Deferred | ||
|
|
||
| - Ruleset edit itself (Jay admin). | ||
| - Moving compile to self-hosted macOS runners (fleet BotFleet pinning work). | ||
| - Requiring Mac Release or TestFlight workflows as merge gates (ship lanes, not | ||
| compile). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Manual
workflow_dispatchof themac-releaseworkflow publishes a Sparkle release without any Swift CI compile check becauseawait-swift-ciis gated togithub.event_name == 'push'only, causingawait-swift-ci.result == 'skipped'to be treated as a green light and defeating the CC-19 gate. Loosen theawait-swift-ciif to justgithub.event.repository.fork == falsesoreleasegates onresult == 'success'for all triggers.Prompt for LLM
Talk to Kody by mentioning @kody
Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.