GitHub Actionsを使ってGoプロジェクトのCI/CD及びカバレッジ計測をおこなう
GitHub Actionsを遅まきながら使ってみて、自分のアクティブなGitHub上のGoのOSSプロジェクトで知見がたまったので、共有するものである。
GitHub Actionsについて
非常に良い。VCSとCI/CDの統合は体験が良い。各種イベントをハンドリングできるが、そのイベントが元々Webhookで提供されていたものなので、Webhookを弄っていた身からすると非常に親しみやすかった。コードpush以外のイベントもハンドリングしてプログラマブルに扱えるので夢が広がる。
使い勝手とか具体的に良くなった点
リポジトリ直下の.github/workflows
配下に既定のYAMLをpushすると、その設定にしたがって自動でアクションが動いてくれる。ブラウザ操作必要ないのは快適。
- GitHub上でいろいろ完結できる
- Windowsのテストもできる!
GITHUB_TOKEN
管理もうまいことやってくれるのでreleaseのアップロードもやりやすくなった
- 各種イベントドリブンでジョブを起動でき、それぞれのワークフローごとにファイル分割できる
- 定型作業はアクションという形で誰でも利用可能な形で公開可能
- ref. https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/about-actions
- 公式で色々用意されているし、サードパーティも色々ある。もちろん自分でも作れる
- 設定を書き連ねて複雑なこと実現できる感じはPlagger感ある
Goで扱う場合
オレオレGoオーサリングツールである、godzilに導入している。ちなみに、godzilで作られる雛形も、GitHub Actions前提となりました。詳しくはリポジトリをみて貰えばと思いますが、以下に解説を書きます。
テストの実施
.github/workflows/test.yaml
の中身が以下。
name: test
on:
push:
branches:
- "**"
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macOS-latest
- windows-latest
steps:
- name: setup go
uses: actions/setup-go@v1
with:
go-version: 1.x
- name: checkout
uses: actions/checkout@v1
with:
fetch-depth: 1
- name: lint
run: |
GO111MODULE=off GOBIN=$(pwd)/bin go get golang.org/x/lint/golint
bin/golint -set_exit_status ./...
if: "matrix.os == 'ubuntu-latest' || matrix.os == 'macOS-latest'"
- name: test
run: go test -coverprofile coverage.out -covermode atomic ./...
- name: Convert coverage to lcov
uses: jandelgado/gcov2lcov-action@v1.0.0
with:
infile: coverage.out
outfile: coverage.lcov
if: "matrix.os == 'ubuntu-latest'"
- name: Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.github_token }}
path-to-lcov: coverage.lcov
if: "matrix.os == 'ubuntu-latest'"
ポイントは以下。
- 構文はヘルプによく纏まっている
- pushイベントをトリガーにしている
- branch指定を
**
にしている - これは全てのブランチを対象にしつつtagのpushは対象外とするため
- branch指定を
- ubuntu/maxOS/windowsを対象にしている
- windows環境ではautocrlfがtrueになっているようなので、改行がCRLFに変換されてしまうことは注意が必要
- golintをかける時に、GOBINを明示的に指定している
- 現状setup-goが GOPATH/bin を
$PATH
にふくめてくれないみたいなので… - ref. https://github.com/actions/setup-go/issues/14
- シェルの記法がwindowsでは異なるのでWindows環境ではlintをskipしている
- 現状setup-goが GOPATH/bin を
- if構文を使って動作可否の判定ができる
github
コンテキスト(変数)内にいろいろ情報がぶら下がっているので便利- 特に
github.event
以下にイベントと情報が入っているので、複雑な判定も可能 - ref. https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/contexts-and-expression-syntax-for-github-actions
- 文字列判定周りは正規表現マッチ的な関数があるとより嬉しいので追加されて欲しい
go test
を実施時に、カバレッジ用のファイルも出力している- それを、coverallsに連携させている
- coveralls公式のアクションcoverallsapp/github-acitonを利用してカバレッジを投稿している
- coverallsのアカウント登録さえ済んでいれば、coveralls上でのrepo登録操作も不要
- coveralls公式のアクションはlcov形式しか介してくれないので、事前の変換のためにjandelgado/gcov2lcov-actionを利用している
- これで、mattn/goverallsが不要になった。お世話になりました。(まだお世話になっているところもある)
リリース
release.yaml
が以下。
name: release
on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: setup go
uses: actions/setup-go@v1
with:
go-version: 1.x
- name: checkout
uses: actions/checkout@v1
with:
fetch-depth: 1
- name: release
env:
GITHUB_TOKEN: ${{ secrets.github_token }}
run: |
export GOBIN=$(pwd)/bin
PATH=$GOBIN:$PATH make crossbuild upload
pushイベントをsemverにマッチするtag限定でフックして、リリースイベントをキックしている。実プロセスとしては最後の行のmake crossbuild upload
が全てですが、内部的にはgoxzでcrossbuildして、ghrでアップロードしています。GITHUB_TOKEN
環境変数をsecrets.github_token
で受け渡せるのが嬉しいポイント。
これまで個人的にはtoken管理の煩雑さを嫌って、手元でビルドしてGitHub Releasesにあげるパターンが多かったのだけど、これで、GitHub Actions上でリリースするようにできたので嬉しい。今はアップロードにghrを使っているが、公式のアクションactions/upload-artifact の機能が充実してきたらそっちに乗り換えも考えたいと思っている。
ちなみに、on: create
でcreateイベントを方法も検討したが、createイベントだとtagsで絞り込むことができないのでやめた。イベントごとに指定できるattributeが異なるのでドキュメントをよく読む必要があります。
バッジ
README.md等に貼り付ける用のバッジも当然あり、URL体系は以下の具合です。
https://github.com/<OWNER>/<REPOSITORY>/workflows/<WORKFLOW_NAME>/badge.svg?branch=master
godzilだと以下の通りです。
https://github.com/Songmu/godzil/workflows/test/badge.svg?branch=master
今後
actions/cacheの活用や、独自acitonの公開などをして知見を貯めて、社内環境への導入も伺いたい。