Files
cfw-autumn/scripts/setupTestUtils/updateEnvFile.ts
amianthus aaa754ae02 feat(test-setup): 🎸 run afterOrgCreated for test org and persist stable pkey to env
createTestOrg now calls the production afterOrgCreated hook directly so
the test org goes through the same bootstrap as real orgs (Stripe
Connect, Svix, OrgService.update). Both org branches gate
createStripeAccount on the existing test_stripe_connect to stay
idempotent across re-runs. Pins TEST_ORG_PUBLISHABLE_KEY (a real
KSUID-generated am_pk_test_* value) and persists
UNIT_TEST_AUTUMN_PUBLIC_KEY plus the auto-generated
UNIT_TEST_AUTUMN_SECRET_KEY to server/.env.local + server/.env so test
clients pick them up. Deletes ensureDefaultStripeAccount.ts (replaced by
the gated afterOrgCreated call).
2026-05-16 15:08:29 +01:00

188 lines
4.8 KiB
TypeScript

import { existsSync, readFileSync, writeFileSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import chalk from "chalk";
import { config } from "dotenv";
import { TEST_ORG_PUBLISHABLE_KEY } from "./createTestOrg.js";
// Get the directory of this script file
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
/**
* Find server/.env file robustly - works whether running from root or scripts dir
*/
function findEnvPath(): string {
// Try from setupTestUtils directory (scripts/setupTestUtils/updateEnvFile.ts -> ../../server/.env)
const fromScriptDir = resolve(__dirname, "../../server/.env");
if (existsSync(fromScriptDir)) {
return fromScriptDir;
}
// Try from current working directory
const fromCwd = resolve(process.cwd(), "server/.env");
if (existsSync(fromCwd)) {
return fromCwd;
}
// If neither exists, return the path from script dir (will fail later with clear error)
return fromScriptDir;
}
export const envPath = findEnvPath();
// Load existing env vars
config({ path: envPath });
/**
* Updates server/.env with new test configuration
*/
export function updateEnvFile({
testOrgSlug,
testOrgId,
autumnSecretKey,
stripeTestKey,
upstashUrl,
upstashToken,
tunnelUrl,
}: {
testOrgSlug: string;
testOrgId: string;
autumnSecretKey: string | null;
stripeTestKey: string;
upstashUrl: string;
upstashToken: string;
tunnelUrl: string;
}) {
console.log(
chalk.magentaBright(
"\n================ Updating Environment Variables ================\n",
),
);
// Read existing .env file
let envContent = "";
try {
envContent = readFileSync(envPath, "utf-8");
} catch {
console.log(
chalk.red(
`❌ Could not read server/.env file at ${envPath}. Make sure it exists.`,
),
);
process.exit(1);
}
// Parse existing env vars
const envVars = new Map<string, string>();
const lines = envContent.split("\n");
for (const line of lines) {
const trimmed = line.trim();
// Skip empty lines and comments
if (!trimmed || trimmed.startsWith("#")) {
continue;
}
const eqIndex = trimmed.indexOf("=");
if (eqIndex > 0) {
const key = trimmed.substring(0, eqIndex);
const value = trimmed.substring(eqIndex + 1);
envVars.set(key, value);
}
}
// Update with new test variables
envVars.set("TESTS_ORG", testOrgSlug);
envVars.set("TESTS_ORG_ID", testOrgId);
envVars.set("UNIT_TEST_AUTUMN_PUBLIC_KEY", TEST_ORG_PUBLISHABLE_KEY);
// Only update the secret key if a new one was generated
if (autumnSecretKey) {
envVars.set("UNIT_TEST_AUTUMN_SECRET_KEY", autumnSecretKey);
}
envVars.set("STRIPE_TEST_KEY", stripeTestKey);
envVars.set("UPSTASH_REDIS_REST_URL", upstashUrl);
envVars.set("UPSTASH_REDIS_REST_TOKEN", upstashToken);
envVars.set("STRIPE_WEBHOOK_URL", tunnelUrl);
// Build new env content, preserving structure
const sections: string[][] = [];
let currentSection: string[] = [];
let inTestSection = false;
for (const line of lines) {
const trimmed = line.trim();
// Check if this is a section header
if (trimmed.startsWith("#")) {
if (currentSection.length > 0) {
sections.push(currentSection);
currentSection = [];
}
currentSection.push(line);
inTestSection = trimmed.toLowerCase().includes("test");
continue;
}
// Skip test-related vars from existing content - we'll add them fresh
if (
trimmed.startsWith("TESTS_ORG") ||
trimmed.startsWith("UNIT_TEST_AUTUMN_PUBLIC_KEY") ||
trimmed.startsWith("UNIT_TEST_AUTUMN_SECRET_KEY") ||
trimmed.startsWith("STRIPE_TEST_KEY") ||
trimmed.startsWith("UPSTASH_REDIS_REST") ||
(trimmed.startsWith("STRIPE_WEBHOOK_URL") && inTestSection)
) {
continue;
}
currentSection.push(line);
}
if (currentSection.length > 0) {
sections.push(currentSection);
}
// Add test configuration section
const testSection = [
"",
"# Test Configuration",
`TESTS_ORG=${testOrgSlug}`,
`TESTS_ORG_ID=${testOrgId}`,
`UNIT_TEST_AUTUMN_PUBLIC_KEY=${TEST_ORG_PUBLISHABLE_KEY}`,
];
// Only add secret key if it was generated/updated
if (autumnSecretKey) {
testSection.push(`UNIT_TEST_AUTUMN_SECRET_KEY=${autumnSecretKey}`);
} else if (envVars.has("UNIT_TEST_AUTUMN_SECRET_KEY")) {
testSection.push(
`UNIT_TEST_AUTUMN_SECRET_KEY=${envVars.get("UNIT_TEST_AUTUMN_SECRET_KEY")}`,
);
}
testSection.push(
`STRIPE_TEST_KEY=${stripeTestKey}`,
"",
"# Upstash (for caching)",
`UPSTASH_REDIS_REST_URL=${upstashUrl}`,
`UPSTASH_REDIS_REST_TOKEN=${upstashToken}`,
"",
"# Tunnel URL (for Stripe webhooks)",
`STRIPE_WEBHOOK_URL=${tunnelUrl}`,
"",
);
sections.push(testSection);
// Write back to file
const newContent = sections.map((s) => s.join("\n")).join("\n");
writeFileSync(envPath, newContent);
console.log(
chalk.greenBright(`✅ Environment variables updated in ${envPath}`),
);
}