云镜之端

GoReleaser(Pro)使用文档

GoReleaser(Pro) 全功能使用手册 适用版本:GoReleaser Pro v2.18.1(GitCommit 47450ce5908844dcfc670efbf19186d8ad88b6d6) 平台:darwin/arm64(Go 1.27.1 构建) 官方文档:https://gor

  • 作者
  • 1 分钟阅读
评论
GoReleaser(Pro)使用文档

GoReleaser(Pro) 全功能使用手册

适用版本:GoReleaser Pro v2.18.1(GitCommit 47450ce5908844dcfc670efbf19186d8ad88b6d6)
平台:darwin/arm64(Go 1.27.1 构建)
官方文档:https://goreleaser.com


目录

  1. 简介与定位
  2. 安装与版本信息
  3. 授权(License)管理
  4. 快速上手(5 分钟跑通)
  5. 命令行总览
  6. 命令详解
  7. Pro 专属能力详解
  8. 打包与镜像格式详解(dmg / pkg / msi / nsis / deb / rpm …)
  9. --skip 可跳过阶段清单
  10. 典型工作流
  11. 故障排查与常用技巧
  12. 附录

1. 简介与定位

GoReleaser 是一款发布工程自动化工具,单条命令即可完成:

  • 跨平台交叉编译 Go 二进制(Linux/macOS/Windows,含 ARM64、RISC-V 等)
  • 生成 .deb / .rpm / .apk / .msi / .pkg / .dmg / Flatpak / Snap / Scoop / Winget / Chocolatey / Homebrew / AUR / Nix / NPM / nfpm 等几十种安装包格式
  • 生成 SBOM(软件物料清单)与签名
  • 推送到 GitHub/GitLab/Gitea、自有 S3/MinIO、Docker Hub、AWS ECR、GHCR 等
  • 自动生成 Changelog、Release Notes 并在 GitHub/GitLab 创建 Release
  • 上传到 Homebrew Tap、Scoop bucket、AUR、Chocolatey、Nix、vLens、Snapcraft……

GoReleaser Pro 是商业版,在开源版(OSS)基础上额外提供:

  • 单二进制授权校验、离线授权文件
  • 拆分发布(--split)、准备-审核-发布-公告分离
  • 单目标构建(--single-target)、按 ID 构建(--id)、nightly 构建
  • 发布后 verify 完整性校验
  • changelog 预览、--soft 检查模式
  • 商业版专属的优先支持

2. 安装与版本信息

将二进制放到 PATH 即可。验证安装:

goreleaser --version

输出示例:

goreleaser-pro: Release engineering, simplified.
https://goreleaser.com/pro

GitVersion:    2.18.1
GitCommit:     47450ce5908844dcfc670efbf19186d8ad88b6d6
GitTreeState:  clean
BuildDate:     2026-09-05T21:07:48Z
BuiltBy:       goreleaser
GoVersion:     go1.27.1
Compiler:      gc
ModuleSum:     unknown
Platform:      darwin/arm64

全局 Flag:

标志说明
-h, --help任意命令后跟 --help 查看帮助
--verbose详细日志模式
-v, --version输出版本信息

3. 授权(License)管理

Pro 版所有"完整"功能需要授权密钥。密钥可通过两种方式提供:

  • 命令行:goreleaser release --key "xxx"
  • 环境变量:export GORELEASER_KEY="xxx"

Snapshot 构建(--snapshot)会跳过授权检查,方便临时试用。

3.1 license-verify — 验证密钥

# 通过参数
goreleaser license-verify -k "你的密钥"

# 通过环境变量
export GORELEASER_KEY="你的密钥"
goreleaser license-verify

成功时输出密钥归属人、所属计划、到期时间等信息。

3.2 license-export — 导出离线授权文件

仅 business 与 enterprise 计划可用。离线授权文件有效期最多 90 天,由官方服务器签名。

# 参数 + 写文件
goreleaser license-export -k "你的密钥" -o goreleaser.key

# 环境变量 + 输出到 stdout
goreleaser license-export -o -

生成的离线文件可放到 CI 的受限环境或断网机器上使用。

3.3 subscribe — 订阅 / 管理订阅

goreleaser subscribe

交互式跳转到官方订阅管理页面。


4. 快速上手(5 分钟跑通)

# 1. 进入你的 Go 项目根目录(需含 go.mod 与 git 仓库)
cd my-go-app

# 2. 生成 .goreleaser.yaml 模板
goreleaser init

# 3. 校验配置是否合法
goreleaser check

# 4. 检查发布所需外部工具(go、upx、nfpm、docker 等)是否齐全
goreleaser healthcheck

# 5. 本地试跑:仅构建,不发布,不校验
goreleaser release --snapshot --clean

成功后会看到类似输出:

• by using this software you agree with its EULA, available at https://goreleaser.com/eula
• running goreleaser v2.18.1
• skipping license check on snapshot
• cleaning distribution directory
• loading environment variables
• getting and validating git state
• setting defaults
• ...
• release succeeded after 12s

产物输出在 ./dist 目录中。


5. 命令行总览

