開発コストのうちGitHub Actions料金が占める割合は小さい傾向にありますが、組織規模によっては削減の必要があるでしょう。
この記事では、主にDatadogを利用した可視化による特定方法と、一般的なコスト削減のヒントを述べます。
前提:パフォーマンスを改善する
従量課金のアプリケーションではパフォーマンス ≒ コストです。まずは実行時間から改善しましょう。
カケハシでは以下のような事例があります。
以下の記事も観点洗い出しができるのでおすすめです。
この記事では実行時間以外のコスト観点で解説します。
実行時間と課金時間の違いを学ぶ
GitHub Actionsの最低課金時間(billable time)は1分です。
1秒実行(Run time)でも1分分の料金になりますし、1分2秒なら課金時間は2分です。
実行時間が長いものに料金がかかるのは当然として、仕組み上、細かいものでも実行回数が多いと料金が嵩んできます
全体を分析する
GitHub Actionsの可視化はGitHubだけでは難しいです。CSVをダウンロードできるだけで、リポジトリ単位でも見づらく、横断での分析は困難です。
ここでDatadogのCI Visibility機能を使いましょう。リポジトリごとの実行時間を可視化できます。
Datadogでの見方要点
Tree Mapが便利です。
Tree MapからCI Pipelinesを選択し、LevelはPipeline、Durationの合計を選択します。リポジトリ、パイプライン名、ブランチでグループ化すると見やすいです。
DatadogでのDurationは課金時間(billable)を指しています。 ただし、現在のところ単価は考慮できません。Larger RunnerやMacインスタンスといった異なる単価が反映できるとよいですね。
可視化だけのためにDatadog CIを新しく使い始めると、料金がまずまずかかって本末転倒なことも。すでにDatadog CIを利用済みならコスト可視化を使いこなしましょう。
GitHub上での見方
Run DetailsのUsageに遷移すると各Jobの課金時間(billable time)が表示されます。
具体的な料金の削減方法
JobをStepにまとめる
ワークフローはJobで構成され、JobのなかにStepを配置する構造です。
課金はJob単位です。複数のJobを単一のJob内Stepとしてまとめるとコスト面では2つの点で有利です。
まず、課金時間の計算方法の違いです。同一の内容でもJobが5個あれば最低5分分課金されますが、一つのJobに5個Stepを詰め込めば最低1分分となります。
次に、Jobはコンテナのように隔離されており個別に初期化されるため、関連したJobをStep化すると合計の実行時間が若干節約できます。
注意点は、Jobと違いStepは並列実行できず、待ちが長くなる可能性があることです。同時に実行する別のJobがあるなら、Job同士の長さを調整して全体のリードタイムが増えないようにするとよいでしょう。
Linter類のようにあまりエラーにならずデバッグも容易なものはまとめやすいです。
重複の排除
GitHub Actionsでは様々な条件のイベントをもとにジョブを実行できます。
CIが複雑化すると、同じような検証処理が何度も実行されていることが多々あります。pushやpull requestのイベント、ブランチの種類といった視点で整理してみましょう。
renovate / dependabotをどこまで検証するか
パッケージのマイナーバージョンアップデートがCI実行時間の多くを占めていることがあります。通常のPRと同等の検証はどこまで必要でしょうか。
- CIの一部を除外する、
- PRをまとめる機能を使う
- PRそのものではCIを実行せず、マージ段階でまとめてテストする
といったことが考えられます。
ソースコード以外の修正時の動作を考える
readmeの修正でワークフローがすべて動くのはもったいないでしょう。開発ツールの設定変更でソースコードのテストが動いてほしくないときもあります。インフラの設定も同様です。
ファイル種類ごとに整理しましょう。
pre commitで高速なツールを使う
Linterのようなpre commitには高速なものを採用しましょう。実行回数が多いことから、なるべく1分を超えないようにしたいですね。
PythonであればruffのようなRust系ツールがよいでしょう。
timeoutが初期設定6時間なので縮める
ワークフロー実行中に応答がなくなりタイムアウトが発生することがあります。タイムアウトの初期設定が6時間なので、発生すると10分のフローなら36回分消費されます。
タイムアウトを設定していないワークフローをコード検索で洗い出してみましょう。自組織を指定し、以下の条件で検索します。
NOT timeout-minutes: path:.github/ language:YAML language:YAML
終わりに
GitHub Actionsについてはパフォーマンス向上が優先であり、コストを毎月トラッキングするほどではないです。半年か四半期に一度ぐらいの頻度が適切でしょう。
文責:高木