GitHub上で構築するコードメトリクス計測基盤

TL;DR

長いので要約すると

  • octocovは計測したコードメトリクスをGitHub Actions Artifactsに保存すると、単体リポジトリでメトリクスの比較レポートなどもしてくれて便利
  • さらに octocovs-template を使って、各リポジトリのArtifactsに保存されているメトリクスを収集する専用リポジトリを作るとバッジも生成・配布できて便利

となります。


GitHub」というキーワードでお声かけいただき、「TECH STAND #9 GitHub」にて、本エントリと同名タイトルで発表させてもらいました。

standfm.connpass.com

GitHubの中の開発の仕方を知ることができたり、GitHubを使った様々な生産性向上のアプローチを知ることができたり、何よりいろんな方に octocov やペパボでの取り組みを知ってもらえてよかったです。

今回は、個人的にずっと模索していたことがTECH STANDでの発表やアフタートーク、その後フィードバックを通じて気づきを得て解決することができたのでそれを紹介したいと思います。

GitHub "のみで" 構築するコードメトリクス計測基盤

octocovはPull Requestへのコードメトリクスレポート機能やCLIによるカバレッジ確認機能などがあります。

なお、CLIによるカバレッジ機能については次のエントリをぜひ。

k1low.hatenablog.com

バッジ生成機能

その中でも面白い(しかし本人はいたって真面目に作った)機能として、バッジ生成機能があります。

せっかくCIで計測しているコードカバレッジやCode To Test Ratioやテスト実行時間をバッジにしてREADME.mdに貼りたいわけです。

↑こういうのです

そのためにパッケージも書いたりしています。

octocov/pkg/badge at main · k1LoW/octocov · GitHub

ただ、これには1つ個人的なこだわりで課題を持っていました。

CIで計測したコードメトリクスのバッジを生成したとして、そのバッジを誰が配布するのか

CIで計測した結果、その場でバッジの生成はできます。

しかしREADME.mdにそれを更新される状態で貼るには、バッジを常に更新されても固定のURLで公開する必要があるわけです。

その実現方法について満足していませんでした。

CI上で生成したバッジをそのままリポジトリのコミットしてしまう

実現方法の1つは、CI上で生成したバッジをそのままリポジトリのコミットしてしまう方法です。

コミットさえしてしまえばそれをREADME.mdから読むことは可能です。

# octocov

![coverage](docs/coverage.svg) ![ratio](docs/ratio.svg) ![time](docs/time.svg)

最近まで、リポジトリとしてのoctocovもこの方法をとっていました。

https://github.com/k1LoW/octocov/blob/v0.41.0/README.md?plain=1#L5

ただ、これには欠点があって「バッジのコミットが積まれてしまう」というものです。これがうざい。テスト実行時間も取得していることから結構な頻度でコミットが積まれていまいます。

Central modeを使う

もう1つはCentral modeを使う方法です。

octocovにはCentral modeというコードメトリクスを複数のリポジトリから収集するモードがあります。

現在は収集したコードメトリクスと、生成したバッジの一覧を生成する機能があります。Central modeを使えばバッジの配布が可能です。

このCentral modeを使う方法にも(今までは)「GitHubのみで構築するコードメトリクス基盤としては、Central modeのリポジトリ(Central repo)に各リポジトリのメトリクスデータを集約する構成の決定打がない」という課題がありました。

従来の実現方法としてはCentral repoに対して各リポジトリGitHub Actionsからコミットをするというものでした。

以下のような感じです。

図をみるとわかるようにCentral repoへコミットするためのPermissionが必要になってしまいます。

できれば、リポジトリにある secrets.GITHUB_TOKEN のみでいい感じに他リポジトリにコミットできる仕組みが欲しいところですが、今のところはありません*1。Parsonal Access Tokenが必要になってしまいます。

なんとかできないものかと思っていたのですが、現状は解決を諦めていました。

GitHub Actions Artifacts

ところで、

octocovに最近追加された機能として、「計測したコードメトリクスのデータをArtifactsに保存する」というものがありました。

これによってリポジトリ単体の機能の範囲で過去メトリクスを保存できるようになり、Pull Requestへのレポート時に「前回メトリクスとの比較」もレポートできるようになりました*2

作者である私自身のoctocovに対する機能の理解としてもここまでだったのですが、先日のイベント登壇からの流れでふと

リポジトリのArtifactsにあるコードメトリクスレポートをCentral repoから収集すればいいのでは?

と思い付いたのです。

そして、実際に設定してみると出来たのでした。

既に機能としては実現していたのに作者が気づいていなかったという...*3

実現イメージとしては以下のような感じです。

GitHub のみで コードメトリクスバッジ基盤を構築する方法

さて、具体的な設定方法です。前提として既にoctocovを利用してGitHub Actions Artifactsにコードメトリクスを保存しているPublicなリポジトリを持っている必要があります。

次にCentral repoを作ります。こちらはテンプレートリポジトリを用意しました。

github.com

このリポジトリの "Use this template" ボタンを押して完成です。終わり。

あとは .octocov.yml の central.reports.datastores: にコードメトリクスを収集したいリポジトリを追加していけば良いです。サンプルとして octocov のメトリクスを収集するようになっています。

central:
  reports:
    datastores:
      - artifact://k1LoW/octocov # delete this line
      # - artifact://owner/repo
      # - artifact://owner/other-repo
      # - artifact://owner/another-repo
  badges:
    datastores:
      - local://badges
  push:
    enable: true

実際にバッジを生成している私のリポジトリこちらです。

まとめ

やっと「GitHub上で構築するコードメトリクス計測基盤」を真の意味で実現できる道筋ができました。

Central modeは、現状は最新のコードメトリクスとバッジの一覧の配布のみに対応していますが、将来的にはメトリクスを蓄積して便利そうなダッシュボードなどをGitHubの機能のみでつくれるところまで実現したいとは思っています。今のところキーワードとなっているGitHubの機能は「FlatData」と「ActionsからPagesへの直接デプロイ」です。

ただ、まあ、、、

ぜひ皆さんも使ってみてください。「(個人や会社で)使っているよ」というフィードバックが一番嬉しいです。機能リクエストやPull Requestもお待ちしています。

*1: @kyanny さんにブログエントリ経由でリポジトリ間のアクセスについてまとまっている https://docs.github.com/ja/actions/security-guides/security-hardening-for-github-actions#considering-cross-repository-access を教えてもらいました

*2:データストアを使えば今までもできていましたが、リポジトリ単体で実現できるようになったのがポイントです

*3:なぜ既に機能として実現していたかというと、octocovがサポートするデータストアはREADは全て io/fs.FS インターフェースで揃えていたからです。詳しくは Go Conference 2021 Autumn の発表資料をご覧ください https://speakerdeck.com/k1low/go-conference-2021-autumn-online