メインコンテンツへスキップ
ブログサイトのロゴsui Tech Blog
7分で読めます

GitHub Actions で APT 依存をキャッシュしてワークフローを高速化する

GitHub Actions で agent-browser を使う際の APT 依存インストールを 4 つのキャッシュ戦略で検証しました。.deb ファイルをキャッシュして dpkg で直接インストールする方式でキャッシュヒット時の apt-get update をスキップでき、ワークフローの実行時間を 36〜45 秒から 16〜19 秒へ 50〜60% 削減できました。本記事では既存ライブラリの Node.js 廃止リスクも含めた各アプローチの比較と、自前実装の composite action を紹介します。

GitHub Actions のランナーはジョブ実行のたびにクリーンな状態で起動します。ビルドの再現性を保証するための設計ですが、「毎回クリーン」ということはシステム依存もゼロからそろえ直すことを意味し、ブラウザを含むプロジェクトでは実行時間に直接影響します。

Vercel Labs が開発した agent-browser は AI エージェント向けのブラウザ操作ライブラリです。実際の Chrome を動かすため、Ubuntu ランナーではシステム依存パッケージも合わせてインストールが必要です。GitHub Actions 上で agent-browser を使い始めると、ワークフロー実行ごとにこのインストールが発生し、実行時間が膨らんでいきます。

「ランナーが毎回クリーンなのだからシステム依存のキャッシュは無理」と思い込んでいましたが、調べると APT1 パッケージも .deb ファイル単位でキャッシュできます。この記事では、その発見に至るまでの各アプローチを順番に検証し、最終的に CI 実行時間を 50〜60% 削減した構成を紹介します。

ベースラインを計測する

まずキャッシュなしの CI で実行時間を計測しました。

項目 内容
ランナー ubuntu-latest(Ubuntu 24.04)
agent-browser npm install -g agent-browser(グローバルインストール)
Chrome Chrome for Testing 148.0.7778.97(175MB)
検証サイト https://claude-code-log.com (筆者開発のサイト)
計測方法 各アプローチを複数回(4〜9回)実行して実行時間の最小〜最大を記録
name: ベースライン計測(キャッシュなし)
 
permissions: {}
 
on:
  push:
    branches:
      - main
 
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
 
jobs:
  baseline:
    name: キャッシュなし
    timeout-minutes: 15
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
 
      - name: agent-browser をインストール
        run: npm install -g agent-browser
 
      - name: Chrome とシステム依存をインストール
        run: agent-browser install --with-deps
 
      - name: ブラウザ操作(open → snapshot → close)
        run: |
          agent-browser batch \
            "open https://claude-code-log.com" \
            "snapshot -i" \
            "close"

計測結果は合計 43 秒で、 agent-browser install --with-deps が 33 秒を占めています。

ボトルネックを深掘りする

--with-deps が内部で実行する apt-get install のログを確認してみましょう。

0 upgraded, 2 newly installed, 0 to remove and 53 not upgraded.
The following NEW packages will be installed:
  fonts-freefont-ttf fonts-noto-cjk
Need to get 66.9 MB of archives.

--with-deps は内部で 35 パッケージのリストを apt-get に渡しますが、実際に新規インストールされたのは fonts-freefont-ttffonts-noto-cjk の 2 パッケージだけです。残り 33 パッケージは Ubuntu 24.04 にすでに含まれており、66.9MB のフォントデータのダウンロードが大半の時間を占めていました。

ボトルネックが特定できたので、改善アプローチを整理します。

アプローチ 概要 期待効果
Chrome のみキャッシュ ~/.agent-browser/browsers/ をキャッシュ Chrome ダウンロード(2.5秒)をスキップ
最小パッケージ手動指定 不足する 2 パッケージのみ apt install APT インストール対象を削減
APT パッケージキャッシュ .deb ファイルをキャッシュし dpkg2 でインストール apt-get update とダウンロードをスキップ

各アプローチを検証する

Chrome バイナリのみキャッシュ

