build: ship pre-built API bundle; images copy output instead of installing
- API: `pnpm build` bundles dist/ into apps/api/.output (esbuild), with Linux musl native packages for sharp and argon2 kept alongside - docker/api.Dockerfile copies that output; no pnpm install on the server - add dist/migrate.js (prisma migrate deploy equivalent, same _prisma_migrations table and lock) so the Prisma CLI is not needed at runtime - pnpm-workspace: supportedArchitectures for linux/x64/musl - admin: apps/admin/.env.production sets VITE_SITE_URL for the production build - drop NPM_REGISTRY / SITE_URL build args from compose and .env.example - gitignore: anchor node_modules rules so pre-built node_modules are committed - README: describe the pre-built deploy flow Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 5.5
parent
ee8258556d
commit
10e453e4be
Vendored
+66
@@ -0,0 +1,66 @@
|
||||
import { createHash, randomUUID } from "node:crypto";
|
||||
import { existsSync } from "node:fs";
|
||||
import { readdir, readFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import pg from "pg";
|
||||
if (existsSync(".env"))
|
||||
process.loadEnvFile(".env");
|
||||
const MIGRATIONS_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../prisma/migrations");
|
||||
const LOCK_ID = 72707369;
|
||||
const client = new pg.Client({ connectionString: process.env.DATABASE_URL });
|
||||
async function main() {
|
||||
await client.query(`SELECT pg_advisory_lock(${LOCK_ID})`);
|
||||
await client.query(`CREATE TABLE IF NOT EXISTS "_prisma_migrations" (
|
||||
"id" VARCHAR(36) PRIMARY KEY NOT NULL,
|
||||
"checksum" VARCHAR(64) NOT NULL,
|
||||
"finished_at" TIMESTAMPTZ,
|
||||
"migration_name" VARCHAR(255) NOT NULL,
|
||||
"logs" TEXT,
|
||||
"rolled_back_at" TIMESTAMPTZ,
|
||||
"started_at" TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
"applied_steps_count" INTEGER NOT NULL DEFAULT 0
|
||||
)`);
|
||||
const { rows } = await client.query(`SELECT migration_name, finished_at FROM "_prisma_migrations" WHERE rolled_back_at IS NULL`);
|
||||
const failed = rows.find((r) => !r.finished_at);
|
||||
if (failed) {
|
||||
throw new Error(`migration ${failed.migration_name} failed earlier; fix the database, then mark it with ` +
|
||||
`\`prisma migrate resolve\` (see its "logs" column in _prisma_migrations)`);
|
||||
}
|
||||
const applied = new Set(rows.map((r) => r.migration_name));
|
||||
const entries = await readdir(MIGRATIONS_DIR, { withFileTypes: true });
|
||||
const pending = entries
|
||||
.filter((e) => e.isDirectory() && !applied.has(e.name))
|
||||
.map((e) => e.name)
|
||||
.sort();
|
||||
for (const name of pending) {
|
||||
const script = await readFile(path.join(MIGRATIONS_DIR, name, "migration.sql"), "utf8");
|
||||
const id = randomUUID();
|
||||
await client.query(`INSERT INTO "_prisma_migrations" (id, checksum, migration_name) VALUES ($1, $2, $3)`, [id, createHash("sha256").update(script).digest("hex"), name]);
|
||||
try {
|
||||
await client.query(script);
|
||||
}
|
||||
catch (e) {
|
||||
await client.query(`UPDATE "_prisma_migrations" SET logs = $2 WHERE id = $1`, [
|
||||
id,
|
||||
String(e),
|
||||
]);
|
||||
throw new Error(`migration ${name} failed`, { cause: e });
|
||||
}
|
||||
await client.query(`UPDATE "_prisma_migrations" SET finished_at = now(), applied_steps_count = 1 WHERE id = $1`, [id]);
|
||||
console.log(`applied ${name}`);
|
||||
}
|
||||
console.log(pending.length ? `${pending.length} migration(s) applied` : "no pending migrations");
|
||||
}
|
||||
try {
|
||||
await client.connect();
|
||||
await main();
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
finally {
|
||||
await client.end();
|
||||
}
|
||||
//# sourceMappingURL=migrate.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"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"}
|
||||
Reference in New Issue
Block a user