mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-13 21:01:21 +08:00
fix(ci): repair two pre-existing test failures on dev (#1488)
Both failures are pre-existing on `dev` (confirmed by checking the most
recent dev run
[26434368271](https://github.com/hexclave/stack-auth/actions/runs/26434368271)
— same two annotations, same line numbers). Neither is caused by an open
PR.
## Failure 1 — \`apps/backend/src/lib/redirect-urls.test.tsx:75\`
\`\`\`
AssertionError: expected false to be true
\`\`\`
The \`withHostedHandlerEnv\` helper set/cleared only the
\`STACK_*\`-prefixed env vars. CI's
[e2e-custom-base-port-api-tests.yaml:21](.github/workflows/e2e-custom-base-port-api-tests.yaml#L21)
sets only the \`HEXCLAVE_*\`-prefixed sibling
(\`NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX=67\`), and the dual-read shim in
[packages/stack-shared/src/utils/env.tsx#L53-L55](packages/stack-shared/src/utils/env.tsx#L53-L55)
prefers \`HEXCLAVE_*\` over \`STACK_*\`:
\`\`\`ts
const hexclaveName = getHexclaveEnvVarName(name);
let value = (hexclaveName ? process.env[hexclaveName] : undefined) ??
process.env[name];
\`\`\`
So \`getEnvVariable(\"NEXT_PUBLIC_STACK_PORT_PREFIX\", \"81\")\`
returned \`\"67\"\` instead of the test's \`\"92\"\`, the template
resolved to port \`6709\` instead of \`9209\`, and the assertion at line
75 failed.
**Fix:** mirror every \`STACK_*\` key managed by the helper to its
\`HEXCLAVE_*\` sibling. The dual-read then resolves to the
test-controlled value regardless of which key it checks first.
## Failure 2 —
\`apps/backend/prisma/migrations/20260526060000_nullable_oauth_access_token_expires_at/tests/nullable-expires-at.ts:58\`
\`\`\`
PostgresError: null value in column \"updatedAt\" of relation
\"OAuthAccessToken\" violates not-null constraint
\`\`\`
The migration test's raw INSERT omits \`\"updatedAt\"\`. The Prisma
model declares \`updatedAt DateTime @updatedAt\` with no
\`@default(now())\`, so the DB column is \`NOT NULL\` with no default —
Prisma populates it at the ORM layer on insert, but this test bypasses
Prisma via \`postgres.js\`.
**Fix:** add the \`\"updatedAt\"\` column to the INSERT, set to
\`NOW()\`, with a comment noting why raw SQL must set it explicitly.
## Verification
- **Failure 1, before fix:** ran \`NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX=67
pnpm test run apps/backend/src/lib/redirect-urls.test.tsx\` locally →
reproduces the exact line-75 assertion failure from CI.
- **Failure 1, after fix:** same command → 33/33 pass.
- **Failure 2:** local reproduction requires the migration-test postgres
harness; the fix is one column matching how every other raw SQL insert
in this repo handles \`@updatedAt\` fields. CI on this branch will
confirm.
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes two failing tests on dev CI by aligning env var handling in
redirect URL tests and by setting the missing updatedAt in a migration
test. Restores green CI with no runtime changes.
- **Bug Fixes**
- Redirect URL tests: `withHostedHandlerEnv` now mirrors `STACK_*`
values to their `HEXCLAVE_*` siblings and restores both, so
`getEnvVariable` reads the test-controlled values even when CI sets only
`HEXCLAVE_*` (e.g. `NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX`).
- Migration test: the raw insert into `OAuthAccessToken` now sets
`"updatedAt" = NOW()` since `Prisma`’s `@updatedAt` isn’t applied when
using `postgres.js` and the column is NOT NULL.
<sup>Written for commit 75c8e4343e.
Summary will update on new commits. <a
href="https://cubic.dev/pr/hexclave/stack-auth/pull/1488?utm_source=github">Review
in cubic</a></sup>
<!-- End of auto-generated description by cubic. -->
This commit is contained in:
parent
9b30a276c4
commit
c7a5c7be1f
@ -55,6 +55,9 @@ export const postMigration = async (sql: Sql, ctx: Awaited<ReturnType<typeof pre
|
||||
expect(columnRows[0].is_nullable).toBe("YES");
|
||||
expect(columnRows[0].data_type).toBe("timestamp without time zone");
|
||||
|
||||
// `OAuthAccessToken."updatedAt"` is `DateTime @updatedAt` in Prisma with no
|
||||
// DB-level default — Prisma populates it at the ORM layer on insert. This
|
||||
// raw SQL bypasses Prisma, so the column has to be set explicitly.
|
||||
await sql`
|
||||
INSERT INTO "OAuthAccessToken" (
|
||||
"id",
|
||||
@ -62,7 +65,8 @@ export const postMigration = async (sql: Sql, ctx: Awaited<ReturnType<typeof pre
|
||||
"oauthAccountId",
|
||||
"accessToken",
|
||||
"scopes",
|
||||
"expiresAt"
|
||||
"expiresAt",
|
||||
"updatedAt"
|
||||
)
|
||||
VALUES (
|
||||
${randomUUID()}::uuid,
|
||||
@ -70,7 +74,8 @@ export const postMigration = async (sql: Sql, ctx: Awaited<ReturnType<typeof pre
|
||||
${ctx.oauthAccountId}::uuid,
|
||||
'github-access-token-without-expiry',
|
||||
ARRAY['user:email']::text[],
|
||||
NULL
|
||||
NULL,
|
||||
NOW()
|
||||
)
|
||||
`;
|
||||
|
||||
|
||||
@ -12,34 +12,41 @@ describe('validateRedirectUrl', () => {
|
||||
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<string, string | undefined> = {
|
||||
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<string, string | undefined>) => {
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user