跳至主要内容

如何使用 GitHub Actions 和 Prisma Postgres 预配预览数据库

15 分钟

概述

本指南将向您展示如何使用 GitHub Actions 和 Prisma Postgres 管理 API 自动创建和删除 Prisma Postgres 数据库。此设置将为每个拉取请求预配一个新数据库,用示例数据填充它,并且 github-actions 机器人会留下一个包含数据库名称和状态的评论。

GitHub Actions comment

PR 关闭后,数据库将自动删除。这允许您在隔离环境中测试更改,而不会影响主开发数据库。

先决条件

请确保您具备以下条件

  • Node.js 20 或更高版本
  • 一、帐户
  • GitHub 存储库

1. 设置项目

初始化您的项目

mkdir prisma-gha-demo && cd prisma-gha-demo
npm init -y

2. 安装和配置 Prisma

在本节中,您将在项目中设置 Prisma,并在将其集成到 GitHub Actions 之前验证其在本地的运行情况。这包括安装 Prisma 的依赖项,连接到 Prisma Postgres 数据库,定义数据模型,应用架构,以及使用示例数据填充数据库。

到本节结束时,您的项目将完全准备好在本地和 CI 工作流中使用 Prisma。

2.1. 安装依赖项

要开始使用 Prisma,请安装所需的依赖项

npm install prisma tsx @types/pg dotenv --save-dev
npm install @prisma/client @prisma/adapter-pg pg
信息

如果你使用的是其他数据库提供程序(MySQL、SQL Server、SQLite),请安装相应的驱动程序适配器包,而不是 @prisma/adapter-pg。有关更多信息,请参阅 数据库驱动程序

安装后,初始化 Prisma

npx prisma init --db --output ../src/generated/prisma

这将创建

  • 一个包含 schema.prismaprisma/ 目录
  • 一个包含 DATABASE_URL.env 文件
  • 一个在 src/generated/prisma 中生成的客户端

2.2. 定义您的 Prisma 架构

编辑 prisma/schema.prisma

prisma/schema.prisma
generator client {
provider = "prisma-client"
output = "../src/generated/prisma"
}

datasource db {
provider = "postgresql"
}

model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}

model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
authorId Int
author User @relation(fields: [authorId], references: [id])
}

创建一个 prisma.config.ts 文件来配置 Prisma 进行填充

prisma.config.ts
import 'dotenv/config'
import { defineConfig, env } from 'prisma/config';

export default defineConfig({
schema: 'prisma/schema.prisma',
migrations: {
path: 'prisma/migrations',
seed: `tsx src/seed.ts`,
},
datasource: {
url: env('DATABASE_URL'),
},
});
注意

您需要安装 dotenv

npm install dotenv

2.3. 运行初始迁移并生成客户端

npx prisma migrate dev --name init

然后生成 Prisma Client

npx prisma generate

这将推送您的架构并准备好客户端。

2.4. 填充数据库

src/seed.ts 创建一个文件

src/seed.ts
import { PrismaClient } from "../src/generated/prisma/client";
import { PrismaPg } from "@prisma/adapter-pg";
import "dotenv/config";

const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL!,
});

const prisma = new PrismaClient({
adapter,
});

const userData = [
{
name: "Alice",
email: "alice@prisma.io",
posts: {
create: [
{
title: "Join the Prisma Discord",
content: "https://pris.ly/discord",
published: true,
},
{
title: "Prisma on YouTube",
content: "https://pris.ly/youtube",
},
],
},
},
{
name: "Bob",
email: "bob@prisma.io",
posts: {
create: [
{
title: "Follow Prisma on Twitter",
content: "https://twitter.com/prisma",
published: true,
},
],
},
},
];

export async function main() {
for (const u of userData) {
await prisma.user.create({ data: u });
}
}

main()
.catch(console.error)
.finally(() => prisma.$disconnect());

更新您的 package.json

