fix: typed error for workflows-scope rejection in review/fallback branch push#42001
Conversation
- Fix review branch push path: use exec.getExecOutput(ignoreReturnCode:true) to capture stderr, detect GitHub's "workflows scope" rejection, return typed error_type:"workflows_scope_required" with actionable message pointing to allow-workflows config - Fix fallback (non-fast-forward) branch push path: same detection and typed error for workflows scope rejection - Add 3 unit tests in threat detection: review branch push describe block - covering the timeout variant, backtick variant, and generic push failure cases - Ran make fmt-cjs, make lint-cjs, make agent-report-progress — all pass Changes in: - actions/setup/js/push_to_pull_request_branch.cjs - actions/setup/js/push_to_pull_request_branch.test.cjs Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…ror helpers - Extracted detection logic into isWorkflowsScopeRejection() helper with case-insensitive matching - Extracted error construction into buildWorkflowsScopeError() helper to eliminate duplication - Both review branch and fallback branch push paths now use shared helpers - Tests still pass (97/97), fmt-cjs and lint-cjs clean, make agent-report-progress passes Changes in: - actions/setup/js/push_to_pull_request_branch.cjs - actions/setup/js/push_to_pull_request_branch.test.cjs Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…or message - Added null/falsy guard to isWorkflowsScopeRejection() to prevent potential TypeError on undefined input - Updated generic push failure test to use a realistic git authentication error URL - All 97 tests pass, fmt-cjs, lint-cjs, make agent-report-progress all pass Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
The fallback (non-fast-forward) branch push now returns the typed error_type:'workflows_scope_required' object directly, consistent with the review branch path. Previously it threw the error message string, losing the structured type field through the catch handler. Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…or error messages Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
Great work on this fix! 🎉 The typed error propagation for The PR is well-structured: the root cause is clearly explained, both the review-branch push and the non-fast-forward fallback paths are covered, and the three new test cases in This looks ready for review. 🚀
|
PR Triage — Run §28315307719
|
|
✅ PR Code Quality Reviewer completed the code quality review. |
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. No ADR enforcement needed: PR #42001 does not have the 'implementation' label and has 0 new lines of code in business logic directories (threshold: 100). |
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅ |
|
✅ Test Quality Sentinel completed test quality analysis. TQS analysis for PR #42001 already completed in this workflow run: comment posted and APPROVE review submitted (score 100/100, 3 design tests, 0 violations). No further action needed. |
There was a problem hiding this comment.
Pull request overview
Improves push_to_pull_request_branch’s diagnostics when GitHub rejects a fallback/review-branch git push due to missing workflows permission, returning a typed error and logging actionable remediation steps instead of a generic push failure.
Changes:
- Add
isWorkflowsScopeRejection(stderr)andbuildWorkflowsScopeError(...)helpers to detect and report missing-workflows-scope push rejections. - Switch review-branch and non-fast-forward fallback pushes from
exec.exec()toexec.getExecOutput(..., { ignoreReturnCode: true })to capture stderr and emit a typed failure. - Add tests covering both known rejection variants plus a generic push failure case.
Show a summary per file
| File | Description |
|---|---|
| actions/setup/js/push_to_pull_request_branch.cjs | Detects “workflows scope required” push rejections and returns a typed, actionable error from review/fallback push paths. |
| actions/setup/js/push_to_pull_request_branch.test.cjs | Adds regression tests for typed error behavior for review-branch push failures. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 2/2 changed files
- Comments generated: 3
- Review effort level: Low
🧪 Test Quality Sentinel Report✅ Test Quality Score: 100/100 — Excellent
📊 Metrics & Test Classification (3 tests analyzed)
Go: 0 ( Notes on mocking: All three tests use Verdict
|
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /tdd and /diagnose — the core fix is sound, with a meaningful test coverage gap for the fallback branch path.
📋 Key Themes & Highlights
Key Themes
- Fallback branch tests missing:
isWorkflowsScopeRejectionwas added to both push paths, but only the review-branch path has new test coverage. Thereturn buildWorkflowsScopeError("Fallback branch", core)code path is entirely untested. - Timeout pattern not isolated: The "timeout variant" test input matches both
includes()branches simultaneously, so the timeout-only code path inisWorkflowsScopeRejectionis never exclusively exercised. - Mock not restored:
mockExec.getExecOutputis overridden in each test but never cleaned up — worth confirming or documenting vitest's reset behaviour for this shared object. - Timeout pattern breadth: The second
includes()check omits the wordworkflows, making it slightly broader than the first; low practical risk but easy to tighten.
Positive Highlights
- ✅
exec.exec→exec.getExecOutput+ignoreReturnCode: trueis exactly the right pattern to capture stderr without relying on a thrown exception - ✅ Typed
error_type: "workflows_scope_required"with a directreturnthat bypasses the outer catch is a clean, intentional design - ✅
buildWorkflowsScopeErroractionable messages pointing operators toallow-workflows+ GitHub App config are well-crafted - ✅ Null-safe, case-insensitive matching in
isWorkflowsScopeRejectionis defensive - ✅ Test 3 (generic auth failure → no typed error) provides solid negative coverage
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 86.9 AIC · ⌖ 10.2 AIC · ⊞ 6.6K
|
@copilot please run the
|
… add fallback-branch scope test
- Forward `options` argument in all three getExecOutput wrappers in the
threat-detection describe block so option-dependent behavior (env, cwd,
ignoreReturnCode) is faithfully preserved when falling through to the
original mock.
- Add an inner beforeEach/afterEach pair within describe("threat detection:
review branch push") that saves and restores mockExec.getExecOutput, so
the mock is explicitly reset between tests.
- Isolate the timeout-only variant: the first test now uses a stderr that
matches only the "workflow can be created or updated due to timeout"
pattern, not the combined timeout + backtick message, so the timeout path
is tested in isolation.
- Add a new test in "repository state scenarios" that exercises the
fallback-branch push path (non-fast-forward -> checkout -b -> getExecOutput
push) returning `workflows_scope_required` when the fallback push is
rejected for missing workflows scope.
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
When threat detection forces a review-branch push and the branch contains
.github/workflows/*.lock.ymlchanges, GitHub's pre-receive hook rejects the push for missingworkflowsscope. The previous code usedexec.exec(), which swallows stderr — the agent received onlygit exit code 1, logged nothing actionable, and silently discarded the changeset commit.Changes
push_to_pull_request_branch.cjsisWorkflowsScopeRejection(stderr)— null-safe, case-insensitive helper matching GitHub's two rejection variants:`workflows` scope may be requiredworkflow can be created or updated due to timeoutbuildWorkflowsScopeError(context, core)— emits twocore.error()messages with remediation steps and returns{ success: false, error_type: "workflows_scope_required", error: "..." }exec.exec→exec.getExecOutput({ ignoreReturnCode: true })so stderr is captured; matched rejectionsreturn buildWorkflowsScopeError(...)directly (bypasses the outercatchthat would striperror_type)push_to_pull_request_branch.test.cjs— 3 new tests indescribe("threat detection: review branch push"):error_type: "workflows_scope_required"error_type: "workflows_scope_required"The proper long-term fix is
push-to-pull-request-branch.allow-workflows: truewith a GitHub App carryingworkflows: write— the error messages now explicitly direct operators there.