~/.agent-browser/browsers/actions/cache でキャッシュして Chrome の再ダウンロードをスキップする方法です。このアプローチの検証ワークフローはこちらです。

キャッシュヒット時のログで ✓ Chrome 148.0.7778.97 is already installed が確認でき、Chrome のダウンロードはスキップされています。ただしシステム依存の apt-get は毎回実行されるため、ほとんど改善しませんでした。

ベースライン キャッシュヒット(4回)
合計 36〜45秒 36〜46秒

Chrome のダウンロードの 2.5 秒を節約しても、APT の 30 秒超は毎回実行されます。ボトルネック自体に届いていないため、ほぼ改善しませんでした。

最小パッケージの手動指定

--with-deps を使わず、実際に不足している 2 パッケージだけを直接指定する方法です。このアプローチの検証ワークフローはこちらです。

ベースライン 実測範囲(5回)
合計 36〜45秒 24〜30秒

apt-get install の対象が 35 パッケージから 2 パッケージに減って速くなりましたが、apt-get update は毎回実行されます。フォント 2 パッケージのダウンロードとインストールで約 20 秒かかるため、Chrome キャッシュの有無に関係なく毎回同じ時間がかかります。

APT パッケージキャッシュ

.deb ファイルそのものをキャッシュし、ヒット時は apt-get update なしで dpkg から直接インストールする方法です。

既存ライブラリを調べると、最も使われているのが awalsh128/cache-apt-pkgs-action(★346)でした。このアクションを使った検証ワークフローはこちらです。
動作確認では最速(ヒット時 4 秒)でしたが、内部で actions/cache@v4(Node.js 20)を使用しています。そのため、Node.js 20 の廃止予定(2026 年 9 月 16 日)以降に動作しなくなる可能性があり、Issue #193PR #198 で議論されているものの、メンテナンスの動きが止まっています。

もう 1 つ調べたのが gerlero/apt-install です。このアクションを使った検証ワークフローはこちらです。シェルスクリプトのみで構成された composite action3 で、内部の actions/cache@v5 は Node.js 24 を使用しているため廃止リスクはありません。ただしキャッシュヒット時も apt-get update を実行するため、ヒット時でも 20 秒かかりました。

実装 実測範囲(4回) Node.js 問題
cache-apt-pkgs-action 13〜19秒 Node.js 20 廃止予定
gerlero 24〜36秒 なし

自前実装で両方の問題を解決する

gerlero/apt-install のしくみを参考に、キャッシュヒット時は apt-get update をスキップする composite action を自作しました。actions/cache/restore@v5actions/cache/save@v5(Node.js 24)のみを使用しており、外部依存はありません。

.github/actions/apt-cache/action.yml
name: "apt キャッシュインストール"
description: "apt パッケージを actions/cache@v5 でキャッシュしてインストールする(Node.js 不使用)"
 
inputs:
  packages:
    description: "インストールするパッケージ(スペース区切り)"
    required: true
  cache-version:
    description: "キャッシュキーの手動バスト用バージョン"
    default: "1"
 
runs:
  using: "composite"
  steps:
    - name: キャッシュを復元
      id: cache
      uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
      with:
        path: ~/.apt-debs
        key: apt-${{ runner.arch }}-${{ runner.os }}-v${{ inputs.cache-version }}-${{ inputs.packages }}
 
    - name: パッケージをダウンロード
      if: steps.cache.outputs.cache-hit != 'true'
      shell: bash
      env:
        PACKAGES: ${{ inputs.packages }}
      run: |
        sudo apt-get update -qq
        mkdir -p ~/.apt-debs
        cd ~/.apt-debs
        apt-get download $PACKAGES
 
    - name: キャッシュを保存
      if: steps.cache.outputs.cache-hit != 'true'
      uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
      with:
        path: ~/.apt-debs
        key: ${{ steps.cache.outputs.cache-primary-key }}
 
    - name: パッケージをインストール
      shell: bash
      run: sudo dpkg --install --recursive --skip-same-version ~/.apt-debs

この composite action を呼び出すワークフローです。

