Skip to content

Cache GitHub Actions job metadata in logs output - #59039

Merged
pelikhan merged 4 commits into
mainfrom
copilot/store-logs-api-responses
Sep 6, 2026
Merged

Cache GitHub Actions job metadata in logs output#59039
pelikhan merged 4 commits into
mainfrom
copilot/store-logs-api-responses

Conversation

Copilot AI commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

The logs command discarded GitHub’s jobs API response, limiting cached run data to a reduced projection.

Changes

  • Cache complete, paginated jobs API responses as owner-readable jobs.json files.
  • Include job and step status, conclusion, timestamps, URLs, runner details, and related metadata in run summaries.
  • Preserve duration and failed-job calculations from the expanded response.

Generated by 👨‍🍳 PR Sous Chef · pi · gpt54 · 34.1 AIC · ⌖ 8.65 AIC · ⊞ 9.2K ·
Comment /souschef to run again

Copilot AI and others added 2 commits September 6, 2026 21:45
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 Cache GitHub jobs API responses in logs output Cache GitHub Actions job metadata in logs output Sep 6, 2026
Copilot AI requested a review from pelikhan September 6, 2026 21:50
@pelikhan
pelikhan marked this pull request as ready for review September 6, 2026 21:50
Copilot AI balanced review requested due to automatic review settings September 6, 2026 21:51
@github-actions

github-actions Bot commented Sep 6, 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 Sep 6, 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 Sep 6, 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 Sep 6, 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 does not have the 'implementation' label and has ≤100 new lines of code in business logic directories.

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Ponytail Reviewer completed successfully!

Lean already. Ship.

Warning

Firewall blocked 1 domain

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

  • ab.chatgpt.com

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

network:
  allowed:
    - defaults
    - "ab.chatgpt.com"

See Network Configuration for more information.

Generated by Ponytail Reviewer for #59039

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Comment Memory

reviewed_at: 2026-09-06T21:54:55Z
review_event: COMMENT
top_themes:
  - no actionable blocking issues in changed lines
  - raw jobs API response cached with richer metadata preserved
files_reviewed:
  - pkg/cli/audit_analysis_fanout.go
  - pkg/cli/logs_github_api.go
  - pkg/cli/logs_github_api_test.go
  - pkg/cli/logs_models.go
  - pkg/cli/logs_run_processor.go
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 · copilot · gpt54 · 23.8 AIC · ⌖ 8.18 AIC · ⊞ 21.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.

Verdict

Non-blocking from this diff alone. The change preserves more of the jobs payload and wires the cache through the existing run summary path without introducing a clear correctness regression in the touched lines.

Highlights
  • The expanded JobInfo/JobStep models are still backward-compatible with partial JSON payloads.
  • fetchJobStatuses intentionally avoids writing jobs.json, which keeps the lightweight status path cheap.
  • The one grumpy-coder finding was dropped because gh api --paginate --slurp is expected to return the paginated JSON array shape this code unmarshals, and the existing behavior already suppresses upstream fetch failures for callers.

🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt54 · 23.8 AIC · ⌖ 8.18 AIC · ⊞ 21.8K
Comment /review to run again

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.

🟡 Changes recommended

Cache-write error handling, overwrite permissions, and concurrent artifact enumeration can produce incomplete or insecure cached output.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Caches complete paginated GitHub Actions job metadata and exposes expanded job and step details in run summaries.

Changes:

  • Stores raw paginated responses in owner-only jobs.json.
  • Expands job and step metadata.
  • Preserves duration and failure calculations.
File summaries
File Description
pkg/cli/logs_run_processor.go Passes the run directory for caching.
pkg/cli/logs_models.go Adds cache filename and metadata fields.
pkg/cli/logs_github_api.go Fetches, caches, and parses paginated jobs.
pkg/cli/logs_github_api_test.go Tests metadata, pagination flags, and permissions.
pkg/cli/audit_analysis_fanout.go Enables job-response caching during audits.
Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 3
  • Review effort level: Balanced

Comment thread pkg/cli/logs_github_api.go Outdated
continue
if outputDir != "" {
responsePath := filepath.Join(outputDir, jobsAPIResponseFileName)
if err := os.WriteFile(responsePath, output, constants.FilePermSensitive); err != nil {

launchMetricsAnalysis(g, gctx, results, runOutputDir, verbose, run.WorkflowPath)
launchJobDetailsAnalysis(g, gctx, results, run.DatabaseID, verbose)
launchJobDetailsAnalysis(g, gctx, results, run.DatabaseID, runOutputDir, verbose)
Comment thread pkg/cli/logs_github_api.go Outdated
Comment on lines +99 to +100
if err := os.WriteFile(responsePath, output, constants.FilePermSensitive); err != nil {
return nil, 0, fmt.Errorf("failed to cache jobs API response: %w", err)

@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 on the jobs-API caching change.

📋 Key Themes & Highlights

Key Themes

  • Resilience regression: switching from per-line to whole-response json.Unmarshal means one malformed page now discards all job data for the run, where previously bad lines were skipped individually.
  • Untested error path: the new os.WriteFile cache-write can fail (missing dir, permissions) and that failure currently propagates as a hard error from fetchJobDetailsWithCounts, with no test exercising it.

Positive Highlights

  • ✅ Good coverage of the new richer JobInfo/JobStep fields in the updated unit tests.
  • ✅ Consistent use of constants.FilePermSensitive (0600) for the cached response, matching the project's sensitive-file convention.
  • ✅ The plumbing of outputDir/runOutputDir through fetchJobDetailsWithCountsfetchJobDetailslaunchJobDetailsAnalysis is clean and consistent across both the logs and audit call paths.

@copilot please address the review comments above.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · sonnet50 · 79.1 AIC · ⌖ 13.7 AIC · ⊞ 10.3K
Comment /matt to run again

var responses []struct {
Jobs []JobInfo `json:"jobs"`
}
if err := json.Unmarshal(output, &responses); err != nil {

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] Resilience regression: parsing now aborts entirely on any malformed byte in the whole paginated response, whereas the old per-line loop skipped just the bad job and kept the rest.

💡 Details

The previous implementation iterated line-by-line and logged+skipped any job that failed to unmarshal, so a single corrupted/partial page didn't discard every other job. Now json.Unmarshal(output, &responses) is all-or-nothing — one bad page (e.g. truncated network response, unexpected field type) zeroes out job info for the entire run, even though most pages were fine. Since this directly affects the failed-job count and audit summaries, consider decoding per-page (or per-job) with a fallback that logs and continues, matching the old resilience behavior. Add a test with one malformed page among several valid ones to lock in the desired behavior.

@copilot please address this.

Comment thread pkg/cli/logs_github_api.go Outdated
continue
if outputDir != "" {
responsePath := filepath.Join(outputDir, jobsAPIResponseFileName)
if err := os.WriteFile(responsePath, output, constants.FilePermSensitive); err != nil {

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] No test covers os.WriteFile failing (e.g. outputDir not existing, permission denied) — that path currently returns a hard error from fetchJobDetailsWithCounts, which callers treat as "no job data available" even though this is a caching side-effect, not a fetch failure.

💡 Suggested test
func TestFetchJobDetailsWithCounts_CacheWriteFailure(t *testing.T) {
    // outputDir points at a non-existent parent (or a read-only dir)
    // assert jobs/failedJobs are still returned, or that the error is
    // clearly scoped to the cache-write concern.
}

Worth deciding intentionally whether a cache-write failure should fail job detail retrieval at all, since every caller already discards fetchJobDetailsWithCounts errors as non-fatal (fetchJobDetails, fetchJobStatuses, launchJobDetailsAnalysis) — so today it silently degrades, which may be fine, but should be covered by a test rather than implicit.

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

Reviewed as a backend/CLI change (not UI), so Impeccable modes were not applicable; performed a direct correctness/reliability review focused on the jobs-API caching change.

Two non-blocking issues found:

  1. logs_github_api.go — a cache-write failure (os.WriteFile for jobs.json) now aborts job parsing entirely instead of degrading gracefully, which can regress previously-reliable job-status reporting on transient filesystem errors.
  2. logs_run_processor.go — the newly cached jobs.json file isn't excluded from listArtifacts, so it leaks into RunSummary.ArtifactsList as if it were a downloaded artifact.

Both are suggestions for hardening/consistency rather than blockers; tests for the changed behavior pass (TestFetchJobDetailsWithCountsIncludesSteps, TestFetchJobDetailsWithCountsNullConclusion, TestCollectAuditAnalysisResultsReturnsContextCancellation).

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · copilot · sonnet50 · 134.5 AIC · ⌖ 14.4 AIC · ⊞ 8.3K

Comments that could not be inline-anchored

pkg/cli/logs_github_api.go:100

When outputDir != &quot;&quot;, a cache-write failure now aborts job parsing entirely (return nil, 0, fmt.Errorf(...)), even though the GitHub API call already succeeded and output holds valid data. fetchJobDetails/fetchJobStatuses swallow errors from this function and return nil/0, so a transient filesystem issue (permission problem, disk full, read-only mount) now causes complete loss of job details/duration/failed-job counts — a capability that previously only failed when the API call it…

pkg/cli/logs_run_processor.go:550

listArtifacts (used to populate RunSummary.ArtifactsList) walks the entire runOutputDir and only excludes runSummaryFileName; it does not exclude jobsAPIResponseFileName. Since finalizeAndSaveRunSummary fetches job details (writing jobs.json into runOutputDir) before calling listArtifacts, the newly-cached jobs.json will now show up in ArtifactsList as if it were a downloaded GitHub Actions artifact, even though it's synthesized metadata rather than an artifact. Consider e…

@pelikhan

pelikhan commented Sep 6, 2026

Copy link
Copy Markdown
Collaborator

@copilot run pr-finisher skill

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

Copy link
Copy Markdown
Collaborator
pr-sous-chef

@copilot Please take the next forward-progress pass on PR #59039.

  • Re-check the current review feedback on the jobs-API caching change and address any remaining correctness/reliability issues on the latest HEAD.
  • Re-run the relevant tests, resolve any appropriate review conversations, and finish with the pr-finisher skill.
  • Provide a concise maintainer-facing handoff summarizing what changed and whether any blocker remains beyond routine review/CI.

Recent review focus:

  • cache-write failures should not discard otherwise-fetched job data.
  • ensure cached jobs.json does not appear as a downloaded artifact in the run summary.

Generated by PR Sous Chef: https://github.com/github/gh-aw/actions/runs/34065397094

Generated by 👨‍🍳 PR Sous Chef · pi · gpt54 · 34.1 AIC · ⌖ 8.65 AIC · ⊞ 9.2K ·
Comment /souschef to run again

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@pelikhan
pelikhan merged commit 70bd59b into main Sep 6, 2026
@pelikhan
pelikhan deleted the copilot/store-logs-api-responses branch September 6, 2026 23:05
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.88.5

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.

4 participants