openclaw/.github/workflows/vitest-cache-warm.yml
2026-09-01 21:12:54 -07:00

215 lines
10 KiB
YAML

name: Vitest Cache Warm
on:
push:
branches: [main]
workflow_dispatch:
repository_dispatch:
types: [vitest-cache-warm]
schedule:
- cron: "17 8 * * *"
permissions:
contents: read
concurrency:
group: vitest-cache-warm-${{ github.ref }}
cancel-in-progress: false
jobs:
warm:
# Shared CI cache publication is isolated from pull-request execution.
# Trusted release/proof workflows may save only through the same authority contract.
if: github.repository == 'openclaw/openclaw'
runs-on: ${{ matrix.platform == 'macos' && 'macos-15' || (vars.OPENCLAW_CI_RUNNER_BACKEND == 'github' && 'ubuntu-24.04' || 'blacksmith-8vcpu-ubuntu-2404') }}
timeout-minutes: 60
strategy:
# Each platform publishes its own cache namespace independently.
fail-fast: false
matrix:
platform: [linux, macos]
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup Node environment
id: setup-node-env
uses: ./.github/actions/setup-node-env
with:
build-all-cache-scope: ${{ matrix.platform == 'linux' && 'full' || '' }}
cache-mode: read-write
dependency-cache: ${{ matrix.platform == 'linux' && 'true' || 'false' }}
install-bun: "false"
node-compile-cache: ${{ matrix.platform == 'linux' && 'true' || 'false' }}
node-compile-cache-scope: "test"
vitest-fs-cache: ${{ matrix.platform == 'linux' && 'true' || 'false' }}
# Setup owns the completed toolchain and dependency trees. Publish them
# before build and transform warming delay unrelated readers.
- name: Save Node toolchain cache
if: ${{ steps.setup-node-env.outputs.cache-mode == 'read-write' && runner.os != 'Windows' && runner.environment != 'github-hosted' && steps.setup-node-env.outputs.node-toolchain-populated == 'true' && steps.setup-node-env.outputs.node-toolchain-cache-matched-key != steps.setup-node-env.outputs.node-toolchain-cache-key }}
continue-on-error: true
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.setup-node-env.outputs.node-toolchain-cache-path }}
key: ${{ steps.setup-node-env.outputs.node-toolchain-cache-key }}
- name: Save exact dependency cache
if: ${{ steps.setup-node-env.outputs.cache-mode == 'read-write' && steps.setup-node-env.outputs.dependency-cache-key != '' && steps.setup-node-env.outputs.dependency-cache-hit != 'true' }}
continue-on-error: true
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
node_modules
ui/node_modules
packages/*/node_modules
extensions/*/node_modules
examples/*/node_modules
.cache/openclaw-pnpm-store
key: ${{ steps.setup-node-env.outputs.dependency-cache-key }}
# Seal this owner before the full build creates sibling package dist trees.
# Those trees are resolution topology, but intentionally are not in this payload.
- name: Restore native SDK boundary cache
id: extension-package-boundary-cache
if: ${{ matrix.platform == 'linux' && steps.setup-node-env.outputs.cache-mode == 'read-write' }}
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
packages/plugin-sdk/dist
.artifacts/extension-package-boundary/plugins
.artifacts/extension-package-boundary/*.json
.artifacts/extension-package-boundary/compile
key: ${{ runner.os }}-extension-package-boundary-v4-${{ github.sha }}
restore-keys: |
${{ runner.os }}-extension-package-boundary-v4-
- name: Prepare native SDK boundary cache
if: ${{ matrix.platform == 'linux' }}
run: node --import ./scripts/tsx.mjs scripts/prepare-extension-package-boundary-artifacts.mts --mode=package-boundary
- name: Save native SDK boundary cache
if: ${{ matrix.platform == 'linux' && steps.setup-node-env.outputs.cache-mode == 'read-write' && steps.extension-package-boundary-cache.outputs.cache-hit != 'true' }}
continue-on-error: true
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
packages/plugin-sdk/dist
.artifacts/extension-package-boundary/plugins
.artifacts/extension-package-boundary/*.json
.artifacts/extension-package-boundary/compile
key: ${{ runner.os }}-extension-package-boundary-v4-${{ github.sha }}
# Packaged declarations must see the same tree as ordinary build consumers.
# The native lint output belongs only in its completed cache archive.
- name: Clear native SDK boundary output before build
if: ${{ matrix.platform == 'linux' }}
run: rm -rf packages/plugin-sdk/dist
- name: Warm build cache
if: ${{ matrix.platform == 'linux' }}
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
- name: Save build-all cache
if: ${{ steps.setup-node-env.outputs.cache-mode == 'read-write' && steps.setup-node-env.outputs.build-all-cache-key != '' }}
continue-on-error: true
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .artifacts/build-all-cache
key: ${{ steps.setup-node-env.outputs.build-all-cache-key }}
- name: Save dist build cache
if: ${{ matrix.platform == 'linux' && steps.setup-node-env.outputs.cache-mode == 'read-write' }}
continue-on-error: true
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
dist/
dist-runtime/
packages/*/dist/
extensions/*/src/host/**/.bundle.hash
extensions/*/src/host/**/*.bundle.js
key: ${{ runner.os }}-dist-build-v3-${{ github.sha }}
- name: Select broad cache seed
if: ${{ matrix.platform == 'linux' }}
shell: bash
run: |
set -euo pipefail
node --import tsx --input-type=module <<'EOF'
import { appendFileSync } from "node:fs";
import { createVitestCacheWarmGroups } from "./scripts/lib/ci-node-test-plan.mts";
// Warm the selected planner envelopes for the striped unit-fast graph
// plus import-bound graphs that remained cold in protected-cache readers.
const groups = createVitestCacheWarmGroups();
appendFileSync(
process.env.GITHUB_ENV,
[
`OPENCLAW_NODE_TEST_GROUPS_JSON=${JSON.stringify(groups)}`,
"OPENCLAW_NODE_TEST_PLAN_CONCURRENCY=1",
"OPENCLAW_NODE_TEST_PLAN_CONTINUE_ON_FAILURE=1",
].join("\n") + "\n",
);
EOF
- name: Warm transform and compile caches
id: warm-caches
if: ${{ matrix.platform == 'linux' }}
continue-on-error: true
env:
# Match the CI shard lanes running the same envelopes: without the
# raised ceiling a heavy suite's worker can die under default heap
# (run 31874567859), skipping every cache save for the day.
NODE_OPTIONS: --max-old-space-size=8192
# Only the publisher prunes restored entries before saving a new seed.
OPENCLAW_VITEST_FS_MODULE_CACHE_WRITER: "1"
OPENCLAW_NODE_COMPILE_CACHE_WRITER: "1"
# Keep compiled imports and per-file cleanup in the normal runner;
# ordinary CI owns test-body validation.
OPENCLAW_NODE_TEST_VITEST_ARGS_JSON: '["--testNamePattern=(?!)"]'
run: node --import tsx scripts/ci-run-node-test-shard.mts
# Let pnpm prune its owned store and record the remaining size; this does
# not guarantee a bound on accumulated content-addressed files.
- name: Prune pnpm store before save
if: ${{ steps.setup-node-env.outputs.cache-mode == 'read-write' && steps.setup-node-env.outputs.pnpm-store-cache-key != '' && steps.setup-node-env.outputs.pnpm-store-cache-hit != 'true' }}
shell: bash
run: |
du -sh "${{ steps.setup-node-env.outputs.pnpm-store-cache-path }}" || true
pnpm store prune
du -sh "${{ steps.setup-node-env.outputs.pnpm-store-cache-path }}" || true
- name: Save pnpm store cache
if: ${{ steps.setup-node-env.outputs.cache-mode == 'read-write' && steps.setup-node-env.outputs.pnpm-store-cache-key != '' && steps.setup-node-env.outputs.pnpm-store-cache-hit != 'true' }}
continue-on-error: true
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.setup-node-env.outputs.pnpm-store-cache-path }}
key: ${{ steps.setup-node-env.outputs.pnpm-store-cache-key }}
- name: Save Vitest transform cache
if: ${{ steps.setup-node-env.outputs.cache-mode == 'read-write' && steps.setup-node-env.outputs.vitest-cache-key != '' }}
continue-on-error: true
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: /var/tmp/openclaw-vitest-fs-cache
key: ${{ steps.setup-node-env.outputs.vitest-cache-key }}
- name: Save Node compile cache
if: ${{ steps.setup-node-env.outputs.cache-mode == 'read-write' && steps.setup-node-env.outputs.node-compile-cache-key != '' }}
continue-on-error: true
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: /var/tmp/openclaw-node-compile-cache
key: ${{ steps.setup-node-env.outputs.node-compile-cache-key }}
- name: Assert cache warming succeeded
if: ${{ always() && matrix.platform == 'linux' }}
run: |
if [ "${{ steps.warm-caches.outcome }}" != "success" ]; then
echo "::error::Vitest cache warming failed"
exit 1
fi