CI/CD
PR

セルフホストランナーの setup-node が古い Node.js を使い続ける原因と対処|check-latest

saratogax
記事内に商品プロモーションを含む場合があります

セルフホストランナーの GitHub Actions で、actions/setup-node に node-version: 24 と書いているのに、Node.js の修正版が出ても古いバージョンのまま動いていませんか?

エラーにはならず、テストもいつもどおり成功するので、Setup Node.js のステップのログを開くまで気付けません。

私の CI でも、Node.js のセキュリティリリースが出た翌日に確かめると、v24.21.0 のまま動いていました。

原因は、setup-node がランナーのキャッシュに条件に合うバージョンがあれば、ダウンロードせずにそれを使うことです。

セルフホストランナーはキャッシュが消えないので、一度ダウンロードしたバージョンを使い続けます。

この記事では、バージョンが選ばれる仕組みと check-latest: true で直す方法、切り替えるときの注意点をまとめます。

症状: node-version: 24 なのに古い v24 のまま

2026 年 10 月 21 日に、Node.js のセキュリティリリース(v22.23.4 / v24.22.1 / v26.12.1)が出ました(Node.js の告知)。

翌日、API の E2E テストを毎日実行しているワークフローのログを見ると、Node.js は v24.21.0 のままでした。

ワークフローの書き方は次のとおりです。

- name: Setup Node.js
  id: setup-node
  uses: actions/setup-node@v6
  with:
    node-version: 24

Setup Node.js のステップのログには、キャッシュにある v24.21.0 を見つけたと出ていました。

Found in cache @ /home/ubuntu/actions-runner/_work/_tool/node/24.21.0/x64

ダウンロードの行はなく、キャッシュにあった v24.21.0 をそのまま使っています。

原因: setup-node はキャッシュにあるバージョンを優先する

setup-node の公式ドキュメントには、check-latest が false(既定)のときの動きが次のように書かれています(actions/setup-node の Advanced Usage)。

When set to false, the action will first check the local cache for a semver match. If unable to find a specific version in the cache, the action will attempt to download a version of Node.js.

まずランナーのキャッシュから指定に合うバージョンを探し、見つからなかったときだけダウンロードする、という意味です。

node-version: 24 は「24 系のどれか」という指定なので、キャッシュにある v24.21.0 でも条件を満たします。

そのため、v24.22.1 が出ていても、ダウンロードしに行きません。

この動きは、私が使っていた v6 でも、現行の v7 のドキュメントでも同じです。

GitHub ホストのランナーとの違い

GitHub がホストするランナーは、ジョブのたびに新しい環境で起動し、キャッシュにはランナーのイメージに入っている Node.js が使われます。

キャッシュの中身はイメージの更新に合わせて入れ替わりますが、イメージが更新されるまでは古いバージョンが使われることはあります。

一方、セルフホストランナーでは、キャッシュは _work/_tool の下にファイルとして残り続けます。

最初にダウンロードしたバージョンが残っている限り、ずっとそれが使われます。

セルフホストランナーで node-version に系列だけを書いている場合、セキュリティリリースは自動では入らないと考えたほうが安全です。

対処: check-latest: true を付ける

対処は、check-latest: true を 1 行足すだけです。

- name: Setup Node.js
  id: setup-node
  uses: actions/setup-node@v6
  with:
    node-version: 24
    check-latest: true

check-latest が true のときの動きは、公式ドキュメントに次のように書かれています。

If check-latest is set to true, the action first checks if the cached version is the latest one. If the locally cached version is not the most up-to-date, a version of Node.js will then be downloaded.

キャッシュのバージョンが最新でなければ、新しいバージョンをダウンロードします。

切り替わったことをログで確認する

変更をマージする前に、テストを 1 本だけ手動で実行したところ、v24.22.1 がダウンロードされました。

マージした翌朝の定期実行のログは次のとおりです。

Attempt to resolve the latest version from manifest...
Resolved as '24.22.1'
Found in cache @ /home/ubuntu/actions-runner/_work/_tool/node/24.22.1/x64

最新のバージョンが 24.22.1 であることを確認したうえで、キャッシュに入っていた v24.22.1 を使っています。

次の修正版が出たら、そのバージョンをダウンロードしてキャッシュに加えます。

切り替えるときの注意点

node_modules のキャッシュが一度外れる

私のワークフローでは、node_modules のキャッシュのキーに Node.js のバージョンを入れています。

- name: Setup npm Cache
  uses: actions/cache@v5
  id: node_modules_cache_id
  with:
    path: '**/node_modules'
    key: ${{ runner.os }}-node-${{ steps.setup-node.outputs.node-version }}-${{ hashFiles('**/package-lock.json') }}

別のバージョンの Node.js で npm ci した node_modules を、そのまま復元しないためです。

このキーの場合、バージョンが上がった最初の実行ではキャッシュが外れて npm ci が走ります。

想定どおりの動きですが、実行時間が一度だけ延びるので、知っておくと慌てずに済みます。

毎回、最新のバージョンを確認しに行く

check-latest: true にすると、実行のたびに最新のバージョンを確認します。

ダウンロードは新しいバージョンが出たときだけなので、毎回ダウンロードするわけではありません。

公式の README には、インターネットに出られないセルフホストランナーでは、使うバージョンをあらかじめキャッシュに入れておく必要があると書かれています(actions/setup-node の README)。

外に出られないランナーでは、この方法は使えないので注意してください。

バージョンを固定する運用とどちらを選ぶか

公式ドキュメントは、安定性を優先して特定のバージョンを使い続けたい場合は、既定(false)のままにすることを勧めています。

check-latest: true にすると、修正版だけでなく、24 系の新しいマイナーバージョンにも自動で上がります。

逆に node-version: 24.22.1 のようにバージョンを固定すれば、いつ上げるかを自分で決められますが、リリースのたびに書き換える必要があります。

どちらを選ぶかは、プロジェクトの事情次第です。

私のワークフローでは、修正版に自動で追従させたかったので check-latest: true を選びました。

どちらの運用でも、セルフホストランナーで系列だけを書いて「最新のバージョンが使われているはず」と思い込まないことが大事です。

自分のワークフローが当てはまるか調べる

当てはまるのは、次の 3 つがそろっている場合です。

  • runs-on がセルフホストランナー
  • setup-node の node-version が 24 や 24.x のような系列の指定
  • check-latest を付けていない

リポジトリの中は、setup-node の前後を見れば確認できます。

grep -rn -A4 "actions/setup-node" .github/workflows

実際に動いているバージョンは、Setup Node.js のステップのログの Found in cache の行で確認できます。

セルフホストランナーでは、ランナー本体のバージョンが古いまま止まり、ジョブを拾わなくなることもあります。

あわせて セルフホストランナーが Idle なのにジョブを拾わない原因と対処 も確認しておくと安心です。

まとめ

  • setup-node は、キャッシュに条件に合うバージョンがあれば、ダウンロードせずにそれを使う
  • セルフホストランナーはキャッシュが残るので、系列だけの指定では修正版に切り替わらない
  • check-latest: true を付けると、実行のたびに最新のバージョンを確認する。バージョンを固定して自分で上げる運用でもよい

Node.js のセキュリティリリースが出たときは、CI のログで実際のバージョンを一度確認してみてください。

ABOUT ME
saratoga
saratoga
フリーランスエンジニア
仕事にも趣味にも IT を駆使するフリーランスエンジニア。技術的な TIPS や日々の生活の中で深堀りしてみたくなったことを備忘録として残していきます。
記事URLをコピーしました