どちらか。
node node_modules/puppeteer/install.js
で手動インストール。- 諦めてDocker使う。
非Docker環境、GitHub Actions上でVRTをstorycapで実行。storycapが依存しているPuppeteer起動ステップで"Could not find Chromium"とエラー表示される。原因は/home/runner/.cache/puppeteer
にChromiumバイナリがないから。
Puppeteerのパッケージにはpuppeteerとpuppeteer-coreがあり、puppeteerの方はinstallコマンドを使うと内部的にChromeをインストールして実行パスに追加する。postinstall
コマンドで依存パッケージのインストール終了後に実行される。
node_modules/puppeteer/package.json
"scripts": {
"build:tsc": "wireit",
"build:types": "wireit",
"build": "wireit",
"clean": "tsc -b --clean && rimraf lib",
"format:types": "wireit",
"generate:package-json": "wireit",
"generate:sources": "wireit",
"postinstall": "node install.js",
"prepack": "wireit"
},
node_modules/puppeteer/install.js
/**
* This file is part of public API.
*
* By default, the `puppeteer` package runs this script during the installation
* process unless one of the env flags is provided.
* `puppeteer-core` package doesn't include this step at all. However, it's
* still possible to install a supported browser using this script when
* necessary.
*/
const path = require('path');
const fs = require('fs');
const {execSync} = require('child_process');
// Need to ensure TS is compiled before loading the installer
if (!fs.existsSync(path.join(__dirname, 'lib'))) {
console.log('It seems we are installing from the git repo.');
console.log('Building install tools from scratch...');
execSync('npm run build --workspace puppeteer');
}
const {downloadBrowser} = require('puppeteer/internal/node/install.js');
downloadBrowser();
ローカルマシンではPuppeteerをインストール後にChromiumバイナリがインストールされたまま残り続ける。CI上ではワークフロー終了後にコンテナごと削除されるため都度Puppeteerのインストールが必要になる。つまり、node_modules
をキャッシュしなければ問題ないと言える。とはいえ、たいていのワークフローではnode_modules
をキャッシュしたい場合が多いので、当該事象の発生につながる。
- ワークフローのPuppeteerを使う前段で準備。
- キャッシュがないか古いときインストールスクリプトを手動実行する。
- キャッシュがある場合キャッシュから復元。
- Chromiumバイナリのインストール先である
/home/runner/.cache/puppeteer
フォルダをキャッシュする。
node node_modules/puppeteer/install.js
package.json
"scripts":{
"install:chrome": "node node_modules/puppeteer/install.js"
}
.github/actions/setup-puppeteer/action.yml
name: Setup puppeteer
description: Install Chromium
runs:
using: composite
steps:
- name: Get installed Playwright version
shell: bash
id: puppeteer-version
run: echo "PUPPETEER_VERSION=$( sh .github/scripts/get-puppeteer-version.sh )" >> $GITHUB_OUTPUT
- uses: actions/cache@v3
name: Setup puppeteer cache
id: puppeteer-cache
with:
path: ${{ env.PUPPETEER_CACHE_DIRECTORY }}
key: ${{ runner.os }}-puppeteer-${{ steps.puppeteer-version.outputs.PUPPETEER_VERSION }}
restore-keys: |
${{ runner.os }}-puppeteer-
env:
PUPPETEER_CACHE_DIRECTORY: "/home/runner/.cache/puppeteer"
- name: Install Chrome
run: |
if ${{ steps.puppeteer-cache.outputs.cache-hit != 'true' }}; then
pnpm install:chrome
fi
shell: bash
.github/scripts/get-puppeteer-version.sh
#!/bin/bash
cat package.json| grep "\"puppeteer\"" | head -n 1 | tr -d ' \":,' | tr -d 'puppeteer'
# 上と同様の出力を得られるが遅い
pnpm list -D | grep puppeteer | tr -d 'puppeteer '
# VSCode拡張のCode Runnerで計測
# 上:[Done] exited with code=0 in 0.1 seconds
# 下:[Done] exited with code=0 in 2.237 seconds
composite actionにした。やっていることはPuppeteerのバージョンをキャシュのキーにしつつ、キャッシュの有無によって処理を切り替えている。
注意点としてはcomposite action内ではif分岐が使えないのでシェル内に分岐処理を書く。