ci: pass workflow inputs to run steps via env vars - #8860
Merged
gustavodiaz7722 merged 1 commit intoSep 11, 2026
Conversation
`${{ }}` expressions are substituted into a `run:` block as raw text
before bash parses it, so any interpolated value has to survive shell
parsing rather than just being used as data. Two steps relied on that.
release-drafter.yaml, "Copy release notes from Draft": the drafter body
is a rendered list of merged PR titles, so characters that are
meaningful to bash (`"`, `$`, `(`, `)`, `;`) end up in the script
itself. `change-title-escapes` in .github/release-drafter.yml escapes
`\<*_&#@` and a backtick, which does not cover those. Move `tag_name`
and `body` into `env:` and reference them as `"$TAG_NAME"` /
`"$RELEASE_BODY"`, and use `printf '%s\n'` so backslashes in the notes
are written verbatim. `${TAG_NAME#v}` replaces `${tag_name:1}` — same
result for a `vX.Y.Z` tag, but it strips the prefix by name instead of
by offset.
Also set `persist-credentials: false` on the checkout in that job. The
following "Upsert pull request" step authenticates with its own `token:`
input (create-pull-request configures the git extraheader itself, and
unsets any persisted one), so nothing in the job needs the credential
that checkout otherwise leaves in the git config.
homebrew-update.yml: the request body was a single-quoted JSON literal
with `${{ }}` values pasted in, which breaks if a value contains a quote
or backslash and would emit malformed JSON. Build it with `jq -n --arg`
from `env:` values instead, which handles the escaping, and pipe it to
curl via `-d @-`. Added `-sSf` so an API error fails the step instead of
passing silently. The token also moves to `env:` so it is not part of
the script text.
No behaviour change for well-formed inputs; verified the rendered
filename, note contents, and JSON payload are byte-identical for a
normal `v0.220.0` release.
gustavodiaz7722
approved these changes
Sep 11, 2026
5 tasks
Merged
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
${{ }}expressions are substituted into arun:block as raw text before bash parses it, so an interpolated value has to survive shell parsing rather than simply being used as data. Two workflow steps relied on that. This passes the values throughenv:and references them as quoted variables instead.release-drafter.yaml— "Copy release notes from Draft"steps.draft.outputs.bodyis a rendered list of merged PR titles (change-template: '- $TITLE (#$NUMBER)'), so characters that are meaningful to bash —",$,(,),;— land in the script itself.change-title-escapesin.github/release-drafter.ymlis set to'\<*_&#@`', which does not cover them, so a title containing a double quote produces a broken script and a garbled or missing release-notes file.Now:
printf '%s\n'rather thanecho, so backslash sequences in the notes are written verbatim.${TAG_NAME#v}replaces${tag_name:1}— same result for avX.Y.Ztag, but it strips the prefix by name rather than by offset.Also set
persist-credentials: falseon this job's checkout. The following Upsert pull request step authenticates with its owntoken:input —create-pull-requestconfigures the gitextraheaderitself and unsets any persisted one — so nothing in the job needs the credential checkout otherwise leaves behind in the git config.homebrew-update.yml— "Create update issue"The request body was a single-quoted JSON literal with
${{ }}values pasted in, which emits malformed JSON if any value contains a quote or backslash. It is now built withjq -n --argfromenv:values, which handles the escaping, and piped to curl with-d @-. Added-sSfso a failed API call fails the step instead of passing silently, and moved the token intoenv:so it is not part of the script text.Checklist
area/nodegroup) and target version (e.g.version/0.12.0)Testing
Ran both rewritten
run:bodies locally with representative env values.release-drafter.yaml— a body containing- evil"; whoami; echo " (#124)plus\n,$VARand backticks writes todocs/release_notes/0.220.0.mdwith every character intact and no expansion:Under the previous version the same body produced a truncated file. For an ordinary body the output is byte-identical.
homebrew-update.yml—jqoutput forTAG_NAME=v0.220.0matches the previous payload exactly:{ "title": "Update eksctl to v0.220.0", "body": "New eksctl release v0.220.0 is available.\n\nRelease URL: https://github.com/eksctl-io/eksctl/releases/tag/v0.220.0", "labels": ["eksctl-update"] }Both files parse as valid YAML.