mirror of
https://github.com/hanzoai/dev.git
synced 2026-10-25 03:32:32 +00:00
fix(cli/postinstall): rerun bootstrap when scripts skipped (#369)
This commit is contained in:
+21
-6
@@ -6,6 +6,7 @@ import { fileURLToPath } from "url";
|
||||
import { platform as nodePlatform, arch as nodeArch } from "os";
|
||||
import { execSync } from "child_process";
|
||||
import { get as httpsGet } from "https";
|
||||
import { runPostinstall } from "../postinstall.js";
|
||||
|
||||
// __dirname equivalent in ESM
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
@@ -270,12 +271,26 @@ const tryBootstrapBinary = async () => {
|
||||
};
|
||||
|
||||
// If missing, attempt to bootstrap into place (helps when Bun blocks postinstall)
|
||||
if (!existsSync(binaryPath) && !existsSync(legacyBinaryPath)) {
|
||||
const ok = await tryBootstrapBinary();
|
||||
if (!ok) {
|
||||
// retry legacy name in case archive provided coder-*
|
||||
if (existsSync(legacyBinaryPath) && !existsSync(binaryPath)) {
|
||||
binaryPath = legacyBinaryPath;
|
||||
let binaryReady = existsSync(binaryPath) || existsSync(legacyBinaryPath);
|
||||
if (!binaryReady) {
|
||||
let runtimePostinstallError = null;
|
||||
try {
|
||||
await runPostinstall({ invokedByRuntime: true, skipGlobalAlias: true });
|
||||
} catch (err) {
|
||||
runtimePostinstallError = err;
|
||||
}
|
||||
|
||||
binaryReady = existsSync(binaryPath) || existsSync(legacyBinaryPath);
|
||||
if (!binaryReady) {
|
||||
const ok = await tryBootstrapBinary();
|
||||
if (!ok) {
|
||||
if (runtimePostinstallError && !lastBootstrapError) {
|
||||
lastBootstrapError = runtimePostinstallError;
|
||||
}
|
||||
// retry legacy name in case archive provided coder-*
|
||||
if (existsSync(legacyBinaryPath) && !existsSync(binaryPath)) {
|
||||
binaryPath = legacyBinaryPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Non-functional change to trigger release workflow
|
||||
|
||||
import { existsSync, mkdirSync, createWriteStream, chmodSync, readFileSync, readSync, writeFileSync, unlinkSync, statSync, openSync, closeSync, copyFileSync, fsyncSync, renameSync, realpathSync } from 'fs';
|
||||
import { join, dirname } from 'path';
|
||||
import { join, dirname, resolve } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { get } from 'https';
|
||||
import { platform, arch, tmpdir } from 'os';
|
||||
@@ -288,13 +288,21 @@ function validateDownloadedBinary(p) {
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
export async function runPostinstall(options = {}) {
|
||||
const { skipGlobalAlias = false, invokedByRuntime = false } = options;
|
||||
if (process.env.CODE_POSTINSTALL_DRY_RUN === '1') {
|
||||
return { skipped: true };
|
||||
}
|
||||
|
||||
if (invokedByRuntime) {
|
||||
process.env.CODE_RUNTIME_POSTINSTALL = process.env.CODE_RUNTIME_POSTINSTALL || '1';
|
||||
}
|
||||
// Detect potential PATH conflict with an existing `code` command (e.g., VS Code)
|
||||
// Only relevant for global installs; skip for npx/local installs to keep postinstall fast.
|
||||
const ua = process.env.npm_config_user_agent || '';
|
||||
const isNpx = ua.includes('npx');
|
||||
const isGlobal = process.env.npm_config_global === 'true';
|
||||
if (isGlobal && !isNpx) {
|
||||
if (!skipGlobalAlias && isGlobal && !isNpx) {
|
||||
try {
|
||||
const whichCmd = process.platform === 'win32' ? 'where code' : 'command -v code || which code || true';
|
||||
const resolved = execSync(whichCmd, { stdio: ['ignore', 'pipe', 'ignore'], shell: process.platform !== 'win32' }).toString().split(/\r?\n/).filter(Boolean)[0];
|
||||
@@ -760,7 +768,19 @@ async function main() {
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(error => {
|
||||
console.error('Installation failed:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
function isExecutedDirectly() {
|
||||
const entry = process.argv[1];
|
||||
if (!entry) return false;
|
||||
try {
|
||||
return resolve(entry) === fileURLToPath(import.meta.url);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (isExecutedDirectly()) {
|
||||
runPostinstall().catch(error => {
|
||||
console.error('Installation failed:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
|
||||
test('runPostinstall resolves in dry-run mode', async () => {
|
||||
const { runPostinstall } = await import('../postinstall.js');
|
||||
process.env.CODE_POSTINSTALL_DRY_RUN = '1';
|
||||
try {
|
||||
const result = await runPostinstall({ invokedByRuntime: true, skipGlobalAlias: true });
|
||||
assert.ok(result && result.skipped === true);
|
||||
} finally {
|
||||
delete process.env.CODE_POSTINSTALL_DRY_RUN;
|
||||
delete process.env.CODE_RUNTIME_POSTINSTALL;
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user