GoReleaser工具与Go构建技巧
GoReleaser
GoReleaser 的创建是为了解决我们都曾遇到过的一个问题:发布软件很无聊而且容易出错。
为了解决这个问题,我们最终都创建了脚本来自动化工作,并取得了不同程度的成功。
一般来说,这些脚本往往不可重用,并且依赖于许多其他工具——这使得该进程很难在其他机器上运行。
GoReleaser 的目标是让所有这些脚本都过时:不再编写脚本,而是编写一个简单的 YAML 配置文件; 您(通常)只需要一个 goreleaser 二进制文件,而不是许多工具。
然后,您只需运行一个命令即可构建、存档、打包、签名和发布工件。
我们努力让您(我们的用户)轻松地为您的用户做最好的事情。 这就是为什么我们专注于提供易于使用的集成、良好的默认设置和许多教程以及有助于缓解供应链安全问题的工具、包管理器、go mod 代理等。
通过这种方式,可以轻松提供易于安装的软件包,例如带有签名的校验和、软件物料清单和可复制的二进制文件。
总结来说:GoReleaser的作用是让你可以用最少的步骤和时间,把你写的Go程序打包成各种格式,然后发布到网上,让别人可以下载和使用。
使用
1. 安装
2. 项目初始化GoReleaser
# 安装goreleaser cli工具
goreleaser init
3. 修改配置。GoReleaser配置文档
下面我使用的配置,可以用作于生产使用。也可以参考:ArgoCD GoReleaser
before: # 前置构建配置,可以放包检测、单元测试、go generate等,同步运行,失败就停止发布。
hooks:
# You may remove this if you don't use go modules.
- go mod tidy
# you may remove this if you don't need go generate
- go generate ./...
builds:
- id: id # 多个构建时候,id必填
main: cmd/main.go # 默认为根目录main.go,没有需要自己配置入口文件地址
env:
- CGO_ENABLED=0
flags: # go build <flags...>
- "-v"
- "-tags=prod" # 自定义编译标签,通过标签与死码消除完成本地与线上开发优化。
ldflags: # go build -ldflags "<ldflags...>"
- "-s -w" # 压缩编译配置
- -X <package>/common.version={{.Version}}
- -X <package>/common.commit={{.FullCommit}}
- -X <package>/common.date={{.Date}}
- -X <package>/common.builtBy=goreleaser
- -extldflags="-static"
goos: # 编译平台
- linux
- darwin
- windows
goarch: # 编译平台支持架构
- amd64
- arm64
- s390x
- ppc64le
ignore: # 忽略的编译架构,
- goos: darwin
goarch: s390x
- goos: darwin
goarch: ppc64le
- goos: windows
goarch: s390x
- goos: windows
goarch: ppc64le
- goos: windows
goarch: arm64
archives: # 制品
- format: tar.gz # 制品格式
# 制品名称模版,可以使用goreleaser变量与go template模版函数。[goreleaser变量](https://goreleaser.com/customization/templates/)
# this name template makes the OS and Arch compatible with the results of uname.
name_template: >-
{{ .ProjectName }}_
{{- title .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else if eq .Arch "386" }}i386
{{- else }}{{ .Arch }}{{ end }}
{{- if .Arm }}v{{ .Arm }}{{ end }}
# use zip for windows archives
# 对一些额外平台做覆盖配置
format_overrides:
- goos: windows
format: zip
checksum:
name_template: 'checksums.txt'
snapshot: #
name_template: "{{ incpatch .Version }}-snapshot"
changelog: # 根据commit log自动生成Change Log
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
# The lines beneath this are called `modelines`. See `:help modeline`
# Feel free to remove those if you don't want/use them.
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
# vim: set ts=2 sw=2 tw=0 fo=cnqoj
4. 构建或发布
# 构建
goreleaser build
# 发布
goreleaser release
Go 构建技巧
Go ldflags
相关可以通过go tool link
命令查看文档,也可以查看这篇介绍:Go gcflags/ldflags 的说明
通过ldflags
在编译时写入编译环境与版本。
1. 提供一个可注入参数变量与包。
package common
import (
"fmt"
"runtime"
)
// Version information set by link flags during build. We fall back to these sane
// default values when we build outside the Makefile context (e.g. go run, go build, or go test).
var (
version = "99.99.99" // value from VERSION file
buildDate = "1970-01-01T00:00:00Z" // output from `date -u +'%Y-%m-%dT%H:%M:%SZ'`
gitCommit = "" // output from `git rev-parse HEAD`
gitTag = "" // output from `git describe --exact-match --tags HEAD` (if clean tree state)
gitTreeState = "" // determined from `git status --porcelain`. either 'clean' or 'dirty'
kubectlVersion = "" // determined from go.mod file
extraBuildInfo = "" // extra build information for vendors to populate during build
)
// Version contains Argo version information
type Version struct {
Version string
BuildDate string
GitCommit string
GitTag string
GitTreeState string
GoVersion string
Compiler string
Platform string
KubectlVersion string
ExtraBuildInfo string
}
func (v Version) String() string {
return v.Version
}
// GetVersion returns the version information
func GetVersion() Version {
var versionStr string
if gitCommit != "" && gitTag != "" && gitTreeState == "clean" {
// if we have a clean tree state and the current commit is tagged,
// this is an official release.
versionStr = gitTag
} else {
// otherwise formulate a version string based on as much metadata
// information we have available.
versionStr = "v" + version
if len(gitCommit) >= 7 {
versionStr += "+" + gitCommit[0:7]
if gitTreeState != "clean" {
versionStr += ".dirty"
}
} else {
versionStr += "+unknown"
}
}
return Version{
Version: versionStr,
BuildDate: buildDate,
GitCommit: gitCommit,
GitTag: gitTag,
GitTreeState: gitTreeState,
GoVersion: runtime.Version(),
Compiler: runtime.Compiler,
Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
KubectlVersion: kubectlVersion,
ExtraBuildInfo: extraBuildInfo,
}
}
2. 通过-ldflags="-X <package>/common.<variable>=<value>"
在编译时候写入参数
推荐阅读
本文参与了1024 程序员节活动,欢迎正在阅读的你也加入。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。