Skip to content

Add fallback artifact so safe outputs survive agent artifact upload failures - #53109

Merged
pelikhan merged 10 commits into
mainfrom
copilot/debug-github-api-consumption-agent
Aug 16, 2026
Merged

Add fallback artifact so safe outputs survive agent artifact upload failures#53109
pelikhan merged 10 commits into
mainfrom
copilot/debug-github-api-consumption-agent

Conversation

Copilot AI commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Run 31942623626 reported "no safe outputs" even though the agent successfully called create_discussion. The agent job's Upload agent artifacts step timed out against blob storage; since that step is continue-on-error: true, the job still reported success but the agent artifact was never created. Agent output reaches downstream jobs only through that artifact, so Download agent output artifact failed, GH_AW_AGENT_OUTPUT was never set, and process_safe_outputs.cjs silently processed zero items.

The fix decouples safe-output transport from the large, failure-prone artifact by also uploading a tiny dedicated copy, and matching both on download.

Upload

  • New constants.AgentOutputFallbackArtifactName = "agent-output-fallback".
  • generateAgentOutputFallbackUpload emits an upload step immediately before the unified agent upload, carrying only agent_output.json and safeoutputs.jsonl (if: always(), continue-on-error: true, if-no-files-found: ignore). Skipped when the workflow declares no safe outputs. Emitted after secret redaction so step-order validation still holds.

Download

  • ArtifactDownloadConfig gains FallbackArtifact. When set, buildArtifactDownloadSteps switches from name: to a brace pattern with merge-multiple: true, which extracts into path identically — downstream file paths are unchanged.
  • Wired into buildAgentOutputDownloadSteps (safe_outputs, detection, evals, conclusion) and the custom safe-jobs download.
- name: Download agent output artifact
  id: download-agent-output
  continue-on-error: true
  uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
  with:
    pattern: "{agent,agent-output-fallback}"
    merge-multiple: true
    path: /tmp/gh-aw/

If both artifacts are missing the step still fails and the env var stays unset, preserving existing behavior.

Notes

  • Named agent-output-fallback rather than reusing constants.AgentOutputArtifactName ("agent-output") because the CLI has legacy flattening logic keyed on a directory of that exact name.
  • All 285 .lock.yml files regenerated.

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


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


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

Copilot AI and others added 2 commits August 16, 2026 12:53
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix GitHub API Consumption Report Agent outputs issue Add fallback artifact so safe outputs survive agent artifact upload failures Aug 16, 2026
Copilot AI requested a review from pelikhan August 16, 2026 13:00
@pelikhan
pelikhan marked this pull request as ready for review August 16, 2026 13:07
Copilot AI balanced review requested due to automatic review settings August 16, 2026 13:07
@github-actions

github-actions Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Ponytail Reviewer completed successfully!

Diff contains only generated .lock.yml files (regenerated workflow artifacts); the actual Go source changes are not present in the available diff. Per review scope, generated files are skipped. Nothing actionable to flag for over-engineering.

Generated by Ponytail Reviewer for #53109

@github-actions

github-actions Bot commented Aug 16, 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

github-actions Bot commented Aug 16, 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 16, 2026

Copy link
Copy Markdown
Contributor

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

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

github-actions Bot commented Aug 16, 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

Copy link
Copy Markdown
Contributor

Comment Memory

reviewed_at: 2026-08-16T00:00:00Z
review_event: COMMENT
top_themes:
  - fallback artifact upload/download wiring looks internally consistent
  - no blocking correctness issues found in changed lines
files_reviewed:
  - pkg/workflow/artifacts.go
  - pkg/workflow/compiler_yaml_artifacts.go
  - pkg/workflow/safe_outputs_steps.go
  - pkg/workflow/safe_jobs.go
  - pkg/constants/job_constants.go
  - pkg/workflow/compiler_artifacts_test.go
  - pkg/workflow/compiler_yaml_post_agent.go
  - .github/workflows/*.lock.yml
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 · gpt54 · 19.2 AIC · ⌖ 5.34 AIC · ⊞ 4.5K ·
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.

Verdict

Non-blocking from my pass: the fallback artifact upload/download path is wired consistently and I did not find a changed-line correctness bug worth blocking on.

What I checked
  • buildArtifactDownloadSteps switches to a merged pattern download only when a fallback artifact is configured.
  • buildAgentOutputDownloadSteps and safe-jobs both opt into the fallback artifact.
  • The fallback upload is emitted before the large unified agent artifact upload.
  • The regression test covers the new upload step ordering and merged download behavior.
  • Regenerated lockfiles reflect the compiler change.

🔎 Code quality review by PR Code Quality Reviewer · gpt54 · 19.2 AIC · ⌖ 5.34 AIC · ⊞ 4.5K
Comment /review to run again

Documents the architectural decision to introduce a dedicated fallback
artifact to decouple safe-output transport from the failure-prone large
agent artifact upload.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🏗️ Design Decision Gate — ADR Required

This PR makes significant changes to core business logic (144 new lines in business logic directories) but does not have a linked Architecture Decision Record (ADR).

📄 Draft ADR committed: docs/adr/53109-fallback-artifact-for-safe-output-transport.md — review and complete it before merging.

🔒 This PR cannot merge until an ADR is linked in the PR body.

📋 What to do next
  1. Review the draft ADR committed to your branch — it was generated from the PR diff
  2. Complete the missing sections — add context the AI couldn't infer, refine the decision rationale, and list real alternatives you considered
  3. Commit the finalized ADR to docs/adr/ on your branch
  4. Reference the ADR in this PR body by adding a line such as:

    ADR: ADR-53109: Fallback Artifact for Safe-Output Transport

Once an ADR is linked in the PR body, this gate will re-run and verify the implementation matches the decision.

❓ Why ADRs Matter

"AI made me procrastinate on key design decisions. Because refactoring was cheap, I could always say 'I'll deal with this later.' Deferring decisions corroded my ability to think clearly."

ADRs create a searchable, permanent record of why the codebase looks the way it does. Future contributors (and your future self) will thank you.

📋 Michael Nygard ADR Format Reference

An ADR must contain these four sections to be considered complete:

  • Context — What is the problem? What forces are at play?
  • Decision — What did you decide? Why?
  • Alternatives Considered — What else could have been done?
  • Consequences — What are the trade-offs (positive and negative)?

All ADRs are stored in docs/adr/ as Markdown files numbered by PR number (e.g., 0042-use-postgresql.md for PR #42).

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · sonnet46 · 50.7 AIC · ⌖ 27.2 AIC · ⊞ 9K ·
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.

The fallback artifact approach is well-implemented. Key observations:

  • if: always() + continue-on-error: true + if-no-files-found: ignore correctly handles the case where the agent run itself failed before producing output.
  • The fallback artifact contains only the two critical files (agent_output.json, safeoutputs.jsonl), making it a smaller, more reliable upload compared to the full agent artifact.
  • The cp "$GH_AW_SAFE_OUTPUTS" /tmp/gh-aw/safeoutputs.jsonl copy step already runs before these uploads, so the path is correct.
  • Download steps use pattern: "{agent,agent-output-fallback}" with merge-multiple: true, which correctly merges files from either artifact — safe-output processing will find safeoutputs.jsonl regardless of which upload succeeded.

No blocking issues found.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 53.5 AIC · ⌖ 7.95 AIC · ⊞ 5.6K

@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 with minor gaps to address.

📋 Key Themes & Highlights

Key Themes

  • Root cause is well diagnosed: the PR description clearly traces the failure from timed-out blob upload → missing artifact → silently dropped safe outputs. The fix correctly decouples the critical small payload from the large, failure-prone artifact.
  • Test coverage: TestAgentOutputFallbackArtifact verifies the happy path thoroughly (ordering, content, download pattern). The negative path — no fallback step when safe-outputs: is absent — is not tested.
  • Fragile test section extraction: the substring windowing in the test is correct today but brittle to future YAML changes.

Positive Highlights

  • ✅ Constant AgentOutputFallbackArtifactName is clearly documented and justified in comments.
  • if-no-files-found: ignore on the fallback upload is the right default — avoids spurious failures when the agent never wrote output.
  • merge-multiple: true correctly handles the case where both artifacts exist without path conflicts.
  • ✅ The fallback upload is placed before the large agent artifact upload, so even a hard job timeout is survived.
  • ✅ The nil-guard in generateAgentOutputFallbackUpload is correct — the fallback step is skipped when no safe outputs are declared.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 56.9 AIC · ⌖ 11.5 AIC · ⊞ 7.7K
Comment /matt to run again

if !strings.Contains(lockYAML, "merge-multiple: true") {
t.Error("Expected 'merge-multiple: true' so both artifacts extract into the same directory")
}
}

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 generateAgentOutputFallbackUpload nil-guard (if data.SafeOutputs == nil { return }) is not tested — there is no test verifying that workflows without safe-outputs: omit the fallback upload step entirely.

💡 Suggested test

Add a case to TestAgentOutputFallbackArtifact (or a sibling test) that compiles a workflow without safe-outputs: and asserts the lock file does not contain "Upload agent output fallback artifact":

func TestAgentOutputFallbackArtifact_NoSafeOutputs(t *testing.T) {
	// Compile a minimal workflow with no safe-outputs section.
	// The fallback upload step must be absent because no safe output
	// processing will run and the artifact would never be consumed.
	...
	if strings.Contains(lockYAML, "Upload agent output fallback artifact") {
		t.Error("Expected no fallback artifact upload when safe-outputs is not declared")
	}
}

Without this test the guard is invisible to the test suite and a refactor could accidentally delete it.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 9c041ae: added TestAgentOutputFallbackArtifact_NoSafeOutputs and tightened generateAgentOutputFallbackUpload so default-only/no-declared safe-output workflows omit the fallback upload.

Comment thread pkg/workflow/compiler_artifacts_test.go Outdated
uploadIdx := strings.Index(lockYAML, "- name: Upload agent output fallback artifact")
if uploadIdx == -1 {
t.Fatal("Expected 'Upload agent output fallback artifact' step in generated workflow")
}

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 test uses a fragile index-based substring extraction to isolate the fallback upload section:

uploadSection := lockYAML[uploadIdx:]
if next := strings.Index(uploadSection[1:], "- name:"); next != -1 {
    uploadSection = uploadSection[:next+1]
}

This silently over- or under-captures if the YAML structure changes (e.g. an additional step is inserted between the comment and the - name: marker, or the step comment itself contains - name:). The test could then pass while checking the wrong section.

💡 Suggestion

Consider extracting the section with a YAML-aware approach or by matching from "- name: Upload agent output fallback artifact" to the next step that starts at the same indentation level. Alternatively, add a t.Log(uploadSection) so failures at least print what was actually checked.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 9c041ae: replaced the fragile substring slicing with extractWorkflowStepByName, which ends the section at the next step with the same indentation.

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 a dedicated fallback artifact so safe outputs survive failures uploading the larger agent artifact.

Changes:

  • Uploads critical agent-output files separately.
  • Downloads and merges primary and fallback artifacts.
  • Regenerates affected workflow lockfiles and updates tests.
Show a summary per file
File Description
pkg/constants/job_constants.go Defines the fallback artifact name.
pkg/workflow/artifacts.go Adds fallback-aware downloads.
pkg/workflow/compiler_yaml_artifacts.go Generates the fallback upload step.
pkg/workflow/compiler_yaml_post_agent.go Emits fallback before unified upload.
pkg/workflow/safe_outputs_steps.go Enables fallback for downstream jobs.
pkg/workflow/safe_jobs.go Enables fallback for custom safe jobs.
pkg/workflow/safe_output_helpers_test.go Updates download expectations.
pkg/workflow/compiler_artifacts_test.go Tests fallback generation and ordering.
.github/workflows/*.lock.yml Regenerates 285 compiled workflows.

Review details

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

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

Comment thread pkg/workflow/artifacts.go
Comment on lines +59 to +60
steps = append(steps, fmt.Sprintf(" pattern: \"{%s,%s}\"\n", config.ArtifactName, config.FallbackArtifact))
steps = append(steps, " merge-multiple: true\n")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 9c041ae: the setup step now checks for agent_output.json before writing GH_AW_AGENT_OUTPUT, so zero-match pattern downloads no longer publish a nonexistent file.

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot resolve the merge conflicts on this branch.

Copilot AI and others added 2 commits August 16, 2026 13:48
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot update audit/logs go commands to use new artifact

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

Copilot AI commented Aug 16, 2026

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts on this branch.

Resolved the merge conflicts and pushed the merge resolution in 249ce8927a.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot PR #53109 still needs a follow-up pass.

Quick triage

Next step

  • Push the follow-up changes, resolve addressed review threads, and get the PR back to merge-ready.

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

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

Copilot AI commented Aug 16, 2026

Copy link
Copy Markdown
Contributor Author

@copilot update audit/logs go commands to use new artifact

Addressed in c639a02: audit/logs artifact filtering now includes agent-output-fallback, flattens it into the run root, and retries it as a critical artifact.

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

Copy link
Copy Markdown
Collaborator

@copilot PR #53109 still needs a follow-up pass.

Quick triage

Next step

  • Push the follow-up changes, resolve addressed review threads, and get the PR back to merge-ready.

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

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

Copilot AI commented Aug 16, 2026

Copy link
Copy Markdown
Contributor Author

@copilot PR #53109 still needs a follow-up pass.

Quick triage...

Addressed in 9c041ae: fixed the both-missing download case, hardened the fallback upload test extraction, added no-safe-outputs guard coverage, and reran targeted validation.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot PR #53109 still needs a follow-up pass.

Quick triage

Next step

  • Push the follow-up changes, resolve addressed review threads, and get the PR back to merge-ready.

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

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

Copilot AI commented Aug 16, 2026

Copy link
Copy Markdown
Contributor Author

@copilot PR #53109 still needs a follow-up pass.

Quick triage...

Current head already contains the requested fixes in 9c041ae: the setup step gates GH_AW_AGENT_OUTPUT on agent_output.json existing, extractWorkflowStepByName replaces the fragile test slicing, and TestAgentOutputFallbackArtifact_NoSafeOutputs covers the nil/no-safe-outputs guard. I reran validation (go test ./pkg/workflow -run 'Test(AgentOutputFallbackArtifact|BuildAgentOutputDownloadSteps)', make lint, make test-unit, and make agent-report-progress).

Copilot AI commented Aug 16, 2026

Copy link
Copy Markdown
Contributor Author

@copilot PR #53109 still needs a follow-up pass.

Quick triage...

Current head already contains these fixes in 9c041ae: GH_AW_AGENT_OUTPUT is only published when agent_output.json exists, extractWorkflowStepByName replaces the fragile section slicing, and TestAgentOutputFallbackArtifact_NoSafeOutputs covers the no-safe-outputs guard. I revalidated with targeted workflow tests, make fmt, make lint, make test-unit, make recompile, and make agent-report-progress. No additional code changes were needed.

@pelikhan
pelikhan merged commit da482ee into main Aug 16, 2026
2 checks passed
@pelikhan
pelikhan deleted the copilot/debug-github-api-consumption-agent branch August 16, 2026 16:28
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.87.1

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.

[aw] GitHub API Consumption Report Agent produced no safe outputs

4 participants