跳转到内容

GitHub 上的 CI/CD

个人项目默认从 GitHub Actions 开始,不要先搭一套 Jenkins。 第一个目标只有两个:PR 自动检查,main 成功后才发布。让失败的检查真正阻止发布,再逐步加缓存、并行与版本发布。

在仓库的 .github/workflows/ci.yml 中添加配置。以下示例要求 npm 项目已提交 package-lock.json,并提供 test 和 build 脚本:

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: actions/setup-node@v7
with:
node-version: '24'
cache: npm
- run: npm ci
- run: npm test
- run: npm run build

npm ci 根据锁文件安装依赖。没有测试的项目,先建立一项真实检查再把它设为必需;不要让本来应该执行的测试被静默跳过。类型与代码检查按项目 scripts 一起加入,CI 中的命令应和本机一致。

pnpm 项目应先使用 pnpm/action-setup,通过 packageManager 固定版本,再用 actions/setup-node 缓存 pnpm,执行 pnpm install --frozen-lockfile。缓存加速下载,不应替代每个任务中的依赖安装。

本书仓库的实际配置见 ci.yml。

GitHub Pages 支持两种常见发布方式:将构建结果推送到专用分支,或使用 Pages 官方 Actions 上传并部署。两者需要对应的仓库 Pages 设置,选择一种即可。

本书沿用 gh-pages 分支部署。在仓库 Settings → Pages 中选择从 gh-pages 的根目录发布。其自动化流程是:

  1. PR 和 main 更新都执行锁文件安装、依赖漏洞审计、测试、Astro 检查、静态构建、站内链接与 SEO 检查。
  2. main 的构建成功后,上传 dist/ 作为本次运行的产物。
  3. 单独的部署任务下载这份产物,通过 peaceiris/actions-gh-pages@v4 发布到 gh-pages。
  4. 仅部署任务声明 contents: write,PR 不执行该任务。

部署路径要与构建配置一致。本书使用 /frontend-guideline/ 前缀;普通单页应用还需根据托管平台配置路由回退。发布前的检查见打包及发布。

如果选择官方 Pages 工作流,应在 Pages 设置中选择 GitHub Actions,并配置 pages: write、id-token: write 与部署环境等要求。

  • 使用默认只读权限,仅给需要部署或创建 Release 的任务增加相应写权限。
  • PR 可能包含外部贡献者的代码。验证工作流使用 pull_request;不要用拥有写权限或密钥的 pull_request_target 执行 PR 中的代码。
  • 部署限定 main 或受保护的标签,并通过 needs 依赖构建结果。使用 concurrency 避免旧构建覆盖新版本。
  • Token 和私钥放在 Actions Secrets 中,不写入源码或构建日志。面向浏览器的环境变量仍会公开到产物中。
  • 第三方 Actions 应核对来源和更新说明;需要更严格的供应链控制时,可固定到审查过的完整提交 SHA。

npm 包发布与静态站点部署是独立流程。优先参考 npm trusted publishing,在 npm 配置受信任仓库、工作流与环境后,通过 OIDC 发布,避免维护长期 Token。

工作流通常由受保护的版本标签触发,依次安装锁定依赖、检查、测试、构建和 npm publish。版本号、包内容(npm pack --dry-run)、访问权限与发布来源都应在发布前确认。使用 Token 的项目还需按 npm 当前要求设置有效期与发布权限。

可以使用 GitHub CLI 上传构建产物到 GitHub Releases。以下步骤应接在实际构建步骤之后,且只在版本标签事件中执行;把文件名替换为项目产出的安装包路径。

permissions:
contents: write
# 放入已有 job 的 steps 中
steps:
# 检出、安装依赖、构建安装包……
- name: Create release and upload installer
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
RELEASE_TAG: ${{ github.ref_name }}
run: gh release create "$RELEASE_TAG" dist/client-app.exe --verify-tag --generate-notes

gh release create 会发布 Release,重复发布已有标签前需明确是更新附件还是创建新版本。旧的 actions/create-release 与 actions/upload-release-asset 已归档,不再作为新工作流的推荐方案。

  • 没有触发:先看 on 的分支、路径与事件过滤,不是每次 push 都匹配同一个工作流。
  • 检查失败:点开失败 job 的第一条相关报错,在同一 Node 与包管理器版本下复现。
  • 构建成功但没上线:看 deploy 是否被 if 跳过、是否拿到正确 artifact,再看 Pages 来源配置与实际 Pages deployment。
  • 权限不足:检查当前 job 的 permissions 和事件类型,别先把整个工作流改成全仓库写权限。

失败后先修一个能验证的原因。旧部署仍可用时保留它,别为了「重来一次」清空发布分支。其他托管选择见部署。