Skip to content

feat(pr-validation): button, real undo example, one live approval - #908

Merged
bedatty merged 1 commit into
developfrom
feat/breaking-change-comment-layout
Oct 15, 2026
Merged

bedatty merged 1 commit into
developfrom
feat/breaking-change-comment-layout

Conversation

@bedatty

@bedatty bedatty commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

Description

Three changes to the breaking-change gate, from reviewing the live comment on #906.

1. The call to action is a button. Markdown has none, so it is a shields.io badge wrapped in the link — compared against an HTML card, a <kbd> and a plain heading on #906, and this one won on looks. It puts a third party in the path of a release control, so the alt text carries the whole call to action: a blocked image leaves a described link, not a broken rectangle. badge-url: '' drops the dependency and falls back to a heading link.

2. The undo example uses this PR's own commits. Instead of a made-up feat(scope)!: subject, it lists the real breaking subjects in a diff block:

- feat(pr-validation)!: smoke test the breaking change approval gate
+ feat(pr-validation): smoke test the breaking change approval gate

Only the ! form is matched there, because that is the form the example illustrates. It is a view, never a verdict — the canonical rule stays in breaking-change-guard, and with nothing matched the wording goes generic.

3. Only one approval request stays open, and approvals expire on a push. This is the one that matters. Every push queued another pending deployment and GitHub retired none of them — #906 had two at once, on f8d5506 and 229bdd0. Approving the stale one approves a revision nobody is merging, while the live one still waits.

A concurrency group keyed to the pull request, with cancel-in-progress, means a push cancels the previous request. That is also what expires an approval: the yes was given to one revision and the next has to earn its own.

The cancelled run still reaches the verdict job, so it now compares the commit it covers against the PR's current head and leaves the pull request alone when they differ. Without that it would overwrite the live revision's comment with "the approval did not complete" — true of the dead run, misleading about the live one.

Type of Change

  • feat: New workflow or new input/output/step in an existing workflow

Breaking Changes

None. badge-url is a new optional input with a default, and no workflow input, output or job name changes.

Testing

  • YAML syntax validated locally
  • Triggered a real workflow run on a caller repository using @this-branch or the beta tag
  • Verified all existing inputs still work with default values
  • Confirmed no secrets or tokens are printed in logs
  • Checked that unrelated workflows are not affected

Layouts were iterated directly on #906 by editing the live comment, which is how the badge was chosen.

The verdict logic was exercised against a stubbed gh for the new state: head unchanged/approved, head changed → superseded, head changed and approval cancelled → superseded (the case that would corrupt the live comment), head unchanged with approval cancelled → unresolved, rejection, and nothing-to-approve.

actionlint, composite-schema, typos clean. 71 wiring tests, 5 new: the concurrency group, that a superseded run drives neither the comment nor the close, the badge fallback, and that the undo example comes from the real commits.

Caller repo / workflow run: #906 carries the gate; the two stale pending deployments there are what motivated change 3.

Related Issues

Three things, from reviewing the comment on #906 in place.

The call to action is now a shields.io badge wrapped in the link, which
is the only thing in Markdown that reads as a button. That puts a third
party in the path of a release control, so the alt text carries the
whole call to action: a blocked image leaves a described link, not a
broken rectangle. Setting badge-url to empty drops the dependency and
falls back to a heading link.

The "not intentional?" example now shows this pull request's own commit
subjects in a diff block instead of a made-up feat(scope)!: subject. It
matches only the `!` form, because that is the form the example
illustrates — a view, never a verdict. The canonical rule stays in the
detector, and with nothing matched the wording goes generic.

And only one approval request stays open. Every push queued another
pending deployment while the old ones kept sitting in the reviewers'
queue, each tied to a commit that is no longer the head — #906 had two
at once. Approving one of those approves a revision nobody is merging.
A concurrency group keyed to the pull request cancels the previous
request, which is also what expires an approval: the yes was given to a
specific revision and the next one has to earn its own.

The cancelled run still reaches the verdict, so it now checks whether it
still covers the head and leaves the pull request alone when it does
not. Otherwise it would overwrite the live comment with "the approval
did not complete".
@bedatty
bedatty requested a review from a team as a code owner October 15, 2026 21:48
@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: Repository: LerianStudio/github-actions-shared-workflows/.coderabbit.yml
  • Review profile: ASSERTIVE
  • Plan: Essentials
  • Run ID: 6034e9b7-9a2d-4e85-bfa8-564699f9e3d4
📥 Commits

Reviewing files that changed from the base of the PR and between f94dba7 and 1b21fb3.

📒 Files selected for processing: 5
  • .github/workflows/breaking-change-approval.yml
  • docs/breaking-change-approval.md
  • src/notify/breaking-change-approval-reporter/README.md
  • src/notify/breaking-change-approval-reporter/action.yml
  • src/validate/breaking-change-guard/test-workflow.py
+----------------------------------------------------------------------------------------------------------------------+
| You can't write perfect software. Software can't be perfect. Protect your code and users from the inevitable errors. |
+----------------------------------------------------------------------------------------------------------------------+
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@lerian-studio lerian-studio added size/M PR changes 200–499 lines documentation Improvements or additions to documentation workflow Changes to one or more reusable workflow files notify Changes to notification composite actions (src/notify/) validate Changes to PR validation composite actions (src/validate/) composite Changes to any composite action manifest (src/**/*.yml) labels Oct 15, 2026
@lerian-studio

Copy link
Copy Markdown
Contributor

🔍 PR Validation Summary

✅ PR Mergeable — no blocking failures

Check Status Blocking
Source Branch ✅ success yes
PR Title ✅ success yes
PR Description ✅ success yes
Breaking Change Guard ✅ success yes
Commit Signatures ✅ success yes
PR Size ✅ success no
Auto Labels ✅ success no
PR Metadata ✅ success no

🔍 View workflow run

@lerian-studio

Copy link
Copy Markdown
Contributor

🔍 Lint Analysis

Check Files Scanned Status
YAML Lint 2 file(s) ✅ success
Action Lint 1 file(s) ✅ success
Pinned Actions 2 file(s) ✅ success
Markdown Link Check 2 file(s) ✅ success
Spelling Check 5 file(s) ✅ success
Shell Check 2 file(s) ✅ success
README Check 2 file(s) ✅ success
Composite Schema 1 file(s) ✅ success
Deployment Matrix no changes ⏭️ skipped

🔍 View full scan logs

@lerian-studio

Copy link
Copy Markdown
Contributor

🛡️ CodeQL Analysis Results

Languages analyzed: actions

Found 1 issue(s): 1 Medium

Severity Rule File Message
🟡 Medium actions/untrusted-checkout/medium .github/workflows/breaking-change-approval.yml:260 Potential unsafe checkout of untrusted pull request on non-privileged workflow.

🔍 View full scan logs | 🛡️ Security tab

@lerian-studio

Copy link
Copy Markdown
Contributor

@coderabbitai review

@lerian-studio lerian-studio added the review-ready Required checks passed — CodeRabbit is cleared to review label Oct 15, 2026
@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Pull request is closed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@bedatty
bedatty merged commit ff9f977 into develop Oct 15, 2026
42 of 43 checks passed
@github-actions
github-actions Bot deleted the feat/breaking-change-comment-layout branch October 15, 2026 21:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

composite Changes to any composite action manifest (src/**/*.yml) documentation Improvements or additions to documentation notify Changes to notification composite actions (src/notify/) review-ready Required checks passed — CodeRabbit is cleared to review size/M PR changes 200–499 lines validate Changes to PR validation composite actions (src/validate/) workflow Changes to one or more reusable workflow files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants