Skip to content

fix: restrict Q workflow triggers to eliminate action_required from PR events#45745

Merged
pelikhan merged 2 commits into
mainfrom
copilot/fix-q-workflow-action-required-issue
Jul 15, 2026
Merged

fix: restrict Q workflow triggers to eliminate action_required from PR events#45745
pelikhan merged 2 commits into
mainfrom
copilot/fix-q-workflow-action-required-issue

Conversation

Copilot AI commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

The Q workflow has been 100% action_required for 10+ days. Root cause: GitHub's bot-approval mechanism fires at the platform level when a workflow is triggered by pull_request or pull_request_review_comment events — producing action_required with 0 jobs/0 duration before any steps run. PR #43527's prompt-level fix had no effect because this is an infrastructure trigger issue.

Changes

  • q.md — Adds events: [issues, issue_comment, pull_request_comment, discussion, discussion_comment] to slash_command:, dropping pull_request and pull_request_review_comment from the trigger set.

  • q.lock.yml — Recompiled: removes both event types from on:, updates activation.if and pre_activation.if consistently.

  • Compiler fix: expression_builder.gobuildCommentAuthorAssociationCondition() previously always emitted guards for both issue_comment and pull_request_review_comment regardless of which events are active, producing dead-code conditions. Now accepts activeCommentEvents []string and only emits guards for events actually present in on:.

    // Before — always emitted both clauses even if pull_request_review_comment isn't a trigger
    (github.event_name != 'issue_comment' && github.event_name != 'pull_request_review_comment') || ...
    
    // After — only emits the clause for the active event
    github.event_name != 'issue_comment' || ...
  • Compiler fix: compiler_pre_activation_job.go — Adds activeCommentEventsInOn() helper to extract active comment events from the compiled on: string; passes them to the updated buildCommentAuthorAssociationCondition().

…triggers

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix Q workflow remaining 100% action required after PR #43527 fix: restrict Q workflow triggers to eliminate action_required from PR events Jul 15, 2026
Copilot AI requested a review from pelikhan July 15, 2026 14:32
@pelikhan
pelikhan marked this pull request as ready for review July 15, 2026 14:34
Copilot AI review requested due to automatic review settings July 15, 2026 14:34
@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR #45745 does not have the 'implementation' label and has only 65 new lines of code in business logic directories (threshold: 100).

@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

No test files were added or modified in this PR. Test Quality Sentinel skipped.

Copilot AI 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.

Pull request overview

Restricts Q workflow triggers to avoid action_required runs and aligns generated authorization guards with active events.

Changes:

  • Removes problematic pull request event triggers.
  • Generates event-specific author-association guards.
  • Recompiles the Q workflow lockfile.
Show a summary per file
File Description
pkg/workflow/expression_builder.go Builds guards only for active comment events.
pkg/workflow/compiler_pre_activation_job.go Detects active comment triggers.
.github/workflows/q.md Restricts Q slash-command events.
.github/workflows/q.lock.yml Applies the recompiled trigger configuration.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Medium

// event detection cannot be performed reliably at compile time.
if needsPermissionCheck && hasCommentEventInOn(data.On) && !botsContainExpression(data.Bots) && !strings.Contains(data.On, "${{") {
jobIfCondition = combinePreActivationIfCondition(RenderCondition(buildCommentAuthorAssociationCondition(data.Bots)), jobIfCondition)
jobIfCondition = combinePreActivationIfCondition(RenderCondition(buildCommentAuthorAssociationCondition(data.Bots, activeCommentEventsInOn(data.On))), jobIfCondition)
@github-actions github-actions Bot mentioned this pull request Jul 15, 2026

@github-actions github-actions 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.

The changes are correct and well-motivated. Removing pull_request and pull_request_review_comment triggers eliminates the platform-level action_required firings. The pull_request_comment alias in q.md correctly maps to issue_comment in GitHub Actions, so activeCommentEventsInOn returns only issue_comment and the simplified guard is accurate. The buildCommentAuthorAssociationCondition refactor cleanly emits guards only for active trigger events.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · 24 AIC · ⌖ 4.27 AIC · ⊞ 5K

@github-actions github-actions 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.

Skills-Based Review 🧠

Applied /diagnosing-bugs and /tdd — commenting, no blocking issues.

📋 Key Themes & Highlights

Root Cause

The fix is correct and well-reasoned: pull_request / pull_request_review_comment events trigger GitHub's bot-approval mechanism at the platform level before any job runs, causing 100% action_required failures. Removing them from the trigger set is the right fix.

Compiler Fix Quality

The change to buildCommentAuthorAssociationCondition is clean — accepting activeCommentEvents []string and emitting guards only for present events eliminates the dead-code conditions precisely.

Positive Highlights

  • ✅ Good use of slices.Contains for readable guard logic
  • activeCommentEventsInOn helper is well-commented and consistent with the existing hasCommentEventInOn pattern
  • ✅ PR description clearly explains the root cause and the before/after expression difference

Suggestions (non-blocking)

  1. Missing regression test (see inline): the most important new behaviour — that issue_comment-only config drops pull_request_review_comment from the guard — has no dedicated test.
  2. Unreachable case 0 (see inline): silently emits an always-true permissive expression; better to panic or document the precondition.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 50.3 AIC · ⌖ 4.68 AIC · ⊞ 6.7K
Comment /matt to run again

switch len(notCommentTerms) {
case 0:
// No guarded comment events are active; the condition is always true.
notCommentEvent = BuildBooleanLiteral(true)

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.

[/diagnosing-bugs] The case 0 branch (BuildBooleanLiteral(true)) is unreachable in practice — this function is only called when hasCommentEventInOn() returns true, guaranteeing at least one active comment event. If that guard is ever relaxed, case 0 would silently emit a permissive always-true expression, bypassing the author-association check entirely.

💡 Suggestion

Make the invariant explicit with a panic to fail loudly rather than silently permitting all actors:

case 0:
    // Unreachable: callers only invoke this function when hasCommentEventInOn() is
    // true, so activeCommentEvents always has at least one entry.
    panic("buildCommentAuthorAssociationCondition: no active comment events")

Alternatively, add a doc comment on the function signature declaring the precondition.

@copilot please address this.

@github-actions github-actions 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.

Two issues to fix before merge

The core approach is sound — dropping pull_request/pull_request_review_comment triggers and emitting guards only for events actually in on: is correct. The YAML parsing via "<event>:" substring match is safe because data.On is always compiler-generated key-colon YAML (same pattern already used by hasCommentEventInOn).

🔴 Blocking findings

1. Fail-open case 0 in buildCommentAuthorAssociationCondition (expression_builder.go line 209)
When activeCommentEvents is empty the function returns BuildBooleanLiteral(true), which ORed with authorizedAssoc makes the whole guard trivially true — the author-association check is silently compiled away. The outer call-site gate (line 521) currently prevents this, but it's an undocumented precondition enforced at a distance. Any future caller passing an empty slice removes the security guard with no warning. The old code was fail-closed; the new code is fail-open here. The case 0 fallback should preserve the full guard.

2. Duplicated event name list (expression_builder.go line 194 + compiler_pre_activation_job.go lines 592–597)
guardedEvents inside buildCommentAuthorAssociationCondition and the strings.Contains checks in activeCommentEventsInOn independently hardcode the same two event names. Adding a third guarded event requires updating both sites; missing one silently drops the guard for the new event with no compile-time signal. A single shared package-level constant would fix this.

🔎 Code quality review by PR Code Quality Reviewer · 56.1 AIC · ⌖ 4.68 AIC · ⊞ 5.6K
Comment /review to run again

switch len(notCommentTerms) {
case 0:
// No guarded comment events are active; the condition is always true.
notCommentEvent = BuildBooleanLiteral(true)

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.

case 0 silently drops the security guard when activeCommentEvents is empty — any future caller passing an empty slice will compile away the author-association check with no error or warning.

💡 Detail and suggested fix

The outer gate in compiler_pre_activation_job.go (line 521) currently prevents this path, but that's an undocumented precondition enforced at a distance. If any future call site passes an empty slice (e.g. from a different compiler path, a refactor, or a test), the function silently returns BuildBooleanLiteral(true). When ORed with authorizedAssoc, the full expression short-circuits to true — the guard is entirely removed.

The old code was fail-closed: it always emitted the guard. The new code is fail-open for the empty-input case. Security controls should default to the more restrictive posture.

Suggested fix — preserve the full guard as the fallback:

case 0:
    // No active events supplied; stay fail-closed by emitting the full unconditional guard.
    notCommentEvent = BuildAnd(
        BuildNotEquals(BuildPropertyAccess("github.event_name"), BuildStringLiteral("issue_comment")),
        BuildNotEquals(BuildPropertyAccess("github.event_name"), BuildStringLiteral("pull_request_review_comment")),
    )

Or add a panic/error so misuse is caught at test time rather than deployed silently.

func buildCommentAuthorAssociationCondition(bots []string, activeCommentEvents []string) ConditionNode {
// Build "not equal" guards only for comment events that are active in this workflow.
// The canonical guarded events are issue_comment and pull_request_review_comment.
guardedEvents := []string{"issue_comment", "pull_request_review_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.

guardedEvents is a hidden dependency on a list maintained in two places — adding a third guarded event type requires updating both this list and activeCommentEventsInOn(), with no compile-time enforcement linking them.

💡 Detail and suggested fix

guardedEvents in buildCommentAuthorAssociationCondition (line 194) and the two strings.Contains checks in activeCommentEventsInOn (lines 592–597) independently hardcode the same event name set. If a developer adds e.g. workflow_run_comment to guardedEvents to guard a future event type, they must also add a corresponding strings.Contains in activeCommentEventsInOn or the new event will never appear in the active list and its guard will silently be omitted.

Suggested: define a single package-level var guardedCommentEvents = []string{"issue_comment", "pull_request_review_comment"} and drive both functions from it, so the two sites cannot diverge.

@pelikhan
pelikhan merged commit 0b0a890 into main Jul 15, 2026
74 of 85 checks passed
@pelikhan
pelikhan deleted the copilot/fix-q-workflow-action-required-issue branch July 15, 2026 14:55
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.82.10

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Q workflow: still 100% action_required after quality gate PR #43527 merged (Jul 5)

3 participants