Skip to content

fix(ci): re-run PR gate on issue_comment and gate prepush frontend lint on changes - #1123

Merged
Ingwannu merged 8 commits into
devfrom
codex/ci-gui-waiver-trigger
Aug 6, 2026
Merged

fix(ci): re-run PR gate on issue_comment and gate prepush frontend lint on changes#1123
Ingwannu merged 8 commits into
devfrom
codex/ci-gui-waiver-trigger

Conversation

@Wibias

@Wibias Wibias commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • The enforce-target PR gate now re-runs on issue_comment events, so a maintainer's frontend-screenshot waiver comment takes effect immediately instead of waiting for a PR edit or push. This fixes the scenario on test(catalog): pin the routed reasoning joint contract (#1100) + bug-grade triage unit #1119 where the waiver was posted but the gate never re-evaluated.
  • The issue_comment re-run is restricted to maintainer comments (OWNER / COLLABORATOR / MEMBER) on actual pull requests. A comment on a plain issue, or from a non-maintainer, does not start the write-capable gate — enforced by a job-level if plus a defensive in-script re-check.
  • The local prepush hook now runs the frontend eslint check only when the push touches the dashboard frontend directory, matching the existing frontend-doctor-if-changed behavior and the CI gates job's change filter. A tests-only or docs-only push no longer pays for an unconditional frontend lint run.
  • The PR gate and PR hygiene bot messages are consolidated into one editable comment: the hygiene workflow writes its status block into the single opencodex-pr-gate comment, and the gate preserves an existing hygiene block across rebuilds. No more two separate bot messages on a PR.

