示例成品 · 平台演示,按左边这组点选真跑出来的
直接放两个文件到 `.github/workflows/` 下,改掉里面的 OSS/CDN 变量就能用。
## 1. `.github/workflows/deploy.yml`
```yaml
name: CI/CD Deploy
on:
push:
branches: [main]
workflow_dispatch:
concurrency:
group: production-deploy
cancel-in-progress: false
jobs:
lint-test:
name: Lint & Test
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run lint
- run: npm test
build-deploy:
name: Build & Deploy
needs: lint-test
# 只有 main 分支 push 或手动触发时才构建部署
if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
timeout-minutes: 20
environment:
name: production
url: https://${{ vars.CDN_DOMAIN }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run build
- name: Setup ossutil
uses: manyuanrong/setup-ossutil@v3
with:
endpoint: ${{ vars.OSS_ENDPOINT }}
access-key-id: ${{ secrets.OSS_ACCESS_KEY_ID }}
access-key-secret: ${{ secrets.OSS_ACCESS_KEY_SECRET }}
# 每次发布都留一个快照,回滚时用
- name: Save release snapshot
run: |
ossutil sync -rf dist/ oss://${{ vars.OSS_RELEASE_BUCKET }}/releases/${{ github.run_id }}/ --delete
# 部署到生产 OSS 根目录
# 这里用 --delete 是为了清掉旧文件,所以生产 bucket 里不要放 releases 备份
- name: Deploy to OSS
run: |
ossutil sync -rf dist/ oss://${{ vars.OSS_BUCKET }}/ --delete
- name: Write release record
run: |
echo "${{ github.run_id }} ${{ github.sha }} $(date -u +%Y-%m-%dT%H:%M:%SZ)" > /tmp/current.txt
ossutil cp /tmp/current.txt oss://${{ vars.OSS_RELEASE_BUCKET }}/release-info/current.txt --force
# 如果不用阿里云 CDN,把下面两步删掉或替换成你们 CDN 的刷新命令
- name: Setup Aliyun CLI
if: vars.CDN_DOMAIN != ''
uses: aliyun/aliyun-cli-action@v1
with:
access-key-id: ${{ secrets.OSS_ACCESS_KEY_ID }}
access-key-secret: ${{ secrets.OSS_ACCESS_KEY_SECRET }}
region-id: ${{ vars.OSS_REGION }}
- name: Refresh CDN
if: vars.CDN_DOMAIN != ''
run: |
aliyun cdn RefreshObjectCaches --ObjectPath https://${{ vars.CDN_DOMAIN }}/
```
## 2. `.github/workflows/rollback.yml`
```yaml
name: Rollback
on:
workflow_dispatch:
inputs:
run_id:
description: '要回滚到的 Deploy run id(不是 run number)'
required: true
concurrency:
group: production-deploy
cancel-in-progress: false
jobs:
rollback:
runs-on: ubuntu-latest
timeout-minutes: 15
environment: production
steps:
- name: Setup ossutil
uses: manyuanrong/setup-ossutil@v3
with:
endpoint: ${{ vars.OSS_ENDPOINT }}
access-key-id: ${{ secrets.OSS_ACCESS_KEY_ID }}
access-key-secret: ${{ secrets.OSS_ACCESS_KEY_SECRET }}
- name: Download old release from OSS
run: |
mkdir -p dist-rollback
ossutil cp -rf oss://${{ vars.OSS_RELEASE_BUCKET }}/releases/${{ github.event.inputs.run_id }}/ ./dist-rollback/
- name: Rollback OSS root
run: |
ossutil sync -rf ./dist-rollback/ oss://${{ vars.OSS_BUCKET }}/ --delete
- name: Write rollback record
点左边「开工 · 直接出成品」,出一份你自己的版本(文字免费)