Skip to content

feat: propagate OAuth token check failure to conclusion job failure issue#44756

Merged
pelikhan merged 2 commits into
mainfrom
copilot/ensure-token-failure-propagation
Jul 10, 2026
Merged

feat: propagate OAuth token check failure to conclusion job failure issue#44756
pelikhan merged 2 commits into
mainfrom
copilot/ensure-token-failure-propagation

Conversation

Copilot AI commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

When a workflow is configured with an OAuth token (gho_...), the activation job fails at check-oauth-tokens but the conclusion job never ran — leaving the user with no actionable feedback. The conclusion job condition only fired when agent.result != 'skipped' or specific activation guardrails were set; OAuth token failure was neither.

Changes

  • check_oauth_tokens.sh — Write oauth_token_check_failed=true to $GITHUB_OUTPUT before exit 1 so the output survives the step failure
  • compiler_activation_job_builder.go — Add oauth_token_check_failed to activation job outputs, referencing the new step output
  • notify_comment_conclusion_helpers.go — Extend the conclusion job if condition with || needs.activation.outputs.oauth_token_check_failed == 'true'; pass GH_AW_OAUTH_TOKEN_CHECK_FAILED to the handle_agent_failure step
  • handle_agent_failure.cjs — Parse the new env var, add oauth_token_check_failed failure category, add buildOAuthTokenCheckFailedContext(), include in both issue/comment template renders and the early-return guard
  • oauth_token_check_failed.md (new) — Error message template with remediation steps (create fine-grained PAT, update secret)
  • agent_failure_issue.md / agent_failure_comment.md — Add {oauth_token_check_failed_context} placeholder between {lockdown_check_failed_context} and {stale_lock_file_failed_context}
  • Golden files + 256 recompiled workflows

Copilot AI and others added 2 commits July 10, 2026 14:43
…ssue

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…ure propagation

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI requested a review from pelikhan July 10, 2026 14:56
@pelikhan pelikhan marked this pull request as ready for review July 10, 2026 15:01
Copilot AI review requested due to automatic review settings July 10, 2026 15:01
@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

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

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

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

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

This pull request ensures that when the activation job fails due to detecting an OAuth token (gho_...) in configured secrets, that failure signal is propagated so the conclusion job still runs and produces an actionable failure issue/comment with remediation guidance.

Changes:

  • Persist oauth_token_check_failed=true to $GITHUB_OUTPUT before failing the OAuth token check step so downstream jobs can detect the failure.
  • Plumb oauth_token_check_failed through activation job outputs into the conclusion job condition and into the failure handler env/context.
  • Add a dedicated remediation template (oauth_token_check_failed.md) and wire it into the agent failure issue/comment rendering; recompile updated .lock.yml workflows.
