From 7da843f2fa31e3dad3a0c140f7a277456ec653df Mon Sep 17 00:00:00 2001 From: claude-ceo-assistant Date: Sat, 23 May 2026 20:09:31 -0700 Subject: [PATCH] fix(ci): move all-required to meta runner lane --- .../tests/test_ci_workflow_bookkeeping.py | 31 ++++++++++++++++ .gitea/workflows/ci.yml | 35 ++++++++++++++++--- 2 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 .gitea/scripts/tests/test_ci_workflow_bookkeeping.py diff --git a/.gitea/scripts/tests/test_ci_workflow_bookkeeping.py b/.gitea/scripts/tests/test_ci_workflow_bookkeeping.py new file mode 100644 index 00000000..418dea64 --- /dev/null +++ b/.gitea/scripts/tests/test_ci_workflow_bookkeeping.py @@ -0,0 +1,31 @@ +from pathlib import Path + +import yaml + + +ROOT = Path(__file__).resolve().parents[2] + + +def load_workflow(name: str) -> dict: + with (ROOT / "workflows" / name).open() as f: + return yaml.safe_load(f) + + +def test_all_required_uses_dedicated_meta_runner_lane(): + workflow = load_workflow("ci.yml") + all_required = workflow["jobs"]["all-required"] + + assert all_required["runs-on"] == "ci-meta" + assert "needs" not in all_required + + +def test_all_required_reuses_path_filter_before_polling(): + workflow = load_workflow("ci.yml") + all_required = workflow["jobs"]["all-required"] + rendered = str(all_required) + + assert "--profile ci" in rendered + assert ".gitea/scripts/detect-changes.py" in rendered + assert "REQUIRE_PLATFORM" in rendered + assert "REQUIRE_CANVAS" in rendered + assert "REQUIRE_SCRIPTS" in rendered diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index e22c9606..90bedd02 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -476,7 +476,11 @@ jobs: # jobs settle, leaving branch protection with a permanent pending # `CI / all-required` context. Instead, this independent sentinel polls the # required commit-status contexts for this SHA and fails if any fail, skip, - # or never emit. + # or never emit. It runs the same path detector as `changes` and only waits + # for path-relevant jobs; Gitea can otherwise leave needs/output-skipped + # jobs permanently pending with "Blocked by required conditions". It runs on + # the dedicated `ci-meta` lane so the poller does not occupy the same + # general runner pool as the jobs it is waiting for. # # canvas-deploy-reminder is intentionally NOT included in all-required.needs. # It is an informational main-push reminder, not a PR quality gate. Keeping @@ -484,9 +488,24 @@ jobs: # sentinel before the `always()` guard can emit a branch-protection status. # continue-on-error: false - runs-on: ubuntu-latest + runs-on: ci-meta timeout-minutes: 45 steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + - id: check + env: + PR_BASE_SHA: ${{ github.event.pull_request.base.sha }} + PR_BASE_REF: ${{ github.event.pull_request.base.ref }} + PUSH_BEFORE: ${{ github.event.before }} + run: | + python3 .gitea/scripts/detect-changes.py \ + --profile ci \ + --event-name "${{ github.event_name }}" \ + --pr-base-sha "$PR_BASE_SHA" \ + --base-ref "$PR_BASE_REF" \ + --push-before "${GITHUB_EVENT_BEFORE:-$PUSH_BEFORE}" - name: Wait for required CI contexts env: GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -494,6 +513,9 @@ jobs: REPOSITORY: ${{ github.repository }} COMMIT_SHA: ${{ github.sha }} EVENT_NAME: ${{ github.event_name }} + REQUIRE_PLATFORM: ${{ steps.check.outputs.platform }} + REQUIRE_CANVAS: ${{ steps.check.outputs.canvas }} + REQUIRE_SCRIPTS: ${{ steps.check.outputs.scripts }} run: | set -euo pipefail python3 - <<'PY' @@ -511,11 +533,14 @@ jobs: event = os.environ["EVENT_NAME"] required = [ f"CI / Detect changes ({event})", - f"CI / Platform (Go) ({event})", - f"CI / Canvas (Next.js) ({event})", - f"CI / Shellcheck (E2E scripts) ({event})", f"CI / Python Lint & Test ({event})", ] + if os.environ.get("REQUIRE_PLATFORM") == "true": + required.append(f"CI / Platform (Go) ({event})") + if os.environ.get("REQUIRE_CANVAS") == "true": + required.append(f"CI / Canvas (Next.js) ({event})") + if os.environ.get("REQUIRE_SCRIPTS") == "true": + required.append(f"CI / Shellcheck (E2E scripts) ({event})") terminal_bad = {"failure", "error"} deadline = time.time() + 40 * 60 last_summary = None -- 2.52.0