Skip to content
Merged
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
52 changes: 52 additions & 0 deletions integration-tests/globalSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,58 @@ export async function setup() {
console.log(`\nIntegration test output directory: ${runDir}`);
console.log(`SDK E2E test output directory: ${sdkE2eRunDir}`);
console.log(`CLI path: ${process.env['TEST_CLI_PATH']}`);

await authPreflight();
}

/**
* Fail fast on a bad gateway credential.
*
* The model-driving E2E tests each spawn the CLI, which aborts on a failed
* auth preflight (HTTP 401) with exit code 1. When the gateway key is expired
* or revoked, that surfaces as ~200 opaque "CLI process exited with code 1"
* assertion failures across the suite — a 25-minute red run with no obvious
* cause (see protoCLI#226). Probing `/models` once here turns that into a
* single clear message and aborts the whole suite immediately.
*
* Only runs when OpenAI-compatible creds are present; a missing key is left
* to the individual tests (some auth paths don't use these env vars). A
* network error is treated as transient and does not block the run — only an
* explicit 401/403 (credential rejection) fails the suite.
*/
async function authPreflight(): Promise<void> {
const baseUrl = process.env['OPENAI_BASE_URL'];
const apiKey = process.env['OPENAI_API_KEY'];
if (!baseUrl || !apiKey) return;

const modelsUrl = `${baseUrl.replace(/\/$/, '')}/models`;
let status: number | undefined;
try {
const res = await fetch(modelsUrl, {
method: 'GET',
headers: { Authorization: `Bearer ${apiKey}` },
signal: AbortSignal.timeout(10_000),
});
status = res.status;
} catch (err) {
// Network error / timeout — don't block the run on transient infra.
console.warn(
`Auth preflight skipped (network error reaching ${modelsUrl}): ${
err instanceof Error ? err.message : String(err)
}`,
);
return;
}

if (status === 401 || status === 403) {
throw new Error(
`E2E auth preflight failed: HTTP ${status} from ${modelsUrl}.\n` +
`The gateway credential (OPENAI_API_KEY / OPENAI_BASE_URL) is invalid, ` +
`expired, or revoked. Rotate the repo secret before re-running — every ` +
`model-driving test will otherwise fail with "CLI process exited with code 1". ` +
`See protoCLI#226.`,
);
}
}

export async function teardown() {
Expand Down
Loading