3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GitHub Actionsワークフローを今よりちょっと最適化してみる〜GitHub CI/CD実践ガイドを読んで〜

Posted at

はじめに

GitHub CI/CD実践ガイドを読みました。

こちらの本では、セキュリティや運用コストを意識したGitHub Actionsの設計や、単体テストや静的解析だけでなくDependabotの自動バージョンアップデートなど様々なワークフロー例が紹介されています。
これまで雰囲気でGitHub Actionsを触ってたのですが、GitHub Actionsをもっとよい設計・運用にできることを学べたので、その中で今すぐ取り入れられるプラクティスをいくつか紹介したいと思います。

無駄なコストを削減する/高速化する

自動キャンセル

例えば、プッシュもしくはプルリクエストをトリガーに動くワークフローでは、同じブランチに短期間で連続プッシュした場合、それぞれのコミット単位でワークフローが実行されると思います。このとき、先に実行していたワークフローを自動でキャンセルすることができるので、無駄なワークフローを実行するコストを減らせます。

on:
  pull_request:
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

ワークフローとブランチの組み合わせでConcurrencyグループを定義し、同じグループであれば実行中のワークフローをキャンセルする仕組みです。

タイムアウト

GitHub Actionsのデフォルトタイムアウトは360分です。万が一ワークフローが終了せず360分も実行したままだとこれも無駄なコストが発生しますし、終了できずに失敗することがすぐにわかりません。
そこで、ジョブまたはステップのタイムアウトを設定することができます。

jobs:
  timeout:
    timeout-minutes: <タイムアウトまでの時間(分)>

キャッシュ

公式のアクションには、様々な言語をセットアップするものがありますが、依存関係をキャッシュするオプションがあります。

# Nodeセットアップの例
steps:
  - uses: actions/setup-node@v4
    with:
      node-version: 20
      cache: npm

また、自分で自由にパスを指定してキャッシュするアクションもあります。
ファイルのダウンロードに時間がかかるケースは、そのファイルをキャッシュすることで時間の短縮につながります。

steps:
  - uses: actions/cache@v4
    with:
      key: <キャッシュの検索に使うキー>
      path: <キャッシュ対象のディレクトリパスまたはファイルパス>
      restore-keys: <キャッシュミス時のリストアキー>

例えば自分は、actions/setup-nodeでは/node_modulesをキャッシュしない(マシン上のグローバルキャッシュ~/.npmをキャッシュしている)ので、/node_modulesもキャッシュしたい場合とかにactions/cacheを使ったりしています。セットアップアクションの仕様は言語ごとに異なるので、詳しくはドキュメントをご参照ください。

# /node_modulesをキャッシュする例
steps:
  - uses: actions/cache@v4
    with:
      key: ./node_modules
      path: node_modules-${{ hashFiles('**/package-lock.json') }}

その他

例えば自動テストなどで並列実行の制御(実行環境のCPU数、ソフトウェアのI/O頻度のチューニングなど)によって高速化を図ることができます。このあたりのチューニングって意外と大事だと思います。他にも。自動テストや静的解析のプラクティスは本で紹介されています。

実行結果を見やすくする

ロギング

ワークフローコマンドを使うと、ワークフローの実行ログを自分で出力したり出力するログをグループ化して見やすくしたりすることができます。

debugワークフローコマンドを使うことで、デバッグログを出力できます。
※デバッグログを出力するにはEnable debug loggingの有効化が必要です。

run: echo "::debug::<デバッグ用メッセージ>"

group endgroupワークフローコマンドを使うことで、↓のようにコマンドの中の出力が折りたたまれて表示されます。

image.png

run: |
  echo "::group::ロググループ"
  echo "以降の出力が折りたたまれる"
  echo "::endgroup::

レポーティング

GitHub Actionsのページでワークフローの実行結果を見やすくするアノテーションとジョブサマリーを設定することができます。

アノテーションはerror warning noticeのワークフローコマンドを使うことで、ジョブの結果を↓のようにError/Warning/Noticeと分かりやすく表示してくれます。

image.png

- name: Error annotation
  run: echo "::error::<エラーメッセージ>"
- name: Warning annotation
  run: echo "::warning::<ワーニングメッセージ>"
- name: Notice annotation
  run: echo "::notice::<メッセージ>"

ジョブサマリーではGITHUB_STEP_SUMMARY環境変数にマークダウンテキスト出力することで、↓のようにアノテーションより多くの情報を出力することができます。

image.png

run: |
  echo "# ジョブサマリー" >> "${GITHUB_STEP_SUMMARY}"
  echo "- マークダウンテキストを書けます" >> "${GITHUB_STEP_SUMMARY}"
  echo "- 実行結果が見やすくなります" >> "${GITHUB_STEP_SUMMARY}"

セキュリティに強くする

中間環境変数

github.pullrequests.titlegithub.pullrequests.bodyなど、信頼できないコンテキストからスクリプトインジェクションが発生する可能性があります。この場合はそのコンテキストを直接ステップで使うのでなく、中間環境変数を使うことで回避することができます。

# 中間環境変数でプルリクエストのタイトルを使う
env:
  PR_TITLE: ${{ github.pullrequests.title }}
  steps:
    - run: echo "${PR_TITLE}"

その他

その他にもクレデンシャルをマスクするなどのテクニックや、サードパーティのアクションを使うルールを策定するといったセキュリティに関する運用プラクティスが紹介されています。

おわりに

これらのプラクティス以外にもたくさんの事例が紹介されています。もっと詳しく知りたい方はぜひ本を読んでみてください!

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?