name: 計測(apt キャッシュ / 自前実装)
 
permissions: {}
 
on:
  push:
    branches:
      - main
 
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
 
jobs:
  apt-cache-custom:
    name: apt キャッシュあり(自前実装)
    timeout-minutes: 15
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
 
      - name: agent-browser をインストール
        run: npm install -g agent-browser
 
      - name: agent-browser バージョンを取得
        id: ab-version
        run: echo "version=$(agent-browser --version)" >> "$GITHUB_OUTPUT"
 
      - name: Chrome バイナリをキャッシュから復元
        id: chrome-cache
        uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
        with:
          path: ~/.agent-browser/browsers
          key: ${{ runner.os }}-chrome-${{ steps.ab-version.outputs.version }}
 
      - name: 不足パッケージをキャッシュ付きでインストール
        uses: ./.github/actions/apt-cache
        with:
          packages: fonts-freefont-ttf fonts-noto-cjk
 
      - name: Chrome をインストール(キャッシュミス時のみ実際にダウンロード)
        if: steps.chrome-cache.outputs.cache-hit != 'true'
        run: agent-browser install
 
      - name: ブラウザ操作(open → snapshot → close)
        run: |
          agent-browser batch \
            "open https://claude-code-log.com" \
            "snapshot -i" \
            "close"

全アプローチの比較です。

No アプローチ キャッシュ状態 実測範囲
1 ベースライン キャッシュなし(毎回) 36〜45秒
2 Chrome のみ Chrome ヒット・APT 毎回 36〜46秒
3 最小パッケージ Chrome ヒット・APT 毎回 24〜30秒
4 cache-apt-pkgs-action Chrome + APT ヒット 13〜19秒
5 gerlero Chrome + APT ヒット 24〜36秒
6 自前実装 Chrome + APT ヒット 16〜19秒

自前実装は cache-apt-pkgs-action とほぼ同等の速度(16〜19 秒)を保ちながら廃止リスクがなく、現時点では最もバランスが良い構成です。今後 cache-apt-pkgs-action が Node.js 24 に対応すれば、シンプルに既存アクションへ切り替えてよいと思います。重要なのは「APT キャッシュという戦略を選ぶこと」であって、実装の選択は Node.js 対応状況という運用上の話にすぎません。

注意点

Ubuntu-latest が更新された場合の影響

今回の「新規インストールが 2 パッケージだけ」という結果は Ubuntu 24.04 時点の依存構成によるものです。Ubuntu-latest が更新されて今まで含まれていたパッケージが削除された場合、Chrome が起動できずブラウザ操作ステップで落ちる可能性はゼロではありません。コアなシステムライブラリが削除されることは考えにくいので、現実的なリスクは低いですが、念頭に置いておくとよいでしょう。

インストール対象パッケージを変更した場合は inputs.packages が変わるためキャッシュキーが自動的に変わります。cache-version の手動バストが必要になるのは、同じパッケージ構成のままキャッシュを強制リセットしたい場合だけです。

さらに短縮するには

今回のキャッシュでは .deb のダウンロードをスキップできましたが、キャッシュミス時の apt-get update(約 10 秒)は毎回発生します。さらなる短縮にはカスタムランナーイメージが有効ですが、GitHub Team / Enterprise プランが必要です。個人リポジトリでは現実的な選択肢ではないため、今回は対象外としました。

まとめ

  • ubuntu-latest には Chromium の依存パッケージのほとんどがすでに含まれており、追加インストールが必要なのはフォント 2 パッケージ(fonts-freefont-ttffonts-noto-cjk)だけだった
  • 「ランナーがクリーンなのでシステム依存のキャッシュは無理」は思い込みで、.deb ファイル単位でキャッシュして dpkg で直接インストールする方法が有効
  • APT パッケージキャッシュで CI 実行時間を 50〜60% 削減できた(36〜45 秒 → 16〜19 秒)
  • 既存の cache-apt-pkgs-action は速いが Node.js 20 廃止リスクがあり、現時点では自前実装がリスクと速度のバランスが良い

