Skip to content

Fail fast on approve_workflow_run permission denials to stop safe-outputs API storm - #55957

Merged
pelikhan merged 5 commits into
mainfrom
copilot/aw-failures-fix-approve-workflow-run
Aug 26, 2026
Merged

Fail fast on approve_workflow_run permission denials to stop safe-outputs API storm#55957
pelikhan merged 5 commits into
mainfrom
copilot/aw-failures-fix-approve-workflow-run

Conversation

Copilot AI commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

PR Sous Chef began attempting approve_workflow_run on fork PR runs with a token that lacks approval permissions, producing Resource not accessible by personal access token and repeatedly burning API quota. This change makes permission-class approval failures non-fatal and short-circuits subsequent approval attempts in the same safe-outputs pass.

  • Approval error classification (handler-level)

    • Added explicit detection for permission-denied approval errors (resource not accessible).
    • Converts that outcome from hard failure to skipped with a dedicated reason code: APPROVE_WORKFLOW_RUN_PERMISSION_DENIED.
  • Fail-fast guard to prevent repeated expensive attempts

    • Introduced per-handler run state (approvePermissionDenied).
    • After the first permission denial, later approve_workflow_run messages return immediately as skipped (no additional API approval attempts).
  • Behavioral contract coverage

    • Added focused tests for:
      • permission-denied approval returning skipped/non-fatal result.
      • subsequent messages being short-circuited after first permission denial.
if (isPermissionDeniedError(errorMessage)) {
  approvePermissionDenied = true;
  return {
    success: false,
    skipped: true,
    reasonCode: "APPROVE_WORKFLOW_RUN_PERMISSION_DENIED",
    reason,
    error: reason,
  };
}

Generated by 👨‍🍳 PR Sous Chef · pi · gpt54 · 18 AIC · ⌖ 8.17 AIC · ⊞ 8.7K ·
Comment /souschef to run again

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix approve_workflow_run for fork PRs due to access token issue Fail fast on approve_workflow_run permission denials to stop safe-outputs API storm Aug 26, 2026
Copilot AI requested a review from pelikhan August 26, 2026 06:33
@pelikhan
pelikhan marked this pull request as ready for review August 26, 2026 06:36
Copilot AI balanced review requested due to automatic review settings August 26, 2026 06:36
@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

Test Quality Sentinel skipped because pre-fetch PR data was unavailable: unable to fetch test file diff

🧪 Test quality analysis by Test Quality Sentinel

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Ponytail Reviewer completed successfully!

Lean already. Ship.

Generated by Ponytail Reviewer for #55957

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check. See the comment below for the result and any generated ADR draft.

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

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

🔎 Code quality review by PR Code Quality Reviewer

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

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

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

@github-actions

Copy link
Copy Markdown
Contributor

Comment Memory

reviewed_at: 2026-08-26T00:00:00Z
review_event: REQUEST_CHANGES
top_themes:
  - global permission-denied latch can suppress unrelated future approvals
files_reviewed:
  - actions/setup/js/approve_workflow_run.cjs
  - actions/setup/js/approve_workflow_run.test.cjs
comment_count: 0

Note

This comment is managed by comment memory.

It stores persistent context for this thread in the code block at the top of this comment.
Edit only the text inside the backtick fences; workflow metadata and the footer are regenerated automatically.

Learn more about comment memory

🔎 Code quality review by PR Code Quality Reviewer · pi · gpt54 · 4.16 AIC · ⌖ 6.87 AIC · ⊞ 7K ·
Comment /review to run again

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

Request changes

This change turns the first approval permission failure into a global skip for the rest of the handler instance. That avoids the API storm, but it also drops all later approval messages without even checking whether they target a different repository/token context where approval would succeed.

Blocking theme

The new approvePermissionDenied latch is process-wide state for the handler, not state scoped to the repository/token/run that actually failed. After one Resource not accessible response, every subsequent approve_workflow_run message is rejected before any per-run validation or API read happens. If a single safe-outputs pass can process approvals across multiple installations/repos/tokens, one transiently unsupported approval poisons unrelated approvals and silently leaves valid runs unapproved.

That needs to be scoped more narrowly (for example per token/repo capability) or derived from configuration up front instead of short-circuiting all later messages.

🔎 Code quality review by PR Code Quality Reviewer · pi · gpt54 · 4.16 AIC · ⌖ 6.87 AIC · ⊞ 7K
Comment /review to run again

@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 /codebase-design — commenting with a few targeted suggestions, no blocking issues.

📋 Key Themes & Highlights

Key Themes

  • Error matching precision: isPermissionDeniedError matches on a partial substring; tightening it reduces the risk of false positives or silent misses if GitHub changes the error wording.
  • Closure lifecycle: approvePermissionDenied flag lifecycle is correct for the intended one-call-per-pass contract but is undocumented, which could confuse future maintainers.
  • processedCount ordering: decrement-before-guard pattern is subtly fragile.

Positive Highlights

  • ✅ Fail-fast guard is a clean, simple closure — no shared global state.
  • ✅ Tests cover both the initial denial and the short-circuit path.
  • reasonCode gives callers a stable string to key on.
  • skipped: true (non-fatal) is the right semantic for a permission denial.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · sonnet46 · 26.2 AIC · ⌖ 10.1 AIC · ⊞ 7.6K
Comment /matt to run again

Comment thread actions/setup/js/approve_workflow_run.cjs
Comment thread actions/setup/js/approve_workflow_run.cjs
Comment thread actions/setup/js/approve_workflow_run.cjs

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

Review: Fail fast on approve_workflow_run permission denials

The approach is sound — a closure-scoped flag (approvePermissionDenied) short-circuits all subsequent calls after a permission error, preventing an API storm. Two issues worth addressing:

Blocking

processedCount off-by-one on permission denial
In the catch block, processedCount-- fires before the permission check. When the denial path is taken, the count is decremented even though the run was skipped (not failed processing). If maxCount depends on this counter, downstream runs may be over-processed.

Non-blocking

isPermissionDeniedError string matching is narrow
Only "resource not accessible" is matched. Octokit errors for 403 responses include other messages ("Must have admin rights", plain 403 status). Checking error.status === 403 as a fallback would make the guard more resilient.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · copilot · sonnet46 · 22.2 AIC · ⌖ 9.31 AIC · ⊞ 6.2K

Comments that could not be inline-anchored

actions/setup/js/approve_workflow_run.cjs:17

[harden] Narrow permission-error detection may miss other 403 variants

The current check only matches &quot;resource not accessible&quot;. GitHub also returns permission-related errors that don't contain this string, for example &quot;Must have admin rights to Repository.&quot; or a raw 403 HTTP status code on the Octokit error object.

A more robust guard would also inspect the HTTP status if available:

function isPermissionDeniedError(message, status) {
  const normalized = String(message || &quot;&quot;

</details>

<details><summary>actions/setup/js/approve_workflow_run.cjs:396</summary>

**[harden] `processedCount--` is decremented before the permission check, leaving the count incorrect**

In the catch block at line ~378–396:

```js
} catch (error) {
  processedCount--;                        // decremented here
  const errorMessage = getErrorMessage(error);
  if (isPermissionDeniedError(errorMessage)) {
    approvePermissionDenied = true;
    ...
    return { success: false, skipped: true, ... };
  }
  throw error;
}

When a permission denial is caught, processedCount h…

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

Adds handler-level circuit breaking for workflow-run approval permission failures.

Changes:

  • Detects permission-denied approval errors.
  • Skips subsequent approval attempts in the same pass.
  • Adds focused behavioral tests.
Show a summary per file
File Description
actions/setup/js/approve_workflow_run.cjs Adds permission classification and fail-fast state.
actions/setup/js/approve_workflow_run.test.cjs Tests skip and short-circuit behavior.

Review details

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread actions/setup/js/approve_workflow_run.cjs
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

gh-aw-pr-sous-chef
@copilot PR Sous Chef triage: this PR still needs a forward-progress pass before maintainer investigation is likely to be productive.

Please do one focused follow-up pass:

  • address the blocking review feedback and push the fixes
  • failed checks to review: none currently; focus on the requested review changes
  • refresh the branch if needed and use the pr-finisher skill before handing back for review

Run: https://github.com/github/gh-aw/actions/runs/32943696113

Generated by 👨🍳 PR Sous Chef

Generated by 👨‍🍳 PR Sous Chef · pi · gpt54 · 18 AIC · ⌖ 8.17 AIC · ⊞ 8.7K ·
Comment /souschef to run again

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Aug 26, 2026

Copy link
Copy Markdown
Contributor Author

gh-aw-pr-sous-chef
@copilot PR Sous Chef triage: this PR still needs a forward-progress pass before maintainer investigation is likely to be productive.
...

Pushed follow-up commit 70f090b addressing the review feedback: tighter permission-denied classification, handler lifecycle documentation, and safer approval count accounting with expanded tests. This remains a mitigation unless maintainers either provision an approval-capable actions: write credential or update the PR body so it no longer closes #55907.

@github-actions

Copy link
Copy Markdown
Contributor

Triage update: Category: bug | Risk: high | Score: 64/100 (impact 36 + urgency 18 + quality 10) | Action: fast_track | Batch: workflow-runtime

Generated by 🔧 PR Triage Agent · copilot · mai10 · 17.1 AIC · ⌖ 2.78 AIC · ⊞ 15.6K ·

@github-actions

Copy link
Copy Markdown
Contributor

Triage update: Category: bug | Risk: high | Score: 64/100 (impact 36 + urgency 18 + quality 10) | Action: fast_track | Batch: workflow-runtime

Generated by 🔧 PR Triage Agent · copilot · mai10 · 17.1 AIC · ⌖ 2.78 AIC · ⊞ 15.6K ·

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

$gh-aw-pr-sous-chef
@copilot PR Sous Chef triage: this PR still needs a forward-progress pass before maintainer investigation is likely to be productive.

Please do one focused follow-up pass:

  • refresh the branch if needed and use the pr-finisher skill before handing back for review

Run: https://github.com/github/gh-aw/actions/runs/32972030991

Generated by 👨‍🍳 PR Sous Chef · pi · gpt54 · 5.54 AIC · ⌖ 8.13 AIC · ⊞ 6.3K ·
Comment /souschef to run again

…ix-approve-workflow-run

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Aug 26, 2026

Copy link
Copy Markdown
Contributor Author

$gh-aw-pr-sous-chef
@copilot PR Sous Chef triage: this PR still needs a forward-progress pass before maintainer investigation is likely to be productive.
...

Completed the focused PR-finisher pass and pushed branch refresh commit 86aaba2d onto latest main. Local validation passed (make fmt, make lint, make test-unit, make test, make recompile, make agent-report-progress); CI on the new agent-pushed head has no check runs yet and needs a maintainer re-trigger before merge.

@pelikhan
pelikhan merged commit 2fb106f into main Aug 26, 2026
@pelikhan
pelikhan deleted the copilot/aw-failures-fix-approve-workflow-run branch August 26, 2026 13:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[aw-failures] [P1] PR Sous Chef: approve_workflow_run fails 'Resource not accessible by personal access token' on fork PRs

4 participants