ci: restore main's Vitest transform cache in PR unit shards (#34512)

* ci: restore main's Vitest transform cache in PR unit shards

Main produces per-shard transform caches on a schedule; PR shards restore
the newest one for the same config/lockfile/runtime policy. A Vitest cache
key generator folds each literal specifier's resolution candidates into the
per-module key so newly added files that shadow a resolution invalidate the
importer, and bails on glob-expanded dynamic imports.

* ci: list the resolution key plugin in the node tsconfig project

* ci: accept Vitest's CACHEDIR.TAG when sealing the unit module cache

Vitest 5.0.5 tags its cache root, which made every seal fail with
'invalid cache entry name' so no producer cache was ever saved.

* ci: reseed the unit module cache when any cache-key input lands on main

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
OrcaWin
2026-10-27 20:04:56 -07:00
committed by GitHub
co-authored by Claude OrcaWin
parent 6bb0c14a98
commit 8b64ec281a
11 changed files with 273 additions and 35 deletions
+2
View File
@@ -888,6 +888,8 @@ jobs:
node_versions: '["24"]'
runner: blacksmith-8vcpu-ubuntu-2404
phase_diagnostics: true
# Restore main's transform cache; the `ci:cold-unit-cache` label or ORCA_UNIT_MODULE_CACHE=off forces cold.
module_cache: ${{ (vars.ORCA_UNIT_MODULE_CACHE == 'off' || contains(github.event.pull_request.labels.*.name, 'ci:cold-unit-cache')) && 'off' || 'warm' }}
shards: ${{ needs.preflight.outputs.shards }}
run_shards: ${{ needs.code_paths.outputs.mobile_ci_tools != 'true' }}
run_relay_integration: ${{ needs.code_paths.outputs.relay_integration != 'false' || needs.code_paths.outputs.orcad_browser == 'true' }}
+50
View File
@@ -0,0 +1,50 @@
name: Unit transform cache producer
# Cold full unit run on main that publishes per-shard Vitest transform caches for PRs.
on:
schedule:
- cron: '17 */6 * * *'
workflow_dispatch:
push:
branches: [main]
# Cache-key inputs (see ci-unit-module-cache.mjs) change the key; reseed right away.
paths:
- '.github/workflows/unit-module-cache.yml'
- '.github/workflows/unit-tests.yml'
- 'config/vitest.config.ts'
- 'config/scripts/vitest*'
- 'config/scripts/ci-unit-module-cache*.mjs'
- 'config/patches/**'
- 'config/scripts/workspace-source-exports.mjs'
- 'config/dark-build-switches.cjs'
- 'config/pnpmfile.cjs'
- '.npmrc'
- '**/package.json'
- '**/tsconfig*.json'
- 'pnpm-lock.yaml'
- 'pnpm-workspace.yaml'
- 'config/.bun-version'
concurrency:
group: unit-module-cache-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
unit_plan:
if: github.ref == 'refs/heads/main'
uses: ./.github/workflows/unit-plan.yml
test:
needs: unit_plan
uses: ./.github/workflows/unit-tests.yml
with:
# Match the PR unit matrix so the cache key's runtime and shard fields line up.
node_versions: '["24"]'
runner: blacksmith-8vcpu-ubuntu-2404
shards: ${{ needs.unit_plan.outputs.shards }}
module_cache: cold
artifact_prefix: cache-producer-unit
run_relay_integration: false
+2
View File
@@ -35,6 +35,8 @@ jobs:
env:
ORCA_UNIT_SELECTION_MODE: ${{ inputs.selection_mode }}
ORCA_PULL_REQUEST_DRAFT: ${{ github.event.pull_request.draft }}
# Same count as PR preflight so transform cache shard keys line up.
ORCA_UNIT_FULL_SHARD_COUNT: ${{ vars.ORCA_UNIT_FULL_SHARD_COUNT || '5' }}
run: node config/scripts/ci-unit-plan.mjs
- uses: actions/upload-artifact@v7
continue-on-error: true
+11 -8
View File
@@ -32,7 +32,7 @@ on:
type: string
module_cache:
description: Transform cache policy (off, cold producer, or warm exact restore).
description: Transform cache policy (off, cold producer, or warm restore).
default: 'off'
type: string
@@ -110,19 +110,22 @@ jobs:
ORCA_UNIT_CACHE_NAMESPACE: ${{ inputs.module_cache_namespace }}
run: node config/scripts/ci-unit-module-cache.mjs identity
- name: Restore exact unit module cache
# The key pins config, plugins, lockfile and runtimes; the newest producer for it wins.
# Source edits are keyed per module by Vitest plus vitest-module-cache-resolution-key.ts.
- name: Restore unit module cache
id: module-cache-restore
if: inputs.module_cache == 'warm' && steps.module-cache.outputs.key != ''
continue-on-error: true
uses: actions/cache/restore@v5
with:
path: ${{ steps.module-cache.outputs.path }}
key: ${{ steps.module-cache.outputs.key }}
key: ${{ steps.module-cache.outputs.key }}-${{ github.sha }}
restore-keys: ${{ steps.module-cache.outputs.key }}-
- name: Validate restored unit module cache or use cold transforms
if: steps.module-cache.outputs.key != ''
env:
ORCA_UNIT_CACHE_RESTORE_HIT: ${{ steps.module-cache-restore.outputs.cache-hit }}
ORCA_UNIT_CACHE_RESTORE_HIT: ${{ steps.module-cache-restore.outputs.cache-matched-key != '' }}
run: node config/scripts/ci-unit-module-cache.mjs prepare
- uses: actions/download-artifact@v8
@@ -155,11 +158,11 @@ jobs:
- name: Seal unit module cache
id: module-cache-seal
# Only cold main/seeded producers publish; PRs consume and never seed each other.
if: >-
success() && steps.module-cache.outputs.key != '' &&
steps.module-cache-restore.outputs.cache-hit != 'true' &&
(github.event_name == 'pull_request' ||
github.ref == 'refs/heads/main' && github.event_name != 'pull_request' ||
inputs.module_cache == 'cold' &&
(github.ref == 'refs/heads/main' && github.event_name != 'pull_request' ||
inputs.module_cache_seed && github.event_name == 'workflow_dispatch')
run: node config/scripts/ci-unit-module-cache.mjs seal
@@ -169,7 +172,7 @@ jobs:
uses: actions/cache/save@v5
with:
path: ${{ steps.module-cache.outputs.path }}
key: ${{ steps.module-cache.outputs.key }}
key: ${{ steps.module-cache.outputs.key }}-${{ github.run_id }}-${{ github.run_attempt }}
- name: Upload unit shard assignment
if: always()