Skip to content

GitHub Actions 自动化部署

从零掌握 GitHub Actions——用 Workflow 实现代码提交后自动测试、构建 Docker 镜像、推送到镜像仓库、部署到服务器的完整 CI/CD 流水线,覆盖前端/后端/全栈项目的自动化部署实践。


1. GitHub Actions 核心概念:CI/CD 从手动到自动

代码写完 → 跑测试 → 构建镜像 → 推送仓库 → SSH 到服务器 → 拉镜像 → 重启服务——每次部署都要重复这 7 步。GitHub Actions 让这一切在 git push 后自动完成。

1.1 为什么需要 CI/CD:告别手动部署

没有 CI/CD 的部署流程:

  git push

      ▼ (手动)
  本地跑测试 → 忘了跑 → 线上有 bug 🐛

      ▼ (手动)
  docker build → docker push → SSH → docker pull

      ▼ (半小时后)
  终于部署完了 → 发现推错分支了 😱

  ═══════════════════════════════════════

有了 CI/CD:

  git push

      ▼ (全自动)
  测试 → 构建 → 推送 → 部署

      ▼ (3 分钟后)
  ✅ 部署完成,Slack 收到通知
概念全称含义
CIContinuous Integration每次提交自动跑测试,尽早发现问题
CDContinuous Delivery自动构建产物(镜像/包),随时可发布
CDContinuous Deployment自动部署到生产环境,push 即上线

1.2 核心概念:Workflow、Job、Step、Action、Runner

GitHub Actions 的层级结构:

  Workflow(工作流)
  ├── .github/workflows/deploy.yml     ← 一个 YAML 文件 = 一个 Workflow

  ├── Job 1: test(测试)              ← 一组步骤,跑在一台机器上
  │   ├── Step 1: checkout              ← 一个操作
  │   ├── Step 2: setup-python
  │   ├── Step 3: pip install
  │   └── Step 4: pytest

  ├── Job 2: build(构建)             ← 可以依赖 Job 1
  │   ├── Step 1: checkout
  │   ├── Step 2: docker build
  │   └── Step 3: docker push

  └── Job 3: deploy(部署)            ← 可以依赖 Job 2
      ├── Step 1: SSH 到服务器
      └── Step 2: docker compose up
概念类比说明
Workflow流水线一个 YAML 文件定义一条流水线
Job工位跑在独立的虚拟机上,可并行
Step工序Job 内的一个操作,按顺序执行
Action工具可复用的操作(官方/社区提供)
Runner工人执行 Job 的机器(GitHub 提供或自托管)

1.3 与 Jenkins / GitLab CI 的对比

特性GitHub ActionsJenkinsGitLab CI
托管方式GitHub 托管自建GitLab 托管
配置格式YAMLGroovyYAML
生态Marketplace 丰富插件多但杂内置功能全
免费额度2000 分钟/月无(自建)400 分钟/月
上手难度⭐⭐⭐⭐⭐⭐⭐⭐⭐

1.4 免费额度与计费规则

GitHub Actions 免费额度(公开仓库无限制):

  私有仓库:
  ──────────────────────────────────
  Free 计划     2,000 分钟/月
  Pro 计划      3,000 分钟/月
  Team 计划    3,000 分钟/月
  Enterprise   50,000 分钟/月
  ──────────────────────────────────

  Runner 计费倍率:
  Linux         1x(最便宜)
  Windows       2x
  macOS         10x(最贵)

💡 省钱技巧:公开仓库完全免费、不限时长。私有仓库尽量用 Linux Runner,一个 Job 跑完所有步骤比拆成多个 Job 更省分钟数。

第 1 章核心知识回顾:

概念一句话解释
CI/CD提交代码后自动测试+构建+部署
Workflow.github/workflows/xxx.yml 定义流水线
Job/StepJob = 一台机器,Step = 一个操作
RunnerGitHub 提供免费 Linux/Windows/macOS 虚拟机