package.json
{
{
"name": "prisma-gha-demo",
"version": "1.0.0",
"description": "",
"scripts": {
"seed": "tsx src/seed.ts"
},
// other configurations...
}

然后运行

npm run seed
npx prisma studio

导航到 https://:5555 并验证数据库是否已填充示例数据。现在您已准备好使用 GitHub Actions 自动化此过程。

3. 添加 GitHub Actions 工作流

在此步骤中,您将设置一个 GitHub Actions 工作流,该工作流在新拉取请求 (PR) 打开时自动预配 Prisma Postgres 数据库。一旦 PR 关闭,工作流将清理数据库。

3.1 创建工作流文件

首先创建所需的目录和文件

mkdir -p .github/workflows
touch .github/workflows/prisma-postgres-management.yml

此文件将包含按 PR 管理数据库的逻辑。此 GitHub Actions 工作流将

  • 在 PR 打开时预配一个临时 Prisma Postgres 数据库
  • 使用测试数据填充数据库
  • 在 PR 关闭时清理数据库
  • 支持预配和清理的手动执行
注意

此工作流使用 us-east-1 作为 Prisma Postgres 的默认区域。您可以通过修改 API 调用中的 region 参数,甚至通过向工作流添加 region 输入来将其更改为首选区域。

3.2. 添加基本配置

将以下内容粘贴到 .github/workflows/prisma-postgres-management.yml 中。这将设置工作流何时运行并提供所需的环境变量。

.github/workflows/prisma-postgres-management.yml
name: Prisma Postgres Management API Workflow

on:
pull_request:
types: [opened, reopened, closed]
workflow_dispatch:
inputs:
action:
description: "Action to perform"
required: true
default: "provision"
type: choice
options:
- provision
- cleanup
database_name:
description: "Database name (for testing, will be sanitized)"
required: false
type: string

env:
PRISMA_POSTGRES_SERVICE_TOKEN: ${{ secrets.PRISMA_POSTGRES_SERVICE_TOKEN }}
PRISMA_PROJECT_ID: ${{ secrets.PRISMA_PROJECT_ID }}
# Sanitize database name once at workflow level
DB_NAME: ${{ github.event.pull_request.number != null && format('pr-{0}-{1}', github.event.pull_request.number, github.event.pull_request.head.ref) || (inputs.database_name != '' && inputs.database_name || format('test-{0}', github.run_number)) }}

# Prevent concurrent runs of the same PR
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

现在您将向此工作流添加预配和清理作业。这些作业将根据拉取请求事件处理 Prisma Postgres 数据库的创建和删除。

3.3. 向工作流添加预配作业

现在添加一个作业,用于在 PR 打开或手动触发时预配数据库。此预配作业将

  • 安装依赖项
  • 检查现有数据库
  • 如果需要,创建一个新数据库
  • 填充数据库
  • 在 PR 上评论状态

在工作流文件中的 jobs: 键下追加以下内容

.github/workflows/prisma-postgres-management.yml
jobs:
provision-database:
if: (github.event_name == 'pull_request' && github.event.action != 'closed') || (github.event_name == 'workflow_dispatch' && inputs.action == 'provision')
runs-on: ubuntu-latest
permissions: write-all
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "22"
cache: "npm"

- name: Install Dependencies
run: npm install

- name: Validate Environment Variables
run: |
if [ -z "${{ env.PRISMA_POSTGRES_SERVICE_TOKEN }}" ]; then
echo "Error: PRISMA_POSTGRES_SERVICE_TOKEN secret is not set"
exit 1
fi
if [ -z "${{ env.PRISMA_PROJECT_ID }}" ]; then
echo "Error: PRISMA_PROJECT_ID secret is not set"
exit 1
fi

- name: Sanitize Database Name
run: |
# Sanitize the database name to match Prisma's requirements
DB_NAME="$(echo "${{ env.DB_NAME }}" | tr '/' '_' | tr '-' '_' | tr '[:upper:]' '[:lower:]')"
echo "DB_NAME=$DB_NAME" >> $GITHUB_ENV

- name: Check If Database Exists
id: check-db
run: |
echo "Fetching all databases..."
RESPONSE=$(curl -s -X GET \
-H "Authorization: Bearer ${{ env.PRISMA_POSTGRES_SERVICE_TOKEN }}" \
-H "Content-Type: application/json" \
"https://api.prisma.io/v1/projects/${{ env.PRISMA_PROJECT_ID }}/databases")

echo "Looking for database with name: ${{ env.DB_NAME }}"

# Extract database ID using jq to properly parse JSON
DB_EXISTS=$(echo "$RESPONSE" | jq -r ".data[]? | select(.name == \"${{ env.DB_NAME }}\") | .id")

if [ ! -z "$DB_EXISTS" ] && [ "$DB_EXISTS" != "null" ]; then
echo "Database ${{ env.DB_NAME }} exists with ID: $DB_EXISTS."
echo "exists=true" >> $GITHUB_OUTPUT
echo "db-id=$DB_EXISTS" >> $GITHUB_OUTPUT
else
echo "No existing database found with name ${{ env.DB_NAME }}"
echo "exists=false" >> $GITHUB_OUTPUT
fi

- name: Create Database
id: create-db
if: steps.check-db.outputs.exists != 'true'
run: |
echo "Creating database ${{ env.DB_NAME }}..."
RESPONSE=$(curl -s -X POST \
-H "Authorization: Bearer ${{ env.PRISMA_POSTGRES_SERVICE_TOKEN }}" \
-H "Content-Type: application/json" \
-d "{\"name\": \"${{ env.DB_NAME }}\", \"region\": \"us-east-1\"}" \
"https://api.prisma.io/v1/projects/${{ env.PRISMA_PROJECT_ID }}/databases")

# Check if response contains an id (success case)
if echo "$RESPONSE" | grep -q '"id":'; then
echo "Database created successfully"
CONNECTION_STRING=$(echo "$RESPONSE" | jq -r '.data.connectionString')
echo "connection-string=$CONNECTION_STRING" >> $GITHUB_OUTPUT
else
echo "Failed to create database"
echo "$RESPONSE"
exit 1
fi

- name: Get Connection String for Existing Database
id: get-connection
if: steps.check-db.outputs.exists == 'true'
run: |
echo "Creating new connection string for existing database..."
CONNECTION_RESPONSE=$(curl -s -X POST \
-H "Authorization: Bearer ${{ env.PRISMA_POSTGRES_SERVICE_TOKEN }}" \
-H "Content-Type: application/json" \
-d '{"name":"read_write_key"}' \
"https://api.prisma.io/v1/databases/${{ steps.check-db.outputs.db-id }}/connections")

CONNECTION_STRING=$(echo "$CONNECTION_RESPONSE" | jq -r '.data.connectionString')
echo "connection-string=$CONNECTION_STRING" >> $GITHUB_OUTPUT

- name: Setup Database Schema
run: |
# Get connection string from appropriate step
if [ "${{ steps.check-db.outputs.exists }}" = "true" ]; then
CONNECTION_STRING="${{ steps.get-connection.outputs.connection-string }}"
else
CONNECTION_STRING="${{ steps.create-db.outputs.connection-string }}"
fi

# Set the DATABASE_URL
export DATABASE_URL="$CONNECTION_STRING"

# Generate Prisma Client
npx prisma generate

# Push schema to database
npx prisma db push

- name: Seed Database
run: |
# Get connection string from appropriate step
if [ "${{ steps.check-db.outputs.exists }}" = "true" ]; then
CONNECTION_STRING="${{ steps.get-connection.outputs.connection-string }}"
else
CONNECTION_STRING="${{ steps.create-db.outputs.connection-string }}"
fi

# Set the DATABASE_URL environment variable for the seed script
export DATABASE_URL="$CONNECTION_STRING"

# Generate Prisma Client
npx prisma generate

# Run the seed script
npm run seed

- name: Comment PR
if: success() && github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `🗄️ Database provisioned successfully!\n\nDatabase name: ${{ env.DB_NAME }}\nStatus: Ready and seeded with sample data`
})

- name: Output Database Info
if: success() && github.event_name == 'workflow_dispatch'
run: |
echo "🗄️ Database provisioned successfully!"
echo "Database name: ${{ env.DB_NAME }}"
echo "Status: Ready and seeded with sample data"

3.4. 向工作流添加清理作业

当拉取请求关闭时,您可以通过添加清理作业自动删除关联的数据库。此清理作业将

  • 按名称查找数据库
  • 从 Prisma Postgres 项目中删除它
  • 也可以使用 action: cleanup 手动触发

将以下内容追加到您的 jobs: 部分,位于 provision-database 作业之后

.github/workflows/prisma-postgres-management.yml
  cleanup-database:
if: (github.event_name == 'pull_request' && github.event.action == 'closed') || (github.event_name == 'workflow_dispatch' && inputs.action == 'cleanup')
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Validate Environment Variables
run: |
if [ -z "${{ env.PRISMA_POSTGRES_SERVICE_TOKEN }}" ]; then
echo "Error: PRISMA_POSTGRES_SERVICE_TOKEN secret is not set"
exit 1
fi
if [ -z "${{ env.PRISMA_PROJECT_ID }}" ]; then
echo "Error: PRISMA_PROJECT_ID secret is not set"
exit 1
fi

- name: Sanitize Database Name
run: |
# Sanitize the database name
DB_NAME="$(echo "${{ env.DB_NAME }}" | tr '/' '_' | tr '-' '_' | tr '[:upper:]' '[:lower:]')"
echo "DB_NAME=$DB_NAME" >> $GITHUB_ENV

