🐁

golangci-lint のバージョン更新は必要なときだけ対応したい

2024/03/30に公開

はじめに

Go の静的解析ツールである golangci-lint は、Gopher御用達のツールです。

https://golangci-lint.run/

みなさんは、golangci-lintのバージョン管理をどのように行っていますか?
aqua や go.mod × tool.go × blank(_)import [1] などで管理するでしょう。
ここに renovate を組み合わせればバージョン更新に自動で追従できます。
このようにすれば最新バージョンを使うことができるはずです。

こういった管理を省き最新バージョンを常に使うためにバージョンとして latest を指定することもあるでしょう。
※ GitHub Actions の golangci-lint-action では以下のように指定すれば常に CI にて最新版が利用できます。

- uses: golangci/golangci-lint-action@v4
  with:
    version: latest

こうすることで常に最新バージョンで静的解析が行えます。
しかしこの方法だと機能開発中に静的解析が落ちることがあります。
その PR で対応するのでもよいですが、PR は分けたい気持ちがあります。

そこで、このような課題を解消する仕組みを GitHub Actions の仕組みを考えてみましたので紹介します。

GitHub Actions

作成した GitHub Actions はこちらになります。

name: golangci-lint
run-name: ${{ github.ref_name }} by @${{ github.actor }} ${{ github.workflow }}
on:
    workflow_dispatch:
    schedule:
      - cron: '15 * * * *'
jobs:
  golangci-lint:
    runs-on: ubuntu-latest
    steps:
      - name: Generate token
        id: generate-token
        uses: actions/create-github-app-token@v1
        with:
          app-id: ${{ secrets.BOT_GITHUB_APP_ID }}
          private-key: ${{ secrets.BOT_GITHUB_APP_PRIVATE_KEY }}
      - name: Checkout
        uses: actions/checkout@v4
        with:
          token: ${{ steps.generate-token.outputs.token }}
      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version-file: go.mod
      - name: Golangci-lint
        uses: golangci/golangci-lint-action@v4
        with:
          version: latest
          args: --allow-parallel-runners
      - name: Auto Creation PR
        if: failure()
        env:
          GH_USER_EMAIL: 126062861+otakakot[bot]@users.noreply.github.com
          GH_USER_NAME: otakakot[bot]
          GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
        run: |
          version=$(golangci-lint --version | awk '{print $4}')
          echo ${version} > .golangci.version
          git branch feature/golangci-lint-v${version}
          git switch feature/golangci-lint-v${version}
          git config --global user.email ${{ env.GH_USER_EMAIL }}
          git config --global user.name ${{ env.GH_USER_NAME }}
          git add .golangci.version
          git commit -m "update golangci-lint version to v${version}"
          git push --set-upstream origin feature/golangci-lint-v${version}
          gh pr create --title "Update golangci-lint version" --body "update golangci-lint version to v${version}" --base main --head feature/golangci-lint-v${version}

至ってシンプルです。失敗したときにPRを作るだけです。
ただし、PR は差分がないと作れないので .golangci.version というファイルを用意して無理やり差分を作ります。
この .golangci.version ファイルは golangci-lint をインストールする際のバージョン指定でも使えるのであってもよいかなと思います。

go install github.com/golangci/golangci-lint/cmd/golangci-lint@v$(cat .golangci.version)

運用フロー

作成した GitHub Actions を cron を用いて定期的に実行するように設定します。
静的解析に失敗した場合は以下のように PR が作成されます。

当然ですがこの PR は静的解析で失敗します。
ちなみに、 golangci-lint-action を使うと下記のように PR 上でなぜ失敗したのか確認することができます。

該当のブランチを修正して完了です。

おわりに

なかなかいい感じの仕組みができた気がします。
今回実装したコードは以下に置いておきます。

https://github.com/otakakot/golangci-lint-auto-creation-pr

脚注
  1. Goモジュールでツールもバージョン管理する ↩︎

Discussion