2. 第一个 Workflow:Hello World 到实用模板

2.1 Workflow 文件结构与触发器

yaml
# .github/workflows/ci.yml
name: CI Pipeline                     # Workflow 名称(显示在 Actions 页面)

on:                                    # 触发条件
  push:
    branches: [main, develop]          # push 到 main/develop 时触发
  pull_request:
    branches: [main]                   # PR 目标为 main 时触发
  schedule:
    - cron: '0 2 * * 1'               # 每周一凌晨 2 点(定时任务)
  workflow_dispatch:                   # 手动触发按钮

jobs:
  hello:
    runs-on: ubuntu-latest             # Runner 类型
    steps:
      - name: Hello World
        run: echo "Hello GitHub Actions! 🎉"
触发器语法场景
pushon: push推送代码时
pull_requeston: pull_requestPR 创建/更新时
schedulecron: '...'定时任务
workflow_dispatch无参数手动触发
releaseon: release发布 Release 时

2.2 YAML 语法详解:on / jobs / steps

yaml
name: Full Example

on:
  push:
    branches: [main]
    paths:                             # 只在这些路径变化时触发
      - 'src/**'
      - 'Dockerfile'
    paths-ignore:                      # 忽略这些路径
      - '*.md'
      - 'docs/**'

jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 10                # 超时限制
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v4      # 使用官方 Action

      - name: Run command
        run: |                         # 多行命令
          echo "Step 1"
          echo "Step 2"
        env:                           # 步骤级环境变量
          MY_VAR: hello

      - name: Conditional step
        if: github.ref == 'refs/heads/main'  # 条件执行
        run: echo "Only on main branch"

2.3 矩阵构建:多版本 / 多平台并行测试

yaml
jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest]
        python-version: ['3.10', '3.11', '3.12']
      fail-fast: false                 # 一个失败不影响其他

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      - run: python -m pytest

2.4 缓存依赖:pip / npm / docker 层缓存

yaml
# ── Python pip 缓存 ──
- uses: actions/setup-python@v5
  with:
    python-version: '3.11'
    cache: 'pip'                       # 自动缓存 pip

# ── Node npm 缓存 ──
- uses: actions/setup-node@v4
  with:
    node-version: '20'
    cache: 'npm'

# ── 手动缓存(通用) ──
- uses: actions/cache@v4
  with:
    path: ~/.cache/pip
    key: pip-${{ hashFiles('requirements.txt') }}
    restore-keys: pip-

💡 缓存的效果:首次安装 pip install 需要 60 秒,缓存命中后只需 5 秒。矩阵构建 6 个组合 × 60 秒 = 6 分钟 → 缓存后 30 秒。

第 2 章核心知识回顾:

概念一句话解释
触发器push/PR/定时/手动,控制 Workflow 何时运行
paths只在特定文件变化时触发,避免无效构建
矩阵构建多版本多平台并行测试,一次覆盖全部组合
缓存缓存依赖安装,构建速度提升 10 倍

3. 自动化测试:提交即测试

3.1 Python 项目:pytest + 覆盖率

yaml
name: Python Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    
    services:                          # 测试需要的服务
      postgres:
        image: postgres:16
        env:
          POSTGRES_PASSWORD: test
          POSTGRES_DB: testdb
        ports: ['5432:5432']
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'
          cache: 'pip'
      
      - name: Install dependencies
        run: pip install -r requirements.txt -r requirements-dev.txt
      
      - name: Run tests with coverage
        run: pytest --cov=app --cov-report=xml --cov-report=term
        env:
          DATABASE_URL: postgresql://postgres:test@localhost:5432/testdb
      
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v4
        with:
          file: coverage.xml

3.2 前端项目:Vitest + ESLint + TypeCheck

yaml
name: Frontend CI

on: [push, pull_request]

