如何使用 GitHub Actions 和 Prisma Postgres 佈建預覽資料庫
總覽
本指南將展示如何使用 GitHub Actions 和 Prisma Postgres 管理 API 自動建立與刪除 Prisma Postgres 資料庫。此設定會為每個合併請求(pull request)佈建一個新的資料庫,並使用範例資料進行填充(seeding),同時 github-actions 機器人會留下包含資料庫名稱與狀態的評論。

當 PR 關閉後,資料庫會自動刪除。這讓您能夠在隔離環境中測試變更,而不會影響主要開發資料庫。
先決條件
請確保您具備以下項目
- Node.js 20 或更高版本
- A帳戶
- GitHub 儲存庫
1. 設定您的專案
初始化您的專案
mkdir prisma-gha-demo && cd prisma-gha-demo
npm init -y
2. 安裝並設定 Prisma
在本節中,您將在專案中設定 Prisma,並在整合至 GitHub Actions 之前驗證其在本機運作正常。這包括安裝 Prisma 的依賴項、連接至 Prisma Postgres 資料庫、定義資料模型、套用 schema 以及使用範例資料填充資料庫。
在本節結束時,您的專案將完全準備好在本機以及 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.prisma的prisma/目錄 - 包含
DATABASE_URL的.env檔案 - 在
src/generated/prisma中產生的 client
2.2. 定義您的 Prisma schema
編輯 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
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. 執行初始遷移並產生 client
npx prisma migrate dev --name init
接著生成 Prisma Client
npx prisma generate
這會推送您的 schema 並準備好 client。
2.4. 填充(Seed)資料庫
在 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
{
{
"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。這會設定工作流程何時執行並提供必要的環境變數。
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
現在您將在此工作流程中加入佈建與清理任務(jobs)。這些任務將根據合併請求事件處理 Prisma Postgres 資料庫的建立與刪除。
3.3. 在工作流程中加入佈建任務
現在加入一個任務,在 PR 開啟或手動觸發時佈建資料庫。佈建任務會
- 安裝依賴項
- 檢查現有的資料庫
- 如有需要則建立一個新的
- 填充資料庫
- 在 PR 上評論狀態
將以下內容附加到您工作流程檔案中的 jobs: 鍵下方
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 任務之後
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 secrets 以對 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. 取得工作流程所需的 secrets
5.1. 取得您的 Prisma Postgres 服務權杖 (Service Token)
為了管理 Prisma Postgres 資料庫,您需要一個服務權杖。請遵循以下步驟來取得它
- 確保您位於上一個步驟建立專案所在的同一個工作區 (workspace) 中。
- 導航至工作區的 Settings 頁面並選取 Service Tokens。
- 點選 New Service Token。
- 複製產生的權杖並將其儲存於
.env檔案中作為PRISMA_POSTGRES_SERVICE_TOKEN。此權杖在下一個步驟的腳本中為必須,且也必須加入至您的 GitHub Actions secrets 中。
5.2 取得您要佈建 Prisma Postgres 資料庫的專案 ID
為了避免與開發資料庫產生衝突,您現在將為 CI 工作流程建立一個專用的專案。使用以下 curl 指令,透過 Prisma Postgres 管理 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 中加入 secrets
若要加入 secrets
- 前往您的 GitHub 儲存庫。
- 導航至 Settings。
- 點選並展開 Secrets and variables 區段。
- 點選 Actions。
- 點選 New repository secret。
- 加入以下項目
PRISMA_PROJECT_ID- 來自 Prisma Console 的 Prisma 專案 ID。PRISMA_POSTGRES_SERVICE_TOKEN- 您的服務權杖。
這些 secrets 將透過 env 在工作流程檔案中被存取。
7. 試用工作流程
您可以透過兩種方式測試此設定
選項 1:透過 PR 自動觸發
- 在儲存庫中開啟合併請求。
- GitHub Actions 將佈建一個新的 Prisma Postgres 資料庫。
- 它會推送您的 schema 並填充資料庫。
- PR 上將會新增一則確認資料庫已建立的評論。
- 當 PR 關閉時,資料庫將自動刪除。
選項 2:手動觸發
- 前往儲存庫中的 Actions 標籤。
- 在左側側邊欄選擇 Prisma Postgres Management API Workflow。
- 點選 Run workflow 下拉選單
- 選擇
provision作為動作,並可選擇性提供自訂資料庫名稱。您也可以選擇cleanup來刪除「現有的」資料庫。 - 點選 Run workflow。
後續步驟
您現在擁有了一個用於管理臨時 Prisma Postgres 資料庫的完全自動化 GitHub Actions 設定。
這讓您擁有
- 每個合併請求都有隔離的資料庫。
- 自動化的 schema 同步與填充。
- 合併後清理未使用的資料庫。
此設定能提升對變更的信心並降低共享資料庫衝突的風險。您可以透過整合測試套件,或將其整合至您的工作流程中來擴展此功能。
與 Prisma 保持聯繫
透過以下方式與我們聯繫,繼續您的 Prisma 旅程: 我們的活躍社群。保持資訊靈通、參與其中,並與其他開發者合作
- 在 X 上關注我們 以獲取公告、現場活動和實用技巧。
- 加入我們的 Discord 提出問題、與社群對話,並透過對話獲得積極支援。
- 在 YouTube 上訂閱 查看教學、演示和直播。
- 在 GitHub 上交流 透過為存放庫加星標、報告問題或為 issue 做出貢獻。