From 3112f394eb478b176973bfeb977ce4548df326a6 Mon Sep 17 00:00:00 2001 From: core-fe Date: Thu, 21 May 2026 23:51:16 -0700 Subject: [PATCH] fix(ci): path-scope main push heavy checks --- .gitea/workflows/ci.yml | 68 ++++++++++++++++---------------- tests/test_lint_workflow_yaml.py | 12 +++--- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index fb9bf2a76..e22c9606a 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -98,10 +98,10 @@ jobs: --base-ref "$PR_BASE_REF" \ --push-before "${GITHUB_EVENT_BEFORE:-$PUSH_BEFORE}" - # Platform (Go) — Go build/vet/test/lint + coverage gates. The always-run - # + per-step gating shape preserves the GitHub-side required-check name - # contract (so when this Gitea port becomes a required check in Phase 4, - # the name match works on PRs that don't touch workspace-server/). + # Platform (Go) — Go build/vet/test/lint + coverage gates. The job always + # emits the required context, but expensive steps are path-scoped on every + # event so docs/E2E/Canvas-only main pushes do not block deploy on unrelated + # Go bootstrap work. platform-build: name: Platform (Go) needs: changes @@ -125,29 +125,29 @@ jobs: run: working-directory: workspace-server steps: - - if: ${{ github.event_name == 'pull_request' && needs.changes.outputs.platform != 'true' }} + - if: ${{ needs.changes.outputs.platform != 'true' }} working-directory: . - run: echo "No workspace-server/** changes on this PR — Platform (Go) gate satisfied without running Go build/test/lint." - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.platform == 'true' }} + run: echo "No workspace-server/** changes — Platform (Go) gate satisfied without running Go build/test/lint." + - if: ${{ needs.changes.outputs.platform == 'true' }} uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.platform == 'true' }} + - if: ${{ needs.changes.outputs.platform == 'true' }} uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 with: go-version: 'stable' - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.platform == 'true' }} + - if: ${{ needs.changes.outputs.platform == 'true' }} run: go mod download - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.platform == 'true' }} + - if: ${{ needs.changes.outputs.platform == 'true' }} run: go build ./cmd/server # CLI (molecli) moved to standalone repo: git.moleculesai.app/molecule-ai/molecule-cli - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.platform == 'true' }} + - if: ${{ needs.changes.outputs.platform == 'true' }} run: go vet ./... - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.platform == 'true' }} + - if: ${{ needs.changes.outputs.platform == 'true' }} name: Install golangci-lint run: go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.12.2 - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.platform == 'true' }} + - if: ${{ needs.changes.outputs.platform == 'true' }} name: Run golangci-lint run: $(go env GOPATH)/bin/golangci-lint run --timeout 3m ./... - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.platform == 'true' }} + - if: ${{ needs.changes.outputs.platform == 'true' }} name: Diagnostic — per-package verbose 60s run: | set +e @@ -163,7 +163,7 @@ jobs: echo "::endgroup::" # mc#774: pre-existing continue-on-error mask; root-fix and remove, do not renew silently. continue-on-error: true - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.platform == 'true' }} + - if: ${{ needs.changes.outputs.platform == 'true' }} name: Run tests with race detection and coverage # Explicit timeout: cold runner cache causes OOM kills at ~4m39s on the # full ./... suite with race detection + coverage. A 10m per-step timeout @@ -171,7 +171,7 @@ jobs: # instead of OOM-killing. The job-level timeout (15m) is a backstop. run: go test -race -timeout 10m -coverprofile=coverage.out ./... - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.platform == 'true' }} + - if: ${{ needs.changes.outputs.platform == 'true' }} name: Per-file coverage report # Advisory — lists every source file with its coverage so reviewers # can see at-a-glance where gaps are. Sorted ascending so the worst @@ -185,7 +185,7 @@ jobs: END {for (f in s) printf "%6.1f%% %s\n", s[f]/c[f], f}' \ | sort -n - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.platform == 'true' }} + - if: ${{ needs.changes.outputs.platform == 'true' }} name: Check coverage thresholds # Enforces two gates from #1823 Layer 1: # 1. Total floor (25% — ratchet plan in COVERAGE_FLOOR.md). @@ -282,20 +282,20 @@ jobs: run: working-directory: canvas steps: - - if: ${{ github.event_name == 'pull_request' && needs.changes.outputs.canvas != 'true' }} + - if: ${{ needs.changes.outputs.canvas != 'true' }} working-directory: . - run: echo "No canvas/** changes on this PR — Canvas (Next.js) gate satisfied without running npm build/test." - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.canvas == 'true' }} + run: echo "No canvas/** changes — Canvas (Next.js) gate satisfied without running npm build/test." + - if: ${{ needs.changes.outputs.canvas == 'true' }} uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.canvas == 'true' }} + - if: ${{ needs.changes.outputs.canvas == 'true' }} uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: '22' - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.canvas == 'true' }} + - if: ${{ needs.changes.outputs.canvas == 'true' }} run: npm ci --include=optional --prefer-offline - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.canvas == 'true' }} + - if: ${{ needs.changes.outputs.canvas == 'true' }} run: npm run build - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.canvas == 'true' }} + - if: ${{ needs.changes.outputs.canvas == 'true' }} name: Run tests with coverage # Coverage instrumentation is configured in canvas/vitest.config.ts # (provider: v8, reporters: text + html + json-summary). Step 2 of @@ -304,7 +304,7 @@ jobs: # tracked in #1815) after the team sees what current coverage is. run: npx vitest run --coverage - name: Upload coverage summary as artifact - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.canvas == 'true' }} + if: ${{ needs.changes.outputs.canvas == 'true' }} # Pinned to v3 for Gitea act_runner v0.6 compatibility — v4+ uses # the GHES 3.10+ artifact protocol that Gitea 1.22.x does NOT # implement, surfacing as `GHESNotSupportedError: @actions/artifact @@ -318,7 +318,7 @@ jobs: retention-days: 7 if-no-files-found: warn - # Shellcheck (E2E scripts) — required check, always runs. + # Shellcheck (E2E scripts) — required context, path-scoped heavy steps. shellcheck: name: Shellcheck (E2E scripts) needs: changes @@ -326,11 +326,11 @@ jobs: # Phase 4 (RFC #219 §1): confirmed green on main 2026-05-12. continue-on-error: false steps: - - if: ${{ github.event_name == 'pull_request' && needs.changes.outputs.scripts != 'true' }} - run: echo "No tests/e2e, scripts, or infra/scripts changes on this PR — Shellcheck gate satisfied without running script checks." - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.scripts == 'true' }} + - if: ${{ needs.changes.outputs.scripts != 'true' }} + run: echo "No tests/e2e, scripts, or infra/scripts changes — Shellcheck gate satisfied without running script checks." + - if: ${{ needs.changes.outputs.scripts == 'true' }} uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.scripts == 'true' }} + - if: ${{ needs.changes.outputs.scripts == 'true' }} name: Run shellcheck on tests/e2e/*.sh and infra/scripts/*.sh # shellcheck is pre-installed on ubuntu-latest runners (via apt). # infra/scripts/ is included because setup.sh + nuke.sh gate the @@ -341,16 +341,16 @@ jobs: find tests/e2e infra/scripts -type f -name '*.sh' -print0 \ | xargs -0 shellcheck --severity=warning - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.scripts == 'true' }} + - if: ${{ needs.changes.outputs.scripts == 'true' }} name: Lint cleanup-trap hygiene (RFC #2873) run: bash tests/e2e/lint_cleanup_traps.sh - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.scripts == 'true' }} + - if: ${{ needs.changes.outputs.scripts == 'true' }} name: Run E2E bash unit tests (no live infra) run: | bash tests/e2e/test_model_slug.sh - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.scripts == 'true' }} + - if: ${{ needs.changes.outputs.scripts == 'true' }} name: Test ECR promote-tenant-image script (mock-driven, no live infra) # Covers scripts/promote-tenant-image.sh — the codified # :staging-latest → :latest ECR promote + tenant fleet redeploy @@ -360,7 +360,7 @@ jobs: run: | bash scripts/test-promote-tenant-image.sh - - if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.scripts == 'true' }} + - if: ${{ needs.changes.outputs.scripts == 'true' }} name: Shellcheck promote-tenant-image script # scripts/ is excluded from the bulk shellcheck pass above (legacy # SC3040/SC3043 cleanup pending). Run shellcheck explicitly on diff --git a/tests/test_lint_workflow_yaml.py b/tests/test_lint_workflow_yaml.py index a8c4d0b2f..2280417f6 100644 --- a/tests/test_lint_workflow_yaml.py +++ b/tests/test_lint_workflow_yaml.py @@ -705,7 +705,7 @@ def test_ci_change_detector_docs_and_meta_scripts_do_not_trigger_surfaces(): } -def test_ci_platform_go_pr_steps_are_path_scoped(): +def test_ci_platform_go_steps_are_path_scoped_on_all_events(): doc = yaml.safe_load(CI_WORKFLOW.read_text(encoding="utf-8")) platform = doc["jobs"]["platform-build"] assert platform.get("needs") == "changes" @@ -720,11 +720,11 @@ def test_ci_platform_go_pr_steps_are_path_scoped(): assert expensive_steps for step in expensive_steps: expr = step.get("if", "") - assert "github.event_name != 'pull_request'" in expr assert "needs.changes.outputs.platform == 'true'" in expr + assert "github.event_name != 'pull_request'" not in expr -def test_ci_canvas_nextjs_pr_steps_are_path_scoped(): +def test_ci_canvas_nextjs_steps_are_path_scoped_on_all_events(): doc = yaml.safe_load(CI_WORKFLOW.read_text(encoding="utf-8")) canvas = doc["jobs"]["canvas-build"] assert canvas.get("needs") == "changes" @@ -739,11 +739,11 @@ def test_ci_canvas_nextjs_pr_steps_are_path_scoped(): assert expensive_steps for step in expensive_steps: expr = step.get("if", "") - assert "github.event_name != 'pull_request'" in expr assert "needs.changes.outputs.canvas == 'true'" in expr + assert "github.event_name != 'pull_request'" not in expr -def test_ci_shellcheck_pr_steps_are_path_scoped(): +def test_ci_shellcheck_steps_are_path_scoped_on_all_events(): doc = yaml.safe_load(CI_WORKFLOW.read_text(encoding="utf-8")) shellcheck = doc["jobs"]["shellcheck"] assert shellcheck.get("needs") == "changes" @@ -756,5 +756,5 @@ def test_ci_shellcheck_pr_steps_are_path_scoped(): assert expensive_steps for step in expensive_steps: expr = step.get("if", "") - assert "github.event_name != 'pull_request'" in expr assert "needs.changes.outputs.scripts == 'true'" in expr + assert "github.event_name != 'pull_request'" not in expr -- 2.52.0