jobs:
  lint-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      
      - run: npm ci                    # 比 npm install 更快更稳定
      - run: npm run lint              # ESLint 检查
      - run: npm run typecheck         # TypeScript 类型检查
      - run: npm run test              # Vitest 单元测试
      - run: npm run build             # 确保能构建成功

3.3 测试覆盖率报告与 PR 评论

yaml
      - name: Comment coverage on PR
        if: github.event_name == 'pull_request'
        uses: marocchino/sticky-pull-request-comment@v2
        with:
          message: |
            ## 📊 测试覆盖率报告
            
            | 指标 | 数值 |
            |:---|:---|
            | 覆盖率 | ${{ steps.coverage.outputs.total }}% |
            | 测试用例 | ${{ steps.test.outputs.total }} 个 |
            | 通过 | ✅ ${{ steps.test.outputs.passed }} |
            | 失败 | ❌ ${{ steps.test.outputs.failed }} |

3.4 分支保护:测试不过不许合并

设置分支保护规则:

  GitHub → Settings → Branches → Branch protection rules

  Branch name pattern: main
  
  ☑ Require a pull request before merging
  ☑ Require status checks to pass before merging
    → 选择你的 CI Job 名称(如 "test")
  ☑ Require branches to be up to date before merging
  
  效果:PR 必须通过所有测试才能合并到 main

💡 分支保护是 CI 真正发挥价值的关键——没有强制检查,开发者可以直接跳过测试合并代码。配置了分支保护,测试就不是"建议"而是"强制"。

第 3 章核心知识回顾:

概念一句话解释
services测试中启动 PostgreSQL/Redis 等容器
覆盖率pytest --cov + Codecov 自动生成报告
PR 评论测试结果自动评论到 PR 上
分支保护测试不过 → 不允许合并

4. Docker 镜像构建与推送

4.1 构建并推送到 Docker Hub

yaml
name: Build & Push Docker Image

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_TOKEN }}

      - name: Build and Push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: |
            username/my-app:latest
            username/my-app:${{ github.sha }}
          cache-from: type=gha            # GitHub Actions 缓存
          cache-to: type=gha,mode=max

4.2 推送到 GitHub Container Registry(GHCR)

yaml
      - name: Login to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}  # 自动提供,无需配置

      - name: Build and Push to GHCR
        uses: docker/build-push-action@v5
        with:
          push: true
          tags: ghcr.io/${{ github.repository }}:latest

💡 GHCR 的优势GITHUB_TOKEN 自动提供,不需要额外配置 Secret。镜像跟代码在同一个地方管理。

4.3 多平台构建:amd64 + arm64

yaml
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Build multi-platform
        uses: docker/build-push-action@v5
        with:
          push: true
          platforms: linux/amd64,linux/arm64
          tags: username/my-app:latest

4.4 镜像 Tag 策略:commit SHA / 语义化版本 / latest

Tag 策略示例适用场景
latestmy-app:latest开发/测试环境
Commit SHAmy-app:a1b2c3d精确回滚
语义化版本my-app:v1.2.3正式发布
分支名my-app:develop多分支部署
yaml
      - name: Docker meta
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: username/my-app
          tags: |
            type=sha
            type=ref,event=branch
            type=semver,pattern={{version}}

第 4 章核心知识回顾:

概念一句话解释
docker/build-push-action官方 Action,一步完成构建+推送
GHCRGitHub 自带镜像仓库,GITHUB_TOKEN 自动认证
多平台QEMU + Buildx 同时构建 amd64/arm64
GHA 缓存cache-from: type=gha 利用 Actions 缓存加速构建

5. 自动部署到服务器

5.1 SSH 部署:拉镜像 + docker compose up

yaml
name: Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    needs: build                       # 等构建完成
    
    steps:
      - name: Deploy via SSH
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /opt/my-app
            docker compose pull
            docker compose up -d --remove-orphans
            docker image prune -f      # 清理旧镜像

5.2 部署到云平台:Vercel / Railway / Fly.io

