♻️

turbo run するときにパススルー引数があるとcache missになる

2025/02/14に公開

おつかれさまです。オウンドメディア担当の水谷です。
自チームのTurborepoを利用しているモノレポでCIが遅いな~と思っていたらキャッシュが効いてなかったのでその対応をしました。

TL;DR

turboのパススルー引数を使わないようにする
yarn backend:test --coverageyarn backend:test:coverage
(使わなくて済むようにtask(pipeline)・scriptsを調整する)

事象

レバテック開発部ではGitHubを利用しており、PR作成時にGitHub ActionsでCIタスクを実行しています。
自チームのバックエンドアプリでもそんなCIタスクとしてlintやUT/ITなどを実行しています。
CIタスクのworkflowはこんな感じ[1]

backend.ci.yml
jobs:
  setup:
    ...

  unit_test:
    ...

  integration_test:
    ...
    steps:
      - name: Execute Migration # migrationの実行
        run: yarn backend:migration && yarn shared:migration
        env:
          NODE_ENV: test

      - name: Run Tests # テストの実行
        run: yarn backend:test:integration --coverage
        env:
          NODE_ENV: test

そしてこれの実行ログを見ると

integration_testのログ
Execute Migration
  @my-apps/domain:build
    cache miss, executing e05d80531f8d5d09
  ...
Run Tests
  @my-apps/domain:build
    cache miss, executing b8214611ebcaaa7f
  ...

同じインスタンス内の同じbuildなのにキャッシュを使えていない😢
これでは無駄な処理なので解決に乗り出しました。

対応

調査

上のログをよく見るとそもそもハッシュ値が違っておりこれがキャッシュが使えていない原因のようです。
ソースコードを書き換えるような処理は当然CI中にはしていませんが、それ以外にもハッシュ値を計算する要素があるということなのか、、、
ということで公式ドキュメントを見てみます。

https://turbo.build/repo/docs/crafting-your-repository/caching#task-inputs

結構色んな要素がありますが、workflowと見比べて↓が原因のようです

Arbitrary passthrough arguments
turbo build -- --arg=value will miss cache compared to turbo build or turbo build -- --arg=diff

修正

  1. アプリ内にカバレッジ取得用のscriptを新しく作成
    src/apps/backend/package.json
      "scripts": {
        "test:integration": "jest --runInBand --config jest.config.integration.js",
    +   "test:integration:coverage": "jest --runInBand --coverage --config jest.config.integration.js",
    
  2. rootのscriptsに上を実行するscriptを新しく作成
    (repository root)/package.json
      "scripts": {
        "backend:test:integration": "turbo run test:integration --filter=@my-apps/backend --",
    +   "backend:test:integration:coverage": "turbo run test:integration:coverage --filter=@my-apps/backend",
    
  3. turbo.jsonにもpipelineを登録
    turbo.json
    + "test:integration:coverage": {
    +   "dependsOn": ["^build"],
    +   "cache": false
    + },
    
  4. CIで実行するコマンドを上で作成したscriptに差し替え
    backend.ci.yml
        - name: Run Tests # テストの実行
    -     run: yarn backend:test:integration --coverage
    +     run: yarn brand:test:integration:coverage
    
integration_testのログ
Execute Migration
  @my-apps/domain:build
    cache miss, executing e05d80531f8d5d09
  ...
Run Tests
  @my-apps/domain:build
    cache hit, replaying logs e05d80531f8d5d09
  ...

無事ハッシュ値が同じになりcache hitするようになりました👏

脚注
  1. 今回の事象・対応以外にも改善の余地はありますがそれはまたの機会に ↩︎

レバテック開発部

Discussion