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
1 change: 1 addition & 0 deletions actions/setup/js/otlp.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ async function logSpan(toolName, attributes = {}, options = {}) {
refName: process.env.GITHUB_REF_NAME || "",
headRef: process.env.GITHUB_HEAD_REF || "",
sha: process.env.GITHUB_SHA || "",
job: process.env.GITHUB_JOB || "",
workflowRef: process.env.GH_AW_CURRENT_WORKFLOW_REF || process.env.GITHUB_WORKFLOW_REF || "",
staged,
});
Expand Down
9 changes: 9 additions & 0 deletions actions/setup/js/otlp.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ describe("otlp.cjs", () => {
GITHUB_REF_NAME: process.env.GITHUB_REF_NAME,
GITHUB_HEAD_REF: process.env.GITHUB_HEAD_REF,
GITHUB_SHA: process.env.GITHUB_SHA,
GITHUB_JOB: process.env.GITHUB_JOB,
GITHUB_WORKFLOW_REF: process.env.GITHUB_WORKFLOW_REF,
GH_AW_CURRENT_WORKFLOW_REF: process.env.GH_AW_CURRENT_WORKFLOW_REF,
GH_AW_INFO_STAGED: process.env.GH_AW_INFO_STAGED,
Expand Down Expand Up @@ -414,6 +415,14 @@ describe("otlp.cjs", () => {

expect(mockBuildGitHubActionsResourceAttributes).toHaveBeenCalledWith(expect.objectContaining({ sha: "abc123def456" }));
});

it("passes GITHUB_JOB to buildGitHubActionsResourceAttributes when set", async () => {
process.env.GITHUB_JOB = "agent";

await otlp.logSpan("my-scanner", {});

expect(mockBuildGitHubActionsResourceAttributes).toHaveBeenCalledWith(expect.objectContaining({ job: "agent" }));
Comment on lines +420 to +424
});
});

