Skip to content

threat-detection: fix strict-mode conclude failure writing no outputs - #50856

Merged
pelikhan merged 4 commits into
mainfrom
copilot/fix-threat-detection-output
Aug 6, 2026
Merged

threat-detection: fix strict-mode conclude failure writing no outputs#50856
pelikhan merged 4 commits into
mainfrom
copilot/fix-threat-detection-output

Conversation

Copilot AI commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Strict-mode (GH_AW_DETECTION_CONTINUE_ON_ERROR=false) failures in conclude_threat_detection.sh exited non-zero without writing any $GITHUB_OUTPUT, leaving detection_reason empty downstream. This caused infra/tooling failures to render to reviewers as [!CAUTION] agentic threat detected instead of a system error — the exact confusion #48940 fixed for the .cjs path, but never covered here.

Script fix (actions/setup/sh/conclude_threat_detection.sh)

  • Strict-mode missing-result-file path now writes conclusion=failure, success=false, reason=agent_failure to $GITHUB_OUTPUT before exit 1, so detection_reason is populated and correctly classified as a tooling failure downstream.
  • Both the warn and strict branches now export GH_AW_DETECTION_CONCLUSION / GH_AW_DETECTION_REASON to $GITHUB_ENV, matching setDetectionFailure in parse_threat_detection_results.cjs for consistency with later steps in the job.
echo "ERR_SYSTEM: ❌ ${result_message}"
echo "conclusion=failure"    >> "${GITHUB_OUTPUT}"
echo "success=false"         >> "${GITHUB_OUTPUT}"
echo "reason=agent_failure"  >> "${GITHUB_OUTPUT}"
if [ -n "${GITHUB_ENV:-}" ]; then
  echo "GH_AW_DETECTION_CONCLUSION=failure" >> "${GITHUB_ENV}"
  echo "GH_AW_DETECTION_REASON=agent_failure" >> "${GITHUB_ENV}"
fi
exit 1

Test coverage (pkg/workflow/threat_detection_conclude_script_test.go)

  • New test asserting strict-mode output/env vars on missing result file.
  • New test asserting continue-on-error mode also exports GH_AW_DETECTION_CONCLUSION / GH_AW_DETECTION_REASON to $GITHUB_ENV.

Run: https://github.com/github/gh-aw/actions/runs/31113572782> Generated by 👨‍🍳 PR Sous Chef · gpt54 · 17.2 AIC · ⊞ 8.3K ·

Comment /souschef to run again

…exit 1

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix threat detection strict mode failure outputs threat-detection: fix strict-mode conclude failure writing no outputs Aug 6, 2026
@pelikhan
pelikhan marked this pull request as ready for review August 6, 2026 12:46
Copilot AI balanced review requested due to automatic review settings August 6, 2026 12:46
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

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

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

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

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

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

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

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

Fixes strict-mode threat-detection failures so downstream reporting correctly identifies tooling errors.

Changes:

  • Writes failure outputs and environment variables before exiting.
  • Adds strict and continue-on-error regression tests.
  • Includes an unrelated agentic-workflows router update.
Show a summary per file
File Description
actions/setup/sh/conclude_threat_detection.sh Emits failure metadata for missing results.
pkg/workflow/threat_detection_conclude_script_test.go Tests output and environment propagation.
.github/skills/agentic-workflows/SKILL.md Adds an unrelated designer mapping entry.

Review details

Tip

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

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

- `.github/aw/debug-agentic-workflow.md`
- `.github/aw/dependabot.md`
- `.github/aw/deployment-status.md`
- `.github/aw/designer-mappings.md`
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

Test Quality Sentinel 🧪

PR: #50856 — "threat-detection: fix strict-mode conclude failure writing no outputs"
Score: 100/100 ✅ Excellent
Implementation Tests: 0% (all 2 new tests are design tests)

Summary

This PR adds 2 new integration tests that directly verify the behavioral fix: ensuring outputs are written to GITHUB_OUTPUT and GITHUB_ENV before the shell script exits in both strict mode and continue-on-error modes.

All new tests are high-value design tests with clear assertions covering both error and success paths. No mock libraries or forbidden patterns detected. Recommendation: Approve.


Coverage Analysis

New Tests (2)
Test Lines Purpose Assertions Quality
TestConcludeThreatDetectionScript_MissingResultStrictModeWritesOutputs 50–96 Verify outputs written before non-zero exit in strict mode 6 ✅ Design
TestConcludeThreatDetectionScript_MissingResultContinueOnErrorExportsEnv 98–129 Verify env vars exported in continue-on-error mode 3 ✅ Design

File: pkg/workflow/threat_detection_conclude_script_test.go

Test Assertions Breakdown

Test 1 — Strict Mode (exit 1 path)

  • Script exits with non-zero exit code ✓
  • GITHUB_OUTPUT contains conclusion=failure
  • GITHUB_OUTPUT contains success=false
  • GITHUB_OUTPUT contains reason=agent_failure
  • GITHUB_ENV contains GH_AW_DETECTION_CONCLUSION=failure
  • GITHUB_ENV contains GH_AW_DETECTION_REASON=agent_failure

Test 2 — Continue-on-Error (exit 0 path)

  • Script exits successfully (exit 0) ✓
  • GITHUB_ENV contains GH_AW_DETECTION_CONCLUSION=warning
  • GITHUB_ENV contains GH_AW_DETECTION_REASON=agent_failure

Production Changes Coverage

All 11 new lines in actions/setup/sh/conclude_threat_detection.sh are exercised:

  • Lines 40–44 (continue-on-error env exports) → Test 2
  • Lines 48–52 (strict-mode env exports) → Test 1

Quality Signals

Design contracts: Both tests verify user-visible output behavior
Edge cases: Strict mode (error) and continue-mode (success) paths both tested
No forbidden patterns: Real shell script execution (no gomock, testify/mock)
Clear assertions: All include descriptive failure messages
No duplication: Distinct scenarios with complementary coverage
Integration tests: Properly test shell script I/O semantics

Notes

  • Test file threat_detection_conclude_script_test.go lacks a //go:build tag (pre-existing, not added in this PR)
  • Test inflation ratio (~7.4:1) is acceptable for shell script integration tests due to environment setup overhead

Recommendation

APPROVE — Score: 100/100. All new tests are high-value design tests with comprehensive behavioral coverage. Zero implementation tests.

🧪 Test quality analysis by Test Quality Sentinel · haiku45 · 17.2 AIC · ⊞ 7.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.

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

Skills-Based Review 🧠

Applied /diagnosing-bugs and /tdd — approving with one minor suggestion.

📋 Key Themes & Highlights

Key Themes

  • Root cause properly addressed: the script now writes conclusion, success, and reason to $GITHUB_OUTPUT and exports GH_AW_DETECTION_CONCLUSION/GH_AW_DETECTION_REASON to $GITHUB_ENV before exit 1, matching the .cjs path from #48940.
  • Regression test coverage: two new tests pin the fixed behaviour for both strict-mode and continue-on-error paths. The strict-mode test is particularly valuable since it validates the previously-absent output writes.
  • Minor gap: TestConcludeThreatDetectionScript_MissingResultContinueOnErrorExportsEnv only asserts GITHUB_ENV; a note linking it to the existing MissingResultContinueOnError test (which covers GITHUB_OUTPUT) would make coverage intent obvious.

Positive Highlights

  • ✅ Symmetric fix — continue-on-error path gets GITHUB_ENV exports for consistency, not just strict mode
  • ✅ Guard [ -n "${GITHUB_ENV:-}" ] is appropriately defensive for local/test contexts
  • ✅ Tests follow the existing script-test pattern cleanly

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 21.5 AIC · ⊞ 7.1K
Comment /matt to run again

t.Fatalf("expected GH_AW_DETECTION_CONCLUSION=warning in GITHUB_ENV, got: %s", envText)
}
if !strings.Contains(envText, "GH_AW_DETECTION_REASON=agent_failure") {
t.Fatalf("expected GH_AW_DETECTION_REASON=agent_failure in GITHUB_ENV, got: %s", envText)

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 ContinueOnErrorExportsEnv test validates GITHUB_ENV exports but does not assert GITHUB_OUTPUT is also populated in this path — the pre-existing MissingResultContinueOnError test may cover it, but a comment linking them (or adding assertions here) would make coverage intent explicit.

💡 Suggestion

Add a quick GITHUB_OUTPUT assertion or a comment referencing the prior test, e.g.:

// GITHUB_OUTPUT assertions covered by TestConcludeThreatDetectionScript_MissingResultContinueOnError

This keeps the test self-documenting for future maintainers.

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

✅ Test Quality Sentinel: 100/100. All 2 new tests are high-value design tests with 0% implementation tests (well below the 30% threshold). Comprehensive behavioral coverage of both strict-mode and continue-on-error paths with no forbidden mock patterns detected.

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

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

The fix is correct and well-structured. The strict-mode path now writes conclusion=failure, success=false, and reason=agent_failure to GITHUB_OUTPUT before exit 1, preventing downstream steps from misclassifying infra failures as threat detections. Both branches also export GH_AW_DETECTION_CONCLUSION/GH_AW_DETECTION_REASON to GITHUB_ENV matching the .cjs path. Two new tests cover the changes. No issues found.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 14.7 AIC · ⊞ 5.3K

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

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

Verdict: Request changes

The $GITHUB_OUTPUT fix is correct and matches the existing warn-mode pattern, but the added $GITHUB_ENV exports in both branches are dead code that do not fix anything and should be removed.

Themes
  • conclude_threat_detection.sh is the last step of the detection job (see threat_detection_job.go / threat_detection_external.go), and downstream jobs only ever consume its results via needs.detection.outputs.detection_conclusion/detection_reason, which are wired from steps.detection_conclusion.outputs.* ($GITHUB_OUTPUT) — never from $GITHUB_ENV. $GITHUB_ENV only affects later steps in the same job, and none exist after this step.
  • The real consumers of the GH_AW_DETECTION_CONCLUSION/GH_AW_DETECTION_REASON env var names (generate_footer.cjs, handle_detection_runs.cjs, notify_comment_error.cjs, push_to_pull_request_branch.cjs, etc.) get them from the safe-outputs job's own env, populated from the detection job's outputs.* — not from this script's $GITHUB_ENV.
  • The new Go tests lock in this no-op behavior rather than testing something that changes production behavior, which will make future cleanup look like a regression.
  • The core fix (writing conclusion=failure, success=false, reason=agent_failure to $GITHUB_OUTPUT in strict mode before exit 1) correctly addresses the described bug and is a good, minimal change on its own.

🔎 Code quality review by PR Code Quality Reviewer · auto · 87.5 AIC · ⊞ 7.8K
Comment /review to run again

echo "reason=agent_failure" >> "${GITHUB_OUTPUT}"
if [ -n "${GITHUB_ENV:-}" ]; then
echo "GH_AW_DETECTION_CONCLUSION=warning" >> "${GITHUB_ENV}"
echo "GH_AW_DETECTION_REASON=agent_failure" >> "${GITHUB_ENV}"

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 new $GITHUB_ENV exports here are a no-op: this is the last step of the detection job, and env vars never cross job boundaries anyway.

💡 Why this does not fix the described bug

Downstream jobs consume detection results exclusively via needs.detection.outputs.detection_conclusion / detection_reason, which are wired in pkg/workflow/threat_detection_job.go from steps.detection_conclusion.outputs.* (i.e. $GITHUB_OUTPUT), not from $GITHUB_ENV. $GITHUB_ENV only affects subsequent steps within the same job, and this conclude step is the last step before exit 0/exit 1 in this job — there is no later step in the detection job that reads these env vars either.

The $GITHUB_OUTPUT writes added alongside this (conclusion/success/reason) are the actual fix; the $GITHUB_ENV block is dead code that adds a false impression of cross-job propagation and increases maintenance surface without changing observable behavior.

# This block has no observable effect in either the warn or strict branch:
if [ -n "${GITHUB_ENV:-}" ]; then
  echo "GH_AW_DETECTION_CONCLUSION=warning" >> "${GITHUB_ENV}"
  echo "GH_AW_DETECTION_REASON=agent_failure" >> "${GITHUB_ENV}"
fi

Recommend removing both $GITHUB_ENV blocks (here and at line 51) unless there is a concrete downstream consumer within the same job that actually reads them — if there is, that dependency should be documented and tested directly, not just asserted via a new unit test that locks in a no-op.

echo "success=false" >> "${GITHUB_OUTPUT}"
echo "reason=agent_failure" >> "${GITHUB_OUTPUT}"
if [ -n "${GITHUB_ENV:-}" ]; then
echo "GH_AW_DETECTION_CONCLUSION=failure" >> "${GITHUB_ENV}"

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.

Same dead-code issue as the warn-mode branch above: this $GITHUB_ENV export is a no-op right before exit 1.

💡 Details

This is the strict-mode branch, and it exits the process immediately after this block via exit 1. There is no subsequent step in this job that reads $GITHUB_ENV, and downstream jobs never see it since env vars do not cross job boundaries in GitHub Actions — only the $GITHUB_OUTPUT values (already correctly added right above) are consumed via needs.detection.outputs.*.

Keeping this creates two independent "sources of truth" for the same conclusion that can silently diverge in future edits (e.g. someone changes the $GITHUB_OUTPUT value but forgets the parallel $GITHUB_ENV value, or vice versa), and it invites a future contributor to wrongly assume some downstream code depends on GH_AW_DETECTION_CONCLUSION/GH_AW_DETECTION_REASON env vars being set by this script, when in reality all real consumers of those env var names (generate_footer.cjs, handle_detection_runs.cjs, notify_comment_error.cjs, etc.) get them from the safe_outputs job env, populated from job outputs — not from this script.

Recommend dropping both $GITHUB_ENV blocks.

Comment on lines +50 to +90
func TestConcludeThreatDetectionScript_MissingResultStrictModeWritesOutputs(t *testing.T) {
scriptPath := filepath.Join("..", "..", "actions", "setup", "sh", "conclude_threat_detection.sh")
outputFile := filepath.Join(t.TempDir(), "github_output.txt")
envFile := filepath.Join(t.TempDir(), "github_env.txt")
missingResult := filepath.Join(t.TempDir(), "missing_detection_result.json")

cmd := exec.Command("bash", scriptPath, missingResult)
cmd.Env = append(os.Environ(),
"RUN_DETECTION=true",
"DETECTION_AGENTIC_EXECUTION_OUTCOME=failure",
"GH_AW_DETECTION_CONTINUE_ON_ERROR=false",
"GITHUB_OUTPUT="+outputFile,
"GITHUB_ENV="+envFile,
)

out, err := cmd.CombinedOutput()
if err == nil {
t.Fatalf("script should exit non-zero in strict mode on missing result: %s", out)
}

outputData, readErr := os.ReadFile(outputFile)
if readErr != nil {
t.Fatalf("failed to read GITHUB_OUTPUT: %v", readErr)
}
outputText := string(outputData)
if !strings.Contains(outputText, "conclusion=failure") {
t.Fatalf("expected conclusion=failure in GITHUB_OUTPUT, got: %s", outputText)
}
if !strings.Contains(outputText, "success=false") {
t.Fatalf("expected success=false in GITHUB_OUTPUT, got: %s", outputText)
}
if !strings.Contains(outputText, "reason=agent_failure") {
t.Fatalf("expected reason=agent_failure in GITHUB_OUTPUT, got: %s", outputText)
}

envData, readErr := os.ReadFile(envFile)
if readErr != nil {
t.Fatalf("failed to read GITHUB_ENV: %v", readErr)
}
envText := string(envData)
if !strings.Contains(envText, "GH_AW_DETECTION_CONCLUSION=failure") {

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.

These new tests lock in behavior (the $GITHUB_ENV writes) that has no observable effect in production, giving false confidence that a real bug is being covered.

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

Great work on this fix! 🎯 This PR elegantly resolves the strict-mode bug where infrastructure failures in conclude_threat_detection.sh were rendering to reviewers as threat detections instead of system errors.

What looks good:

  • ✅ Fixes the exact issue described in threat-detection: strict-mode conclude failure writes no outputs, rendering infra failures as detected threats #50645 — strict-mode failures now write outputs before exiting
  • ✅ Adds environment variable exports (GH_AW_DETECTION_CONCLUSION / GH_AW_DETECTION_REASON) to both branches for consistency with the .cjs path
  • ✅ Comprehensive test coverage in threat_detection_conclude_script_test.go covering both strict and continue-on-error modes
  • ✅ Clean, focused change with no unrelated modifications
  • ✅ Well-documented PR body with clear problem statement and proposed solution

This is ready for maintainer review. The fix aligns perfectly with the acceptance criteria from the issue, and the test coverage validates both the happy path and error scenarios.

Generated by ✅ Contribution Check · auto · 57.2 AIC · ⊞ 8.7K ·

@pelikhan

pelikhan commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

@copilot run pr-finisher skill

@pelikhan

pelikhan commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

@copilot resolve the merge conflicts on this branch.

Copilot AI and others added 2 commits August 6, 2026 15:00
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…tection-output

# Conflicts:
#	actions/setup/sh/conclude_threat_detection.sh
#	pkg/workflow/threat_detection_conclude_script_test.go

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

Copy link
Copy Markdown
Collaborator

@copilot Maintainer triage: this PR is blocked by merge conflicts. Please run make merge-main, resolve the conflicts on this branch, then run the pr-finisher skill and report back with the resolution summary.

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

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 17.2 AIC · ⊞ 8.3K ·
Comment /souschef to run again

@pelikhan

pelikhan commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

@copilot resolve the merge conflicts in this pull request

Copilot AI commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@copilot run pr-finisher skill

Ran the pr-finisher pass. Addressed review feedback by removing the unrelated skill-router change and the no-op GITHUB_ENV additions, merged latest main to resolve conflicts, and pushed 71e67ad.

@copilot resolve the merge conflicts on this branch.

Resolved the merge conflicts by merging latest main and keeping the upstream threat-detect conclude delegation. Pushed in 71e67ad.

@pelikhan
pelikhan merged commit e5f91da into main Aug 6, 2026
@pelikhan
pelikhan deleted the copilot/fix-threat-detection-output branch August 6, 2026 15:23
Copilot stopped work on behalf of pelikhan due to an error August 6, 2026 15:24
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.86.0

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.

threat-detection: strict-mode conclude failure writes no outputs, rendering infra failures as detected threats

4 participants