Skip to content

Commit 8c63e4c

Browse files
committed
Initial commit
1 parent 6608f30 commit 8c63e4c

File tree

43 files changed

+549
-441
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+549
-441
lines changed

.github/workflows/models.yml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ jobs:
6363
node-version: ${{ steps.tool-versions.outputs.node-version }}
6464

6565
- name: Setup pnpm
66-
uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
66+
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
6767
# Note: version is specified in package.json packageManager field, not here
6868

6969
- name: Setup Python
@@ -133,6 +133,9 @@ jobs:
133133
fi
134134
}
135135
136+
# Cache version - bump to force-invalidate all caches
137+
CACHE_VERSION="v1"
138+
136139
COMMON=$(hash_dir packages/models/scripts/common)
137140
PACKAGE_JSON=$(shasum -a 256 packages/models/package.json | cut -d' ' -f1)
138141
BUILD_MJS=$(shasum -a 256 packages/models/scripts/build.mjs | cut -d' ' -f1)
@@ -149,6 +152,7 @@ jobs:
149152
QUANTIZED_DIR=$(hash_dir packages/models/scripts/quantized)
150153
QUANTIZED_HASH=$(echo "${CONVERTED_HASH}${QUANTIZED_DIR}" | shasum -a 256 | cut -d' ' -f1)
151154
155+
echo "cache_version=${CACHE_VERSION}" >> $GITHUB_OUTPUT
152156
echo "downloaded_hash=${DOWNLOADED_HASH}" >> $GITHUB_OUTPUT
153157
echo "quantized_hash=${QUANTIZED_HASH}" >> $GITHUB_OUTPUT
154158
@@ -158,15 +162,15 @@ jobs:
158162
if: ${{ !inputs.force }}
159163
with:
160164
path: packages/models/build/${{ steps.build-mode.outputs.mode }}/out/Final
161-
key: model-final-${{ steps.build-mode.outputs.mode }}-${{ steps.cache-key.outputs.quantized_hash }}
165+
key: model-final-${{ steps.cache-key.outputs.cache_version }}-${{ steps.build-mode.outputs.mode }}-${{ steps.cache-key.outputs.quantized_hash }}
162166

163167
- name: Restore model checkpoint cache
164168
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
165169
id: model-checkpoint-cache
166170
if: ${{ !inputs.force }}
167171
with:
168172
path: packages/models/build/${{ steps.build-mode.outputs.mode }}/checkpoints
169-
key: model-checkpoints-${{ steps.build-mode.outputs.mode }}-${{ steps.cache-key.outputs.quantized_hash }}
173+
key: model-checkpoints-${{ steps.cache-key.outputs.cache_version }}-${{ steps.build-mode.outputs.mode }}-${{ steps.cache-key.outputs.quantized_hash }}
170174

171175
- name: Validate build cache integrity
172176
id: validate-cache

.github/workflows/node-smol.yml

Lines changed: 35 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ jobs:
145145
clang --version
146146
147147
- name: Setup pnpm
148-
uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
148+
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
149149
# Note: version is specified in package.json packageManager field, not here
150150

