GitHub ActionsでNode.js Nightly版でもテストする
はじめに
GitHub Actionsのmatrix機能で複数のNode.jsバージョンを対象にビルド・テストなどする場合に、Node.jsのNightly版も加える方法です。
対象Node.jsバージョンにNightly版を入れれば、将来のNode.jsバージョンでうまく動かなくなる事象が早めに発覚して対処がしやすくなります。
一方で、Node.js側のバグを踏む可能性もありますので、あくまでも参考としてエラーを出してもらい、パイプライン全体には影響しないようにします。
やり方
- ジョブに
continue-on-error
設定を追加 - マトリックスに、
continue-on-error
用の変数を追加 - マトリックスの
include
を使って、Node.jsのバージョンがNightlyの場合はcontinue-on-error
をtrue
に設定する
最終的なワークフロー定義は以下のとおり。
name: Node.js Nightly Demo
on:
push:
jobs:
nightly-demo:
runs-on: ubuntu-latest
strategy:
# node-version と experimental という2つの変数からなるマトリックスを定義
matrix:
node-version:
- 16
- 18
experimental:
- false
# { node-version: "20-nightly", experimental: true } を追加
include:
- node-version: 20-nightly
experimental: true
name: Runs on Node.js ${{ matrix.node-version }}
# trueの場合、このジョブが失敗しても、ワークフローは継続する(失敗にしない)
continue-on-error: ${{ matrix.experimental }}
steps:
- uses: actions/checkout@v3
# setup-nodeはv3.6.0以降でNightly版のインストールに対応した
- uses: actions/setup-node@v3.6.0
with:
node-version: ${{ matrix.node-version }}
# ここから後は、好きなステップを実施する(ビルドでもLintでもテストでも)
- run: node index.js
この記事を書こうと思った背景
GitHub Actionsで好きなバージョンのNode.jsをインストールするactions/setup-nodeのv3.6.0がリリースされました。このバージョンではNightly版、RC版などをインストールすることに対応し、気軽にNightly版を使えるようになりました。
ステップごとの説明
準備
当記事の説明用に、まずGitHubにリポジトリーを用意し、以下の2ファイルを追加しました。
今回は、Node.js LTS版では正常に動くがNightly版では異常終了するスクリプトを用意してみました。
本来ここは単にスクリプトを動かすのではなくビルドやテストをするところです。
import { version } from "node:process";
import { setTimeout } from "timers/promises";
// Node.jsのバージョンを表示する
console.log(`node version is: ${version}`);
if (version.indexOf("nightly") > 0) {
// バージョンにnightlyが含まれていたらエラーにする
throw new Error("This script runs on Node.js Nightly");
}
// 問題無ければ、5秒待ってから終了する
await setTimeout(5000);
name: Node.js Nightly Demo
on:
push:
jobs:
nightly-demo:
runs-on: ubuntu-latest
strategy:
matrix:
node-version:
# 一通りLTSバージョンで動かす
- 16
- 18
name: Runs on Node.js ${{ matrix.node-version }}
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.6.0
with:
node-version: ${{ matrix.node-version }}
# 当記事用のスクリプトを実行する
- run: node index.mjs
とりあえず上記の状態でプッシュすると、こうなりました。
普通にNode.jsのバージョン16と18で動かして成功しただけです。
単純にNightlyを加えてみる 👎
単純にmatrix(この例ならnode-version
)に20-nightly
を加えてみます。
index.mjs
はNode.jsのバージョンが20で始まっている場合はエラーをthrowしますので…
name: Node.js Nightly Demo
on:
push:
jobs:
nightly-demo:
runs-on: ubuntu-latest
strategy:
matrix:
node-version:
- # 一通りLTSバージョンで動かす
- 16
- 18
+ # Nightlyでも実行してみる
+ - 20-nightly
name: Runs on Node.js ${{ matrix.node-version }}
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.6.0
with:
node-version: ${{ matrix.node-version }}
# 当記事用のスクリプトを実行する
- run: node index.mjs
このようにワークフロー全体がエラーになり、他のNode.jsバージョンのジョブは途中でキャンセルされました。
NightlyではNode.js側の理由でジョブ失敗のリスクが高いため、Node.js自体を開発する人以外で採用するのは止めた方が良いです。
Nightlyは失敗しても影響ないようにする 👍
そこでNightly版の場合は失敗してもスルーするようにします。
name: Node.js Nightly Demo
on:
push:
jobs:
nightly-demo:
runs-on: ubuntu-latest
strategy:
matrix:
node-version:
- 16
- 18
- # Nightlyでも実行してみる
- - 20-nightly
+ experimental:
+ - false
+ include:
+ - node-version: 20-nightly
+ experimental: true
name: Runs on Node.js ${{ matrix.node-version }}
+ continue-on-error: ${{ matrix.experimental }}
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.6.0
with:
node-version: ${{ matrix.node-version }}
# 当記事用のスクリプトを実行する
- run: node index.mjs
まず適当な変数(ここではexperimental
)をマトリックスに定義し、それをジョブのcontinue-on-error
に渡します。
continue-on-error: true
にすると、そのジョブが失敗してもワークフロー全体を継続します。
continue-on-error
のリファレンスはここちらです。
そして、マトリックスでinclude
を使うと、特定の変数値の組み合わせをマトリックスに追加できます。
include
のリファレンスはこちらです。
上記のマトリックスの場合、以下の組み合わせで実行されます。
node-version | experimental |
---|---|
16 | false |
18 | false |
20-nightly | true |
pushしてみたら以下のようになりました。
Nightlyが7秒でジョブに失敗していますが、バージョン16や18のジョブがキャンセルされることもなく、ワークフロー全体が成功になっています。
終わりに
上記の通り、これまでの運用に悪い影響を与えずに、Nightly版でのジョブ実行を加えることができました。
GitHub Actionsはpublicリポジトリーであれば基本的にいくら使っても無料です。少しだけワークフロー定義は複雑になりますが、せっかくならNode.jsのNightlyバージョンを先取りして継続的インテグレーション(CI)に加えてみてはいかがでしょうか。
当記事を書くために参考にしたマニュアルなど
Using a matrix for your jobs - Handling failures
setup-node/advanced-usage.md - Nightly versions
Discussion