跳轉到內容

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 版本

下一步學習:

開始你的自動化之旅吧!🚀✨

最後更新於: