跳转到内容

GitHub Actions 完全指南 | CI/CD 自动化工作流配置教程

GitHub Actions Workflow

GitHub Actions 是 GitHub 提供的持续集成和持续部署(CI/CD)服务,让你能够在代码仓库中直接自动化执行各种任务。从构建、测试到部署,GitHub Actions 都能帮你轻松实现。本文将详细介绍多个实用的工作流配置示例,帮助你快速上手并提升开发效率。

什么是 GitHub Actions?

核心概念

术语说明示例
Workflow自动化流程配置文件.github/workflows/build.yml
Event触发事件push, pull_request, schedule
Job工作任务构建、测试、部署
Step工作步骤checkout、install、build
Action可复用的操作单元actions/checkout@v4
Runner执行环境ubuntu-latest, windows-latest
Secrets加密环境变量API 密钥、密码

为什么选择 GitHub Actions?

原生集成:与 GitHub 无缝整合,无需额外配置 ✅ 免费额度:公共仓库无限使用,私有仓库每月 2000 分钟 ✅ 丰富生态:Marketplace 提供数千个现成 Actions ✅ 灵活配置:支持 Linux、Windows、macOS 多种环境 ✅ 社区活跃:大量开源项目和文档支持

自动化部署到腾讯云 COS

将静态网站或构建产物自动上传到腾讯云对象存储(COS),实现快速分发和 CDN 加速。

获取 API 密钥

腾讯云控制台 - 访问管理 - 创建 API 密钥或者子用户

  • 子用户权限策略 - QcloudCOSDataFullControl
  • 获取 SecretIdSecretKey

详细步骤

步骤 1:创建子用户

  1. 登录 腾讯云控制台
  2. 进入【访问管理】→【用户】→【用户列表】
  3. 点击【新建用户】
  4. 选择【快速创建】
  5. 填写用户名,勾选【编程访问】
  6. 点击【下一步】

步骤 2:分配权限

  1. 在权限配置页面,点击【关联策略】
  2. 搜索 QcloudCOSDataFullControl
  3. 勾选该策略
  4. 点击【下一步】→【完成】

步骤 3:获取密钥

  1. 进入【访问密钥】→【API 密钥管理】
  2. 点击【新建密钥】
  3. 复制 SecretIdSecretKey
  4. ⚠️ 立即保存,密钥只显示一次!

安全建议:

🔒 使用子用户而非主账号
🔒 遵循最小权限原则
🔒 定期轮换密钥
🔒 不要将密钥硬编码在代码中

获取 COS 桶信息

腾讯云控制台 - 对象存储 - 存储桶 - 基本配置

  • 空间名(Bucket) - xxx-xxxxxx
  • 所属地域(Region) - ap-shanghai

常见地域代码

地域代码说明
北京ap-beijing华北地区
上海ap-shanghai华东地区
广州ap-guangzhou华南地区
成都ap-chengdu西南地区
香港ap-hongkong港澳台地区
新加坡ap-singapore东南亚
东京ap-tokyo日本
硅谷na-siliconvalley美国西部

配置 Secrets

GitHub 仓库 - Settings - Secrets

添加上文创建的 SecretId SecretKey Bucket Region

配置步骤

  1. 进入 GitHub 仓库
  2. 点击【Settings】标签
  3. 左侧菜单找到【Secrets and variables】→【Actions】
  4. 点击【New repository secret】
  5. 依次添加以下 Secrets:
Name: SecretId
Value: <你的 SecretId>

Name: SecretKey
Value: <你的 SecretKey>

Name: Bucket
Value: <你的存储桶名称>

Name: Region
Value: <你的地域代码>

验证配置:

bash
# 在 workflow 中使用
${{ secrets.SecretId }}
${{ secrets.SecretKey }}
${{ secrets.Bucket }}
${{ secrets.Region }}

创建workflow

GitHub 仓库 - Actions - Set up a workflow yourself

  • 创建 sync.yml
  • 提交sync.yml后,检测到 push 后将会自动 Upload 到腾讯云 COS
yaml
name: sync to cos

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v1
      - name: Install coscmd
        run: sudo pip install coscmd
      - name: Configure coscmd
        env:
          SECRET_ID: ${{ secrets.SecretId }}
          SECRET_KEY: ${{ secrets.SecretKey }}
          BUCKET: ${{ secrets.Bucket }}
          REGION: ${{ secrets.Region }}
        run: coscmd config -a $SECRET_ID -s $SECRET_KEY -b $BUCKET -r $REGION
      - name: Upload
        run: coscmd upload -rfs --delete ./ / --ignore "./.git/*"

配置详解

触发条件:

yaml
on: [push]
# 每次 push 到任何分支都会触发

