Drizzle migrations in CI/CD
An example on how to run Drizzle migrations as a part of your CI/CD.
Start by creating a function that runs migrations.
const migrator = new sst.aws.Function("DatabaseMigrator", { handler: "src/migrator.handler", link: [rds], vpc, copyFiles: [ { from: "migrations", to: "./migrations", }, ],});Where src/migrator.ts looks like.
import { db } from "./drizzle";import { migrate } from "drizzle-orm/postgres-js/migrator";
export const handler = async (event: any) => { await migrate(db, { migrationsFolder: "./migrations", });};And we can set it up to run on every deploy.
if (!$dev){ new aws.lambda.Invocation("DatabaseMigratorInvocation", { input: Date.now().toString(), functionName: migrator.name, });}We use the current time to make sure the function runs on every deploy.
const vpc = new sst.aws.Vpc("MyVpc", { bastion: true, nat: "ec2" });const rds = new sst.aws.Postgres("MyPostgres", { vpc, proxy: true });
new sst.aws.Function("MyApi", { vpc, url: true, link: [rds], handler: "src/api.handler",});
const migrator = new sst.aws.Function("DatabaseMigrator", { handler: "src/migrator.handler", link: [rds], vpc, copyFiles: [ { from: "migrations", to: "./migrations", }, ],});
if (!$dev) { new aws.lambda.Invocation("DatabaseMigratorInvocation", { input: Date.now().toString(), functionName: migrator.name, });}
new sst.x.DevCommand("Studio", { link: [rds], dev: { command: "npx drizzle-kit studio", },});import { db } from "./drizzle";import { todo } from "./todo.sql";import { APIGatewayProxyEventV2 } from "aws-lambda";
export const handler = async (evt: APIGatewayProxyEventV2) => { if (evt.requestContext.http.method === "GET") { const result = await db.select().from(todo).execute();
return { statusCode: 200, body: JSON.stringify(result, null, 2), }; }
if (evt.requestContext.http.method === "POST") { const result = await db .insert(todo) .values({ title: "Todo", description: crypto.randomUUID() }) .returning() .execute();
return { statusCode: 200, body: JSON.stringify(result), }; }};View the full example.