chore: revert database v2 url changes

This commit is contained in:
Charlie Lamb
2026-04-27 14:01:26 +01:00
parent 9aff8b3d30
commit 0dc77a7dcd
20 changed files with 61 additions and 61 deletions

View File

@@ -6,7 +6,7 @@
# branches: # branches:
# - main # - main
# env: # env:
# DATABASE_V2_URL: ${{ secrets.SUPABASE_URL }} # DATABASE_URL: ${{ secrets.SUPABASE_URL }}
# UNIT_TEST_AUTUMN_SECRET_KEY: ${{ secrets.AUTUMN_KEY }} # UNIT_TEST_AUTUMN_SECRET_KEY: ${{ secrets.AUTUMN_KEY }}
# REDIS_URL: redis://localhost:6379 # REDIS_URL: redis://localhost:6379
# ENCRYPTION_IV: ${{ secrets.ENCRYPTION_IV }} # ENCRYPTION_IV: ${{ secrets.ENCRYPTION_IV }}
@@ -92,7 +92,7 @@
# - name: Create .env file # - name: Create .env file
# run: | # run: |
# echo "Creating .env file..." # echo "Creating .env file..."
# echo "DATABASE_V2_URL=${{ env.DATABASE_V2_URL }}" >> .env # echo "DATABASE_URL=${{ env.DATABASE_URL }}" >> .env
# echo "UNIT_TEST_AUTUMN_SECRET_KEY=${{ env.UNIT_TEST_AUTUMN_SECRET_KEY }}" >> .env # echo "UNIT_TEST_AUTUMN_SECRET_KEY=${{ env.UNIT_TEST_AUTUMN_SECRET_KEY }}" >> .env
# echo "REDIS_URL=${{ env.REDIS_URL }}" >> .env # echo "REDIS_URL=${{ env.REDIS_URL }}" >> .env
# echo "ENCRYPTION_IV=${{ env.ENCRYPTION_IV }}" >> .env # echo "ENCRYPTION_IV=${{ env.ENCRYPTION_IV }}" >> .env

View File

@@ -8,7 +8,7 @@ services:
volumes: volumes:
- valkey-data:/bitnami/valkey/data - valkey-data:/bitnami/valkey/data
healthcheck: healthcheck:
test: ['CMD', 'redis-cli', '-h', 'localhost', '-p', '6379', 'ping'] test: [ "CMD", "redis-cli", "-h", "localhost", "-p", "6379", "ping" ]
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 5 retries: 5
@@ -65,7 +65,7 @@ services:
environment: environment:
- NODE_ENV=development - NODE_ENV=development
- REDIS_URL=redis://valkey:6379 - REDIS_URL=redis://valkey:6379
- DATABASE_V2_URL=${DATABASE_V2_URL} - DATABASE_URL=${DATABASE_URL}
- ENCRYPTION_IV=${ENCRYPTION_IV} - ENCRYPTION_IV=${ENCRYPTION_IV}
- ENCRYPTION_PASSWORD=${ENCRYPTION_PASSWORD} - ENCRYPTION_PASSWORD=${ENCRYPTION_PASSWORD}
- TESTS_ORG=${TESTS_ORG} - TESTS_ORG=${TESTS_ORG}
@@ -98,7 +98,6 @@ services:
- shared - shared
restart: unless-stopped restart: unless-stopped
# Run localtunnel # Run localtunnel
localtunnel: localtunnel:
build: build:
@@ -113,7 +112,6 @@ services:
- server - server
restart: unless-stopped restart: unless-stopped
volumes: volumes:
# Shared package dist output # Shared package dist output
shared-dist: shared-dist:
@@ -123,4 +121,4 @@ volumes:
shared-node-modules: shared-node-modules:
server-node-modules: server-node-modules:
vite-node-modules: vite-node-modules:
root-node-modules: root-node-modules:

View File

