Skip to content

CI/CD 自动化部署

持续集成和持续部署(CI/CD)可以帮助你自动化构建和部署流程,提高开发效率。本文将介绍几种常用的 CI/CD 配置方案。

GitHub Actions

基础配置

创建 .github/workflows/deploy.yml

yaml
name: Deploy VitePress site to Pages

on:
  push:
    branches: [main]
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: pages
  cancel-in-progress: false

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
      
      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      
      - name: Setup Pages
        uses: actions/configure-pages@v4
      
      - name: Install dependencies
        run: npm ci
      
      - name: Build with VitePress
        run: npm run docs:build
      
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: docs/.vitepress/dist

  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

带 PR 预览的配置

yaml
name: Deploy VitePress site

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      
      - name: Install
        run: npm ci
      
      - name: Build
        run: npm run docs:build
      
      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: dist
          path: docs/.vitepress/dist

  deploy-production:
    if: github.event_name == 'push'
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Download artifact
        uses: actions/download-artifact@v4
        with:
          name: dist
      
      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: .

  preview-pr:
    if: github.event_name == 'pull_request'
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Download artifact
        uses: actions/download-artifact@v4
        with:
          name: dist
      
      - name: Deploy Preview
        uses: rossjrw/pr-preview-action@v1
        with:
          source-dir: .

Vercel 部署

自动部署

Vercel 原生支持 VitePress:

  1. 导入 GitHub 仓库
  2. Vercel 自动检测 VitePress
  3. 配置构建命令和输出目录
配置项
Build Commandnpm run docs:build
Output Directorydocs/.vitepress/dist
Install Commandnpm install

vercel.json 配置

json
{
  "buildCommand": "npm run docs:build",
  "outputDirectory": "docs/.vitepress/dist",
  "framework": "vitepress",
  "rewrites": [
    { "source": "/api/(.*)", "destination": "/api/$1" }
  ],
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        { "key": "X-Content-Type-Options", "value": "nosniff" },
        { "key": "X-Frame-Options", "value": "DENY" }
      ]
    }
  ]
}

Netlify 部署

netlify.toml 配置

toml
[build]
  command = "npm run docs:build"
  publish = "docs/.vitepress/dist"

[build.environment]
  NODE_VERSION = "20"

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

[[headers]]
  for = "/*"
  [headers.values]
    X-Frame-Options = "DENY"
    X-XSS-Protection = "1; mode=block"
    X-Content-Type-Options = "nosniff"

Netlify Functions 示例

javascript
// netlify/functions/api.js
export async function handler(event, context) {
  return {
    statusCode: 200,
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      message: 'Hello from Netlify Functions!'
    })
  }
}

Cloudflare Pages 部署

构建配置

配置项
Build commandnpm run docs:build
Build output directorydocs/.vitepress/dist
Node version20 (环境变量设置)

wrangler.toml 配置

toml
name = "vitepress-site"
compatibility_date = "2024-01-01"
pages_build_output_dir = "docs/.vitepress/dist"

[vars]
NODE_VERSION = "20"

自建服务器部署

Docker 部署

创建 Dockerfile

dockerfile
FROM node:20-alpine AS builder

WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run docs:build

FROM nginx:alpine

COPY --from=builder /app/docs/.vitepress/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

nginx.conf 配置

nginx
events {
  worker_connections 1024;
}

http {
  include       /etc/nginx/mime.types;
  default_type  application/octet-stream;
  
  server {
    listen 80;
    server_name localhost;
    root /usr/share/nginx/html;
    index index.html;
    
    # SPA 路由支持
    location / {
      try_files $uri $uri/ /index.html;
    }
    
    # 静态资源缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
      expires 1y;
      add_header Cache-Control "public, immutable";
    }
    
    # Gzip 压缩
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
    gzip_min_length 1000;
  }
}

Docker Compose 部署

yaml
version: '3.8'

services:
  vitepress:
    build: .
    ports:
      - "80:80"
    restart: unless-stopped

缓存优化

GitHub Actions 缓存

yaml
- name: Cache dependencies
  uses: actions/cache@v4
  with:
    path: |
      ~/.npm
      node_modules
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-

构建产物缓存

yaml
- name: Cache VitePress
  uses: actions/cache@v4
  with:
    path: |
      docs/.vitepress/cache
      docs/.vitepress/dist
    key: vitepress-${{ github.sha }}
    restore-keys: |
      vitepress-

部署通知

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 }}

邮件通知

yaml
- name: Send email
  if: failure()
  uses: dawidd6/action-send-mail@v3
  with:
    server_address: smtp.gmail.com
    server_port: 465
    username: ${{ secrets.EMAIL_USERNAME }}
    password: ${{ secrets.EMAIL_PASSWORD }}
    subject: Build Failed
    to: your-email@example.com
    from: CI/CD Bot
    body: |
      Build failed for ${{ github.repository }}
      Commit: ${{ github.sha }}
      Author: ${{ github.actor }}

部署检查清单

构建前检查

  • [ ] 代码已通过测试
  • [ ] 代码已通过 Lint 检查
  • [ ] 依赖版本已锁定
  • [ ] 环境变量已配置

构建后检查

  • [ ] 构建产物正确
  • [ ] 页面可正常访问
  • [ ] 静态资源加载正常
  • [ ] 路由跳转正常

部署后检查

  • [ ] 网站可访问
  • [ ] HTTPS 证书有效
  • [ ] CDN 缓存已刷新
  • [ ] 监控告警正常

最佳实践

1. 分环境部署

main 分支 -> 生产环境
develop 分支 -> 测试环境
PR -> 预览环境

2. 回滚机制

yaml
- name: Rollback on failure
  if: failure()
  run: |
    # 回滚到上一个稳定版本
    echo "Rolling back..."

3. 自动化测试

yaml
- name: Run tests
  run: npm test

- name: Run e2e tests
  run: npm run test:e2e

自动化优势

使用 CI/CD 可以减少人为错误,确保每次部署的一致性和可靠性。

贡献者

加载中...

想要成为贡献者?

在 CNB 上参与贡献