Skip to content

fix: normalize INPUT_JOB_NAME hyphen variant so OTLP spans include the actual job name#24823

Merged
pelikhan merged 2 commits intomainfrom
copilot/fix-otel-spend-job-name
Apr 6, 2026
Merged

fix: normalize INPUT_JOB_NAME hyphen variant so OTLP spans include the actual job name#24823
pelikhan merged 2 commits intomainfrom
copilot/fix-otel-spend-job-name

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 6, 2026

OTLP spans were emitting gh-aw.job.setup / gh-aw.job.conclusion instead of gh-aw.<jobname>.setup / gh-aw.<jobname>.conclusion because some runner versions set INPUT_JOB-NAME (hyphen) instead of the standard INPUT_JOB_NAME (underscore) — the same runner quirk already handled for INPUT_TRACE_ID.

Changes

  • index.js — normalize INPUT_JOB-NAMEINPUT_JOB_NAME at startup; pass canonical value into setup.sh env and set process.env.INPUT_JOB_NAME before delegating to action_setup_otlp.cjs
  • action_setup_otlp.cjs — apply the same two-key lookup as INPUT_TRACE_ID; canonicalize to underscore form in process.env so sendJobSetupSpan (which reads process.env.INPUT_JOB_NAME directly) always finds it
  • action_conclusion_otlp.cjs — replace direct process.env.INPUT_JOB_NAME read with normalized lookup before constructing the span name
  • setup.sh — explicitly forward INPUT_JOB_NAME to action_setup_otlp.cjs in script mode, alongside the existing INPUT_TRACE_ID
// Before — only underscore form checked
const spanName = process.env.INPUT_JOB_NAME
  ? `gh-aw.${process.env.INPUT_JOB_NAME}.conclusion`
  : "gh-aw.job.conclusion";

// After — hyphen fallback mirrors INPUT_TRACE_ID pattern
const jobName = (process.env.INPUT_JOB_NAME || process.env["INPUT_JOB-NAME"] || "").trim();
const spanName = jobName ? `gh-aw.${jobName}.conclusion` : "gh-aw.job.conclusion";

Some GitHub Actions runner versions preserve the original hyphen in
input env var names (INPUT_JOB-NAME) instead of converting to
underscore (INPUT_JOB_NAME). This caused OTLP spans to fall back to
the generic 'gh-aw.job.setup' / 'gh-aw.job.conclusion' names instead
of using the actual job name.

Apply the same two-key normalization already used for INPUT_TRACE_ID:
- index.js: normalize INPUT_JOB_NAME at startup, pass to setup.sh
  env and set in process.env before calling action_setup_otlp.cjs
- action_setup_otlp.cjs: normalize INPUT_JOB_NAME and canonicalize
  to underscore form so sendJobSetupSpan always finds the value
- action_conclusion_otlp.cjs: normalize INPUT_JOB_NAME inline
- setup.sh: explicitly pass INPUT_JOB_NAME to action_setup_otlp.cjs
  in script mode (alongside INPUT_TRACE_ID)

Tests added for the hyphen form in action_conclusion_otlp.test.cjs
and action_otlp.test.cjs.

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/099777bf-2d2a-4e33-b4a6-60eff2ca3d20

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@pelikhan pelikhan marked this pull request as ready for review April 6, 2026 04:13
Copilot AI review requested due to automatic review settings April 6, 2026 04:13
@pelikhan pelikhan merged commit 13ac7de into main Apr 6, 2026
50 checks passed
@pelikhan pelikhan deleted the copilot/fix-otel-spend-job-name branch April 6, 2026 04:13
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

Fixes OTLP span naming so job lifecycle spans consistently include the real job name even when some runner versions expose the input env var as INPUT_JOB-NAME (hyphen) instead of INPUT_JOB_NAME (underscore).

Changes:

  • Normalize INPUT_JOB[-_]NAME to the canonical underscore form in the JS entrypoint and setup-span sender.
  • Use a normalized job-name lookup in the conclusion-span sender.
  • Add tests to validate the hyphen-form job-name behavior for both setup and conclusion spans.
Show a summary per file
File Description
actions/setup/setup.sh Forwards INPUT_JOB_NAME into the script-mode action_setup_otlp.cjs invocation.
actions/setup/js/action_setup_otlp.cjs Normalizes job name from INPUT_JOB-NAME/INPUT_JOB_NAME and sets canonical process.env.INPUT_JOB_NAME.
actions/setup/js/action_otlp.test.cjs Adds a setup-span test covering the hyphen-form job-name env var.
actions/setup/js/action_conclusion_otlp.cjs Uses normalized job-name lookup when constructing conclusion span names.
actions/setup/js/action_conclusion_otlp.test.cjs Extends conclusion-span tests to cover hyphen-form env var and restores env properly.
actions/setup/index.js Normalizes job-name env var at startup and passes canonical value into setup.sh and action_setup_otlp.cjs.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 6/6 changed files
  • Comments generated: 3

