From 75c8e4343ec9b6ac0bc2a4d1457e89d97b1173f6 Mon Sep 17 00:00:00 2001 From: Bilal Godil Date: Tue, 26 May 2026 11:52:39 -0700 Subject: [PATCH] fix(ci): repair two pre-existing test failures on dev 1. apps/backend/src/lib/redirect-urls.test.tsx The withHostedHandlerEnv helper only set/cleared the STACK_*-prefixed env vars. CI's e2e-custom-base-port-api-tests workflow sets only the HEXCLAVE_*-prefixed sibling (NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX=67), and the dual-read shim in stack-shared/utils/env.tsx prefers HEXCLAVE_* over STACK_*. Result: getEnvVariable('NEXT_PUBLIC_STACK_PORT_PREFIX') returned '67' instead of the test's '92', breaking the assertion at line 75. Mirror every STACK_* key to its HEXCLAVE_* sibling so the dual-read resolves to the same value regardless of lookup order. 2. apps/backend/prisma/migrations/20260526060000_nullable_oauth_access_token_expires_at/tests/nullable-expires-at.ts Raw INSERT into OAuthAccessToken omitted the 'updatedAt' column. The Prisma model declares 'updatedAt DateTime @updatedAt' with no DB-level default; Prisma populates it at the ORM layer, but raw SQL bypasses that and hits the NOT NULL constraint. Set updatedAt = NOW() explicitly. --- .../tests/nullable-expires-at.ts | 9 +++- apps/backend/src/lib/redirect-urls.test.tsx | 47 +++++++++++-------- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/apps/backend/prisma/migrations/20260526060000_nullable_oauth_access_token_expires_at/tests/nullable-expires-at.ts b/apps/backend/prisma/migrations/20260526060000_nullable_oauth_access_token_expires_at/tests/nullable-expires-at.ts index c127b775d..9a4e4f6b4 100644 --- a/apps/backend/prisma/migrations/20260526060000_nullable_oauth_access_token_expires_at/tests/nullable-expires-at.ts +++ b/apps/backend/prisma/migrations/20260526060000_nullable_oauth_access_token_expires_at/tests/nullable-expires-at.ts @@ -55,6 +55,9 @@ export const postMigration = async (sql: Sql, ctx: Awaited { callback: () => T, ): T => { const processEnv = Reflect.get(process, "env"); - const oldHostedHandlerUrlTemplate = Reflect.get(processEnv, "NEXT_PUBLIC_STACK_HOSTED_HANDLER_URL_TEMPLATE"); - const oldHostedHandlerDomainSuffix = Reflect.get(processEnv, "NEXT_PUBLIC_STACK_HOSTED_HANDLER_DOMAIN_SUFFIX"); - const oldStackPortPrefix = Reflect.get(processEnv, "NEXT_PUBLIC_STACK_PORT_PREFIX"); - try { - for (const [key, value] of Object.entries({ - NEXT_PUBLIC_STACK_HOSTED_HANDLER_URL_TEMPLATE: values.hostedHandlerUrlTemplate, - NEXT_PUBLIC_STACK_HOSTED_HANDLER_DOMAIN_SUFFIX: values.hostedHandlerDomainSuffix, - NEXT_PUBLIC_STACK_PORT_PREFIX: values.stackPortPrefix, - })) { + // Hexclave rebrand: getEnvVariable() in stack-shared/utils/env.tsx prefers the + // HEXCLAVE_*-prefixed sibling of each STACK_* var. CI sets only the HEXCLAVE_* + // variant (e.g. NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX), so writing only the STACK_* + // key here would be silently overridden. Mirror every STACK_* key to its + // HEXCLAVE_* sibling so both representations resolve to the same value. + const stackKeys = [ + "NEXT_PUBLIC_STACK_HOSTED_HANDLER_URL_TEMPLATE", + "NEXT_PUBLIC_STACK_HOSTED_HANDLER_DOMAIN_SUFFIX", + "NEXT_PUBLIC_STACK_PORT_PREFIX", + ] as const; + const hexclaveOf = (name: string) => name.replace("STACK_", "HEXCLAVE_"); + const allKeys = [...stackKeys, ...stackKeys.map(hexclaveOf)]; + const oldValues = Object.fromEntries(allKeys.map((k) => [k, Reflect.get(processEnv, k)])); + const newValues: Record = { + NEXT_PUBLIC_STACK_HOSTED_HANDLER_URL_TEMPLATE: values.hostedHandlerUrlTemplate, + NEXT_PUBLIC_STACK_HOSTED_HANDLER_DOMAIN_SUFFIX: values.hostedHandlerDomainSuffix, + NEXT_PUBLIC_STACK_PORT_PREFIX: values.stackPortPrefix, + }; + for (const stackKey of stackKeys) { + newValues[hexclaveOf(stackKey)] = newValues[stackKey]; + } + const applyValues = (entries: Record) => { + for (const [key, value] of Object.entries(entries)) { if (value == null) { Reflect.deleteProperty(processEnv, key); } else { Reflect.set(processEnv, key, value); } } + }; + try { + applyValues(newValues); return callback(); } finally { - for (const [key, value] of Object.entries({ - NEXT_PUBLIC_STACK_HOSTED_HANDLER_URL_TEMPLATE: oldHostedHandlerUrlTemplate, - NEXT_PUBLIC_STACK_HOSTED_HANDLER_DOMAIN_SUFFIX: oldHostedHandlerDomainSuffix, - NEXT_PUBLIC_STACK_PORT_PREFIX: oldStackPortPrefix, - })) { - if (value == null) { - Reflect.deleteProperty(processEnv, key); - } else { - Reflect.set(processEnv, key, value); - } - } + applyValues(oldValues); } };