Skip to content

fix: add env-var fallbacks for gh-aw.workflow.name in conclusion spans#26320

Merged
pelikhan merged 2 commits intomainfrom
copilot/otel-improvement-add-env-var-fallbacks
Apr 14, 2026
Merged

fix: add env-var fallbacks for gh-aw.workflow.name in conclusion spans#26320
pelikhan merged 2 commits intomainfrom
copilot/otel-improvement-add-env-var-fallbacks

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 14, 2026

sendJobConclusionSpan resolved workflowName exclusively from aw_info.json, which is only written by the agent step. Jobs that fail before the agent runs (or non-agent jobs like safe-outputs and activation) emit conclusion spans with gh-aw.workflow.name: "", making them invisible in any dashboard filtering by workflow name — exactly the failure signals that matter most for MTTR.

Changes

  • send_otlp_span.cjs — mirror the three-layer fallback already used by sendJobSetupSpan:

    // before
    const workflowName = awInfo.workflow_name || "";
    
    // after
    const workflowName = awInfo.workflow_name || process.env.GH_AW_INFO_WORKFLOW_NAME || process.env.GITHUB_WORKFLOW || "";

    GH_AW_INFO_WORKFLOW_NAME is compiler-injected at job level and is always present in the post-step runner environment where conclusion spans are sent.

  • send_otlp_span.test.cjs — add GH_AW_INFO_WORKFLOW_NAME and GITHUB_WORKFLOW to the env cleanup list for sendJobConclusionSpan tests, and add four new tests covering each tier of the fallback chain: aw_info.jsonGH_AW_INFO_WORKFLOW_NAMEGITHUB_WORKFLOW"".

Copilot AI changed the title [WIP] Add env-var fallbacks for gh-aw.workflow.name in conclusion spans fix: add env-var fallbacks for gh-aw.workflow.name in conclusion spans Apr 14, 2026
Copilot AI requested a review from pelikhan April 14, 2026 22:55
@pelikhan pelikhan marked this pull request as ready for review April 14, 2026 23:10
Copilot AI review requested due to automatic review settings April 14, 2026 23:10
@pelikhan pelikhan merged commit 0d482d5 into main Apr 14, 2026
69 checks passed
@pelikhan pelikhan deleted the copilot/otel-improvement-add-env-var-fallbacks branch April 14, 2026 23:11
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR ensures sendJobConclusionSpan populates gh-aw.workflow.name even when aw_info.json is missing (e.g., jobs failing before the agent runs), by adding environment-variable fallbacks so conclusion spans remain discoverable in workflow-name–filtered dashboards.

Changes:

  • Add a fallback chain for workflowName in sendJobConclusionSpan: aw_info.jsonGH_AW_INFO_WORKFLOW_NAMEGITHUB_WORKFLOW"".
  • Extend sendJobConclusionSpan tests with new cases covering each tier of the fallback chain.
  • Update test env cleanup to include GH_AW_INFO_WORKFLOW_NAME and GITHUB_WORKFLOW.
Show a summary per file
File Description
actions/setup/js/send_otlp_span.cjs Adds env-var fallbacks for gh-aw.workflow.name in conclusion spans.
actions/setup/js/send_otlp_span.test.cjs Adds/updates tests and env cleanup to validate the new fallback behavior.

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)