151151
- name: Setup Node.js
@@ -238,13 +238,9 @@ jobs:
238238
fi
239239
240240
# Helper function to hash files, returns empty string if no files found
241+
# Callers must pass -type f and optionally -name "*.mjs" to filter appropriately
241242
hash_files() {
242-
local files=$(find "$@" 2>/dev/null | sort)
243-
if [ -z "$files" ]; then
244-
echo ""
245-
else
246-
echo "$files" | xargs $hash_cmd 2>/dev/null | $hash_cmd | cut -d' ' -f1
247-
fi
243+
find "$@" 2>/dev/null | sort | xargs $hash_cmd 2>/dev/null | $hash_cmd | cut -d' ' -f1 || echo ""
248244
}
249245
250246
# Helper function to get hierarchical paths for a category/phase/platform/arch
@@ -269,6 +265,8 @@ jobs:
269265
# Now with hierarchical paths: shared/ → platform/shared/ → platform/arch/
270266
271267
# Common scripts (used by all phases) - hierarchical
268+
# Each checkpoint now has its own paths.mjs that re-exports from scripts/paths.mjs
269+
# This makes dependencies explicit and ensures changes to paths.mjs are tracked per-checkpoint
272270
COMMON_PATHS=$(get_hierarchical_paths scripts common "$PLATFORM" "$ARCH")
273271
COMMON_SCRIPTS=$(hash_files $COMMON_PATHS -type f -name "*.mjs")
274272
@@ -334,165 +332,54 @@ jobs:
334332
echo "final_hash=${FINAL_KEY}" >> $GITHUB_OUTPUT
335333
echo "build_mode=${BUILD_MODE}" >> $GITHUB_OUTPUT
336334
337-
- name: Restore node-source cache
338-
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
339-
id: node-source-cache
340-
if: ${{ !inputs.force }}
341-
with:
342-
path: packages/node-smol-builder/build/${{ steps.smol-cache-key.outputs.build_mode }}/source
343-
key: node-source-${{ env.CACHE_VERSION }}-${{ steps.tool-versions.outputs.node-build-version }}-${{ steps.smol-cache-key.outputs.source_cloned_hash }}
344-
345-
- name: Clean stale ninja files from cache
346-
shell: bash
347-
run: |
348-
BUILD_MODE="${STEPS_SMOL_CACHE_KEY_OUTPUTS_BUILD_MODE}"
349-
OUT_DIR="packages/node-smol-builder/build/${BUILD_MODE}/source/out"
350-
if [ -d "$OUT_DIR" ]; then
351-
echo "Cleaning stale ninja files from cached source to free disk space..."
352-
rm -rf "$OUT_DIR"
353-
echo "✅ Cleaned $OUT_DIR"
354-
else
355-
echo "No out/ directory to clean"
356-
fi
357-
env:
358-
STEPS_SMOL_CACHE_KEY_OUTPUTS_BUILD_MODE: ${{ steps.smol-cache-key.outputs.build_mode }}
359-
360-
- name: Restore node Release cache
361-
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
362-
id: node-release-cache
363-
if: ${{ !inputs.force }}
364-
with:
365-
path: packages/node-smol-builder/build/${{ steps.smol-cache-key.outputs.build_mode }}/out/Release
366-
key: node-release-${{ steps.tool-versions.outputs.node-build-version }}-${{ matrix.platform }}-${{ matrix.arch }}-${{ steps.smol-cache-key.outputs.build_mode }}-${{ steps.smol-cache-key.outputs.binary_released_hash }}
367-
368-
- name: Restore node Stripped cache
369-
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
370-
id: node-stripped-cache
371-
if: ${{ !inputs.force }}
372-
with:
373-
path: packages/node-smol-builder/build/${{ steps.smol-cache-key.outputs.build_mode }}/out/Stripped
374-
key: node-stripped-${{ steps.tool-versions.outputs.node-build-version }}-${{ matrix.platform }}-${{ matrix.arch }}-${{ steps.smol-cache-key.outputs.build_mode }}-${{ steps.smol-cache-key.outputs.binary_stripped_hash }}
375-
376-
- name: Restore node Compressed cache
377-
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
378-
id: node-compressed-cache
379-
if: ${{ !inputs.force }}
380-
with:
381-
path: packages/node-smol-builder/build/${{ steps.smol-cache-key.outputs.build_mode }}/out/Compressed
382-
key: node-compressed-${{ steps.tool-versions.outputs.node-build-version }}-${{ matrix.platform }}-${{ matrix.arch }}-${{ steps.smol-cache-key.outputs.build_mode }}-${{ steps.smol-cache-key.outputs.binary_compressed_hash }}
383-
384-
- name: Restore node Final cache
385-
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
386-
id: node-final-cache
387-
if: ${{ !inputs.force }}
388-
with:
389-
path: packages/node-smol-builder/build/${{ steps.smol-cache-key.outputs.build_mode }}/out/Final
390-
key: node-final-${{ steps.tool-versions.outputs.node-build-version }}-${{ matrix.platform }}-${{ matrix.arch }}-${{ steps.smol-cache-key.outputs.build_mode }}-${{ steps.smol-cache-key.outputs.final_hash }}
391-
392335
- name: Restore checkpoint cache
393336
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
394337
id: checkpoint-cache
395338
if: ${{ !inputs.force }}
396339
with:
397-
path: packages/node-smol-builder/build/${{ steps.smol-cache-key.outputs.build_mode }}/checkpoints
398-
key: node-checkpoints-${{ steps.tool-versions.outputs.node-build-version }}-${{ matrix.platform }}-${{ matrix.arch }}-${{ steps.smol-cache-key.outputs.build_mode }}-${{ steps.smol-cache-key.outputs.final_hash }}
340+
path: |
341+
packages/node-smol-builder/build/shared/checkpoints
342+
packages/node-smol-builder/build/${{ steps.smol-cache-key.outputs.build_mode }}/checkpoints
343+
key: node-checkpoints-${{ env.CACHE_VERSION }}-${{ steps.tool-versions.outputs.node-build-version }}-${{ matrix.platform }}-${{ matrix.arch }}-${{ steps.smol-cache-key.outputs.build_mode }}-${{ steps.smol-cache-key.outputs.final_hash }}
399344

