Skip to content

Fix dependabot milestone handling and branding footer automation#1013

Merged
ashleyshaw merged 7 commits into
developfrom
fix/automation-governance-hardening
Jun 19, 2026
Merged

Fix dependabot milestone handling and branding footer automation#1013
ashleyshaw merged 7 commits into
developfrom
fix/automation-governance-hardening

Conversation

@ashleyshaw

@ashleyshaw ashleyshaw commented Jun 19, 2026

Copy link
Copy Markdown
Member

Linked issues

Fixes #1010

Context

  • Severity/Impact: Medium
  • Affected versions/environments: Repository automation for issue and pull request metadata, branding footer insertion, and Dependabot PR handling

Reproduction

  • Steps: Open a Dependabot PR or markdown doc that the branding agent should process
  • Expected vs Actual: Expected grouped or absent milestone handling for Dependabot PRs, and a branded footer appended to scoped markdown docs; actual behaviour was one milestone per item and missing footer insertion on some docs

Root Cause

  • Dependabot milestone creation was auto-derived from item metadata instead of inheriting only from linked issues
  • Footer insertion was using outdated path/config assumptions and could miss documents when the footer text appeared elsewhere in the body

Fix Summary

  • Removed auto-created milestone behaviour for Dependabot PRs and kept milestone inheritance only where a linked issue already carries one
  • Switched footer resolution to the canonical config path and made footer detection tail-aware
  • Backfilled branded markdown footers and updated validation, docs, and workflow gates

Verification

  • Tests added/updated to cover the bug
  • Manual verification steps (browsers/devices)
  • Negative/edge cases checked

Risk & Rollback

  • Risk level: Medium
  • Rollback plan: Revert the branch commit if footer validation or metadata sync regresses

Changelog

Added

  • Added footer validation to CI and documented the canonical branding config path

Changed

  • Changed Dependabot milestone handling so the automation no longer creates one milestone per PR
  • Changed footer detection to use the canonical configuration and document tail instead of matching body text

Fixed

  • Fixed missing branding footer insertion on markdown docs that were previously skipped
  • Fixed footer automation so body references no longer prevent insertion

Removed

  • Removed automatic milestone creation for Dependabot PRs

Checklist (Global DoD / PR)

  • All AC met and demonstrated
  • Tests added/updated (unit/E2E as appropriate)
  • Docs/readme/changelog updated (if user-facing)
  • Risk assessment completed above
  • Testing instructions provided above

References

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

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 42 minutes and 7 seconds. Learn how PR review limits work.

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

⌛ 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.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

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: ad1033df-5579-46b1-b1d3-232bb0f7a255

📥 Commits

Reviewing files that changed from the base of the PR and between 2029f69 and 76b58f7.

📒 Files selected for processing (15)
  • .github/scripts/validate-footers.js
  • .github/workflows/checks.yml
  • CHANGELOG.md
  • config/footers.config.yaml
  • docs/AUTOMATION.md
  • docs/BRANCHING_STRATEGY.md
  • docs/BRANDING_AGENT_USAGE.md
  • docs/BRANDING_CONFIG_SPEC.md
  • docs/FOOTER_REMEDIATION_GUIDE.md
  • docs/ISSUE_CREATION_GUIDE.md
  • package.json
  • scripts/agents/includes/__tests__/header-footer.test.js
  • scripts/agents/includes/__tests__/issue-pr-metadata.test.js
  • scripts/agents/includes/header-footer.js
  • scripts/agents/includes/issue-pr-metadata.cjs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/automation-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 commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

🎨 Mermaid Diagram Validation

✅ All Mermaid diagram checks passed.

Check Result
✅ Syntax (diagram type, direction, bracket matching) Passed
✅ Accessibility (accTitle / accDescr present) Passed
✅ Colour contrast (WCAG 2.2 AA ≥ 4.5:1) Passed

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

🔍 Reviewer Summary for PR #1013

CI Status:success
Files changed: 15
Risk Distribution: 1 critical, 2 high, 2 medium, 10 low

Recommendations

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

@github-actions

Copy link
Copy Markdown
Contributor

Metadata governance

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

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.

Code Review