@@ -184,7 +184,7 @@ async function getCustomerCount(
} }
/** /**
* Read DATABASE_V2_URL from server/.env file * Read DATABASE_URL from server/.env file
*/ */
function readLocalDatabaseUrl(): string | null { function readLocalDatabaseUrl(): string | null {
try { try {
@@ -194,8 +194,8 @@ function readLocalDatabaseUrl(): string | null {
for (const line of lines) { for (const line of lines) {
const trimmed = line.trim(); const trimmed = line.trim();
if (trimmed.startsWith("DATABASE_V2_URL=")) { if (trimmed.startsWith("DATABASE_URL=")) {
const url = trimmed.replace(/^DATABASE_V2_URL=/, "").trim(); const url = trimmed.replace(/^DATABASE_URL=/, "").trim();
// Remove quotes if present // Remove quotes if present
return url.replace(/^["']|["']$/g, ""); return url.replace(/^["']|["']$/g, "");
} }
@@ -237,7 +237,7 @@ async function pullDatabase({
if (!localUrl) { if (!localUrl) {
console.error("❌ Could not find local database URL"); console.error("❌ Could not find local database URL");
console.error(" Options:"); console.error(" Options:");
console.error(" 1. Ensure server/.env exists and contains DATABASE_V2_URL"); console.error(" 1. Ensure server/.env exists and contains DATABASE_URL");
console.error(" 2. Pass local URL as second argument"); console.error(" 2. Pass local URL as second argument");
console.error(" 3. Set LOCAL_DATABASE_URL environment variable"); console.error(" 3. Set LOCAL_DATABASE_URL environment variable");
process.exit(1); process.exit(1);
@@ -359,7 +359,7 @@ if (!remoteUrl) {
" local-database-url (optional) Local database URL to pull into", " local-database-url (optional) Local database URL to pull into",
); );
console.log( console.log(
" If not provided, reads from server/.env DATABASE_V2_URL\n", " If not provided, reads from server/.env DATABASE_URL\n",
); );
console.log("Environment variables:"); console.log("Environment variables:");
console.log(" REMOTE_DATABASE_URL Remote database URL"); console.log(" REMOTE_DATABASE_URL Remote database URL");
@@ -370,7 +370,7 @@ if (!remoteUrl) {
console.log(' REMOTE_DATABASE_URL="postgresql://..." bun db:pull\n'); console.log(' REMOTE_DATABASE_URL="postgresql://..." bun db:pull\n');
console.log("⚠️ Important: URLs must be quoted to prevent shell expansion\n"); console.log("⚠️ Important: URLs must be quoted to prevent shell expansion\n");
console.log( console.log(
"By default, the script reads DATABASE_V2_URL from server/.env for the local database.\n", "By default, the script reads DATABASE_URL from server/.env for the local database.\n",
); );
process.exit(1); process.exit(1);
} }

View File

@@ -39,7 +39,9 @@ const setEnvFromInfisicalExport = (value: unknown) => {
return; return;
} }
for (const [key, secretValue] of Object.entries(value as Record<string, string>)) { for (const [key, secretValue] of Object.entries(
value as Record<string, string>,
)) {
process.env[key] = secretValue; process.env[key] = secretValue;
} }
}; };
@@ -71,9 +73,11 @@ const main = async () => {
loadInfisicalEnv(env); loadInfisicalEnv(env);
const criticalDatabaseUrl = process.env.DATABASE_V2_CRITICAL_URL; const criticalDatabaseUrl = process.env.DATABASE_CRITICAL_URL;
if (!criticalDatabaseUrl) { if (!criticalDatabaseUrl) {
throw new Error(`DATABASE_V2_CRITICAL_URL is not set in Infisical env "${env}"`); throw new Error(
`DATABASE_CRITICAL_URL is not set in Infisical env "${env}"`,
);
} }
const client = new Pool({ const client = new Pool({
@@ -106,7 +110,7 @@ const main = async () => {
}); });
try { try {
console.log("Verified in a new DATABASE_V2_CRITICAL_URL session:"); console.log("Verified in a new DATABASE_CRITICAL_URL session:");
for (const key of Object.keys(ROLE_SETTINGS)) { for (const key of Object.keys(ROLE_SETTINGS)) {
const verifyResult = await verifyClient.query<Record<string, string>>( const verifyResult = await verifyClient.query<Record<string, string>>(
`SHOW ${key}`, `SHOW ${key}`,

View File

@@ -14,13 +14,13 @@ database_url="${database_base_url%/*}/${database_name}${database_query}"
logged_database_url="$(printf '%s' "${database_url}" | sed -E 's#(postgres(ql)?://[^:/?]+):[^@/]*@#\1:***@#')" logged_database_url="$(printf '%s' "${database_url}" | sed -E 's#(postgres(ql)?://[^:/?]+):[^@/]*@#\1:***@#')"
cache_url="${LOCAL_CACHE_URL:-redis://localhost:6379}" cache_url="${LOCAL_CACHE_URL:-redis://localhost:6379}"
echo "dev-local: overriding Infisical DATABASE_V2_URL/CACHE_URL with local values and disabling CACHE_CERT" echo "dev-local: overriding Infisical DATABASE_URL/CACHE_URL with local values and disabling CACHE_CERT"
echo "dev-local: DATABASE_V2_URL=${logged_database_url}" echo "dev-local: DATABASE_URL=${logged_database_url}"
exec infisical run --env=prod -- env \ exec infisical run --env=prod -- env \
ENV_FILE=.env.prod \ ENV_FILE=.env.prod \
NODE_ENV=development \ NODE_ENV=development \
DATABASE_V2_URL="${database_url}" \ DATABASE_URL="${database_url}" \
CACHE_URL="${cache_url}" \ CACHE_URL="${cache_url}" \
CACHE_URL_US_EAST="${cache_url}" \ CACHE_URL_US_EAST="${cache_url}" \
CACHE_CERT="" \ CACHE_CERT="" \

View File

@@ -8,7 +8,7 @@ export const migrateFunctions = async () => {
const { initializeDatabaseFunctions } = await import( const { initializeDatabaseFunctions } = await import(
"@server/db/initializeDatabaseFunctions" "@server/db/initializeDatabaseFunctions"
); );
const databaseUrl = process.env.DATABASE_V2_URL; const databaseUrl = process.env.DATABASE_URL;
if (databaseUrl?.includes("us-east-2")) { if (databaseUrl?.includes("us-east-2")) {
const { confirm } = await inquirer.prompt([ const { confirm } = await inquirer.prompt([

View File

@@ -177,10 +177,10 @@ const generateSupabaseDatabaseUrl = async () => {
const projectId = found.id; const projectId = found.id;
const region = found.region; const region = found.region;
// Step 8: Construct DATABASE_V2_URL // Step 8: Construct DATABASE_URL
const databaseUrl = `postgresql://postgres.${projectId}:${dbPassword}@aws-1-${region}.pooler.supabase.com:5432/postgres`; const databaseUrl = `postgresql://postgres.${projectId}:${dbPassword}@aws-1-${region}.pooler.supabase.com:5432/postgres`;
console.log(chalk.greenBright(`\nGenerated DB password: ${dbPassword}\n`)); console.log(chalk.greenBright(`\nGenerated DB password: ${dbPassword}\n`));
console.log(chalk.greenBright(`\nYour DATABASE_V2_URL is:\n${databaseUrl}\n`)); console.log(chalk.greenBright(`\nYour DATABASE_URL is:\n${databaseUrl}\n`));
console.log(chalk.yellow("--------------------------------")); console.log(chalk.yellow("--------------------------------"));
// Step 9: Prompt to run docker compose up // Step 9: Prompt to run docker compose up
@@ -208,8 +208,8 @@ const handleDatabaseSetup = async () => {
message: chalk.cyan("How do you want to set up your database?"), message: chalk.cyan("How do you want to set up your database?"),
choices: [ choices: [
{ name: "Set up Supabase (Cloud) for Autumn", value: "supabase" }, { name: "Set up Supabase (Cloud) for Autumn", value: "supabase" },
{ name: "Paste in your own DATABASE_V2_URL", value: "paste" }, { name: "Paste in your own DATABASE_URL", value: "paste" },
{ name: "Paste in your own DATABASE_V2_URL later", value: "later" }, { name: "Paste in your own DATABASE_URL later", value: "later" },
], ],
default: "supabase", default: "supabase",
}, },
@@ -224,7 +224,7 @@ const handleDatabaseSetup = async () => {
{ {
type: "input", type: "input",
name: "databaseUrl", name: "databaseUrl",
message: "Paste in your DATABASE_V2_URL:", message: "Paste in your DATABASE_URL:",
validate: (input) => input && input.length > 5, validate: (input) => input && input.length > 5,
}, },
]); ]);
@@ -285,7 +285,7 @@ async function main() {
// Database section // Database section
if (databaseUrl) { if (databaseUrl) {
envSections.push("# Database", `DATABASE_V2_URL=${databaseUrl}`, ""); envSections.push("# Database", `DATABASE_URL=${databaseUrl}`, "");
} }
// Stripe Webhooks section // Stripe Webhooks section

View File

@@ -26,7 +26,7 @@ async function main() {
STRIPE_WEBHOOK_URL: process.env.STRIPE_WEBHOOK_URL, STRIPE_WEBHOOK_URL: process.env.STRIPE_WEBHOOK_URL,
}; };
const databaseUrl = process.env.DATABASE_V2_URL; const databaseUrl = process.env.DATABASE_URL;
const stripeWebhookVars = []; const stripeWebhookVars = [];
// stripeWebhookVars = await handleLocalRunSetup(); // stripeWebhookVars = await handleLocalRunSetup();
@@ -57,7 +57,7 @@ async function main() {
// Database section // Database section
if (databaseUrl) { if (databaseUrl) {
envSections.push("# Database", `DATABASE_V2_URL=${databaseUrl}`, ""); envSections.push("# Database", `DATABASE_URL=${databaseUrl}`, "");
} }
// Stripe Webhooks section // Stripe Webhooks section

View File

@@ -18,7 +18,9 @@ const serverPort = process.env.AGENT_SERVER_PORT ?? "8080";
const vitePort = process.env.AGENT_VITE_PORT ?? "3000"; const vitePort = process.env.AGENT_VITE_PORT ?? "3000";
if (existsSync(serverEnvPath)) { if (existsSync(serverEnvPath)) {
console.log("[writeAgentEnv] server/.env already exists — skipping generation"); console.log(
"[writeAgentEnv] server/.env already exists — skipping generation",
);
} else { } else {
const passThrough = [ const passThrough = [
"STRIPE_SANDBOX_CLIENT_ID", "STRIPE_SANDBOX_CLIENT_ID",
@@ -50,7 +52,7 @@ ENCRYPTION_IV=${genUrlSafeBase64({ bytes: 16 })}
ENCRYPTION_PASSWORD=${genUrlSafeBase64({ bytes: 64 })} ENCRYPTION_PASSWORD=${genUrlSafeBase64({ bytes: 64 })}
# Local services # Local services
DATABASE_V2_URL=postgresql://postgres:postgres@localhost:5432/autumn DATABASE_URL=postgresql://postgres:postgres@localhost:5432/autumn
CACHE_URL=redis://localhost:6379 CACHE_URL=redis://localhost:6379
CACHE_URL_US_EAST=redis://localhost:6379 CACHE_URL_US_EAST=redis://localhost:6379
REDIS_URL=redis://localhost:6379 REDIS_URL=redis://localhost:6379

View File

@@ -18,7 +18,7 @@ LOCALTUNNEL_RESERVED_KEY=
# DATABASE # DATABASE
# You can grab this from the Supabase dashboard by pressing the "Connect" button in the upper navbar, or pass in your own connection string to a postgres instance # You can grab this from the Supabase dashboard by pressing the "Connect" button in the upper navbar, or pass in your own connection string to a postgres instance
DATABASE_V2_URL= DATABASE_URL=
CRITICAL_DATABASE_URL= CRITICAL_DATABASE_URL=
# ------------------------------------------------------------------------ # ------------------------------------------------------------------------

View File

@@ -113,12 +113,12 @@ export const isConnectionDropError = ({
return CONNECTION_DROP_CODES.has(code); return CONNECTION_DROP_CODES.has(code);
}; };
/** Throws if DATABASE_V2_URL looks like a production database. Single source of truth for this check. */ /** Throws if DATABASE_URL looks like a production database. Single source of truth for this check. */
export const assertNotProductionDb = () => { export const assertNotProductionDb = () => {
const url = process.env.DATABASE_V2_URL || ""; const url = process.env.DATABASE_URL || "";
if (url.includes("us-east-2")) { if (url.includes("us-east-2")) {
throw new Error( throw new Error(
"Refusing to run against production database (DATABASE_V2_URL contains us-east-2)", "Refusing to run against production database (DATABASE_URL contains us-east-2)",
); );
} }
}; };

View File

@@ -53,8 +53,8 @@ export const initDrizzle = ({
poolConfig?: PoolConfig; poolConfig?: PoolConfig;
} = {}) => { } = {}) => {
const envDbUrl = replica const envDbUrl = replica
? process.env.DATABASE_V2_REPLICA_URL ? process.env.DATABASE_REPLICA_URL
: process.env.DATABASE_V2_URL; : process.env.DATABASE_URL;
const dbUrl = databaseUrl || envDbUrl || ""; const dbUrl = databaseUrl || envDbUrl || "";
@@ -86,10 +86,10 @@ export const initDrizzle = ({
export const { db: dbCritical, client: clientCritical } = initDrizzle({ export const { db: dbCritical, client: clientCritical } = initDrizzle({
maxConnections: 5, maxConnections: 5,
connectTimeout: 2, connectTimeout: 2,
databaseUrl: process.env.DATABASE_V2_CRITICAL_URL, databaseUrl: process.env.DATABASE_CRITICAL_URL,
poolConfig: { poolConfig: {
application_name: "autumn-critical", application_name: "autumn-critical",
// Server-side timeout is configured on the DATABASE_V2_CRITICAL_URL role. // Server-side timeout is configured on the DATABASE_CRITICAL_URL role.
query_timeout: 2_000, query_timeout: 2_000,
}, },
}); });
@@ -100,8 +100,8 @@ export const { db: dbGeneral, client: clientGeneral } = initDrizzle({
}); });
// -- Replica pool: used as fallback when primary is degraded -- // -- Replica pool: used as fallback when primary is degraded --
// Only created if DATABASE_V2_REPLICA_URL is configured. // Only created if DATABASE_REPLICA_URL is configured.
const replicaResult = process.env.DATABASE_V2_REPLICA_URL const replicaResult = process.env.DATABASE_REPLICA_URL
? initDrizzle({ replica: true, maxConnections: 5, connectTimeout: null }) ? initDrizzle({ replica: true, maxConnections: 5, connectTimeout: null })
: null; : null;
export const dbReplica = replicaResult?.db ?? null; export const dbReplica = replicaResult?.db ?? null;

View File

@@ -49,11 +49,7 @@ export const getDbHealth = (): PgHealth => state;
* Initialize the health monitor with a pg pool for probing. * Initialize the health monitor with a pg pool for probing.
* Call once at startup. The probe client should be the critical pool's raw client. * Call once at startup. The probe client should be the critical pool's raw client.
*/ */
export const initPgHealthMonitor = ({ export const initPgHealthMonitor = ({ client }: { client: Pool }): void => {
client,
}: {
client: Pool;
}): void => {
probeClient = client; probeClient = client;
logger.info("[PgHealthMonitor] Initialized", { type: "pg_health_init" }); logger.info("[PgHealthMonitor] Initialized", { type: "pg_health_init" });
}; };
@@ -247,7 +243,7 @@ export const getPgHealthState = (): {
failureCount, failureCount,
probeActive: probeInterval !== null, probeActive: probeInterval !== null,
firstProbeSuccessAt, firstProbeSuccessAt,
hasReplica: !!process.env.DATABASE_V2_REPLICA_URL, hasReplica: !!process.env.DATABASE_REPLICA_URL,
}); });
/** Force DEGRADED state (for testing). Does NOT start the recovery probe. */ /** Force DEGRADED state (for testing). Does NOT start the recovery probe. */

View File

@@ -33,9 +33,9 @@ export const redactDatabaseUrl = (databaseUrl?: string) => {
}; };
export const getRedactedDatabaseUrls = () => ({ export const getRedactedDatabaseUrls = () => ({
primary: redactDatabaseUrl(process.env.DATABASE_V2_URL), primary: redactDatabaseUrl(process.env.DATABASE_URL),
replica: redactDatabaseUrl(process.env.DATABASE_V2_REPLICA_URL), replica: redactDatabaseUrl(process.env.DATABASE_REPLICA_URL),
critical: redactDatabaseUrl( critical: redactDatabaseUrl(
process.env.DATABASE_V2_CRITICAL_URL || process.env.DATABASE_V2_URL, process.env.DATABASE_CRITICAL_URL || process.env.DATABASE_URL,
), ),
}); });

View File

@@ -85,7 +85,7 @@ debugRouter.post("/pool-test", async (c) => {
return c.json({ error: "Forbidden" }, 403); return c.json({ error: "Forbidden" }, 403);
} }
if (process.env.DATABASE_V2_URL?.includes("us-east-2")) { if (process.env.DATABASE_URL?.includes("us-east-2")) {
return c.json({ error: "Not available against production database" }, 403); return c.json({ error: "Not available against production database" }, 403);
} }

View File

@@ -2,8 +2,8 @@ import { logger } from "@/external/logtail/logtailUtils.js";
import "dotenv/config"; import "dotenv/config";
export const checkEnvVars = () => { export const checkEnvVars = () => {
if (!process.env.DATABASE_V2_URL) { if (!process.env.DATABASE_URL) {
console.error(`DATABASE_V2_URL is not set`); console.error(`DATABASE_URL is not set`);
process.exit(1); process.exit(1);
} }

View File

@@ -21,11 +21,11 @@ export const clearMasterOrg = async () => {
process.exit(1); process.exit(1);
} }
const databaseUrl = process.env.DATABASE_V2_URL ?? ""; const databaseUrl = process.env.DATABASE_URL ?? "";
if (databaseUrl.toLowerCase().includes("fancy-duckling")) { if (databaseUrl.toLowerCase().includes("fancy-duckling")) {
console.error( console.error(
chalk.red( chalk.red(
"\n❌ Refusing to run clearMasterOrg against prod-like DATABASE_V2_URL (contains 'fancy-duckling').\n", "\n❌ Refusing to run clearMasterOrg against prod-like DATABASE_URL (contains 'fancy-duckling').\n",
), ),
); );
process.exit(1); process.exit(1);

View File

@@ -1,5 +1,5 @@
import net from "node:net";
import { expect, test } from "bun:test"; import { expect, test } from "bun:test";
import net from "node:net";
import { sql } from "drizzle-orm"; import { sql } from "drizzle-orm";
import { assertNotProductionDb } from "@/db/dbUtils.js"; import { assertNotProductionDb } from "@/db/dbUtils.js";
import { import {
@@ -47,8 +47,8 @@ test("db connect timeout fails fast when postgres accepts tcp but never responds
throw new Error("Failed to bind test TCP server"); throw new Error("Failed to bind test TCP server");
} }
const databaseUrl = process.env.DATABASE_V2_URL; const databaseUrl = process.env.DATABASE_URL;
process.env.DATABASE_V2_URL = `postgres://user:password@127.0.0.1:${address.port}/db`; process.env.DATABASE_URL = `postgres://user:password@127.0.0.1:${address.port}/db`;
const { client: deadClient } = initDrizzle({ connectTimeout: 1 }); const { client: deadClient } = initDrizzle({ connectTimeout: 1 });
const startedAt = Date.now(); const startedAt = Date.now();
@@ -58,7 +58,7 @@ test("db connect timeout fails fast when postgres accepts tcp but never responds
expect(Date.now() - startedAt).toBeLessThan(2_000); expect(Date.now() - startedAt).toBeLessThan(2_000);
} finally { } finally {
process.env.DATABASE_V2_URL = databaseUrl; process.env.DATABASE_URL = databaseUrl;
await deadClient.end().catch(() => {}); await deadClient.end().catch(() => {});
await new Promise<void>((resolve, reject) => { await new Promise<void>((resolve, reject) => {
server.close((error) => (error ? reject(error) : resolve())); server.close((error) => (error ? reject(error) : resolve()));

View File

@@ -317,7 +317,7 @@ test(`${chalk.yellowBright("pg failover: critical endpoints failover to replica
} }
} else { } else {
console.log( console.log(
"\n--- Step 5: SKIPPED (no DATABASE_V2_REPLICA_URL configured) ---", "\n--- Step 5: SKIPPED (no DATABASE_REPLICA_URL configured) ---",
); );
} }

View File

@@ -8,6 +8,6 @@ export default defineConfig({
out: "./drizzle", out: "./drizzle",
schema: "./db/schema.ts", schema: "./db/schema.ts",
dbCredentials: { dbCredentials: {
url: process.env.DATABASE_V2_URL!, url: process.env.DATABASE_URL!,
}, },
}); });