Travis CIを使用したGolangビルド
みなさん、Golang書いてますか?
お久しぶりです。メディアシステム開発部の森竹です。 前回はDocker for Macを使ってRuby on Rails開発環境を構築するを紹介させて頂きました。 今回はTravis CIを使用したGolangビルドを紹介させて頂きます。
ビルド
Travis CIでGolangビルドを実行し、AWS S3へPUTします。ビルドサーバーでGolangビルドする案もありましたが、下記の観点を鑑み、Travis CIを選択しました。
Travis CI | ビルドサーバー | |
---|---|---|
運用コスト | 月額固定(https://travis-ci.com/plans) | サーバー費用など |
管理コスト | 小(Golangバージョンアップは.travis.yml の変更のみ) | 大(ビルドサーバー自体を管理する必要があり、Golangバージョンアップはサーバー全体に影響する) |
成果物 | AWS S3 | ビルドサーバーのストレージなど |
.travis.yml
は下記のように定義しています。
.travis.yml
dist: trusty
language: go
go:
- 1.7.5
env:
global:
- TZ=Asia/Tokyo
before_install:
- make glide # vendoringツールのGlideをインストールします
- make awscli # aws-cliをインストールします
install:
- make deps # glide instalを実行し、パッケージをインストールします
before_script:
- make fmt # gofmtを実行します
- make imports # goimportsを実行します
- make lint # golintを実行します
- make vet # go vetを実行します
- make mysql # go testで使用するDBのcreate、migrateを実行します
- make test # go testを実行します
script:
- make -f development.mk # Development環境のgo buildを実行します
- make -f staging.mk # Staging環境のgo buildを実行します
- make -f production.mk # Production環境のgo buildを実行します
addons:
apt:
packages:
- mysql-server-5.6
- mysql-client-core-5.6
- mysql-client-5.6
artifacts:
s3_region: "ap-northeast-1"
paths:
- $(git ls-files -o --exclude-standard | tr "\n" ":")
debug: true
target-paths: $TRAVIS_REPO_SLUG/$TRAVIS_BRANCH
bucket: "xxxxx-golang-artifacts"
AWS S3へのPUTは、Travis CIのaddons
であるtravis-ci/artifactsを使用しています。上記のように定義すると、s3://xxxxx-golang-artifacts/repository_fqdn/repository_path/branch/au_web_portal.production.linux.amd64.gz
のような構成で成果物が配置されます。
AWS S3へのPUTにはARTIFACTS_KEY
とARTIFACTS_SECRET
が必要です。こちらはTravis CIのSettings
からEnvironment Variables
に定義すると、.travis.yml
に定義する必要がありませんのでお勧めです。
基本的にコードフォーマット(gofmt
、goimports
)、静的解析(golint
、go vet
)、単体テスト(go test
)が通らないとGolangビルド(go build
)は実行されません。
Travis CIで実行するコマンドなどはMakefile
に定義し、.travis.yml
からmake
する方針としました。
Production環境のgo build
を実行するMakefile
は下記のように定義しました。
production.mk
.PHONY: build clean
NAME := au_web_portal
ENV := production
GOOS := linux
GOARCH := amd64
HASH := $$(git rev-parse --verify HEAD)
DATE := $$(date '+%Y/%m/%d %H:%M:%S %Z')
GOVERSION = $$(go version)
build: $(NAME).$(ENV).$(GOOS).$(GOARCH).gz
$(NAME).$(ENV).$(GOOS).$(GOARCH):
GOOS=$(GOOS) GOARCH=$(GOARCH) \
go build -tags=$(ENV) \
-o $(NAME) \
-ldflags "-X main.Hash=$(HASH) \
-X \"main.Date=$(DATE)\" \
-X \"main.GoVersion=$(GOVERSION)\"" \
./au_web_portal
mv $(NAME) $@
$(NAME).$(ENV).$(GOOS).$(GOARCH).gz: $(NAME).$(ENV).$(GOOS).$(GOARCH)
gzip -f $<
clean:
rm -rf $(NAME).$(ENV).$(GOOS).$(GOARCH).gz
rm -rf $(NAME).$(ENV).$(GOOS).$(GOARCH)
環境毎に異なる値はBuild Constraints
を使用し、各環境(Production、Staging、Development)のgo build
を実行します。
またldflags
オプションを指定し、Golangバイナリに情報を埋め込みます。開発段階ではGitHubへのpush後すぐ(go build
が実行される前)にデプロイを実行し、変更が反映されていない状況があったりしました。そのような時に、Golangバイナリがどのような状態で動作しているのかを確認するのに便利です。
デプロイ
デプロイはCapistranoを使用しました。AWS S3から各環境に対応したGolangバイナリを取得し、対象サーバーへデプロイします。 下記のようなコマンドを実行します。
$ bundle exec cap branch=master production deploy
おわりに
Travis CIを使用したGolangビルドを紹介させて頂きました。 今回はTravis CIが実行されると各環境(Production、Staging、Development)に対応したGolangビルドが実行されますが、GitHubブランチルールを策定し、各ブランチに対応した環境のGolangビルドを実行するようにしても良いかもしれません。
- 例)
master
ブランチの場合、Production環境のGolangビルドを実行するrelease/99999999
ブランチの場合、Staging環境のGolangビルドを実行するfeature/xxxxxxxx
ブランチの場合、Development環境のGolangビルドを実行する
またGolangバイナリのAWS S3へのPUTですが、aws-cliを使用し、下記のように実行しても良かったと思っています。
$ aws s3 cp au_web_portal.production.linux.amd64.gz s3://xxxxx-golang-artifacts/repository_fqdn/repository_path/branch/
今後はGolangバージョンアップなど、継続的にアップデートや改善をして行きたいと思います。