Fix local build for macOS e2e testing (Vibe Kanban) (#1679)

* Done! Here's a summary of the changes:

## Changes Made

### `npx-cli/bin/download.js`
- Added `LOCAL_DEV_MODE` detection - automatically enabled when R2 placeholders aren't replaced or `VIBE_KANBAN_LOCAL=1` env var is set
- Modified `ensureBinary()` to use local binaries from `npx-cli/dist/{platform}/` in local dev mode
- Exported `LOCAL_DEV_MODE` and `LOCAL_DIST_DIR` for use by `cli.js`

### `npx-cli/bin/cli.js`
- In local dev mode, extracts binaries directly to `npx-cli/dist/{platform}/` instead of global cache
- Skips version update check in local dev mode
- Shows "(local dev)" label in startup message when running locally

### `local-build.sh`
- Added instructions at the end showing how to run the local build

## How to test
```bash
cd vibe-kanban
./local-build.sh
cd npx-cli && node bin/cli.js
```

* Updated the README to reflect the correct local build instructions.

* Fixed. Now `LOCAL_DEV_MODE` only activates when the `dist/` directory actually exists, which means:

1. **Local dev** (after `./local-build.sh` creates `npx-cli/dist/`): local mode works
2. **npx** (npm cache has no `dist/` folder): normal R2 download works

* Done! The fixes are:

1. **`npx-cli/package.json`**: Added `dist` to the `files` array so local binaries get included in the tarball
2. **`npx-cli/bin/cli.js`**: Added a guard to skip `getLatestVersion()` when R2 URL is a placeholder (starts with `__`)

Now the workflow should work:
```bash
cd vibe-kanban
./local-build.sh
cd npx-cli
npm pack
npx vibe-kanban-0.0.142.tgz
```
This commit is contained in:
Louis Knight-Webb
2025-12-29 18:00:23 +00:00
committed by GitHub
parent 332bfbd965
commit 9a83d09ffd
5 changed files with 37 additions and 12 deletions

View File

@@ -90,11 +90,10 @@ cd frontend
pnpm build
```
### Build from source
### Build from source (macOS)
1. Run `build-npm-package.sh`
2. In the `npx-cli` folder run `npm pack`
3. You can run your build with `npx [GENERATED FILE].tgz`
1. Run `./local-build.sh`
2. Test with `cd npx-cli && node bin/cli.js`
### Environment Variables

View File

@@ -33,8 +33,11 @@ zip -q vibe-kanban-review.zip vibe-kanban-review
rm -f vibe-kanban-review
mv vibe-kanban-review.zip npx-cli/dist/macos-arm64/vibe-kanban-review.zip
echo "✅ NPM package ready!"
echo "✅ Build complete!"
echo "📁 Files created:"
echo " - npx-cli/dist/macos-arm64/vibe-kanban.zip"
echo " - npx-cli/dist/macos-arm64/vibe-kanban-mcp.zip"
echo " - npx-cli/dist/macos-arm64/vibe-kanban-review.zip"
echo ""
echo "🚀 To test locally, run:"
echo " cd npx-cli && node bin/cli.js"

View File

@@ -4,7 +4,7 @@ const { execSync, spawn } = require("child_process");
const AdmZip = require("adm-zip");
const path = require("path");
const fs = require("fs");
const { ensureBinary, BINARY_TAG, CACHE_DIR, getLatestVersion } = require("./download");
const { ensureBinary, BINARY_TAG, CACHE_DIR, LOCAL_DEV_MODE, LOCAL_DIST_DIR, R2_BASE_URL, getLatestVersion } = require("./download");
const CLI_VERSION = require("../package.json").version;
@@ -71,7 +71,10 @@ function getBinaryName(base) {
}
const platformDir = getPlatformDir();
const versionCacheDir = path.join(CACHE_DIR, BINARY_TAG, platformDir);
// In local dev mode, extract directly to dist directory; otherwise use global cache
const versionCacheDir = LOCAL_DEV_MODE
? path.join(LOCAL_DIST_DIR, platformDir)
: path.join(CACHE_DIR, BINARY_TAG, platformDir);
function showProgress(downloaded, total) {
const percent = total ? Math.round((downloaded / total) * 100) : 0;
@@ -145,8 +148,9 @@ async function main() {
const isMcpMode = args.includes("--mcp");
const isReviewMode = args[0] === "review";
// Non-blocking update check (skip in MCP mode to avoid stdout pollution)
if (!isMcpMode) {
// Non-blocking update check (skip in MCP mode, local dev mode, and when R2 URL not configured)
const hasValidR2Url = !R2_BASE_URL.startsWith("__");
if (!isMcpMode && !LOCAL_DEV_MODE && hasValidR2Url) {
getLatestVersion()
.then((latest) => {
if (latest && latest !== CLI_VERSION) {
@@ -183,7 +187,8 @@ async function main() {
});
});
} else {
console.log(`Starting vibe-kanban v${CLI_VERSION}...`);
const modeLabel = LOCAL_DEV_MODE ? " (local dev)" : "";
console.log(`Starting vibe-kanban v${CLI_VERSION}${modeLabel}...`);
await extractAndRun("vibe-kanban", (bin) => {
if (platform === "win32") {
execSync(`"${bin}"`, { stdio: "inherit" });

View File

@@ -8,6 +8,11 @@ const R2_BASE_URL = "__R2_PUBLIC_URL__";
const BINARY_TAG = "__BINARY_TAG__"; // e.g., v0.0.135-20251215122030
const CACHE_DIR = path.join(require("os").homedir(), ".vibe-kanban", "bin");
// Local development mode: use binaries from npx-cli/dist/ instead of R2
// Only activate if dist/ exists (i.e., running from source after local-build.sh)
const LOCAL_DIST_DIR = path.join(__dirname, "..", "dist");
const LOCAL_DEV_MODE = fs.existsSync(LOCAL_DIST_DIR) || process.env.VIBE_KANBAN_LOCAL === "1";
async function fetchJson(url) {
return new Promise((resolve, reject) => {
https.get(url, (res) => {
@@ -92,6 +97,18 @@ async function downloadFile(url, destPath, expectedSha256, onProgress) {
}
async function ensureBinary(platform, binaryName, onProgress) {
// In local dev mode, use binaries directly from npx-cli/dist/
if (LOCAL_DEV_MODE) {
const localZipPath = path.join(LOCAL_DIST_DIR, platform, `${binaryName}.zip`);
if (fs.existsSync(localZipPath)) {
return localZipPath;
}
throw new Error(
`Local binary not found: ${localZipPath}\n` +
`Run ./local-build.sh first to build the binaries.`
);
}
const cacheDir = path.join(CACHE_DIR, BINARY_TAG, platform);
const zipPath = path.join(cacheDir, `${binaryName}.zip`);
@@ -117,4 +134,4 @@ async function getLatestVersion() {
return manifest.latest;
}
module.exports = { R2_BASE_URL, BINARY_TAG, CACHE_DIR, ensureBinary, getLatestVersion };
module.exports = { R2_BASE_URL, BINARY_TAG, CACHE_DIR, LOCAL_DEV_MODE, LOCAL_DIST_DIR, ensureBinary, getLatestVersion };

View File

@@ -14,6 +14,7 @@
"adm-zip": "^0.5.16"
},
"files": [
"bin"
"bin",
"dist"
]
}