LoginSignup
7
1

[golang]Github ActionsでGoのCIやってみた

Last updated at Posted at 2023-06-11

はじめに

前回 Go で 簡単な API を作りました。

今回は Github Actions を使って CI の実装をしてみたいと思います。

Github Actions とは?

Github が提供するビルド、テスト、デプロイのパイプラインを自動化できる継続的インテグレーションと継続的デリバリー(CI/CD)のプラットフォームのこと。
リポジトリに対するすべての pull request をビルドしてテストしたり、マージされた pull request を運用環境にデプロイしたりするワークフローを作成できます。

詳細は以下を参照してください。

今回のゴール

Github Actions を使って簡単な CI のワークフローを作ります。

CIのフローは以下のようになります。

  1. リポジトリへソースを PUSH or PR の作成
  2. Github Actions 上で CI の実行
    • 単体テストの実行
    • linter の実行
    • 結果を Slack へ通知

イメージ
image.png

ワークフロー作成

ワークフローの作成には、
.github/workflows配下に YAML 形式のファイル(.yml, yaml)を作成しワークフローを定義していきます。

.
├── .github                 # ディレクトリ作成
│   └── workflows
│       └── golang-ci.yml   #  作成するワークフローのファイル

単体テスト

まずは、単体テストを実行するためのワークフローを書いていきます。
Github Action 上で Go の単体テスト(go test -v)を行うための構文は以下のようになります

.github/workflows/golang-ci.yml
# ワークフローの名前
name: Go CI

# トリガーになる Github イベント
# 今回は、リポジトリへのコミット(push)と PR 作成(pull_request)をトリガーにします
on:
  push:
  pull_request:

# ジョブ定義
jobs:
  # ジョブ名
  test:
    # ジョブ実行環境の指定
    runs-on: ubuntu-latest
    # ジョブ内で実行する step を定義
    steps:
      # リポジトリからソースコードの取得
      - uses: actions/checkout@v3
      # Go の実行環境 Set up
      - uses: actions/setup-go@v4
        with:
          go-version: ^1.20
      # テストの実行
      - name: Run Test
        run: go test -v ./...

これだけです。簡単ですね。
では、実際にこのコードをリポジトリに push して CI を走らせます。
image.png
↑こんな感じにリポジトリの Actions タブから ワークフローの実行結果を確認することができます。
無事、テストも成功しているようです。
実際の開発現場では、PR 作成前に 単体テストを実行して、問題なければ PR 作成、問題があれば再度修正をする、という流れになると思います。

では、特に問題なさそうなので、このまま PR を作成します。
実際に作成した PR はこんな感じ。
image.png
PR のページでは、All check have passedと表示され、テストが成功している事もわかります。

リポジトリの設定で、ワークフローが失敗している場合(今回であれば単体テストの実行)、マージをブロックすることもできるので、そこはよしなに運用にあわせて設定してみてください。

では、これで PR をマージして、単体テスト実行のワークフロー作成は完了です。

linter

続いて、 linter を実行するためのワークフローを書いていきます。
linter には golangci-lintを使用します。
また、補助ツールとして reviewdog を使い、 linter 指摘箇所を PR 作成時にコメントさせてみます。

そもそも linter とは?

いわゆる静的解析を行うツールです。
ソースコードの静的解析を行ってくれるもので、構文のチェックやバグの発見をしてくれたりします。
Java であれば CheckStyle とか FindBugs なんかが有名ですね。

golangci-lint とは?

Go の静的解析ツールを統合して実行してくれるツールです。
Golang には色々な解析ツールがあります(gofmt, goimports, govet)。
golangci-lint はこれらの様々な解析ツールを統合して実行することができます。
これ一つあれば、複数のツールを組み合わせなくていいし、実行速度も早いという優れもの。

reviewdog とは?

各種 linter の解析結果を PR にコメントする形で指摘してくれる補助ツールです。
linter を使って規約違反があることがわかっても実際の該当コードを探すのが大変だったりするのですが、 reviewdog を使うと、PR に直接コメント形式で linter 指摘を書いてくれるので該当コードを確認するのがとても楽になります。
image.png

golangci-lint の設定

では、まずは golangci-lint の設定ファイルを書いていきます。
golangci-lint は、設定で、どの linter を有効にするのか解析対象のファイルの指定除外対象のファイルの指定などを行うことができます。
詳細は以下を参考にしてみてください。

今回はこんな感じに設定してみました。

# linter の設定
linters:
  # 全ての linter を無効化
  disable-all: true
  # 指定した linter のみ有効化
  enable:
    - govet
    - errcheck
    - staticcheck
    - unused
    - gosimple
    - varcheck
    - misspell
    - lll
    - gofumpt 

設定ファイルの書き方は大きく black list 形式と white list 形式があります。
golangci-lint にはデフォルトで有効になっている linter があり、何も指定しないとデフォルトで有効化されている linter が実行されます。利用する linter は明示的に指定したいので、今回は全ての linter を無効化してから、使いたい linter のみ enable で指定して有効化しています。(これが white list 形式)

reviewdog の設定

続いてreviewdog の設定です。
PR 作成時、 golangci-lint を実行し、指摘箇所があれば PR にコメントをさせるようワークフローを設定します。
以下のファイルを追加します。

