おそらくはそれさえも平凡な日々

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のアップロードもやりやすくなった
  • 各種イベントドリブンでジョブを起動でき、それぞれのワークフローごとにファイル分割できる
  • 定型作業はアクションという形で誰でも利用可能な形で公開可能

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は対象外とするため
  • 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している
  • if構文を使って動作可否の判定ができる
  • 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の公開などをして知見を貯めて、社内環境への導入も伺いたい。

created at
last modified at

2019-11-14T14:10:18+0900

comments powered by Disqus