全力で怠けたい

怠けるために全力を尽くしたいブログ。

goreleaser コマンドをちょろっと使ってみたらすごく便利だったメモ [GoReleaser]

はじめに

goreleaser コマンドをちょろっと使ってみたらすごく便利だったメモ。

GoReleaserCLIGitHub Actions が公開している。 個人的には GitHub Actions のほうを CI に取り込んで使うのがすごく便利に感じていて自分が作ってるツールとかは少しずつ GoReleaser を GitHub Actions のワークフローでやるようにしてるけど、GoReleaser がどんなものかは CLI のほうでいろいろ試してたら CLI のほうもすごく便利だった。

まだ GoReleaser を使ってないとかなら CLI でサッと試すのがお手軽だと思うし GitHub Actions じゃなくて CLI で手元のほうからなにかやるとかもありそうな気がするので CLIgoreleaser コマンドをちょろっと使ってみたのをメモしておく。

GoReleaser はなにができるか

GoReleaser はこんなことができる。

自分は Go のプロジェクトは gox でクロスコンパイルして ghrGitHub の Releases ページにアップロードしてるけどそのへんが GoReleaser で置き換えることができて、あと GoReleaser はクロスコンパイルの設定、アーティファクトの作成とか GitHub の releases へのアップロードの設定が YAML で設定できるのがとても便利で楽になってると感じる。

あと GoReleaser は動作がかなり速くて体感的にはクロスコンパイルとか一瞬で終わる感じ。

GoReleaser とかのバージョンをメモしておく。

GoReleaser のバージョン。

$ goreleaser --version
goreleaser version 0.164.0
commit: d822baf11f7773f6c02eeaf7e187157b335935b3
built by: homebrew

macOS のバージョン。

$ sw_vers | grep Product
ProductName:    macOS
ProductVersion: 11.3.1

インストール方法

Macbrew で GoReleaser をインストールできる。

$ brew install goreleaser

go install することもできる。

$ go install github.com/goreleaser/goreleaser

deb, rpm と apk でもインストールできる。このへんは 公式サイト のほうにやり方が書いてある。

goreleaser コマンドを使ってみる

.goreleaser.yml の雛形を作る

Git のリポジトリを作って適当な Go ファイルを作成する。

// main.go
package main

func main() {
    println("Hello World!")
}

goreleaser init コマンドを実行して .goreleaser.yml の雛形を作る。実際に使うときは自分の用途に合うように .goreleaser.yml を設定していく。

$ goreleaser init
   • Generating .goreleaser.yml file
   • config created; please edit accordingly to your needs file=.goreleaser.yml

goreleaser check コマンドを実行して .goreleaser.yml の設定が間違ってないかチェックする。

.goreleaser.ymlYAML の構文エラーのときはこんな感じにエラーがある行を表示する。

$ goreleaser check
   • loading config file       file=.goreleaser.yml
   ⨯ command failed            error=yaml: line 5: mapping values are not allowed in this context

YAML の構文エラーがないけど .goreleaser.yml の設定が間違ってるとこんな感じにエラーがある行を表示する。

$ goreleaser check
   • loading config file       file=.goreleaser.yml
   ⨯ command failed            error=yaml: unmarshal errors:
  line 10: field goosssss not found in type config.Build

.goreleaser.yml が問題なければこんな感じに表示する。

$ goreleaser check
   • loading config file       file=.goreleaser.yml
   • checking config:
      • snapshotting
      • github/gitlab/gitea releases
      • project name
      • loading go mod information
      • building binaries
      • creating source archive
      • archives
      • linux packages
      • snapcraft packages
      • calculating checksums
      • signing artifacts
      • docker images
      • artifactory
      • blobs
      • homebrew tap formula
      • scoop manifests
      • milestones
   • config is valid

とりあえず GoReleaser を動かしてみる

goreleaser --snapshot --skip-publish --rm-dist コマンドを実行してとりあえず GoReleaser を動かしてみる。

$ goreleaser --snapshot --skip-publish --rm-dist

GoReleaser は通常は Git のタグと一緒に使うけど --snapshot オプションを指定すると Git のタグは関係なく とりあえずロスコンパイルする。あと GoReleaser はデフォルトではアーティファクトGitHub とかにアップロードするけど --skip-publish オプションを指定するとアーティファクトGitHub とかにアップロードしない。 とりあえず動作と構成を確認したいけどアーティファクトGitHub とかにアップロードしたくないときはこの2つのオプションを指定して goreleaser コマンドを実行する感じ。

あと GoReleaser はデフォルトはアーティファクトdist ディレクトリに作成する & dist が空じゃないときはエラーになるけど、--rm-dist オプションを指定すると dist ディレクトリを削除してからクロスコンパイルする。 一応、アーティファクトの作成先のディレクトリは .goreleaser.ymldist で指定できる。

# .goreleaser.yml
dist: ./build

バージョンの埋め込み

GoReleaser はデフォルトで以下を ldflags に設定する。

  • main.version
  • main.commit
  • main.date

こんな感じのコードを書いておくとバージョンとかが main.version とかに埋め込む。

// main.go
package main

import "fmt"

var (
    version = "dev"
    commit  = "none"
    date    = "unknown"
    builtBy = "unknown"
)

func main() {
    fmt.Printf("my app %s, commit %s, built at %s by %s", version, commit, date, builtBy)
    // my app v0.0.0-next, commit none, built at 2021-05-16T15:10:15Z by gorelease
}

アーティファクトGitHub にアップロードする

GoReleaser がアーティファクトGitHub にアップロードするときは GitHubAPI トークンが必要になるので PAT を GITHUB_TOKEN に設定しておく。もし PAT がまだ発行してなかったら https://github.com/settings/tokens/new で発行しておく。

$ export GITHUB_TOKEN=<GitHub の API トークン>
$ goreleaser --rm-dist

GitHubAPI トークンはファイルに保存しておいてファイルへのパスを .goreleaser.yml で指定することもできる。

env_files:
  github_token: /path/to/your/github_token

すぐに使える .goreleaser.yml

.goreleaser.yml はだいたいこんな感じのものを個別のプロジェクトごとに設定をカスタマイズして使えそう。

before:
  hooks:
    - go mod tidy
builds:
  - env:
      - CGO_ENABLED=0
    goos:
      - linux
      - windows
      - darwin
    goarch:
      - 386
      - amd64
      - arm64
    ignore:
      - goos: darwin
        goarch: 386
      - goos: windows
        goarch: arm64
archives:
  # アーティファクトのアーカイブのフォーマット。
  # `tar.gz`, `tar.xz`, `gz`, `zip` and `binary` のいずれかを指定する。デフォルトは `tar.gz`
  - format: zip
    # アーティファクトのファイル名のテンプレート。
    # `myproject_darwin_amd64.zip` みたいなファイル名
    name_template: '{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}'
    wrap_in_directory: true
checksum:
  name_template: 'checksums.txt'
snapshot:
  name_template: "{{ .Tag }}-next"
changelog:
  sort: asc
  filters:
    exclude:
      - '^docs:'
      - '^test:'

参考サイト