GitHub Actions の lockfile対応 - 利用者と提供者両方の観点から
tl;dr:
- 利用者側は使わない理由はない
- カスタムアクションやreusable workflow提供者側に関する仕様はまだ議論中のものもあるため、現状を理解した上で提供方法をアップデートしていくと良い
GitHub Actions workflow lockfiles がGA 🎉
全人類待望のGitHub Actionsのworkflow dependency lockfile が、2026年10月28日にGAになりました。ワークフローから利用するカスタムアクションの依存を lockfileで固定できる機能です。
GitHub Actions workflow lockfiles are generally available
これまで、サプライチェーン攻撃対策やビルドの再現性を高めるために、カスタムアクションのバージョン指定をコミットSHAで固定する、いわゆるSHA pinningが推奨されていました。ただ、ワークフロー宣言に長いハッシュを並べなければならないのは、書き手にとっても読み手にとっても体験が良くありません。また、直接利用しているアクションだけを固定しても、そのアクションが内部で利用している、いわゆる推移的依存先のアクションまでは固定できないという問題もありました。
lockfileはこの両方を改善するものです。ワークフローには読みやすいタグを記述しつつ、実行するハッシュ値はlockfileで固定する。さらに、アクションの推移的依存も固定する。普通のアプリケーション開発では馴染み深い依存管理が、GitHub Actionsにもやってきたという話です。
Workflow dependency lockfiles - GitHub Enterprise Cloud Docs
利用者としては、対応環境であれば基本的に使わない理由はありません。ただ、アクションやreusable workflowを提供している側は、少し整理して考える必要があります。
利用者としては使わない理由はない
使い方は多くの場所で解説されてるため、ここでは取り上げませんが、導入も簡単で直ぐに利用開始できます。エコシステムの未来の観点からも、速やかに移行することが望ましいと考えます。
バージョンロック機構を利用する場合、バージョンの継続更新も実施しないと片手落ちです。これには、dependabot の利用を強く推奨します。以下のエントリーでも取り上げましたが、dependabotが起票するpull request上のアクションは制限された権限で動作するため、万が一新しいバージョンに悪意があるコードが混入していたケースでも内部シークレットを読み取られるリスクなどが低減されています。また、Cooldownもデフォルト3日で設定されるようになりました。
- サプライチェーンアタック対策とdependabot活用 | おそらくはそれさえも平凡な日々
- Dependabot version updates introduce default package cooldown - GitHub Changelog
安全のためにワークフローのメンテナンス性や可読性を犠牲にするのではなく、読みやすい宣言と、機械的な固定・更新を両立できるのが嬉しいところです。指定にあたっての注意点を2点述べます。
リポジトリ内のワークフロー指定には $/ を使う
リポジトリ内のワークフローをcomposite actionやreusable workflowsとして利用する場合は ./ ではなく $/ による指定を使うようにして下さい。これによって、ランナー内にcheckoutされたワークフローではなく、呼び出し元のコミットのワークフローが使われ、呼び出し元のlockfileが正しく適用されます。
- uses: $/.github/actions/build
参考: Locking action dependencies in a repository's workflows - GitHub Docs
Reusable workflowのバージョン固定には引き続きSHA pinningを使う
Reusable workflowにバージョンを指定して固定したい場合、現状は @v1.2.3 のように指定してもlockfileにハッシュ値を記録しないため、ロックしたい場合は引き続き @<sha> のようにコミットSHAで固定する必要があります。
jobs:
build:
# uses: example/shared-workflows/.github/workflows/build.yml@v1.2.3 # これだとロックはできない
uses: example/shared-workflows/.github/workflows/build.yml@<sha> # v1.2.3
Workflow dependency lockfiles - GitHub Docs にも以下のように書かれています。
It doesn't pin calls to reusable workflows (
jobs.<job_id>.uses).
これは、以下のissueでも触れられていますが、reusable workflowは内部コードが使われることが多いため、デフォルトで外部依存同様の厳密なロック対象にしてしまうと煩雑になるという判断のようです。なので、ロック対象外のアクションを選択できる機能と合わせ、reusable workflowのロックも来るかも知れません。
勘違いしたくないのは、このreusable workflowでの非対応部分はここのバージョン指定だけの話で、reusable workflow内部でlockfileを使えないわけではありません。これについては後述します。
ちなみに、SHA pinningを利用する場合、pinact が欠かせませんが、pinact でこのreusable workflowに対してSHA pinningする方法はいち早く以下のドキュメントにまとめられています。
pinact/docs/workflow_lockfile.md at main · suzuki-shunsuke/pinact
アクション提供者側の対応
ここからはアクション提供者側の対応について書きます。具体的には、composite actionを利用したカスタムアクションや、reusable workflowを提供し、それを他リポジトリから呼び出してもらうケースです。
ちなみに、同一リポジトリ内でcomposite actionやreusable workflowを使うだけなら、普通にlockfileを生成して管理するだけで問題ないため、この後の内容は関係ありません。
Composite actionの場合
Composite action 内部で他アクションに依存している場合、その外部アクションのバージョンをどの様に指定すれば良いでしょうか。Composite action側はlockfileは提供できません。そのため、提供者側の選択肢は2つで、両方に一長一短あります。
- SHA pinningを引き続き使い、提供者はマメに依存の更新を実施する
- floating tag (
@v7等)を指定し、利用者側に依存管理を委ねる
SHA pinning
SHA pinningの場合、提供側は内部依存の更新だけでバージョンアップデートが必要になります。これは提供側だけではなく、利用者側にアップデートの負担がかかります。逆に、提供側のリリースが滞ってしまうと、最新の推移依存を使いたいのに古いバージョンでSHA pinningされたままという状況も起こり得ます。
また、提供者と利用者両者がクールダウンを設定していると、推移依存の最新バージョンが降ってくるのがより遅くなる問題もあります。例えば、それぞれが1週間のクールダウンを設定している場合、内部依存の更新が降ってくるのは最短でも2週間後です。
floating tag
なので、その昔に主流だった、 @v7 のようなメジャーバージョンのfloating tagを指定する方法も有力です。利用者側のlockfileで内部依存を固定でき、推移依存先のコントロールもやりやすくなります。
ただ、この場合、利用者側がまだlockfileを使っていない場合に問題になります。まず、実行環境が不定になり、安全性が下がる問題があります。また、Enforce SHA Pinning設定を有効にしているリポジトリでは利用できなくなってしまいます。なので今すぐこの方式に移行するのは現実的ではないかも知れません。
いずれにせよ、この様なベストプラクティス確立の観点からも、GitHub Actions利用者側は速やかにlockfileに移行することが望ましいでしょう。
また、composite actions提供側のサプライチェーンについては以下のissueでも議論されており、改善には取り組むつもりはあるものの、現時点はSHA pinningを利用することが推奨されています。
Feature request: How should composite actions lock themselves? · Issue #183 · github/gh-actions-lock
ちなみに、このバージョン固定の構想が発表された「What's coming to our GitHub Actions 2026 security roadmap」というエントリーでは、Goの依存管理への言及もあるので、個人的には Minimal Version Selection (MVS) のような最適な依存バージョン解決が実装されると嬉しく思っていますが、今回出てきたものがlockfileだったのでそういう方向性ではないのかも知れません。
Reusable workflowの場合
Reusable workflow側では、lockfileを利用できます。なので積極的な利用が推奨です。
Reusable workflowは独立した再利用可能なワークフローであり、権限境界の観点から、利用者側からは依存バージョンをロックできず、reusable workflow側でバージョンロックを実施することになります。
これまではSHA pinningによるバージョンロックしかありませんでしたが、lockfileを使えるようになったので速やかに移行すると良いでしょう。また、Reusable workflow側がバージョンロックされていない場合、利用者側からバージョンロックすることは引き続きできないため、注意が必要です。
まとめ
何度も書いてしまいましたが、利用者側としては乗り換えない理由はありません。多くの人が速やかに乗り換えることで、それを前提としたシステムを作りやすくなるため、より安全なエコシステムの発展も期待できます。
提供側については、まだ議論もありますが、現状の仕様を理解した上で、提供方法をアップデートしていくと良いでしょう。特に、composite action側での依存管理については、個人的に tagpr を含めたいくつかのカスタムGitHub Actionsを提供しているので、今後の進化に期待しています。