Skip to content

fix(release): pass release notes by file, cap them under GitHub's body limit - #374

Merged
jdfalk merged 5 commits into
mainfrom
fix/release-notes-body-path
Oct 16, 2026
Merged

jdfalk merged 5 commits into
mainfrom
fix/release-notes-body-path

Conversation

@jdfalk

@jdfalk jdfalk commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

Problem

The audiobook-organizer stable release v0.222.2 (run 38901709831) failed in Create GitHub Release with:

An error occurred trying to start process '.../node24/bin/node' ... Argument list too long

The release notes were about 125 KB (every commit since v0.222.0). body: reaches the action as an INPUT_BODY env var, and Linux caps any single env/argv string at 128 KiB (MAX_ARG_STRLEN). The release itself was published, but the step failed, so everything after it was skipped:

  • changelog fragment collection (428 fragments left un-collected)
  • superseded-draft cleanup
  • the GitHub Packages publish

The RC draft step has the same issue: it passes the notes through CHANGELOG env and then gh api -f body= / gh release create --notes, both of which are argv.

GitHub also rejects any release body over 125,000 characters, so a file alone isn't enough.

Fix

  • release_workflow.py generate-changelog writes the notes to $RUNNER_TEMP/release-notes/changelog.md and emits the path as the changelog_file output; the old changelog_content output is removed, since its only consumers were the two steps below. The commit list is capped at 110,000 characters, newest first, and ends with … and N older commit(s) not listed. The cap reserves the exact length of that last line.
  • New Compose release notes step: notes file plus the assets footer, written to body.md. The release step then uses body_path:.
  • The RC draft step builds draft-body.md and uses -F body=@file / --notes-file.

Tests

  • tests/workflow_scripts/: 66 passed.
  • New tests cover the cap (newest kept, oldest dropped, the omitted count, staying within budget) and a 6,000-commit multibyte history that stays under 120,000 characters.
  • actionlint is clean on reusable-release.yml.
  • The pre-commit hooks reformatted release_workflow.py (ruff format/isort), so the diff includes some untouched lines.

🤖 Generated with Claude Code

https://claude.ai/code/session_012mtQZQ26prebPvRBbC5wdL

…y limit

A ~125 KB changelog passed through 'body:' (an INPUT_* env var) exceeded
Linux's 128 KiB per-string limit, so 'Create GitHub Release' failed with
'Argument list too long' after publishing, and changelog collection, draft
cleanup and the packages publish were skipped. generate-changelog now writes
a capped notes file; the release step uses body_path and the RC draft step
uses -F body=@file / --notes-file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012mtQZQ26prebPvRBbC5wdL
@github-actions github-actions Bot added size/L github-actions GitHub Actions related work type:documentation Improvements or additions to documentation type:testing Testing related work module:config Configuration management tech:python Python programming language workflow:github-actions GitHub Actions workflows labels Oct 16, 2026
jdfalk and others added 4 commits October 16, 2026 09:56
… whole (#374 review)

The scripts are checked out at the caller's ghcommon-ref, separately from the
workflow, so a new workflow can run an old script (no changelog_file) and the
reverse. Both new steps now fail with an error naming the ref to bump, and the
script still emits changelog_content so an older workflow keeps its notes.
_cap_commit_lines returns a list that fits whole unchanged, and the omitted
line no longer calls the newest commit 'older'. Version headers on the script
and its test; usage map lists the new output.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012mtQZQ26prebPvRBbC5wdL
…ref (#374 re-review)

Callers without .github/ghcommon-ref.txt get scripts at the fallback SHA,
which predates changelog_file, so the guard would have stopped every one of
their releases. A separate step now writes changelog_content to a file only
when changelog_file is absent (so current runs never put the notes in env),
and the error fires only when neither exists. changelog_content uses
write_output's uuid delimiter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012mtQZQ26prebPvRBbC5wdL
…ip; fragment notes the legacy env limit (#374 round 3)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012mtQZQ26prebPvRBbC5wdL
…ngs and unpacking in release_workflow.py

ruff.toml's per-file ignores for workflow CLIs (stdout is the interface, git/gh
by name, status emoji, semver counts) covered .github/scripts but not
.github/workflows/scripts, where the reusable workflows' GHCOMMON_SCRIPTS_DIR
points, so the changed-file Python lint on #374 failed on release_workflow.py's
existing prints and subprocess calls. Same list, second path. The two findings
it does not cover are fixed in code: public-function docstrings and RUF005.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012mtQZQ26prebPvRBbC5wdL
@jdfalk
jdfalk merged commit 1f0d70e into main Oct 16, 2026
42 checks passed
jdfalk added a commit that referenced this pull request Oct 16, 2026
… whole (#374 review)

The scripts are checked out at the caller's ghcommon-ref, separately from the
workflow, so a new workflow can run an old script (no changelog_file) and the
reverse. Both new steps now fail with an error naming the ref to bump, and the
script still emits changelog_content so an older workflow keeps its notes.
_cap_commit_lines returns a list that fits whole unchanged, and the omitted
line no longer calls the newest commit 'older'. Version headers on the script
and its test; usage map lists the new output.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012mtQZQ26prebPvRBbC5wdL
jdfalk added a commit that referenced this pull request Oct 16, 2026
…ref (#374 re-review)

Callers without .github/ghcommon-ref.txt get scripts at the fallback SHA,
which predates changelog_file, so the guard would have stopped every one of
their releases. A separate step now writes changelog_content to a file only
when changelog_file is absent (so current runs never put the notes in env),
and the error fires only when neither exists. changelog_content uses
write_output's uuid delimiter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012mtQZQ26prebPvRBbC5wdL
@jdfalk
jdfalk deleted the fix/release-notes-body-path branch October 16, 2026 14:16
jdfalk added a commit that referenced this pull request Oct 16, 2026
…ip; fragment notes the legacy env limit (#374 round 3)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012mtQZQ26prebPvRBbC5wdL
jdfalk added a commit that referenced this pull request Oct 16, 2026
…mon#374)

Callers without .github/ghcommon-ref.txt ran e73b801's scripts, which predate
changelog_file, so reusable-release.yml took the legacy inline-changelog path
(uncapped, through env). 12 occurrences across 6 workflows; the only script
change between the two SHAs is #374's release_workflow.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012mtQZQ26prebPvRBbC5wdL
jdfalk added a commit that referenced this pull request Oct 20, 2026
…refix, docs)

- reusable-ci: ruff-version input sits next to python-version; description
  says "bare version, e.g. 0.17.0", points at RUFF_VERSION instead of
  duplicating the number, and states that it takes effect once the script ref
  includes this change; TODO comment on the separate ruff==0.16.10 job
- ci_workflow.py: strip a leading v from the RUFF_VERSION override; the
  override test is parametrized over bare, v-prefixed and padded values and
  has a docstring
- headers: last-edited on ci-tests.yml, version bumps on touched files
- changelog: rollout section (script ref follows in a separate PR, as in
  #374), known consumers and their effect, the ruff-version escape hatch

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QfaLiLJxzi62hjzmR7uAZH
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

github-actions GitHub Actions related work module:config Configuration management size/L size/XL tech:python Python programming language type:documentation Improvements or additions to documentation type:testing Testing related work workflow:github-actions GitHub Actions workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant