Skip to content

fix(ci): gate the release notes backfill behind reviewer approval - #37142

Open
sfreudenthaler wants to merge 1 commit into
37136-manual-changelog-publishfrom
37139-gate-notes-backfill
Open

fix(ci): gate the release notes backfill behind reviewer approval#37142
sfreudenthaler wants to merge 1 commit into
37136-manual-changelog-publishfrom
37139-gate-notes-backfill

Conversation

@sfreudenthaler

@sfreudenthaler sfreudenthaler commented Aug 20, 2026

Copy link
Copy Markdown
Member

Closes: #37139

Top of stack #37143. Based on #37141.

Problem

cicd_ai-release-notes-backfill.yml ends in an unconditional replace on a public release body:

gh release edit "$RELEASE_TAG" --notes-file /tmp/release-notes.md

It overwrites hand edits and cannot be undone from the workflow.

workflow_dispatch is limited to accounts with write access — never forks, never anonymous users — but that is 45 accounts on this repo. Since this workflow shipped in March 2026 it has been an unreviewed write path to public release documentation, for any release tag, by any of those accounts.

Fix

A no-op approval gate on the release-notes-backfill environment (required_reviewers: dotDevelopers), with the generate job needs: gate. Same pattern as cicd_evergreen-tracks-promote.yml's apply gate and the changelog-site-publish gate in #37141.

The environment has been created with that rule. If it is ever removed, GitHub auto-creates a missing environment unprotected on first use, silently removing the gate — it fails open, not closed. The workflow comment says so at the gate.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EbgDBJuoBrpJxh5qLMPorL

@claude

claude Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Claude finished @sfreudenthaler's task in 57s —— View job


Review: gate release notes backfill behind reviewer approval

  • Read the diff against origin/37136-manual-changelog-publish
  • Compare against the referenced cicd_evergreen-tracks-promote.yml gate pattern
  • Check gate wiring, injection, and failure semantics

The gate wiring is correct. release-notes has needs: gate, and since this workflow is workflow_dispatch-only there's no scheduled/skip path — so an unconditional needs: gate (no if) is right: gate must succeed for generation to run. This matches the evergreen apply pattern, minus the skipped allowance it doesn't need. The comment documenting the fail-open auto-create behavior is a good call-out.

New Issues

  • 🟡 Medium: .github/workflows/cicd_ai-release-notes-backfill.yml:45-47 — the gate run: block interpolates ${{ inputs.release_tag }} and ${{ inputs.previous_tag }} directly into the shell script. This is the GitHub Actions script-injection pattern: a release_tag value like $(curl …) or "; …; echo " executes on the runner. The blast radius is narrower than usual — dispatch is write-access-only and this step runs after a reviewer approves the environment — but that's precisely the point of the gate: a reviewer approving "rewrite notes for tag X" is not approving arbitrary code execution, so this quietly widens what approval authorizes. Prefer passing inputs through env: and referencing shell vars:

        steps:
          - env:
              RELEASE_TAG: ${{ inputs.release_tag }}
              PREVIOUS_TAG: ${{ inputs.previous_tag }}
            run: |
              echo "Approved: rewrite release notes for $RELEASE_TAG"
              echo "Previous tag: ${PREVIOUS_TAG:-(auto-detect)}"

    Fix this →

    Note: this is a hardening nit on a no-op echo, not a blocker. Confirm whether the downstream cicd_comp_ai-release-notes-phase.yml already applies the same indirection where release_tag reaches gh release edit.

Nothing else in the diff is problematic — the gate does what the PR describes.
· 37139-gate-notes-backfill

The phase's final step is `gh release edit --notes-file`, an unconditional
replace on a public release body -- it overwrites hand edits and cannot be
undone from the workflow. workflow_dispatch is open to every account with
write access on this repo (45 today), so this has been an unreviewed write
path to public release documentation since March.

Adds a no-op approval gate on the release-notes-backfill environment
(required_reviewers: dotDevelopers), matching the changelog-site-publish
gate and cicd_evergreen-tracks-promote.yml's apply gate.

Closes: #37139

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EbgDBJuoBrpJxh5qLMPorL
@sfreudenthaler

Copy link
Copy Markdown
Member Author

No code changes needed here — the review found no issues, and its one note was a verification request rather than a defect.

Confirming it: the release-notes-backfill environment exists with the protection rule, created before this PR was opened and re-verified just now via gh api /repos/dotCMS/core/environments/release-notes-backfill:

required_reviewers -> dotDevelopers

So the gate is real, not pending setup.

Two points from the review worth keeping on the record:

  • The fail-open behavior is correctly identified and is not fixable in-repo. If the environment is deleted, GitHub recreates it unprotected on first use and the gate silently passes. The comment at the gate says so; there is no workflow-level assertion that can catch it.
  • The pre-existing cancel-in-progress: true means a run parked on approval can be cancelled by a newer dispatch for the same tag. Unchanged by this PR and harmless here — a cancelled backfill writes nothing — so leaving it as-is rather than widening scope.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area : CI/CD PR changes GitHub Actions/workflows

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Release notes backfill can rewrite any public release body with no review

1 participant