Skip to content

fix(ci): pass the release tag through env so actionlint can lint release.yml - #88

Merged
savvides merged 1 commit into
mainfrom
fix/release-workflow-actionlint
Aug 30, 2026
Merged

fix(ci): pass the release tag through env so actionlint can lint release.yml#88
savvides merged 1 commit into
mainfrom
fix/release-workflow-actionlint

Conversation

@savvides

Copy link
Copy Markdown
Owner

Follow-up to #87, which enabled VALIDATE_GITHUB_ACTIONS. That left a latent trap: release.yml fails actionlint today, so the next PR to touch it would be blocked.

Mechanism

actionlint runs shellcheck over run: blocks. Before doing so it substitutes each ${{ ... }} expression with an equal-length underscore placeholder. ${{ github.ref_name }} is 22 characters, so shellcheck saw:

if [ "v$VER" != "______________________" ]; then

The left side is v followed by a variable; the right side is a literal that cannot begin with v. shellcheck concludes the comparison can never be true:

SC2193: The arguments to this comparison can never be equal.

Reproduced locally against the real file — placeholder length 22 confirmed, shellcheck exits 1. With the fix applied to the same script, shellcheck exits 0.

Fix

Bind the expression to an env: var and reference it as a normal shell variable. shellcheck can no longer prove the operands unequal, so SC2193 goes away.

This is also GitHub's recommended pattern for getting context values into run: blocks — interpolating ${{ }} directly into a shell script is the script-injection shape. github.ref_name is tag-constrained here so this was not exploitable, but the safe form costs two lines.

Behaviour is unchanged: same comparison, same error message, same exit code.

Since this PR modifies release.yml, actionlint lints it under VALIDATE_ALL_CODEBASE: false — so a green run-lint on this PR is the verification.

🤖 Generated with Claude Code

…ase.yml

#87 turned on VALIDATE_GITHUB_ACTIONS, which runs actionlint over every
workflow. release.yml does not currently pass it.

actionlint feeds `run:` blocks to shellcheck, substituting each `${{ }}`
expression with an underscore placeholder of equal length first. At 22
characters, `${{ github.ref_name }}` became:

  if [ "v$VER" != "______________________" ]; then

The left operand starts with a literal `v` and the right operand cannot,
so shellcheck reports SC2193 — "the arguments to this comparison can
never be equal" — and actionlint exits 1.

Binding the expression to an env var and comparing against `$TAG_NAME`
removes the placeholder from the compared text, so the check passes.
Verified locally: the placeholder form exits 1 on SC2193, the env form
exits 0.

This is also the pattern GitHub recommends for reaching context values
from a run block, since interpolating `${{ }}` straight into a shell
script is the script-injection shape. Not exploitable here — the trigger
is restricted to `v*` tags — but the safe form is two lines.

No behaviour change: same comparison, message, and exit code.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@savvides
savvides merged commit f3606a1 into main Aug 30, 2026
12 checks passed
@savvides
savvides deleted the fix/release-workflow-actionlint branch August 30, 2026 14:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant