CI/CD 集成 #
CI/CD 概述 #
Vercel 内置了 CI/CD 功能,也支持与外部 CI/CD 工具集成:
text
┌─────────────────────────────────────────┐
│ Vercel CI/CD 选项 │
├─────────────────────────────────────────┤
│ 内置 CI/CD → 自动构建部署 │
│ GitHub Actions → 自定义工作流 │
│ GitLab CI → GitLab 集成 │
│ 其他工具 → 通过 API 集成 │
└─────────────────────────────────────────┘
Vercel 内置 CI/CD #
自动部署流程 #
text
Git Push → Vercel 检测 → 触发构建 → 自动部署
text
┌──────────────────────────────────────────────────────┐
│ │
│ main 分支 push │
│ │ │
│ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 触发构建 │ ──▶│ 执行构建 │ ──▶│ 生产部署 │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ PR 创建/更新 │
│ │ │
│ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 触发构建 │ ──▶│ 执行构建 │ ──▶│ 预览部署 │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
└──────────────────────────────────────────────────────┘
配置 Git 集成 #
text
Project Settings → Git
├── Production Branch # 生产分支
├── Ignored Build Step # 忽略构建条件
├── Auto Job Cancelation # 自动取消旧构建
└── Skipped Build Steps # 跳过构建条件
生产分支配置 #
text
┌─────────────────────────────────────────┐
│ Production Branch │
├─────────────────────────────────────────┤
│ Branch: [main ▼] │
│ │
│ 当此分支有新提交时,自动部署到生产环境 │
└─────────────────────────────────────────┘
忽略构建 #
忽略特定文件变更:
json
{
"git": {
"deploymentEnabled": {
"exclude": [
"README.md",
"docs/**",
".vscode/**",
"LICENSE"
]
}
}
}
自定义忽略命令:
text
Project Settings → Git → Ignored Build Step
bash
git diff --quiet HEAD^ HEAD ./src/
GitHub Actions 集成 #
创建 Vercel Token #
- 访问 vercel.com/account/tokens
- 点击 “Create Token”
- 设置名称和过期时间
- 复制 Token
配置 GitHub Secrets #
text
Repository → Settings → Secrets and variables → Actions
添加以下 Secrets:
| Secret | 说明 |
|---|---|
VERCEL_TOKEN |
Vercel API Token |
VERCEL_ORG_ID |
团队 ID |
VERCEL_PROJECT_ID |
项目 ID |
获取 ID:
bash
vercel link
查看 .vercel/project.json:
json
{
"orgId": "team_xxx",
"projectId": "prj_xxx"
}
基础工作流 #
yaml
name: Vercel Deployment
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Vercel CLI
run: npm install --global vercel@latest
- name: Pull Vercel Environment Information
run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
- name: Build Project Artifacts
run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
- name: Deploy Project Artifacts to Vercel
run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}
预览部署工作流 #
yaml
name: Preview Deployment
on:
pull_request:
branches: [main]
jobs:
preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Vercel CLI
run: npm install --global vercel@latest
- name: Pull Vercel Environment Information
run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}
- name: Build Project Artifacts
run: vercel build --token=${{ secrets.VERCEL_TOKEN }}
- name: Deploy Project Artifacts to Vercel
run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} > deployment-url.txt
- name: Comment PR with Deployment URL
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const url = fs.readFileSync('deployment-url.txt', 'utf8').trim();
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `🚀 Preview deployed to: ${url}`
});
完整工作流示例 #
yaml
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
test:
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run test
deploy-preview:
runs-on: ubuntu-latest
needs: test
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
- run: npm install --global vercel@latest
- run: vercel pull --yes --environment=preview --token=$VERCEL_TOKEN
- run: vercel build --token=$VERCEL_TOKEN
- run: vercel deploy --prebuilt --token=$VERCEL_TOKEN
deploy-production:
runs-on: ubuntu-latest
needs: test
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- run: npm install --global vercel@latest
- run: vercel pull --yes --environment=production --token=$VERCEL_TOKEN
- run: vercel build --prod --token=$VERCEL_TOKEN
- run: vercel deploy --prebuilt --prod --token=$VERCEL_TOKEN
使用官方 Action #
yaml
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'
GitLab CI 集成 #
配置 GitLab Variables #
text
Settings → CI/CD → Variables
| Variable | 说明 |
|---|---|
VERCEL_TOKEN |
Vercel API Token |
VERCEL_ORG_ID |
团队 ID |
VERCEL_PROJECT_ID |
项目 ID |
.gitlab-ci.yml #
yaml
stages:
- test
- deploy
variables:
NODE_VERSION: '20'
.test_template:
image: node:${NODE_VERSION}
before_script:
- npm ci
cache:
paths:
- node_modules/
lint:
extends: .test_template
stage: test
script:
- npm run lint
test:
extends: .test_template
stage: test
script:
- npm run test
deploy_preview:
stage: deploy
image: node:${NODE_VERSION}
rules:
- if: $CI_MERGE_REQUEST_IID
script:
- npm install --global vercel@latest
- vercel pull --yes --environment=preview --token=$VERCEL_TOKEN
- vercel build --token=$VERCEL_TOKEN
- vercel deploy --prebuilt --token=$VERCEL_TOKEN
deploy_production:
stage: deploy
image: node:${NODE_VERSION}
rules:
- if: $CI_COMMIT_BRANCH == 'main'
script:
- npm install --global vercel@latest
- vercel pull --yes --environment=production --token=$VERCEL_TOKEN
- vercel build --prod --token=$VERCEL_TOKEN
- vercel deploy --prebuilt --prod --token=$VERCEL_TOKEN
Vercel API 集成 #
创建部署 #
bash
curl -X POST "https://api.vercel.com/v13/deployments" \
-H "Authorization: Bearer $VERCEL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my-project",
"gitSource": {
"type": "github",
"repo": "username/repo",
"ref": "main"
}
}'
获取部署状态 #
bash
curl "https://api.vercel.com/v13/deployments/$DEPLOYMENT_ID" \
-H "Authorization: Bearer $VERCEL_TOKEN"
列出部署 #
bash
curl "https://api.vercel.com/v6/deployments?projectId=$PROJECT_ID" \
-H "Authorization: Bearer $VERCEL_TOKEN"
部署钩子 #
创建部署钩子 #
text
Project Settings → Git → Deploy Hooks
text
┌─────────────────────────────────────────┐
│ Create Deploy Hook │
├─────────────────────────────────────────┤
│ Name: [Deploy from CMS ] │
│ Branch: [main ▼] │
│ │
│ Hook URL: │
│ https://api.vercel.com/deploy... │
│ │
│ [Create Hook] │
└─────────────────────────────────────────┘
触发部署 #
bash
curl -X POST "https://api.vercel.com/integrations/deploy/$HOOK_ID"
使用场景 #
text
┌─────────────────────────────────────────┐
│ 部署钩子使用场景 │
├─────────────────────────────────────────┤
│ CMS 更新 → 内容更新后自动部署 │
│ 定时任务 → 定期重新部署 │
│ 外部系统 → 第三方触发部署 │
│ Webhook → 事件触发部署 │
└─────────────────────────────────────────┘
构建缓存 #
启用构建缓存 #
yaml
- name: Cache node modules
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
Vercel 缓存 #
Vercel 自动缓存以下内容:
node_modules.next/cache- 构建输出
部署通知 #
Slack 通知 #
yaml
- name: Notify Slack
if: always()
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
fields: repo,message,commit,author
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
部署状态徽章 #
markdown
[](https://vercel.com)
最佳实践 #
分支策略 #
text
┌─────────────────────────────────────────┐
│ 推荐分支策略 │
├─────────────────────────────────────────┤
│ main → 生产环境 │
│ develop → 预览环境 │
│ feature/* → PR 预览 │
│ hotfix/* → 紧急修复 │
└─────────────────────────────────────────┘
环境隔离 #
yaml
deploy-staging:
environment: staging
steps:
- run: vercel deploy --env STAGE=staging
deploy-production:
environment: production
steps:
- run: vercel deploy --prod
回滚机制 #
yaml
rollback:
runs-on: ubuntu-latest
steps:
- name: Rollback to previous deployment
run: |
vercel rollback ${{ inputs.deployment-url }} --token=$VERCEL_TOKEN
下一步 #
掌握 CI/CD 集成后,接下来学习 域名绑定 配置自定义域名!
最后更新:2026-03-28