grpcurlを使ってGitHub Actions上でgRPCなAPIのテストを実行する


はじめに

grpcurlというgRPCサーバをコマンドラインで叩けるツールを利用し、それをGitHub Actions上で動かしてひとまず正常動作確認まで試せたのでここに記録を残します。

環境

go version go1.13.1 darwin/amd64
grpcurl version: v1.4.0

Main Contents

プロジェクト内のGo製ツールの管理はtools.goファイルを生やす

grpcurlはGo製のツールなのでgo installでコマンドを落とすことができます。

Go製のツールのバージョンもGo Moduleのgo.modにて管理するための方法を探しました。

すると公式のGo Modulesに関するこちらのリンクにて言及があり、tools.go(ファイル名は何でも良い)上でツールをimportすることが現状(2020年1月時点)のベストプラクティスとわかりました。

公式での具体例がこちら、GitHubのIssueでの議論がこちらになります。

例として、tools.goは以下のようになります。

tools.go
// +build tools

package tools

import (
    _ "github.com/fullstorydev/grpcurl/cmd/grpcurl"
    _ "github.com/golang/mock/mockgen"
    _ "github.com/golang/protobuf/protoc-gen-go"
    _ "github.com/google/wire/cmd/wire"
)

ポイントは+build toolsを付けることでプロダクションコードにはtools.goでimport記述されているライブラリコード分をコンパイル対象にさせないことです。

そして今回、こちらの記事を参考にMakefile上で上記ツールをインストールするコマンドを用意しました。

Makefileの一部
.PHONY: setup
setup: install-tools
    @true

.PHONY: install-tools
install-tools:
    $(GOMOD) download
    @cat tools/tools.go | grep _ | awk -F'"' '{print $$2}' | xargs -tI % go install % 

make install-toolsとすることでツールコマンドがインストールされ、そのバージョンがgo.modで管理されるようになります。

grpcurlをローカルで試す

pgrpcurlのREADMEの例を見ながら検証しました。

デフォルトではgRPCのデバッグをするために利用するreflectionの機能が有効になっていることが想定されていますが、今回はprotoファイルを参照してクライアントコールする方法にしています。

$ grpcurl -v -d @ -plaintext -proto pb/service.proto localhost:8081 pb.service.Method < test.json

上記では

  • -d @test.jsonとしてgRPCクライアント側でテスト用に渡すJSONファイルを指定
  • -protoオプションでprotoファイルを参照するよう指定

しています。gRPCサーバを8081ポートで動作させていれば以下のような結果が得られます。

Resolved method descriptor:
// A server-to-client streaming RPC.
//
// Comment
rpc Method ( Args) returns ( stream .pb.ReturnType);

Request metadata to send:
(empty)

Response headers received:
content-type: application/grpc

Response contents:
{
  "userId": "ABCDE",
  ....
}

GitHub ActionsにてGo製ツールを使うためにGOPATHとPATH設定をする

GitHub Actionsの公式ランナーにてGOPATH設定しPATHを通すようにするには、現状(2020年1月時点)スマートな方法がまだないようです。

ここのIssueでの議論を参考に、以下のような設定をした上でgrpcurlコマンドでテストをしています。

GitHubActionsのworkflowsファイル一部
name: Test
on: push
jobs:
  integration:
    name: Integration test
    runs-on: ubuntu-latest
    steps:

    - name: Setup Go
      uses: actions/setup-go@v1
      with:
        go-version: 1.13.1

    - name: Setup GOPATH
      # temporary step to run grpcurl command in GOPATH
      # copied from https://github.com/actions/setup-go/issues/14#issuecomment-563273583
      run: |
        echo "::set-env name=GOPATH::$(go env GOPATH)"
        echo "::add-path::$(go env GOPATH)/bin"
      shell: bash

    - name: Checkout code
      uses: actions/checkout@v2

    - name: Install test tools
      run: make setup

    # gRPCサーバを立てる作業

    - name: Run gRPC API test
      run: grpcurl -v -d @ -plaintext -proto pb/service.proto localhost:8081 pb.service.Method < test.json

gRPCサーバに異常があれば正常終了しないのでひとまず正常系のテストができるようになりました。

gRPCにはHTTPステータスコードとの互換を想定したコード定義が以下リンクのように公式で定められているので、今後これに対応するようにサーバ側を更新しテストを充実させていく予定です。
https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto

参考