# 更精确的控制:
on:
  push:
    branches:
      - main      # 仅 main 分支
      - master    # 或 master 分支
  pull_request:
    branches:
      - main      # PR 时也触发

工作步骤说明:

  1. Checkout 代码

    yaml
    - uses: actions/checkout@v1
    # 克隆仓库代码到 runner
  2. 安装 coscmd

    yaml
    - name: Install coscmd
      run: sudo pip install coscmd
    # 安装腾讯云 COS 命令行工具
  3. 配置认证信息

    yaml
    - name: Configure coscmd
      env:
        SECRET_ID: ${{ secrets.SecretId }}
        SECRET_KEY: ${{ secrets.SecretKey }}
        BUCKET: ${{ secrets.Bucket }}
        REGION: ${{ secrets.Region }}
      run: coscmd config -a $SECRET_ID -s $SECRET_KEY -b $BUCKET -r $REGION
    # 使用 Secrets 配置 coscmd
  4. 上传文件

    yaml
    - name: Upload
      run: coscmd upload -rfs --delete ./ / --ignore "./.git/*"
    # -r: 递归上传
    # -f: 强制覆盖
    # -s: 显示进度
    # --delete: 删除 COS 上本地已删除的文件
    # --ignore: 忽略 .git 目录

优化版本

yaml
name: Deploy to Tencent COS

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'pnpm'
      
      - name: Install dependencies
        run: pnpm install
      
      - name: Build project
        run: pnpm build
      
      - name: Install coscmd
        run: pip install coscmd
      
      - name: Configure coscmd
        env:
          SECRET_ID: ${{ secrets.SecretId }}
          SECRET_KEY: ${{ secrets.SecretKey }}
          BUCKET: ${{ secrets.Bucket }}
          REGION: ${{ secrets.Region }}
        run: coscmd config -a $SECRET_ID -s $SECRET_KEY -b $BUCKET -r $REGION
      
      - name: Upload to COS
        run: coscmd upload -rfs --delete ./dist/ / --ignore "./.git/*"
      
      - name: Refresh CDN cache
        run: |
          # 如果使用 CDN,可以在此添加刷新缓存的步骤
          echo "CDN cache refreshed"

Fork 仓库后定时拉取原项目 Commits

保持 fork 的仓库与上游仓库同步,避免落后太多 commits。

yaml
name: Merge-upstream

on:
  push:
    branches:
      - master
  schedule:
    - cron: 40 16 * * *

jobs:
  merge:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@master
        with:
          ref: master
          fetch-depth: 0
          lfs: true

      - name: Set git identity
        run: |
          git config --global user.email "xxx@xxx.com"
          git config --global user.name "xxxxx"
      - name: Load upstream commits
        run: git pull https://github.com/xxxxxx/xxxxxx.git --no-edit --strategy-option ours

      - name: Push Commits
        env:
          DOWNSTREAM_BRANCH: master
        run: git push origin $DOWNSTREAM_BRANCH

配置详解

触发条件:

yaml
on:
  push:
    branches:
      - master          # 推送到 master 时触发
  schedule:
    - cron: 40 16 * * * # 每天 UTC 16:40(北京时间 00:40)

Cron 表达式说明:

┌───────────── 分钟 (0 - 59)
│ ┌───────────── 小时 (0 - 23)
│ │ ┌───────────── 日期 (1 - 31)
│ │ │ ┌───────────── 月份 (1 - 12)
│ │ │ │ ┌───────────── 星期几 (0 - 6, 0=周日)
│ │ │ │ │
* * * * *

常用时间表:

描述Cron 表达式北京时间
每天凌晨 2 点0 18 * * *02:00
每 6 小时0 */6 * * *每6小时
每周一上午 9 点0 1 * * 1周一 09:00
每月 1 号0 0 1 * *每月1号 08:00

关键步骤:

  1. Checkout 代码

    yaml
    uses: actions/checkout@master
    with:
      ref: master           # 指定分支
      fetch-depth: 0        # 获取完整历史
      lfs: true             # 支持 Git LFS
  2. 设置 Git 身份

    yaml
    git config --global user.email "xxx@xxx.com"
    git config --global user.name "xxxxx"
    # 必须配置,否则无法提交
  3. 拉取上游更新

    yaml
    git pull https://github.com/xxxxxx/xxxxxx.git \
      --no-edit \
      --strategy-option ours
    # --no-edit: 不编辑合并信息
    # --strategy-option ours: 冲突时使用我们的版本
  4. 推送更改

    yaml
    git push origin $DOWNSTREAM_BRANCH
    # 推送到 fork 的仓库

注意事项:

  • ⚠️ 替换 https://github.com/xxxxxx/xxxxxx.git 为实际的上游仓库地址
  • ⚠️ 修改 Git 用户邮箱和姓名
  • ⚠️ 确保有推送权限

