Skip to content

[codex] harden main branch governance checks#817

Merged
ashleyshaw merged 9 commits into
developfrom
codex/branch-governance-hardening
Jun 3, 2026
Merged

[codex] harden main branch governance checks#817
ashleyshaw merged 9 commits into
developfrom
codex/branch-governance-hardening

Conversation

@ashleyshaw
Copy link
Copy Markdown
Member

@ashleyshaw ashleyshaw commented Jun 3, 2026

Linked issues

Changelog

Added

  • Hardened the main branch guard so it validates actual release/vX.Y.Z and hotfix/<slug> branch shapes.
  • Moved the guard to the workflow context so it cannot be bypassed by PR code.
  • Wired validate:issue-fields and validate:retired-doc-links into CI.

Changed

  • Updated issue template enforcement so invalid issues are commented on and failed without being mislabelled as not_planned.
  • Cleaned up the issue-fields metadata drift and the unused homepage import.

Fixed

  • Tightened the release gate to require a real release/hotfix branch shape and the matching PR template structure.
  • Bumped frontmatter versions on the changed docs so freshness validation passes.

Removed

  • Unused homepage import in website/src/pages/index.astro.

Checklist (Global DoD / PR)

  • All AC met and demonstrated
  • Tests added/updated (unit/E2E as appropriate)
  • Docs/readme/changelog updated (if user-facing)
  • Frontmatter updated where applicable (last_updated and version)
  • Code/design reviews approved
  • CI green; linked issues closed; release notes prepared (if shipping)

What changed

  • Hardened the main branch guard so it validates actual release/vX.Y.Z and hotfix/<slug> branch shapes.
  • Moved the guard to the workflow context so it cannot be bypassed by PR code.
  • Added release/hotfix PR body checks and release title validation.
  • Wired validate:issue-fields and validate:retired-doc-links into CI.
  • Fixed issue template enforcement so invalid issues are commented on and failed without being mislabelled as not_planned.
  • Cleaned the issue-fields metadata drift and the unused homepage import.

Why

The previous protection only checked the branch prefix. That left the release gate weaker than the branch policy described in the repo and allowed the main-branch protection to depend on a single lightweight check. This patch closes that gap and extends CI coverage for docs/config drift.

Validation

  • npm run test
  • npm run validate:retired-doc-links
  • npm run validate:issue-fields
  • npm run validate:workflows
  • npx jest --config .jest.config.cjs scripts/workflows/__tests__/validate-main-branch-pr.test.js --runInBand

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

Warning

Review limit reached

@ashleyshaw, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 35 minutes and 2 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 41d003ae-67da-41b0-9463-a4e73d7d6fff

📥 Commits

Reviewing files that changed from the base of the PR and between 88ba9e6 and c1d3ae4.