// ---------------------------------------------------------------------------
Expand Down
12 changes: 9 additions & 3 deletions actions/setup/js/send_otlp_span.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -297,13 +297,14 @@ function buildOTLPResourceAttributes(serviceName, scopeVersion, resourceAttribut
* refName?: string,
* headRef?: string,
* sha?: string,
* job?: string,
* workflowRef?: string,
* staged: boolean,
* runAttempt?: string,
* }} ctx
* @returns {Array<{key: string, value: object}>}
*/
function buildGitHubActionsResourceAttributes({ repository, runId, eventName = "", ref = "", refName = "", headRef = "", sha = "", workflowRef = "", staged, runAttempt = "1" }) {
function buildGitHubActionsResourceAttributes({ repository, runId, eventName = "", ref = "", refName = "", headRef = "", sha = "", job = "", workflowRef = "", staged, runAttempt = "1" }) {
const resourceAttributes = [buildAttr("github.repository", repository), buildAttr("github.run_id", runId), buildAttr("github.run_attempt", runAttempt)];
if (repository && runId && repository.includes("/")) {
const [owner, repo] = repository.split("/");
Expand All @@ -324,6 +325,9 @@ function buildGitHubActionsResourceAttributes({ repository, runId, eventName = "
if (sha) {
resourceAttributes.push(buildAttr("github.sha", sha));
}
if (job) {
resourceAttributes.push(buildAttr("github.job", job));
}
if (workflowRef) {
resourceAttributes.push(buildAttr("github.workflow_ref", workflowRef));
}
Expand Down Expand Up @@ -873,6 +877,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 job = process.env.GITHUB_JOB || "";
const workflowRef = process.env.GH_AW_CURRENT_WORKFLOW_REF || process.env.GITHUB_WORKFLOW_REF || "";

const attributes = [
Expand Down Expand Up @@ -914,7 +919,7 @@ async function sendJobSetupSpan(options = {}) {
attributes.push(...buildExperimentAttributes(experimentAssignments));
attributes.push(...buildEpisodeAttributesFromContext(awInfo, runId, runAttempt));

const resourceAttributes = buildGitHubActionsResourceAttributes({ repository, runId, eventName, ref, refName, headRef, sha, workflowRef, staged, runAttempt });
const resourceAttributes = buildGitHubActionsResourceAttributes({ repository, runId, eventName, ref, refName, headRef, sha, job, workflowRef, staged, runAttempt });

const payload = buildOTLPPayload({
traceId,
Expand Down Expand Up @@ -1232,6 +1237,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 job = process.env.GITHUB_JOB || "";
const workflowRef = process.env.GITHUB_WORKFLOW_REF || "";

// Agent conclusion is passed to downstream jobs via GH_AW_AGENT_CONCLUSION.
Expand Down Expand Up @@ -1365,7 +1371,7 @@ async function sendJobConclusionSpan(spanName, options = {}) {
const conclusionExperimentAssignments = readExperimentAssignments();
attributes.push(...buildExperimentAttributes(conclusionExperimentAssignments));

const resourceAttributes = buildGitHubActionsResourceAttributes({ repository, runId, eventName, ref, refName, headRef, sha, workflowRef, staged, runAttempt });
const resourceAttributes = buildGitHubActionsResourceAttributes({ repository, runId, eventName, ref, refName, headRef, sha, job, workflowRef, staged, runAttempt });
// OpenTelemetry semantic convention for exceptions. Each event has
// name="exception" with "exception.type" and "exception.message" attributes,
// making individual errors queryable and classifiable in backends like
Expand Down
30 changes: 30 additions & 0 deletions actions/setup/js/send_otlp_span.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -1074,6 +1074,7 @@ describe("sendJobSetupSpan", () => {
"GITHUB_REF_NAME",
"GITHUB_HEAD_REF",
"GITHUB_SHA",
"GITHUB_JOB",
"GITHUB_WORKFLOW_REF",
"GH_AW_INFO_VERSION",
"GH_AW_INFO_STAGED",
Expand Down Expand Up @@ -1539,6 +1540,20 @@ describe("sendJobSetupSpan", () => {
expect(resourceKeys).not.toContain("github.workflow_ref");
});

it("includes github.job as resource attribute when GITHUB_JOB is set", async () => {
const mockFetch = vi.fn().mockResolvedValue({ ok: true, status: 200, statusText: "OK" });
vi.stubGlobal("fetch", mockFetch);

process.env.GH_AW_OTLP_ENDPOINTS = JSON.stringify([{ url: "https://traces.example.com" }]);
process.env.GITHUB_JOB = "agent";

await sendJobSetupSpan();

const body = JSON.parse(mockFetch.mock.calls[0][1].body);
const resourceAttrs = body.resourceSpans[0].resource.attributes;
expect(resourceAttrs).toContainEqual({ key: "github.job", value: { stringValue: "agent" } });
Comment on lines +1547 to +1554
});

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 @@ -2106,6 +2121,7 @@ describe("sendJobConclusionSpan", () => {
"GITHUB_REF_NAME",
"GITHUB_HEAD_REF",
"GITHUB_SHA",
"GITHUB_JOB",
"GITHUB_WORKFLOW_REF",
"INPUT_JOB_NAME",
"GH_AW_AGENT_CONCLUSION",
Expand Down Expand Up @@ -3999,6 +4015,20 @@ describe("sendJobConclusionSpan", () => {
expect(resourceKeys).not.toContain("github.workflow_ref");
});

it("includes github.job as resource attribute when GITHUB_JOB is set", async () => {
const mockFetch = vi.fn().mockResolvedValue({ ok: true, status: 200, statusText: "OK" });
vi.stubGlobal("fetch", mockFetch);

process.env.GH_AW_OTLP_ENDPOINTS = JSON.stringify([{ url: "https://traces.example.com" }]);
process.env.GITHUB_JOB = "conclusion";

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.job", value: { stringValue: "conclusion" } });
});

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

Expand Down