GitHub Actions 生成

按项目类型生成一份能直接提交的 CI 工作流:装依赖、跑测试、构建、传产物,需要时再发布到 Pages、SSH 或镜像仓库。

生成规则

构建 job 固定用 actions/checkout@v4 拉代码,再按项目类型装运行时。Node 用 setup-node 的 cache,Python 用 setup-python 的 pip 缓存,Go 打开 cache: true。缓存靠锁文件哈希,锁文件不提交命中率就是零。

产物通过 upload-artifact / download-artifact 在 job 之间传递,而不是让发布 job 重新构建一遍。这样发布的内容和测试过的完全一致,也省一遍构建时间。

发布到 Pages 时用的是官方三件套:configure-pages、upload-pages-artifact、deploy-pages,仓库设置里要把 Pages 的来源切到 GitHub Actions。推镜像是 build-push-action,默认推到 GHCR,tag 同时打 latest 和 commit sha。

生成的 workflow 只是骨架,部署密钥、服务器路径、健康检查这些要按实际情况补。要在服务器上跑 systemd 服务的话,配一个systemd 服务单元,发布后执行 restart 就行。

常见问题

为什么要拆成 build 和 deploy 两个 job?

构建和发布的生命周期不一样:构建每次提交都跑,发布只关心主分支。拆开之后,发布 job 可以只依赖构建产物,权限也能单独收紧;以后加一个环境审批,不用改构建逻辑。

npm ci 和 npm install 在 CI 里有什么区别?

npm ci 严格按 package-lock.json 安装,锁文件不一致会直接失败,装出来的依赖可复现。npm install 可能顺手改锁文件,在 CI 里反而会让「本地能跑、线上不一样」。前提是锁文件要提交进仓库。

缓存为什么没命中?

setup-node 的 cache 按锁文件的哈希做 key,锁文件变了就重建。pnpm 要先执行 pnpm/action-setup 再 setup-node,否则找不到 pnpm 的存储目录。monorepo 里还要指定 cache-dependency-path。

GITHUB_TOKEN 的权限够用吗?

默认权限在仓库设置里可能是只读。推镜像到 GHCR 需要 packages: write,发布 Pages 需要 pages: write 和 id-token: write。工作流里显式声明 permissions,比改仓库全局设置更安全。

为什么发布步骤在 fork 的 PR 里失败了?

fork 提交的 PR 拿不到 secrets,也不能写仓库内容,这是 GitHub 的安全设计。把发布 job 限制成只在 push 到主分支时执行(if: github.ref == ...),PR 只跑构建和测试。

第三方 action 要固定版本吗?

要。用 v1 这种浮动 tag 意味着对方随时能改你运行的代码。生产流水线建议固定到 commit SHA,至少也要盯住 action 的更新公告。官方 actions/* 相对可信,但同样建议锁主版本。