coding_agent

GitHub Actions 自动化部署实战

将代码部署到 GitHub Pages 是静态网站最常见的托管方案之一,而 GitHub Actions 提供了免费的自动化构建部署能力。但要让这个流程真正可靠,需要处理依赖缓存、构建优化、错误处理等多个细节。

基础 workflow 配置

一个最基本的 GitHub Actions workflow 包含 trigger(触发条件)、job(作业)、step(步骤)三个层级。对于 GitHub Pages 部署,trigger 通常设置为 push 到特定分支(如 maingh-pages),以及 pull_request 用于预览。下面的配置展示了一个生产级别的 workflow 结构:

name: Deploy to GitHub Pages
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
permissions:
  contents: read
  pages: write
  id-token: write

permissions 部分是新版本 GitHub Actions 的安全增强要求,明确声明需要用到的权限范围,避免过度授权。contents: read 用于检出代码,pages: writeid-token: write 用于向 GitHub Pages API 推送构建产物。

依赖缓存:加速构建的关键

每次 workflow 运行时重新下载 npm 依赖会极大延长构建时间。通过 actions/cache 可以将 node_modules 缓存起来,只在依赖变化时重新下载。一个优化过的步骤配置通常包含缓存命中检测和回退逻辑:

- name: Setup Node
  uses: actions/setup-node@v4
  with:
    node-version: '20'
    cache: 'npm'

- name: Install dependencies
  run: npm ci

actions/setup-node@v4 自带的 cache: 'npm' 选项会自动检测 lockfile 的变化,只有 lockfile 变化时才重新安装依赖。对于 monorepo 或有多个 lockfile 的项目,可能需要使用 actions/cache 手动配置缓存路径。

多端点 fallback 策略

直接 git push 在某些网络环境下可能失败,比如通过代理访问 GitHub 时。智能的 CI/CD pipeline 应该实现多端点 fallback:优先尝试 git push,失败后切换到 GitHub API 直接上传 Pages 内容。这个逻辑可以封装在一个自定义的脚本中,由 workflow 调用:

#!/bin/bash
git push origin $GITHUB_REF || {
  echo "git push failed, trying GitHub API..."
  # 使用 gh api 上传 Pages 内容
}

这种设计在 stash 代理环境下特别重要,因为代理的 TLS 握手问题可能导致 git push 随机失败,但 API 上传不受影响。

常见错误与处理经验

GitHub Actions 部署中最常见的错误之一是权限不足GITHUB_TOKEN 默认权限有限,如果 workflow 需要访问私有仓库的依赖或写入 Packages,需要在 workflow 文件的 permissions 部分显式声明。近年来 GitHub 逐步收紧默认权限,最佳实践是在 workflow 开头就声明所有需要的权限,而不是依赖隐式的默认行为。

另一个常见问题是构建产物路径不匹配。GitHub Pages 要求上传的 docs/ 或构建输出目录结构必须符合预期。Astro 项目的默认构建输出是 dist/,需要确认 github-pages artifact 上传的是正确路径。可以在 workflow 中添加验证步骤:

- name: Verify build output
  run: |
    if [ ! -d "dist" ]; then
      echo "Error: dist directory not found"
      exit 1
    fi

最后,分支策略也需要注意。虽然很多项目习惯使用 master 分支,但 GitHub 默认分支通常是 main。操作前先检查哪个分支存在,可以避免 push 到错误的分支导致部署失败。

完整 workflow 示例

一个生产级别的完整 workflow 应该包含:依赖安装(带缓存)、类型检查、构建、部署、以及失败通知。每个步骤都应该是幂等的,失败后可以从任意步骤重试而不会产生副作用。

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

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - uses: actions/download-pages-artifact@v3
      - uses: actions/configure-pages@v4
      - uses: actions/upload-pages-artifact@v3

这个配置将构建和部署分离为两个 job,部署 job 依赖构建 job 的产出,符合单一职责原则。environment 配置会在部署前要求人工审批(如果配置了 required reviewers),增加了生产部署的安全性。