自动同步 fork 上游仓库

更完善的同步方案,支持多种触发方式和标签同步。

修改以下git config信息和upstream上游仓库,并设置cron定时同步或本人star仓库触发同步.

yaml
name: Merge upstream branches
on:
  push:
  schedule:
    - cron: '0 18 * * *'
  watch:
    types: [started]
jobs:
  merge:
    runs-on: ubuntu-latest
    if: github.event.repository.owner.id == github.event.sender.id
    steps:
      - uses: actions/checkout@v2.3.5
      - name: Merge upstream
        run: |
          git config --global user.name 'name'
          git config --global user.email 'name@email.com'
          git pull --unshallow
          git remote add upstream https://github.com/xxxxx/xxxxx.git
          git fetch upstream
          git checkout main
          git merge --no-edit upstream/main
          git push origin main
          git fetch upstream --tags
          git push --tags

配置详解

触发条件:

yaml
on:
  push:              # 任何 push 事件
  schedule:
    - cron: '0 18 * * *'  # 每天 UTC 18:00(北京时间 02:00)
  watch:
    types: [started]      # 有人 star 仓库时

条件执行:

yaml
if: github.event.repository.owner.id == github.event.sender.id
# 仅在仓库所有者触发时执行
# 防止他人 star 时意外触发

同步步骤:

bash
# 1. 配置 Git 用户信息
git config --global user.name 'name'
git config --global user.email 'name@email.com'

# 2. 获取完整历史( shallow clone 时需要)
git pull --unshallow

# 3. 添加上游远程仓库
git remote add upstream https://github.com/xxxxx/xxxxx.git

# 4. 获取上游最新代码
git fetch upstream

# 5. 切换到主分支
git checkout main

# 6. 合并上游更改(无编辑模式)
git merge --no-edit upstream/main

# 7. 推送到 fork 仓库
git push origin main

# 8. 同步标签
git fetch upstream --tags
git push --tags

优势:

  • ✅ 自动同步标签
  • ✅ 支持浅克隆转完整克隆
  • ✅ 防止未授权触发
  • ✅ 定时 + 事件双重触发

自动构建和上传镜像

将 Docker 镜像自动构建并推送到 Docker Hub 或其他容器 registry。

yaml
name: Build and push Docker images for ubuntu

on:
  push:
    branches:
      - master

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: Build and push Docker images
        uses: docker/build-push-action@v1
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
          repository: stilleshan/xxxxx
          tags: latest
          path: xxxx/

配置 Secrets

在 GitHub 仓库 Settings → Secrets 中添加:

DOCKER_USERNAME: <你的 Docker Hub 用户名>
DOCKER_PASSWORD: <你的 Docker Hub 密码或 Access Token>

推荐使用 Access Token:

  1. 登录 Docker Hub
  2. Account Settings → Security
  3. New Access Token
  4. 生成并复制 Token

优化版本(多平台构建)

yaml
name: Build and Push Multi-platform Docker Image

on:
  push:
    branches: [main]
    tags: ['v*']

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      
      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: your-username/your-repo
          tags: |
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=sha
            type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
      
      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

特性:

  • ✅ 多平台构建(amd64 + arm64)
  • ✅ 智能标签(语义化版本 + SHA)
  • ✅ 构建缓存加速
  • ✅ 元数据自动生成

自动合并拉取请求

将其中的 imgbot[bot] 修改成需要自动合并的作者

yaml
name: Merge pull request

on:
  pull_request:
    types:
      - opened
      - ready_for_review
  pull_request_review:
    types:
      - submitted
  status: {}