yaml
# ── 部署到 Vercel(前端项目) ──
      - name: Deploy to Vercel
        uses: amondnet/vercel-action@v25
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
          vercel-args: '--prod'

# ── 部署到 Fly.io ──
      - name: Deploy to Fly.io
        uses: superfly/flyctl-actions/setup-flyctl@master
      - run: flyctl deploy --remote-only
        env:
          FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}

5.3 零停机部署:蓝绿发布与滚动更新

bash
# SSH 部署脚本中实现滚动更新
script: |
  cd /opt/my-app
  docker compose pull
  
  # 逐个重启(不是全部停掉再启动)
  docker compose up -d --no-deps --build web
  
  # 等待健康检查通过
  sleep 10
  curl -f http://localhost:8000/health || exit 1

5.4 多环境部署:staging → production 流水线

yaml
jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    environment: staging               # 需要在 GitHub 设置环境
    steps:
      - name: Deploy to Staging
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.STAGING_HOST }}
          script: cd /opt/my-app && docker compose up -d

  deploy-production:
    runs-on: ubuntu-latest
    needs: deploy-staging
    environment: production            # 可配置"需要审批"
    steps:
      - name: Deploy to Production
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.PROD_HOST }}
          script: cd /opt/my-app && docker compose up -d

💡 environment 审批:在 GitHub → Settings → Environments → production 中设置 "Required reviewers",部署到生产前需要指定人员点击 Approve。

第 5 章核心知识回顾:

概念一句话解释
SSH 部署appleboy/ssh-action 远程执行命令
零停机--no-deps 逐个重启 + 健康检查
多环境staging → production,production 需审批

6. Secrets、环境变量与安全

6.1 Secrets 管理:仓库级 vs 环境级

Secrets 的两种级别:

  仓库级 Secrets
  ═══════════════════════════════════════
  Settings → Secrets and variables → Actions
  所有 Workflow 都能用
  适合:DOCKER_TOKEN, SSH_KEY

  环境级 Secrets
  ═══════════════════════════════════════
  Settings → Environments → production → Secrets
  只有指定环境的 Job 能用
  适合:PROD_DATABASE_URL, PROD_API_KEY

6.2 环境变量与 .env 文件生成

yaml
      - name: Create .env file
        run: |
          cat > .env << EOF
          DATABASE_URL=$&#123;&#123; secrets.DATABASE_URL &#125;&#125;
          REDIS_URL=$&#123;&#123; secrets.REDIS_URL &#125;&#125;
          SECRET_KEY=$&#123;&#123; secrets.SECRET_KEY &#125;&#125;
          DEBUG=false
          EOF

      - name: Deploy with .env
        uses: appleboy/ssh-action@v1
        with:
          host: $&#123;&#123; secrets.SERVER_HOST &#125;&#125;
          script: |
            cd /opt/my-app
            docker compose --env-file .env up -d

6.3 OIDC 无密钥认证(AWS / GCP)

yaml
# 无需存储 AWS 密钥——用 OIDC 临时凭证
permissions:
  id-token: write
  contents: read

steps:
  - name: Configure AWS Credentials
    uses: aws-actions/configure-aws-credentials@v4
    with:
      role-to-assume: arn:aws:iam::123456789:role/github-actions
      aws-region: ap-east-1

6.4 安全最佳实践:最小权限与审计

实践说明
最小权限 TokenGITHUB_TOKEN 权限收窄到 contents: read
Pin Action 版本@v4 而不是 @main,防止供应链攻击
环境审批production 环境需要人工 Approve
Secret 轮换定期更新 Token 和密钥
审计日志Settings → Log 查看 Secret 使用记录

💡 绝对不要:在 Workflow 中 echo $<span v-pre>&#123;&#123; secrets.XXX &#125;&#125;</span>——GitHub 会自动遮掩,但在某些边角情况下可能泄露。

第 6 章核心知识回顾:

