fix(deploy): Regenerate migrations & ensure artifacts are copied

This commit is contained in:
fullsizemalt 2025-12-17 00:23:44 -08:00
parent 09a6f076d6
commit 00b8e8b627
4 changed files with 758 additions and 98 deletions

50
apps/web/Dockerfile Normal file
View file

@ -0,0 +1,50 @@
FROM oven/bun:latest AS base
# Install dependencies only when needed
FROM base AS deps
WORKDIR /app
COPY package.json ./
RUN bun install
# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Build Next.js
ENV NEXT_TELEMETRY_DISABLED=1
RUN bun run build
# # Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
# Copy public folder
COPY --from=builder /app/public ./public
# Set permission for prerender cache
RUN mkdir .next
# Automatically leverage output traces to reduce image size
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
# Copy migrations and migration script
COPY --from=builder /app/drizzle ./drizzle
COPY --from=builder /app/src/db/migrate.ts ./src/db/migrate.ts
COPY --from=builder /app/src ./src
RUN bun install drizzle-orm pg dotenv
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
# Custom entrypoint to run migrations then start app
CMD ["sh", "-c", "bun --bun run src/db/migrate.ts && bun --bun run server.js"]

View file

@ -1,41 +1,3 @@
CREATE TABLE IF NOT EXISTS "user" (
"id" text PRIMARY KEY NOT NULL,
"name" text,
"email" text NOT NULL,
"emailVerified" timestamp,
"image" text
);
CREATE TABLE IF NOT EXISTS "pastes" (
"id" text PRIMARY KEY NOT NULL,
"title" text,
"content" text NOT NULL,
"contentType" text DEFAULT 'text/plain',
"syntax" text,
"visibility" text DEFAULT 'public',
"author_id" text,
"session_id" text,
"expires_at" timestamp,
"created_at" timestamp DEFAULT now(),
"updated_at" timestamp DEFAULT now()
);
CREATE TABLE IF NOT EXISTS "tags" (
"id" text PRIMARY KEY NOT NULL,
"name" text NOT NULL UNIQUE,
"color" text,
"description" text
);
CREATE TABLE IF NOT EXISTS "pastes_to_tags" (
"paste_id" text NOT NULL,
"tag_id" text NOT NULL,
CONSTRAINT "pastes_to_tags_paste_id_tag_id_pk" PRIMARY KEY("paste_id", "tag_id")
);
CREATE TABLE IF NOT EXISTS "agent_sessions" (
"id" text PRIMARY KEY NOT NULL,
"title" text,
"agent_name" text,
"user_id" text,
"created_at" timestamp DEFAULT now()
);
CREATE TABLE IF NOT EXISTS "account" (
"userId" text NOT NULL,
"type" text NOT NULL,
@ -50,19 +12,17 @@ CREATE TABLE IF NOT EXISTS "account" (
"session_state" text,
CONSTRAINT "account_provider_providerAccountId_pk" PRIMARY KEY("provider", "providerAccountId")
);
CREATE TABLE IF NOT EXISTS "session" (
"sessionToken" text PRIMARY KEY NOT NULL,
"userId" text NOT NULL,
"expires" timestamp NOT NULL
);
CREATE TABLE IF NOT EXISTS "verificationToken" (
"identifier" text NOT NULL,
"token" text NOT NULL,
"expires" timestamp NOT NULL,
CONSTRAINT "verificationToken_identifier_token_pk" PRIMARY KEY("identifier", "token")
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "agent_sessions" (
"id" text PRIMARY KEY NOT NULL,
"title" text,
"agent_name" text,
"user_id" text,
"created_at" timestamp DEFAULT now()
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "authenticator" (
"credentialID" text PRIMARY KEY NOT NULL UNIQUE,
"credentialID" text NOT NULL,
"userId" text NOT NULL,
"providerAccountId" text NOT NULL,
"credentialPublicKey" text NOT NULL,
@ -70,55 +30,81 @@ CREATE TABLE IF NOT EXISTS "authenticator" (
"credentialDeviceType" text NOT NULL,
"credentialBackedUp" boolean NOT NULL,
"transports" text,
CONSTRAINT "authenticator_userId_credentialID_pk" PRIMARY KEY("userId", "credentialID")
CONSTRAINT "authenticator_userId_credentialID_pk" PRIMARY KEY("userId", "credentialID"),
CONSTRAINT "authenticator_credentialID_unique" UNIQUE("credentialID")
);
DO $$ BEGIN
ALTER TABLE "pastes"
ADD CONSTRAINT "pastes_author_id_user_id_fk" FOREIGN KEY ("author_id") REFERENCES "user"("id") ON DELETE
set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "pastes"
ADD CONSTRAINT "pastes_session_id_agent_sessions_id_fk" FOREIGN KEY ("session_id") REFERENCES "agent_sessions"("id") ON DELETE
set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "pastes_to_tags"
ADD CONSTRAINT "pastes_to_tags_paste_id_pastes_id_fk" FOREIGN KEY ("paste_id") REFERENCES "pastes"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "pastes_to_tags"
ADD CONSTRAINT "pastes_to_tags_tag_id_tags_id_fk" FOREIGN KEY ("tag_id") REFERENCES "tags"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "agent_sessions"
ADD CONSTRAINT "agent_sessions_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "pastes" (
"id" text PRIMARY KEY NOT NULL,
"title" text,
"content" text NOT NULL,
"content_type" text DEFAULT 'text/plain',
"syntax" text,
"visibility" text DEFAULT 'public',
"author_id" text,
"session_id" text,
"expires_at" timestamp,
"created_at" timestamp DEFAULT now(),
"updated_at" timestamp DEFAULT now()
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "pastes_to_tags" (
"paste_id" text,
"tag_id" text,
CONSTRAINT "pastes_to_tags_paste_id_tag_id_pk" PRIMARY KEY("paste_id", "tag_id")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "session" (
"sessionToken" text PRIMARY KEY NOT NULL,
"userId" text NOT NULL,
"expires" timestamp NOT NULL
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "tags" (
"id" text PRIMARY KEY NOT NULL,
"name" text NOT NULL,
"color" text,
"description" text,
CONSTRAINT "tags_name_unique" UNIQUE("name")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "user" (
"id" text PRIMARY KEY NOT NULL,
"name" text,
"email" text NOT NULL,
"emailVerified" timestamp,
"image" text
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "verificationToken" (
"identifier" text NOT NULL,
"token" text NOT NULL,
"expires" timestamp NOT NULL,
CONSTRAINT "verificationToken_identifier_token_pk" PRIMARY KEY("identifier", "token")
);
--> statement-breakpoint
ALTER TABLE "account"
ADD CONSTRAINT "account_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ALTER TABLE "session"
ADD CONSTRAINT "session_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
ADD CONSTRAINT "account_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
--> statement-breakpoint
ALTER TABLE "agent_sessions"
ADD CONSTRAINT "agent_sessions_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
--> statement-breakpoint
ALTER TABLE "authenticator"
ADD CONSTRAINT "authenticator_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
ADD CONSTRAINT "authenticator_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
--> statement-breakpoint
ALTER TABLE "pastes"
ADD CONSTRAINT "pastes_author_id_user_id_fk" FOREIGN KEY ("author_id") REFERENCES "public"."user"("id") ON DELETE
set null ON UPDATE no action;
--> statement-breakpoint
ALTER TABLE "pastes"
ADD CONSTRAINT "pastes_session_id_agent_sessions_id_fk" FOREIGN KEY ("session_id") REFERENCES "public"."agent_sessions"("id") ON DELETE
set null ON UPDATE no action;
--> statement-breakpoint
ALTER TABLE "pastes_to_tags"
ADD CONSTRAINT "pastes_to_tags_paste_id_pastes_id_fk" FOREIGN KEY ("paste_id") REFERENCES "public"."pastes"("id") ON DELETE cascade ON UPDATE no action;
--> statement-breakpoint
ALTER TABLE "pastes_to_tags"
ADD CONSTRAINT "pastes_to_tags_tag_id_tags_id_fk" FOREIGN KEY ("tag_id") REFERENCES "public"."tags"("id") ON DELETE cascade ON UPDATE no action;
--> statement-breakpoint
ALTER TABLE "session"
ADD CONSTRAINT "session_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;

View file

@ -0,0 +1,611 @@
{
"id": "f6b95186-510d-43a2-b8c9-40511244786f",
"prevId": "00000000-0000-0000-0000-000000000000",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.account": {
"name": "account",
"schema": "",
"columns": {
"userId": {
"name": "userId",
"type": "text",
"primaryKey": false,
"notNull": true
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": true
},
"provider": {
"name": "provider",
"type": "text",
"primaryKey": false,
"notNull": true
},
"providerAccountId": {
"name": "providerAccountId",
"type": "text",
"primaryKey": false,
"notNull": true
},
"refresh_token": {
"name": "refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"access_token": {
"name": "access_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "expires_at",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"token_type": {
"name": "token_type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"scope": {
"name": "scope",
"type": "text",
"primaryKey": false,
"notNull": false
},
"id_token": {
"name": "id_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"session_state": {
"name": "session_state",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"account_userId_user_id_fk": {
"name": "account_userId_user_id_fk",
"tableFrom": "account",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"account_provider_providerAccountId_pk": {
"name": "account_provider_providerAccountId_pk",
"columns": [
"provider",
"providerAccountId"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.agent_sessions": {
"name": "agent_sessions",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false
},
"agent_name": {
"name": "agent_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"agent_sessions_user_id_user_id_fk": {
"name": "agent_sessions_user_id_user_id_fk",
"tableFrom": "agent_sessions",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.authenticator": {
"name": "authenticator",
"schema": "",
"columns": {
"credentialID": {
"name": "credentialID",
"type": "text",
"primaryKey": false,
"notNull": true
},
"userId": {
"name": "userId",
"type": "text",
"primaryKey": false,
"notNull": true
},
"providerAccountId": {
"name": "providerAccountId",
"type": "text",
"primaryKey": false,
"notNull": true
},
"credentialPublicKey": {
"name": "credentialPublicKey",
"type": "text",
"primaryKey": false,
"notNull": true
},
"counter": {
"name": "counter",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"credentialDeviceType": {
"name": "credentialDeviceType",
"type": "text",
"primaryKey": false,
"notNull": true
},
"credentialBackedUp": {
"name": "credentialBackedUp",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"transports": {
"name": "transports",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"authenticator_userId_user_id_fk": {
"name": "authenticator_userId_user_id_fk",
"tableFrom": "authenticator",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"authenticator_userId_credentialID_pk": {
"name": "authenticator_userId_credentialID_pk",
"columns": [
"userId",
"credentialID"
]
}
},
"uniqueConstraints": {
"authenticator_credentialID_unique": {
"name": "authenticator_credentialID_unique",
"nullsNotDistinct": false,
"columns": [
"credentialID"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.pastes": {
"name": "pastes",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false
},
"content": {
"name": "content",
"type": "text",
"primaryKey": false,
"notNull": true
},
"content_type": {
"name": "content_type",
"type": "text",
"primaryKey": false,
"notNull": false,
"default": "'text/plain'"
},
"syntax": {
"name": "syntax",
"type": "text",
"primaryKey": false,
"notNull": false
},
"visibility": {
"name": "visibility",
"type": "text",
"primaryKey": false,
"notNull": false,
"default": "'public'"
},
"author_id": {
"name": "author_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"session_id": {
"name": "session_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"pastes_author_id_user_id_fk": {
"name": "pastes_author_id_user_id_fk",
"tableFrom": "pastes",
"tableTo": "user",
"columnsFrom": [
"author_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
},
"pastes_session_id_agent_sessions_id_fk": {
"name": "pastes_session_id_agent_sessions_id_fk",
"tableFrom": "pastes",
"tableTo": "agent_sessions",
"columnsFrom": [
"session_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.pastes_to_tags": {
"name": "pastes_to_tags",
"schema": "",
"columns": {
"paste_id": {
"name": "paste_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"tag_id": {
"name": "tag_id",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"pastes_to_tags_paste_id_pastes_id_fk": {
"name": "pastes_to_tags_paste_id_pastes_id_fk",
"tableFrom": "pastes_to_tags",
"tableTo": "pastes",
"columnsFrom": [
"paste_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"pastes_to_tags_tag_id_tags_id_fk": {
"name": "pastes_to_tags_tag_id_tags_id_fk",
"tableFrom": "pastes_to_tags",
"tableTo": "tags",
"columnsFrom": [
"tag_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"pastes_to_tags_paste_id_tag_id_pk": {
"name": "pastes_to_tags_paste_id_tag_id_pk",
"columns": [
"paste_id",
"tag_id"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.session": {
"name": "session",
"schema": "",
"columns": {
"sessionToken": {
"name": "sessionToken",
"type": "text",
"primaryKey": true,
"notNull": true
},
"userId": {
"name": "userId",
"type": "text",
"primaryKey": false,
"notNull": true
},
"expires": {
"name": "expires",
"type": "timestamp",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"session_userId_user_id_fk": {
"name": "session_userId_user_id_fk",
"tableFrom": "session",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.tags": {
"name": "tags",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"color": {
"name": "color",
"type": "text",
"primaryKey": false,
"notNull": false
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"tags_name_unique": {
"name": "tags_name_unique",
"nullsNotDistinct": false,
"columns": [
"name"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.user": {
"name": "user",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"emailVerified": {
"name": "emailVerified",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"image": {
"name": "image",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.verificationToken": {
"name": "verificationToken",
"schema": "",
"columns": {
"identifier": {
"name": "identifier",
"type": "text",
"primaryKey": false,
"notNull": true
},
"token": {
"name": "token",
"type": "text",
"primaryKey": false,
"notNull": true
},
"expires": {
"name": "expires",
"type": "timestamp",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {
"verificationToken_identifier_token_pk": {
"name": "verificationToken_identifier_token_pk",
"columns": [
"identifier",
"token"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View file

@ -0,0 +1,13 @@
{
"version": "7",
"dialect": "postgresql",
"entries": [
{
"idx": 0,
"version": "7",
"when": 1765959773637,
"tag": "0000_busy_bill_hollister",
"breakpoints": true
}
]
}