Skip to content

fix(ci): build the tag being released, not the dispatch branch - #669

Merged
guibeira merged 1 commit into
mainfrom
fix/release-builds-dispatched-tag
Aug 2, 2026
Merged

fix(ci): build the tag being released, not the dispatch branch#669
guibeira merged 1 commit into
mainfrom
fix/release-builds-dispatched-tag

Conversation

@guibeira

@guibeira guibeira commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator

The problem

actions/checkout with no ref resolves the ref that started the run. On a push: tags: trigger that is the tag itself, so the release path was correct by accident. On a workflow_dispatch it is the branch the dispatch was started from — and alpha-release.yml:225 dispatches with gh 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.py reads the version out of its name, and tag_name goes to create-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.2 shipped this way:

  • Alpha Release ran on feat/new-sdk-migration and created the tag. It points at bd119851, whose state/Cargo.toml has version = "0.21.4-alpha.2" and iii-sdk = "=0.22.0-alpha.3".
  • Release — the run that compiles and uploads the assets — was a workflow_dispatch from main (d5bfaf1f), which pins iii-sdk = "=0.21.6".

The published binary (sha256 ec31dd33…) embeds iii-sdk-0.21.6 and iii-helpers-0.21.6, and contains no occurrence of 0.22.0. Captured on the wire against a live engine, its engine::workers::register call carries no namespace field, 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/checkout in the release path now takes the ref being released:

  • release.yml uses ${{ 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.yml and _publish-registry.yml gain an optional ref input defaulting to '' — which is actions/checkout's own default. Nothing changes for a tag push.

Nine checkouts in total. release.yml is the only caller of all four reusable workflows, so the change is self-contained.

The dispatch keeps using --ref main on 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 reads Cargo.toml and package.json uniformly; comparing the two in parse_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.

@vercel

vercel Bot commented Aug 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
workers Ready Ready Preview Aug 2, 2026 6:11pm
workers-tech-spec Ready Ready Preview Aug 2, 2026 6:11pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The release workflow now selects ${{ inputs.tag || github.ref }} and passes it to reusable workflows. Bundle, container, registry, and Rust binary workflows accept ref and use it for checkout operations.

Changes

Release reference propagation

Layer / File(s) Summary
Reusable workflow ref inputs and checkouts
.github/workflows/_bundle.yml, .github/workflows/_container.yml, .github/workflows/_publish-registry.yml, .github/workflows/_rust-binary.yml
Reusable workflows accept an optional ref input and use it in their checkout steps.
Release workflow wiring
.github/workflows/release.yml
Setup, release creation, and reusable workflow calls use `${{ inputs.tag

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
Loading

Possibly related PRs

  • iii-hq/workers#667: Updates release CI workflows to build from the intended tag or Git reference.

Suggested labels: no-ticket

Suggested reviewers: ytallo, sergiofilhowz, andersonleal

Poem

A rabbit checked the release trail,
With ref tucked in a leafy pail.
Tags now guide each build along,
Every checkout finds its song.
Hop, hop—workflow paths align!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary CI change: building the released tag instead of the dispatch branch.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/release-builds-dispatched-tag

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

skill-check — worker

0 verified, 51 skipped (no docs/).

Layer Result
structure
vale
ai
render

Four for four. Nicely done.

@guibeira
guibeira force-pushed the fix/release-builds-dispatched-tag branch from 87f033c to b8c5137 Compare August 2, 2026 18:08
@guibeira guibeira changed the title fix(ci): build the tag being released, not the dispatch branch fix(ci): compilar a tag que está sendo publicada, não a branch do dispatch Aug 2, 2026
`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.
@guibeira guibeira changed the title fix(ci): compilar a tag que está sendo publicada, não a branch do dispatch fix(ci): build the tag being released, not the dispatch branch Aug 2, 2026
@guibeira
guibeira force-pushed the fix/release-builds-dispatched-tag branch from b8c5137 to 4691419 Compare August 2, 2026 18:10

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between d5bfaf1 and 87f033c.

📒 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

Comment on lines +51 to +52
with:
ref: ${{ inputs.ref }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 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:


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

Comment on lines +190 to +191
with:
ref: ${{ inputs.tag || github.ref }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 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}')
PY

Repository: 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}')
PY

Repository: 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)
PY

Repository: 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 || true

Repository: 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:


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-L62 and #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

@guibeira guibeira added the no-ticket PR deliberately has no Linear ticket (bump/typo/CI-only) label Aug 2, 2026
@guibeira
guibeira merged commit 4b52a11 into main Aug 2, 2026
17 of 20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-ticket PR deliberately has no Linear ticket (bump/typo/CI-only)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant