You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Analysis Date: 2026-07-27 Focus Area: context.Background() Call-Chain Leakage — Uncancellable Sub-calls Despite Cobra Signal Context at Entry Points Strategy Type: Custom Custom Area: Yes — distinct from prior context-propagation runs (2026-06-03/09/22) which targeted exec.Command; this run targets wrappers and helper functions that hard-code context.Background() even when caller context exists
Executive Summary
The repository's entry-point commands consistently capture a cancellable context via signal.NotifyContext(context.Background(), ...) and thread it through cobra RunE handlers. However, 40 context.Background() calls exist in non-test production code below the entry points, many inside functions that are already called with a live context — or whose callers hold one. This creates silent cancellation dead zones: when a user presses Ctrl+C, the signal context is cancelled and most work stops cleanly, but calls routed through the affected helpers continue running until they time out or finish naturally.
The most impactful cluster is in pkg/workflow/github_cli.go: three convenience wrappers (ExecGH, RunGH, RunGHCombined) discard their callers' contexts and hard-code context.Background(), affecting 92 downstream call sites. Context-aware siblings (ExecGHContext, RunGHContext, RunGHCombinedContext) already exist and are the correct fix path. A secondary cluster in pkg/parser/remote_workflow_spec.go has three context.Background() network calls with an existing TODO comment acknowledging the gap.
Five high-value fixes would eliminate the largest leakage surface, propagate cancellation signals through compiler pipelines, validation helpers, and log-download flows, and bring the codebase closer to fully honouring its own signal-aware lifecycle contract.
Entry-point signal context wiring is consistently correct
Context-aware siblings exist for all problematic gh wrappers
Most option-struct nil-ctx fallbacks are intentional and documented
The ctxbackground linter exists and catches in-function violations — but doesn't catch wrapper functions that create the context before delegating
Areas for Improvement
[HIGH]pkg/workflow/github_cli.go:106,191,213 — ExecGH, RunGH, RunGHCombined each call their *Context siblings with a hard-coded context.Background(). Any caller that has a valid context and uses the non-context variant loses cancellation for all gh CLI network I/O
[HIGH]pkg/parser/remote_workflow_spec.go:91,93,156 — Three downloadFileFromGitHub / resolveRefToSHA calls hard-code context.Background(). The enclosing functions are called during compilation; an in-progress compile cannot be cancelled at this step. A TODO comment at line 71 already acknowledges this
[MEDIUM]pkg/cli/logs_orchestrator_filters.go:167 — fetchJobStatusesForProcessedRun(context.Background(), ...) inside buildRunsModel; the enclosing flow is called from log-download commands that carry a live context
[MEDIUM]pkg/cli/update_extension_check.go:49 — upgradeExtensionIfOutdated creates no context parameter; its only caller (runUpgradeCommand at line 245) holds opts.ctx from cobra. GitHub API call for the latest release is fully uncancellable
[LOW]pkg/cli/syft.go:67 — RunSyftOnLockFiles is called from compilePipeline which checks ctx.Err() right before the call, but runSyftScans creates a fresh context.Background() internally and never propagates cancellation into the image-scan loop
The three context-less wrappers exist for convenience but create a systemic leakage:
// Line 106 — drops caller contextfuncExecGH(args...string) *exec.Cmd {
returnsetupGHCommand(context.Background(), args...) // should use caller-provided ctx
}
// Line 191funcRunGH(spinnerMessagestring, args...string) ([]byte, error) {
returnRunGHContext(context.Background(), spinnerMessage, args...)
}
// Line 213funcRunGHCombined(spinnerMessagestring, args...string) ([]byte, error) {
returnRunGHCombinedContext(context.Background(), spinnerMessage, args...)
}
All 92 call sites of these functions could inherit caller context if the functions were removed and callers migrated to the *Context variants.
pkg/parser/remote_workflow_spec.go — Acknowledged TODO
// Line 71 — comment acknowledges the gap// packages is tracked as a follow-up task; context.Background() is used in the interim.// Line 91/93/156content, err=downloadFileFromGitHub(context.Background(), owner, repo, filePath, ref)
content, err=downloadFileFromGitHubWithDepth(context.Background(), ...)
resolvedSHA, err:=resolveRefToSHA(context.Background(), ...)
The calling functions accept no ctx parameter, so fixing requires a signature change to propagate the compiler's context.
pkg/cli/logs_orchestrator_filters.go:167
// Inside buildRunsModel — function has access to outer ctx through enclosing pipelineiffailedJobCount, err:=fetchJobStatusesForProcessedRun(context.Background(), run.DatabaseID, verbose); err==nil {
The fetchJobStatusesForProcessedRun function accepts a context.Context; only the call site supplies the wrong one.
// upgradeExtensionIfOutdated has no ctx parameterfuncupgradeExtensionIfOutdated(verbosebool, includePrereleasesbool) (bool, string, error) {
// ...latestVersion, err:=getLatestRelease(context.Background(), includePrereleases) // line 63
The fix requires adding ctx context.Context to upgradeExtensionIfOutdated and threading it from opts.ctx in runUpgradeCommand.
🤖 Tasks for Copilot Agent
NOTE TO PLANNER AGENT: Split the following tasks into individual work items.
Improvement Tasks
Task 1: Deprecate Non-Context gh Wrappers and Migrate Top Call Sites
Priority: High Estimated Effort: Medium Focus Area: context.Background() Call-Chain Leakage
Description: The three context-less wrapper functions ExecGH, RunGH, and RunGHCombined in pkg/workflow/github_cli.go (lines 106, 191, 213) hard-code context.Background() while calling their context-aware siblings. Identify all call sites using grep -rn 'ExecGH\|RunGH\|RunGHCombined' pkg/ cmd/ (excluding the *Context variants), add a // Deprecated: doc comment to each wrapper, and migrate call sites inside pkg/cli/ that already have a ctx variable in scope to the corresponding *Context variant.
Acceptance Criteria:
ExecGH, RunGH, RunGHCombined each have a // Deprecated: use the *Context variant doc comment
Call sites in pkg/cli/ that have a local ctx context.Context in scope are migrated to pass that context
make fmt passes
make test-unit passes
Code Region:pkg/workflow/github_cli.go, pkg/cli/
In pkg/workflow/github_cli.go, add Deprecated doc comments to ExecGH (line 100), RunGH (line 186), and RunGHCombined (line 207).
Then, find every caller in pkg/cli/ that already has a `ctx` variable in scope (use grep or static analysis) and replace:
- ExecGH(...) → ExecGHContext(ctx, ...)
- RunGH(msg, ...) → RunGHContext(ctx, msg, ...)
- RunGHCombined(msg, ...) → RunGHCombinedContext(ctx, msg, ...)
Do not change call sites that genuinely have no context (e.g., fire-and-forget helpers); leave those with the deprecated wrapper for a follow-up.
Task 2: Propagate Caller Context Through Remote Workflow Spec Fetchers
Priority: High Estimated Effort: Medium Focus Area: context.Background() Call-Chain Leakage
Description:pkg/parser/remote_workflow_spec.go contains three context.Background() network calls on lines 91, 93, and 156 with a TODO comment at line 71 acknowledging the gap. The enclosing functions (downloadRemoteFileForImport, resolveRemoteRef) lack ctx parameters. Add ctx context.Context parameters to these functions and propagate the compiler's context from callers in pkg/parser/ and pkg/cli/.
Acceptance Criteria:
downloadRemoteFileForImport and resolveRemoteRef (or equivalent enclosing functions) accept ctx context.Context
All three context.Background() calls on lines 91/93/156 are replaced with the propagated ctx
The TODO comment at line 71 is removed
All callers in pkg/parser/ and pkg/cli/ are updated to pass context
make test-unit passes
Code Region:pkg/parser/remote_workflow_spec.go
In pkg/parser/remote_workflow_spec.go:
1. Find the functions enclosing lines 91, 93, and 156 — they currently lack a `ctx` parameter.
2. Add `ctx context.Context` as the first parameter to each.
3. Replace the three `context.Background()` arguments with `ctx`.
4. Remove the TODO comment block around line 71.
5. Trace all call sites in pkg/parser/ and pkg/cli/ and update them to pass an appropriate context (typically the compiler's ctx or the cobra cmd.Context()).
6. Run `make fmt && make test-unit`.
Task 3: Thread Context Through upgradeExtensionIfOutdated
Priority: Medium Estimated Effort: Small Focus Area: context.Background() Call-Chain Leakage
Description:upgradeExtensionIfOutdated in pkg/cli/update_extension_check.go (line 49) has no ctx context.Context parameter, so its internal call to getLatestRelease(context.Background(), ...) (line 63) cannot be cancelled. Its only production caller runUpgradeCommand in pkg/cli/upgrade_command.go (line 245) holds opts.ctx. Add a ctx parameter and thread it.
In pkg/cli/update_extension_check.go:
- Change `func upgradeExtensionIfOutdated(verbose bool, includePrereleases bool)` to accept `ctx context.Context` as the first parameter.
- On line 63, replace `context.Background()` with `ctx`.
In pkg/cli/upgrade_command.go:
- Update the call at line 245 to: `upgraded, installPath, err := upgradeExtensionIfOutdated(opts.ctx, opts.verbose, opts.preReleases)`
Update any test stubs in pkg/cli/*_test.go that call upgradeExtensionIfOutdated directly.
Run `make fmt && make test-unit`.
Task 4: Fix context.Background() in logs_orchestrator_filters and syft scan loop
Priority: Medium Estimated Effort: Small Focus Area: context.Background() Call-Chain Leakage
Description: Two related context-leakage points in the log/scan pipeline: (a) pkg/cli/logs_orchestrator_filters.go:167 calls fetchJobStatusesForProcessedRun(context.Background(), ...) inside buildRunsModel — the outer pipeline carries a live context that should flow here; (b) pkg/cli/syft.go:67 creates a standalone context.Background() for runSyftOnImage calls inside an image-scan loop, while compile_pipeline.go checks ctx.Err() right before calling RunSyftOnLockFiles but the ctx never reaches the loop.
Acceptance Criteria:
buildRunsModel (or its enclosing function) in pkg/cli/logs_orchestrator_filters.go receives a ctx parameter and passes it to fetchJobStatusesForProcessedRun
RunSyftOnLockFiles / runSyftScans in pkg/cli/syft.go and pkg/cli/compile_external_tools.go accept ctx context.Context and the scan loop uses it
compile_pipeline.go call sites pass their local ctx to the syft function
Fix A — logs_orchestrator_filters.go:
1. Locate `buildRunsModel` (or whichever function contains line 167).
2. Add `ctx context.Context` parameter.
3. Replace `context.Background()` on line 167 with `ctx`.
4. Update all callers to pass their live context.
Fix B — syft.go:
1. Change `RunSyftOnLockFiles` in compile_external_tools.go to accept `ctx context.Context` as first param.
2. Pass `ctx` through to `runSyftScans` in syft.go.
3. In `runSyftScans`, replace `ctx := context.Background()` (line 67) with the passed-in ctx.
4. Update call sites in compile_pipeline.go to pass `ctx`.
Run `make fmt && make test-unit`.
Task 5: Add ctxbackground Linter Coverage for Wrapper Functions That Synthesise Background Context
Priority: Low Estimated Effort: Small Focus Area: context.Background() Call-Chain Leakage
Description: The existing ctxbackground linter in pkg/linters/ctxbackground/ flags context.Background()inside functions that already receive a context parameter — but it does not flag wrapper functions whose only purpose is to call a *Context sibling with context.Background() (e.g. ExecGH, RunGH, RunGHCombined). Extend the linter or add a new lint rule to detect this pattern: a function with no context.Context parameter that calls an identically-named *Context sibling with a hardcoded context.Background() as first argument.
Acceptance Criteria:
A new analyzer or an extension to ctxbackground flags the pattern: func Foo(args) { return FooContext(context.Background(), args) }
The three existing wrappers in github_cli.go (once deprecated) trigger the new rule or are excluded via nolint with rationale
The linter is registered in pkg/linters/all.go (if a new analyzer)
make test-unit passes including pkg/linters/... tests
In pkg/linters/ctxbackground/, add a new check (or extend the existing `run` function) to detect the pattern:
- Function body is a single return/expression statement
- That statement calls a function whose name is `<ThisFunctionName>Context`- The first argument to that call is `context.Background()`- The outer function has no `context.Context` parameter
Flag such functions with: "wrapper function synthesises context.Background(); consider adding a ctx parameter and delegating to the *Context variant".
Add a testdata file covering positive and negative cases.
Register the updated/new analyzer, run `make fmt && make test-unit`.
📊 Historical Context
Previous Focus Areas
Date
Focus Area
Type
Custom
Key Outcomes
2026-07-22
Output Stream Abstraction Gap
Custom
Y
167 os.Stdout refs, 5 renderLogs* tasks
2026-07-17
Error Chain Transparency & Non-Wrapping fmt.Errorf Gap
Custom
Y
788 non-wrapping calls, 5 tasks
2026-07-16
Options Struct Pattern Adoption for High-Arity Functions
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
🎯 Repository Quality Improvement Report — context.Background() Call-Chain Leakage
Analysis Date: 2026-07-27
Focus Area: context.Background() Call-Chain Leakage — Uncancellable Sub-calls Despite Cobra Signal Context at Entry Points
Strategy Type: Custom
Custom Area: Yes — distinct from prior context-propagation runs (2026-06-03/09/22) which targeted
exec.Command; this run targets wrappers and helper functions that hard-codecontext.Background()even when caller context existsExecutive Summary
The repository's entry-point commands consistently capture a cancellable context via
signal.NotifyContext(context.Background(), ...)and thread it through cobraRunEhandlers. However, 40context.Background()calls exist in non-test production code below the entry points, many inside functions that are already called with a live context — or whose callers hold one. This creates silent cancellation dead zones: when a user presses Ctrl+C, the signal context is cancelled and most work stops cleanly, but calls routed through the affected helpers continue running until they time out or finish naturally.The most impactful cluster is in
pkg/workflow/github_cli.go: three convenience wrappers (ExecGH,RunGH,RunGHCombined) discard their callers' contexts and hard-codecontext.Background(), affecting 92 downstream call sites. Context-aware siblings (ExecGHContext,RunGHContext,RunGHCombinedContext) already exist and are the correct fix path. A secondary cluster inpkg/parser/remote_workflow_spec.gohas threecontext.Background()network calls with an existing TODO comment acknowledging the gap.Five high-value fixes would eliminate the largest leakage surface, propagate cancellation signals through compiler pipelines, validation helpers, and log-download flows, and bring the codebase closer to fully honouring its own signal-aware lifecycle contract.
Full Analysis Report
Focus Area: context.Background() Call-Chain Leakage
Current State Assessment
Entry points (
cmd/gh-aw/main.go,pkg/cli/forecast.go) correctly anchor a signal-aware context:This context flows through cobra's
cmd.Context()intoRunEhandlers and option structs. However, deeper helpers bypass it.Metrics Collected:
context.Background()calls in non-test production codecontext.Contextparam (ctxbackground violations)ghwrappers (ExecGH,RunGH,RunGHCombined)context.TODO()calls in production codeFindings
Strengths
ghwrappersctxbackgroundlinter exists and catches in-function violations — but doesn't catch wrapper functions that create the context before delegatingAreas for Improvement
pkg/workflow/github_cli.go:106,191,213—ExecGH,RunGH,RunGHCombinedeach call their*Contextsiblings with a hard-codedcontext.Background(). Any caller that has a valid context and uses the non-context variant loses cancellation for all gh CLI network I/Opkg/parser/remote_workflow_spec.go:91,93,156— ThreedownloadFileFromGitHub/resolveRefToSHAcalls hard-codecontext.Background(). The enclosing functions are called during compilation; an in-progress compile cannot be cancelled at this step. A TODO comment at line 71 already acknowledges thispkg/cli/logs_orchestrator_filters.go:167—fetchJobStatusesForProcessedRun(context.Background(), ...)insidebuildRunsModel; the enclosing flow is called from log-download commands that carry a live contextpkg/cli/update_extension_check.go:49—upgradeExtensionIfOutdatedcreates no context parameter; its only caller (runUpgradeCommandat line 245) holdsopts.ctxfrom cobra. GitHub API call for the latest release is fully uncancellablepkg/cli/syft.go:67—RunSyftOnLockFilesis called fromcompilePipelinewhich checksctx.Err()right before the call, butrunSyftScanscreates a freshcontext.Background()internally and never propagates cancellation into the image-scan loopDetailed Analysis
pkg/workflow/github_cli.go— Non-context gh wrappers (92 downstream callers)The three context-less wrappers exist for convenience but create a systemic leakage:
All 92 call sites of these functions could inherit caller context if the functions were removed and callers migrated to the
*Contextvariants.pkg/parser/remote_workflow_spec.go— Acknowledged TODOThe calling functions accept no
ctxparameter, so fixing requires a signature change to propagate the compiler's context.pkg/cli/logs_orchestrator_filters.go:167The
fetchJobStatusesForProcessedRunfunction accepts acontext.Context; only the call site supplies the wrong one.pkg/cli/update_extension_check.go:49+pkg/cli/upgrade_command.go:245The fix requires adding
ctx context.ContexttoupgradeExtensionIfOutdatedand threading it fromopts.ctxinrunUpgradeCommand.🤖 Tasks for Copilot Agent
NOTE TO PLANNER AGENT: Split the following tasks into individual work items.
Improvement Tasks
Task 1: Deprecate Non-Context gh Wrappers and Migrate Top Call Sites
Priority: High
Estimated Effort: Medium
Focus Area: context.Background() Call-Chain Leakage
Description: The three context-less wrapper functions
ExecGH,RunGH, andRunGHCombinedinpkg/workflow/github_cli.go(lines 106, 191, 213) hard-codecontext.Background()while calling their context-aware siblings. Identify all call sites usinggrep -rn 'ExecGH\|RunGH\|RunGHCombined' pkg/ cmd/(excluding the*Contextvariants), add a// Deprecated:doc comment to each wrapper, and migrate call sites insidepkg/cli/that already have actxvariable in scope to the corresponding*Contextvariant.Acceptance Criteria:
ExecGH,RunGH,RunGHCombinedeach have a// Deprecated: use the *Context variantdoc commentpkg/cli/that have a localctx context.Contextin scope are migrated to pass that contextmake fmtpassesmake test-unitpassesCode Region:
pkg/workflow/github_cli.go,pkg/cli/Task 2: Propagate Caller Context Through Remote Workflow Spec Fetchers
Priority: High
Estimated Effort: Medium
Focus Area: context.Background() Call-Chain Leakage
Description:
pkg/parser/remote_workflow_spec.gocontains threecontext.Background()network calls on lines 91, 93, and 156 with a TODO comment at line 71 acknowledging the gap. The enclosing functions (downloadRemoteFileForImport,resolveRemoteRef) lackctxparameters. Addctx context.Contextparameters to these functions and propagate the compiler's context from callers inpkg/parser/andpkg/cli/.Acceptance Criteria:
downloadRemoteFileForImportandresolveRemoteRef(or equivalent enclosing functions) acceptctx context.Contextcontext.Background()calls on lines 91/93/156 are replaced with the propagated ctxpkg/parser/andpkg/cli/are updated to pass contextmake test-unitpassesCode Region:
pkg/parser/remote_workflow_spec.goTask 3: Thread Context Through upgradeExtensionIfOutdated
Priority: Medium
Estimated Effort: Small
Focus Area: context.Background() Call-Chain Leakage
Description:
upgradeExtensionIfOutdatedinpkg/cli/update_extension_check.go(line 49) has noctx context.Contextparameter, so its internal call togetLatestRelease(context.Background(), ...)(line 63) cannot be cancelled. Its only production callerrunUpgradeCommandinpkg/cli/upgrade_command.go(line 245) holdsopts.ctx. Add actxparameter and thread it.Acceptance Criteria:
upgradeExtensionIfOutdatedsignature becomesfunc upgradeExtensionIfOutdated(ctx context.Context, verbose bool, includePrereleases bool) (bool, string, error)getLatestReleasecall at line 63 uses the passed-in ctxrunUpgradeCommandat line 245 passesopts.ctx_test.gofiles are updatedmake test-unitpassesCode Region:
pkg/cli/update_extension_check.go,pkg/cli/upgrade_command.goTask 4: Fix context.Background() in logs_orchestrator_filters and syft scan loop
Priority: Medium
Estimated Effort: Small
Focus Area: context.Background() Call-Chain Leakage
Description: Two related context-leakage points in the log/scan pipeline: (a)
pkg/cli/logs_orchestrator_filters.go:167callsfetchJobStatusesForProcessedRun(context.Background(), ...)insidebuildRunsModel— the outer pipeline carries a live context that should flow here; (b)pkg/cli/syft.go:67creates a standalonecontext.Background()forrunSyftOnImagecalls inside an image-scan loop, whilecompile_pipeline.gochecksctx.Err()right before callingRunSyftOnLockFilesbut the ctx never reaches the loop.Acceptance Criteria:
buildRunsModel(or its enclosing function) inpkg/cli/logs_orchestrator_filters.goreceives actxparameter and passes it tofetchJobStatusesForProcessedRunRunSyftOnLockFiles/runSyftScansinpkg/cli/syft.goandpkg/cli/compile_external_tools.goacceptctx context.Contextand the scan loop uses itcompile_pipeline.gocall sites pass their localctxto the syft functionmake test-unitpassesCode Region:
pkg/cli/logs_orchestrator_filters.go,pkg/cli/syft.go,pkg/cli/compile_external_tools.go,pkg/cli/compile_pipeline.goTask 5: Add ctxbackground Linter Coverage for Wrapper Functions That Synthesise Background Context
Priority: Low
Estimated Effort: Small
Focus Area: context.Background() Call-Chain Leakage
Description: The existing
ctxbackgroundlinter inpkg/linters/ctxbackground/flagscontext.Background()inside functions that already receive a context parameter — but it does not flag wrapper functions whose only purpose is to call a*Contextsibling withcontext.Background()(e.g.ExecGH,RunGH,RunGHCombined). Extend the linter or add a new lint rule to detect this pattern: a function with nocontext.Contextparameter that calls an identically-named*Contextsibling with a hardcodedcontext.Background()as first argument.Acceptance Criteria:
ctxbackgroundflags the pattern:func Foo(args) { return FooContext(context.Background(), args) }github_cli.go(once deprecated) trigger the new rule or are excluded vianolintwith rationalepkg/linters/all.go(if a new analyzer)make test-unitpasses includingpkg/linters/...testsCode Region:
pkg/linters/ctxbackground/,pkg/linters/all.go📊 Historical Context
Previous Focus Areas
🎯 Recommendations
Immediate Actions (This Week)
Short-term Actions (This Month)
Long-term Actions (This Quarter)
📈 Success Metrics
*Contextvariants)Next Steps
References:
[§30271523540]— workflow run that generated this reportGenerated by Repository Quality Improvement Agent
All reactions