これを自動化したい
GitHubのReleaseにクロスコンパイルで作成したアーカイブを配置(Assets)
こんなかんじ
方法
GitHub ActionsのパイプラインでOS・CPUアーキテクチャごとのアーカイブを作成し、リリースに配置します。
GitHub Actionsにアーカイブを作成するコマンドを書いてもいいのですが、自分はMakefileで書いてみました。
(GitLabを使うことが多いのでそちらに流用できるように)
Makefile
ビルドやアーカイブファイルの作成用の処理
GO ?= go
GOOS ?= $(shell $(GO) env GOOS)
GOARCH ?= $(shell $(GO) env GOARCH)
MODULE_NAME ?= $(shell cat go.mod | head -n1 | cut -f 2 -d ' ')
all: build
# パッケージのダウンロード
.PHONY: get
get:
go mod download
# ビルド (変数にOSやCPUアーキテクチャをいれてクロスコンパイル)
# ビルド後のファイルの配置場所 : `./.build/<OS>-<CPUアーキテクチャ>/*
.PHONY: build
build: get
mkdir -p .build/$(GOOS)-$(GOARCH)/
GOOS=$(GOOS) GOARCH=$(GOARCH) $(GO) build
if [ $(GOOS) = "windows" ] ; then \
mv ./$(MODULE_NAME).exe ./.build/$(GOOS)-$(GOARCH)/ ; \
else \
mv ./$(MODULE_NAME) ./.build/$(GOOS)-$(GOARCH)/ ; \
fi ; \
# アーカイブの作成 (必要なファイルを含んだアーカイブファイルをOS・CPUアーキテクチャを指定して作成)
# アーカイブファイルの配置場所 : `./packages/<Gitのタグ>/*
TAG ?= $(shell git tag | tail -n1)
.PHONY: package
package:
mkdir -p ./packages/$(TAG)/$(MODULE_NAME)-$(TAG).$(GOOS)-$(GOARCH)
cp -r LICENSE README.md \
./packages/$(TAG)/$(MODULE_NAME)-$(TAG).$(GOOS)-$(GOARCH)
if [ $(GOOS) = "windows" ] ; then \
cp ./.build/$(GOOS)-$(GOARCH)/$(MODULE_NAME).exe ./packages/$(TAG)/$(MODULE_NAME)-$(TAG).$(GOOS)-$(GOARCH) ; \
else \
cp ./.build/$(GOOS)-$(GOARCH)/$(MODULE_NAME) ./packages/$(TAG)/$(MODULE_NAME)-$(TAG).$(GOOS)-$(GOARCH) ; \
fi
cd ./packages/$(TAG) ; \
if [ $(GOOS) = "windows" ] ; then \
zip -r $(MODULE_NAME)-$(TAG).$(GOOS)-$(GOARCH).zip ./$(MODULE_NAME)-$(TAG).$(GOOS)-$(GOARCH) ; \
else \
tar cvf $(MODULE_NAME)-$(TAG).$(GOOS)-$(GOARCH).tar.gz ./$(MODULE_NAME)-$(TAG).$(GOOS)-$(GOARCH) ; \
fi ; \
rm -r ./$(MODULE_NAME)-$(TAG).$(GOOS)-$(GOARCH)
# 削除用
.PHONY: clean
clean:
-rm -r ./.build ./packages ./.build.env
make
でビルド、make package
でアーカイブファイルの作成
GOOS=linux GOARCH=amd64
などを指定してコンパイルするOS・CPUアーキテクチャの指定ができます。
package
の処理はアプリケーションごとに必要なファイルが変わってくると思うので各々書き換えてください。
この部分の1行目が必要なファイルを指定している箇所で、2行目に指定しているディレクトリにコピーされます。
cp -r LICENSE README.md \
./packages/$(TAG)/$(MODULE_NAME)-$(TAG).$(GOOS)-$(GOARCH)
Goが対応しているすべてのOS・CPUアーキテクチャでアーカイブファイルをそれぞれ作成する処理
# Goが対応しているOS・CPUアーキテクチャのリストからそれぞれビルドしてアーカイブファイルを作成
# アーカイブファイルの配置場所 : `./packages/<Gitのタグ>/*
.PHONY: package-all-with-build
package-all-with-build: get
$(GO) tool dist list | grep 'aix\|darwin\|freebsd\|illumos\|linux\|netbsd\|openbsd\|windows' | while read line ; \
do \
printf GOOS= > ./.build.env ; \
echo $$line | cut -f 1 -d "/" >> ./.build.env ; \
printf GOARCH= >> ./.build.env ; \
echo $$line | cut -f 2 -d "/" >> ./.build.env ; \
. ./.build.env ; \
make build GOOS=$$GOOS GOARCH=$$GOARCH ; \
make package GOOS=$$GOOS GOARCH=$$GOARCH ; \
done
rm ./.build.env
go tool dist list
コマンドでリストを取得し、シェルのwhlieループでそれぞれビルドとアーカイブファイルの作成をしています。
grep
することで、想定していないOS(例の場合はandroid, ios等)を除外し、特定のOSだけビルドするようにしています。
こんなかんじのを1行ずつ読んでループさせてます。
$ go tool dist list | grep 'aix\|darwin\|freebsd\|illumos\|linux\|netbsd\|openbsd\|windows'
aix/ppc64
darwin/amd64
darwin/arm64
freebsd/386
freebsd/amd64
freebsd/arm
freebsd/arm64
illumos/amd64
linux/386
linux/amd64
linux/arm
linux/arm64
linux/mips
linux/mips64
linux/mips64le
linux/mipsle
linux/ppc64
linux/ppc64le
linux/riscv64
linux/s390x
netbsd/386
netbsd/amd64
netbsd/arm
netbsd/arm64
openbsd/386
openbsd/amd64
openbsd/arm
openbsd/arm64
openbsd/mips64
windows/386
windows/amd64
windows/arm
windows/arm64
GitHub Actions workflow
Makefileが書けたら次はGitHub Actionsのワークフローを書く。
name: "<任意の名前>"
# `v*`に一致するタグがPushされたらパイプラインを実行
on:
push:
tags:
- "v*"
jobs:
# Goのセットアップ
setup:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
# ビルド・アーカイブファイルの作成とリリースアセットのアップロード
release:
needs: setup
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
# Makefileで書いたアーカイブファイルの作成処理を実行
- name: Build and package
run: make package-all-with-build TAG=${GITHUB_REF##*/}
- uses: actions/upload-artifact@master
with:
name: packages
path: ./packages
# 作成した`*.tar.gz`と`*.zip`をアップロード
- run: |
set -x
assets=()
for asset in ./packages/${GITHUB_REF##*/}/*.tar.gz ./packages/${GITHUB_REF##*/}/*.zip ; do
assets+=("-a" "$asset")
done
tag_name="${GITHUB_REF##*/}"
hub release create "${assets[@]}" -m "$tag_name" "$tag_name"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
これでGitHubでタグを作るとパイプラインが実行されてリリースページにアセットを配置できます。
あとがき
シェルスクリプトを紹介してばかりになってしまった・・・難しい。
パッケージを作成するときの必要なファイルをコピーする部分だけ各々書き換えて貰えれば使えると思うので参考にしてもらえれば嬉しいです。