goreleaser [command] [--flags]
命令用途是否 Pro
init生成 .goreleaser.yaml 模板OSS
check校验配置文件OSS(--soft 需 Pro)
healthcheck检查依赖工具是否在 $PATHOSS
jsonschema输出 JSON Schema(用于编辑器校验/补全)OSS
build只构建二进制(不打包、不发布)OSS(--single-target、--id 需 Pro)
release完整发布(构建 + 打包 + 签名 + 发布 + 公告)Pro 需授权(非 snapshot)
publish发布由 --prepare / --split 准备好的产物Pro
announce公告已发布版本Pro
continue续跑被中断的发布Pro
verify重新下载产物并校验完整性Pro
changelog预览即将发布的 changelogPro
license-export导出离线授权文件Pro
license-verify校验密钥Pro
subscribe订阅 / 管理订阅Pro
completion生成 Shell 自动补全脚本OSS

6. 命令详解

6.1 init — 生成配置

goreleaser init [--flags]

在当前目录生成一份 .goreleaser.yaml 模板。

标志说明
-f, --config配置文件路径(默认 .goreleaser.yaml)
-l, --language项目语言,目前仅 go
--verbose详细日志

6.2 check — 校验配置

goreleaser check [configuration files] [--flags]

可同时传入多个配置文件进行检查。默认严格模式,遇到错误立即失败。

标志说明
-q, --quiet静默模式:无输出
--softPro:仅在有语法错误时退出码 1,否则返回 0;常用于 CI 的"软校验"
--debug打印最终合并后的完整配置
--deprecated只显示已弃用项警告
--strict严格模式
--verbose详细日志

6.3 healthcheck — 检查依赖工具

goreleaser healthcheck [--flags]

检查 .goreleaser.yaml 中引用到的所有外部命令(go、upx、docker、nfpm、podman、cosign、signify、gpg、snapcraft、flatpak、docker-buildx 等)是否在 $PATH 中。任何一个缺失则退出码 1。

标志说明
-f, --config配置文件路径
-q, --quiet静默模式
--timeout超时,默认 5m

6.4 jsonschema — 输出 JSON Schema

goreleaser jsonschema [--flags]

将 GoReleaser 配置文件对应的 JSON Schema 输出到 stdout 或文件。可用于 IDE(VSCode、JetBrains)的 YAML 自动补全与校验。

标志说明
-o, --output输出文件(- 表示 stdout)
--option输出哪一套 schema:release / build / single-target,默认 release
--indent缩进美化

6.5 build — 只构建二进制

goreleaser build [--flags]

只完成 go build 阶段,不打包、不签名、不发布。常用于 Makefile 或本地调试。

标志说明
--auto-snapshot仓库脏时自动启用 --snapshot
--clean构建前清空 dist/
-f, --config配置文件路径
--idPro:只构建指定 ID(可重复使用),隐含 --skip=publish
-o, --output把构建出的二进制拷贝到指定路径(仅在 --single-target 且单 ID 时生效)
-p, --parallelism并发数,默认 CPU 核数
--single-targetPro:只构建当前 GOOS/GOARCH,隐含 --skip=publish
--skip跳过阶段,可选:after, before, before-publish, post-hooks, pre-hooks, report-sizes, validate
--snapshotsnapshot 构建,跳过所有校验
--timeout超时,默认 1h
--verbose详细日志

--single-target 时可用 TARGET 或 GOOS / GOARCH / GOARM / GOAMD64 / GOARM64 / GORISCV64 / GO386 / GOPPC64 / GOMIPS / GOMIPS64 环境变量指定目标,未设置则取当前机器。


6.6 release — 完整发布

goreleaser release [--flags]

最核心的命令。一次跑完所有阶段:构建 → 归档 → 打包(deb/rpm/dmg/pkg/msi…)→ 签名 → SBOM → 推送到所有配置的 publishers → 创建 GitHub/GitLab Release → 公告。

标志说明
--auto-snapshot仓库脏时自动 --snapshot
--clean先清空 dist/
-f, --config配置文件路径
--draft创建为草稿 Release(覆盖 release.draft)
--fail-fast首个错误即中止发布
--idPro:只构建指定 ID(可多次),隐含 --skip=publish
-k, --keyPro:授权密钥(也可由 GORELEASER_KEY 提供)
--nightlyPro:生成 nightly 构建,发布到支持的渠道,隐含 --skip=announce,validate
-p, --parallelism并发数,默认 CPU 核数
--preparePro:只准备(构建 + 归档 + 打包 + 签名),不发布/公告;之后用 publish / announce 续跑
--release-footer从 markdown 文件加载自定义 Release Notes 页脚
--release-footer-tmpl同上,但使用 Go 模板
--release-header自定义 Release Notes 页眉
--release-header-tmpl模板版页眉
--release-notes用自定义 markdown 完全替换自动 changelog
--release-notes-tmpl模板版 Release Notes
--single-targetPro:只构建当前平台,隐含 --skip=publish
--skip跳过阶段,完整列表见第 8 节
--snapshotsnapshot 模式,跳过授权检查且不发布
--splitPro:将构建拆成多份(按构建 ID / 矩阵),需后续 --merge,隐含 --prepare
--timeout超时,默认 1h
--verbose详细日志

典型调用:

# 1. 正式发布(需授权)
export GORELEASER_KEY="..."
goreleaser release --clean

# 2. 拆分发布:大矩阵 + 多个 runner 各跑一部分
goreleaser release --split --clean

# 3. 准备但不发布
goreleaser release --prepare --clean

# 4. 仅发布到 Homebrew、跳过 Docker
goreleaser release --skip=docker,dockerhub

# 5. Draft
goreleaser release --draft

# 6. Nightly
goreleaser release --nightly

6.7 publish — 发布已准备的产物

goreleaser publish [--flags]