400-
- name: Validate build cache integrity
345+
- name: Validate checkpoint cache integrity
401346
id: validate-cache
402-
if: steps.node-final-cache.outputs.cache-hit == 'true'
347+
if: steps.checkpoint-cache.outputs.cache-hit == 'true'
403348
shell: bash
404349
run: |
405350
BUILD_MODE="${STEPS_SMOL_CACHE_KEY_OUTPUTS_BUILD_MODE}"
406-
FINAL_DIR="packages/node-smol-builder/build/${BUILD_MODE}/out/Final"
407-
CHECKPOINT_DIR="packages/node-smol-builder/build/${BUILD_MODE}/checkpoints"
408-
409-
echo "Validating cached build for ${{ matrix.platform }}-${{ matrix.arch }}..."
410-
411-
# Determine expected binary name
412-
if [ "${{ matrix.os }}" = "windows" ]; then
413-
BINARY_NAME="node.exe"
414-
else
415-
BINARY_NAME="node"
416-
fi
351+
SHARED_CHECKPOINT_DIR="packages/node-smol-builder/build/shared/checkpoints"
352+
MODE_CHECKPOINT_DIR="packages/node-smol-builder/build/${BUILD_MODE}/checkpoints"
417353
418-
# Check if binary exists
419-
if [ ! -f "${FINAL_DIR}/${BINARY_NAME}" ]; then
420-
echo "❌ Binary missing: ${FINAL_DIR}/${BINARY_NAME}"
421-
rm -rf "$FINAL_DIR" "$CHECKPOINT_DIR"
422-
echo "cache_valid=false" >> $GITHUB_OUTPUT
423-
exit 0
424-
fi
354+
echo "Validating cached checkpoints for ${{ matrix.platform }}-${{ matrix.arch }}..."
425355
426-
# Check binary size (minimum 50MB for node binary)
427-
if [ "${{ matrix.os }}" = "windows" ]; then
428-
BINARY_SIZE=$(stat -c%s "${FINAL_DIR}/${BINARY_NAME}" 2>/dev/null || powershell -Command "(Get-Item '${FINAL_DIR}/${BINARY_NAME}').Length")
429-
else
430-
BINARY_SIZE=$(stat -f%z "${FINAL_DIR}/${BINARY_NAME}" 2>/dev/null || stat -c%s "${FINAL_DIR}/${BINARY_NAME}")
431-
fi
432-
433-
MIN_SIZE=52428800 # 50MB in bytes
434-
if [ "$BINARY_SIZE" -lt "$MIN_SIZE" ]; then
435-
echo "❌ Binary too small: $BINARY_SIZE bytes (minimum $MIN_SIZE)"
436-
rm -rf "$FINAL_DIR" "$CHECKPOINT_DIR"
437-
echo "cache_valid=false" >> $GITHUB_OUTPUT
438-
exit 0
439-
fi
440-
echo "✓ Binary size OK: $BINARY_SIZE bytes"
441-
442-
# Check if checkpoint files exist (phase-based structure, flat directory)
443-
if [ ! -f "${CHECKPOINT_DIR}/binary-released.json" ] || \
444-
[ ! -f "${CHECKPOINT_DIR}/binary-stripped.json" ] || \
445-
[ ! -f "${CHECKPOINT_DIR}/binary-compressed.json" ]; then
356+
# Check if checkpoint tarballs and JSON files exist
357+
# source-cloned is in shared directory, others are in mode-specific directory
358+
if [ ! -f "${SHARED_CHECKPOINT_DIR}/source-cloned.tar.gz" ] || \
359+
[ ! -f "${SHARED_CHECKPOINT_DIR}/source-cloned.json" ] || \
360+
[ ! -f "${MODE_CHECKPOINT_DIR}/binary-compressed.tar.gz" ] || \
361+
[ ! -f "${MODE_CHECKPOINT_DIR}/binary-compressed.json" ]; then
446362
echo "❌ Checkpoint files incomplete"
447-
rm -rf "$FINAL_DIR" "$CHECKPOINT_DIR"
363+
rm -rf "${SHARED_CHECKPOINT_DIR}" "${MODE_CHECKPOINT_DIR}"
448364
echo "cache_valid=false" >> $GITHUB_OUTPUT
449365
exit 0
450366
fi
451367
452-
# Validate checksum if available in checkpoint
453-
if command -v jq &> /dev/null; then
454-
EXPECTED_CHECKSUM=$(jq -r '.checksum // empty' "${CHECKPOINT_DIR}/binary-compressed.json")
455-
if [ -n "$EXPECTED_CHECKSUM" ]; then
456-
if command -v shasum &> /dev/null; then
457-
ACTUAL_CHECKSUM=$(shasum -a 256 "${FINAL_DIR}/${BINARY_NAME}" | cut -d' ' -f1)
458-
else
459-
ACTUAL_CHECKSUM=$(sha256sum "${FINAL_DIR}/${BINARY_NAME}" | cut -d' ' -f1)
460-
fi
461-
462-
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]; then
463-
echo "❌ Checksum mismatch (cache corruption detected)"
464-
echo " Expected: $EXPECTED_CHECKSUM"
465-
echo " Actual: $ACTUAL_CHECKSUM"
466-
rm -rf "$FINAL_DIR" "$CHECKPOINT_DIR"
467-
echo "cache_valid=false" >> $GITHUB_OUTPUT
468-
exit 0
368+
# Check tarball integrity for both directories
369+
for checkpoint_dir in "${SHARED_CHECKPOINT_DIR}" "${MODE_CHECKPOINT_DIR}"; do
370+
for tarball in "${checkpoint_dir}"/*.tar.gz; do
371+
if [ -f "$tarball" ]; then
372+
if ! gzip -t "$tarball" 2>/dev/null; then
373+
echo "❌ Corrupted tarball: $(basename "$tarball")"
374+
rm -rf "${SHARED_CHECKPOINT_DIR}" "${MODE_CHECKPOINT_DIR}"
375+
echo "cache_valid=false" >> $GITHUB_OUTPUT
376+
exit 0
377+
fi
469378
fi
470-
echo "✓ Checksum validation passed"
471-
fi
472-
fi
473-
474-
# Smoke test: check version (only for native builds, skip cross-compiled)
475-
# We build natively on each architecture except Windows ARM64 (cross-compiled on x64)
476-
if [ "${{ matrix.cross_compile }}" != "true" ]; then
477-
"${FINAL_DIR}/${BINARY_NAME}" --version > /dev/null 2>&1
478-
if [ $? -ne 0 ]; then
479-
echo "❌ Binary smoke test failed"
480-
rm -rf "$FINAL_DIR" "$CHECKPOINT_DIR"
481-
echo "cache_valid=false" >> $GITHUB_OUTPUT
482-
exit 0
483-
fi
484-
485-
# Verify Node.js version matches
486-
NODE_VER=$("${FINAL_DIR}/${BINARY_NAME}" --version | sed 's/v//')
487-
if [ "$NODE_VER" != "${{ steps.tool-versions.outputs.node-build-version }}" ]; then
488-
echo "❌ Version mismatch: expected ${{ steps.tool-versions.outputs.node-build-version }}, got $NODE_VER"
489-
rm -rf "$FINAL_DIR" "$CHECKPOINT_DIR"
490-
echo "cache_valid=false" >> $GITHUB_OUTPUT
491-
exit 0
492-
fi
493-
fi
379+
done
380+
done
494381
495-
echo "✅ Cache validation passed"
382+
echo "✅ Checkpoint cache validation passed"
496383
echo "cache_valid=true" >> $GITHUB_OUTPUT
497384
env:
498385
STEPS_SMOL_CACHE_KEY_OUTPUTS_BUILD_MODE: ${{ steps.smol-cache-key.outputs.build_mode }}
@@ -526,7 +413,7 @@ jobs:
526413
fi
527414
528415
- name: Build Node.js smol
529-
if: steps.node-final-cache.outputs.cache-hit != 'true' || steps.validate-cache.outputs.cache_valid == 'false'
416+
if: steps.checkpoint-cache.outputs.cache-hit != 'true' || steps.validate-cache.outputs.cache_valid == 'false'
530417
shell: bash
531418
env:
532419
BUILD_MODE: ${{ inputs.build_mode || 'prod' }}

0 commit comments

Comments
 (0)