概念一句话解释
仓库 vs 环境 Secrets仓库级全局可用,环境级限定 Job
.env 生成在 CI 中动态生成 .env 文件
OIDC无需存储密钥,用临时凭证认证云服务
Pin 版本Action 用 @v4 不用 @main,防供应链攻击

7. 实战:三种典型项目的完整 CI/CD

7.1 前端项目:React/Vue → 构建 → 部署到 Vercel/Nginx

yaml
name: Frontend CI/CD

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

jobs:
  test:
    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 lint
      - run: npm run test
      - run: npm run build
      - uses: actions/upload-artifact@v4
        with:
          name: dist
          path: dist/

  deploy:
    needs: test
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/download-artifact@v4
        with: { name: dist, path: dist/ }
      - name: Deploy to Vercel
        uses: amondnet/vercel-action@v25
        with:
          vercel-token: $&#123;&#123; secrets.VERCEL_TOKEN &#125;&#125;
          vercel-args: '--prod'
          vercel-org-id: $&#123;&#123; secrets.VERCEL_ORG_ID &#125;&#125;
          vercel-project-id: $&#123;&#123; secrets.VERCEL_PROJECT_ID &#125;&#125;

7.2 Python 后端:FastAPI → Docker → 服务器

yaml
name: Backend CI/CD

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env: { POSTGRES_PASSWORD: test, POSTGRES_DB: testdb }
        ports: ['5432:5432']
        options: --health-cmd pg_isready --health-interval 10s --health-retries 5
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: '3.11', cache: 'pip' }
      - run: pip install -r requirements.txt -r requirements-dev.txt
      - run: pytest --cov=app
        env:
          DATABASE_URL: postgresql://postgres:test@localhost:5432/testdb

  build-and-deploy:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: $&#123;&#123; github.actor &#125;&#125;
          password: $&#123;&#123; secrets.GITHUB_TOKEN &#125;&#125;

      - uses: docker/build-push-action@v5
        with:
          push: true
          tags: ghcr.io/$&#123;&#123; github.repository &#125;&#125;:$&#123;&#123; github.sha &#125;&#125;
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - uses: appleboy/ssh-action@v1
        with:
          host: $&#123;&#123; secrets.SERVER_HOST &#125;&#125;
          username: $&#123;&#123; secrets.SERVER_USER &#125;&#125;
          key: $&#123;&#123; secrets.SSH_PRIVATE_KEY &#125;&#125;
          script: |
            cd /opt/my-api
            docker compose pull
            docker compose up -d

7.3 全栈项目:前端 + 后端 + 数据库迁移

yaml
name: Full Stack CI/CD

on:
  push:
    branches: [main]

jobs:
  test-backend:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: '3.11', cache: 'pip' }
      - run: pip install -r backend/requirements.txt
      - run: cd backend && pytest

  test-frontend:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20', cache: 'npm' }
      - run: cd frontend && npm ci && npm run test

  deploy:
    needs: [test-backend, test-frontend]  # 两个都通过
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: appleboy/ssh-action@v1
        with:
          host: $&#123;&#123; secrets.SERVER_HOST &#125;&#125;
          key: $&#123;&#123; secrets.SSH_PRIVATE_KEY &#125;&#125;
          script: |
            cd /opt/fullstack-app
            git pull origin main
            docker compose build
            docker compose run --rm migrate alembic upgrade head
            docker compose up -d

💡 全栈项目的部署顺序:先跑数据库迁移(alembic upgrade head),再重启应用容器。千万别反过来——新代码可能依赖新的数据库字段。

第 7 章核心知识回顾:

项目类型测试构建部署
前端lint + test + buildartifact 上传Vercel/Nginx
后端pytest + 数据库服务Docker 镜像SSH 拉镜像
全栈前后端并行测试Docker Compose迁移 → 重启

8. 进阶技巧与优化

8.1 可复用 Action 与 Composite Action

yaml
# .github/actions/setup-python-env/action.yml
name: 'Setup Python Environment'
description: 'Install Python and dependencies'