搭配 goreleaser release --prepare 或 goreleaser release --split 使用。环境变量在 publish 阶段会重新求值,请确保同样可用。

Pro only

标志说明
-d, --dist待发布的 dist 目录(默认 ./dist)
-k, --key授权密钥
--merge合并来自 --split 的多份产物(需要所有分片都已就位)
-p, --parallelism并发数
--skip可跳过:after, archive, aur, aur-source, before, before-publish, chocolatey, cloudsmith, dmg, docker, dockerhub, flatpak, fury, homebrew, iru, ko, makeself, mcp, msi, nfpm, nix, notarize, npm, nsis, pkg, report-sizes, sbom, scoop, sign, snapcraft, srpm, verify, winget
--timeout超时,默认 30m
--verbose详细日志
# 典型用法
goreleaser release --prepare --clean    # 阶段 1
# ...人工审核 dist/...
goreleaser publish                       # 阶段 2
goreleaser announce                      # 阶段 3

6.8 announce — 公告已发布的版本

goreleaser announce [--flags]

Pro only

在 release --prepare → publish 之后再调用。GoReleaser 配置不会重新解析——若 dist 路径不是默认的 ./dist,需要显式指定。

标志说明
-d, --distdist 目录
-k, --key授权密钥
--merge合并 --split 多分片
-p, --parallelism并发数
--skip同 publish
--timeout超时,默认 30m
--verbose详细日志

6.9 continue — 续跑已中断的发布

goreleaser continue [--flags]

Pro only

当 release 因网络抖动、CI 资源被回收等原因中断后,可基于 dist/metadata.json(含 ctx.json 与 artifacts.json)续跑。环境变量会重新求值。

标志说明
-d, --distdist 目录
-k, --key授权密钥
--merge合并 --split 多分片
-p, --parallelism并发数
--skip可跳过:after, verify
--timeout超时,默认 30m
--verbose详细日志

6.10 verify — 校验已发布产物完整性

goreleaser verify [--flags]

Pro only

把已发布的制品重新下载下来,逐个对比:

  • 校验和 vs checksums.txt(以及本地记录的)
  • 跑配置中定义的签名校验命令(cosign / gpg / signify 等)

verify pipe 也会在 release 与 publish 末尾自动执行。

标志说明
-d, --distdist 目录(默认 ./dist)
-k, --key授权密钥
-p, --parallelism并发数
--timeout超时,默认 30m
--verbose详细日志

6.11 changelog — 预览变更日志

goreleaser changelog [--flags]

Pro only

读取最新 tag 到当前 commit 的变更,渲染 .goreleaser.yaml 中 changelog 段配置好的模板。不发布、不校验。

标志说明
-f, --config配置文件路径
-o, --output保存到文件;不指定则输出 stdout
--timeout超时,默认 1m
--verbose详细日志
# 输出到 stdout
goreleaser changelog

# 保存到文件
goreleaser changelog -o CHANGELOG.preview.md

6.12 subscribe — 订阅 / 管理订阅

goreleaser subscribe

引导用户进入官方订阅管理页。Pro 用户可在此升级/降级/续费。


6.13 completion — 生成 Shell 自动补全

goreleaser completion <shell>

支持 bash / zsh / fish / powershell。

# bash
goreleaser completion bash | sudo tee /etc/bash_completion.d/goreleaser > /dev/null

# zsh
goreleaser completion zsh > "${fpath[1]}/_goreleaser"

# fish
goreleaser completion fish | source

7. Pro 专属能力详解

7.1 --id — 只构建指定 ID

.goreleaser.yaml 可定义多个 builds 块,每个有 id:

builds:
  - id: cli
    main: ./cmd/cli
    binary: mycli
  - id: agent
    main: ./cmd/agent
    binary: myagent
# 只构建 cli
goreleaser build --id cli

# 构建 cli 和 agent
goreleaser build --id cli --id agent

隐含 --skip=publish。

7.2 --single-target — 仅当前平台

写一次 .goreleaser.yaml 覆盖所有目标,本地试跑不必等全矩阵:

goreleaser build --single-target
# 或在 release 模式下
goreleaser release --single-target --snapshot

可用环境变量(与 go build 兼容):

  • TARGET(形如 linux_amd64_v1)
  • GOOS / GOARCH
  • GOARM / GOAMD64 / GOARM64 / GORISCV64 / GO386 / GOPPC64 / GOMIPS / GOMIPS64

未设置时取当前机器。

7.3 --nightly — 每夜构建

goreleaser release --nightly

仅对支持 nightly 的目标生效(Docker、Homebrew 等),隐含 --skip=announce,validate。

7.4 --prepare + publish + announce — 准备 / 审核 / 发布三段式

适合对生产发布有人工审核环节或多环境(测试 → 灰度 → 正式)的团队:

# CI 跑构建 + 打包(可能 20+ 分钟)
goreleaser release --prepare --clean

# 人工审核 dist/ 目录下的产物
ls dist/

# 发布到所有 publisher
goreleaser publish

# 单独发公告
goreleaser announce

优势:环境变量在每个阶段会重新求值,可分别用不同凭据。

7.5 --split + --merge — 拆分并行发布

构建矩阵很大时(几十个 OS/Arch 组合),单台 runner 跑不动。--split 按 ID/构建切片分给多个 runner 并行跑,最后一台用 --merge 合并发布。

# runner 1
goreleaser release --split --clean --id a

# runner 2
goreleaser release --split --clean --id b