⛔ Files ignored due to path filters (1)
  • website/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (12)
  • .github/workflows/checks.yml
  • .github/workflows/main-branch-guard.yml
  • .github/workflows/template-enforcement.yml
  • docs/CANONICAL_CONFIGS_GUIDE.md
  • docs/ISSUE_FIELDS.md
  • scripts/validation/validate-retired-doc-links.cjs
  • scripts/workflows/__tests__/validate-main-branch-pr.test.js
  • scripts/workflows/branch-policy/validate-main-branch-pr.cjs
  • website/package.json
  • website/src/components/Slideshow.svelte
  • website/src/components/SlideshowViewer.svelte
  • website/src/pages/index.astro
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/branch-governance-hardening

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions github-actions Bot added area:ci Build and CI pipelines area:documentation Docs & guides area:tests Test suites & harnesses area:scripts Scripts & tooling lang:js JavaScript/TypeScript lang:md Markdown content/docs status:needs-review Awaiting code review priority:normal Default priority type:chore Chore / small hygiene change labels Jun 3, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request enhances the branch policy validation script (validate-main-branch-pr.cjs) by adding detailed metadata validation for release and hotfix pull requests targeting the main branch, along with comprehensive unit tests and minor documentation and website updates. The feedback highlights opportunities to improve the robustness of the validation script, specifically by properly checking for empty pull request payloads, handling JSON parsing errors from the GitHub event payload, and ensuring the exported metadata validation function independently rejects unsupported branch types.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +93 to +96
if (!pullRequest) {
findings.push("Missing pull request payload.");
return findings;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In main(), pullRequest is initialized as payload.pull_request || {}. This means pullRequest will always be a truthy object (at least {}), so the check if (!pullRequest) inside validatePullRequestMetadata will never be triggered when called from main(). To correctly detect a missing or empty pull request payload, we should check if the object is empty (e.g., using Object.keys(pullRequest).length === 0).

  if (!pullRequest || Object.keys(pullRequest).length === 0) {
    findings.push("Missing pull request payload.");
    return findings;
  }

Comment on lines +102 to +114
if (normalisedBranch.startsWith("release/") && !isReleaseBranch(normalisedBranch)) {
findings.push(
`Release branches must use the form release/vX.Y.Z. Received '${normalisedBranch}'.`,
);
return findings;
}

if (normalisedBranch.startsWith("hotfix/") && !isHotfixBranch(normalisedBranch)) {
findings.push(
`Hotfix branches must use the form hotfix/<slug>. Received '${normalisedBranch}'.`,
);
return findings;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Currently, if validatePullRequestMetadata is called with a branch name that does not start with release/ or hotfix/ (for example, feature/my-feature or main), it skips both prefix checks and returns an empty findings array (indicating the metadata is valid). While main() has a prefix check before calling this function, validatePullRequestMetadata should be self-contained and robust on its own, especially since it is exported and unit-tested. We can combine the checks to ensure any invalid branch targeting main is rejected with an appropriate message.

  if (!isReleaseBranch(normalisedBranch) && !isHotfixBranch(normalisedBranch)) {
    if (normalisedBranch.startsWith("release/")) {
      findings.push(
        "Release branches must use the form release/vX.Y.Z. Received '" + normalisedBranch + "'."
      );
    } else if (normalisedBranch.startsWith("hotfix/")) {
      findings.push(
        "Hotfix branches must use the form hotfix/<slug>. Received '" + normalisedBranch + "'."
      );
    } else {
      findings.push(
        "Only release/* or hotfix/* branches may merge into main. Received '" + normalisedBranch + "'."
      );
    }
    return findings;
  }

Comment on lines +149 to +150
const payload = getEventPayload();
const pullRequest = payload.pull_request || {};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

getEventPayload() catches JSON parsing errors and returns { parseError: error.message }. However, main() does not check for payload.parseError and proceeds to access payload.pull_request, which will be undefined. This results in confusing validation errors (e.g., missing required sections or incorrect title) instead of failing immediately with a clear message about the corrupt event payload.

  const payload = getEventPayload();
  if (payload.parseError) {
    console.error("Failed to parse GitHub event payload: " + payload.parseError);
    process.exit(1);
  }
  const pullRequest = payload.pull_request || {};

@github-actions github-actions Bot added type:bug Bug or defect meta:needs-changelog Requires a changelog entry before merge labels Jun 3, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 3, 2026

✅ Template check passed after update. Thanks for fixing the PR description.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7aebbf795d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 20 to +21
steps:
- uses: actions/checkout@v4
- name: Validate release and hotfix PR shape
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use a protected workflow context for the guard

In the main-branch-guard workflow I checked, this new inline policy still runs under the existing pull_request trigger, which GitHub runs in the PR merge-ref context rather than the base repository's default-branch context. A release/* or hotfix/* PR can therefore change this workflow file in the same PR to remove or weaken the script and still produce a passing validate-release-branch check, so the main-branch gate remains bypassable; move this no-checkout validation to pull_request_target or another protected/default-branch workflow context.

Useful? React with 👍 / 👎.

Comment on lines +94 to +96
const missing = missingSections(pr.body, releaseSections);
if (missing.length > 0) {
fail(`Release PR body is missing required section(s): ${missing.join(', ')}.`);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep generated release PRs compatible with the gate

This new release-body check blocks the repository's existing automated release path: scripts/agents/release.agent.js creates release PRs with the correct chore(release): vX.Y.Z title but only a one-line body, so those PRs will always be missing Linked issues & merged PRs, Changelog, and the checklist and cannot pass the required main-branch guard. Either update both release PR creators to emit the required template sections or relax this gate for automation-generated release PRs.

Useful? React with 👍 / 👎.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 3, 2026

🔍 Reviewer Summary for PR #817

CI Status:success
Files changed: 13
Risk Distribution: 3 critical, 1 high, 4 medium, 5 low

Recommendations

  • ⚠️ 3 critical-risk file(s) modified (workflows, secrets)
  • ⚠️ Security-sensitive files modified (review carefully)

@github-actions github-actions Bot removed the type:chore Chore / small hygiene change label Jun 3, 2026
@ashleyshaw ashleyshaw requested a review from Copilot June 3, 2026 19:46
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens governance enforcement in the repo by strengthening the main branch merge gate for release/hotfix PRs, improving template enforcement behaviour, and expanding CI validation coverage to catch config/docs drift earlier.

Changes:

  • Reworked the main branch guard to validate release/vX.Y.Z and hotfix/<slug> branch shapes plus PR title/body requirements.
  • Updated issue template enforcement to comment + fail without auto-closing/misclassifying issues, and wired additional validation scripts into CI.
  • Cleaned up minor drift/unused code and bumped doc versions to keep freshness validation passing.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
website/src/pages/index.astro Removes an unused import and derived value from the homepage.
scripts/workflows/branch-policy/validate-main-branch-pr.cjs Expands branch guard logic (branch shape + PR metadata checks) and exports helpers for testing.
scripts/workflows/__tests__/validate-main-branch-pr.test.js Adds unit coverage for the new branch-shape and PR-metadata validation logic.
scripts/validation/validate-retired-doc-links.cjs Marks docs/CANONICAL_CONFIGS_GUIDE.md as an “active” doc for retired-link validation.
docs/ISSUE_FIELDS.md Bumps frontmatter/document version and refreshes last_updated.
docs/CANONICAL_CONFIGS_GUIDE.md Bumps version and refines wording around legacy doc references.
.github/workflows/template-enforcement.yml Stops auto-closing invalid issues; instead comments and fails the workflow.
.github/workflows/main-branch-guard.yml Moves the main-branch guard to an in-workflow github-script implementation (no checkout).
.github/workflows/checks.yml Adds validate:issue-fields and validate:retired-doc-links to CI validation.

Comment on lines 18 to +22
name: validate-release-branch
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate release and hotfix PR shape
uses: actions/github-script@v7
Comment thread .github/workflows/main-branch-guard.yml Outdated
Comment on lines +29 to +33
const releasePattern = /^release\/v(?<version>\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)$/;
const hotfixPattern = /^hotfix\/[a-z0-9._-]+$/i;

const releaseSections = [
{ name: 'Linked issues & merged PRs', regex: /^##\s+Linked issues\s*&\s*merged PRs$/im },
Comment thread scripts/workflows/branch-policy/validate-main-branch-pr.cjs Outdated
ashleyshaw and others added 2 commits June 3, 2026 21:49
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Ash Shaw <ashley@lightspeedwp.agency>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Ash Shaw <ashley@lightspeedwp.agency>
@coderabbitai coderabbitai Bot requested a review from krugazul June 3, 2026 19:50
@ashleyshaw ashleyshaw enabled auto-merge (squash) June 3, 2026 19:52
@ashleyshaw ashleyshaw removed the meta:needs-changelog Requires a changelog entry before merge label Jun 3, 2026
@ashleyshaw ashleyshaw added meta:no-changelog No changelog needed type:chore Chore / small hygiene change and removed type:bug Bug or defect labels Jun 3, 2026
@ashleyshaw ashleyshaw removed the request for review from krugazul June 3, 2026 20:01
@github-actions github-actions Bot added the lang:json JSON config/content label Jun 3, 2026
@ashleyshaw ashleyshaw merged commit 42b95a7 into develop Jun 3, 2026
23 checks passed
@ashleyshaw ashleyshaw deleted the codex/branch-governance-hardening branch June 3, 2026 20:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:ci Build and CI pipelines area:documentation Docs & guides area:scripts Scripts & tooling area:tests Test suites & harnesses lang:js JavaScript/TypeScript lang:json JSON config/content lang:md Markdown content/docs meta:no-changelog No changelog needed priority:normal Default priority status:needs-review Awaiting code review type:chore Chore / small hygiene change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[INTEGRATION] Integrate template validation into GitHub branch protection

2 participants