Validation

  • bun test tests/ci-workflows.test.ts — 120 pass / 0 fail (covers the issue_comment re-run, the maintainer-only guard, the plain-issue skip, and the hygiene-section round-trip)
  • node --test .github/scripts/enforce-pr-target.test.cjs — 17 pass / 0 fail
  • node --test .github/scripts/*.test.cjs — 434 pass / 0 fail
  • bun test tests/docs-bun-source-requirement.test.ts tests/repo-hygiene.test.ts — 12 pass / 0 fail
  • bun run typecheck — clean
  • bun run privacy:scan — passed

Review notes

  • The issue_comment trigger never touches PR head code: the checkout stays on the trusted base/default branch, and the gate script re-reads the live PR via the API. This is the same trusted-base model as pull_request_target, so it does not open the head-controlled-YAML escalation that review events would.
  • The pull_number resolution falls back from context.payload.pull_request?.number to context.payload.issue?.number, and the concurrency group resolves from whichever payload exists.
  • Lint findings always fail the push in the new script — unlike the frontend doctor, there is no engine fetch, so there is no infra soft-skip path.
  • The hygiene/gate comment merge is marker-delimited (<!-- pr-hygiene-block:start/end -->), so both workflows edit one comment without clobbering each other's section.

Summary by CodeRabbit

  • New Features

    • Pull request quality checks can now be rerun from eligible pull-request comments, including edited comments.
    • Hygiene results are preserved and updated within consolidated pull request status comments.
    • GUI linting now runs automatically when relevant GUI files change.
  • Bug Fixes

    • Improved pull request detection and checkout behavior for comment-triggered checks.
    • Prevented stale quality status from being incorrectly treated as current.
  • Documentation

    • Updated contributor guidance and hook setup messages to reflect conditional GUI checks.

… changes

The maintainer GUI-waiver comment ("not touching gui") never re-ran the
enforce-target gate because pull_request_target types do not include issue
comments. Add an issue_comment trigger so the waiver takes effect when
posted, resolving the PR number from the issue payload and falling the
checkout back to the default branch.

Also stop running lint:gui unconditionally in the local prepush hook: it now
runs only when the push touches gui/, mirroring doctor:gui:if-changed. CI
already gated GUI lint behind the changes filter; the local hook now matches.
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Aug 6, 2026
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds conditional GUI linting for pre-push checks. The PR-target workflow reruns for created or edited maintainer comments on pull requests. Shared hygiene helpers preserve hygiene sections in consolidated gate comments.

Changes

GUI linting and hook integration

Layer / File(s) Summary
Conditional GUI lint execution
scripts/lint-gui-if-changed.ts, package.json, scripts/fixtures/*, scripts/setup-hooks.ts, CONTRIBUTING.md, tests/ci-workflows.test.ts
The pre-push hook detects changes under gui/ and runs GUI lint only when required. The script supports overrides, dry runs, Git base fallbacks, and lint failure propagation. Documentation, hook output, package wiring, fixtures, and tests use the conditional command.

Issue-comment PR enforcement

Layer / File(s) Summary
Issue-comment workflow handling
.github/workflows/enforce-pr-target.yml, .github/scripts/enforce-pr-target.test.cjs, tests/helpers/enforce-pr-target-harness.ts, tests/ci-workflows.test.ts, .github/scripts/pr-quality-state.test.cjs
The workflow handles created and edited issue comments from pull requests. It checks commenter association, resolves the PR number from either payload shape, groups runs by PR number, uses a fallback checkout ref, and treats missing event head SHAs as stale checklist state.
Hygiene section comment handling
.github/scripts/pr-quality-messages.cjs, .github/scripts/pr-quality-messages.test.cjs, .github/workflows/pr-hygiene.yml, .github/workflows/enforce-pr-target.yml, .github/workflows/issue-quality-tests.yml, tests/ci-workflows.test.ts
Shared markers and helpers render, extract, replace, and preserve hygiene sections. The workflows merge hygiene status into consolidated gate comments and retain standalone hygiene-comment behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHub
  participant PRTargetWorkflow
  participant QualityMessages
  participant PRHygieneWorkflow
  GitHub->>PRTargetWorkflow: issue_comment created or edited
  PRTargetWorkflow->>QualityMessages: rebuild gate comment
  QualityMessages-->>PRTargetWorkflow: preserve existing hygiene section
  PRHygieneWorkflow->>QualityMessages: merge hygiene status
  QualityMessages-->>PRHygieneWorkflow: consolidated gate comment body
Loading

Possibly related PRs

Suggested labels: chore

Suggested reviewers: lidge-jun, ingwannu

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the two primary changes: rerunning the PR gate on issue comments and conditionally running frontend lint during pre-push.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/ci-gui-waiver-trigger

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.

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown

✅ READY

  • all PR quality gates passed.

@github-actions
github-actions Bot marked this pull request as draft August 6, 2026 10:48
…tests

The CJS validator test asserted the exact base-SHA checkout ref and did not
cover the new issue_comment trigger. Update the ref assertion to the
fallback form and add a test pinning that a maintainer GUI-waiver comment
re-runs the gate via the issue_comment event.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/enforce-pr-target.yml:
- Around line 16-19: Restrict the workflow job handling issue comments to events
where github.event.issue.pull_request is present, while preserving other event
triggers. Add a regression test covering an ordinary issue comment and obtain
the required explicit security review specified by MAINTAINERS.md.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9a5e67da-4509-4784-80b5-dde363d9497c

📥 Commits

Reviewing files that changed from the base of the PR and between 75f384c and 8b39f1a.

📒 Files selected for processing (8)
  • .github/workflows/enforce-pr-target.yml
  • CONTRIBUTING.md
  • package.json
  • scripts/fixtures/lint-findings-exit.ts
  • scripts/lint-gui-if-changed.ts
  • scripts/setup-hooks.ts
  • tests/ci-workflows.test.ts
  • tests/helpers/enforce-pr-target-harness.ts

Comment thread .github/workflows/enforce-pr-target.yml
@Ingwannu

Ingwannu commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Maintainer screenshot waiver: this PR is not touching gui. The changed files do not modify the rendered dashboard, so a UI screenshot is not applicable. This waiver applies only to the screenshot gate.

The PR should remain draft for now. The issue_comment job must be restricted to comments whose issue payload contains pull_request; otherwise every ordinary issue comment can start a PR-only workflow with a non-PR issue number. Please add the job-level event guard and a regression test for an ordinary issue comment being skipped. Because this changes a pull_request_target/issue_comment workflow boundary, the explicit workflow security review required by MAINTAINERS.md is also still needed. I will re-check the updated head and full CI after those are resolved.

@Wibias Wibias changed the title fix(ci): re-run PR gate on issue_comment and gate prepush lint on gui changes fix(ci): re-run PR gate on issue_comment and gate prepush frontend lint on changes Aug 6, 2026
@github-actions
github-actions Bot marked this pull request as ready for review August 6, 2026 10:51
…olidate bot comments

The issue_comment trigger fired for any comment on any issue from any user.
Guard the enforce-target job so only maintainer (OWNER/COLLABORATOR/MEMBER)
comments on actual PRs re-run the write-capable gate; a comment on a plain
issue or from a contributor is skipped, with a defensive in-script re-check
matching the job-level if.

Also consolidate the PR gate and PR hygiene bot messages into the single
opencodex-pr-gate comment. The hygiene workflow now writes its status block
into the gate comment (preserving the gate section) instead of posting a
second standalone message, and the gate rebuild preserves an existing
hygiene block so neither workflow clobbers the other.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/scripts/pr-quality-messages.cjs:
- Around line 118-120: Update the hygiene-block regular expressions used by the
body match and existence check around HYGIENE_BLOCK_START/HYGIENE_BLOCK_END so
both delimiters match only when they occupy complete lines, including
appropriate line-boundary handling. Apply the same predicate consistently at
both locations, and add a regression test covering delimiter text embedded in a
filename-like hygiene line.

In @.github/workflows/enforce-pr-target.yml:
- Around line 284-293: Use the same per-PR concurrency group for the
comment-update workflows: update the concurrency configuration in
.github/workflows/enforce-pr-target.yml (lines 284-293) and
.github/workflows/pr-hygiene.yml (lines 129-150) to share one key, preserving
any existing PR-specific isolation. Ensure the shared group serializes updates
performed by the gate comment rebuild flow and the hygiene comment-update flow.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: bf81c5a2-8a1f-4913-a9d4-4e4ea442bcad

📥 Commits

Reviewing files that changed from the base of the PR and between 8b39f1a and 732f296.

📒 Files selected for processing (8)
  • .github/scripts/enforce-pr-target.test.cjs
  • .github/scripts/pr-quality-messages.cjs
  • .github/scripts/pr-quality-messages.test.cjs
  • .github/workflows/enforce-pr-target.yml
  • .github/workflows/issue-quality-tests.yml
  • .github/workflows/pr-hygiene.yml
  • tests/ci-workflows.test.ts
  • tests/helpers/enforce-pr-target-harness.ts

Comment thread .github/scripts/pr-quality-messages.cjs Outdated
Comment thread .github/workflows/enforce-pr-target.yml

@Ingwannu Ingwannu left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

The issue-comment guard is now correct on head 732f296e: it restricts the job to maintainer comments on pull requests, repeats that check inside the trusted script, and covers both ordinary issues and non-maintainer comments. That resolves my previous workflow-boundary blocker.

One new merge blocker remains in the hygiene-comment consolidation. enforce-pr-target.yml and pr-hygiene.yml now both read and replace the same complete bot comment, but they run under different concurrency groups (enforce-pr-target-* and pr-hygiene-*). On the same PR event they can both read body A, independently build bodies B and C, and last-write-wins can restore stale gate/readiness state or drop the newly written hygiene block. The round-trip unit tests cover sequential rebuilds only; they do not make the cross-workflow read-modify-write atomic.

Please keep the hygiene status as its standalone comment in this PR (the smallest and safest fix), or move both mutations behind one serialized owner with a regression that proves an interleaved gate/hygiene update cannot lose either state. Simply sharing a concurrency group also needs care because the current hygiene workflow uses cancel-in-progress: true, which may cancel the gate mid-mutation. The standalone-comment approach avoids expanding this PR further.

After that is resolved and exact-head CI is green, the guarded issue_comment trigger and conditional GUI lint are acceptable from the workflow security perspective.

@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: ac8505d76c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread .github/workflows/enforce-pr-target.yml Outdated
Comment thread .github/workflows/enforce-pr-target.yml
Comment thread .github/workflows/enforce-pr-target.yml
Comment thread .github/workflows/enforce-pr-target.yml
…te comment concurrency

Two CodeRabbit findings on the consolidated gate comment:

- The hygiene block delimiters matched anywhere in the comment body. A
  contributor-controlled changed filename could embed delimiter text mid-line
  and corrupt the block boundary on the next rewrite. Anchor both delimiters
  to complete lines via a shared regex used by the existence check and the
  replacement, with a regression test for embedded delimiter text.

- The gate and hygiene workflows each had their own per-PR concurrency group
  while both read-modify-write the same consolidated comment. A concurrent
  gate rebuild and hygiene update could run from stale snapshots and the last
  write would drop the other's section. Share one per-PR concurrency group
  between the two workflows and pin it in the workflow tests.

@coderabbitai coderabbitai 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/pr-hygiene.yml (1)

140-152: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Remove stale standalone hygiene comments after merging into the gate.

In .github/workflows/pr-hygiene.yml, .github/workflows/pr-hygiene.yml lines 143-152 update the existing gate comment but leave any earlier github-actions[bot] comment containing HYGIENE_MARKER in place. Add stale cleanup after updateComment and add a regression test for the case where both comments already exist.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/pr-hygiene.yml around lines 140 - 152, After updating the
gate comment in the existing merge path, remove any other github-actions[bot]
comments containing HYGIENE_MARKER, excluding the gateComment itself; preserve
the updated gate comment and use the existing GitHub issue-comment deletion
mechanism. Add a regression test covering both an existing gate comment and a
stale standalone hygiene comment, verifying the stale comment is deleted after
merging.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In @.github/workflows/pr-hygiene.yml:
- Around line 140-152: After updating the gate comment in the existing merge
path, remove any other github-actions[bot] comments containing HYGIENE_MARKER,
excluding the gateComment itself; preserve the updated gate comment and use the
existing GitHub issue-comment deletion mechanism. Add a regression test covering
both an existing gate comment and a stale standalone hygiene comment, verifying
the stale comment is deleted after merging.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b69a00ee-2167-497b-b386-b50145e7bf12

📥 Commits

Reviewing files that changed from the base of the PR and between 732f296 and 36c87af.

📒 Files selected for processing (5)
  • .github/scripts/pr-quality-messages.cjs
  • .github/scripts/pr-quality-messages.test.cjs
  • .github/workflows/enforce-pr-target.yml
  • .github/workflows/pr-hygiene.yml
  • tests/ci-workflows.test.ts

…rifiable checklists

Codex-bot review findings on the issue_comment trigger:

- The checkout fell back to the repository default branch (main) on
  issue_comment, which can lag the integration branch the gate enforces.
  Fall back to dev (the gate's only allowed base) so comment-triggered runs
  evaluate with the gate's own current scripts.

- issue_comment events carry no pull_request.head.sha, so eventHeadSha
  fell back to the live head and a completed checklist with no recorded
  completion head was accepted as attesting the current head. Pass an empty
  eventHeadSha on issue_comment so completionIsStale resets the checklist
  (fail closed) instead of promoting readiness from an unverifiable
  attestation. Regression tests cover both.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/enforce-pr-target.yml (1)

43-48: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Authorize comment reruns against MAINTAINERS.md.

Lines 43-48 and 164-168 treat MEMBER and COLLABORATOR as maintainers. These GitHub author associations do not prove that the commenter is in the repository's canonical maintainer list. A non-maintainer with either association can start this write-capable gate and cause PR comment, label, title, and draft-state mutations.

Use parseMaintainerLogins() with the trusted checked-out MAINTAINERS.md, then require context.payload.comment.user.login to be in that list before github.rest.pulls.get() or any mutation. Add a regression case for a MEMBER or COLLABORATOR absent from MAINTAINERS.md.

Proposed guard
- const association = context.payload.comment?.author_association;
- const isMaintainer = ["OWNER", "COLLABORATOR", "MEMBER"].includes(
-   association
- );
+ const commenter = context.payload.comment?.user?.login;
+ const isMaintainer =
+   typeof commenter === "string" &&
+   readMaintainerLogins().includes(commenter);

As per path instructions, .github/** is a security boundary and maintainer-only issue-comment reruns must not weaken this control.

Also applies to: 161-168

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/enforce-pr-target.yml around lines 43 - 48, Replace the
issue-comment authorization checks in the workflow guards around the
pull-request lookup and mutation steps with canonical maintainer validation:
load the trusted checked-out MAINTAINERS.md through parseMaintainerLogins(),
then require context.payload.comment.user.login to be present in the parsed list
before github.rest.pulls.get() or any write operation. Do not treat MEMBER or
COLLABORATOR as sufficient authorization, and add a regression case covering an
associated user absent from MAINTAINERS.md.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/ci-workflows.test.ts`:
- Around line 2699-2708: Merge the duplicate comments properties in this test
fixture into one comments array, preserving both the maintainer “not touching
gui” waiver comment and the readinessComment fixture. Remove the second comments
key so the harness receives both entries and Biome no longer reports a duplicate
key.

---

Outside diff comments:
In @.github/workflows/enforce-pr-target.yml:
- Around line 43-48: Replace the issue-comment authorization checks in the
workflow guards around the pull-request lookup and mutation steps with canonical
maintainer validation: load the trusted checked-out MAINTAINERS.md through
parseMaintainerLogins(), then require context.payload.comment.user.login to be
present in the parsed list before github.rest.pulls.get() or any write
operation. Do not treat MEMBER or COLLABORATOR as sufficient authorization, and
add a regression case covering an associated user absent from MAINTAINERS.md.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3a97e072-1636-443f-9e17-215b549b8967

📥 Commits

Reviewing files that changed from the base of the PR and between 36c87af and 4d13067.

📒 Files selected for processing (4)
  • .github/scripts/enforce-pr-target.test.cjs
  • .github/scripts/pr-quality-state.test.cjs
  • .github/workflows/enforce-pr-target.yml
  • tests/ci-workflows.test.ts

Comment thread tests/ci-workflows.test.ts Outdated
…rleaving

Maintainer review blocker: both workflows read-modify-write the same
consolidated gate comment, but pr-hygiene used cancel-in-progress: true.
With the shared per-PR concurrency group, a newer hygiene run could cancel
an in-flight gate mutation, losing that read-modify-write. Set
cancel-in-progress: false so runs in the shared group queue, matching the
enforce-target workflow.

Add an interleaving regression test: a gate rebuild followed by a hygiene
update (and the reverse order) preserves both the gate status and the
hygiene block, with exactly one block each way. Pin the non-cancelling
shared group in the workflow structure test.
@Wibias

Wibias commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator Author

[GD] Addressed the maintainer review blocker on head a0740f7.

The hygiene-comment consolidation race is closed two ways:

  1. Shared serialized writes. Both enforce-pr-target.yml and pr-hygiene.yml now use the same per-PR concurrency group pr-gate-comment-${{ github.event.pull_request.number || github.event.issue.number }}, and pr-hygiene's cancel-in-progress is now false (matching the gate, which never cancels). Runs in the group queue instead of cancelling, so a gate rebuild and a hygiene update for the same PR cannot run concurrently from stale snapshots — GitHub serializes them.

  2. Order-independent merge. The merge helpers are idempotent in both directions: a gate rebuild preserves an existing hygiene block, and a hygiene update preserves the gate section. The new regression test preserves both sections across an interleaved gate rebuild and hygiene update runs gate→hygiene and hygiene→gate and asserts both the gate status and the hygiene block survive with exactly one block each way. The shared non-cancelling group is pinned in the workflow structure test.

The issue_comment guard and conditional lint were confirmed acceptable; this removes the last merge blocker. Full CI is running on the new head.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/scripts/pr-quality-messages.test.cjs:
- Around line 400-413: The reverse-order test must verify that the gate rebuild
preserves hygiene content from the preceding update. Update the test around
afterHygieneFirst and afterGateSecond to extract and reuse the hygiene lines
from afterHygieneFirst instead of supplying a new hard-coded hygiene array, or
call the production rebuild path that performs this extraction.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2957acea-43c8-4ac5-97d0-2e65f3723694

📥 Commits

Reviewing files that changed from the base of the PR and between 4d13067 and a0740f7.

📒 Files selected for processing (3)
  • .github/scripts/pr-quality-messages.test.cjs
  • .github/workflows/pr-hygiene.yml
  • tests/ci-workflows.test.ts

Comment thread .github/scripts/pr-quality-messages.test.cjs
…verse-order test

Two CodeRabbit findings on the interleaving and issue_comment tests:

- The issue_comment checklist-provenance test passed two `comments` keys;
  the second overwrote the maintainer waiver comment. Merge both fixtures
  into one array so the waiver is actually delivered to the harness.

- The reverse-order interleaving test built afterHygieneFirst but never
  consumed it; afterGateSecond used a hard-coded hygiene array, so the test
  passed even if the gate rebuild discarded the prior hygiene update.
  Extract the hygiene content from afterHygieneFirst via
  extractHygieneSection and feed it into the gate rebuild.

@Ingwannu Ingwannu left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Re-reviewed head 8c4ad03f. The ordinary-issue guard, shared non-cancelling concurrency group, order-independent hygiene merge, and reverse-order regression are now in place. The focused workflow suite passes 121/121 locally.

One workflow-security blocker remains. .github/workflows/enforce-pr-target.yml still treats OWNER, COLLABORATOR, or MEMBER author association as sufficient authorization in both the job guard and the in-script guard. Those associations are broader than this repository's canonical maintainer list, so a non-maintainer collaborator/member can start this write-capable gate and cause PR comment, label, title, and draft-state mutations.

parseMaintainerLogins and the trusted checked-out MAINTAINERS.md are already available in this job. The association check can remain as a cheap job-level prefilter, but before github.rest.pulls.get() or any mutation the script must load the trusted maintainer list and require context.payload.comment.user.login to be a member of it. Please add a regression where the event reports COLLABORATOR or MEMBER, but the commenter is absent from MAINTAINERS.md; the harness should observe no PR lookup and no writes.

CI is also still running on this exact head. Keeping changes requested until the canonical-maintainer authorization and exact-head CI are complete.

Maintainer security blocker: OWNER/COLLABORATOR/MEMBER association is
broader than the repository's canonical maintainer list, so a
non-maintainer collaborator or member could start the write-capable gate
and cause PR comment, label, title, and draft-state mutations.

Before pulls.get or any mutation, the issue_comment guard now loads the
trusted MAINTAINERS.md list (case-insensitively) and requires the
commenter's login to be in it. The association check remains as the cheap
job-level prefilter; the canonical list is the authorization.

Regression: a COLLABORATOR who is not in MAINTAINERS.md cannot re-run the
gate — no PR lookup, no writes, no GraphQL mutation.
@Wibias

Wibias commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator Author

[GD] Addressed on head 22cd62c: the issue_comment guard now requires the commenter to be a canonical maintainer, not merely OWNER/COLLABORATOR/MEMBER.

Before pulls.get or any mutation, the script loads the trusted MAINTAINERS.md (already sparse-checked-out from the base) via the existing readMaintainerLogins() and requires context.payload.comment.user.login to be in that list (case-insensitively). The association check stays as the cheap job-level prefilter; the canonical list is the actual authorization. A collaborator/member who is not a maintainer can no longer start the write-capable gate.

Regression test added: "a COLLABORATOR who is not in MAINTAINERS.md cannot re-run the gate" — the harness observes no pulls.get, no comment/label/title writes, and no GraphQL mutation. Full focused suite: 122/122 pass.

@Ingwannu Ingwannu left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Approved on head 22cd62cb after the workflow-security re-review.

The comment-trigger path now uses author association only as a cheap job prefilter, then reads the trusted checked-out MAINTAINERS.md and requires the commenter's normalized login to be in that canonical list before pulls.get or any mutation. Missing/unreadable maintainer data fails the run closed. The regression proves that an associated but non-maintainer collaborator performs no PR lookup or write.

The earlier ordinary-issue guard, shared non-cancelling per-PR concurrency group, order-independent hygiene merge, and stale-checklist behavior remain intact. Focused workflow validation passes 122/122 locally.

Required CI is still running on this exact head; this approval does not waive it. Merge only after every required check is green.

@Ingwannu
Ingwannu merged commit 3c24629 into dev Aug 6, 2026
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants