LoginSignup
3
1

More than 1 year has passed since last update.

Goのリリースアセットの配置を自動化したい

Last updated at Posted at 2021-12-30

これを自動化したい

GitHubのReleaseにクロスコンパイルで作成したアーカイブを配置(Assets)

こんなかんじ

スクリーンショット 2021-12-30 19.43.56.png
Prometheus

方法

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でタグを作るとパイプラインが実行されてリリースページにアセットを配置できます。

あとがき

シェルスクリプトを紹介してばかりになってしまった・・・難しい。
パッケージを作成するときの必要なファイルをコピーする部分だけ各々書き換えて貰えれば使えると思うので参考にしてもらえれば嬉しいです。

参考

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1