From 1dbbc934ccdc1fe2defc3c52d95a80eb40268569 Mon Sep 17 00:00:00 2001 From: Keith Williams Date: Tue, 30 Dec 2025 12:29:33 -0300 Subject: [PATCH] chore: use lookup-only cache check to skip deps job downloads (#26314) * fix(ci): skip yarn install in deps job when cache is hit The Install Dependencies / Yarn install & cache step in pr.yml is primarily for populating the cache when nothing is cached. When cache keys are found, we can skip the actual yarn install and let the workflow carry on quickly. This adds a skip-install-if-cache-hit parameter to the yarn-install action that allows skipping the install when node_modules cache is hit. This is enabled for the deps job in yarn-install.yml but not for other jobs that actually need node_modules for their work. Co-Authored-By: keith@cal.com * fix(ci): also skip playwright install in deps job when cache is hit Extends the skip-install-if-cache-hit parameter to the yarn-playwright-install action as well, so both yarn install and playwright install are skipped in the deps job when their respective caches are hit. Co-Authored-By: keith@cal.com * fix(ci): use lookup-only cache check to avoid downloading 1.2GB When skip-install-if-cache-hit is true, use actions/cache/restore@v4 with lookup-only: true to check if caches exist without downloading them. This avoids downloading ~1.2GB of cache data when we just want to verify caches exist in the deps job. The flow is now: 1. If skip-install-if-cache-hit is true, run lookup-only checks for all caches 2. If all caches hit, skip the entire restore + install flow (no downloads) 3. If any cache misses, fall back to normal restore + install + save behavior This optimization only applies when skip-install-if-cache-hit is set to true, so other jobs that need node_modules continue to work normally. Co-Authored-By: keith@cal.com * Apply suggestion from @keithwillcode * Apply suggestion from @keithwillcode * Apply suggestion from @keithwillcode * Apply suggestion from @keithwillcode * fix(ci): address @cubic-dev-ai feedback on cache conditions 1. yarn-install: Add 'all-caches-check' step to compute whether all three caches hit (not just node_modules). This ensures we only bail out when everything is cached, matching the PR description. 2. yarn-playwright-install: Fix backward compatibility for install step. In default mode, check playwright-cache.outputs.cache-hit (the restore step). In skip mode, check playwright-cache-check.outputs.cache-hit (lookup-only). Co-Authored-By: keith@cal.com --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/actions/yarn-install/action.yml | 54 +++++++++++++++++++ .../yarn-playwright-install/action.yml | 26 ++++++++- .github/workflows/yarn-install.yml | 4 ++ 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/.github/actions/yarn-install/action.yml b/.github/actions/yarn-install/action.yml index c48a484f0f..a930ce326d 100644 --- a/.github/actions/yarn-install/action.yml +++ b/.github/actions/yarn-install/action.yml @@ -15,6 +15,10 @@ inputs: node_version: required: false default: v20.x + skip-install-if-cache-hit: + description: "Skip yarn install if node_modules cache is hit. Use this for jobs that only need to check that cache exists." + required: false + default: "false" runs: using: "composite" @@ -29,9 +33,56 @@ runs: run: | echo "CACHE_FOLDER=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT + # When skip-install-if-cache-hit is true, first check if all caches exist without downloading (lookup-only mode) + # This avoids downloading ~1.2GB of cache data when we just want to verify caches exist + - name: Check yarn cache (lookup-only) + if: ${{ inputs.skip-install-if-cache-hit == 'true' }} + uses: actions/cache/restore@v4 + id: yarn-download-cache-check + with: + path: ${{ steps.yarn-config.outputs.CACHE_FOLDER }} + key: yarn-download-cache-${{ hashFiles('yarn.lock') }} + lookup-only: true + + - name: Check node_modules cache (lookup-only) + if: ${{ inputs.skip-install-if-cache-hit == 'true' }} + uses: actions/cache/restore@v4 + id: yarn-nm-cache-check + with: + path: | + **/node_modules/ + !**/.next/node_modules/ + key: ${{ runner.os }}-yarn-nm-cache-${{ hashFiles('yarn.lock', '.yarnrc.yml') }} + lookup-only: true + + - name: Check yarn install state cache (lookup-only) + if: ${{ inputs.skip-install-if-cache-hit == 'true' }} + uses: actions/cache/restore@v4 + id: yarn-install-state-cache-check + with: + path: .yarn/ci-cache/ + key: ${{ runner.os }}-yarn-install-state-cache-${{ hashFiles('yarn.lock', '.yarnrc.yml') }} + lookup-only: true + + # Compute whether all caches hit (only in skip mode) + - name: Check if all caches hit + if: ${{ inputs.skip-install-if-cache-hit == 'true' }} + id: all-caches-check + shell: bash + run: | + if [[ "${{ steps.yarn-download-cache-check.outputs.cache-hit }}" == "true" && \ + "${{ steps.yarn-nm-cache-check.outputs.cache-hit }}" == "true" && \ + "${{ steps.yarn-install-state-cache-check.outputs.cache-hit }}" == "true" ]]; then + echo "all-hit=true" >> $GITHUB_OUTPUT + else + echo "all-hit=false" >> $GITHUB_OUTPUT + fi + # Yarn rotates the downloaded cache archives, @see https://github.com/actions/setup-node/issues/325 # Yarn cache is also reusable between arch and os. + # Only restore if not in skip mode, or if skip mode but any cache check missed - name: Restore yarn cache + if: ${{ inputs.skip-install-if-cache-hit != 'true' || steps.all-caches-check.outputs.all-hit != 'true' }} uses: actions/cache@v4 id: yarn-download-cache with: @@ -40,6 +91,7 @@ runs: # Invalidated on yarn.lock changes - name: Restore node_modules + if: ${{ inputs.skip-install-if-cache-hit != 'true' || steps.all-caches-check.outputs.all-hit != 'true' }} id: yarn-nm-cache uses: actions/cache@v4 with: @@ -50,6 +102,7 @@ runs: # Invalidated on yarn.lock changes - name: Restore yarn install state + if: ${{ inputs.skip-install-if-cache-hit != 'true' || steps.all-caches-check.outputs.all-hit != 'true' }} id: yarn-install-state-cache uses: actions/cache@v4 with: @@ -57,6 +110,7 @@ runs: key: ${{ runner.os }}-yarn-install-state-cache-${{ hashFiles('yarn.lock', '.yarnrc.yml') }} - name: Install dependencies + if: ${{ inputs.skip-install-if-cache-hit != 'true' || steps.all-caches-check.outputs.all-hit != 'true' }} shell: bash run: | yarn install --inline-builds diff --git a/.github/actions/yarn-playwright-install/action.yml b/.github/actions/yarn-playwright-install/action.yml index 7d444283c1..ea3ae0469b 100644 --- a/.github/actions/yarn-playwright-install/action.yml +++ b/.github/actions/yarn-playwright-install/action.yml @@ -1,5 +1,10 @@ name: Install playwright binaries description: "Install playwright, cache and restore if necessary" +inputs: + skip-install-if-cache-hit: + description: "Skip playwright install if cache is hit. Use this for jobs that only need to check that cache exists." + required: false + default: "false" runs: using: "composite" steps: @@ -7,7 +12,23 @@ runs: shell: bash id: playwright-version run: echo "PLAYWRIGHT_VERSION=$(node -e "console.log(require('./package.json').devDependencies['@playwright/test'])")" >> $GITHUB_ENV + + # When skip-install-if-cache-hit is true, first check if cache exists without downloading (lookup-only mode) + - name: Check playwright cache (lookup-only) + if: ${{ inputs.skip-install-if-cache-hit == 'true' }} + id: playwright-cache-check + uses: actions/cache/restore@v4 + with: + path: | + ~/Library/Caches/ms-playwright + ~/.cache/ms-playwright + ${{ github.workspace }}/node_modules/playwright + key: ${{ runner.os }}-playwright-${{ env.PLAYWRIGHT_VERSION }} + lookup-only: true + + # Only restore cache if not in skip mode, or if skip mode but cache check missed - name: Cache playwright binaries + if: ${{ inputs.skip-install-if-cache-hit != 'true' || steps.playwright-cache-check.outputs.cache-hit != 'true' }} id: playwright-cache uses: actions/cache@v4 with: @@ -16,7 +37,10 @@ runs: ~/.cache/ms-playwright ${{ github.workspace }}/node_modules/playwright key: ${{ runner.os }}-playwright-${{ env.PLAYWRIGHT_VERSION }} + + # In default mode: run if playwright-cache missed + # In skip mode: run if playwright-cache-check missed (but cache restore step was also skipped) - name: Yarn playwright install - if: steps.playwright-cache.outputs.cache-hit != 'true' + if: ${{ (inputs.skip-install-if-cache-hit != 'true' && steps.playwright-cache.outputs.cache-hit != 'true') || (inputs.skip-install-if-cache-hit == 'true' && steps.playwright-cache-check.outputs.cache-hit != 'true') }} shell: bash run: yarn playwright install --with-deps diff --git a/.github/workflows/yarn-install.yml b/.github/workflows/yarn-install.yml index 81eb75d630..e9e4c6ca59 100644 --- a/.github/workflows/yarn-install.yml +++ b/.github/workflows/yarn-install.yml @@ -15,4 +15,8 @@ jobs: - uses: actions/checkout@v4 - uses: ./.github/actions/dangerous-git-checkout - uses: ./.github/actions/yarn-install + with: + skip-install-if-cache-hit: "true" - uses: ./.github/actions/yarn-playwright-install + with: + skip-install-if-cache-hit: "true"