# ...所有分片都跑完后:
goreleaser publish --merge
# 或
goreleaser announce --merge
# 或
goreleaser continue --merge

7.6 --verify — 完整性自检

发布后任何时候可重跑:

goreleaser verify

会自动从已配置的上游(GitHub Release、对象存储等)拉回所有 artifact,比对 checksum,跑签名校验命令。

7.7 changelog 预览

发布前先看看 changelog 写得好不好:

goreleaser changelog
# 或
goreleaser changelog -o preview.md

7.8 check --soft — 软校验

goreleaser check --soft

只在配置存在语法错误时返回非零;弃用项警告不算失败。CI 中可在合并前放行。

7.9 离线授权

把密钥导出成 90 天有效的签名文件,用于完全离线环境:

goreleaser license-export -k "$GORELEASER_KEY" -o /etc/goreleaser/license.key
# 之后把 GORELEASER_KEY_PATH 指向它,或直接放在默认搜索路径

8. 打包与镜像格式详解(dmg / pkg / msi / nsis / deb / rpm …)

GoReleaser 在 release 流程中,先把每个 build 的二进制放进 archives 归档(tar.gz / zip),再交给下面这些"打包器"生成可直接分发的安装介质,最后才推到对应的 publisher(Homebrew Tap、Scoop bucket、AUR、Nix、Chocolatey…)。

以下 8.1–8.19 各小节均给出:功能 / 默认跳过值(即 --skip 名称)/ 平台 / 是否 Pro / .goreleaser.yaml 最小可用示例 / 常见定制点 / 故障排查。
想"全部启用"的最快办法:把 skip 全部留空,让配置里的块自然生效。

8.1 archives — 通用归档(前置环节)

虽然不是"安装包",但所有打包器都依赖 archives 输出的 .tar.gz / .zip,所以必须先理解。