actions/setup/js/send_otlp_span.test.cjs:1637

  • Similarly, this test assumes aw_info.json is absent but doesn’t stub filesystem reads. To keep the test hermetic, stub fs.readFileSync to throw ENOENT (or reuse a shared stub) so the fallback to GITHUB_WORKFLOW is deterministic.
  it("falls back to GITHUB_WORKFLOW when aw_info.json and GH_AW_INFO_WORKFLOW_NAME are absent", async () => {
    const mockFetch = vi.fn().mockResolvedValue({ ok: true, status: 200, statusText: "OK" });
    vi.stubGlobal("fetch", mockFetch);

    process.env.OTEL_EXPORTER_OTLP_ENDPOINT = "https://traces.example.com";
    process.env.GITHUB_WORKFLOW = "github-workflow";

    await sendJobConclusionSpan("gh-aw.job.conclusion");

actions/setup/js/send_otlp_span.test.cjs:1651

  • This test expects gh-aw.workflow.name to be empty when all sources are absent, but it still may read a real /tmp/gh-aw/aw_info.json if present. Stub fs.readFileSync to throw ENOENT here (or set up a default stub for the whole describe) so the test doesn’t depend on the host filesystem state.
  it("sets gh-aw.workflow.name to empty string when all sources are absent", async () => {
    const mockFetch = vi.fn().mockResolvedValue({ ok: true, status: 200, statusText: "OK" });
    vi.stubGlobal("fetch", mockFetch);

    process.env.OTEL_EXPORTER_OTLP_ENDPOINT = "https://traces.example.com";

    await sendJobConclusionSpan("gh-aw.job.conclusion");

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

@@ -681,7 +681,7 @@ async function sendJobConclusionSpan(spanName, options = {}) {
const rawParentSpanId = (process.env.GITHUB_AW_OTEL_PARENT_SPAN_ID || "").trim().toLowerCase();
const parentSpanId = isValidSpanId(rawParentSpanId) ? rawParentSpanId : "";

Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

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

sendJobConclusionSpan now resolves workflowName from GH_AW_INFO_WORKFLOW_NAME and GITHUB_WORKFLOW as fallbacks. The function’s JSDoc “Environment variables consumed” list should be updated to include these variables so the documentation matches the implementation.

Suggested change
// Resolve workflowName from aw_info first, then fall back to the environment
// variables GH_AW_INFO_WORKFLOW_NAME and GITHUB_WORKFLOW.

Copilot uses AI. Check for mistakes.
Comment on lines +1613 to +1622
it("falls back to GH_AW_INFO_WORKFLOW_NAME when aw_info.json is absent", async () => {
const mockFetch = vi.fn().mockResolvedValue({ ok: true, status: 200, statusText: "OK" });
vi.stubGlobal("fetch", mockFetch);

process.env.OTEL_EXPORTER_OTLP_ENDPOINT = "https://traces.example.com";
process.env.GH_AW_INFO_WORKFLOW_NAME = "env-workflow";
process.env.GITHUB_WORKFLOW = "github-workflow";

await sendJobConclusionSpan("gh-aw.job.conclusion");

Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

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

This test asserts behavior "when aw_info.json is absent" but doesn’t stub fs.readFileSync/readJSONIfExists to force that condition. If /tmp/gh-aw/aw_info.json exists on the machine running tests, the test will read it and may fail. Consider stubbing fs.readFileSync to throw ENOENT (or adding a default readFileSync stub in beforeEach for this describe) and overriding it only in tests that need file contents.

This issue also appears in the following locations of the same file:

  • line 1629
  • line 1644

Copilot uses AI. Check for mistakes.
@github-actions github-actions bot mentioned this pull request Apr 14, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 90/100

Excellent test quality

Metric Value
New/modified tests analyzed 4
✅ Design tests (behavioral contracts) 4 (100%)
⚠️ Implementation tests (low value) 0 (0%)
Tests with error/edge cases 4 (100%)
Duplicate test clusters 0
Test inflation detected Yes (71:1 ratio — see note below)
🚨 Coding-guideline violations None

Test Classification Details

Test File Classification Issues Detected
reads gh-aw.workflow.name from aw_info.json when present actions/setup/js/send_otlp_span.test.cjs ✅ Design None — verifies priority: aw_info.json wins over env vars
falls back to GH_AW_INFO_WORKFLOW_NAME when aw_info.json is absent actions/setup/js/send_otlp_span.test.cjs ✅ Design None — verifies first env-var fallback
falls back to GITHUB_WORKFLOW when aw_info.json and GH_AW_INFO_WORKFLOW_NAME are absent actions/setup/js/send_otlp_span.test.cjs ✅ Design None — verifies second env-var fallback
sets gh-aw.workflow.name to empty string when all sources are absent actions/setup/js/send_otlp_span.test.cjs ✅ Design None — verifies empty-string boundary condition

Flagged Tests — Requires Review

None. All 4 tests are behavioral design tests with no issues requiring remediation.


Test Inflation Note

The test-to-production line ratio is 71:1 (71 lines added in tests vs. 1 line in production), which mechanically triggers the inflation penalty (−10 pts). However, this is well-justified: the single production line encodes a 3-tier priority chain (aw_info.jsonGH_AW_INFO_WORKFLOW_NAMEGITHUB_WORKFLOW""), and each tier requires its own dedicated test to verify correct priority ordering. The inflation penalty is an artifact of the heuristic, not a real quality concern here.


Language Support

Tests analyzed:

  • 🐹 Go (*_test.go): 0 tests
  • 🟨 JavaScript (*.test.cjs): 4 tests (vitest)

Verdict

Check passed. 0% of new tests are implementation tests (threshold: 30%). All 4 new tests verify observable OTLP span attribute values under different priority-chain input configurations — a clear behavioral contract. Mocking targets (fs.readFileSync, fetch) are external I/O, which is acceptable practice.


📖 Understanding Test Classifications

Design Tests (High Value) verify what the system does:

  • Assert on observable outputs, return values, or state changes
  • Cover error paths and boundary conditions
  • Would catch a behavioral regression if deleted
  • Remain valid even after internal refactoring

Implementation Tests (Low Value) verify how the system does it:

  • Assert on internal function calls (mocking internals)
  • Only test the happy path with typical inputs
  • Break during legitimate refactoring even when behavior is correct
  • Give false assurance: they pass even when the system is wrong

Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators.

🧪 Test quality analysis by Test Quality Sentinel · ● 662.8K ·

Copy link
Copy Markdown
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

✅ Test Quality Sentinel: 90/100. Test quality is excellent — 0% of new tests are implementation tests (threshold: 30%). All 4 new tests verify the behavioral priority chain for gh-aw.workflow.name resolution in OTLP conclusion spans.

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.

[otel-advisor] OTel improvement: add env-var fallbacks for gh-aw.workflow.name in conclusion spans

3 participants