🐧

pinact - GitHub Actions のバージョンを commit hash で固定

2023/05/01に公開

GitHub Actions の action と reusable workflow の version を commit hash で固定する CLI ツールの紹介です。

https://github.com/suzuki-shunsuke/pinact

$ pinact run
$ git diff
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index 84bd67a..5d92e44 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -113,17 +113,17 @@ jobs:
     needs: path-filter
     permissions: {}
     steps:
-      - uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 # v3
-      - uses: actions/setup-go@v4
+      - uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 # v3.5.1
+      - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
       - name: Cache Primes
         id: cache-primes
-        uses: actions/cache@v3.3.1
+        uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
         with:
           path: prime-numbers
           key: ${{ runner.os }}-primes
 
   actionlint:
-    uses: suzuki-shunsuke/actionlint-workflow/.github/workflows/actionlint.yaml@v0.5.0
+    uses: suzuki-shunsuke/actionlint-workflow/.github/workflows/actionlint.yaml@b6a5f966d4504893b2aeb60cf2b0de8946e48504 # v0.5.0
     with:
       aqua_version: v2.3.4
     permissions:

背景

GitHub Actions の action のバージョンの指定には branch や tag を用いる事ができます。

- uses: actions/checkout@main
- uses: actions/checkout@v3
- uses: actions/checkout@v3.5.1

しかしこれらの branch や tag の commit hash は immutable ではなく、実行タイミングによって実行される action が変わる可能性があります。そのため、コードを修正していないのに突然 CI が壊れたり悪意のあるコードが実行されてしまうリスクがあります。

そこで tag や branch の代わりに commit hash を指定することでそのようなリスクを無くすことができます。

- uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 # v3.5.1

commit hash だけだと version が何なのかわからないので、 version をインラインコメントとして残すのが良いでしょう。
Renovate は version をコメントとして残しておくと、それに従って action を update してくれます。

https://docs.renovatebot.com/modules/manager/github-actions/#additional-information

このように tag の代わりに commit hash を指定した場合でも Renovate で action の update を自動化できます。

解決したい課題

action の version として tag が指定されているものを commit hash に置き換えるには、 tag の commit hash を逐一調べて書き換える必要があります。

Renovate は tag を commit hash に変換する preset を提供しているので、今回紹介するツールは不要だと思うかもしれませんが、
残念ながらこの preset は v3 のような semver じゃない(minor や patch version を含んでいない) tag を semver に変換してくれません。
semver でなくとも Renovate は commit hash を update してくれますが、 Renovate の pull request を見てもその変更内容を理解するのは難しいです。
なぜなら Release Notes が含まれていませんし、 commit hash に相当する tag がわかりませんし、その update が minor update なのか patch update なのかすらわからないからです。

e.g. https://github.com/suzuki-shunsuke/test-github-action/pull/141

image

一方 semver であれば Renovate の Pull Request には version や Release Note が含まれているので内容を理解できます。

e.g. https://github.com/suzuki-shunsuke/test-github-action/pull/143

image

そこで自分は一時期 v3 のような semver でない tag を semver に手作業で修正していたのですが、
流石に面倒すぎるので自動で変換するツールを作りました。それが今回紹介するツールです。

https://github.com/suzuki-shunsuke/pinact

$ pinact run [<workflow file path> ...]

引数を何も指定しないと .github/workflows 配下の YAML が対象になりますが、引数でファイルを指定することも可能です。

機能はシンプルなのでこれ以上説明することがありません。あとは README を読んでください。

Discussion