Skip to content

Commit 502a324

Browse files
zomarskeithwillcodeUdit-takkar
authored
chore: run migrations conditionally (#13925)
Co-authored-by: Keith Williams <keithwillcode@gmail.com> Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
1 parent a4bc079 commit 502a324

File tree

6 files changed

+75
-27
lines changed

6 files changed

+75
-27
lines changed

apps/web/app/future/apps/categories/[category]/page.tsx

+5-11
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import CategoryPage, { type PageProps } from "@pages/apps/categories/[category]";
2-
import { Prisma } from "@prisma/client";
32
import { withAppDirSsg } from "app/WithAppDirSsg";
43
import { _generateMetadata } from "app/_utils";
54
import { WithLayout } from "app/layoutHOC";
65

76
import { APP_NAME } from "@calcom/lib/constants";
8-
import prisma from "@calcom/prisma";
97
import { AppCategories } from "@calcom/prisma/enums";
8+
import { isPrismaAvailableCheck } from "@calcom/prisma/is-prisma-available-check";
109

1110
import { getStaticProps } from "@lib/apps/categories/[category]/getStaticProps";
1211

@@ -19,16 +18,11 @@ export const generateMetadata = async () => {
1918

2019
export const generateStaticParams = async () => {
2120
const paths = Object.keys(AppCategories);
21+
const isPrismaAvailable = await isPrismaAvailableCheck();
2222

23-
try {
24-
await prisma.$queryRaw`SELECT 1`;
25-
} catch (e: unknown) {
26-
if (e instanceof Prisma.PrismaClientInitializationError) {
27-
// Database is not available at build time. Make sure we fall back to building these pages on demand
28-
return [];
29-
} else {
30-
throw e;
31-
}
23+
if (!isPrismaAvailable) {
24+
// Database is not available at build time. Make sure we fall back to building these pages on demand
25+
return [];
3226
}
3327

3428
return paths.map((category) => ({ category }));

apps/web/pages/apps/categories/[category].tsx

+8-15
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
"use client";
22

3-
import { Prisma } from "@prisma/client";
43
import type { InferGetStaticPropsType } from "next";
54
import Link from "next/link";
65

76
import Shell from "@calcom/features/shell/Shell";
87
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
98
import { useLocale } from "@calcom/lib/hooks/useLocale";
10-
import prisma from "@calcom/prisma";
119
import { AppCategories } from "@calcom/prisma/enums";
10+
import { isPrismaAvailableCheck } from "@calcom/prisma/is-prisma-available-check";
1211
import { AppCard, SkeletonText } from "@calcom/ui";
1312

1413
import { getStaticProps } from "@lib/apps/categories/[category]/getStaticProps";
@@ -62,19 +61,13 @@ Apps.PageWrapper = PageWrapper;
6261

6362
export const getStaticPaths = async () => {
6463
const paths = Object.keys(AppCategories);
65-
66-
try {
67-
await prisma.$queryRaw`SELECT 1`;
68-
} catch (e: unknown) {
69-
if (e instanceof Prisma.PrismaClientInitializationError) {
70-
// Database is not available at build time. Make sure we fall back to building these pages on demand
71-
return {
72-
paths: [],
73-
fallback: "blocking",
74-
};
75-
} else {
76-
throw e;
77-
}
64+
const isPrismaAvailable = await isPrismaAvailableCheck();
65+
if (!isPrismaAvailable) {
66+
// Database is not available at build time. Make sure we fall back to building these pages on demand
67+
return {
68+
paths: [],
69+
fallback: "blocking",
70+
};
7871
}
7972

8073
return {

packages/prisma/auto-migrations.ts

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import dotEnv from "dotenv";
2+
import { exec as execCb } from "node:child_process";
3+
import { promisify } from "node:util";
4+
5+
import { isPrismaAvailableCheck } from "./is-prisma-available-check";
6+
7+
dotEnv.config({ path: "../../.env" });
8+
9+
const exec = promisify(execCb);
10+
11+
/**
12+
* TODO: re-write this when Prisma.io gets a programmatic migration API
13+
* Thanks to @olalonde for the idea.
14+
* @see https://github.com/prisma/prisma/issues/4703#issuecomment-1447354363
15+
*/
16+
async function main(): Promise<void> {
17+
if (!process.env.DATABASE_URL) {
18+
console.info("No DATABASE_URL found, skipping migrations");
19+
return;
20+
}
21+
if (!process.env.DATABASE_DIRECT_URL) {
22+
console.info("No DATABASE_DIRECT_URL found, skipping migrations");
23+
return;
24+
}
25+
if (!(await isPrismaAvailableCheck())) {
26+
console.info("Prisma can't be initialized, skipping migrations");
27+
return;
28+
}
29+
// throws an error if migration fails
30+
const { stdout, stderr } = await exec("yarn prisma migrate deploy", {
31+
env: {
32+
...process.env,
33+
},
34+
});
35+
console.log(stdout);
36+
console.error(stderr);
37+
}
38+
39+
main().catch((e) => {
40+
console.error(e.stdout || e.stderr || e.message);
41+
process.exit(1);
42+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Prisma } from "@prisma/client";
2+
3+
import prisma from ".";
4+
5+
export async function isPrismaAvailableCheck() {
6+
try {
7+
await prisma.$queryRaw`SELECT 1`;
8+
return true;
9+
} catch (e: unknown) {
10+
if (e instanceof Prisma.PrismaClientInitializationError) {
11+
// Database might not available at build time.
12+
return false;
13+
} else {
14+
throw e;
15+
}
16+
}
17+
}

packages/prisma/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"private": true,
55
"scripts": {
66
"clean": "rm -rf .turbo && rm -rf node_modules",
7-
"build": "yarn prisma migrate deploy || true",
7+
"build": "ts-node --transpile-only ./auto-migrations.ts",
88
"db-deploy": "yarn prisma migrate deploy",
99
"db-migrate": "yarn prisma migrate dev",
1010
"db-nuke": "docker compose down --volumes --remove-orphans || docker-compose down --volumes --remove-orphans",

turbo.json

+2
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@
237237
"DAILY_API_KEY",
238238
"DAILY_SCALE_PLAN",
239239
"DAILY_WEBHOOK_SECRET",
240+
"DATABASE_DIRECT_URL",
241+
"DATABASE_URL",
240242
"DEBUG",
241243
"E2E_TEST_APPLE_CALENDAR_EMAIL",
242244
"E2E_TEST_APPLE_CALENDAR_PASSWORD",

0 commit comments

Comments
 (0)