Show a summary per file
File Description
actions/setup/sh/check_oauth_tokens.sh Writes an output flag before exiting non-zero so the step failure can be detected by downstream job logic.
pkg/workflow/compiler_activation_job_builder.go Exposes oauth_token_check_failed as an activation job output derived from the check-oauth-tokens step output.
pkg/workflow/compiler_activation_jobs_test.go Adds unit coverage asserting the activation job exports the new oauth_token_check_failed output reference.
pkg/workflow/notify_comment_conclusion_helpers.go Ensures the conclusion job runs when OAuth token check fails and passes GH_AW_OAUTH_TOKEN_CHECK_FAILED into the failure handler.
actions/setup/js/handle_agent_failure.cjs Adds a new failure category + context builder and injects {oauth_token_check_failed_context} into rendered issue/comment templates and guard logic.
actions/setup/md/oauth_token_check_failed.md New remediation template shown in the failure issue/comment when an OAuth token is detected.
actions/setup/md/agent_failure_issue.md Adds {oauth_token_check_failed_context} placeholder to the issue template.
actions/setup/md/agent_failure_comment.md Adds {oauth_token_check_failed_context} placeholder to the comment template.
.github/workflows/*.lock.yml (many files) Recompiled workflows to include the new activation output, updated conclusion-job if condition, and new env var wiring.
.changeset/patch-propagate-oauth-token-check-failure.md Documents the patch-level change in behavior for release notes.

Review details

Tip

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

  • Files reviewed: 270/270 changed files
  • Comments generated: 0
  • Review effort level: Low

@github-actions github-actions Bot mentioned this pull request Jul 10, 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.

Review: OAuth Token Check Failure Propagation

The implementation is correct and well-structured. It follows the existing patterns for activation guardrail failures (lockdown check, stale lock file) consistently across all layers:

  • check_oauth_tokens.sh: correctly writes output before exit 1 so the value survives step failure
  • compiler_activation_job_builder.go: step ID check-oauth-tokens matches the step definition
  • notify_comment_conclusion_helpers.go: activationGuardrailsFailed condition correctly ORs in the new check; env var propagation follows the pattern
  • handle_agent_failure.cjs: early-return guard, title, category, context builder, template rendering, and module export are all wired consistently
  • oauth_token_check_failed.md: clear remediation template with {run_url} placeholder
  • Tests cover the new buildOAuthTokenCheckFailedContext function thoroughly

No blocking issues found.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · 38.8 AIC · ⌖ 4.34 AIC · ⊞ 4.8K

@pelikhan pelikhan merged commit 99cbea1 into main Jul 10, 2026
82 of 105 checks passed
@pelikhan pelikhan deleted the copilot/ensure-token-failure-propagation branch July 10, 2026 15:10

@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 on two test coverage gaps; no blocking issues.

📋 Key Themes & Highlights

Key Themes

  • Signal propagation is correct end-to-end: The fix properly wires oauth_token_check_failed from check_oauth_tokens.sh → activation job output → conclusion job if condition → GH_AW_OAUTH_TOKEN_CHECK_FAILED env var → handle_agent_failure.cjs. The pattern is consistent with the existing lockdown_check_failed and stale_lock_file_failed peers.
  • Two test coverage gaps identified: (1) buildConclusionJobCondition has no unit test asserting the compiled if string includes oauth_token_check_failed; (2) the JS failure handler has no test asserting the absent-env-var-means-false default. Neither is a blocker, but both would prevent silent regression.

Positive Highlights

  • check_oauth_tokens.sh correctly writes the output before exit 1, so the signal is available to downstream jobs
  • ✅ The === 'true' guard in handle_agent_failure.cjs safely handles absent values
  • ✅ Remediation template (oauth_token_check_failed.md) is clear and actionable
  • ✅ The JS tests added for buildOAuthTokenCheckFailedContext are thorough
  • ✅ Go test for the activation job output wiring is in place

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

oauthTokenCheckFailed := BuildEquals(BuildPropertyAccess(fmt.Sprintf("needs.%s.outputs.oauth_token_check_failed", constants.ActivationJobName)), BuildStringLiteral("true"))
staleLockFileFailed := BuildEquals(BuildPropertyAccess(fmt.Sprintf("needs.%s.outputs.stale_lock_file_failed", constants.ActivationJobName)), BuildStringLiteral("true"))
activationGuardrailsFailed := BuildOr(lockdownCheckFailed, staleLockFileFailed)
activationGuardrailsFailed := BuildOr(lockdownCheckFailed, BuildOr(oauthTokenCheckFailed, staleLockFileFailed))

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.

[/tdd] The buildConclusionJobCondition function now includes oauth_token_check_failed in activationGuardrailsFailed, but there is no unit test asserting the compiled if string contains this signal.\n\n

\n💡 Suggested test\n\nAdd a test alongside the existing activation output test:\n\ngo\nfunc TestBuildConclusionJobCondition_OAuthTokenCheckFailed(t *testing.T) {\n data := \&WorkflowData{Name: "Test", MarkdownContent: "# Test\n\nContent"}\n cond := buildConclusionJobCondition(data, "agent", nil)\n rendered := RenderCondition(cond)\n assert.Contains(t, rendered, "oauth_token_check_failed",\n "conclusion if condition should fire when OAuth token check fails")\n}\n\n\nWithout this, a future refactor could silently drop the signal — exactly the regression this PR was created to prevent.\n\n
\n\n@copilot please address this.

// OAuth token check failure from the activation job — set when check_oauth_tokens.sh detects
// a gho_... OAuth token in COPILOT_GITHUB_TOKEN, GH_AW_GITHUB_TOKEN, or GH_AW_GITHUB_MCP_SERVER_TOKEN.
// The agent is skipped in this case; the conclusion job runs to surface remediation guidance.
const hasOAuthTokenCheckFailed = process.env.GH_AW_OAUTH_TOKEN_CHECK_FAILED === "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 GH_AW_OAUTH_TOKEN_CHECK_FAILED env var is only passed to the conclusion job when needs.activation.outputs.oauth_token_check_failed is 'true'. If the activation job itself is skipped (e.g. due to a runner setup failure before this step), the output would be absent rather than false — the === 'true' guard in handle_agent_failure.cjs handles this correctly. This is fine, but worth a comment in the test to lock the expectation.\n\n

\n💡 Suggested assertion in JS test\n\nIn handle_agent_failure.test.cjs, add a test covering the missing env var case:\n\njs\nit('treats missing GH_AW_OAUTH_TOKEN_CHECK_FAILED env var as false', () => {\n delete process.env.GH_AW_OAUTH_TOKEN_CHECK_FAILED;\n // Should not trigger oauth_token_check_failed handling\n expect(process.env.GH_AW_OAUTH_TOKEN_CHECK_FAILED === 'true').toBe(false);\n});\n\n\nThis pins the safe default and avoids future confusion if someone changes the absent-value handling.\n\n
\n\n@copilot please address this.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

⚠️ Test Quality Score: 73/100 — Acceptable

Analyzed 6 test(s): 5 design, 1 implementation, 0 violation(s).

📊 Metrics (6 tests)
Metric Value
Analyzed 6 (Go: 1, JS: 5)
✅ Design 5 (83%)
⚠️ Implementation 1 (17%)
Edge/error coverage 2 (33%)
Duplicate clusters 0
Inflation No (JS 1.43:1, Go N/A)
🚨 Violations 0
Test File Classification Issues
TestBuildActivationJob_OAuthTokenCheckFailedOutput pkg/workflow/compiler_activation_jobs_test.go:403 design_test None
returns empty string when check did not fail handle_agent_failure.test.cjs:1913 design_test None
returns formatted context when OAuth token check failed handle_agent_failure.test.cjs:1917 implementation_test Weak assertion (toBeTruthy only)
includes OAuth token detection message handle_agent_failure.test.cjs:1922 design_test None
includes fine-grained PAT replacement guidance handle_agent_failure.test.cjs:1928 design_test None
includes run URL link handle_agent_failure.test.cjs:1935 design_test None
⚠️ Flagged Tests (1)

returns formatted context when OAuth token check failed (handle_agent_failure.test.cjs:1917) — implementation_test. Only asserts toBeTruthy() and length > 0, which verifies that something is returned but not what it contains. Consider adding a toContain assertion for a key expected string (e.g., OAuth Token) to make this a genuine behavioral assertion. The following three tests do validate specific content, so this test adds minimal unique value.

Verdict

Passed. 17% implementation tests (threshold: 30%). The 6 new tests cover the OAuth token check failure propagation feature well — 5 are design tests verifying behavioral contracts. One JS test (returns formatted context when OAuth token check failed) uses a weak toBeTruthy assertion and could be strengthened or merged into adjacent content-assertion tests.

References:

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • awmgmcpg

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

🧪 Test quality analysis by Test Quality Sentinel · 42.6 AIC · ⌖ 13.7 AIC · ⊞ 6.8K ·
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.

✅ Test Quality Sentinel: 73/100. 17% implementation tests (threshold: 30%).

@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 — one high-severity correctness issue, plus defensive hardening needed

The overall approach is sound: writing oauth_token_check_failed=true to GITHUB_OUTPUT before exit 1, propagating it through activation job outputs, extending the conclusion job condition, and threading the new env var into handle_agent_failure.cjs is all correct. However, there is one high-severity issue that can silently defeat the entire mechanism.

🔴 Blocking issue

GITHUB_OUTPUT write can be silently skipped (check_oauth_tokens.sh line 59): the $GITHUB_STEP_SUMMARY redirect at line 45 runs first under set -e. If that write fails (unset variable, read-only path, test harness without GHA environment), the script aborts before the GITHUB_OUTPUT write, the output is never set, the conclusion job condition evaluates false, and the user receives no actionable feedback — exactly the regression this PR exists to fix.

Fix: move echo "oauth_token_check_failed=true" >> "$GITHUB_OUTPUT" to before the summary block, or add || true on the summary redirect.

🟡 Non-blocking: defensive guard gaps in handle_agent_failure.cjs

The hasCompletedDespiteJobFailure guard (line 3115) and hasOnlyNoopOutputs guard (line 3105) do not explicitly exclude hasOAuthTokenCheckFailed. Both are safe today because the agent is skipped when the OAuth check fails, so those paths are unreachable. However, this relies on implicit coupling that is non-obvious and fragile against future step-ordering changes. Adding && !hasOAuthTokenCheckFailed to both guards would make the intent explicit.

🔎 Code quality review by PR Code Quality Reviewer · 176.3 AIC · ⌖ 4.67 AIC · ⊞ 5.4K
Comment /review to run again

Comments that could not be inline-anchored

actions/setup/sh/check_oauth_tokens.sh:59

GITHUB_OUTPUT write silently skipped if GITHUB_STEP_SUMMARY write fails under set -e: the redirect at line 45 runs before line 59; if $GITHUB_STEP_SUMMARY is unset/invalid, set -e aborts the script before oauth_token_check_failed=true is written — conclusion job gets no signal and the user sees no failure issue.

<details>
<summary>💡 Suggested fix</summary>

Write the output flag first, then guard the summary write with || true:

if [[ &quot;$token_value&quot; == gho_* ]]; then…

</details>

<details><summary>actions/setup/js/handle_agent_failure.cjs:3115</summary>

**`hasCompletedDespiteJobFailure` early-return guard does not exclude `hasOAuthTokenCheckFailed`**: if step ordering ever changes so the agent runs after an OAuth check failure, this guard would suppress the failure issue silently.

&lt;details&gt;
&lt;summary&gt;💡 Suggested fix&lt;/summary&gt;

Add the guard explicitly for defensive consistency with the other exclusions:

```js
if (hasCompletedDespiteJobFailure &amp;&amp; !hasReportIncomplete &amp;&amp; !hasCacheMissMisconfiguration &amp;&amp; !hasOAuthTokenCheckFailed) {

Simila…

@github-actions

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.82.8

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.

3 participants