fix(ci): build the tag being released, not the dispatch branch - #669
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThe release workflow now selects ChangesRelease reference propagation
Estimated code review effort: 2 (Simple) | ~10 minutes Sequence Diagram(s)sequenceDiagram
participant Release as release.yml
participant Workflow as reusable release workflow
participant Checkout as actions/checkout
Release->>Workflow: pass inputs.tag || github.ref as ref
Workflow->>Checkout: checkout inputs.ref
Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
skill-check — worker0 verified, 51 skipped (no docs/).
Four for four. Nicely done. |
87f033c to
b8c5137
Compare
`actions/checkout` with no `ref` resolves the ref that started the run. On a `push: tags:` trigger that is the tag, so the release path was correct by accident. On a `workflow_dispatch` it is the branch the dispatch was started from — `alpha-release.yml` dispatches with `--ref main` — while the tag reaches the jobs only as metadata: the version parsed from its name and `tag_name` on the GitHub Release. So a dispatched release compiles one commit and labels the artifacts with another commit's version, silently. `state/v0.21.4-alpha.2` shipped this way: the tag points at a commit pinning `iii-sdk = "=0.22.0-alpha.3"`, but the binary was built from main, which pins `=0.21.6`. The published artifact carries the prerelease version number and none of the code it names — it does not send `namespace` on `engine::workers::register`, so no worker built this way can join a namespaced project. Every checkout in the release path now takes the ref being released. The reusable workflows get an optional `ref` input defaulting to `''`, which is `actions/checkout`'s own default, so nothing changes for a tag push. The dispatch keeps using `--ref main`: the pipeline definition should come from main, only the source it compiles should follow the tag.
b8c5137 to
4691419
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/_container.yml:
- Around line 51-52: Update the actions/checkout@v5 configuration by adding
persist-credentials: false alongside the existing ref input, while preserving
the current checkout behavior and ref value.
In @.github/workflows/release.yml:
- Around line 190-191: Update the checkout step in the create-release job to set
persist-credentials to false, then configure the subsequent release action to
authenticate explicitly with GITHUB_TOKEN instead of relying on persisted
checkout credentials.
- Around line 190-191: Disable persisted checkout credentials by adding
persist-credentials: false to every release-path actions/checkout step:
.github/workflows/release.yml:190-191, .github/workflows/_bundle.yml:62-63 and
84-85, .github/workflows/_container.yml:51-52,
.github/workflows/_publish-registry.yml:61-62, and
.github/workflows/_rust-binary.yml:68-69, 137-138, and 241-242. Preserve
existing checkout refs and behavior; no later Git operation requires the
persisted token.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 235a1224-a5b0-4c61-be7b-f07a6db85a95
📒 Files selected for processing (5)
.github/workflows/_bundle.yml.github/workflows/_container.yml.github/workflows/_publish-registry.yml.github/workflows/_rust-binary.yml.github/workflows/release.yml
| with: | ||
| ref: ${{ inputs.ref }} |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow files =="
git ls-files .github/workflows || true
echo "== target workflow context =="
if [ -f .github/workflows/_container.yml ]; then
sed -n '1,140p' .github/workflows/_container.yml | cat -n
fi
echo "== search for persisted credentials / git auth post checkout =="
rg -n "persist-credentials|git credential|GITHUB_TOKEN|contents: read|checkout|container" .github/workflows || true
echo "== diff around target if available =="
git diff -- .github/workflows/_container.yml | sed -n '1,200p'Repository: iii-hq/workers
Length of output: 10720
🌐 Web query:
actions checkout persist-credentials default true README
💡 Result:
The default value for the persist-credentials input in the actions/checkout GitHub Action is true [1][2][3]. When persist-credentials is set to true (the default), the action configures the Git credential helper or local git configuration with the provided GITHUB_TOKEN or SSH key, allowing subsequent git commands in your workflow (such as git fetch or git push) to run authenticated [1][2][4]. To prevent the action from configuring these credentials, you must explicitly set persist-credentials to false [1][2]. Note that in recent versions (starting with v6.0.0), the action has been updated to improve credential security by storing credentials in a separate file under $RUNNER_TEMP instead of directly in.git/config, though the default setting of true remains [1][2][5][6].
Citations:
- 1: https://github.com/actions/checkout
- 2: https://github.com/actions/checkout/tree/v6.0.2?tab=readme-ov-file
- 3: https://github.com/actions/checkout/blob/cbb722410c2e876e24abbe8de2cc27693e501dcb/action.yml
- 4: https://github.com/marketplace/actions/checkout?version=v3.6.0
- 5: https://github.com/actions/checkout/tree/v6.0.0
- 6: actions/checkout@v5.0.1...v6.0.0
Disable persisted checkout credentials.
Set persist-credentials: false on actions/checkout@v5 because the later container build uses a direct docker/login-action login and does not need Git authentication after checkout.
🧰 Tools
🪛 zizmor (1.28.0)
[warning] 50-52: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/_container.yml around lines 51 - 52, Update the
actions/checkout@v5 configuration by adding persist-credentials: false alongside
the existing ref input, while preserving the current checkout behavior and ref
value.
Source: Linters/SAST tools
| with: | ||
| ref: ${{ inputs.tag || github.ref }} |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow relevant snippets =="
cat -n .github/workflows/release.yml | sed -n '150,230p'
echo
echo "== all checkout refs and persist-credentials in release workflow =="
python3 - <<'PY'
import pathlib, re
p=pathlib.Path('.github/workflows/release.yml')
text=p.read_text()
for i,line in enumerate(text.splitlines(),1):
if 'actions/checkout' in line or 'persist-credentials' in line or 'GITHUB_TOKEN' in line or 'github-token' in line:
print(f'{i}: {line}')
PYRepository: iii-hq/workers
Length of output: 4353
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== create-release surrounding steps =="
cat -n .github/workflows/release.yml | sed -n '1,125p'
echo
echo "== release workflow references to git credentials/repo tokens =="
python3 - <<'PY'
import pathlib
text=pathlib.Path('.github/workflows/release.yml').read_text()
terms=['git','persist-credentials','github-token','GITHUB_TOKEN','secrets.GITHUB_TOKEN','git config','git push','git tag','git push origin','GH_TOKEN','action-gh-release','actions/checkout']
for i,line in enumerate(text.splitlines(),1):
if any(t in line for t in terms):
print(f'{i}: {line}')
PYRepository: iii-hq/workers
Length of output: 4903
Disable persisted checkout credentials.
Set persist-credentials: false on the create-release checkout step, then use GITHUB_TOKEN only for the subsequent release action.
🧰 Tools
🪛 zizmor (1.28.0)
[warning] 189-191: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/release.yml around lines 190 - 191, Update the checkout
step in the create-release job to set persist-credentials to false, then
configure the subsequent release action to authenticate explicitly with
GITHUB_TOKEN instead of relying on persisted checkout credentials.
Source: Linters/SAST tools
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'Files matching release/bundle container registry rust workflows:\n'
fd -a '^(release|_bundle|_container|_publish-registry|_rust-binary)\.ya?ml$' .github/workflows || true
printf '\nRelevant checkout action occurrences:\n'
rg -n "actions/checkout|persist-credentials|setup-git|currentRef|ref:" .github/workflows || true
printf '\nWorkflow excerpts:\n'
for f in .github/workflows/release.yml .github/workflows/_bundle.yml .github/workflows/_container.yml .github/workflows/_publish-registry.yml .github/workflows/_rust-binary.yml; do
if [ -f "$f" ]; then
echo "---- $f ----"
wc -l "$f"
sed -n '40,110p' "$f"
sed -n '170,210p' "$f"
fi
done
printf '\nDependency/action pins in release path worklfows:\n'
python3 - <<'PY'
import pathlib, re, yaml
for p in pathlib.Path('.github/workflows').glob('*.yml'):
text=p.read_text()
if any(s in text for s in ['release', 'bundle', 'container', 'registry', 'rust-binary']) or p.name in ['release.yml','_bundle.yml','_container.yml','_publish-registry.yml','_rust-binary.yml']:
print(f'---- {p.name} ----')
try:
data=yaml.safe_load(text)
jobs=data.get('jobs',{})
except Exception as e:
print('YAML parse error', e)
continue
for name,job in jobs.items():
if not isinstance(job, dict): continue
steps=job.get('steps', [])
for i,s in enumerate(steps):
uses=s.get('with',{}).get('uses')
if 'checkout' in str(s):
withs=s.get('with',{})
print(name, i, s.get('id'), uses, withs)
PYRepository: iii-hq/workers
Length of output: 25871
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '120,320p' .github/workflows/release.yml
printf '\n---- .github/workflows/_rust-binary.yml excerpts ----\n'
sed -n '50,160p' .github/workflows/_rust-binary.yml
sed -n '225,265p' .github/workflows/_rust-binary.yml
sed -n '265,365p' .github/workflows/_rust-binary.yml
printf '\n---- _publish-registry.yml package/registry step context ----\n'
sed -n '80,175p' .github/workflows/_publish-registry.yml
sed -n '175,270p' .github/workflows/_publish-registry.yml
sed -n '270,345p' .github/workflows/_publish-registry.yml
printf '\nSearch for git credential/config usage in workflows:\n'
rg -n "git (config|remote|push|fetch|ls-remote)|GITHUB_TOKEN|secrets\.GITHUB_TOKEN|persist-credentials|GH_TOKEN|GH_PAT" .github/workflows || trueRepository: iii-hq/workers
Length of output: 33324
🌐 Web query:
actions/checkout v5 persist-credentials default true README
💡 Result:
In the actions/checkout action, including version v5, the persist-credentials input defaults to true [1][2]. When this setting is enabled (the default), the action configures the authentication token or SSH key with the local git configuration [1][2]. This allows your workflow scripts to execute authenticated git commands [1][3]. During the post-job cleanup phase, the action automatically removes these credentials [1][3]. To disable this behavior, you can explicitly set persist-credentials to false in your workflow configuration [1][4].
Citations:
- 1: https://github.com/actions/checkout
- 2: https://github.com/actions/checkout/blob/72f2cec99f417b1a1c5e2e88945068983b7965f9/action.yml
- 3: https://github.com/actions/checkout/?tab=readme-ov-file
- 4: https://git.liteyuki.org/actions/checkout/src/tag/v5/README.md
Disable persisted checkout credentials in the release path.
actions/checkout@v5 leaves token auth in the local Git config by default. Set persist-credentials: false on the release-path checkouts unless a later Git operation requires it.
.github/workflows/release.yml#L189-L191.github/workflows/_bundle.yml#L60-L62and#L82-L84.github/workflows/_container.yml#L50-L51.github/workflows/_publish-registry.yml#L60-L61.github/workflows/_rust-binary.yml#L66-L68,#L135-L137, and#L239-L241
🧰 Tools
🪛 zizmor (1.28.0)
[warning] 189-191: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
📍 Affects 5 files
.github/workflows/release.yml#L190-L191(this comment).github/workflows/_bundle.yml#L62-L63.github/workflows/_bundle.yml#L84-L85.github/workflows/_container.yml#L51-L52.github/workflows/_publish-registry.yml#L61-L62.github/workflows/_rust-binary.yml#L68-L69.github/workflows/_rust-binary.yml#L137-L138.github/workflows/_rust-binary.yml#L241-L242
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/release.yml around lines 190 - 191, Disable persisted
checkout credentials by adding persist-credentials: false to every release-path
actions/checkout step: .github/workflows/release.yml:190-191,
.github/workflows/_bundle.yml:62-63 and 84-85,
.github/workflows/_container.yml:51-52,
.github/workflows/_publish-registry.yml:61-62, and
.github/workflows/_rust-binary.yml:68-69, 137-138, and 241-242. Preserve
existing checkout refs and behavior; no later Git operation requires the
persisted token.
Source: Linters/SAST tools
The problem
actions/checkoutwith norefresolves the ref that started the run. On apush: tags:trigger that is the tag itself, so the release path was correct by accident. On aworkflow_dispatchit is the branch the dispatch was started from — andalpha-release.yml:225dispatches withgh workflow run release.yml --ref main -f tag="$TAG", so that branch is always main.The tag reaches the jobs only as metadata:
parse_release_tag.pyreads the version out of its name, andtag_namegoes tocreate-release. Nothing there decides what gets compiled.The result is a release that compiles one commit and labels the artifacts with another commit's version, with no signal that it happened.
How it surfaced
state/v0.21.4-alpha.2shipped this way:feat/new-sdk-migrationand created the tag. It points atbd119851, whosestate/Cargo.tomlhasversion = "0.21.4-alpha.2"andiii-sdk = "=0.22.0-alpha.3".workflow_dispatchfrom main (d5bfaf1f), which pinsiii-sdk = "=0.21.6".The published binary (
sha256 ec31dd33…) embedsiii-sdk-0.21.6andiii-helpers-0.21.6, and contains no occurrence of0.22.0. Captured on the wire against a live engine, itsengine::workers::registercall carries nonamespacefield, while a control worker built from the new SDK does. The artifact carries the prerelease version number and none of the code that number names, so no worker published through this path can join a namespaced project.The change
Every
actions/checkoutin the release path now takes the ref being released:release.ymluses${{ inputs.tag || github.ref }}in its own two jobs and passes the same value down to the four reusable workflows._rust-binary.yml,_bundle.yml,_container.ymland_publish-registry.ymlgain an optionalrefinput defaulting to''— which isactions/checkout's own default. Nothing changes for a tag push.Nine checkouts in total.
release.ymlis the only caller of all four reusable workflows, so the change is self-contained.The dispatch keeps using
--ref mainon purpose: the pipeline definition should come from main, and only the source it compiles should follow the tag. Those two were conflated; this separates them.Verification
All five files still parse, and a structural check over the parsed YAML confirms no checkout in the release path was left without a
ref.Suggested follow-up (not in this PR)
Nothing today compares the tag's version against the version declared in the worker's manifest — which is why the mismatch stayed silent.
_lib.read_version()already readsCargo.tomlandpackage.jsonuniformly; comparing the two inparse_release_tag.py(skipping dry runs, whose tags carry their own suffix) would turn a wrong build into a job that fails loudly. Left out to keep this PR to the fix itself, but worth having as a net.