私が歌川です

@utgwkk が書いている

GitHub Actions workflowのプロファイラを書いた

github.com

表題のものを書きました。

CIをもっと高速に回したい、という欲求は誰しも持っていると思います。CIを高速化することは、開発のテンポを上げることにも、機能リリースまでのリードタイムを下げることにもつながります。 一般的にもそうだと思いますが、測定して現状を把握し、ボトルネックになっているステップを特定することが高速化の一歩になります。

GitHub Actionsのweb UIは、各workflowのjobのステップごとにかかった時間を網羅的に見るのには向いていません。各jobのログを見て、手で集計する、というのはできなくはないと思いますが日が暮れてしまいます。

都合の良いことに、GitHub Actions workflowに関する情報を取ってこれるREST APIが提供されています。これを使わない手はないでしょう。kataribeのように、各ステップの所要時間の統計が取れればプロファイルの手がかりがつかめるはずです。……ということでガッと書きました。 TOMLで設定できるとか、アクセストークンは環境変数経由で渡すことができるとか、自分が使うにあたって欲しいであろう機能はひと通り実装できたと思います。

たとえば、以下は github.com/utgwkk/Twitter-Test のGitHub Actions (.github/workflows/ci.yml) をプロファイルした結果です。 cpanm -L local --installdeps . の所要時間の最大値が跳ねているのは、 local ディレクトリのキャッシュがないときにモジュールを全部インストールすることになるからだ、と推測できます。Maxは大きいけど50%ileで見るとそこまでないとか、最近はキャッシュが効いているのでインストールに時間はかからなくなった、ということも読み取れるでしょう。

Job: Perl 5.32
Number  Min     Median  Mean    P50     P90     P95     P99     Max     Name
1       2.000000        3.000000        3.217391        3.000000        4.000000        4.000000        5.500000        6.000000        Set up job
2       1.000000        1.000000        1.362319        1.000000        2.000000        3.000000        3.000000        3.000000        Run actions/checkout@v2
3       0.000000        1.000000        1.159420        1.000000        2.000000        3.000000        5.000000        6.000000        Run actions/cache@v2
4       1.000000        2.000000        1.971014        2.000000        2.000000        2.000000        3.000000        3.000000        Set up Perl
5       0.000000        0.000000        0.000000        0.000000        0.000000        0.000000        0.000000        0.000000        Remove Perl Problem Matcher
6       0.000000        0.000000        6.840580        0.000000        2.500000        26.000000       176.500000      178.000000      Run cpanm -L local --installdeps .
7       0.000000        2.000000        1.608696        2.000000        3.000000        4.000000        5.000000        6.000000        Run cpanm -L local Test2::Plugin::GitHub::Actions::AnnotateFailedTest
8       2.000000        3.000000        2.741935        3.000000        3.000000        3.500000        4.000000        4.000000        Run prove -Ilocal/lib/perl5 -Ilib -lv t
13      0.000000        0.000000        0.394737        0.000000        1.000000        1.000000        1.000000        1.000000        Post Run actions/cache@v2
14      0.000000        0.000000        0.210526        0.000000        1.000000        1.000000        1.000000        1.000000        Post Run actions/checkout@v2
15      0.000000        0.000000        0.260870        0.000000        1.000000        1.000000        2.500000        3.000000        Post Run actions/cache@v2
16      0.000000        0.000000        0.129032        0.000000        0.500000        1.000000        1.000000        1.000000        Post Run actions/checkout@v2
17      0.000000        0.000000        0.032258        0.000000        0.000000        0.000000        0.500000        1.000000        Complete job

プロファイル結果をJSONで出力することもできます。JSONを加工してMackerelにメトリックとして投稿する、ということもできるかもしれません。

既知の不具合

  • 設定ファイル (TOML) を渡しつつコマンドライン引数にも値を渡したとき、直感的にはコマンドライン引数の値が優先されてほしいけどされていない
  • GitHubのREST APIが返すjobの統計情報に含まれる、各ステップの開始・終了時間はミリ秒以下が切り捨てられている
    • 小数点以下を出してるけど平均値でしか意味を成さない……
    • 将来的にタイムスタンプがミリ秒単位で返されるようになったら嬉しい
  • ジョブの出力順が毎回変わる
  • テストがほぼない
    • 整えたい!!!