GitHub Actions CD自动部署 #
本节通过一个完整的CD示例,展示如何实现自动化部署流程。
部署概述 #
CD流程 #
text
代码合并 → 构建 → 测试 → 部署到Staging → 验证 → 部署到Production
部署环境 #
| 环境 | 描述 |
|---|---|
| Development | 开发环境 |
| Staging | 预发布环境 |
| Production | 生产环境 |
基础部署工作流 #
yaml
name: Deploy
on:
push:
branches: [main]
workflow_dispatch:
inputs:
environment:
description: 'Environment'
required: true
type: choice
options:
- staging
- production
default: 'staging'
jobs:
build:
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 build
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
deploy:
needs: build
runs-on: ubuntu-latest
environment: ${{ github.event.inputs.environment || 'staging' }}
steps:
- uses: actions/download-artifact@v4
with:
name: dist
path: ./dist
- name: Deploy
run: |
echo "Deploying to ${{ github.event.inputs.environment || 'staging' }}"
./deploy.sh ${{ github.event.inputs.environment || 'staging' }}
GitHub Pages部署 #
yaml
name: Deploy to GitHub Pages
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: true
jobs:
build:
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 build
- uses: actions/upload-pages-artifact@v3
with:
path: dist
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/deploy-pages@v4
id: deployment
Docker部署 #
yaml
name: Docker Deploy
on:
push:
tags: ['v*']
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
outputs:
image: ${{ steps.build.outputs.image }}
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
id: build
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy-staging:
needs: build
runs-on: ubuntu-latest
environment: staging
steps:
- name: Deploy to staging
run: |
echo "Deploying ${{ needs.build.outputs.image }} to staging"
deploy-production:
needs: build
runs-on: ubuntu-latest
environment: production
steps:
- name: Deploy to production
run: |
echo "Deploying ${{ needs.build.outputs.image }} to production"
完整CD工作流 #
多环境部署 #
yaml
name: Deploy
on:
push:
branches:
- main
- develop
tags:
- 'v*'
workflow_dispatch:
inputs:
environment:
description: 'Environment'
required: true
type: choice
options:
- staging
- production
default: 'staging'
version:
description: 'Version'
required: false
type: string
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
prepare:
runs-on: ubuntu-latest
outputs:
environment: ${{ steps.env.outputs.environment }}
version: ${{ steps.env.outputs.version }}
should-deploy: ${{ steps.env.outputs.should-deploy }}
steps:
- id: env
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
echo "environment=${{ github.event.inputs.environment }}" >> $GITHUB_OUTPUT
echo "version=${{ github.event.inputs.version || github.sha }}" >> $GITHUB_OUTPUT
echo "should-deploy=true" >> $GITHUB_OUTPUT
elif [ "${{ github.ref_type }}" == "tag" ]; then
echo "environment=production" >> $GITHUB_OUTPUT
echo "version=${{ github.ref_name }}" >> $GITHUB_OUTPUT
echo "should-deploy=true" >> $GITHUB_OUTPUT
elif [ "${{ github.ref }}" == "refs/heads/main" ]; then
echo "environment=staging" >> $GITHUB_OUTPUT
echo "version=${{ github.sha }}" >> $GITHUB_OUTPUT
echo "should-deploy=true" >> $GITHUB_OUTPUT
elif [ "${{ github.ref }}" == "refs/heads/develop" ]; then
echo "environment=development" >> $GITHUB_OUTPUT
echo "version=${{ github.sha }}" >> $GITHUB_OUTPUT
echo "should-deploy=true" >> $GITHUB_OUTPUT
else
echo "should-deploy=false" >> $GITHUB_OUTPUT
fi
build:
needs: prepare
if: needs.prepare.outputs.should-deploy == 'true'
runs-on: ubuntu-latest
outputs:
image: ${{ steps.build.outputs.image }}
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
id: build
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.prepare.outputs.version }}
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
needs: [prepare, build]
runs-on: ubuntu-latest
environment: ${{ needs.prepare.outputs.environment }}
steps:
- uses: actions/checkout@v4
- name: Deploy
run: |
echo "Deploying version ${{ needs.prepare.outputs.version }}"
echo "Environment: ${{ needs.prepare.outputs.environment }}"
echo "Image: ${{ needs.build.outputs.image }}"
# 部署脚本
./deploy.sh ${{ needs.prepare.outputs.environment }} ${{ needs.prepare.outputs.version }}
- name: Verify deployment
run: |
echo "Verifying deployment..."
# 验证脚本
./verify.sh ${{ needs.prepare.outputs.environment }}
notify:
needs: [prepare, build, deploy]
if: always()
runs-on: ubuntu-latest
steps:
- name: Notify on success
if: success()
uses: slackapi/slack-github-action@v1
with:
channel-id: 'C0123456789'
slack-message: |
:rocket: Deployment Successful
Environment: ${{ needs.prepare.outputs.environment }}
Version: ${{ needs.prepare.outputs.version }}
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
- name: Notify on failure
if: failure()
uses: slackapi/slack-github-action@v1
with:
channel-id: 'C0123456789'
slack-message: |
:x: Deployment Failed
Environment: ${{ needs.prepare.outputs.environment }}
Version: ${{ needs.prepare.outputs.version }}
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
回滚工作流 #
yaml
name: Rollback
on:
workflow_dispatch:
inputs:
environment:
description: 'Environment'
required: true
type: choice
options:
- staging
- production
version:
description: 'Version to rollback to'
required: true
type: string
reason:
description: 'Rollback reason'
required: true
type: string
jobs:
rollback:
runs-on: ubuntu-latest
environment: ${{ github.event.inputs.environment }}
steps:
- uses: actions/checkout@v4
- name: Rollback
run: |
echo "Rolling back to version ${{ github.event.inputs.version }}"
echo "Environment: ${{ github.event.inputs.environment }}"
echo "Reason: ${{ github.event.inputs.reason }}"
./rollback.sh ${{ github.event.inputs.environment }} ${{ github.event.inputs.version }}
- name: Create issue
uses: peter-evans/create-issue-from-file@v4
with:
title: "Rollback: ${{ github.event.inputs.environment }} to ${{ github.event.inputs.version }}"
content: |
## Rollback Details
- **Environment**: ${{ github.event.inputs.environment }}
- **Version**: ${{ github.event.inputs.version }}
- **Reason**: ${{ github.event.inputs.reason }}
- **Triggered by**: ${{ github.actor }}
labels: rollback
最佳实践 #
1. 使用环境保护 #
yaml
environment: production
2. 使用版本标签 #
yaml
tags: |
user/app:latest
user/app:${{ github.sha }}
3. 添加部署验证 #
yaml
- name: Verify deployment
run: ./verify.sh
4. 设置通知 #
yaml
- name: Notify
if: always()
uses: slackapi/slack-github-action@v1
5. 准备回滚方案 #
创建专门的回滚工作流。
下一步学习 #
- 完整DevOps流程 - 查看完整流程
- CI流水线构建 - 学习CI配置
- 安全最佳实践 - 了解安全配置
小结 #
- CD实现自动化部署
- 使用环境保护生产环境
- 支持多环境部署
- 使用版本标签管理镜像
- 添加部署验证
- 设置通知告警
- 准备回滚方案
最后更新:2026-03-28