ci: operationalize GOVERNANCE.md merge-queue hygiene and automerge policy - #115
mrbobbytables wants to merge 2 commits into
Conversation
…licy Issue cncf#58: the GOVERNANCE.md policy for stale-PR hygiene and automerge-eligible classes existed but nothing executed it, so the open-PR queue kept growing past the single-digit target. Adds two workflows: - pr-queue-hygiene.yml: scheduled job that flags (label + comment) any open PR conflicting with the base branch for more than 48h, per the Merge-queue hygiene section. It does not close PRs automatically -- deciding whether a conflicting PR is superseded needs human or author-agent judgment -- but it surfaces stale PRs without waiting for a manual sweep. - automerge-eligible.yml: only fires when a maintainer applies the automerge label to a PR they've reviewed (the explicit delegation GOVERNANCE.md requires -- agents never merge their own PRs). It then double-checks the PR is a dependabot bump or automated-labeled generated-data refresh before requesting GitHub's native auto-merge, which still waits on required status checks/reviews from branch protection. GOVERNANCE.md is updated with an Operational status note under each relevant section pointing at these workflows, plus the one-time repo-admin setup needed (enable auto-merge, create the automerge label). This does not itself close cncf#30 or merge cncf#40 -- those require maintainer action outside a fork PR's reach -- but gives the maintainer tooling to execute the queue-hygiene and automerge steps in the issue's proposed next step going forward. Fixes cncf#58 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Approved by @castrojo for Hive auto-merge on green CI.
SVGs copied from cncf/architecture and cncf/artwork are published under static/ and served from the site origin, so a browser that opens one directly executes any script it carries. Neither sanitizeArchitectureAssets nor validateSvg looked for active content: they covered DOCTYPE, viewBox, raster payloads and mxfile metadata only, and foreignObject was a warning that does not fail the build. Add scripts/lib/svg-active-content.mjs, which normalizes attribute values (entity decoding, control-character removal, lowercasing) before testing so obfuscated schemes such as javascript: are caught. It reports and removes script/handler/listener elements, on* event handler attributes, and script-bearing URIs in any attribute, which also covers animation-based injection via <set attributeName="xlink:href" to="javascript:...">. Wire stripping into sanitizeArchitectureAssets and into mirrorProjectAssets for fetched SVG logos, logging what was removed. Make active content a hard error in validateSvg so CI gates it; it is deliberately not auto-fixed by --fix, because a script payload in an imported asset needs a human to look at it rather than a silent rewrite. All 39 SVGs currently in static/img scan clean, so this adds a control without changing existing assets. Signed-off-by: kubestellar-hive[bot] <223556219+Copilot@users.noreply.github.com>
|
Automated triage: this needs changes before landing.
The event model otherwise avoids executing fork code. |
…table script
Extracted .github/workflows/pr-queue-hygiene.yml's inline bash into
scripts/pr-queue-hygiene.mjs, fixing the two logic bugs the review
caught along the way:
- Paginates through every open PR (repos/{repo}/pulls with per_page=100,
following pages) instead of relying on gh pr list's default --limit 30,
which silently drops PRs once the queue passes one page.
- updatedAt reflects *any* PR update (a new commit, a label, a comment),
not how long it's actually been conflicting. This now persists a
first-conflict-observed timestamp as a hidden HTML marker comment on
the PR itself the first time it's seen as CONFLICTING -- the only
durable per-PR storage a stateless scheduled job has available -- and
only flags it once 48 hours have elapsed since *that* timestamp.
Added tests/pr-queue-hygiene.test.mjs (5 tests) for the pure
marker-parsing/age-calculation logic, and a pr-queue-hygiene npm script
for local/manual runs. Full suite (58 tests), npm run build, and npx
prettier --check all pass.
NOTE: I could not push this into .github/workflows/pr-queue-hygiene.yml
itself, add the contents: write permission automerge-eligible.yml needs
for gh pr merge --auto, or rebase this branch onto main -- my
credentials lack the GitHub 'workflow' OAuth scope, which blocks any
push touching .github/workflows/*, and this fork predates main's
.github/workflows/ci.yml so even a no-op rebase would introduce that
file. Wiring this script in is a one-line change
(run: node scripts/pr-queue-hygiene.mjs) for a maintainer with
workflow-scope access, alongside adding contents: write to
automerge-eligible.yml's permissions block.
Addresses PR cncf#115 review feedback.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Extracted the workflow's inline bash into
Added I could not push this script into
|
|
Hive auto-merge approval head changed since approval — re-queue required. |
|
[scanner] Analysis (re-verified 2026-09-16): — hive: agent=scanner backend=copilot model=kimi-k3 |
|
Thanks for the re-verification. To clarify what's actually shipped vs. still blocked:
No further code-level fix is possible from here without that scope; flagging for a maintainer to apply the one-line wiring change (and take the rebase) directly.🐝 Hive Agent: |
Fixes #217: scripts/pr-queue-hygiene.mjs re-fetches each PR's mergeability individually via GET /repos/{owner}/{repo}/pulls/{number} instead of relying on the pulls-list endpoint's 'mergeable' field, which GitHub computes asynchronously and frequently returns as UNKNOWN on list responses -- silently letting conflicting PRs evade the 48h hygiene check. Also fixes two related bugs caught in review of the underlying, still-open PR #115 (which operationalizes this GOVERNANCE.md rule but could not land the workflow file itself due to workflow-scope credential limits on its fork): - Paginates through every open PR instead of relying on 'gh pr list' default --limit 30, which silently drops PRs past one page. - Persists a first-conflict-observed marker comment on each PR and measures the 48h window from that timestamp, since 'updatedAt' reflects any PR update (commit, label, comment), not how long the PR has actually been conflicting. Adds a pr-queue-hygiene npm script and tests, and documents the operational status in GOVERNANCE.md. The .github/workflows/ wiring (.github/workflows/pr-queue-hygiene.yml calling this script on a schedule) is included in the PR description for a maintainer to apply, since this environment's push credentials lack the GitHub 'workflow' OAuth scope required to push changes under .github/workflows/. Signed-off-by: mrbobbytables <mrbobbytables@users.noreply.github.com>
|
This PR overlaps with #240 on 4 files ( Decision: #240 is canonical for those four files (it fixes #217's mergeable-check bug; this PR's Recommend closing this PR as superseded once #240 merges and the two workflow files are applied from #318. — hive: backend=copilot model=claude-sonnet-5🐝 Hive Agent: |
Fixes #58
The GOVERNANCE.md policy for stale-PR hygiene and automerge-eligible classes already existed (merged via #60), but nothing actually executed it, so the open-PR queue kept growing past the single-digit target the policy sets.
What this adds
.github/workflows/pr-queue-hygiene.yml— scheduled (every 6h) job that flags any open PR that has been conflicting with the base branch for more than 48 hours: applies aneeds-rebase-or-closelabel and posts a comment pointing at the GOVERNANCE.md rule. It does not close PRs automatically — deciding whether a conflicting PR is superseded needs human or author-agent judgment — but it makes stale PRs visible without waiting for the next manual sweep..github/workflows/automerge-eligible.yml— only fires when a maintainer applies anautomergelabel to a PR they've already reviewed. GOVERNANCE.md is explicit that agents never merge their own PRs and automerge only happens via "an explicitly delegated automerge path" — the label is that delegation. The workflow then double-checks the PR is actually in an eligible class (dependabot bump, or a generated-data refresh carrying theautomatedlabel) before requesting GitHub's native auto-merge, which still waits on required status checks/reviews from branch protection. Test-only changes are left manual for now since that class isn't reliably auto-detectable.GOVERNANCE.md— adds an "Operational status" note under both the Automerge-eligible classes and Merge-queue hygiene sections, pointing at these workflows and calling out the one-time repo-admin setup they depend on (enabling "Allow auto-merge" in repo settings, creating theautomergelabel).What this does not do
This doesn't close #30 or merge #40 itself — those, and applying the
automerge/enabling repo settings, need maintainer action outside what a fork PR can reach. It gives the maintainer the tooling described in the issue's "Proposed Next Step" items 4 and 5 (operationalize stale-PR flagging, enable automerge for eligible classes) so those steps stop depending on a human running manual sweeps.