- name: Delete Database
run: |
echo "Fetching all databases..."
RESPONSE=$(curl -s -X GET \
-H "Authorization: Bearer ${{ env.PRISMA_POSTGRES_SERVICE_TOKEN }}" \
-H "Content-Type: application/json" \
"https://api.prisma.io/v1/projects/${{ env.PRISMA_PROJECT_ID }}/databases")

echo "Looking for database with name: ${{ env.DB_NAME }}"

# Extract database ID using jq to properly parse JSON
DB_EXISTS=$(echo "$RESPONSE" | jq -r ".data[]? | select(.name == \"${{ env.DB_NAME }}\") | .id")

if [ ! -z "$DB_EXISTS" ] && [ "$DB_EXISTS" != "null" ]; then
echo "Database ${{ env.DB_NAME }} exists with ID: $DB_EXISTS. Deleting..."
DELETE_RESPONSE=$(curl -s -X DELETE \
-H "Authorization: Bearer ${{ env.PRISMA_POSTGRES_SERVICE_TOKEN }}" \
-H "Content-Type: application/json" \
"https://api.prisma.io/v1/databases/$DB_EXISTS")

echo "Delete API Response: $DELETE_RESPONSE"

if echo "$DELETE_RESPONSE" | grep -q '"error":'; then
ERROR_MSG=$(echo "$DELETE_RESPONSE" | jq -r '.message // "Unknown error"')
echo "Failed to delete database: $ERROR_MSG"
exit 1
else
echo "Database deletion initiated successfully"
fi
else
echo "No existing database found with name ${{ env.DB_NAME }}"
fi

这完成了您的 Prisma Postgres 管理工作流设置。在下一步中,您将配置所需的 GitHub 密钥以向 Prisma API 进行身份验证。

4. 将代码存储在 GitHub 中

初始化一个 git 存储库并推送到 GitHub

如果您在 GitHub 中还没有存储库,请在 GitHub 上创建一个。一旦存储库准备就绪,运行以下命令

git add .
git commit -m "Initial commit with Prisma Postgres integration"
git branch -M main
git remote add origin https://github.com/<your-username>/<repository-name>.git
git push -u origin main
注意

<your-username><repository-name> 替换为您的 GitHub 用户名和存储库名称。

5. 检索工作流的密钥

5.1. 检索您的 Prisma Postgres 服务令牌

