Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions apps/hub/src/db/migrate.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { expect, test } from "bun:test";
import journal from "./migrations/meta/_journal.json";

// 0038 reapplies 0037 on databases that skipped it, so 0037 stays as shipped.
const repairedOutOfOrder = new Set(["0037_approval_round"]);

// The migrator skips any migration whose `when` is not later than the newest
// one already applied, so an out-of-order entry never runs on existing databases.
test("migration journal timestamps strictly increase", () => {
const entries = [...journal.entries].sort((a, b) => a.idx - b.idx);
let latest = 0;
const outOfOrder: string[] = [];
for (const entry of entries) {
if (entry.when <= latest) outOfOrder.push(entry.tag);
latest = Math.max(latest, entry.when);
}
expect(outOfOrder).toEqual([...repairedOutOfOrder]);
});
32 changes: 32 additions & 0 deletions apps/hub/src/db/migrations/0038_approval_round_reapply.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
-- 0037's journal timestamp sorts before 0036's, so databases migrated past
-- 0036 skipped it. This reapplies 0037 so it is a no-op where it already ran.
CREATE TABLE IF NOT EXISTS "sb_approval_round" (
"id" text PRIMARY KEY NOT NULL,
"tenant_id" text NOT NULL,
"project_id" text NOT NULL,
"artifact_id" text NOT NULL,
"package_version" integer NOT NULL,
"package_sha256" text NOT NULL,
"started_by" text NOT NULL,
"expiry_preset" text NOT NULL,
"expires_at" timestamp with time zone NOT NULL,
"settled_at" timestamp with time zone,
"reviewers" jsonb NOT NULL,
"triage" jsonb DEFAULT '[]'::jsonb NOT NULL,
"triggered_run_id" text,
"created_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "sb_approval_round" ADD CONSTRAINT "sb_approval_round_tenant_id_tenant_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenant"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "sb_approval_round" ADD CONSTRAINT "sb_approval_round_project_id_project_id_fk" FOREIGN KEY ("project_id") REFERENCES "public"."project"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "sb_approval_round" ADD CONSTRAINT "sb_approval_round_started_by_principal_id_fk" FOREIGN KEY ("started_by") REFERENCES "public"."principal"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "sb_approval_round_project_idx" ON "sb_approval_round" USING btree ("tenant_id","project_id","created_at");
Loading