name: Next build cache
description: "Keep the Turbopack filesystem cache (`<app>/.next/cache`) that `open-next-build`'s `next build` writes on a sticky disk, one disk for every listed app, so an SST deploy that rebuilds starts warm. Apps with no next.config.mjs (cfx-ecs's SST app) are skipped."

inputs:
  apps:
    description: "Comma list of the SST apps this job builds, e.g. admin-dashboard,ui-sandbox."
    required: true
  stage:
    description: "`dev` or `prod`. Each stage's deploy commits its own disk, so a prod build never replaces the dev cache PRs read; a PR preview reads dev's."
    required: true

runs:
  using: composite
  steps:
    # Only `.next/cache`, never the build, so the disk can change how much
    # recompiles but not what ships. Nx caches the build itself, but restores it
    # only on a hit, when nothing builds; this covers the misses. Next keeps
    # `cache` when it cleans the dist dir, so the link survives every build.
    - name: List the apps' caches
      id: apps
      shell: bash
      env:
        APPS: ${{ inputs.apps }}
      run: |
        set -euo pipefail
        {
          echo "paths<<EOF"
          for app in ${APPS//,/ }; do
            if [ -f "packages/$app/next.config.mjs" ]; then
              echo "packages/$app/.next/cache"
            fi
          done
          echo "EOF"
        } >> "$GITHUB_OUTPUT"

    - if: ${{ steps.apps.outputs.paths != '' }}
      uses: ./.github/actions/sticky-cache
      with:
        key: next-build-${{ inputs.stage }}
        max_size_gb: "25"
        paths: ${{ steps.apps.outputs.paths }}

    # Turbopack loads a cache written under other settings and fails mid-build
    # (a loader runtime switch left `ChildProcessesBackend` cells it could no
    # longer read). Each cache carries a stamp of what wrote it; a mismatch
    # empties that cache, so the build starts cold instead of failing.
    - if: ${{ steps.apps.outputs.paths != '' }}
      name: Drop caches written under other build settings
      shell: bash
      env:
        PATHS: ${{ steps.apps.outputs.paths }}
        STAMP: ${{ hashFiles('bun.lock', '.bun-version', 'packages/*/next.config.mjs') }}
      run: |
        set -euo pipefail
        while IFS= read -r cache; do
          [ -n "$cache" ] || continue
          mkdir -p "$cache"
          if [ "$(cat "$cache/.cfx-build-stamp" 2>/dev/null || true)" != "$STAMP" ]; then
            echo "$cache: written under other build settings, starting cold"
            find "$cache" -mindepth 1 -delete
            echo "$STAMP" > "$cache/.cfx-build-stamp"
          fi
        done <<< "$PATHS"
