fix: include workflow ID in experiment artifact cache keys and artifact name#29747
fix: include workflow ID in experiment artifact cache keys and artifact name#29747
Conversation
…ct name
- Replace `${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}` in experiment cache
keys with the literal sanitized workflow ID baked in at compile time.
The activation job does not set this env var, so the cache key was
resolving to an empty string (e.g. `experiments--<run_id>`).
- Include the sanitized workflow ID as prefix in the experiment artifact
name for non-workflow_call workflows (e.g. `smokecopilot-experiment`).
- Update `buildExperimentArtifactDownloadSteps` to accept `*WorkflowData`
and compute the correct artifact name for both workflow_call and regular
workflows.
- Recompile affected lock files and update golden test fixtures.
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/0b4d51cc-ad50-45c8-add4-48e3e0fe09b3
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…mpty ID fallback Agent-Logs-Url: https://github.com/github/gh-aw/sessions/0b4d51cc-ad50-45c8-add4-48e3e0fe09b3 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes experiment cache key + artifact naming so experiment state is scoped per workflow (avoids cross-workflow cache/artifact collisions), including in activation jobs where GH_AW_WORKFLOW_ID_SANITIZED is not set.
Changes:
- Embed a compile-time sanitized workflow ID into experiment cache keys and (non-
workflow_call) artifact names. - Refactor experiment artifact download step generation to derive the correct artifact name from
WorkflowData(consistent forworkflow_callvs regular workflows). - Update tests, lockfiles, and golden fixtures to reflect the new naming.
Show a summary per file
| File | Description |
|---|---|
pkg/workflow/compiler_experiments.go |
Computes cache keys using compile-time sanitized workflow ID; updates upload/download artifact naming helpers. |
pkg/workflow/compiler_experiments_test.go |
Adjusts tests to assert workflow-scoped cache keys/artifact names and updated helper signature. |
pkg/workflow/threat_detection.go |
Updates call site to new buildExperimentArtifactDownloadSteps(*WorkflowData) signature. |
pkg/workflow/testdata/TestWasmGolden_CompileFixtures/with-imports.golden |
Golden output updates from recompilation (pinned action SHAs / formatting). |
pkg/workflow/testdata/TestWasmGolden_CompileFixtures/smoke-copilot.golden |
Golden output updates from recompilation (pinned action SHAs / formatting). |
pkg/workflow/testdata/TestWasmGolden_CompileFixtures/basic-copilot.golden |
Golden output updates from recompilation (pinned action SHAs / formatting). |
.github/workflows/smoke-copilot.lock.yml |
Updates experiment cache keys and artifact name to include sanitized workflow ID. |
.github/workflows/daily-community-attribution.lock.yml |
Updates experiment cache keys and artifact name to include sanitized workflow ID. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (2)
pkg/workflow/compiler_experiments.go:258
sanitizedIDis used unconditionally in the cache key/restore key format strings. Ifdata.WorkflowIDis empty (or sanitizes to an empty string), this will still produce keys likeexperiments--${{ github.run_id }}and reintroduce cross-workflow cache collisions. Consider explicitly validatingdata.WorkflowID/sanitizedIDwhen experiments are enabled, or falling back to a non-empty, workflow-scoped identifier.
// Use the literal sanitized workflow ID in the cache key so it is correct in the
// activation job, which does not have GH_AW_WORKFLOW_ID_SANITIZED in its environment.
sanitizedID := SanitizeWorkflowIDForCacheKey(data.WorkflowID)
cacheKey := fmt.Sprintf("experiments-%s-${{ github.run_id }}", sanitizedID)
restoreKey := fmt.Sprintf("experiments-%s-", sanitizedID)
pkg/workflow/compiler_experiments.go:412
experimentArtifactUploadNametakessanitizedIDas a separate parameter even though it can be derived fromdata.WorkflowID. This makes it easier for callers to accidentally pass a mismatched value (leading to upload/download name divergence). Since sanitization is cheap, consider computing the sanitized ID inside the helper (or accepting the raw workflow ID) to keep the API harder to misuse.
func experimentArtifactUploadName(data *WorkflowData, sanitizedID string) string {
if hasWorkflowCallTrigger(data.On) {
return artifactPrefixExprForActivationJob(data) + constants.ExperimentArtifactName
}
if sanitizedID == "" {
return constants.ExperimentArtifactName
}
return sanitizedID + "-" + constants.ExperimentArtifactName
}
- Files reviewed: 8/8 changed files
- Comments generated: 1
| // writes a Markdown step summary); outputs: one per experiment (e.g. "caveman=yes") + "experiments" JSON blob | ||
| // 3. Save experiment cache – actions/cache/save keyed by workflow ID | ||
| // 4. Upload experiment artifact – actions/upload-artifact named "experiment" | ||
| // 4. Upload experiment artifact – actions/upload-artifact named "{workflowID}-experiment" |
🧪 Test Quality Sentinel ReportTest Quality Score: 97/100✅ Excellent test quality
Test Classification Details
Analysis Notes
No issues detected: build tag present ( Language SupportTests analyzed:
Verdict
📖 Understanding Test ClassificationsDesign Tests (High Value) verify what the system does:
Implementation Tests (Low Value) verify how the system does it:
Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators. References: §25250407795
|
Summary
Fixes the experiment artifact key generation to include the workflow ID.
Root Cause
The experiment cache steps in the activation job used
${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}in their cache keys:However,
GH_AW_WORKFLOW_ID_SANITIZEDis only set in the agent job environment — not in the activation job. At runtime this env var evaluates to an empty string, resulting in cache keys likeexperiments--12345instead ofexperiments-smokecopilot-12345. This means:Similarly, the experiment artifact was uploaded as just
"experiment"without any workflow ID scoping.Fix
Cache keys: Replace
${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}with the literal sanitized workflow ID baked in at compile time (sincedata.WorkflowIDis known when the workflow is compiled):Artifact name: Include the sanitized workflow ID as prefix for non-
workflow_callworkflows:buildExperimentArtifactDownloadSteps: Updated to accept*WorkflowDatainstead of a prefix string, computing the correct artifact name for bothworkflow_calland regular workflows. Upload and download names are always consistent.Files Changed
pkg/workflow/compiler_experiments.go— core fix + new helperspkg/workflow/threat_detection.go— updated call sitepkg/workflow/compiler_experiments_test.go— updated testsReference: https://github.com/github/gh-aw/actions/runs/25249937943/job/74040362646#step:14:1