みなさんはdeb/RPMパッケージを作ったことはありますか?
私はtcpdpのパッケージ作成ではじめて作りました。具体的にはここらへんです。
tcpdpはlibpcapに依存していることもあり、DockerでUbuntu/CentOSの環境を作ってその上でコンパイルして、合わせてdeb/RPMパッケージ化までするようにしています。
本来Goはクロスコンパイルができるので、コンパイルしてできたバイナリをdeb/RPMパッケージにできればいいわけです。
ただ、意外にdeb/RPMパッケージをするための前準備が面倒です。
debパッケージであればcontrolファイルを書かないといけないですし、RPMパッケージであればspecファイルを書く必要があります。それぞれ覚えているほど書く機会はないので毎回ググるはめに。
ビルド方法にもお作法があります。これもあまり覚えていませんがディレクトリ構成などいろいろ面倒だった記憶があります。。
いくらワンバイナリとはいえaptやyumで管理できるメリットは大きいので、できればdeb/RPMパッケージも用意したいのですが、上記のような面倒さから億劫になっていました。
NFPM
ここで見つけたのがNFPMです。
NFPMはGoReleaserのorg配下にあり、GoReleaser( .goreleaser.yml )からも呼び出せるようになっています。むしろGoReleaser経由の方法を紹介します。
実際にcgrpsの設定を元に説明します。
cgrps/.goreleaser.yml at master · k1LoW/cgrps · GitHub
builds ディレクティブで id を付与する
まず、builds ディレクティブでビルド方法を指定すると思いますが、こちらで id を付与して nfpms ディレクティブで指定できるようにします。
builds: - id: cgrps-linux 👈 env: - CGO_ENABLED=0 goos: - linux goarch: - amd64
ちょっと古い .goreleaser.yml の書き方だと id の指定は必要ありませんが、これの機会に指定しておきましょう。
nfpms ディレクティブを追加する
nfpms ディレクティブを追加します。
cgrpsでは以下のようにしています。
nfpms: - id: cgrps-nfpms name_template: "{{ .ProjectName }}_{{ .Version }}-1_{{ .Arch }}" builds: - cgrps-linux 👈 homepage: https://github.com/k1LoW/cgrps maintainer: Ken'ichiro Oyama <k1lowxb@gmail.com> description: cgrps is a set of commands for checking cgroups. license: MIT formats: - deb - rpm bindir: /usr/bin epoch: 1
詳しくは GoReleaserのNFPMの設定のドキュメント をご覧ください。
nfpms.builds には、先ほどの builds.id を指定します。
UbuntuやCentOSで利用するdeb/RPMパッケージであれば、Linux用にコンパイルする設定を書いた builds.id を指定することになると思います。
goreleaserコマンドを実行
設定は、これで終わりです。
試しに以下のコマンドを実行すると dist/ ディレクトリにdeb/RPMパッケージが作成されていると思います。
$ goreleaser --snapshot --skip-publish --rm-dist
あとはいつものように goreleaser コマンドを実行することでリリースが完了します。
NFPMでは何をしているのか?
では実際にNFPMでは何をしているのか気になったので、ソースコードを見てみました。
愚直にspecファイルを書いて、rpmbuildコマンドを叩いていました *1
ある意味安心な実装でしたので、みなさんも是非ご利用ください。