Skip to content

Commit e0694b2

Browse files
committed
Initial commit
1 parent 0363d89 commit e0694b2

File tree

29 files changed

+745
-175
lines changed

29 files changed

+745
-175
lines changed

.github/actions/restore-checkpoint/action.yml

Lines changed: 90 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,16 @@ runs:
5252
MODE_CHECKPOINT_DIR="packages/${PACKAGE_NAME}/build/${BUILD_MODE}/checkpoints"
5353
SHARED_CHECKPOINT_DIR="packages/${PACKAGE_NAME}/build/shared/checkpoints"
5454
OUTPUT_DIR="packages/${PACKAGE_NAME}/build/${BUILD_MODE}/out"
55+
SHARED_SOURCE_DIR="packages/${PACKAGE_NAME}/build/shared/source"
56+
MODE_SOURCE_DIR="packages/${PACKAGE_NAME}/build/${BUILD_MODE}/source"
5557
5658
echo "📦 Package: ${PACKAGE_NAME}"
5759
echo "🔧 Build mode: ${BUILD_MODE}"
5860
echo "📁 Mode checkpoint directory: ${MODE_CHECKPOINT_DIR}"
5961
echo "📁 Shared checkpoint directory: ${SHARED_CHECKPOINT_DIR}"
6062
echo "📤 Output directory: ${OUTPUT_DIR}"
63+
echo "📂 Shared source directory: ${SHARED_SOURCE_DIR}"
64+
echo "📂 Mode source directory: ${MODE_SOURCE_DIR}"
6165
echo ""
6266
6367
# Parse checkpoint chain into array (comma-separated)
@@ -149,10 +153,92 @@ runs:
149153
fi
150154
echo ""
151155
152-
# Extract checkpoint
153-
echo "📦 Extracting checkpoint to ${OUTPUT_DIR}..."
154-
mkdir -p "${OUTPUT_DIR}"
155-
tar -xzf "${CHECKPOINT_FILE}" -C "${OUTPUT_DIR}"
156+
# Extract checkpoint to correct directory based on checkpoint name
157+
# Checkpoint structure varies by package:
158+
#
159+
# node-smol-builder:
160+
# - finalized → build/{mode}/out/Final/
161+
# - binary-compressed → build/{mode}/out/Compressed/
162+
# - binary-stripped → build/{mode}/out/Stripped/
163+
# - binary-released → build/{mode}/out/Release/
164+
# - source-cloned → build/shared/source/
165+
# - source-patched → build/{mode}/source/
166+
#
167+
# onnxruntime-builder, yoga-layout-builder:
168+
# - finalized → build/{mode}/out/Final/
169+
# - wasm-synced → build/{mode}/out/Synced/
170+
# - wasm-released → build/{mode}/out/Released/
171+
# - wasm-optimized → build/{mode}/out/Optimized/
172+
# - wasm-compiled → build/{mode}/out/Compiled/
173+
# - source-configured → build/{mode}/source/ (yoga-layout only)
174+
# - source-cloned → build/shared/source/
175+
#
176+
# models:
177+
# - finalized → build/{mode}/out/Final/
178+
# - quantized → build/{mode}/models/
179+
# - converted → build/{mode}/models/
180+
# - downloaded → build/{mode}/models/
181+
EXTRACT_DIR="${OUTPUT_DIR}"
182+
case "${RESTORED_CHECKPOINT}" in
183+
finalized)
184+
EXTRACT_DIR="${OUTPUT_DIR}/Final"
185+
;;
186+
# node-smol-builder checkpoints
187+
binary-compressed)
188+
EXTRACT_DIR="${OUTPUT_DIR}/Compressed"
189+
;;
190+
binary-stripped)
191+
EXTRACT_DIR="${OUTPUT_DIR}/Stripped"
192+
;;
193+
binary-released)
194+
EXTRACT_DIR="${OUTPUT_DIR}/Release"
195+
;;
196+
# onnxruntime-builder, yoga-layout-builder checkpoints
197+
wasm-synced)
198+
EXTRACT_DIR="${OUTPUT_DIR}/Synced"
199+
;;
200+
wasm-released)
201+
EXTRACT_DIR="${OUTPUT_DIR}/Released"
202+
;;
203+
wasm-optimized)
204+
EXTRACT_DIR="${OUTPUT_DIR}/Optimized"
205+
;;
206+
wasm-compiled)
207+
EXTRACT_DIR="${OUTPUT_DIR}/Compiled"
208+
;;
209+
source-configured)
210+
# yoga-layout-builder specific: extract to mode source directory
211+
EXTRACT_DIR="${MODE_SOURCE_DIR}"
212+
;;
213+
# models checkpoints
214+
quantized|converted|downloaded)
215+
# Models checkpoints extract to build/{mode}/models/
216+
EXTRACT_DIR="packages/${PACKAGE_NAME}/build/${BUILD_MODE}/models"
217+
;;
218+
# Source checkpoints (shared across packages)
219+
source-cloned)
220+
# Shared checkpoint: extract to shared source directory
221+
EXTRACT_DIR="${SHARED_SOURCE_DIR}"
222+
;;
223+
source-patched)
224+
# Mode-specific checkpoint: extract to mode source directory
225+
EXTRACT_DIR="${MODE_SOURCE_DIR}"
226+
;;
227+
esac
228+
229+
echo "📦 Extracting checkpoint to ${EXTRACT_DIR}..."
230+
mkdir -p "${EXTRACT_DIR}"
231+
# Extract tarball, stripping the top-level directory wrapper
232+
# -x: extract archive
233+
# -z: decompress with gzip
234+
# -f: input file
235+
# -C: change to directory before extracting
236+
# --strip-components=1: remove first directory level from paths
237+
#
238+
# Example: tarball contains Final/ort.wasm
239+
# Without --strip-components=1: extracts to out/Final/Final/ort.wasm (WRONG)
240+
# With --strip-components=1: extracts to out/Final/ort.wasm (CORRECT)
241+
tar -xzf "${CHECKPOINT_FILE}" -C "${EXTRACT_DIR}" --strip-components=1
156242
echo "✅ Checkpoint extracted successfully"
157243
echo ""
158244

packages/build-infra/lib/checkpoint-manager.mjs

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -146,36 +146,62 @@ export async function hasCheckpoint(buildDir, packageName, checkpointName) {
146146
* - Tarball: build/{mode}/checkpoints/{package}/{phase}.tar.gz (if artifactPath provided)
147147
*
148148
* @param {string} buildDir - Build directory path
149-
* @param {string} packageName - Package name
150149
* @param {string} checkpointName - Checkpoint name (e.g., 'release', 'patches-applied')
151150
* @param {Function} smokeTest - Async function that validates build artifacts (REQUIRED)
152-
* @param {object} data - Checkpoint metadata
153-
* @param {string} [data.artifactPath] - Path to file or directory to archive in checkpoint
154-
* @param {string[]} [data.sourcePaths] - Source file paths to hash for cache validation
155-
* @param {string} [data.packageRoot] - Package root for relative path display
156-
* @param {string} [data.platform] - Platform (darwin, linux, win32)
157-
* @param {string} [data.arch] - Architecture (x64, arm64)
151+
* @param {object} [options] - Optional checkpoint metadata
152+
* @param {string | undefined} [options.packageName=''] - Package name (defaults to '' for flat structure)
153+
* @param {string | undefined} [options.artifactPath] - Path to file or directory to archive in checkpoint
154+
* @param {string[] | undefined} [options.sourcePaths] - Source file paths to hash for cache validation
155+
* @param {string | undefined} [options.packageRoot] - Package root for relative path display
156+
* @param {string | undefined} [options.platform=process.platform] - Platform (darwin, linux, win32)
157+
* @param {string | undefined} [options.arch=process.arch] - Architecture (x64, arm64)
158+
* @param {string | undefined} [options.binaryPath] - Binary path for macOS code signing
158159
* @returns {Promise<void>}
159160
*
160161
* @example
161-
* await createCheckpoint(BUILD_DIR, '', 'release', async () => {
162-
* // Smoke test: Verify binary runs
162+
* // Minimal usage
163+
* await createCheckpoint(BUILD_DIR, 'release', async () => {
164+
* await spawn(binaryPath, ['--version'])
165+
* })
166+
*
167+
* // With options
168+
* await createCheckpoint(BUILD_DIR, 'release', async () => {
163169
* await spawn(binaryPath, ['--version'])
164170
* }, {
165-
* artifactPath: './out/Release/node', // Archive this binary
166-
* sourcePaths: ['build.mjs', 'patches/*.patch'], // Cache key
171+
* artifactPath: './out/Release/node',
172+
* sourcePaths: ['build.mjs', 'patches/*.patch'],
167173
* packageRoot: PACKAGE_ROOT,
168-
* platform: 'darwin',
169-
* arch: 'arm64',
170174
* })
171175
*/
172176
export async function createCheckpoint(
173177
buildDir,
174-
packageName,
175178
checkpointName,
176179
smokeTest,
177-
data = {},
180+
options = {},
178181
) {
182+
// Extract options with defaults
183+
const {
184+
arch = process.arch,
185+
artifactPath,
186+
binaryPath,
187+
packageName = '',
188+
packageRoot,
189+
platform = process.platform,
190+
sourcePaths,
191+
...rest
192+
} = options
193+
194+
// Build data object for legacy code paths
195+
const data = {
196+
artifactPath,
197+
sourcePaths,
198+
packageRoot,
199+
platform,
200+
arch,
201+
binaryPath,
202+
...rest,
203+
}
204+
179205
// Enforce smoke test requirement
180206
if (typeof smokeTest !== 'function') {
181207
const actualValue =
@@ -187,18 +213,17 @@ export async function createCheckpoint(
187213
'ERROR: createCheckpoint() called incorrectly!\n' +
188214
`${'='.repeat(70)}\n` +
189215
`Checkpoint: "${checkpointName}"\n` +
190-
`Package: "${packageName || '(none)'}"\n` +
191216
'\n' +
192-
'Expected parameter 4: smokeTest callback function\n' +
193-
`Actual parameter 4: ${actualValue}\n` +
217+
'Expected parameter 3: smokeTest callback function\n' +
218+
`Actual parameter 3: ${actualValue}\n` +
194219
'\n' +
195220
'Correct pattern:\n' +
196-
' createCheckpoint(buildDir, pkg, name, async () => {\n' +
221+
' createCheckpoint(buildDir, checkpointName, async () => {\n' +
197222
' // Smoke test validation code here\n' +
198-
' }, data)\n' +
223+
' }, options)\n' +
199224
'\n' +
200225
'You passed:\n' +
201-
' createCheckpoint(buildDir, pkg, name, data) ❌ Missing callback!\n' +
226+
' createCheckpoint(buildDir, checkpointName, options) ❌ Missing callback!\n' +
202227
`${'='.repeat(70)}\n`,
203228
)
204229
}
@@ -213,7 +238,6 @@ export async function createCheckpoint(
213238
}
214239

215240
// Build checkpoint identifier with platform/arch if provided
216-
const { arch, packageRoot, platform } = data
217241
let checkpointId = checkpointName
218242
if (platform && arch) {
219243
checkpointId = `${checkpointName} (${platform}-${arch})`
@@ -291,6 +315,16 @@ export async function createCheckpoint(
291315
const unixTarDir = toUnixPath(tarDir)
292316

293317
try {
318+
// Create tarball with artifact as top-level entry
319+
// -c: create archive
320+
// -z: compress with gzip
321+
// -f: output file
322+
// -C: change to directory before archiving (ensures artifact becomes top-level entry)
323+
// tarBase: the artifact basename to archive (file or directory)
324+
//
325+
// Example: tar -czf checkpoint.tar.gz -C /build/dev/out Final
326+
// → Creates tarball containing Final/ as top-level entry
327+
// → During extraction, use --strip-components=1 to remove this wrapper
294328
await spawn(
295329
tarBin,
296330
['-czf', unixTarballPath, '-C', unixTarDir, tarBase],

0 commit comments

Comments
 (0)