Actions yamlを壊さず直す差分最小メンテ術


GitHub Actionsのワークフローを修正するとき、「直したつもりがCIが通らなくなった」という経験はないでしょうか。特に複数人で触っているリポジトリだと、変更箇所が増えるほどレビューも大変になります。

この記事では、既存のワークフローを壊さずに保守するための「差分を最小に抑える」アプローチを紹介します。

まず手を付けるべきは「置換先が明確な箇所」

ワークフロー修正で失敗しにくいのは、GitHubが公式に「これをこう直してください」と案内している箇所です。代表的なのが set-outputsave-state コマンドの置き換え。

Runner v2.298.2以降では、これらをstdout経由で使っていると警告が出ます。置換方法は単純で、環境ファイルへの追記に変えるだけです。

# Before(警告が出る書き方)
- run: echo "::set-output name=version::1.0.0"

# After(環境ファイルを使う書き方)
- run: echo "version=1.0.0" >> $GITHUB_OUTPUT

save-state も同様に $GITHUB_STATE へ追記する形に変えます。挙動がほぼ変わらない修正なので、差分も小さく済みます。

ちなみに GITHUB_OUTPUTGITHUB_STATE は用途が違います。前者はstep間の値の受け渡し、後者はアクション内部のstate管理用です。混ぜて使うと後で「どこで何が設定されているのか」が追いにくくなるので、用途で分けておくのが保守のコツです。

YAMLアンカーで「変更点を1箇所に集約」する

2025年9月にGitHub Actionsで正式サポートされたYAMLアンカー機能。これが差分最小メンテにかなり効きます。

アンカー(&)とエイリアス(*)を使うと、重複した定義を1箇所にまとめられます。

env: &common-env
  NODE_VERSION: "20"
  CACHE_KEY: "v1"

jobs:
  build:
    env: *common-env
    # ...
  test:
    env: *common-env
    # ...

こうしておけば、Node.jsのバージョンを上げたいときも common-env を1箇所直すだけ。buildとtest両方の定義を探して書き換える必要がありません。

ただし、アンカーは「同一構造を再利用する」仕組みなので、参照元を変えると参照先すべてに影響します。最初は env や、複数jobで使い回している共通stepなど、影響範囲が読みやすい単位から導入するのが無難です。

contextsは「使える場所」を確認してから触る

${{ github }}${{ needs }} といったcontextsを修正するときは注意が必要です。contextsはキーごとに「どこで使えるか」が決まっていて、使えない場所で展開しようとすると壊れます。

たとえば needs contextはjob間の依存関係を表現するものなので、step内の run では使えても、workflow全体の env では使えません。修正前後で「このキーはここで評価される式か」を確認するだけで、無駄なトライ&エラーを減らせます。

デバッグ目的で ${{ toJson(github) }} をログに出力したくなることがありますが、これは避けたほうがいいです。github contextには github.token などの機微な情報が含まれる可能性があります。公式ドキュメントでも注意喚起されている点です。

setup-nodeのキャッシュ設定は「明示」が安全

actions/setup-node を使っている場合、v6系ではキャッシュ周りの挙動が変わっています。

package.jsonpackageManager フィールドや devEngines.packageManager の有無で自動キャッシュの条件が変わるため、意図せぬ動作変更が起きることがあります。「速くしようとしたのに逆に遅くなった」というケースも。

- uses: actions/setup-node@v4
  with:
    node-version: '20'
    cache: 'npm'
    # キャッシュを使わない場合は明示的に無効化
    # package-manager-cache: false

キャッシュを使うか使わないか、どのパッケージマネージャを対象にするかは明示的に書いておくのがおすすめです。暗黙の挙動に依存すると、アクションのバージョンアップで突然動きが変わる可能性があります。

なお、node_modules ディレクトリ自体はsetup-nodeのキャッシュ対象外です。「node_modulesをキャッシュして高速化しよう」と思って設定を変えても、期待どおりにならないことがあります。公式の「何がキャッシュされるか」を確認してから最小限の差分で調整するのが結局は早道です。

差分最小の修正がレビューを楽にする

ワークフロー修正で差分を小さく保つメリットは、レビュアーの負担が減ることです。「何を変えたのか」が一目でわかれば、意図しない変更の混入も防げます。

今回紹介した方法をまとめると:

  1. set-output / save-state の置換は挙動がほぼ変わらないので最初に手を付けやすい
  2. YAMLアンカーで重複を減らし、変更箇所を集約する
  3. contextsは使える場所を確認してから触る
  4. setup-nodeのキャッシュは明示設定で暗黙の挙動変更を避ける

全部を一度にやる必要はありません。警告が出ている箇所から順に直していけば、徐々にメンテしやすいワークフローになっていきます。

参考リンク