mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-27 22:12:13 +00:00
fix(installer): fail failed Windows git builds
This commit is contained in:
@@ -47,6 +47,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- Windows installer: fail Git checkout installs when `pnpm install` or `pnpm build` fails instead of writing a wrapper to a missing CLI build.
|
||||
- Agents: keep parallel OpenAI-compatible tool-call deltas in separate argument buffers so interleaved tool calls no longer corrupt streamed arguments. (#82263) Thanks @luna-system.
|
||||
- Memory/doctor: report missing or unusable QMD workspace directories as workspace failures instead of generic binary failures. (#63167) Thanks @sercada.
|
||||
- Debug proxy: record CONNECT client-socket errors and destroy the paired upstream socket so abrupt client disconnects no longer leak tunnel resources. (#82444) Thanks @SebTardif.
|
||||
|
||||
@@ -23,6 +23,12 @@ function Fail-Install {
|
||||
return $false
|
||||
}
|
||||
|
||||
function Test-BooleanSuccessResult {
|
||||
param([object[]]$Results)
|
||||
|
||||
return ($Results.Count -gt 0 -and $Results[-1] -eq $true)
|
||||
}
|
||||
|
||||
function Complete-Install {
|
||||
param([bool]$Succeeded)
|
||||
|
||||
@@ -1043,10 +1049,18 @@ function Install-OpenClawFromGit {
|
||||
Push-Location -LiteralPath $RepoDir
|
||||
$pushedRepoLocation = $true
|
||||
& $pnpmCommand install
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "[!] pnpm install failed for the Git checkout" -ForegroundColor Red
|
||||
return $false
|
||||
}
|
||||
if (-not (& $pnpmCommand ui:build)) {
|
||||
Write-Host "[!] UI build failed; continuing (CLI may still work)" -ForegroundColor Yellow
|
||||
}
|
||||
& $pnpmCommand build
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "[!] pnpm build failed for the Git checkout" -ForegroundColor Red
|
||||
return $false
|
||||
}
|
||||
} finally {
|
||||
if ($pushedRepoLocation) {
|
||||
Pop-Location
|
||||
@@ -1054,12 +1068,18 @@ function Install-OpenClawFromGit {
|
||||
$env:NPM_CONFIG_SCRIPT_SHELL = $prevPnpmScriptShell
|
||||
}
|
||||
|
||||
$entryPath = Join-Path $RepoDir "dist\\entry.js"
|
||||
if (-not (Test-Path $entryPath)) {
|
||||
Write-Host "[!] OpenClaw build did not produce $entryPath" -ForegroundColor Red
|
||||
return $false
|
||||
}
|
||||
|
||||
$binDir = Join-Path $env:USERPROFILE ".local\\bin"
|
||||
if (-not (Test-Path $binDir)) {
|
||||
New-Item -ItemType Directory -Force -Path $binDir | Out-Null
|
||||
}
|
||||
$cmdPath = Join-Path $binDir "openclaw.cmd"
|
||||
$cmdContents = "@echo off`r`nnode ""$RepoDir\\dist\\entry.js"" %*`r`n"
|
||||
$cmdContents = "@echo off`r`nnode ""$entryPath"" %*`r`n"
|
||||
Set-Content -Path $cmdPath -Value $cmdContents -NoNewline
|
||||
|
||||
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
|
||||
@@ -1202,7 +1222,8 @@ function Main {
|
||||
}
|
||||
} catch { }
|
||||
$finalGitDir = $GitDir
|
||||
if (-not (Install-OpenClawFromGit -RepoDir $GitDir -SkipUpdate:$NoGitUpdate)) {
|
||||
$gitInstallResults = @(Install-OpenClawFromGit -RepoDir $GitDir -SkipUpdate:$NoGitUpdate)
|
||||
if (-not (Test-BooleanSuccessResult -Results $gitInstallResults)) {
|
||||
return (Fail-Install)
|
||||
}
|
||||
} else {
|
||||
@@ -1211,7 +1232,8 @@ function Main {
|
||||
Remove-Item -Force $gitWrapper
|
||||
Write-Host "[OK] Removed git wrapper (switching to npm)" -ForegroundColor Green
|
||||
}
|
||||
if (-not (Install-OpenClaw)) {
|
||||
$npmInstallResults = @(Install-OpenClaw)
|
||||
if (-not (Test-BooleanSuccessResult -Results $npmInstallResults)) {
|
||||
return (Fail-Install)
|
||||
}
|
||||
}
|
||||
@@ -1321,5 +1343,5 @@ function Main {
|
||||
}
|
||||
|
||||
$mainResults = @(Main)
|
||||
$installSucceeded = $mainResults.Count -gt 0 -and $mainResults[-1] -eq $true
|
||||
$installSucceeded = Test-BooleanSuccessResult -Results $mainResults
|
||||
Complete-Install -Succeeded:$installSucceeded
|
||||
|
||||
@@ -6,7 +6,12 @@ import { createScriptTestHarness } from "./test-helpers";
|
||||
|
||||
const SCRIPT_PATH = "scripts/install.ps1";
|
||||
const ENTRYPOINT_RE =
|
||||
/\r?\n\$mainResults = @\(Main\)\r?\n\$installSucceeded = \$mainResults\.Count -gt 0 -and \$mainResults\[-1\] -eq \$true\r?\nComplete-Install -Succeeded:\$installSucceeded\s*$/m;
|
||||
/\r?\n\$mainResults = @\(Main\)\r?\n\$installSucceeded = Test-BooleanSuccessResult -Results \$mainResults\r?\nComplete-Install -Succeeded:\$installSucceeded\s*$/m;
|
||||
const ENTRYPOINT_LINES = [
|
||||
"$mainResults = @(Main)",
|
||||
"$installSucceeded = Test-BooleanSuccessResult -Results $mainResults",
|
||||
"Complete-Install -Succeeded:$installSucceeded",
|
||||
];
|
||||
|
||||
function extractFunctionBody(source: string, name: string): string {
|
||||
const match = source.match(
|
||||
@@ -50,9 +55,7 @@ function createFailingNodeFixture(source: string): string {
|
||||
"function Check-Node { return $false }",
|
||||
"function Install-Node { return $false }",
|
||||
"",
|
||||
"$mainResults = @(Main)",
|
||||
"$installSucceeded = $mainResults.Count -gt 0 -and $mainResults[-1] -eq $true",
|
||||
"Complete-Install -Succeeded:$installSucceeded",
|
||||
...ENTRYPOINT_LINES,
|
||||
"",
|
||||
].join("\n");
|
||||
}
|
||||
@@ -77,9 +80,12 @@ describe("install.ps1 failure handling", () => {
|
||||
|
||||
it("keeps failure termination in the top-level completion handler", () => {
|
||||
const completeInstallBody = extractFunctionBody(source, "Complete-Install");
|
||||
const booleanSuccessBody = extractFunctionBody(source, "Test-BooleanSuccessResult");
|
||||
expect(completeInstallBody).toMatch(/\$PSCommandPath/);
|
||||
expect(completeInstallBody).toMatch(/\bexit \$script:InstallExitCode\b/);
|
||||
expect(completeInstallBody).toMatch(/\bthrow "OpenClaw installation failed with exit code/);
|
||||
expect(booleanSuccessBody).toContain("$Results.Count -gt 0");
|
||||
expect(source).toContain("$installSucceeded = Test-BooleanSuccessResult -Results $mainResults");
|
||||
});
|
||||
|
||||
it("runs npm install through the resolved command with quiet CI defaults", () => {
|
||||
@@ -227,6 +233,7 @@ describe("install.ps1 failure handling", () => {
|
||||
const pnpmVersionMatchBody = extractFunctionBody(source, "Test-PnpmCommandMatchesVersion");
|
||||
const ensurePnpmBody = extractFunctionBody(source, "Ensure-Pnpm");
|
||||
const gitInstallBody = extractFunctionBody(source, "Install-OpenClawFromGit");
|
||||
const mainBody = extractFunctionBody(source, "Main");
|
||||
|
||||
expect(pnpmVersionBody).toContain("package.json");
|
||||
expect(pnpmVersionBody).toContain("$packageJson.packageManager -match '^pnpm@(?<version>[^+]+)'");
|
||||
@@ -247,9 +254,31 @@ describe("install.ps1 failure handling", () => {
|
||||
expect(gitInstallBody.indexOf("git -C $RepoDir pull --rebase")).toBeLessThan(
|
||||
gitInstallBody.indexOf("Ensure-Pnpm -RepoDir $RepoDir"),
|
||||
);
|
||||
expect(mainBody).toContain("$gitInstallResults = @(Install-OpenClawFromGit");
|
||||
expect(mainBody).toContain(
|
||||
"Test-BooleanSuccessResult -Results $gitInstallResults",
|
||||
);
|
||||
expect(mainBody).toContain("$npmInstallResults = @(Install-OpenClaw)");
|
||||
expect(mainBody).toContain(
|
||||
"Test-BooleanSuccessResult -Results $npmInstallResults",
|
||||
);
|
||||
expect(gitInstallBody).toContain("Push-Location -LiteralPath $RepoDir");
|
||||
expect(gitInstallBody).toContain("& $pnpmCommand install");
|
||||
expect(gitInstallBody).toContain(
|
||||
'Write-Host "[!] pnpm install failed for the Git checkout"',
|
||||
);
|
||||
expect(gitInstallBody).toContain("& $pnpmCommand build");
|
||||
expect(gitInstallBody).toContain(
|
||||
'Write-Host "[!] pnpm build failed for the Git checkout"',
|
||||
);
|
||||
expect(gitInstallBody).toContain('$entryPath = Join-Path $RepoDir "dist\\\\entry.js"');
|
||||
expect(gitInstallBody).toContain("Test-Path $entryPath");
|
||||
expect(gitInstallBody).toContain(
|
||||
'Write-Host "[!] OpenClaw build did not produce $entryPath"',
|
||||
);
|
||||
expect(gitInstallBody).toContain('node ""$entryPath"" %*');
|
||||
expect(gitInstallBody).not.toContain("& $pnpmCommand -C $RepoDir install");
|
||||
expect(gitInstallBody).not.toContain('node ""$RepoDir\\\\dist\\\\entry.js"" %*');
|
||||
});
|
||||
|
||||
it("cleans legacy git submodules only from the selected git checkout", () => {
|
||||
@@ -309,6 +338,42 @@ describe("install.ps1 failure handling", () => {
|
||||
expect(result.stdout).toContain("alive-after-install");
|
||||
});
|
||||
|
||||
runIfPowerShell("treats noisy Git install false as failure", () => {
|
||||
const tempDir = harness.createTempDir("openclaw-install-ps1-");
|
||||
const scriptPath = join(tempDir, "install.ps1");
|
||||
const scriptWithoutEntryPoint = source.replace(ENTRYPOINT_RE, "");
|
||||
writeFileSync(
|
||||
scriptPath,
|
||||
[
|
||||
scriptWithoutEntryPoint,
|
||||
"",
|
||||
"function Write-Banner { }",
|
||||
"function Ensure-ExecutionPolicy { return $true }",
|
||||
"function Check-Node { return $true }",
|
||||
"function Check-ExistingOpenClaw { return $false }",
|
||||
"function Get-NpmCommandPath { return $null }",
|
||||
"function Install-OpenClawFromGit {",
|
||||
" Write-Output 'pnpm stdout before failure'",
|
||||
" return $false",
|
||||
"}",
|
||||
"function Ensure-OpenClawOnPath { throw 'should not continue after failed git install' }",
|
||||
"$InstallMethod = 'git'",
|
||||
"$GitDir = 'C:\\\\openclaw-test'",
|
||||
"$NoOnboard = $true",
|
||||
"$result = Main",
|
||||
'if ($result -ne $false) { throw "Main returned $result" }',
|
||||
'if ($script:InstallExitCode -ne 1) { throw "InstallExitCode=$script:InstallExitCode" }',
|
||||
"",
|
||||
].join("\n"),
|
||||
);
|
||||
chmodSync(scriptPath, 0o755);
|
||||
|
||||
const result = runPowerShell(["-NoLogo", "-NoProfile", "-Command", `. ${toPowerShellSingleQuotedLiteral(scriptPath)}`]);
|
||||
|
||||
expect(result.status).toBe(0);
|
||||
expect(result.stderr).toBe("");
|
||||
});
|
||||
|
||||
runIfPowerShell("keeps npm chatter out of Main's success return value", () => {
|
||||
const tempDir = harness.createTempDir("openclaw-install-ps1-");
|
||||
const scriptPath = join(tempDir, "install.ps1");
|
||||
@@ -371,9 +436,7 @@ describe("install.ps1 failure handling", () => {
|
||||
"function Refresh-GatewayServiceIfLoaded { }",
|
||||
"function Invoke-OpenClawCommand { return 'OpenClaw test-version' }",
|
||||
"$NoOnboard = $true",
|
||||
"$mainResults = @(Main)",
|
||||
"$installSucceeded = $mainResults.Count -gt 0 -and $mainResults[-1] -eq $true",
|
||||
"Complete-Install -Succeeded:$installSucceeded",
|
||||
...ENTRYPOINT_LINES,
|
||||
"",
|
||||
].join("\n"),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user