This pull request standardizes the footer branding across all Markdown files in the repository and updates the .github/scripts/validate-footers.js script to enforce these branded footers and backfill them from category defaults. It also updates metadata governance documentation in docs/AUTOMATION.md. The review comments correctly identify two critical issues in the updated validation script: a data loss bug in replaceFooterTail where frontmatter separators are mistaken for footer separators, and a classification bug in inferCategory where README files inside template directories are incorrectly categorized as templates instead of readmes due to pattern matching order.

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 +133 to +154
function replaceFooterTail(content, footerTemplate) {
const footerBlock = `\n---\n\n${footerTemplate.trimEnd()}\n`;
const separators = [];
const lines = content.split("\n");

lines.forEach((line, idx) => {
if (line.trim() === "---") {
separators.push(idx);
}
});

if (separators.length === 0) {
if (content.endsWith("\n")) {
return `${content}${footerBlock.trimStart()}`;
}

return `${content}\n${footerBlock.trimStart()}`;
}

const lastSeparatorIdx = separators[separators.length - 1];
const contentWithoutTail = lines.slice(0, lastSeparatorIdx).join("\n").replace(/\s+$/, "");
return `${contentWithoutTail}${footerBlock}`;

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.

critical

The current implementation of replaceFooterTail has a critical bug that results in data loss.

If a Markdown file has frontmatter (which starts and ends with --- separators) but does not yet have a footer, separators.length will be 2. The code will set lastSeparatorIdx to the second separator (the closing frontmatter separator) and slice the content from 0 to lastSeparatorIdx. This completely discards the entire body of the document, leaving only the frontmatter and the new footer.

To prevent this, we must identify and skip the frontmatter separators when searching for the footer separator.

function replaceFooterTail(content, footerTemplate) {
  const footerBlock = "\n---\n\n" + footerTemplate.trimEnd() + "\n";
  const separators = [];
  const lines = content.split("\n");

  lines.forEach((line, idx) => {
    if (line.trim() === "---") {
      separators.push(idx);
    }
  });

  const hasFrontmatter = lines[0]?.trim() === "---" || (lines[0]?.trim() === "" && lines[1]?.trim() === "---\n");
  const footerSeparators = separators.filter((idx, sIdx) => !hasFrontmatter || sIdx >= 2);

  if (footerSeparators.length === 0) {
    if (content.endsWith("\n")) {
      return content + footerBlock.trimStart();
    }
    return content + "\n" + footerBlock.trimStart();
  }

  const lastSeparatorIdx = footerSeparators[footerSeparators.length - 1];
  const contentWithoutTail = lines.slice(0, lastSeparatorIdx).join("\n").replace(/\s+$/, "");
  return contentWithoutTail + footerBlock;
}

Comment on lines +163 to +192
const pathPatterns = [
{ pattern: /^\.github\/ISSUE_TEMPLATE\/.*\.md$/i, category: "issue-template" },
{ pattern: /^\.github\/PULL_REQUEST_TEMPLATE\/.*\.md$/i, category: "pull-request-template" },
{ pattern: /^agents\/.*\.(?:md|agent\.md)$/i, category: "agents" },
{
pattern: /^instructions\/.*\.md$|.*\.instructions\.md$/i,
category: "instructions",
},
{ pattern: /^schema\/.*\.md$|.*\.schema\.md$/i, category: "schema" },
{
pattern: /^\.github\/reports\/.*\.md$|.*audit.*\.md$/i,
category: "audit",
},
{ pattern: /.*research.*\.md$/i, category: "research" },
{
pattern: /^scripts\/.*\.md$|^utils\/.*\.md$|.*utility.*\.md$/i,
category: "utility",
},
{
pattern: /^docs\/.*governance.*\.md$|^governance\/.*\.md$/i,
category: "governance",
},
{
pattern: /^docs\/.*(?:automation|ai-ops).*\.md$/i,
category: "ai-ops",
},
{ pattern: /^docs\/.*\.md$/i, category: "docs" },
{ pattern: /^(?:.*\/)?README\.md$/i, category: "readme" },
];

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

The README.md pattern is currently placed at the very bottom of pathPatterns. Because pathPatterns.find stops at the first match, any README.md file located inside .github/ISSUE_TEMPLATE/ or .github/PULL_REQUEST_TEMPLATE/ will be incorrectly classified as "issue-template" or "pull-request-template" instead of "readme".

This causes template placeholders (like Related issues: {related_issues} or Closes: {closes_issues}) to be appended to the README files instead of the standard branded footer.

Moving the README.md pattern to the top of the array resolves this issue.

  const pathPatterns = [
    { pattern: /^(?:.*\/)?README\.md$/i, category: "readme" },
    { pattern: /^\.github\/ISSUE_TEMPLATE\/.*\.md$/i, category: "issue-template" },
    { pattern: /^\.github\/PULL_REQUEST_TEMPLATE\/.*\.md$/i, category: "pull-request-template" },
    { pattern: /^agents\/.*\.(?:md|agent\.md)$/i, category: "agents" },
    {
      pattern: /^instructions\/.*\.md$|.*\.instructions\.md$/i,
      category: "instructions",
    },
    { pattern: /^schema\/.*\.md$|.*\.schema\.md$/i, category: "schema" },
    {
      pattern: /^\.github\/reports\/.*\.md$|.*audit.*\.md$/i,
      category: "audit",
    },
    { pattern: /.*research.*\.md$/i, category: "research" },
    {
      pattern: /^scripts\/.*\.md$|^utils\/.*\.md$|.*utility.*\.md$/i,
      category: "utility",
    },
    {
      pattern: /^docs\/.*governance.*\.md$|^governance\/.*\.md$/i,
      category: "governance",
    },
    {
      pattern: /^docs\/.*(?:automation|ai-ops).*\.md$/i,
      category: "ai-ops",
    },
    { pattern: /^docs\/.*\.md$/i, category: "docs" }
  ];

@ashleyshaw ashleyshaw marked this pull request as ready for review June 19, 2026 10:23
@ashleyshaw ashleyshaw enabled auto-merge (squash) June 19, 2026 10:23
@ashleyshaw

Copy link
Copy Markdown
Member Author

@Mergifyio queue

@mergify

mergify Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

  • 🟠 Waiting for queue conditions
  • ⏳ Enter queue
  • ⏳ Run checks
  • ⏳ Merge
Waiting for
  • -closed [📌 queue requirement]
  • any of: [🔀 queue conditions]
    • all of: [📌 queue conditions of queue rule Merge queue]
      • any of: [🛡 GitHub branch protection]
        • check-neutral = CI • Unified Checks (Lint, Test, Validate) / All Checks Passed
        • check-skipped = CI • Unified Checks (Lint, Test, Validate) / All Checks Passed
        • check-success = CI • Unified Checks (Lint, Test, Validate) / All Checks Passed
      • any of: [🛡 GitHub branch protection]
        • check-neutral = Validate PR Template / validate-pr-template
        • check-skipped = Validate PR Template / validate-pr-template
        • check-success = Validate PR Template / validate-pr-template
    • all of: [📌 queue conditions of queue rule dependabot]
      • any of: [🛡 GitHub branch protection]
        • check-neutral = CI • Unified Checks (Lint, Test, Validate) / All Checks Passed
        • check-skipped = CI • Unified Checks (Lint, Test, Validate) / All Checks Passed
        • check-success = CI • Unified Checks (Lint, Test, Validate) / All Checks Passed
      • any of: [🛡 GitHub branch protection]
        • check-neutral = Validate PR Template / validate-pr-template
        • check-skipped = Validate PR Template / validate-pr-template
        • check-success = Validate PR Template / validate-pr-template
All conditions
  • -closed [📌 queue requirement]
  • any of [🔀 queue conditions]:
    • all of [📌 queue conditions of queue rule Merge queue]:
      • any of [🛡 GitHub branch protection]:
        • check-neutral = CI • Unified Checks (Lint, Test, Validate) / All Checks Passed
        • check-skipped = CI • Unified Checks (Lint, Test, Validate) / All Checks Passed
        • check-success = CI • Unified Checks (Lint, Test, Validate) / All Checks Passed
      • any of [🛡 GitHub branch protection]:
        • check-neutral = Validate PR Template / validate-pr-template
        • check-skipped = Validate PR Template / validate-pr-template
        • check-success = Validate PR Template / validate-pr-template
    • all of [📌 queue conditions of queue rule dependabot]:
      • author~=^(dependabot\[bot\]|app/dependabot)$
      • any of [🛡 GitHub branch protection]:
        • check-neutral = CI • Unified Checks (Lint, Test, Validate) / All Checks Passed
        • check-skipped = CI • Unified Checks (Lint, Test, Validate) / All Checks Passed
        • check-success = CI • Unified Checks (Lint, Test, Validate) / All Checks Passed
      • any of [🛡 GitHub branch protection]:
        • check-neutral = Validate PR Template / validate-pr-template
        • check-skipped = Validate PR Template / validate-pr-template
        • check-success = Validate PR Template / validate-pr-template
      • -conflict
      • -draft
      • base=develop
      • label=area:dependencies
  • -conflict [📌 queue requirement]
  • -draft [📌 queue requirement]
  • any of [📌 queue -> configuration change requirements]:
    • -mergify-configuration-changed
    • check-success = Configuration changed
  • any of [📌 queue requirement]:
    • check-neutral = Mergify Merge Protections
    • check-skipped = Mergify Merge Protections
    • check-success = Mergify Merge Protections

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

Copy link
Copy Markdown

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: 6f146b0480

ℹ️ 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".

function getFooterSignatures() {
const canonicalTemplates = getCanonicalFooterTemplates();
const canonicalSignatures = canonicalTemplates
.map((template) => template.split("\n").map((line) => line.trim()).find(Boolean))

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 Skip delimiter lines when deriving footer signatures

When the canonical config/footers.config.yaml is present, each template starts with a --- divider, and this find(Boolean) records that divider as a known footer signature. In any Markdown document that uses a horizontal rule after frontmatter, hasKnownFooter() then treats everything after the last --- as an existing footer, so ensureFooter() replaces real body content with a footer. Filter out delimiter-only lines, as the validator does, before adding canonical signatures.

Useful? React with 👍 / 👎.

Comment on lines +97 to +98
function buildFooterBlock(footerText) {
return `\n---\n\n${footerText.trimEnd()}\n`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid wrapping canonical footers with a second divider

With the normal footer config loaded, getFooterPhrases() returns the full configured template, and those templates already include their leading --- divider. This wrapper prepends another divider, so generated footers become --- followed by another --- before the footer text; the same shape is used by the new validate-footers --fix path. Strip the configured divider or only add one for legacy fallback footers to keep generated documents in the documented single-footer format.

Useful? React with 👍 / 👎.

Comment on lines +106 to +107
const tailStart = separators[separators.length - 1] + 1;
return lines.slice(tailStart).join("\n").trim();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Strip frontmatter before scanning for footer signatures

For a document with frontmatter but no footer, the closing frontmatter marker is the last ---, so this returns the whole body as the footer tail. If the body merely shows an example footer signature, as remediation/specification docs commonly do, footerHitCounts becomes non-zero and the new require_footer_in_document CI check passes even though no footer exists at the end of the file. Remove the frontmatter block before locating the footer divider.

Useful? React with 👍 / 👎.

@github-actions github-actions Bot added status:needs-review Awaiting code review type:bug Bug or defect priority:normal Default priority area:ci Build and CI pipelines area:dependencies Composer/npm dependency work area:documentation Docs & guides area:tests Test suites & harnesses area:scripts Scripts & tooling lang:js JavaScript/TypeScript lang:md Markdown content/docs lang:json JSON config/content labels Jun 19, 2026
@github-actions github-actions Bot added lang:yaml YAML config type:chore Chore / small hygiene change meta:needs-changelog Requires a changelog entry before merge labels Jun 19, 2026
@github-actions github-actions Bot removed the type:chore Chore / small hygiene change label Jun 19, 2026
@ashleyshaw ashleyshaw merged commit bd43ba3 into develop Jun 19, 2026
29 checks passed
@ashleyshaw ashleyshaw deleted the fix/automation-governance-hardening branch June 19, 2026 10:36
@ashleyshaw ashleyshaw mentioned this pull request Jun 19, 2026
7 tasks
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:dependencies Composer/npm dependency work 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 lang:yaml YAML config meta:needs-changelog Requires a changelog entry before merge priority:normal Default priority status:needs-review Awaiting code review type:bug Bug or defect

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Harden Dependabot metadata and branding footer automation

1 participant