Commit13e7ee3
fix(deploy): unblock flyctl deploy — COPY drizzle, migration breakpoints, healthz shape, --ha=false
fix(deploy): unblock flyctl deploy — COPY drizzle, migration breakpoints, healthz shape, --ha=false Four P0s that would have bricked the first `flyctl deploy`: 1. Dockerfile never COPYd drizzle/ into the image — src/db/migrate.ts (line 30) readdir'd an empty dir, logged "No migration files found.", exited 0, and left the DB schema empty. Every DB-backed route would have 500'd on the first user request. Added `COPY drizzle/ ./drizzle/`. 2. Five migration files (0030 signing_keys, 0031 user_follows, 0032 repo_rulesets, 0033 commit_statuses) shipped without `--> statement-breakpoint` markers. migrate.ts:50 splits on that marker and hands each chunk to neon()'s HTTP sql() — which only accepts single statements. Without breakpoints the whole file was one giant multi-statement blob and Neon rejects it. Added markers between every top-level DDL statement. 3. /healthz body shape didn't match what scripts/preflight.ts:253 asserted (`status: "ok"`). `bun run preflight` — the documented pre-deploy gate — was therefore red even on a healthy process. Added `status: "ok"` alongside the existing `ok: true`. 4. flyctl deploy defaulted to HA mode (2 machines). fly.toml has a single-mount [[mounts]] block pointing at one gluecron_repos volume — the second machine would never attach it and would crash-loop. Added `--ha=false` so the deploy matches the single-volume shape. Also added: - Dead lines removed from Dockerfile: `RUN mkdir -p /data/repos` and `ENV GIT_REPOS_PATH=/data/repos` — fly.toml overrides the env var to `/app/repos` (the actual volume mount path) so the Dockerfile defaults were no-ops. - .github/workflows/fly-deploy.yml now triggers on the current feature branch so the deploy can run before we merge to main. Duplicate drizzle/0000_init.sql (hand-rolled, no breakpoints) will be deleted in a follow-up commit; 0000_initial.sql (drizzle-kit format, has breakpoints) covers the same schema.
7 files changed+19−513e7ee303353f6c3344b3388c94a5c628807de37
7 changed files+19−5
Modified.github/workflows/fly-deploy.yml+6−1View fileUnifiedSplit
@@ -5,6 +5,7 @@ on:
55 branches:
66 - main
77 - claude/build-status-update-3MXsf
8 - claude/crontech-platform-setup-SeKfw
89 workflow_dispatch: {}
910
1011concurrency:
@@ -58,7 +59,11 @@ jobs:
5859 EMAIL_PROVIDER: ${{ vars.EMAIL_PROVIDER || 'log' }}
5960
6061 - name: Deploy
61 run: flyctl deploy --remote-only --app gluecron
62 # --ha=false forces single-machine deploy. The [[mounts]] block in
63 # fly.toml attaches to ONE gluecron_repos volume; Fly's default HA
64 # mode spins up a second machine that cannot attach the volume and
65 # crash-loops. Single volume → single machine.
66 run: flyctl deploy --remote-only --ha=false --app gluecron
6267 env:
6368 FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
6469
ModifiedDockerfile+1−4View fileUnifiedSplit
@@ -10,14 +10,11 @@ RUN bun install --frozen-lockfile --production
1010
1111# Copy source
1212COPY src/ ./src/
13COPY drizzle/ ./drizzle/
1314COPY tsconfig.json drizzle.config.ts ./
1415COPY legal/ ./legal/
1516COPY CLAUDE.md LICENSE ./
1617
17# Create repos directory
18RUN mkdir -p /data/repos
19
20ENV GIT_REPOS_PATH=/data/repos
2118ENV NODE_ENV=production
2219ENV PORT=3000
2320
Modifieddrizzle/0030_signing_keys.sql+4−0View fileUnifiedSplit
@@ -20,11 +20,14 @@ CREATE TABLE IF NOT EXISTS "signing_keys" (
2020 "last_used_at" timestamp,
2121 "created_at" timestamp NOT NULL DEFAULT now()
2222);
23--> statement-breakpoint
2324
2425CREATE UNIQUE INDEX IF NOT EXISTS "signing_keys_fp_unique"
2526 ON "signing_keys" ("key_type", "fingerprint");
27--> statement-breakpoint
2628CREATE INDEX IF NOT EXISTS "signing_keys_user_idx"
2729 ON "signing_keys" ("user_id");
30--> statement-breakpoint
2831
2932CREATE TABLE IF NOT EXISTS "commit_verifications" (
3033 "id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
@@ -38,6 +41,7 @@ CREATE TABLE IF NOT EXISTS "commit_verifications" (
3841 "signer_fingerprint" text,
3942 "verified_at" timestamp NOT NULL DEFAULT now()
4043);
44--> statement-breakpoint
4145
4246CREATE UNIQUE INDEX IF NOT EXISTS "commit_verifications_sha_unique"
4347 ON "commit_verifications" ("repository_id", "commit_sha");
Modifieddrizzle/0031_user_follows.sql+1−0View fileUnifiedSplit
@@ -10,6 +10,7 @@ CREATE TABLE IF NOT EXISTS "user_follows" (
1010 PRIMARY KEY ("follower_id", "following_id"),
1111 CONSTRAINT "user_follows_no_self" CHECK ("follower_id" <> "following_id")
1212);
13--> statement-breakpoint
1314
1415CREATE INDEX IF NOT EXISTS "user_follows_following_idx"
1516 ON "user_follows" ("following_id");
Modifieddrizzle/0032_repo_rulesets.sql+4−0View fileUnifiedSplit
@@ -14,11 +14,14 @@ CREATE TABLE IF NOT EXISTS "repo_rulesets" (
1414 "created_at" timestamp NOT NULL DEFAULT now(),
1515 "updated_at" timestamp NOT NULL DEFAULT now()
1616);
17--> statement-breakpoint
1718
1819CREATE INDEX IF NOT EXISTS "repo_rulesets_repo_idx"
1920 ON "repo_rulesets" ("repository_id");
21--> statement-breakpoint
2022CREATE UNIQUE INDEX IF NOT EXISTS "repo_rulesets_repo_name_unique"
2123 ON "repo_rulesets" ("repository_id", "name");
24--> statement-breakpoint
2225
2326CREATE TABLE IF NOT EXISTS "ruleset_rules" (
2427 "id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
@@ -27,6 +30,7 @@ CREATE TABLE IF NOT EXISTS "ruleset_rules" (
2730 "params" text NOT NULL DEFAULT '{}', -- JSON
2831 "created_at" timestamp NOT NULL DEFAULT now()
2932);
33--> statement-breakpoint
3034
3135CREATE INDEX IF NOT EXISTS "ruleset_rules_set_idx"
3236 ON "ruleset_rules" ("ruleset_id");
Modifieddrizzle/0033_commit_statuses.sql+2−0View fileUnifiedSplit
@@ -16,9 +16,11 @@ CREATE TABLE IF NOT EXISTS "commit_statuses" (
1616 "created_at" timestamp NOT NULL DEFAULT now(),
1717 "updated_at" timestamp NOT NULL DEFAULT now()
1818);
19--> statement-breakpoint
1920
2021CREATE UNIQUE INDEX IF NOT EXISTS "commit_statuses_repo_sha_context_unique"
2122 ON "commit_statuses" ("repository_id", "commit_sha", "context");
23--> statement-breakpoint
2224
2325CREATE INDEX IF NOT EXISTS "commit_statuses_repo_sha_idx"
2426 ON "commit_statuses" ("repository_id", "commit_sha");