archives:
  - id: default
    formats: [tar.gz]            # 可选 tar.gz / zip / gz / bz2 / xz / zst
    name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
    files:
      - LICENSE
      - README.md
      - src: ./completions/*
        dst: completions       # 把补全脚本一起打包
    builds_info:
      group: root
      owner: root
      mode: 0644
    mod_timestamp: '{{ .CommitTimestamp }}'  # 复现构建
    rlcp: true                                  # 复制 symlink
  • 通过 --skip=archive 可整体跳过。
  • name_template 是大部分打包器默认查找的命名模板。

8.2 nfpms — deb / rpm / apk(Pro)

默认 --skip 名称:nfpm
Pro only

使用 nfpm 同时打包 Debian、Red Hat、Arch 三大家族的二进制包。

最小示例:

nfpms:
  - id: packages
    package_name: mycli
    file_name_template: "{{ .ConventionalFileName }}"
    formats:
      - deb
      - rpm
      - apk
    dependencies:
      - git
    recommends:
      - bash
    suggests:
      - zsh
    replaces:
      - myapp
    conflicts:
      - myapp-old
    section: utils
    priority: optional
    maintainer: "You <you@example.com>"
    description: |
      My awesome CLI does X, Y, Z.
      Long description spanning multiple lines.
    homepage: "https://example.com"
    license: MIT
    vendor: Acme Inc.
    changelog: "changelog.tmpl"   # 可选;可指向模板
    contents:
      - src: ./completions/mycli.bash
        dst: /etc/bash_completion.d/mycli
      - src: ./config/mycli.yaml
        dst: /etc/mycli/config.yaml
        type: config|noreplace
    scripts:
      preinstall:  scripts/preinstall.sh
      postinstall: scripts/postinstall.sh
      preremove:   scripts/preremove.sh
      postremove:  scripts/postremove.sh
    overrides:
      deb:
        dependencies:
          - libc6
      rpm:
        dependencies:
          - glibc
    signature:
      key_file: '{{ .Env.GPG_KEY_PATH }}'
      type: gpg
    meta: true                        # 把构建信息写进 .nfpm.yaml

常见场景:

  • 只打 deb:formats: [deb]
  • 区分维护者:每个 id 单独配置
  • 通过 contents 注入 systemd unit / 默认配置

跳过:--skip=nfpm 或环境变量 NFPM_SKIP=true

前置依赖:nfpm CLI 在 $PATH(goreleaser healthcheck 会自动检查)。

8.3 dmg — macOS DMG 镜像(Pro)

默认 --skip 名称:dmg
Pro only

为 macOS 输出可拖拽安装的 .dmg 卷镜像(背景图、窗口布局可定制)。

dmg:
  - id: default
    title: "{{ .ProjectName }} {{ .Version }}"
    icon: build/icon.icns
    background: build/dmg-background.png
    window:
      width: 540
      height: 380
    contents:
      - x: 140
        y: 200
        type: file
        path: mycli
      - x: 380
        y: 200
        type: link
        path: /Applications
    sign: false                      # 设为 true 触发 Apple 公证
    format: UDZO                     # UDRO / UDZO / ULFO / UDBZ
    additional_params: []            # 透传给 hdiutil

要点:

  • 镜像里第一个 file 通常是你的 .app Bundle 或单个二进制;link 一般指 /Applications。
  • sign: true 时会调用 codesign 并把 DMG 推去 Apple 公证(需 notarize 段配置)。
  • 想做"漂亮的背景 + 排版",把 PNG 放 background。

跳过:--skip=dmg

8.4 pkg — macOS PKG 安装包(Pro)

默认 --skip 名称:pkg
Pro only

适合需要"安装到 /usr/local/bin"、预/后置脚本、或要分发到 MDM 的企业场景。

pkg:
  - id: default
    package_name: mycli
    file_name_template: "{{ .ConventionalFileName }}"
    homepage: "https://example.com"
    maintainer: "You <you@example.com>"
    description: "My awesome CLI"
    license: MIT
    formats:                         # 默认 [pkg]
      - pkg
    dependencies:
      - name: "com.example.dependency"
        version: "1.0.0"
        package: "com.example.other"
    install_scripts:
      preinstall:  scripts/pkg-preinstall.sh
      postinstall: scripts/pkg-postinstall.sh
    files:
      src: ./bin/mycli
      dst: /usr/local/bin/mycli
      mode: 0755
    publish: true                    # 让 pkg 也能被当作发布产物推上去
    signature:                       # macOS flat / chain 安装
      type: flat
      identifier: "com.example.mycli"

跳过:--skip=pkg

8.5 notarize — Apple 公证(Pro)

默认 --skip 名称:notarize

给 .app / .dmg / .pkg 做 Apple Notarization,绕过 Gatekeeper。

notarize:
  - id: default
    hosts:
      - appleId:       you@example.com
        appleIdPassword: "{{ .Env.APP_SPECIFIC_PASSWORD }}"
        teamId:        ABCDE12345
    artifact:        # 留空则对所有 dmg/pkg 生效
      - mycli.dmg
    sign: true
    staple: true
    timeout: 30m

跳过:--skip=notarize

8.6 msi — Windows MSI 安装包(Pro)

默认 --skip 名称:msi
Pro only

基于 go-msi / WiX 工具集,输出企业可静默安装的 .msi。

msi:
  - id: default
    wix:                       # 兼容 go-msi 旧版
      - "{{ .Env.WIX }}"
    namespace: "com.example.mycli"
    name: "My CLI"
    manufacturer: "Acme Inc."
    description: "My awesome CLI"
    homepage: "https://example.com"
    license: LICENSE
    arch: amd64                # amd64 / arm64
    program_files:
      - id: mycli
        directory: INSTALLDIR
        install: []
    wxs:
      - dir: scripts/installer.wxs
    extensions:
      - wix_ui
      - wixUtilExtension
    install_scope: perMachine  # perMachine / perUser
    install_command: ""
    upgrade_command: ""
    no_patch: false

要点:

  • 需要 wix 二进制在 $PATH(goreleaser healthcheck 提示)。
  • 通过 goreleaser-msi 子包可在纯 Go 流程中输出。

跳过:--skip=msi

8.7 nsis — Windows NSIS 安装包(Pro)

默认 --skip 名称:nsis

比 MSI 更轻量、可定制 UI 的 Windows 安装器。

nsis:
  - id: default
    template: scripts/installer.nsi
    header_image: build/nsis-header.bmp
    sidebar_image: build/nsis-sidebar.bmp
    title: "My CLI {{ .Version }}"
    publisher: "Acme Inc."
    install_mode: perMachine
    languages: [English, German, French]
    uninstall_display_name: "My CLI"
    installer_icon: build/installer.ico
    install_dir_key: "MyCompany\MyCLI"
    install_dir: '$PROGRAMFILES64\{{ .ProjectName }}'

跳过:--skip=nsis

8.8 aur / aur-source — Arch User Repository(Pro)

默认 --skip 名称:aur / aur-source
Pro only

自动在 AUR 仓库里创建/更新 PKGBUILD(二进制包 + 源码包两份)。

aur:
  - homepage: "https://example.com"
    description: "My awesome CLI"
    maintainers:
      - "Your Name <you@example.com>"
    package: |                     # 自定义 PKGBUILD 模板
      # Maintainer: {{ .Maintainer }}
      pkgname={{ .PackageName }}
      ...
    conflicts:
      - myapp
    depends:
      - git
    optdepends:
      - zsh: "Zsh completions"
    provides:
      - mycli
    replaces:
      - myapp
    commit_author:
      name: goreleaserbot
      email: bot@example.com
    commit_msg_template: "Update to {{ .Tag }}"
    private: false

跳过:--skip=aur,aur-source

8.9 snap / snapcraft — Ubuntu Snap(Pro)

默认 --skip 名称:snapcraft
Pro only

snapcraft:
  - name: mycli
    title: My CLI
    summary: Short one-liner
    description: |
      Long description.
    base: core22
    grade: stable                  # stable / devel
    confinement: strict           # strict / devmode / classic
    apps:
      mycli:
        command: bin/mycli
        plugs: [network, home]
    plugs:
      home:
        read: [$HOME/.config/mycli]
    publish: true
    files:
      - src: ./bin/mycli
        dst: bin/mycli
    layout:
      /usr/bin/mycli:
        bind-file: $SNAP/usr/bin/mycli

需 snapcraft CLI + 已登录 Snap Store。

跳过:--skip=snapcraft

8.10 flatpak — Linux Flatpak(Pro)

默认 --skip 名称:flatpak
Pro only

flatpak:
  - id: mycli
    maintainer: "Acme Inc. <ops@example.com>"
    categories: [Development, Utility]
    description: |
      Long description.
    icon: build/icon.png
    base: org.freedesktop.Platform//23.08
    runtime: org.freedesktop.Sdk//23.08
    sdk: org.freedesktop.Sdk//23.08
    command: mycli
    finish_args: |
      --share=network
      --filesystem=home
    files:
      - src: ./bin/mycli
        dest: bin/mycli
    publish: true

跳过:--skip=flatpak

8.11 scoop — Windows Scoop bucket(Pro)

默认 --skip 名称:scoop
Pro only

把 manifest 推到你的 scoop-bucket 仓库,用户 scoop install mycli 即可。

scoop:
  bucket:
    owner: your-org
    name: scoop-bucket
  homepage: "https://example.com"
  description: My awesome CLI
  license: MIT
  persist_data: true
  shortcuts:
    - "mycli.exe"
  url_template: "https://github.com/your-org/mycli/releases/download/{{ .Tag }}/{{ .ArtifactName }}"
  hash:
    url_template: "https://github.com/your-org/mycli/releases/download/{{ .Tag }}/checksums.txt"
    algorithm: sha256
  checkver:
    github:
      user: your-org
      use_tag: true
  autoupdate:
    url_template: "https://github.com/your-org/mycli/releases/download/{{ .Tag }}/{{ .ArtifactName }}"

需 SCOOP_BUCKET_GITHUB_TOKEN 环境变量。

跳过:--skip=scoop

8.12 winget — Windows Package Manager(Pro)

默认 --skip 名称:winget
Pro only

输出 winget create 需要的 manifest,发 PR 到 microsoft/winget-pkgs。

winget:
  - name: MyCLI
    publisher: Acme Inc.
    license: MIT
    short_description: My awesome CLI
    manifest_path: winget
    publisher_url: "https://example.com"
    publisher_support_url: "https://example.com/support"
    author: Acme Inc.
    copyright: "Copyright (c) Acme Inc."
    description: "Long description."
    homepage: "https://example.com"
    package_identifier: Acme.MyCLI
    tags:
      - command-line
    release_notes_url: "https://example.com/changelog"
    release_date: "{{ .CommitDate }}"
    installers:
      - id: mycli-amd64
        architecture: x64
        installer_type: zip
        installer_url: "https://github.com/your-org/mycli/releases/download/{{ .Tag }}/{{ .ArtifactName }}"
        installer_sha256: "{{ .Sha256 }}"
        manifest: scripts/installer.yaml
    default_locale: en-US
    locales:
      en-US:
        publisher: Acme Inc.
        publisher_url: "https://example.com"
        package_name: MyCLI
        license: MIT
        short_description: My awesome CLI
        tags: [command-line]
        release_notes: CHANGELOG.md

跳过:--skip=winget

8.13 chocolatey — Windows Chocolatey(Pro)

默认 --skip 名称:chocolatey
Pro only

chocolatey:
  - name: mycli
    title: My CLI
    authors: Acme Inc.
    project_url: "https://example.com"
    project_source_url: "https://github.com/your-org/mycli"
    copyright: "© Acme Inc."
    license_url: "https://example.com/license"
    docs_url: "https://example.com/docs"
    bug_tracker_url: "https://github.com/your-org/mycli/issues"
    mailing_list_url: ""
    icon_url: "https://example.com/icon.png"
    require_license_acceptance: false
    description: |
      Long description.
    summary: One-liner
    release_notes: "https://github.com/your-org/mycli/releases/tag/{{ .Tag }}"
    api_key:
      source: env:CHOCO_API_KEY
    source:
      - "https://example.com/mycli.install"
    version_source: ""
    priority: 0
    architecture: x64
    url_template: "https://github.com/your-org/mycli/releases/download/{{ .Tag }}/{{ .ArtifactName }}"

跳过:--skip=chocolatey

8.14 nix — Nix(Pro)

默认 --skip 名称:nix
Pro only

把 default.nix 推到 nixpkgs 仓库或自建 nix flake 仓库。

nix:
  - name: mycli
    path: nix/
    repository:
      owner: your-org
      name: nixpkgs
    branch: master
    homepage: "https://example.com"
    description: My awesome CLI
    license: mit
    license_files:
      - LICENSE
    extra_files:
      - src: ./nix/default.nix
        dst: default.nix
    commit_author:
      name: goreleaserbot
      email: bot@example.com
    commit_msg_template: "mycli: {{ .Tag }}"

跳过:--skip=nix

8.15 makeself — 自解压安装器(Pro)

默认 --skip 名称:makeself

跨平台 self-extracting installer(基于 makeself)。

makeself:
  - id: mycli
    script: scripts/install.sh
    name: "mycli-{{ .Version }}-{{ .Os }}-{{ .Arch }}.run"
    label: "My CLI {{ .Version }}"

跳过:--skip=makeself

8.16 docker_manifests — 多架构 Docker manifest(Pro)

默认 --skip 名称:docker / dockerhub

把多个 dockers 镜像合成一个多架构 manifest。

dockers:
  - image_templates:
      - "ghcr.io/your-org/mycli:{{ .Tag }}-amd64"
      - "ghcr.io/your-org/mycli:latest-amd64"
    dockerfile: Dockerfile
    use: buildx
    build_flag_templates:
      - "--platform=linux/amd64"
    skip_push: false
  - image_templates:
      - "ghcr.io/your-org/mycli:{{ .Tag }}-arm64v8"
      - "ghcr.io/your-org/mycli:latest-arm64v8"
    dockerfile: Dockerfile
    use: buildx
    build_flag_templates:
      - "--platform=linux/arm64/v8"

docker_manifests:
  - name_template: "ghcr.io/your-org/mycli:{{ .Tag }}"
    image_templates:
      - "ghcr.io/your-org/mycli:{{ .Tag }}-amd64"
      - "ghcr.io/your-org/mycli:{{ .Tag }}-arm64v8"
    skip_push: false

跳过:--skip=docker,dockerhub(同时跳过构建+manifest)

8.17 ko — Go → 容器(Pro)

默认 --skip 名称:ko

无需 Dockerfile,直接用 ko build 编译并发布 OCI 镜像。

kos:
  - id: mycli
    build:
      main: ./cmd/mycli
    base: gcr.io/distroless/static-debian12
    image: "ghcr.io/your-org/mycli"
    tags:
      - "{{ .Tag }}"
      - latest
    labels:
      org.opencontainers.image.source: "https://github.com/your-org/mycli"
    mounts:
      - type: tmpfs
        destination: /tmp
    platforms:
      - linux/amd64
      - linux/arm64
    sbom: spdx
    reproducible: true
    preserve_import_paths: false

跳过:--skip=ko

8.18 sboms — 软件物料清单(Pro)

虽然不是"安装包",但通常伴随打包流程:生成 SPDX / CycloneDX 报告。

sboms:
  - id: archive-sbom
    artifacts: archive            # binary / archive / package / all
    documents:
      - "${artifact}.spdx.json"
      - "${artifact}.cdx.json"
    cmd: cyclonedx-gomod          # 或 syft
    args: ["-output", "spdx-json", "-output", "cyclonedx-json"]

跳过:--skip=sbom

8.19 一次启用所有打包格式的最小 config 骨架

project_name: mycli

builds:
  - id: mycli
    main: ./cmd/mycli
    binary: mycli
    goos: [linux, darwin, windows]
    goarch: [amd64, arm64]

archives:
  - formats: [tar.gz, zip]

# 跨发行版
nfpms:
  - id: pkg
    package_name: mycli
    formats: [deb, rpm, apk]
    maintainer: "You <you@example.com>"

# macOS
dmg:
  - id: default
    title: "{{ .ProjectName }} {{ .Version }}"
pkg:
  - id: default
    package_name: mycli

# Windows
msi:
  - id: default
    wix: ["{{ .Env.WIX }}"]
nsis:
  - id: default
    template: scripts/installer.nsi
scoop:
  bucket: { owner: your-org, name: scoop-bucket }
winget:
  - name: MyCLI
    package_identifier: Acme.MyCLI
chocolatey:
  - name: mycli

# Linux 桌面分发
snapcraft:
  - name: mycli
    confinement: strict
flatpak:
  - id: mycli
    base: org.freedesktop.Platform//23.08
aur:
  - homepage: "https://example.com"
    description: My awesome CLI

# 通用
nix:
  - name: mycli
    repository: { owner: your-org, name: nixpkgs }
makeself:
  - id: mycli
    script: scripts/install.sh

release:
  prerelease: auto
  draft: false

# 如果只想本地试跑不要推任何打包
# goreleaser release --snapshot --skip=nfpm,dmg,pkg,msi,nsis,scoop,winget,chocolatey,snapcraft,flatpak,aur,nix,makeself

8.20 只想保留某几种、跳过其余

# 只出 deb/rpm/apk 和 homebrew,其它全跳
goreleaser release --skip=dmg,pkg,notarize,msi,nsis,scoop,winget,chocolatey,snapcraft,flatpak,aur,nix,makeself,ko,sbom

8.21 常见故障

现象原因 / 解决
nfpm: command not foundbrew install goreleaser/tap/nfpm 或 go install github.com/goreleaser/nfpm/v2/cmd/nfpm@latest
hdiutil: not found在非 macOS 上跑 dmg;需 macOS runner
wix: command not found装 WiX 3.x,并 export WIX=/path/to/wix
codesign failed缺 Developer ID Application 证书;先 security find-identity -v
snapcraft login required跑 snapcraft login;CI 上用 SNAPCRAFT_STORE_CREDENTIALS
aur: 404 not foundaur.publishers 的 aur 没在配置里;先在 AUR 手动建空仓库
flatpak-builder not foundapt install flatpak-builder
DMG/PKG 产物很大关闭 format: UDBZ、去掉冗余 contents
winget PR 失败License / publisher URL 与 manifest 不一致导致 winget validate 拒绝

9. --skip 可跳过阶段清单

release 命令 --skip 接受以下值(用逗号分隔多个):

值阶段
after发布后钩子(release.hooks.post)
announce创建 GitHub/GitLab Release + Twitter 等公告
archive生成 tar/zip 归档
aur / aur-source发布到 Arch AUR
before / before-publish / post-hooks / pre-hooks钩子
chocolateyChocolatey 包
cloudsmithCloudsmith 仓库
dmgmacOS DMG 镜像
docker / dockerhubDocker 镜像
flatpakFlatpak
furyRubyGems 镜像
homebrewHomebrew Tap
iruiRu(GitHub 指标)
koko(Go → 容器)
makeselfmakeself 自解压安装包
mcpMCP(Model Context Protocol)发布
msiWindows MSI
nfpmnfpm(deb/rpm/apk 等)
nixNix
notarizeApple 公证
npmNPM 包
nsisNSIS 安装包
pkgmacOS PKG
publish所有 publisher
report-sizes上报产物大小
sbom生成 SBOM
scoopScoop bucket
sign签名
snapcraftSnapcraft
srpmSource RPM
validate前置校验
verify完整性校验
wingetwinget manifest

build / publish / announce / continue 命令的 --skip 是其子集(详见各命令章节)。


10. 典型工作流

10.1 开源小项目:tag → 推 GitHub

git tag v1.2.3
git push origin v1.2.3

export GORELEASER_KEY="..."
goreleaser release --clean

10.2 本地 snapshot 试运行

goreleaser release --snapshot --clean
ls dist/

10.3 仅构建当前平台给同事用

goreleaser build --single-target --output ./bin/mycli

10.4 大矩阵 + 拆分发布

# 分片
goreleaser release --split --id linux --clean
goreleaser release --split --id darwin --clean
goreleaser release --split --id windows --clean

# 合并发布
goreleaser publish --merge
goreleaser announce --merge

10.5 严格发布门禁

# 软校验,不阻断 MR
goreleaser check --soft

# PR 合并后,main 上 tag 触发正式发布
goreleaser release --clean --fail-fast

10.6 中断后续跑

# 第一次跑到 50% 被 CI 杀掉
goreleaser release --clean

# 重新跑,自动从 dist/metadata.json 续跑未完成阶段
goreleaser continue

10.7 草稿发布 + 团队 review

goreleaser release --draft
# ...人工 review GitHub Draft...
# 取消 draft 后让 CI 再推一次
goreleaser release --clean

10.8 完全离线 CI

# 在能上网的机器导出
goreleaser license-export -k "$KEY" -o license.key
scp license.key ci-runner:/etc/goreleaser/

# ci-runner 上
export GORELEASER_KEY_PATH=/etc/goreleaser/license.key
goreleaser release --clean

11. 故障排查与常用技巧

11.1 找不到 git tag

error=current tag v1.2.3 was not found in the repository

解决:先 git tag v1.2.3 && git push origin v1.2.3,或临时用 --snapshot 跳过校验。

11.2 猜不到 project name

error=project name: couldn't guess project_name, please add it to your config

解决:在 .goreleaser.yaml 顶层显式写:

project_name: mycli

或在 go.mod 中确保 module 字段标准。

11.3 发布失败但 dist/ 里有产物

CI 网络问题常见。dist/metadata.json 包含 ctx.json + artifacts.json,重跑:

goreleaser continue

或跳过某些阶段:

goreleaser continue --skip=verify

11.4 Pro 报错 missing GoReleaser Pro key

command failed error=missing GoReleaser Pro key, please provide one with --key or using the GORELEASER_KEY environment variable

解决:

export GORELEASER_KEY="你的密钥"
# 或
goreleaser release --key "你的密钥"
# 或临时试用
goreleaser release --snapshot

11.5 外部工具缺失

goreleaser healthcheck

按提示 brew install docker nfpm 或 apt install rpm 即可。

11.6 自定义 Release Notes 完全覆盖

goreleaser release --release-notes NOTES.md

模板版(支持 {{ .TagName }} 等变量):

goreleaser release --release-notes-tmpl NOTES.tmpl

页眉页脚同理:--release-header / --release-header-tmpl / --release-footer / --release-footer-tmpl。

11.7 调试最终生效的配置

goreleaser check --debug

把合并所有包含文件后的最终配置打出来,方便排查 includes 引入的差异。

11.8 IDE 自动补全配置

goreleaser jsonschema --indent --option release > goreleaser.schema.json
# 放进项目根,VSCode 配合 "JSON Schema" 设置自动识别 .goreleaser.yaml

11.9 提高并发

构建/打包阶段对 CPU 不敏感,但 IO 多,可调大:

goreleaser release --parallelism 8

11.10 查看详细日志

goreleaser release --verbose --clean 2>&1 | tee release.log

12. 附录

附录 A:常用环境变量

变量用途
GORELEASER_KEYPro 授权密钥
GITHUB_TOKEN / GITLAB_TOKEN / GITEA_TOKEN创建 Release 用
DOCKER_USERNAME / DOCKER_PASSWORDDocker 登录凭据
HOMEBREW_TAP_GITHUB_TOKEN推 Homebrew Tap
NPM_TOKEN发到 npm
SCOOP_BUCKET_GITHUB_TOKEN推 Scoop bucket
GOOS / GOARCH / ...--single-target 时使用
TARGET--single-target 目标字符串

附录 B:常见 .goreleaser.yaml 结构骨架

project_name: mycli

builds:
  - id: mycli
    main: ./cmd/mycli
    binary: mycli
    env:
      - CGO_ENABLED=0
    goos:
      - linux
      - darwin
      - windows
    goarch:
      - amd64
      - arm64

archives:
  - formats: [tar.gz]
    name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"

nfpms:
  - id: packages
    package_name: mycli
    formats:
      - deb
      - rpm
      - apk
    maintainer: "You <you@example.com>"
    description: "My awesome CLI"
    homepage: "https://example.com"
    license: MIT

brews:
  - repository:
      owner: your-org
      name: homebrew-tap
    homepage: "https://example.com"
    description: "My awesome CLI"

scoop:
  bucket:
    owner: your-org
    name: scoop-bucket

release:
  draft: false
  prerelease: auto
  name_template: "{{ .ProjectName }} v{{ .Version }}"

changelog:
  sort: asc
  use: github
  filters:
    exclude:
      - "^docs:"
      - "^test:"

signs:
  - cmd: cosign
    artifacts: all

docker_signs:
  - cmd: cosign
    artifacts: all

sboms:
  - id: sbom
    artifacts: archive

评论

推荐阅读

订阅邮件

订阅更新,及时收到最新文章。

作者