From 25f337494c73e4594426e534030bdf22d2ace684 Mon Sep 17 00:00:00 2001 From: cluade-reviewer-andresmgsl Date: Wed, 29 Jul 2026 12:10:38 +0000 Subject: [PATCH 1/2] fix: rig's ceremony CI guards resolve on Forgejo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The six ceremony actions in ci.yml are step `uses:` references, and a bare step reference resolves through FORGEJO__actions__DEFAULT_ACTIONS_URL — which this forge points at code.forgejo.org, where heavy-duty/ceremony does not exist. Measured with a registered runner on the instance: `git clone https://code.forgejo.org/heavy-duty/ceremony` -> 404, so every guard fails the moment rig's own CI runs on the forge. Those six become absolute. The two reusable-workflow callers do NOT move, and this is the correction to the original "make all eight absolute" ruling. A reusable `uses:` never consults DEFAULT_ACTIONS_URL; it resolves against the runner's own instance, so both callers already fetch ceremony from this forge and expand. Absolutising release.yml's would actively break CI: ceremony's docs-sync reads rig's pin out of that one line with a grep anchored to the bare spelling, so the prefix makes the pin invisible and docs-sync exits 1 with "no pin line ... found none". actions/checkout@v4 stays bare in all three places — the mirror serves it, and that is exactly what DEFAULT_ACTIONS_URL is for. The pin stays @0.3.0 throughout; no .ceremony/ edit, no pin bump. test/cli.sh pins all three shapes, including the docs-sync grep verbatim, so ceremony's parser and rig's caller cannot drift apart silently. Refs #112 Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/ci.yml | 24 ++++++++++++++++------ README.md | 31 ++++++++++++++-------------- changelog.d/112.md | 3 +++ test/cli.sh | 44 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 21 deletions(-) create mode 100644 changelog.d/112.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a8ca94f..96d98ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,26 +50,38 @@ jobs: # lives with its implementation upstream; the six pins below and the # two workflow callers must always name the same ceremony tag. # + # These six are ABSOLUTE and the two callers in release.yml/labels.yml + # are BARE. That asymmetry is measured, not stylistic (#112) — do not + # "tidy" either half into the other: + # a step `uses:` resolves a bare name through DEFAULT_ACTIONS_URL, + # which this forge points at code.forgejo.org, where ceremony does not + # exist — bare 404s and every guard below fails; + # a reusable-workflow `uses:` never consults DEFAULT_ACTIONS_URL at + # all — it resolves against the runner's own instance, so bare already + # works there. And release.yml's caller is the line ceremony's own + # docs-sync greps for its pin, anchored to the bare spelling: make it + # absolute and the pin goes invisible and docs-sync exits 1. + # # changelog-armed: the version-keyed arming rule (rig#66; the # unconditional form rig#44 reverted — this is its correct return). - - uses: heavy-duty/ceremony/actions/changelog-armed@0.3.0 + - uses: https://forgejo.heavyduty.builders/heavy-duty/ceremony/actions/changelog-armed@0.3.0 # changelog-monotonic: no shipped heading deleted or duplicated # (#98, box#122). Strict by default: an unresolvable base ref is red, # never a quiet skip — hence the fetch-depth: 0 above. - - uses: heavy-duty/ceremony/actions/changelog-monotonic@0.3.0 + - uses: https://forgejo.heavyduty.builders/heavy-duty/ceremony/actions/changelog-monotonic@0.3.0 # changelog-assembled: a release's stamped section must exactly match # the fragments it consumed. Vacuous on non-release PRs. - - uses: heavy-duty/ceremony/actions/changelog-assembled@0.3.0 + - uses: https://forgejo.heavyduty.builders/heavy-duty/ceremony/actions/changelog-assembled@0.3.0 # drill-recorded: a release version carries drills/.md # (rig's drill meaning: drills/README.md). Vacuous on -dev trees. - - uses: heavy-duty/ceremony/actions/drill-recorded@0.3.0 + - uses: https://forgejo.heavyduty.builders/heavy-duty/ceremony/actions/drill-recorded@0.3.0 # runner-isolated: PR-triggered workflows never execute unreviewed # branch code on a self-hosted runner. - - uses: heavy-duty/ceremony/actions/runner-isolated@0.3.0 + - uses: https://forgejo.heavyduty.builders/heavy-duty/ceremony/actions/runner-isolated@0.3.0 # docs-sync: the .ceremony/ doctrine mirror is byte-identical to the # pin read from release.yml (ceremony#19) — a hand edit or a # half-done pin bump goes red here. - - uses: heavy-duty/ceremony/actions/docs-sync@0.3.0 + - uses: https://forgejo.heavyduty.builders/heavy-duty/ceremony/actions/docs-sync@0.3.0 # The install LIFECYCLE against a tree install.sh itself produced — the four # beats box and cast already run in CI (#106): install from this checkout, diff --git a/README.md b/README.md index 69d5bfa..baae332 100644 --- a/README.md +++ b/README.md @@ -1179,31 +1179,32 @@ FORGEJO__actions__ENABLED=true FORGEJO__actions__DEFAULT_ACTIONS_URL=https://code.forgejo.org ``` -> **`DEFAULT_ACTIONS_URL` is a single fallback, and rig's own workflows need -> two origins.** It decides where a *bare* `uses: owner/repo@ref` resolves. -> Measured: +> **`DEFAULT_ACTIONS_URL` is a single fallback, and it only governs *steps*.** +> It decides where a bare `uses: owner/repo@ref` on a **step** resolves — and +> nothing else. Measured on this instance, with a registered runner (#112): > -> | reference | count in `.github/workflows/` | `code.forgejo.org` | -> |---|---|---| -> | `actions/checkout@v4` | 3 | **200** — mirrored | -> | `heavy-duty/ceremony/...@0.3.0` | 8 | **404** — lives on this Forgejo instead | +> | reference | count | bare resolves to | verdict | +> |---|---|---|---| +> | `actions/checkout@v4` (step) | 3 | `code.forgejo.org` | **200** — mirrored, keep bare | +> | `heavy-duty/ceremony/actions/…` (step) | 6 | `code.forgejo.org` | **404** — must be absolute | +> | `heavy-duty/ceremony/.github/workflows/…` (reusable) | 2 | **this instance** | **200** — keep bare | > -> So with the value above, every ceremony guard (`changelog-armed`, -> `changelog-monotonic`, `changelog-assembled`, `drill-recorded`, -> `runner-isolated`, `docs-sync`, and the release/labels callers) fails to -> resolve the moment rig's CI actually runs on the forge. +> The last row is the one that surprises: a **reusable-workflow** `uses:` never +> consults `DEFAULT_ACTIONS_URL` at all. It resolves against the runner's own +> instance, so the `release.yml` and `labels.yml` callers already work bare. > -> Forgejo accepts an absolute URL per step, so one side has to be explicit. > **The ruling is to keep the value above** — `actions/*` are exactly what > `DEFAULT_ACTIONS_URL` is designed to resolve, and `code.forgejo.org` mirrors -> them — and to make the eight first-party references absolute: +> them — and to make only the **six** first-party *step* references absolute: > > ```yaml > - uses: https://forgejo.heavyduty.builders/heavy-duty/ceremony/actions/docs-sync@0.3.0 > ``` > -> That change is tracked in forgejo#112, not made here. Until it lands, -> **rig's own CI is not expected to run on Forgejo**. +> The two reusable callers **stay bare**, and `release.yml`'s must: ceremony's +> `docs-sync` reads rig's pin out of that line with a grep anchored to the bare +> spelling, so absolutising it hides the pin and the guard exits 1. `test/cli.sh` +> pins all three shapes. > `rig forgejo-runner` exists to run *your repositories'* workflows and does not > depend on any of it — the value above is correct for those from the start. diff --git a/changelog.d/112.md b/changelog.d/112.md new file mode 100644 index 0000000..8d6ee75 --- /dev/null +++ b/changelog.d/112.md @@ -0,0 +1,3 @@ +### Fixed + +- rig's six ceremony CI guards resolve on Forgejo — bare names 404'd through `DEFAULT_ACTIONS_URL`; the two reusable callers stay bare (#112) diff --git a/test/cli.sh b/test/cli.sh index 46ade38..060c307 100644 --- a/test/cli.sh +++ b/test/cli.sh @@ -3516,6 +3516,50 @@ check "rig runner: still requires --repo, unchanged" 2 "--repo is r check "rig runner: still speaks github.com" 0 "https://github.com/" \ grep -o "https://github.com/\${repo}" "$ROOT/commands/lib/runner-config.sh" +# --- ceremony uses: resolution on this forge (#112) -------------------------- +# The six ci.yml guards resolve ABSOLUTELY; the two reusable callers stay BARE. +# The two halves pull opposite ways and each was measured on the instance: +# +# guards — a step `uses:` resolves a bare name through DEFAULT_ACTIONS_URL +# (code.forgejo.org here), where heavy-duty/ceremony does not +# exist: a real run 404'd on `git clone`, so every guard failed. +# callers — a reusable-workflow `uses:` never consults DEFAULT_ACTIONS_URL; +# it resolves against the runner's own instance, so bare already +# fetches ceremony from this forge and expands. +# +# release.yml's caller additionally MUST stay bare: ceremony's docs-sync reads +# rig's pin out of that one line with an anchored grep, and an absolute prefix +# makes the pin invisible (docs-sync exits 1, `no pin line ... found none`). +# The pin regex below is that grep verbatim — if ceremony's parser and this +# file ever disagree, this is the test that says so. +wf_count() { printf 'count=%s\n' "$(grep -cE "$2" "$ROOT/.github/workflows/$1" || true)"; } + +check "ci.yml: six ceremony guards, absolute at 0.3.0" 0 "count=6" \ + wf_count ci.yml '^[[:space:]]*- uses: https://forgejo\.heavyduty\.builders/heavy-duty/ceremony/actions/[a-z-]+@0\.3\.0$' +check "ci.yml: no bare ceremony action survives (they 404 via DEFAULT_ACTIONS_URL)" 0 "count=0" \ + wf_count ci.yml '^[[:space:]]*- uses: heavy-duty/ceremony/' +check "ci.yml: the three actions/checkout stay bare (the mirror resolves them)" 0 "count=3" \ + wf_count ci.yml '^[[:space:]]*- uses: actions/checkout@v4$' + +# The docs-sync pin grep, verbatim from ceremony 0.3.0 +# actions/docs-sync/docs-sync.sh — exactly one line must match, or the guard +# dies with "expected exactly one" / "found none". +check "release.yml: the pin is still visible to ceremony's docs-sync grep" 0 "count=1" \ + wf_count release.yml '^[[:space:]]*(-[[:space:]]*)?uses:[[:space:]]*heavy-duty/ceremony/\.github/workflows/release\.yml@' +check "labels.yml: the reusable caller stays bare too" 0 "count=1" \ + wf_count labels.yml '^[[:space:]]*uses:[[:space:]]*heavy-duty/ceremony/\.github/workflows/labels\.yml@0\.3\.0$' +check "release.yml: the caller was not absolutised (docs-sync would go red)" 0 "count=0" \ + wf_count release.yml '^[[:space:]]*uses:[[:space:]]*https://.*ceremony/\.github/workflows/' +check "labels.yml: the caller was not absolutised either" 0 "count=0" \ + wf_count labels.yml '^[[:space:]]*uses:[[:space:]]*https://.*ceremony/\.github/workflows/' + +# One tag governs all eight references — the pin may be bumped, never split. +ceremony_tags() { + grep -rhoE 'heavy-duty/ceremony/[^@]+@[^[:space:]]+' "$ROOT/.github/workflows/" \ + | sed -E 's/.*@//' | sort -u | tr '\n' ' ' +} +check "all eight ceremony references still name one tag" 0 "0.3.0" ceremony_tags + echo "---" echo "$PASS passed, $FAIL failed" [ "$FAIL" -eq 0 ] -- 2.45.2 From 54efc17246da9c2cfbf943e93d843267cb61bf58 Mon Sep 17 00:00:00 2001 From: cluade-reviewer-andresmgsl Date: Wed, 29 Jul 2026 12:22:08 +0000 Subject: [PATCH 2/2] docs: the changelog fragment says what changed and stops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CONTRIBUTING's changelog rule is explicit — the fragment answers one question, what is different in this version; why it was wrong and what it implies belong in the PR body and the commit message, which is where anyone chasing the reasoning already goes. The entry carried both. Review: codex-reviewer-andresmgsl on !113. Refs #112 Co-Authored-By: Claude Opus 5 (1M context) --- changelog.d/112.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/112.md b/changelog.d/112.md index 8d6ee75..ade8a25 100644 --- a/changelog.d/112.md +++ b/changelog.d/112.md @@ -1,3 +1,3 @@ ### Fixed -- rig's six ceremony CI guards resolve on Forgejo — bare names 404'd through `DEFAULT_ACTIONS_URL`; the two reusable callers stay bare (#112) +- rig's six ceremony CI guards resolve on Forgejo (#112) -- 2.45.2