🚀

node-sqlite3のワークフローを改善してみるという話

2024/06/03に公開

はじめに

こんにちは. エンジニア社会人1年目のwind111です.
社内のフロントエンド研修でmixiさんの資料を一部使用したのですが, npm install時にエラーが大量に出てきて環境構築にハマったという出来事がありました.
エラーログを読んでみた結果, node-sqlite3というNode.jsでSQLite3を使用するパッケージが古いnode-gypに依存していることが原因でした.
node-sqlite3のリポジトリではRenovateが導入されているのですが, 何かしらのパッケージ更新PRで必ずテストが落ちているという状況だったので, 既存ワークフローを確認・改善してみることにしました.

断り書き

node-sqlite3で使用しているnode-gypはv8で, Python3.11まで存在したdistutilに依存していました. Python3.12では, pip install setuptoolsをすることで3.12でもdistutilが利用可能ですし, Pyenvが導入されている環境では3.11に下げることも手段です.
ですが, 現在3.12に対応したnode-gyp v10がリリースされていることから, ワークフローの改善に踏み切りました.

テスト失敗の原因を探る


tarをアップデートするPRのテストログを見てみると, 依存パッケージを使うためのNodeバージョン(今回はnode-addon-api)要件が16以上を満たしていないですね.
ですが, setup-nodeではNode18がインストールされているという...変です
ということでtools/semver-check.jsを見てみましょう...

tools/semver-check.js
const fs = require('fs');
const path = require('path');
const semver = require('semver');

const supportedVersions = '10.12.0';

function checkEngines(modulePath) {
    const packageJsonPath = path.join(modulePath, 'package.json');

    if (!fs.existsSync(packageJsonPath)) return;

    const packageJson = JSON.parse(fs.readFileSync(packageJsonPath));
    const engines = packageJson.engines;

    if (engines && engines.node) {
        const minVersion = semver.minVersion(engines.node);

        if (semver.gt(minVersion, supportedVersions)) {
            console.log(`${packageJson.name}@${packageJson.version} requires ${engines.node}`);
            process.exit(1);
        }
    }
}

<>

for (const dependency of allDependencies) {
    const modulePath = path.join(__dirname, '..', 'node_modules', dependency);
    checkEngines(modulePath);
}

semver.gt...の部分でパッケージの最低要件minVersionとサポートするバージョンsupportedVersionで比較を行っているみたいですが, 何故かNode10が指定されてますね...

semver-check.jsの修正

tools/semver-check.js
const supportedVersions = process.versions.node;

Node10は2021年初頭にEOLになっているので, supportedVersionをマシン依存のバージョンに変更します.
これでNode18を使用したテストが実行されました.

ワークフローが1つ動かない

semver-check.jsの修正後にワークフローを回した際, macos-m1だけ無限Pendingが発生し, 48時間後に失敗していることに気づきました.
これに関して色々と調べていたのですが, セルフホストランナー or Public betaの時期に書かれたものか見分けがつかなかったので,
これを参考にして該当部分をmacos-latestに書き換えてみました.

これでALL OKになりました!

バージョンを上げてテストを実行してみる

RenovateのPRに上がっていたパッケージのバージョンを上げてテストを実行してみた結果, 全てPASSしていることを確認できました🎉🎉🎉

PRを投げる

https://github.com/TryGhost/node-sqlite3/pull/1790
バージョンチェックの部分は長い間放置されているみたいなので, PRを投げてみました.

変更点には,

  • semver-check.jsのバージョンチェックをマシン依存にする
  • 対象OSをmacos-m1からmacos-latestに変更
  • Debian bullseyeのTLS接続エラーを回避するためにnpm install時にmaxsockets=1を指定
    • これはnpm側でも議論されている問題のため, 一時的な対策です.Debian Bookwormに変更も検討しましたが, Maintainerに何言われるか分からないので, PRに提案を出すだけに留めました.

node-sqlite3のMaintainerの方はかなり多忙みたいなので, 気長に待ちます.

おわりに

研修で色々ハマった結果, まさかPRを投げることになるとは思っていなかったですが, OSSのコントリビュートをする良い機会になったので, これから先も自分が愛用しているパッケージでバグや改善したいことに遭遇した際は積極的に投げていきたいと思っています.

Discussion