inputs:
  python-version:
    default: '3.11'

runs:
  using: 'composite'
  steps:
    - uses: actions/setup-python@v5
      with:
        python-version: $&#123;&#123; inputs.python-version &#125;&#125;
        cache: 'pip'
    - run: pip install -r requirements.txt
      shell: bash
yaml
# 在 Workflow 中使用
steps:
  - uses: ./.github/actions/setup-python-env
    with:
      python-version: '3.12'

8.2 自托管 Runner:用自己的服务器跑 CI

bash
# 在你的服务器上安装 Runner
# GitHub → Settings → Actions → Runners → New self-hosted runner

./config.sh --url https://github.com/user/repo --token XXXXX
./run.sh      # 或 sudo ./svc.sh install && sudo ./svc.sh start
yaml
# Workflow 中使用自托管 Runner
jobs:
  build:
    runs-on: self-hosted       # 替换 ubuntu-latest

8.3 Workflow 优化:并行、条件跳过、超时控制

yaml
# 跳过 CI(commit message 中包含 [skip ci])
on:
  push:
    branches: [main]

jobs:
  test:
    if: "!contains(github.event.head_commit.message, '[skip ci]')"

# 取消同分支的旧运行(节省资源)
concurrency:
  group: $&#123;&#123; github.workflow &#125;&#125;-$&#123;&#123; github.ref &#125;&#125;
  cancel-in-progress: true

8.4 通知集成:Slack / 飞书 / 钉钉

yaml
      - name: Notify on success
        if: success()
        uses: slackapi/slack-github-action@v1
        with:
          payload: |
            {"text": "✅ 部署成功!$&#123;&#123; github.repository &#125;&#125; @ $&#123;&#123; github.sha &#125;&#125;"}
        env:
          SLACK_WEBHOOK_URL: $&#123;&#123; secrets.SLACK_WEBHOOK &#125;&#125;

      - name: Notify on failure
        if: failure()
        run: |
          curl -X POST $&#123;&#123; secrets.FEISHU_WEBHOOK &#125;&#125; \
            -H 'Content-Type: application/json' \
            -d '{"msg_type":"text","content":{"text":"❌ 部署失败!请检查 GitHub Actions"&#125;&#125;'

附录:GitHub Actions 速查手册

A.1 触发器(on)速查

触发器语法说明
pushon: push推送代码
pull_requeston: pull_requestPR 事件
schedulecron: '0 2 * * *'定时(UTC)
workflow_dispatchon: workflow_dispatch手动按钮
releaseon: release发布 Release
workflow_callon: workflow_call被其他 Workflow 调用

A.2 常用官方/社区 Action 推荐

Action用途
actions/checkout@v4拉取代码
actions/setup-python@v5安装 Python
actions/setup-node@v4安装 Node.js
actions/cache@v4缓存依赖
actions/upload-artifact@v4上传构建产物
docker/build-push-action@v5构建+推送 Docker 镜像
docker/login-action@v3登录镜像仓库
appleboy/ssh-action@v1SSH 远程执行命令
codecov/codecov-action@v4上传测试覆盖率

A.3 Workflow YAML 语法速查

语法示例说明
runs-onubuntu-latestRunner 类型
needsneeds: [test, lint]Job 依赖
ifif: github.ref == 'refs/heads/main'条件执行
envenv: { KEY: value }环境变量
timeout-minutestimeout-minutes: 10超时限制
continue-on-errorcontinue-on-error: true失败不阻断
concurrencygroup: xxx并发控制

A.4 常见报错与解决方案

报错原因解决
permission deniedGITHUB_TOKEN 权限不足添加 permissions
secret not foundSecret 名称拼错或未配置检查 Settings → Secrets
timeoutJob 运行太久timeout-minutes
cache miss缓存 key 不匹配检查 hashFiles() 路径
image not found推送未成功检查 login + tag

坚持是一种品格