Skip to content

Commit 70206b7

Browse files
committed
fix(smol): optimize build flow and fix macOS ARM64 signing
Optimize the build flow to be more efficient and fix macOS ARM64 execution: Build flow optimizations: 1. Build → Sign (for testing) → Test 2. Strip debug symbols 3. Compress binary 4. Sign compressed binary (macOS ARM64 only) 5. Copy to /Final Removed inefficiencies: - Eliminated premature /Signed directory copy - Eliminated premature uncompressed /Final copy - Eliminated double signing (sign once after compression) - Sign compressed binary directly instead of uncompressed then re-sign macOS ARM64 fix: - Move initial code signing before binary testing - Required for execution in GitHub Actions CI runners - Fixes "exit code 1, stdout: null, stderr: null" error Result: Cleaner flow, one less signing operation, fewer file copies
1 parent 51c6c74 commit 70206b7

File tree

1 file changed

+53
-95
lines changed

1 file changed

+53
-95
lines changed

packages/node-smol-builder/scripts/build.mjs

Lines changed: 53 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1456,9 +1456,20 @@ async function main() {
14561456
await createCheckpoint(BUILD_DIR, 'built')
14571457
logger.log('')
14581458

1459+
const nodeBinary = join(NODE_DIR, 'out', 'Release', 'node')
1460+
1461+
// Sign early for macOS ARM64 (required before execution in CI).
1462+
if (IS_MACOS && ARCH === 'arm64') {
1463+
printHeader('Code Signing (macOS ARM64 - Initial)')
1464+
logger.log('Signing binary before testing for macOS ARM64 compatibility...')
1465+
logger.logNewline()
1466+
await exec('codesign', ['--sign', '-', '--force', nodeBinary])
1467+
logger.success('Binary signed successfully')
1468+
logger.logNewline()
1469+
}
1470+
14591471
// Test the binary.
14601472
printHeader('Testing Binary')
1461-
const nodeBinary = join(NODE_DIR, 'out', 'Release', 'node')
14621473

14631474
logger.log('Running basic functionality tests...')
14641475
logger.log('')
@@ -1568,68 +1579,6 @@ async function main() {
15681579
logger.success('Stripped binary copied to build/out/Stripped')
15691580
logger.logNewline()
15701581

1571-
// Sign for macOS ARM64.
1572-
if (IS_MACOS && ARCH === 'arm64') {
1573-
printHeader('Code Signing (macOS ARM64)')
1574-
logger.log('Signing binary for macOS ARM64 compatibility...')
1575-
logger.logNewline()
1576-
await exec('codesign', ['--sign', '-', '--force', nodeBinary])
1577-
1578-
const sigInfo = await execCapture(`codesign -dv "${nodeBinary}"`, {
1579-
env: { ...process.env, STDERR: '>&1' },
1580-
})
1581-
logger.log(sigInfo.stdout || sigInfo.stderr)
1582-
logger.logNewline()
1583-
logger.success('Binary signed successfully')
1584-
logger.logNewline()
1585-
}
1586-
1587-
// Copy signed binary to build/out/Signed (macOS only).
1588-
let outputSignedBinary = null
1589-
if (IS_MACOS && ARCH === 'arm64') {
1590-
printHeader('Copying to Build Output (Signed)')
1591-
logger.log('Copying signed binary to build/out/Signed directory...')
1592-
logger.logNewline()
1593-
1594-
const outputSignedDir = join(BUILD_DIR, 'out', 'Signed')
1595-
await mkdir(outputSignedDir, { recursive: true })
1596-
outputSignedBinary = join(outputSignedDir, 'node')
1597-
await exec('cp', [nodeBinary, outputSignedBinary])
1598-
1599-
logger.substep(`Signed directory: ${outputSignedDir}`)
1600-
logger.substep('Binary: node (stripped + signed)')
1601-
logger.logNewline()
1602-
logger.success('Signed binary copied to build/out/Signed')
1603-
logger.logNewline()
1604-
}
1605-
1606-
// Copy final binary to build/out/Final.
1607-
// This creates an initial uncompressed version, which will be replaced with
1608-
// compressed version + decompressor if compression is enabled (default).
1609-
printHeader('Copying to Build Output (Final - Initial)')
1610-
logger.log('Creating initial distribution binary...')
1611-
logger.logNewline()
1612-
1613-
const outputFinalDir = join(BUILD_DIR, 'out', 'Final')
1614-
await mkdir(outputFinalDir, { recursive: true })
1615-
const outputFinalBinary = join(outputFinalDir, 'node')
1616-
1617-
// Select source based on platform.
1618-
const finalSource = outputSignedBinary || outputStrippedBinary
1619-
await exec('cp', [finalSource, outputFinalBinary])
1620-
1621-
if (outputSignedBinary) {
1622-
logger.substep('Source: build/out/Signed/node (signed)')
1623-
} else {
1624-
logger.substep('Source: build/out/Stripped/node (stripped, no signing needed)')
1625-
}
1626-
1627-
logger.substep(`Destination: ${outputFinalDir}`)
1628-
logger.substep('Note: Will be replaced with compressed version if compression enabled')
1629-
logger.logNewline()
1630-
logger.success('Initial binary copied to build/out/Final')
1631-
logger.logNewline()
1632-
16331582
// Compress binary for smaller distribution size (DEFAULT for smol builds).
16341583
// Uses native platform APIs (Apple Compression, liblzma, Windows Compression API) instead of UPX.
16351584
// Benefits: 75-79% compression (vs UPX's 50-60%), works with code signing, zero AV false positives.
@@ -1639,7 +1588,7 @@ async function main() {
16391588

16401589
if (shouldCompress) {
16411590
printHeader('Compressing Binary for Distribution')
1642-
logger.log('Compressing binary using platform-specific compression...')
1591+
logger.log('Compressing stripped binary using platform-specific compression...')
16431592
logger.logNewline()
16441593

16451594
const compressedDir = join(BUILD_DIR, 'out', 'Compressed')
@@ -1652,12 +1601,12 @@ async function main() {
16521601
// Windows: LZMS (best for PE).
16531602
const compressionQuality = IS_MACOS ? 'lzfse' : 'lzma'
16541603

1655-
logger.substep(`Input: ${outputFinalBinary}`)
1604+
logger.substep(`Input: ${outputStrippedBinary}`)
16561605
logger.substep(`Output: ${compressedBinary}`)
16571606
logger.substep(`Algorithm: ${compressionQuality.toUpperCase()}`)
16581607
logger.logNewline()
16591608

1660-
const sizeBeforeCompress = await getFileSize(outputFinalBinary)
1609+
const sizeBeforeCompress = await getFileSize(outputStrippedBinary)
16611610
logger.log(`Size before compression: ${sizeBeforeCompress}`)
16621611
logger.log('Running compression tool...')
16631612
logger.logNewline()
@@ -1667,7 +1616,7 @@ async function main() {
16671616
process.execPath,
16681617
[
16691618
join(ROOT_DIR, 'scripts', 'compress-binary.mjs'),
1670-
outputFinalBinary,
1619+
outputStrippedBinary,
16711620
compressedBinary,
16721621
`--quality=${compressionQuality}`,
16731622
],
@@ -1678,11 +1627,10 @@ async function main() {
16781627
logger.log(`Size after compression: ${sizeAfterCompress}`)
16791628
logger.logNewline()
16801629

1681-
// Re-sign compressed binary (macOS ARM64).
1682-
// The compressed binary can be signed to prevent tampering.
1683-
// The decompressor will extract the original signed Node.js binary.
1630+
// Sign compressed binary (macOS ARM64 only).
1631+
// The compressed binary wrapper is signed; decompressor extracts unsigned Node.js binary.
16841632
if (IS_MACOS && ARCH === 'arm64') {
1685-
logger.log('Re-signing compressed binary...')
1633+
logger.log('Signing compressed binary...')
16861634
await exec('codesign', ['--sign', '-', '--force', compressedBinary])
16871635

16881636
const sigInfo = await execCapture(`codesign -dv "${compressedBinary}"`, {
@@ -1746,24 +1694,21 @@ async function main() {
17461694
logger.log('')
17471695
}
17481696

1749-
// Replace Final directory with compressed version if compression succeeded.
1697+
// Copy final distribution binary to build/out/Final.
1698+
// Use compressed binary if available, otherwise use stripped binary.
1699+
printHeader('Copying to Build Output (Final)')
1700+
const finalDir = join(BUILD_DIR, 'out', 'Final')
1701+
await mkdir(finalDir, { recursive: true })
1702+
const finalBinary = join(finalDir, 'node')
1703+
17501704
if (compressedBinary && existsSync(compressedBinary)) {
1751-
printHeader('Updating Final Distribution with Compressed Binary')
1752-
logger.log('Replacing Final directory with compressed distribution package...')
1705+
logger.log('Copying compressed distribution package to Final directory...')
17531706
logger.logNewline()
17541707

1755-
const finalDir = join(BUILD_DIR, 'out', 'Final')
17561708
const compressedDir = join(BUILD_DIR, 'out', 'Compressed')
17571709

1758-
// Remove old uncompressed binary from Final.
1759-
const oldFinalBinary = join(finalDir, 'node')
1760-
if (existsSync(oldFinalBinary)) {
1761-
await fs.unlink(oldFinalBinary)
1762-
}
1763-
17641710
// Copy compressed binary to Final.
1765-
const finalCompressedBinary = join(finalDir, 'node')
1766-
await exec('cp', [compressedBinary, finalCompressedBinary])
1711+
await exec('cp', [compressedBinary, finalBinary])
17671712

17681713
// Copy decompressor tool to Final.
17691714
const decompressTool = IS_MACOS
@@ -1777,16 +1722,30 @@ async function main() {
17771722
await exec('chmod', ['+x', decompressToolDest])
17781723
}
17791724

1780-
const compressedSize = await getFileSize(finalCompressedBinary)
1725+
const compressedSize = await getFileSize(finalBinary)
17811726
const decompressToolSize = existsSync(decompressToolDest)
17821727
? await getFileSize(decompressToolDest)
17831728
: 'N/A'
17841729

1785-
logger.substep(`Binary: ${compressedSize} (compressed)`)
1730+
logger.substep('Source: build/out/Compressed/node (compressed + signed)')
1731+
logger.substep(`Binary: ${compressedSize}`)
17861732
logger.substep(`Decompressor: ${decompressToolSize}`)
17871733
logger.substep(`Location: ${finalDir}`)
17881734
logger.logNewline()
1789-
logger.success('Final distribution updated with compressed package')
1735+
logger.success('Final distribution created with compressed package')
1736+
logger.logNewline()
1737+
} else {
1738+
logger.log('Copying stripped binary to Final directory...')
1739+
logger.logNewline()
1740+
1741+
await exec('cp', [outputStrippedBinary, finalBinary])
1742+
1743+
const binarySize = await getFileSize(finalBinary)
1744+
logger.substep('Source: build/out/Stripped/node (stripped, uncompressed)')
1745+
logger.substep(`Binary: ${binarySize}`)
1746+
logger.substep(`Location: ${finalDir}`)
1747+
logger.logNewline()
1748+
logger.success('Final distribution created with uncompressed binary')
17901749
logger.logNewline()
17911750
}
17921751

@@ -1820,13 +1779,13 @@ async function main() {
18201779
printHeader('Installing to pkg Cache')
18211780
logger.log('Installing binary to pkg cache...')
18221781
logger.logNewline()
1823-
logger.substep(`Source: ${outputFinalBinary}`)
1782+
logger.substep(`Source: ${finalBinary}`)
18241783
logger.substep(`Cache directory: ${pkgCacheDir}`)
18251784
logger.substep(`Binary name: ${targetName}`)
18261785
logger.logNewline()
18271786

18281787
await mkdir(pkgCacheDir, { recursive: true })
1829-
await exec('cp', [outputFinalBinary, targetPath])
1788+
await exec('cp', [finalBinary, targetPath])
18301789

18311790
// Verify it was copied.
18321791
if (!existsSync(targetPath)) {
@@ -1877,7 +1836,7 @@ async function main() {
18771836
const distributionOutputDir = join(BUILD_DIR, 'out', 'Distribution')
18781837
await mkdir(distributionOutputDir, { recursive: true })
18791838
const distributionOutputBinary = join(distributionOutputDir, 'node')
1880-
await exec('cp', [outputFinalBinary, distributionOutputBinary])
1839+
await exec('cp', [finalBinary, distributionOutputBinary])
18811840

18821841
logger.substep(`Distribution directory: ${distributionOutputDir}`)
18831842
logger.substep('Binary: node (final distribution build)')
@@ -1893,7 +1852,7 @@ async function main() {
18931852
const distDir = join(ROOT_DIR, 'dist')
18941853
await mkdir(distDir, { recursive: true })
18951854
const distBinary = join(distDir, 'socket-smol')
1896-
await exec('cp', [outputFinalBinary, distBinary])
1855+
await exec('cp', [finalBinary, distBinary])
18971856
await exec('chmod', ['+x', distBinary])
18981857

18991858
logger.substep(`E2E binary: ${distBinary}`)
@@ -1943,13 +1902,12 @@ async function main() {
19431902
logger.log(` Source: ${nodeBinary}`)
19441903
logger.log(` Release: ${outputReleaseBinary}`)
19451904
logger.log(` Stripped: ${outputStrippedBinary}`)
1946-
logger.log(` Signed: ${outputSignedBinary}`)
1947-
logger.log(` Final: ${outputFinalBinary}`)
1948-
logger.log(` Distribution: ${distributionOutputBinary}`)
1949-
logger.log(` pkg cache: ${targetPath}`)
19501905
if (compressedBinary) {
1951-
logger.log(` Compressed: ${compressedBinary} (with decompression tool)`)
1906+
logger.log(` Compressed: ${compressedBinary} (signed, with decompression tool)`)
19521907
}
1908+
logger.log(` Final: ${finalBinary}`)
1909+
logger.log(` Distribution: ${distributionOutputBinary}`)
1910+
logger.log(` pkg cache: ${targetPath}`)
19531911
logger.logNewline()
19541912

19551913
logger.log('🚀 Next Steps:')

0 commit comments

Comments
 (0)