gogcli 发布流程实战指南:基于 GitHub Actions 的统一版本发布管道与 Docker 收尾

gogcli 发布流程实战指南:基于 GitHub Actions 的统一版本发布管道与 Docker 收尾 gogcli 发布流程实战指南基于 GitHub Actions 的统一版本发布管道与 Docker 收尾【免费下载链接】gogcliGoogle Workspace in your terminal.项目地址: https://gitcode.com/GitHub_Trending/gogcl/gogcliGogCLIGoogle Workspace in your terminal的官方发布完全由一个统一化的 GitHub Actions 工作流承载从版本冻结、签名公证、多平台构建到 Homebrew Tap 同步均以流水线方式自动完成。本文以 docs/RELEASING.md 为主线结合仓库中的工作流定义、GoReleaser 配置与脚本实现完整讲解发布前准备、工作流派发、Docker 镜像收尾及发布后的验证与关闭流程帮助读者掌握一套可复用的「受保护 main 不可变 tag 资产验证」发布实践。一、发布的总原则一切只走统一工作流GogCLI 的官方发布只允许通过.github/workflows/release-unified.yml触发该工作流调用 fleet 标准的openclaw/release-workflowsGo CLI 管道v1。文档明确列出两条硬性约束不要在本地创建或推送发布标签tag不要使用本地的签名或公证notarization凭据。从源码看release-unified.yml 本身是一个轻量分发器它只有一个preflight任务做版本元数据校验随后将实际发布工作委托给可复用的release-go-cli.ymljobs: preflight: runs-on: ubuntu-latest steps: - name: Validate GogCLI version metadata env: VERSION: ${{ inputs.version }} run: | set -euo pipefail release_version${VERSION#v} test $(tr -d \r\n internal/cmd/VERSION) v${release_version} release: needs: preflight uses: openclaw/release-workflows/.github/workflows/release-go-cli.ymlv1 with: version: ${{ inputs.version }} repository-type: openclaw homebrew-tap: openclaw/homebrew-tap homebrew-formula: gogcli checksum-filename: checksums.txt nfpm: auto build-runner: macos stable-identifier: com.steipete.gogcli.gog darwin-universal: disabled reproducible-rebuild: non-darwin其中preflight会强制校验internal/cmd/VERSION文件内容与派发参数一致从源头杜绝「版本号不一致的发布」。发布授权模型发布授权由三部分叠加而成仓库的Actions write权限受保护、且必需检查required checks全部为绿的main分支提交组织级organization-scoped的签名、公证与 Homebrew Tap 凭据。统一工作流负责创建不可变的带注释标签annotated tagGogCLI 刻意不设置独立的本地标签签名授权步骤即本地开发者没有单独给 tag 签名的能力所有版本标签都只能由工作流产生。二、发布前的准备Prepare the release文档要求按顺序完成 4 步更新依赖并合入完整的发布队列release queue确保main上只包含计划内的变更在 CHANGELOG.md 顶部定稿一个带日期的章节格式为## X.Y.Z - YYYY-MM-DD。仓库当前 changelog 顶部格式即## 0.40.0 - 2026-09-11上方保留## 0.40.1 - Unreleased供下一轮迭代设置 internal/cmd/VERSION 为vX.Y.Z。该文件当前内容为v0.40.0-dev发布前要把-dev去掉运行make ci审查完整 diff合入受保护的main并使必需检查全部通过。make ci是仓库 CI 的总入口见 Makefile它串联了ci: pnpm-gate docker-version-check fmt-check lint deadcode test docs-check agent-skills-check即依次执行前端 pnpm 门禁如存在 package.json、Docker 镜像 Go 版本与go.mod工具链一致性检查、代码格式检查、golangci-lint、死代码扫描、Go 单测与 Node 测试、文档覆盖率检查、Agent skills 生成检查。发布前这一整套全部通过是进入工作流派发的先决条件。版本注入的底层机制发布二进制中的版本号并非硬编码而是通过 GoReleaser 的ldflags在编译期注入。查看 .goreleaser.yamlldflags: - -s -w -X github.com/openclaw/gogcli/internal/cmd.version{{ .Tag }} -X github.com/openclaw/gogcli/internal/cmd.commit... -X github.com/openclaw/gogcli/internal/cmd.date{{ .CommitDate }}即internal/cmd包中的version包级变量由-X标志写入测试 execute_version_exitcodes_test.go 也直接覆盖了该变量如version 1.2.3来验证退出码行为。因此internal/cmd/VERSION与 ldflags 注入的版本必须保持同步这正是preflight校验存在的原因。三、统一工作流的执行链路派发成功后release-go-cli.ymlv1会依次完成以下动作文档明确列举冻结受保护的main提交freeze the protected main commit创建或复用其不可变的带注释版本标签从该冻结提交构建产物使用组织 secrets对原生 Darwin 二进制进行签名与公证在arm64 与 Intel 两种 runner 上独立验证完整的资产清单资产清单与 checksum 相互印证发布 GitHub Release依据验证器verifier绑定的资产哈希更新openclaw/homebrew-tap/Formula/gogcli.rb。公共工件契约artifact contract工作流调用方即本仓库需要保持 GogCLI 对外公开的工件契约GoReleaser 矩阵产出的原生 Darwin、Linux、Windows 归档。从 .goreleaser.yaml 可见构建矩阵分为两个 buildgogLinux 与 Windows 的 amd64/arm64 四目标与gog_darwindarwin_amd64/darwin_arm64启用 CGO 与 clang 工具链归档格式 Linux/Darwin 用tar.gz、Windows 用zipchecksums.txt作为校验和资产见.goreleaser.yaml的checksum.name_template同时通过工作流参数checksum-filename: checksums.txt传入既定的签名标识com.steipete.gogcli.gogstable-identifier参数不产出额外的 universal Darwin 归档darwin-universal: disabled非 Darwin 平台的可复现重建验证reproducible-rebuild: non-darwinnFPM 自动检测nfpm: auto保持默认不激活除非 GoReleaser 配置中新增了包package定义。四、派发工作流Dispatch从当前的受保护main上使用不带前导v的 SemVer 版本号派发gh workflow run release-unified.yml \ --repo openclaw/gogcli \ --ref main \ -f versionX.Y.Z仓库同时提供等价的便捷封装脚本 scripts/release.shscripts/release.sh X.Y.Z该脚本内部先做版本格式校验正则^v?[0-9]\.[0-9]\.[0-9]([.-][0-9A-Za-z.-])?$再以-f version${version#v}去掉前导v后执行上述gh workflow run命令。派发后需要紧盯返回的精确工作流运行直到结束。若同一版本重试工作流会复用已存在的不可变标签——标签一旦创建就绝不会被移动这保证了同一 SemVer 号对应的提交永远不变。五、Docker 镜像收尾Docker closeoutGitHub Release 公开且其标签验证通过后需要单独发布 Docker 镜像除非一次精确标签的 Docker 构建运行已经成功。为什么要单独发因为统一发布工作流是用GITHUB_TOKEN创建标签的该动作不会触发Docker 工作流中基于标签推送tag push的触发器——即docker.yml里on.push.tags: v*分支不会被这次「由 token 打 tag」的事件激活所以需要手动补发一次。正确做法是在派发docker.yml时--ref与-f tag都使用发布标签gh workflow run docker.yml \ --repo openclaw/gogcli \ --ref vX.Y.Z \ -f tagvX.Y.Z这里有一个关键陷阱--ref决定 checkout 的提交但构建提交元数据GITHUB_SHA来自派发时的 SHA。如果从main派发就会把更新的提交标注到 tagged build 上。因此必须验证本次运行的 head SHA 与冻结的发布提交一致等待构建成功再确认 GHCR 上的版本标签已发布稳定版还需确认latest标签。查看 docker.yml手动派发时它会校验tag输入格式正则^v[0-9]\.[0-9]\.[0-9](-[a-zA-Z0-9.])?$以ref: ${{ github.event_name workflow_dispatch inputs.tag || github.ref }}精确 checkout 指定标签执行make docker-version-check校验 Dockerfile 的 Go 版本与go.mod构建工具链一致通过docker/metadata-action生成 GHCR 标签其中latest仅在稳定版版本号不含-连字符时启用通过 build-args 注入VERSION、COMMIT12 位短 SHA、DATE构建元数据。六、验证与关闭Verify and close out宣布发布完成前必须逐项核验以下清单精确的工作流运行已成功是派发时返回的那次运行而非其它运行带注释标签解析到冻结的受保护 main 提交GitHub Release 已发布且 Release 正文与对应 changelog 章节一致GoReleaser 的release.name_template为标签名正文取自 changelog 管道已发布的 checksum 与资产清单inventory覆盖每一个资产两个原生 macOS 验证任务均通过各自核验了签名、Team ID、稳定标识符com.steipete.gogcli.gog、hardened runtime、时间戳、架构与在线公证online notarization检查Homebrew 交接成功Formula/gogcli.rb中包含已验证的版本号、归档文件名与哈希。收尾进入下一轮开发版本最后两步收尾动作在 changelog 顶部落一个下一补丁版本的Unreleased章节将 internal/cmd/VERSION 设置为已发布版本加-dev后缀例如发布v0.40.0后设为v0.40.1-dev当前仓库即处于v0.40.0-dev状态。需要特别注意的是可复用工作流可能自动开启一个只包含 changelog 标题的关闭closeoutPR。此时应把开发版本号的改动加到那个确切的 PR 上再审查合并而不是另开一个并行的过渡 PR——目的是始终保持且只有一个Unreleased章节避免 changelog 头部出现多个待发布条目。七、总结一套可复用的发布心智模型从整个流程可以提炼出 GogCLI 发布的关键设计单一入口所有版本操作收敛到.github/workflows/release-unified.yml本地零签名、零打标不可变事实版本标签由工作流创建且永不移动同一版本号永远对应同一提交重试安全双端验证非 Darwin 产物做可复现重建验证macOS 产物在两种架构 runner 上独立做签名/公证核验发布即同步GitHub Release、Homebrew Formula、Docker GHCR 三处分发点由同一次发布的事实冻结提交 标签 哈希串联其中 Docker 因 token 打标不触发 tag 触发器而需要单独收尾。本文所涉及的发布配置与脚本均位于仓库内可按需深入阅读.github/workflows/release-unified.yml、.github/workflows/docker.yml、.goreleaser.yaml、scripts/release.sh、Makefile 以及 internal/cmd/VERSION。【免费下载链接】gogcliGoogle Workspace in your terminal.项目地址: https://gitcode.com/GitHub_Trending/gogcl/gogcli创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考