GoReleaser(Pro) 全功能使用手册
适用版本:GoReleaser Pro v2.18.1(GitCommit
47450ce5908844dcfc670efbf19186d8ad88b6d6)
平台:darwin/arm64(Go 1.27.1 构建)
官方文档:https://goreleaser.com
目录
- 简介与定位
- 安装与版本信息
- 授权(License)管理
- 快速上手(5 分钟跑通)
- 命令行总览
- 命令详解
- Pro 专属能力详解
- 打包与镜像格式详解(dmg / pkg / msi / nsis / deb / rpm …)
- 8.1 archives — 通用归档(前置环节)
- 8.2 nfpms — deb / rpm / apk(Pro)
- 8.3 dmg — macOS DMG 镜像(Pro)
- 8.4 pkg — macOS PKG 安装包(Pro)
- 8.5 notarize — Apple 公证(Pro)
- 8.6 msi — Windows MSI 安装包(Pro)
- 8.7 nsis — Windows NSIS 安装包(Pro)
- 8.8 aur / aur-source — Arch User Repository(Pro)
- 8.9 snap / snapcraft — Ubuntu Snap(Pro)
- 8.10 flatpak — Linux Flatpak(Pro)
- 8.11 scoop — Windows Scoop bucket(Pro)
- 8.12 winget — Windows Package Manager(Pro)
- 8.13 chocolatey — Windows Chocolatey(Pro)
- 8.14 nix — Nix(Pro)
- 8.15 makeself — 自解压安装器(Pro)
- 8.16 docker_manifests — 多架构 Docker manifest(Pro)
- 8.17 ko — Go → 容器(Pro)
- 8.18 sboms — 软件物料清单(Pro)
- 8.19 一次启用所有打包格式的最小 config 骨架
- 8.20 只想保留某几种、跳过其余
- 8.21 常见故障
--skip可跳过阶段清单- 典型工作流
- 故障排查与常用技巧
- 附录
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 | 检查依赖工具是否在 $PATH | OSS |
jsonschema | 输出 JSON Schema(用于编辑器校验/补全) | OSS |
build | 只构建二进制(不打包、不发布) | OSS(--single-target、--id 需 Pro) |
release | 完整发布(构建 + 打包 + 签名 + 发布 + 公告) | Pro 需授权(非 snapshot) |
publish | 发布由 --prepare / --split 准备好的产物 | Pro |
announce | 公告已发布版本 | Pro |
continue | 续跑被中断的发布 | Pro |
verify | 重新下载产物并校验完整性 | Pro |
changelog | 预览即将发布的 changelog | Pro |
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 | 静默模式:无输出 |
--soft | Pro:仅在有语法错误时退出码 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 | 配置文件路径 |
--id | Pro:只构建指定 ID(可重复使用),隐含 --skip=publish |
-o, --output | 把构建出的二进制拷贝到指定路径(仅在 --single-target 且单 ID 时生效) |
-p, --parallelism | 并发数,默认 CPU 核数 |
--single-target | Pro:只构建当前 GOOS/GOARCH,隐含 --skip=publish |
--skip | 跳过阶段,可选:after, before, before-publish, post-hooks, pre-hooks, report-sizes, validate |
--snapshot | snapshot 构建,跳过所有校验 |
--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 | 首个错误即中止发布 |
--id | Pro:只构建指定 ID(可多次),隐含 --skip=publish |
-k, --key | Pro:授权密钥(也可由 GORELEASER_KEY 提供) |
--nightly | Pro:生成 nightly 构建,发布到支持的渠道,隐含 --skip=announce,validate |
-p, --parallelism | 并发数,默认 CPU 核数 |
--prepare | Pro:只准备(构建 + 归档 + 打包 + 签名),不发布/公告;之后用 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-target | Pro:只构建当前平台,隐含 --skip=publish |
--skip | 跳过阶段,完整列表见第 8 节 |
--snapshot | snapshot 模式,跳过授权检查且不发布 |
--split | Pro:将构建拆成多份(按构建 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, --dist | dist 目录 |
-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, --dist | dist 目录 |
-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, --dist | dist 目录(默认 ./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/GOARCHGOARM/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通常是你的.appBundle 或单个二进制;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 found | brew 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 found | aur.publishers 的 aur 没在配置里;先在 AUR 手动建空仓库 |
flatpak-builder not found | apt 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 | 钩子 |
chocolatey | Chocolatey 包 |
cloudsmith | Cloudsmith 仓库 |
dmg | macOS DMG 镜像 |
docker / dockerhub | Docker 镜像 |
flatpak | Flatpak |
fury | RubyGems 镜像 |
homebrew | Homebrew Tap |
iru | iRu(GitHub 指标) |
ko | ko(Go → 容器) |
makeself | makeself 自解压安装包 |
mcp | MCP(Model Context Protocol)发布 |
msi | Windows MSI |
nfpm | nfpm(deb/rpm/apk 等) |
nix | Nix |
notarize | Apple 公证 |
npm | NPM 包 |
nsis | NSIS 安装包 |
pkg | macOS PKG |
publish | 所有 publisher |
report-sizes | 上报产物大小 |
sbom | 生成 SBOM |
scoop | Scoop bucket |
sign | 签名 |
snapcraft | Snapcraft |
srpm | Source RPM |
validate | 前置校验 |
verify | 完整性校验 |
winget | winget 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_KEY | Pro 授权密钥 |
GITHUB_TOKEN / GITLAB_TOKEN / GITEA_TOKEN | 创建 Release 用 |
DOCKER_USERNAME / DOCKER_PASSWORD | Docker 登录凭据 |
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
评论