From 95f1b2e13be31150d5ccd05e41708906330fce7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Flor=C3=AAncio?= Date: Sun, 15 Feb 2026 23:38:08 +0000 Subject: [PATCH] fix: bundle --- apps/cli/src/bundle.ts | 8 ++++++++ apps/cli/src/run.ts | 6 ++++++ scripts/release/package-web.sh | 13 ++++++++++++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/apps/cli/src/bundle.ts b/apps/cli/src/bundle.ts index ab9162f18b..d47424a218 100644 --- a/apps/cli/src/bundle.ts +++ b/apps/cli/src/bundle.ts @@ -5,6 +5,14 @@ import path from "node:path"; export function extractZip(zipPath: string, destDir: string): void { const zip = new AdmZip(zipPath); zip.extractAllTo(destDir, true); + + // adm-zip doesn't preserve Unix file permissions, so mark binaries executable + const binDir = path.join(destDir, "kandev", "bin"); + if (fs.existsSync(binDir)) { + for (const file of fs.readdirSync(binDir)) { + fs.chmodSync(path.join(binDir, file), 0o755); + } + } } export function ensureExtracted(zipPath: string, destDir: string): void { diff --git a/apps/cli/src/run.ts b/apps/cli/src/run.ts index c210c25dc1..fd1bf1b1e9 100644 --- a/apps/cli/src/run.ts +++ b/apps/cli/src/run.ts @@ -67,6 +67,12 @@ async function prepareReleaseBundle({ throw new Error(`agentctl binary not found at ${agentctlBin}`); } + // Ensure binaries are executable (adm-zip doesn't preserve Unix permissions) + if (process.platform !== "win32") { + fs.chmodSync(backendBin, 0o755); + fs.chmodSync(agentctlBin, 0o755); + } + const actualBackendPort = backendPort ?? (await pickAvailablePort(DEFAULT_BACKEND_PORT)); const actualWebPort = webPort ?? (await pickAvailablePort(DEFAULT_WEB_PORT)); const agentctlPort = await pickAvailablePort(DEFAULT_AGENTCTL_PORT); diff --git a/scripts/release/package-web.sh b/scripts/release/package-web.sh index 45796f4d45..041752813f 100755 --- a/scripts/release/package-web.sh +++ b/scripts/release/package-web.sh @@ -17,7 +17,18 @@ fi rm -rf "$OUT_DIR" mkdir -p "$OUT_DIR" -cp -R "$WEB_DIR/.next/standalone/." "$OUT_DIR/" +# Copy with symlinks dereferenced so pnpm's .pnpm/ structure survives +# zip/unzip (adm-zip can't handle symlinks). The standalone output may +# contain broken symlinks from partial tracing — --safe-links skips those +# and rsync exits with code 23 (partial transfer), which is expected. +rsync -a --copy-links --safe-links "$WEB_DIR/.next/standalone/" "$OUT_DIR/" || { + rc=$? + if [ "$rc" -eq 23 ]; then + echo "Warning: some broken symlinks were skipped (expected for standalone output)" + else + exit "$rc" + fi +} mkdir -p "$OUT_DIR/.next" cp -R "$WEB_DIR/.next/static" "$OUT_DIR/.next/"