LoginSignup
5
7

More than 5 years have passed since last update.

gored: golangプロジェクトをローカルでもCIでもビルド/リリースできるようにするための環境整備ツール

Last updated at Posted at 2018-01-06

golangで作ったツールをリリースするときにはだいたい以下のような作業をすることになります。

先人の様々なツールによってgolang製ツールのリリースが成り立っていることがわかりますね。
このような環境セットアップやリリースを誰でも簡単に行えるようにするため、多くのgolangプロジェクトではMakefileが書かれます。(と、みんなのGo言語に書かれていました)
また、最近のCIサービスではDocker Imageを利用することが多いため、一連の処理がコンテナ上で動くようになっていると、ローカルとCIで同じ環境を利用できて便利です。
そこで、既存のgolangプロジェクトに、コンテナ上でのビルド/リリース環境を簡単に準備するためのDocker Imageを作りました。

mpppk/gored: release engineering (via docker) tool for golang project

使い方

以下のコマンドを実行します。

release.sh
$ cd gopath/src/github.com/yourname/yourrepo
$ docker run -v $(pwd):/init mpppk/gored     # リリースに必要なファイル群を生成
$ docker-compose run bump-and-commit         # バージョンとCHANGELOGを更新してgit push
$ docker-compose run release                 # ビルドしたバイナリをGitHub reelasesへアップロード

実行したあとにリポジトリを見てみると、releaseされていることがわかります。
Image

バージョンとCHANGELOGも更新されています。
Image

すごい!かんたん!!

何が起きているのか

まず1行目のdocker run -v $(pwd):/init mpppk/goredは、実行すると以下のファイルが生成されます。

  • docker-compose.yml
  • Makefile
  • .circleci/config.yml

(既にこれらのファイルが存在する場合はgoredと言うsuffix付きで生成します)

デフォルトではビルドパスやバージョン番号が含まれたgoファイルのパスはカレントディレクトリを参照します。変更する場合は--build-path--version-pathを利用してください。

$ docker run -v $(pwd):/init mpppk/gored gored init --build-path [build path] --version-path [version path]

毎回これを打つのがめんどくさい場合は、シングルバイナリ版をお使い頂くと多少マシになります。

$ go get github.com/mpppk/gored
$ gored init --build-path [build path] --version-path [version path]

次にdocker-compose run bump-and-commitreleaseです。
実際とは少し違いますが、生成されたdocker-compose.ymlbump-and-commitreleaseはそれぞれ以下のような内容になっています。

docker-compose.yml
bump-and-commit: &bump-and-commit
  image: mpppk/gored
  volumes:
    - $PWD:/go/src/github.com/yourname/yourrepo
  environment:
    GITHUB_TOKEN: $GITHUB_TOKEN
  working_dir: /go/src/github.com/yourname/yourrepo
  command: make bump-and-commit -f Makefile
release:
  <<: *bump-and-commit
  command: make release -f Makefile

それぞれMakefileの同名ターゲットを実行していますね。
ではMakefileを見てみます。

(略)
deps:
    dep ensure

bump-and-commit: deps test
    gobump patch -w $(BUILD_PATH)
    ghch -w -N v`gobump show -r $(BUILD_PATH)`
    git add CHANGELOG.md
    git commit -am "Checking in changes prior to tagging of version v`gobump show -r $(BUILD_PATH)` [skip ci]"
    git tag `gobump show -r $(BUILD_PATH)`
    git push "https://$(GITHUB_TOKEN)@github.com/$(REPO_OWNER)/$(REPO_NAME)" HEAD:master

crossbuild: deps test
    goxz -pv=v`gobump show -r $(BUILD_PATH)` -d=./dist/v`gobump show -r $(BUILD_PATH)` $(BUILD_PATH)

release: crossbuild
    ghr --username $(REPO_OWNER) `gobump show -r $(BUILD_PATH)` dist/v`gobump show -r $(BUILD_PATH)`
(略)

bump-and-commitでは、以下の処理が行われます。

  1. depsターゲットで依存ライブラリをダウンロード
  2. gobumpでバージョンをpatchインクリメントしてgit add
    • 例えばソースコード中のconst version = "0.0.1"const version = "0.0.2"に書き換わります。
  3. ghchでCHANGELOG.mdを更新してgit add
  4. git commitしてバージョンタグを打ってgit push

releaseでは以下の処理が行われます。

  1. crossbuildターゲットで、goxzによりwindows, mac, linux用のバイナリを生成
  2. ghrでreleaseにバイナリをアップロード

以上の処理がdocker-compose.ymlによりカレントディレクトリをマウントした状態でmpppk/goredコンテナ上で実行されます。
mpppk/goredイメージには既にgobumpghrなどのツールがインストール済みなので、別途インストールする必要はありません。

CI

上記まででコンテナ上でのリリースができるようになっているため、Docker Imageを利用するCIサービスだと大体自動リリースもシュッと実現できると思います。
goredではCircle CIを特に優遇しており、設定ファイルである.circleci/config.ymlを一緒に生成するので、これをコミットしておくと次からはPRのマージ時に自動でリリースされます。

config.yml
version: 2
jobs:
  build: &build
    docker:
      - image: mpppk/gored
    working_directory: /go/src/github.com/yourname/yourproject
    steps:
      - checkout
      - run: make test
  release:
    <<: *build
    steps:
      - checkout
      - run: make bump-and-commit
      - run: make release
workflows:
  version: 2
  build_and_release:
    jobs:
      - build
      - release:
          requires:
            - build
          filters:
            branches:
              only: master

こんな感じで、masterにpushされた時だけrelease jobが走ります。
注意点として、release時のcommit messageの末尾には必ず[skip ci]という文字列を含めておいてください。
これがないとrelease時のpushをtriggerにまたCircle CIが走り始めるので、無限にリリースが行われ続けます。(これに気付かずうっかりv0.0.1からv0.0.804まで一瞬でリリースされました)

workflowの変更

このようにリリース作業に必要なファイルを自動生成してくれるgoredですが、実際にはworkflowを一部変更したいことがあると思います。この場合は生成されたMakefileを編集してください。
例えばデフォルトのMakefileでは依存ライブラリの解決にdepを使いますが、代わりにglideを使いたい場合は、depsターゲットを以下のように変更してください。

(略)
deps:
    glide install
(略)

その他、mpppk/goredイメージに含まれていないツールを使いたい場合、とりあえずMakefileに書いちゃってもいいですが、毎回go getするのが気になる場合は以下のような自前のDockerfileを書いた方が良いかもしれません。

(略)
setup:
    go get ${u} github.com/golang/dep/cmd/dep
    ...(追加したいpackageを書く)
(略)
FROM golang:1.9.2 AS builder
COPY Makefile /go/src/github.com/yourname/yourrepo/Makefile
WORKDIR /go/src/github.com/yourname/yourrepo
RUN make setup

FROM circleci/golang:1.9.2
COPY --from=builder /go/bin/* /go/bin/
RUN git config --global user.email "gored-bot@dammy.com"
RUN git config --global user.name  "gored-bot"

というわけで、お手軽に自動リリース環境を構築するgoredの紹介でした。ご興味あれば使ってみてください!

参考

5
7
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
5
7