MCPcopy Create free account
hub / github.com/github/gh-aw / sendJobSetupSpan

Function sendJobSetupSpan

actions/setup/js/send_otlp_span.cjs:1214–1393  ·  view source on GitHub ↗

* Send a `gh-aw. .setup` span (or `gh-aw.job.setup` when no job name * is configured) to the configured OTLP endpoint. * * This is designed to be called from `actions/setup/index.js` immediately after * the setup script completes. It always returns `{ traceId, spanId, parentSpanId }` so

(options = {})

Source from the content-addressed store, hash-verified

1212 * @returns {Promise<{ traceId: string, spanId: string, parentSpanId: string }>} The trace/span IDs used and resolved parent span ID.
1213 */
1214async function sendJobSetupSpan(options = {}) {
1215 // Resolve the trace ID before the early-return so it is always available as
1216 // an action output regardless of whether OTLP is configured.
1217 // Priority: options.traceId > INPUT_TRACE_ID > aw_info.context.otel_trace_id > newly generated ID.
1218 // Invalid (wrong length, non-hex) values are silently discarded.
1219
1220 // Validate options.traceId if supplied; callers may pass raw user input.
1221 const optionsTraceId = options.traceId && isValidTraceId(options.traceId) ? options.traceId : "";
1222 const optionsParentSpanId = options.parentSpanId && isValidSpanId(options.parentSpanId) ? options.parentSpanId : "";
1223
1224 // Normalize INPUT_TRACE_ID to lowercase before validating: OTLP requires lowercase
1225 // hex, but trace IDs pasted from external tools may use uppercase characters.
1226 // Also handle INPUT_TRACE-ID (with hyphen) in case the runner preserves the original
1227 // input name hyphen instead of converting it to an underscore.
1228 const rawInputTraceId = (process.env.INPUT_TRACE_ID || process.env["INPUT_TRACE-ID"] || "").trim().toLowerCase();
1229 const inputTraceId = isValidTraceId(rawInputTraceId) ? rawInputTraceId : "";
1230 const rawInputParentSpanId = (process.env.INPUT_PARENT_SPAN_ID || process.env["INPUT_PARENT-SPAN-ID"] || "").trim().toLowerCase();
1231 const inputParentSpanId = isValidSpanId(rawInputParentSpanId) ? rawInputParentSpanId : "";
1232
1233 // When this job was dispatched by a parent workflow, the parent's trace ID is
1234 // propagated via aw_context.otel_trace_id → aw_info.context.otel_trace_id so that
1235 // composite-action spans share a single trace with their caller.
1236 const awInfo = readJSONIfExists("/tmp/gh-aw/aw_info.json") || {};
1237 const setupAwContext = parseSetupAwContext(process.env.GH_AW_SETUP_AW_CONTEXT);
1238 if ((!awInfo.context || typeof awInfo.context !== "object") && Object.keys(setupAwContext).length > 0) {
1239 awInfo.context = setupAwContext;
1240 }
1241 const rawContextTraceId = typeof awInfo.context?.otel_trace_id === "string" ? awInfo.context.otel_trace_id.trim().toLowerCase() : "";
1242 const contextTraceId = isValidTraceId(rawContextTraceId) ? rawContextTraceId : "";
1243 // When this job was dispatched by a parent workflow, the parent's setup span ID is
1244 // propagated via aw_context.otel_parent_span_id → aw_info.context.otel_parent_span_id so
1245 // that the child's setup span is nested under the parent's setup span in the trace.
1246 const rawContextParentSpanId = typeof awInfo.context?.otel_parent_span_id === "string" ? awInfo.context.otel_parent_span_id.trim().toLowerCase() : "";
1247 const contextParentSpanId = isValidSpanId(rawContextParentSpanId) ? rawContextParentSpanId : "";
1248 const staged = awInfo.staged === true || process.env.GH_AW_INFO_STAGED === "true";
1249 const itemType = typeof awInfo.context?.item_type === "string" ? awInfo.context.item_type : "";
1250 const itemNumber = typeof awInfo.context?.item_number === "string" ? awInfo.context.item_number : "";
1251 const triggerLabel = typeof awInfo.context?.trigger_label === "string" ? awInfo.context.trigger_label : "";
1252 const commentId = typeof awInfo.context?.comment_id === "string" ? awInfo.context.comment_id : "";
1253 const frontmatterSource = (typeof awInfo.frontmatter_source === "string" ? awInfo.frontmatter_source : "") || process.env.GH_AW_INFO_FRONTMATTER_SOURCE || "";
1254 const frontmatterEmoji = (typeof awInfo.frontmatter_emoji === "string" ? awInfo.frontmatter_emoji : "") || process.env.GH_AW_INFO_FRONTMATTER_EMOJI || "";
1255 const awfVersion = (typeof awInfo.awf_version === "string" ? awInfo.awf_version : "") || process.env.GH_AW_INFO_AWF_VERSION || "";
1256 const awmgVersion = (typeof awInfo.awmg_version === "string" ? awInfo.awmg_version : "") || process.env.GH_AW_INFO_AWMG_VERSION || "";
1257 const bodyModified = typeof awInfo.body_modified === "boolean" ? awInfo.body_modified : parseBooleanEnv(process.env.GH_AW_INFO_BODY_MODIFIED);
1258
1259 const traceId = optionsTraceId || inputTraceId || contextTraceId || generateTraceId();
1260 const parentSpanId = optionsParentSpanId || inputParentSpanId || contextParentSpanId || "";
1261
1262 // Always generate a span ID so it can be written to GITHUB_ENV as
1263 // GITHUB_AW_OTEL_PARENT_SPAN_ID even when OTLP is not configured, allowing downstream
1264 // scripts to establish the correct parent span context.
1265 const spanId = generateSpanId();
1266
1267 // Build the full payload unconditionally so the JSONL mirror is always written,
1268 // enabling artifact-based debugging even without a live OTLP collector.
1269 const startMs = options.startMs ?? nowMs();
1270 const endMs = nowMs();
1271

Callers 3

runFunction · 0.85

Calls 15

isValidTraceIdFunction · 0.85
isValidSpanIdFunction · 0.85
parseSetupAwContextFunction · 0.85
parseBooleanEnvFunction · 0.85
generateTraceIdFunction · 0.85
generateSpanIdFunction · 0.85
resolveEngineIdFunction · 0.85
buildAttrFunction · 0.85

Tested by

no test coverage detected