jobs:
  imgbot:
    name: Merge pull request
    runs-on: ubuntu-latest
    permissions: write-all
    if: ${{ github.actor == 'imgbot[bot]' && github.event_name == 'pull_request'}}
    steps:
      - name: Enable auto-merge for imgbot PRs
        run: gh pr merge --auto --squash "$PR_URL"
        env:
          PR_URL: ${{ github.event.pull_request.html_url }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

配置详解

触发条件:

yaml
on:
  pull_request:
    types:
      - opened              # PR 打开时
      - ready_for_review    # Draft 转为 Ready 时
  pull_request_review:
    types:
      - submitted           # 提交审查时
  status: {}                # 状态检查通过时

条件判断:

yaml
if: ${{ github.actor == 'imgbot[bot]' && github.event_name == 'pull_request'}}
# 仅当 actor 是 imgbot[bot] 且事件是 PR 时执行

合并命令:

bash
gh pr merge --auto --squash "$PR_URL"
# --auto: 启用自动合并
# --squash: 压缩提交为一个
# $PR_URL: PR 的 URL

适用场景

ImgBot 自动图片优化:

  • ImgBot 扫描仓库中的图片
  • 自动优化并压缩图片
  • 创建 PR 提交更改
  • 此 workflow 自动合并通过的 PR

其他 Bot:

yaml
# Dependabot(依赖更新)
if: ${{ github.actor == 'dependabot[bot]' }}

# Renovate(依赖管理)
if: ${{ github.actor == 'renovate[bot]' }}

# Greenkeeper(依赖监控)
if: ${{ github.actor == 'greenkeeper[bot]' }}

安全增强版

yaml
name: Auto-merge Trusted Bots

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  auto-merge:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
      contents: write
    
    if: |
      github.actor == 'dependabot[bot]' ||
      github.actor == 'renovate[bot]' ||
      github.actor == 'imgbot[bot]'
    
    steps:
      - name: Approve PR
        run: gh pr review --approve "$PR_URL"
        env:
          PR_URL: ${{ github.event.pull_request.html_url }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Enable auto-merge
        run: gh pr merge --auto --squash "$PR_URL"
        env:
          PR_URL: ${{ github.event.pull_request.html_url }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

改进:

  • ✅ 先批准 PR
  • ✅ 支持多个可信 Bot
  • ✅ 更清晰的权限控制

最佳实践与建议

1. 工作流组织

.github/
└── workflows/
    ├── ci.yml          # 持续集成
    ├── deploy.yml      # 部署流程
    ├── sync.yml        # 同步上游
    └── docker.yml      # Docker 构建

建议:

  • 📁 按功能分离工作流文件
  • 📝 使用清晰的命名
  • 📋 每个文件顶部添加注释说明

2. 性能优化

yaml
# 使用缓存加速构建
- uses: actions/cache@v3
  with:
    path: ~/.pnpm-store
    key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
    restore-keys: |
      ${{ runner.os }}-pnpm-

# 并行执行独立任务
jobs:
  test:
    runs-on: ubuntu-latest
  lint:
    runs-on: ubuntu-latest
  build:
    needs: [test, lint]  # 等待 test 和 lint 完成
    runs-on: ubuntu-latest

3. 错误处理

yaml
steps:
  - name: Step that might fail
    run: exit 1
    continue-on-error: true  # 失败后继续
  
  - name: Cleanup on failure
    if: failure()
    run: echo "Cleaning up..."
  
  - name: Always run
    if: always()
    run: echo "This always runs"

4. 通知机制

yaml
- name: Notify on failure
  if: failure()
  uses: actions/github-script@v6
  with:
    script: |
      github.rest.issues.create({
        owner: context.repo.owner,
        repo: context.repo.repo,
        title: 'Build Failed',
        body: `Build failed in workflow ${context.workflow}`
      })

常见问题排查

Q1: Workflow 不触发?

检查清单:

yaml
# 1. 文件位置是否正确
.github/workflows/*.yml

# 2. 语法是否正确
# 使用 YAML 验证器检查

# 3. 触发条件是否匹配
on: [push]  # 确保有 push 事件

# 4. 分支是否匹配
branches: [main]  # 确保推送到 main 分支

Q2: Secrets 无法读取?

解决方案:

bash
# 1. 确认 Secret 名称大小写敏感
${{ secrets.MY_SECRET }}  # 不是 my_secret

# 2. 确认 Secret 已添加
# Settings → Secrets → 检查列表

# 3. 不要在日志中打印 Secret
echo ${{ secrets.MY_SECRET }}  # ❌ 危险!

Q3: 权限不足?

修复方法:

yaml
# 在 workflow 中声明权限
permissions:
  contents: write
  packages: write
  pull-requests: write

# 或在仓库设置中调整
# Settings → Actions → General → Workflow permissions

Q4: 构建时间过长?

优化技巧:

yaml
# 1. 使用缓存
- uses: actions/cache@v3

# 2. 减少 fetch-depth
- uses: actions/checkout@v4
  with:
    fetch-depth: 1

# 3. 并行执行
jobs:
  job1: ...
  job2: ...
  job3: ...

# 4. 使用更快的 runner
runs-on: ubuntu-latest  # 比 macOS 快

总结

GitHub Actions 为开发者提供了强大的自动化能力:

  1. 灵活触发:支持多种事件和时间表
  2. 丰富生态:数千个现成 Actions 可用
  3. 安全可靠:Secrets 加密存储
  4. 成本友好:公共仓库免费使用
  5. 易于调试:详细的日志和状态反馈

关键要点回顾:

yaml
1. 理解核心概念:Workflow、Job、Step、Action
2. 合理使用 Secrets 保护敏感信息
3. 利用缓存和并行优化性能
4. 遵循最佳实践组织工作流
5. 定期维护和更新 Actions 版本

下一步学习:

开始你的自动化之旅吧!🚀✨