Comment on lines +65 to +69
const inputJobName = (process.env.INPUT_JOB_NAME || process.env["INPUT_JOB-NAME"] || "").trim();
if (inputJobName) {
// Normalise to the canonical underscore form so sendJobSetupSpan (which
// reads process.env.INPUT_JOB_NAME) always finds the value.
process.env.INPUT_JOB_NAME = inputJobName;
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

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

The fallback order uses process.env.INPUT_JOB_NAME || process.env["INPUT_JOB-NAME"] before trimming, so a whitespace-only INPUT_JOB_NAME will shadow a valid hyphen-form value and resolve to an empty string after .trim(). Consider trimming each candidate first and then selecting the first non-empty value; also delete/clear process.env.INPUT_JOB_NAME when the trimmed result is empty so downstream sendJobSetupSpan() doesn’t treat whitespace as a real job name.

Suggested change
const inputJobName = (process.env.INPUT_JOB_NAME || process.env["INPUT_JOB-NAME"] || "").trim();
if (inputJobName) {
// Normalise to the canonical underscore form so sendJobSetupSpan (which
// reads process.env.INPUT_JOB_NAME) always finds the value.
process.env.INPUT_JOB_NAME = inputJobName;
const inputJobNameUnderscore = (process.env.INPUT_JOB_NAME || "").trim();
const inputJobNameHyphen = (process.env["INPUT_JOB-NAME"] || "").trim();
const inputJobName = inputJobNameUnderscore || inputJobNameHyphen;
if (inputJobName) {
// Normalise to the canonical underscore form so sendJobSetupSpan (which
// reads process.env.INPUT_JOB_NAME) always finds the value.
process.env.INPUT_JOB_NAME = inputJobName;
} else if (process.env.INPUT_JOB_NAME && !inputJobNameUnderscore) {
// Clear whitespace-only underscore-form input so downstream consumers do
// not treat it as a real job name.
delete process.env.INPUT_JOB_NAME;

Copilot uses AI. Check for mistakes.
const spanName = process.env.INPUT_JOB_NAME ? `gh-aw.${process.env.INPUT_JOB_NAME}.conclusion` : "gh-aw.job.conclusion";
// Normalize job-name input: handle both INPUT_JOB_NAME (underscore, standard)
// and INPUT_JOB-NAME (hyphen, used by some runner versions).
const jobName = (process.env.INPUT_JOB_NAME || process.env["INPUT_JOB-NAME"] || "").trim();
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

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

The lookup (process.env.INPUT_JOB_NAME || process.env["INPUT_JOB-NAME"]) occurs before trimming, so a whitespace-only INPUT_JOB_NAME will prevent the hyphen-form value from being used and will fall back to the default span name after .trim(). To make the fallback robust, trim both candidates first and pick the first non-empty trimmed value.

Suggested change
const jobName = (process.env.INPUT_JOB_NAME || process.env["INPUT_JOB-NAME"] || "").trim();
const underscoreJobName = (process.env.INPUT_JOB_NAME || "").trim();
const hyphenJobName = (process.env["INPUT_JOB-NAME"] || "").trim();
const jobName = underscoreJobName || hyphenJobName;

Copilot uses AI. Check for mistakes.
Comment on lines +155 to +176
it("uses job name from INPUT_JOB-NAME (hyphen form) in setup span when INPUT_JOB_NAME is not set", async () => {
const tmpOut = path.join(path.dirname(__dirname), `action_setup_otlp_test_job_name_hyphen_${Date.now()}.txt`);
try {
process.env.OTEL_EXPORTER_OTLP_ENDPOINT = "http://localhost:14317";
process.env["INPUT_JOB-NAME"] = "agent";
delete process.env.INPUT_JOB_NAME;
process.env.GITHUB_OUTPUT = tmpOut;
process.env.GITHUB_ENV = tmpOut;

let capturedBody;
const fetchSpy = vi.spyOn(global, "fetch").mockImplementation((_url, opts) => {
capturedBody = opts?.body;
return Promise.resolve(new Response(null, { status: 200 }));
});

await runSetup();

const payload = JSON.parse(capturedBody);
const spanName = payload?.resourceSpans?.[0]?.scopeSpans?.[0]?.spans?.[0]?.name;
expect(spanName).toBe("gh-aw.agent.setup");
fetchSpy.mockRestore();
} finally {
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

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

This test restores fetchSpy only on the success path; if an assertion throws, the spy can leak into later tests (this file doesn’t have a global vi.restoreAllMocks() in afterEach). Move fetchSpy.mockRestore() into the finally block (or add an afterEach that restores mocks) to keep the suite isolated.

Copilot uses AI. Check for mistakes.
github-actions bot added a commit that referenced this pull request Apr 6, 2026
… normalization

The two-key lookup pattern for normalizing GitHub Actions inputs (handling both
INPUT_X and INPUT_X-HYPHEN forms) was introduced in PR #24823 and repeated in
three places: index.js, action_setup_otlp.cjs, and action_conclusion_otlp.cjs.

Extract a getActionInput(name) helper in action_input_utils.cjs that:
- Checks both the underscore (standard) and hyphen (some runner versions) forms
- Trims whitespace from the result (aligning with GitHub Actions conventions)
- Documents the rationale once, rather than repeating it at each call site

This reduces code duplication, removes repetitive comments, and makes it easy
to add new inputs with the same normalization in the future.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

3 participants