.
├── .github                 
│   └── workflows
        ├── golang-ci.yml
         └── golangci-lint-reviewdog.yml   #  追加したファイル

追加したファイルの内容

.github/workflows/golangci-lint-reviewdog.yml
# ワークフローの名前
name: Golangci-lint ReviewDog 

on:
  pull_request:

# ジョブ定義
jobs:
  # lint
  golangci-lint:
    # GITHUB_TOKEN への権限設定
    permissions:
      checks: write
      contents: read
      pull-requests: write 
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: reviewdog/action-golangci-lint@v2
        with:
          github_token: ${{ secrets.github_token }}
          go_version: ^1.20
          # reviewdog の動作モードの指定
          reporter: github-pr-review
          # Github Status へのレポートレベルの指定
          level: warning
          golangci_lint_flags: "--config=.golangci.yml"

こちらは、 PR 作成時のみ動作するようにしています。
主な設定はポイントは以下です。

github_token
reviewdog が PR にコメントできるようにトークンを指定
reporter
reviewdog の動作設定の指定
ここでは、PR に直接コメントをさせたいので github-pr-review を指定します。
level
Github Checks に報告するレベルの指定
info, worning, error の指定が可能
今回は指摘があってもマージができるようにしたいので warning としています

実際に動かしてみる

動作確認用に以下のファイルを追加しました。
これを使って実際に PR を作成します。(スペルミスで指摘されるはず)

cmd/go-api-sample-todo/golangci_lint_reviredog_sample.go
package main
func typo() {
	mispell := "misspell"
	println(mispell)
}

すると、こんな感じにコメントが付きました。いいですね!
image.png
コードレビューする時、このレベルのチェックに時間や労力を割きたくないので、自動化できるところは自動化して、人間は大事なところにのみ労力を集中したいものです。

linter の設定は以上です。

Slack 連携

最後に Slack 連携です。
ここまでで、Github Actions を使った CI(単体テスト、静的解析) の構築をしました。
ここでは、、その CI の実行結果を Slack に連携できるようにしてみたいと思います。
ただし、実行結果を毎回全て通知されてもうざいだけなので、ここでは CI(単体テスト) が失敗したときのみ Slack へ通知するようにしてみたいと思います。

いやいや、とにかくなんでも通知が欲しいんだーって方は、
この辺使ってできるので参考にしてみてくださいmm

Slack 連携のやり方

以下の手順でやっていきます。

  1. Slack の Incoming Webhook URL の発行
  2. 発行した Incoming Webhook URL を リポジトリに環境変数として登録
  3. CI が失敗した時のみ Slack 通知できるようにワークフローの修正

1. Slack の Incoming Webhook URL の発行

まずは Webhook の発行です。
Slack 公式サイトより Webhook 作成ページを開き、ログイン、通知先のチャンネルを指定して「Incoming Webhook インテグレーションの追加」をします。
※ ここでは、#golang-api-sample-todoを通知先として指定しています。(各自、これは自身の環境にあわせてください)
image.png

すると、こんな感じに Webhook の URL が発行されます。
これは後で使うのでしっかりメモっておいてください。
image.png

2. 発行した Incoming Webhook URL を リポジトリに環境変数として登録

次に、発行した Webhook の URL をリポジトリに環境変数として登録します。
Settings タブからSecres and variables -> Actionsを選択し、New repository secretから登録します。
image.png

Name には参照するときの変数名、Secret には実際の値を入力します。
ここでは、 Name は SLACK_WEBHOOK_URLとしておきます。
image.png

Add secretで追加。こんな感じに SLACK_WEBHOOK_URL が追加されます。
image.png

3. CI が失敗した時に Slack 通知できるようにワークフローの修正

これで Slack 通知のための下準備ができたので、ワークフローを修正して失敗時のみ Slack 通知するようにします。
修正したコードはこちら。

golang-ci.yml
# ワークフローの名前
name: Go CI

# トリガーになる Github イベント
# 今回は、リポジトリへのコミットと PR 作成をトリガーにします
on:
  push:
  pull_request:

# ジョブ定義
jobs:
  # ジョブ名
  unit-test:
    # ジョブの実行環境の指定
    runs-on: ubuntu-latest
    # ジョブ内で実行する step を定義
    steps:
      # リポジトリからソースコードの取得
      - uses: actions/checkout@v3
      # Go の実行環境の Set up
      - uses: actions/setup-go@v4
        with:
          go-version: ^1.20
      # テストの実行
      - name: Run Test
        run: go test -v ./...
      # 以下を追記
      # Slack 通知用の step
      - uses: rtCamp/action-slack-notify@v2.0.2
        # テストが失敗したときのみ通知する
        if: failure()
        env:
          SLACK_TITLE: Test Failure
          SLACK_COLOR: danger
          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}

${{ secrets.SLACK_WEBHOOK_URL }}は、先程登録した環境変数を参照するための記述です。

では、テストが失敗するようにコードを修正して、実際に通知されるか試してみます。
結果、こんな感じにちゃんと通知がきました。よかった
image.png

Slack 連携は以上です。

最後に

簡単ですが、 Github Actions を使った CI の構築から Slack 連携までやってみました。
Github Actions、便利ですね (´・ω・`)
今回作ったものは以下に公開してます。参考までに。

次回は AWS に環境作って、 API を デプロイしていくとこもつくってみようかなーと思います。
ではでは。

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