要管理 Prisma Postgres 数据库,您还需要一个服务令牌。请按照以下步骤检索它

  1. 确保您位于上一步中创建项目的同一工作区。
  2. 导航到您工作区的 Settings 页面并选择 Service Tokens
  3. 点击 New Service Token
  4. 复制生成的令牌并将其保存到您的 .env 文件中,作为 PRISMA_POSTGRES_SERVICE_TOKEN。此令牌是下一步脚本所需的,并且必须添加到您的 GitHub Actions 密钥中。

5.2 检索您要预配 Prisma Postgres 数据库的项目 ID

为避免与您的开发数据库冲突,您现在将专门为 CI 工作流创建一个专用项目。使用以下 curl 命令通过 Prisma Postgres Management API 创建一个新的 Prisma Postgres 项目

curl -X POST https://api.prisma.io/v1/projects \
-H "Authorization: Bearer $PRISMA_POSTGRES_SERVICE_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"region\": \"us-east-1\", \"name\": \"$PROJECT_NAME\"}"
注意

确保将 $PRISMA_POSTGRES_SERVICE_TOKEN 变量替换为之前存储的服务令牌。

将 $PRISMA_POSTGRES_SERVICE_TOKEN 替换为服务令牌,将 $PROJECT_NAME 替换为您的项目名称(例如,my-gha-preview)。脚本将在 us-east-1 区域创建一个新的 Prisma Postgres 项目。

CLI 输出将如下所示

{
"data": {
"id": "$PRISMA_PROJECT_ID",
"type": "project",
"name": "$PROJECT_NAME",
"createdAt": "2025-07-15T08:35:10.546Z",
"workspace": {
"id": "$PRISMA_WORKSPACE_ID",
"name": "$PRISMA_WORKSPACE_NAME"
}
}
}

复制并存储输出中的 $PRISMA_PROJECT_ID。这是您的 Prisma 项目 ID,您将在下一步中使用它。

6. 在 GitHub 中添加密钥

要添加密钥

  1. 转到您的 GitHub 存储库。
  2. 导航到 Settings
  3. 点击并展开 Secrets and variables 部分。
  4. 点击 Actions
  5. 点击 New repository secret
  6. 添加以下内容
    • PRISMA_PROJECT_ID - 您在 Prisma 控制台中的 Prisma 项目 ID。
    • PRISMA_POSTGRES_SERVICE_TOKEN - 您的服务令牌。

这些密钥将通过 env 在工作流文件中访问。

7. 尝试工作流

您可以通过两种方式测试设置

选项 1:通过 PR 自动触发

  1. 在存储库上打开一个拉取请求。
  2. GitHub Actions 将预配一个新的 Prisma Postgres 数据库。
  3. 它将推送您的架构并填充数据库。
  4. 将向 PR 添加一条评论,确认数据库已创建。
  5. 当 PR 关闭时,数据库将自动删除。

选项 2:手动触发

  1. 转到存储库中的 Actions 选项卡。
  2. 在左侧边栏选择 Prisma Postgres Management API Workflow
  3. 点击 Run workflow 下拉菜单
  4. 选择 provision 作为操作,并可选择提供自定义数据库名称。您也可以选择 cleanup 来删除一个*现有*数据库。
  5. 点击 Run workflow

后续步骤

您现在拥有一个完全自动化的 GitHub Actions 设置,用于管理临时 Prisma Postgres 数据库。

这将为您提供

  • 每个拉取请求的独立数据库。
  • 自动架构同步和填充。
  • 合并后清理未使用的数据库。

此设置提高了对更改的信心,并降低了共享数据库冲突的风险。您可以通过集成测试套件或将其集成到工作流中来扩展此功能。


与 Prisma 保持联系

通过以下方式与我们保持联系,继续你的 Prisma 之旅: 我们的活跃社区。保持信息灵通,参与其中,并与其他开发人员协作。

我们真诚地感谢你的参与,并期待你成为我们社区的一部分!

© . This site is unofficial and not affiliated with Prisma Data, Inc.