From 7339ae6a7c9db63a567fe58ae7530a8fed6d8f2d Mon Sep 17 00:00:00 2001 From: Nico Pappagianis Date: Tue, 18 Aug 2026 10:26:11 -0700 Subject: [PATCH] chore: log orgId, pod, and UTC timestamp on NUT failures Emit a structured [NUT-CONTEXT] line at shared scratch-org setup and a [NUT-FAILURE] line on any failing z-series test, carrying orgId, instance/pod, a UTC timestamp (MM/DD/YYYY:HH:mm:ss), and the error, so CI failures can be correlated in Splunk. Only non-sensitive identifiers are logged; no auth tokens or devhub. --- test/nuts/shared-setup.ts | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/nuts/shared-setup.ts b/test/nuts/shared-setup.ts index 03a99e6c..d83968a1 100644 --- a/test/nuts/shared-setup.ts +++ b/test/nuts/shared-setup.ts @@ -26,6 +26,17 @@ import { sleep, ensureArray } from '@salesforce/kit'; let testSession: TestSession | undefined; let testSessionPromise: Promise | undefined; let agentUsername: string | undefined; +// Non-sensitive scratch-org identifiers captured at setup for CI failure correlation. +let orgId: string | undefined; +let orgPod: string | undefined; + +// Format a UTC timestamp as MM/DD/YYYY:HH:mm:ss for CI log correlation (Splunk-friendly). +function fmtUtc(d: Date): string { + const p = (n: number): string => String(n).padStart(2, '0'); + return `${p(d.getUTCMonth() + 1)}/${p(d.getUTCDate())}/${d.getUTCFullYear()}:${p(d.getUTCHours())}:${p( + d.getUTCMinutes() + )}:${p(d.getUTCSeconds())}`; +} // Helper function to wait for Einstein AI services to be ready async function waitForEinsteinReady(connection: Connection, maxAttempts = 30): Promise { @@ -103,6 +114,14 @@ export async function getTestSession(): Promise { const org = await Org.create({ aliasOrUsername: defaultOrg.username }); const connection = org.getConnection(); + // Capture non-sensitive org identifiers for CI failure correlation (orgId + pod + UTC timestamp). + orgId = org.getOrgId(); + const orgInfo = await connection.singleRecordQuery<{ InstanceName: string }>( + 'SELECT InstanceName FROM Organization' + ); + orgPod = orgInfo.InstanceName; + console.log(`[NUT-CONTEXT] utc=${fmtUtc(new Date())} orgId=${orgId} pod=${orgPod}`); + // assign the EinsteinGPTPromptTemplateManager to the scratch org admin user const queryResult = await connection.singleRecordQuery<{ Id: string; Name: string }>( `SELECT Id, Name FROM User WHERE Username='${defaultOrg.username}'` @@ -272,3 +291,18 @@ export function getAgentUsername(): string | undefined { } return agentUsername; } + +// Root-level hook: on any failing test that used the shared scratch org, emit orgId + pod + +// UTC timestamp + error so CI logs can be correlated in Splunk. Registered once when this shared +// module is first imported by the z-series NUTs. (A failing before-all hook is not caught here, but +// the [NUT-CONTEXT] line logged at setup still records that run's orgId + pod + time.) +afterEach(function (this: Mocha.Context) { + if (this.currentTest?.state === 'failed' && orgId) { + const err = this.currentTest.err; + console.log( + `[NUT-FAILURE] utc=${fmtUtc(new Date())} orgId=${orgId} pod=${ + orgPod ?? 'unknown' + } test="${this.currentTest.fullTitle()}" error=${err?.message ?? String(err)}` + ); + } +});