diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c68fcf3f..5be910324 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,14 +19,13 @@ name: CI # A draft pull request runs only `changes`: its author ran the gates on their own machine, and a # draft decides nothing, so the matrix would only repeat that. The matrix runs once per push to a # ready pull request, and `ready_for_review` starts it for the push the draft already holds. -# `changes` reports code=false and sdl=false for a draft, the builds skip, and `ci-ok` passes on -# skipped jobs; `gh pr ready` is therefore what makes the required check mean something, and +# `changes` reports code=false and sdl=false for a draft; all other jobs, including +# `ci-ok`, skip; `gh pr ready` is therefore what makes the required check mean something, and # `main`'s ruleset still requires it. Pushes to main and the merge queue are unchanged. # -# A green `ci-ok` on a draft means "nothing was built", and that is safe only because a draft -# cannot be merged and the merge queue reruns the whole matrix on the `merge_group` ref. Turning -# a ready PR back into a draft is not a trigger, so its last full result stays on it; push or -# mark it ready again for a fresh one. +# A skipped `ci-ok` is safe only on a draft: a draft cannot be merged, and the merge queue +# reruns the whole matrix on the `merge_group` ref. Turning a ready PR back into a draft is +# not a trigger, so its last full result stays on it; push or mark it ready again for a fresh one. # # The Zig compiler is restored from the Actions cache by every job: setup-zig keeps the verified # tarball under the key `setup-zig-tarball-` (the version is pinned by ZIG_VERSION; @@ -714,24 +713,31 @@ jobs: kill "$weston_pid" "$xvfb_pid" || true exit "$status" - # The required check. Passes when every job above passed or was skipped (a docs-only change - # skips the builds); fails on any failure or cancellation, `changes` included. A job added to - # this workflow joins the gate by being added to `needs`. + # The required check. Drafts run only changes. Otherwise, every selected job must succeed; + # only jobs deliberately excluded by the code/SDL filters may be skipped. Add each new job + # to needs and to CODE_RESULTS or SDL_RESULT so the required check includes its result. ci-ok: name: ci-ok - if: always() + if: always() && !(github.event_name == 'pull_request' && github.event.pull_request.draft) needs: [changes, format, test, examples, integration, verdict, windows-fizzy-backend, sdl] runs-on: ubuntu-latest steps: - - name: Every job passed or was skipped + - name: Every selected job passed shell: bash env: - RESULTS: ${{ join(needs.*.result, ' ') }} + CHANGES: ${{ needs.changes.result }} + CODE: ${{ needs.changes.outputs.code }} + SDL: ${{ needs.changes.outputs.sdl }} + CODE_RESULTS: ${{ needs.format.result }} ${{ needs.test.result }} ${{ needs.examples.result }} ${{ needs.integration.result }} ${{ needs.verdict.result }} ${{ needs.windows-fizzy-backend.result }} + SDL_RESULT: ${{ needs.sdl.result }} run: | - echo "results: $RESULTS" - for r in $RESULTS; do - case "$r" in - success | skipped) ;; - *) exit 1 ;; - esac + set -euo pipefail + [ "$CHANGES" = success ] + case "$CODE" in true) expected=success ;; false) expected=skipped ;; *) exit 1 ;; esac + for r in $CODE_RESULTS; do + echo "code job: $r (expected $expected)" + [ "$r" = "$expected" ] done + case "$SDL" in true) expected=success ;; false) expected=skipped ;; *) exit 1 ;; esac + echo "SDL job: $SDL_RESULT (expected $expected)" + [ "$SDL_RESULT" = "$expected" ] diff --git a/.github/workflows/web.yml b/.github/workflows/web.yml index a74d33b3f..f66b9a649 100644 --- a/.github/workflows/web.yml +++ b/.github/workflows/web.yml @@ -142,7 +142,8 @@ jobs: with: ref: ${{ matrix.ref }} # The Zig cache as in ci.yml's test job: a fixed key, one cold build saved once. setup-zig's - # own cache saved a new copy every run. + # package cache saved a new copy every run. The compiler tarball is still cached separately + # as setup-zig-tarball- (version, OS and architecture), as in ci.yml. - name: Zig cache key id: zig-cache-key run: | diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f730f7ff8..a87efd0fc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -254,7 +254,8 @@ passed. `.github/rulesets/main.json` is the record of that ruleset; changing it as well as a PR. Admins can merge a PR past a failing check in an emergency, never push to `main` directly. -`ci-ok` passes when every other CI job passed or was skipped: a PR changing only Markdown skips -the builds and still gets its check. `main` merges through the merge +`ci-ok` requires success from every job selected by `changes`; a PR changing only Markdown +deliberately skips the builds and still gets its check. Drafts run only `changes` and skip +`ci-ok`; marking ready starts the full selected checks. `main` merges through the merge queue (squash, up to 4 PRs a batch, `ci-ok` rerun on the `merge_group` ref): `gh pr merge N --auto` queues a PR once its checks pass, and the queue lands it. diff --git a/docs/AGENT_WORK.md b/docs/AGENT_WORK.md index 50453fea1..a6b2875b7 100644 --- a/docs/AGENT_WORK.md +++ b/docs/AGENT_WORK.md @@ -150,11 +150,11 @@ PR creation. Fix the reported problem and retry finish. Neither helper merges or Three places, in order: the worker's **local gates** (step 3), which decide whether the PR is worth pushing; **cross-review** by a different worker; and **CI at ready**. A draft PR runs only -the light `changes` job (`ci.yml`), so pushing to a draft costs almost nothing and proves nothing; -`gh pr ready` starts the full matrix, and `ci-ok` is the required check on that run. A reviewer -waits for finished checks, so a draft is reviewed from its diff and the gate output in its body, +the light `changes` job (`ci.yml`); `ci-ok` is skipped on drafts. Pushing to a draft costs almost +nothing and proves nothing; `gh pr ready` starts the full matrix, and `ci-ok` is the required +check on that run. A reviewer waits for finished checks, so a draft is reviewed from its diff and the gate output in its body, and a cross-reviewer may give a verdict on a draft without CI. The merge question waits for the -full CI at ready. +full CI at ready. Workflow changes require the maintainer's explicit yes before merge. ## Review