ブログ一覧

playwright install --with-deps で CI が 15 分止まる原因

更新: Web開発者向け

GitHub Actions の E2E テストジョブが 15 分で落ちました。結果は failure ではなく cancelled です。

ログを遡ると、時間を食っていたのはテストではなく playwright install --with-deps でした。それも、ブラウザのダウンロードではなく数 MB のフォントパッケージの取得に数分単位でかかっていました

まず実ログ

2026-08-19、ubuntu-latest ランナーでの実際のログです。

Get:2 http://azure.archive.ubuntu.com/ubuntu noble/universe amd64 fonts-ipafont-gothic all 00303-21ubuntu1 [3513 kB]
Get:3 http://azure.archive.ubuntu.com/ubuntu noble/main amd64 fonts-freefont-ttf all 20211204+svn4273-2 [5641 kB]
##[error]The operation was canceled.

タイムスタンプで追うと、3.5MB の fonts-ipafont-gothic に約 6 分、5.6MB の fonts-freefont-ttf に約 9 分かかっています。合わせて 9MB に 15 分です。ジョブは timeout-minutes: 15 に到達して 15 分 21 秒で強制終了されました。

紛らわしい点が 2 つあります。

  • 結果が failure ではなく cancelled になる。タイムアウトによる強制終了は cancelled 扱いなので、テストの失敗を探しても何も見つかりません。私は最初、誰かがジョブを手で止めたのかと考えました
  • 再現するとは限らない。apt がどのミラーに繋がるか、そのミラーがそのとき遅いかどうかの問題なので、同じワークフローが別の日にはあっさり通ることもあり得ます。この種の「引き次第の遅さ」は原因の特定を遅らせます

なぜフォントに 15 分かかるのか

playwright install --with-deps は 2 つのことをします。ブラウザバイナリのダウンロードと、apt-get によるシステム依存パッケージ(ライブラリとフォント類)のインストールです。

前者は Playwright 側の CDN から落ちるので比較的安定しています。問題は後者で、ubuntu-latest ランナーの apt は Azure 上のミラー(azure.archive.ubuntu.com)を向いており、ここの転送速度はこちらから制御できません。遅いミラーに当たった日は、数 MB のパッケージが数百 KB/分でしか落ちてきません。

actions/cache でブラウザバイナリをキャッシュする定番の対策がありますが、apt の側には効きません。キャッシュがヒットしても --with-deps 相当のシステム依存インストールは走るので、ミラーの引きが悪い日はキャッシュがあっても同じ場所で止まります

対処: インストールというステップ自体を消す

対処は、Playwright 公式のコンテナイメージでジョブを実行することにしました。ブラウザもシステム依存もフォントも焼き込み済みなので、playwright install のステップそのものが不要になります。apt ミラーとの通信が発生しなければ、ミラーの当たり外れという変数が消えます。

修正後のワークフローの全体です。

jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    container:
      image: mcr.microsoft.com/playwright:v1.62.1-noble
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22 }
      - run: npm ci
      - run: npm run build
      - run: npm test
      - run: npm run e2e
        env: { HOME: /root }
      - uses: actions/upload-artifact@v4
        if: failure()
        with: { name: playwright-report, path: playwright-report/ }

移行時に踏んだポイント

  • イメージタグは `@playwright/test` のバージョンと完全一致させるmcr.microsoft.com/playwright:v1.62.1-noblev1.62.1 の部分です。ここがズレると、コンテナ内のブラウザとテストランナーの期待バージョンが食い違い、実行時にブラウザの再ダウンロードが走ります。インストールを消すために入れたコンテナで再ダウンロードが始まったら本末転倒なので、Playwright を更新するときはイメージタグも同時に上げる運用になります
  • `HOME: /root` を明示する。コンテナ内は root 実行ですが、環境によっては HOME が正しく設定されず、ブラウザの起動に失敗する場合があります。E2E ステップに env: { HOME: /root } を付けておくのが安全です
  • `timeout-minutes` は保険として残す。原因を消したからといって上限を外すと、次に別の理由でハングしたときに 6 時間(既定値)課金されてから気づくことになります

どこで止まるか

この対処にも残るコストはあります。コンテナイメージの取得はジョブごとに発生し、公式イメージは軽くありません。それでも、取得元が Microsoft のコンテナレジストリ 1 か所になるので、apt ミラーの当たり外れのような予測不能な分散はなくなります。「速くなる」というより「遅さが読めるようになる」対処です。

また、runs-on のランナー環境とコンテナ内の環境は別物なので、ジョブ内でランナー側のツール(プリインストールされた CLI など)に依存していた場合は動かなくなります。今回のジョブは npm スクリプトで完結していたので、この影響はありませんでした。

この構成で気をつけること

  • `playwright install --with-deps` の遅さはブラウザではなく apt 側で起きることがある。ログのタイムスタンプでどのパッケージに時間がかかったかを先に見る
  • タイムアウトは cancelled と表示される。failure だけ監視していると時間切れを見落とす
  • キャッシュはブラウザには効くが、apt ミラーの遅さには効かない
  • コンテナ移行後は、Playwright とイメージタグのバージョンを揃えて上げる運用を忘れない

なお、公式コンテナでの実行自体は Playwright のドキュメントにも載っている定番の構成です。この記事の価値があるとすれば、「定番の対策をなぜ採るのか」を実ログ付きで残したことだと思います。フォント 2 つに 15 分、という具体的な数字を見てからだと、インストールステップを消すという判断に迷いがなくなります。

関連

この記事をシェア