Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions actions/setup/js/send_otlp_span.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ async function sendJobSetupSpan(options = {}) {
const refName = process.env.GITHUB_REF_NAME || "";
const headRef = process.env.GITHUB_HEAD_REF || "";
const sha = process.env.GITHUB_SHA || "";
const workflowRef = process.env.GITHUB_WORKFLOW_REF || "";

const attributes = [
buildAttr("gh-aw.job.name", jobName),
Expand Down Expand Up @@ -533,6 +534,9 @@ async function sendJobSetupSpan(options = {}) {
if (sha) {
resourceAttributes.push(buildAttr("github.sha", sha));
}
if (workflowRef) {
resourceAttributes.push(buildAttr("github.workflow_ref", workflowRef));
}
resourceAttributes.push(buildAttr("deployment.environment", staged ? "staging" : "production"));

const payload = buildOTLPPayload({
Expand Down Expand Up @@ -705,6 +709,7 @@ async function sendJobConclusionSpan(spanName, options = {}) {
const refName = process.env.GITHUB_REF_NAME || "";
const headRef = process.env.GITHUB_HEAD_REF || "";
const sha = process.env.GITHUB_SHA || "";
const workflowRef = process.env.GITHUB_WORKFLOW_REF || "";

// Agent conclusion is passed to downstream jobs via GH_AW_AGENT_CONCLUSION.
// Values: "success", "failure", "timed_out", "cancelled", "skipped".
Expand Down Expand Up @@ -819,6 +824,9 @@ async function sendJobConclusionSpan(spanName, options = {}) {
if (sha) {
resourceAttributes.push(buildAttr("github.sha", sha));
}
if (workflowRef) {
resourceAttributes.push(buildAttr("github.workflow_ref", workflowRef));
}
resourceAttributes.push(buildAttr("deployment.environment", staged ? "staging" : "production"));

// Build OTel exception span events — one per error — following the
Expand Down
58 changes: 58 additions & 0 deletions actions/setup/js/send_otlp_span.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,7 @@ describe("sendJobSetupSpan", () => {
"GITHUB_REF_NAME",
"GITHUB_HEAD_REF",
"GITHUB_SHA",
"GITHUB_WORKFLOW_REF",
"GH_AW_INFO_VERSION",
"GH_AW_INFO_STAGED",
];
Expand Down Expand Up @@ -1286,6 +1287,34 @@ describe("sendJobSetupSpan", () => {
expect(resourceKeys).not.toContain("github.sha");
});

it("includes github.workflow_ref as resource attribute when GITHUB_WORKFLOW_REF is set", 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_REF = "owner/repo/.github/workflows/my-workflow.yml@refs/heads/main";

await sendJobSetupSpan();

const body = JSON.parse(mockFetch.mock.calls[0][1].body);
const resourceAttrs = body.resourceSpans[0].resource.attributes;
expect(resourceAttrs).toContainEqual({ key: "github.workflow_ref", value: { stringValue: "owner/repo/.github/workflows/my-workflow.yml@refs/heads/main" } });
});

it("omits github.workflow_ref resource attribute when GITHUB_WORKFLOW_REF is not set", 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 sendJobSetupSpan();

const body = JSON.parse(mockFetch.mock.calls[0][1].body);
const resourceAttrs = body.resourceSpans[0].resource.attributes;
const resourceKeys = resourceAttrs.map(a => a.key);
expect(resourceKeys).not.toContain("github.workflow_ref");
});

it("includes github.actions.run_url as resource attribute when repository and run_id are set", async () => {
const mockFetch = vi.fn().mockResolvedValue({ ok: true, status: 200, statusText: "OK" });
vi.stubGlobal("fetch", mockFetch);
Expand Down Expand Up @@ -1554,6 +1583,7 @@ describe("sendJobConclusionSpan", () => {
"GITHUB_REF_NAME",
"GITHUB_HEAD_REF",
"GITHUB_SHA",
"GITHUB_WORKFLOW_REF",
"INPUT_JOB_NAME",
"GH_AW_AGENT_CONCLUSION",
"GH_AW_INFO_WORKFLOW_NAME",
Expand Down Expand Up @@ -2914,6 +2944,34 @@ describe("sendJobConclusionSpan", () => {
});
});

it("includes github.workflow_ref as resource attribute when GITHUB_WORKFLOW_REF is set", 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_REF = "owner/repo/.github/workflows/my-workflow.yml@refs/heads/main";

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

const body = JSON.parse(mockFetch.mock.calls[0][1].body);
const resourceAttrs = body.resourceSpans[0].resource.attributes;
expect(resourceAttrs).toContainEqual({ key: "github.workflow_ref", value: { stringValue: "owner/repo/.github/workflows/my-workflow.yml@refs/heads/main" } });
});

it("omits github.workflow_ref resource attribute when GITHUB_WORKFLOW_REF is not set", 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");

const body = JSON.parse(mockFetch.mock.calls[0][1].body);
const resourceAttrs = body.resourceSpans[0].resource.attributes;
const resourceKeys = resourceAttrs.map(a => a.key);
expect(resourceKeys).not.toContain("github.workflow_ref");
});

describe("staged / deployment.environment", () => {
let readFileSpy;

Expand Down
Loading