Skip to content

docs: align release guides with shipped settlement flow - #58

Open
Troublor wants to merge 1 commit into
mainfrom
docs/release-pipeline-refresh
Open

Troublor wants to merge 1 commit into
mainfrom
docs/release-pipeline-refresh

Conversation

@Troublor

@Troublor Troublor commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Audits the release documentation against the pipeline that ships on main
(e285f0d4) and corrects every statement that no longer matches the shipped
actions, templates and guards. Documentation only: no action, workflow, Python
tool or test changes.

The audit covers docs/RELEASING.md, .github/actions/RELEASE.md, README.md
and all eleven .github/actions/release-*/README.md files plus
app-token-lint/README.md. README.md needed no change. Nothing was guessed:
claims that cannot be settled from this repository are listed under Unverified
below and that prose was left alone.

Main themes:

  • the clean-candidate-merge no-op (clean) and why a push-routed refresh
    legitimately creates no settle PR;
  • the push/action asymmetry: push routing cannot see changelog state, dispatch
    routing assumes it, and only release-publish verifies it;
  • recovery of an interrupted publication created by a settle-PR merge, which a
    versioned dispatch refuses because the tag is not at the candidate merge;
  • the exact three-file Gutenberg allowlist (no release-publish-* prefixes);
  • release-branch CI filters, which the templates do not cover;
  • changelog sources (non-merge commit subjects, not PR titles), template
    defaults (VERSION/plain, not mega-reth's Cargo values), and the
    compat: label being a consumer gate rather than a shared one.

Corrected statements

Before line numbers are from e285f0d4; after line numbers are on this branch.

# Before (file:line, statement) After (file:line) Evidence in code
1 docs/RELEASING.md:18 - Gutenberg mint allowed in release-publish-*.yml docs/RELEASING.md:16-18 - exactly release-candidate.yml, release-settle.yml, on-release.yml .github/scripts/app_token_lint.py:56 (RELEASE_WORKFLOW_FILES), :164-165 (exact filename match)
2 docs/RELEASING.md:247 - L2' message ends ... on-release.yml or release-publish-*.yml docs/RELEASING.md:278 - the message the script prints, plus "filename prefixes do not grant access" .github/scripts/app_token_lint.py:165 (', '.join(sorted(...)))
3 docs/RELEASING.md:248 - L5 message in hand-maintained order docs/RELEASING.md:282 - the message the script actually prints .github/scripts/app_token_lint.py:136
4 docs/RELEASING.md:56 - a push "opens or updates" a settle PR, unconditionally docs/RELEASING.md:54-63 - the clean state writes nothing and creates no PR .github/actions/release-tools/release_tools.py:145-151; .github/actions/release-settle/action.yml:236-240, :249-278 (write steps gated on needs-settle-pr)
5 docs/RELEASING.md:79-83 - a clean dispatch "routes to publish" with no further condition docs/RELEASING.md:86-98 - dispatch routing assumes a matching changelog, publish verifies it, settle_source=dispatch release_tools.py:304-306 (settle_state called without section_matches); .github/actions/release-publish/action.yml:278-308
6 docs/RELEASING.md:203 - "dispatch Release Settle with the version" recovers a half-published tag docs/RELEASING.md:233, :95-97 - only a tag at the candidate merge resumes; a settle-PR merge re-runs its original push release_tools.py:141-144 (tag SHA mismatch blocks before release_exists is considered)
7 docs/RELEASING.md:95 - "the tag push (the Release) fires On Release" docs/RELEASING.md:110-111 - release: published fires it workflow-templates/on-release.yml:41-43
8 docs/RELEASING.md:172 - templates carry mega-reth values (Cargo.toml, toml, cargo update --workspace, private deps) docs/RELEASING.md:186-190 - VERSION/plain, the bump command commented out, copy_templates.py renders real values workflow-templates/release-candidate.yml:77-82; .github/scripts/copy_templates.py:45, :117-119
9 docs/RELEASING.md:178 - every PR "must" carry compat: docs/RELEASING.md:205-211 - a consumer-specific gate, not implemented by the shared actions release-candidate/action.yml:117-121 and release-settle/action.yml:53-58 (pr_labels empty by default; no label check in either action)
10 missing - no guidance on required checks for PRs targeting release-v* docs/RELEASING.md:193-201 and .github/actions/RELEASE.md:354-373 release-candidate/action.yml:60-64 (the carry list defaults to two release workflows); consumer example mega-optimism/.github/workflows/lint.yml:6-7 filters main only
11 docs/RELEASING.md:14 - the reviewer approves the environment only "when a dispatch publishes" docs/RELEASING.md:14 - either publish path workflow-templates/release-settle.yml:114-125 (environment: release on the single publish job)
12 docs/RELEASING.md:12-13 - Maxwell reads private dependencies for a release docs/RELEASING.md:13 - Maxwell mints nothing in a release workflow; dependency reads use a separate read-only Gutenberg token app_token_lint.py:20-22, :160-162 (L3)
13 docs/RELEASING.md:35, .github/actions/RELEASE.md:131, release-candidate/README.md:118 - changelog drafted from merged PR titles same places - non-merge commit subjects release-candidate/action.yml:484-485 (git log --no-merges --format='%H%x09%s')
14 docs/RELEASING.md:250 - a refused base_commit means "choose a commit on the default branch" docs/RELEASING.md:251 - trunk, or the latest release line release-candidate/action.yml:234-252 (on_release_line)
15 docs/RELEASING.md:256 - missing settle marker: "close it and let settle recreate it" docs/RELEASING.md:256 - the PR is already merged on this path; refresh the current tip release-publish/action.yml:219-221
16 missing - no entry for the dispatch changelog refusal docs/RELEASING.md:264 release-publish/action.yml:294-302
17 docs/RELEASING.md:268 - the paraphrased "release branch '…' tip is '…', expected …" docs/RELEASING.md:268 - the two real messages and what each allows release-publish/action.yml:190-205
18 .github/actions/RELEASE.md:31 - four phases, "each a workflow" .github/actions/RELEASE.md:31-34 - three workflows, four phases workflow-templates/ holds release-candidate.yml, release-settle.yml, on-release.yml
19 .github/actions/RELEASE.md:40 - the settle phase always opens a PR .github/actions/RELEASE.md:41 release_tools.py:145-151
20 .github/actions/RELEASE.md:100 - L2' includes release-publish-*.yml .github/actions/RELEASE.md:106-107 - exact filenames app_token_lint.py:56, :164-165
21 .github/actions/RELEASE.md:77 - "from the merged PR titles" .github/actions/RELEASE.md:83-85 release-candidate/action.yml:484-485
22 .github/actions/RELEASE.md:174-180 - a clean dispatch publishes with no changelog caveat .github/actions/RELEASE.md:188-197 release-publish/action.yml:278-302
23 .github/actions/RELEASE.md:490 - "that version is released" whenever the tag exists .github/actions/RELEASE.md:530-532 - distinguish a completed Release from an interrupted one release_tools.py:141-144
24 .github/actions/RELEASE.md:502 - "all targets are idempotent, so the ones that succeeded are no-ops" .github/actions/RELEASE.md:541-545 - Release assets are re-uploaded with --clobber .github/actions/release-assets/action.yml:67
25 release-settle/README.md:78-79 - the example uses workflow inputs inputs.version / inputs.commit that do not exist release-settle/README.md:78-91 - matrix.target.*, plus a note that version is the only dispatch input workflow-templates/release-settle.yml:35-38, :107-109; release_tools.py:291-296
26 release-settle/README.md:95 - state/settled described like action outputs release-settle/README.md:95-112 - internal step outputs; the public outputs stay empty release-settle/action.yml:69-78 (only version, pr_url, notes_file)
27 release-settle/README.md:113 - marker <!-- release-settle: vX.Y.Z <sha> --> release-settle/README.md:125 - <40-hex> release-settle/action.yml:340; release_tools.py:228
28 release-route/README.md:86-87 - ancestry "without a candidate" is an empty string release-route/README.md:86-90 - that dispatch fails with missing settlement facts release_tools.py:292-302; release-route/action.yml:172-183
29 release-route/README.md:92-95 - any published version routes to skip release-route/README.md:92-112 - the tag must be at the candidate merge; dispatch checks neither changelog nor version order release_tools.py:141-144, :304-306; release-publish/action.yml:104-113
30 release-route/README.md - no statement of the dispatch input contract release-route/README.md:109-112 workflow-templates/release-settle.yml:35-38
31 release-publish/README.md:134 - "This workflow must exist on the release branch" release-publish/README.md:141-144 - it is a composite action; its caller is release-settle.yml workflow-templates/release-settle.yml:114-151
32 release-publish/README.md - no dispatch changelog caveat release-publish/README.md:110-116 release-publish/action.yml:278-302
33 release-candidate/README.md:106-110 - the example sets bump_command without dependency_token release-candidate/README.md:111 release-candidate/action.yml:40-46 (hard error without it)
34 release-tools/README.md:9-22 - the table omits latest-tag, check-order, settle-state and route; changelog-extract lacks --include-heading release-tools/README.md:13-21, :29-36 release_tools.py:505-554

Unverified (reported, not changed)

  • Organisation-level placement of MEGA_GUTENBERG_CLIENT_ID/MEGA_GUTENBERG_PK,
    repository access grants, environment reviewers and ruleset bypass actors are
    external configuration. The names in the docs match every reference in this
    repository (workflow-templates/*.yml, app_token_lint.py:9), but the live
    settings cannot be checked from here.
  • GCP_AUTH_KEY is consistent across the templates. Whether consumers keep it
    at environment or repository scope is external.

Code concerns found (no code changed)

  • Versioned dispatch never passes a changelog comparison to settle_state
    (release_tools.py:304-306), so a stale section routes publish and then
    fails inside release-publish (action.yml:294-302) instead of routing
    refresh. The docs now describe this; routing refresh directly would be
    friendlier.
  • Versioned dispatch blocks any tag not at the candidate merge before it looks
    at release_exists (release_tools.py:141-144), so a fully published
    settle-PR release reports as blocked rather than published, and an interrupted
    settle-PR publication cannot be resumed by dispatch.
  • Versioned dispatch performs no order_refusal check (release_tools.py:289-306);
    only release-publish refuses an older version.
  • Generated metadata in action.yml descriptions and the generated error tables
    are lossy (truncated messages such as ${decision#*$, settle PR body has no).
    They are regenerated by action_docs.py and were left untouched; the
    corrected prose lives outside the generated blocks.

Deliberate remaining grep matches

release-publish.yml remains only where removal or non-installation is the
point: .github/actions/RELEASE.md:247 (a stale copy is deleted) and :345
(nothing to install), .github/actions/release-candidate/README.md:21 and the
generated input description it mirrors (release-candidate/action.yml:64), and
.github/actions/app-token-lint/README.md:75 (a lint negative example).
commit= matches only real action inputs, base_commit= in a dispatch command,
and unrelated actions. publish environment, RELEASE_APP_CLIENT,
RELEASE_APP_PRIVATE_KEY and GCP_S3_AUTH_KEY have zero matches.

Verification

  • Branch diff touches documentation files only.
  • python3 .github/scripts/action_docs.py --check -> documentation up to date.
  • python3 .github/scripts/app_token_lint.py --repo my-repo workflow-templates/ -> 5 file(s) clean.
  • python3 -m unittest discover -s .github/actions/release-tools -p 'test_*.py' -> 84 tests, OK.
  • python3 -m unittest discover -s .github/scripts -p 'test_*.py' -> 86 tests, OK.

Test plan

  • Generated action docs still match action.yml.
  • Template lint clean; release helper and script test suites green.
  • Every changed statement cites the shipped code that proves it (table above).

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