Files
cfw-autumn/scripts/setup/writeAgentEnv.ts
amianthus 25e920bbd3 feat(dw): 🎸 parallel agent worktrees with isolated infra + test harness
bun dw spins up a fully isolated per-worktree dev stack: Neon DB branch,
Dragonfly + ElasticMQ via docker compose, portless aliases, tmux
session, and emulate.dev Google OAuth. Workers, dev server, vite,
checkout, and stripe-listen run as concurrently siblings. bun setup-test
auto-runs on first dw and seeds unit-test-org via
clearOrg+setupOrg+ensureDefaultStripeAccount with 13 features + team
invites for all 5 useautumn.com members. Hardcoded localhost URLs in
test scenarios now read AUTUMN_TEST_BASE_URL/AUTUMN_TEST_VITE_URL.
preload-env.ts loads .env.local so bun t/cm/setup-test route to the
worktree server. 1265-line scripts/dw.ts split into scripts/dw/ module
(index + commands + helpers). server/src/db/initDrizzle.ts reverted to
upstream (search_path concerns solved by per-branch Neon isolation).
Workers enabled in agent worktrees now that SQS is per-worktree via
ElasticMQ.
2026-05-16 02:02:43 +01:00

92 lines
2.8 KiB
TypeScript

// NOTE: For worktree-based agent flows, bun dw writes .env.local directly via
// writeEnvLocalFiles in scripts/dw.ts. This file is retained for the legacy
// agent-bootstrap.sh path only.
import { randomBytes } from "node:crypto";
import { copyFileSync, existsSync, writeFileSync } from "node:fs";
import { join } from "node:path";
const root = join(import.meta.dir, "..", "..");
const serverEnvPath = join(root, "server", ".env");
const viteEnvPath = join(root, "vite", ".env");
const viteExamplePath = join(root, "vite", ".env.example");
const genUrlSafeBase64 = ({ bytes }: { bytes: number }): string =>
randomBytes(bytes)
.toString("base64")
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=+$/g, "");
const serverPort = process.env.AGENT_SERVER_PORT ?? "8080";
const vitePort = process.env.AGENT_VITE_PORT ?? "3000";
if (existsSync(serverEnvPath)) {
console.log(
"[writeAgentEnv] server/.env already exists — skipping generation",
);
} else {
const passThrough = [
"STRIPE_SANDBOX_CLIENT_ID",
"STRIPE_SANDBOX_SECRET_KEY",
"STRIPE_SANDBOX_WEBHOOK_SECRET",
"STRIPE_LIVE_CLIENT_ID",
"STRIPE_LIVE_SECRET_KEY",
"STRIPE_LIVE_WEBHOOK_SECRET",
"ANTHROPIC_API_KEY",
"RESEND_API_KEY",
"RESEND_DOMAIN",
"SVIX_API_KEY",
"POSTHOG_API_KEY",
"POSTHOG_HOST",
] as const;
const passLines = passThrough
.map((k) => `${k}=${process.env[k] ?? ""}`)
.join("\n");
const content = `# -----------------------------------------------------------------------
# Generated by scripts/setup/writeAgentEnv.ts
# Delete this file and re-run bun dev:agent to regenerate.
# -----------------------------------------------------------------------
# Per-agent random secrets
BETTER_AUTH_SECRET=${genUrlSafeBase64({ bytes: 64 })}
ENCRYPTION_IV=${genUrlSafeBase64({ bytes: 16 })}
ENCRYPTION_PASSWORD=${genUrlSafeBase64({ bytes: 64 })}
# Local services
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/autumn
CACHE_URL=redis://localhost:6379
CACHE_URL_US_EAST=redis://localhost:6379
REDIS_URL=redis://localhost:6379
# ElasticMQ (local SQS, per-agent isolated queue)
SQS_QUEUE_URL_V2=http://localhost:9324/000000000000/autumn.fifo
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=x
AWS_SECRET_ACCESS_KEY=x
# ClickHouse (local)
TINYBIRD_CLICKHOUSE_URL=http://localhost:8123
# App URLs
BETTER_AUTH_URL=http://localhost:${serverPort}
CLIENT_URL=http://localhost:${vitePort}
STRIPE_WEBHOOK_URL=http://localhost:${serverPort}
# Static team-wide (pass-through from process.env)
${passLines}
# Environment
NODE_ENV=development
`;
writeFileSync(serverEnvPath, content);
console.log("[writeAgentEnv] Wrote server/.env");
}
if (!existsSync(viteEnvPath) && existsSync(viteExamplePath)) {
copyFileSync(viteExamplePath, viteEnvPath);
console.log("[writeAgentEnv] Wrote vite/.env from .env.example");
}