参考

github.com のアイコン
github.com

GitHub - vercel-labs/agent-browser: Browser automation CLI for AI agents

Browser automation CLI for AI agents. Contribute to vercel-labs/agent-browser development by creating an account on GitHub.

github.com のアイコン
github.com

GitHub - awalsh128/cache-apt-pkgs-action: Cache APT packages in GitHub Actions

Cache APT packages in GitHub Actions. Contribute to awalsh128/cache-apt-pkgs-action development by creating an account on GitHub.

github.com のアイコン
github.com

Bump off of Node 20 actions (fixes #191) by immoseb · Pull Request #193 · awalsh128/cache-apt-pkgs-action

Fixes #191 Related: https://github.com/actions/cache/releases/tag/v5.0.3 https://github.com/actions/upload-artifact/releases/tag/v7.0.0 @awalsh128 for your consideration 🙏

github.com のアイコン
github.com

GitHub - gerlero/apt-install: 💾 GitHub Action to install and cache APT packages

💾 GitHub Action to install and cache APT packages. Contribute to gerlero/apt-install development by creating an account on GitHub.

github.com のアイコン
github.com

GitHub - Suntory-N-Water/github-actions-agent-browser-cache-strategy

Contribute to Suntory-N-Water/github-actions-agent-browser-cache-strategy development by creating an account on GitHub.

Footnotes

  1. Advanced Package Tool の略。Ubuntu などの GNU/Linux ディストリビューションで使われるパッケージ管理システムです。

  2. .deb パッケージファイルを直接インストール・管理するローレベルのツール。apt-get の内部でも使われています。

  3. GitHub Actions の composite action は、複数のステップをまとめた再利用可能なアクションを YAML と shell script だけで定義する方式。Node.js 等のランタイムが不要な点が特徴です。

理解度チェック

問題1: agent-browser を ubuntu-latest 環境で実行する際、実際に不足しており `apt-get` で新規インストールが必要だったパッケージは何でしたか?

  • 2つのフォントパッケージ(fonts-freefont-ttf, fonts-noto-cjk)

    正解正解です!

    Ubuntu 24.04 には Chromium の依存パッケージの大部分がすでに含まれており、不足していたのはこの2つのフォントパッケージのみでした。

  • agent-browser が要求する35個の依存ライブラリすべて

    不正解もう一度考えてみましょう!

    35パッケージが指定されますが、そのうち33パッケージはすでにOSに含まれていました。

  • Chrome ブラウザ本体のバイナリ

    不正解もう一度考えてみましょう!

    Chrome のバイナリは別でダウンロード・キャッシュされるものであり、APT パッケージの話ではありません。

  • Node.js の最新バージョン

    不正解もう一度考えてみましょう!

問題2: この記事において、CI の実行時間を最も効果的に短縮(50〜60%削減)した最終的なキャッシュ戦略はどれですか?

  • .deb ファイルをキャッシュし、ヒット時は `apt-get update` をスキップして `dpkg` で直接インストールする

    正解正解です!

    この方法により、時間のかかるパッケージのダウンロードと `apt-get update` をスキップでき、CI実行時間を大幅に短縮できました。

  • Chrome バイナリをキャッシュし、APT パッケージのインストールはそのまま実行する

    不正解もう一度考えてみましょう!

    Chrome のダウンロードはスキップできても、APT のインストールに毎回30秒以上かかるため、ほとんど時間短縮になりませんでした。

  • 不要なパッケージを除外し、不足している2パッケージのみを毎回 `apt-get install` で指定する

    不正解もう一度考えてみましょう!

    対象は減りますが、`apt-get update` とパッケージのダウンロードが毎回発生するため、期待したほどの効果は得られませんでした。

  • GitHub Team プランを契約し、カスタムランナーイメージを利用する

    不正解もう一度考えてみましょう!

    カスタムランナーイメージは有効な手段ですが、個人リポジトリでは現実的な選択肢ではないとして今回の対象外とされています。

関連記事