mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(e2e): download non-root installer before execution
Download the non-root Docker smoke installer before executing it. - preserve the existing 30-second connection and 300-second transfer limits - clean up the temporary installer on success or failure - prove failed downloads cannot execute partial installer content Co-authored-by: thomas.szbay <xydigit-zt@users.noreply.github.com> Punchcard-Session: golden-lantern-meadow-0x
This commit is contained in:
@@ -62,7 +62,12 @@ node -e '
|
||||
command -v npm >/dev/null
|
||||
|
||||
echo "==> Run installer (non-root user)"
|
||||
curl -fsSL --connect-timeout 30 --max-time 300 -- "$INSTALL_URL" | bash
|
||||
# This non-root harness downloads first; public smoke and CLI lanes intentionally
|
||||
# retain their streaming installer contract.
|
||||
installer="$(mktemp)"
|
||||
trap 'rm -f "$installer"' EXIT
|
||||
curl -fsSL --connect-timeout 30 --max-time 300 -o "$installer" -- "$INSTALL_URL"
|
||||
bash "$installer"
|
||||
|
||||
# Ensure PATH picks up user npm prefix
|
||||
export PATH="$HOME/.npm-global/bin:$PATH"
|
||||
|
||||
@@ -71,6 +71,18 @@ function extractInstallE2eInstallerFunction(): string {
|
||||
return script.slice(start, end);
|
||||
}
|
||||
|
||||
function extractNonrootInstallerStep(): string {
|
||||
const script = readFileSync(NONROOT_RUNNER_PATH, "utf8");
|
||||
const startMarker = 'echo "==> Run installer (non-root user)"';
|
||||
const endMarker = "\n\n# Ensure PATH";
|
||||
const start = script.indexOf(startMarker);
|
||||
const end = script.indexOf(endMarker, start + startMarker.length);
|
||||
if (start < 0 || end <= start) {
|
||||
throw new Error("non-root installer step was not found");
|
||||
}
|
||||
return script.slice(start, end);
|
||||
}
|
||||
|
||||
function extractDockerTimezoneValidator(): string {
|
||||
const script = readFileSync(DOCKER_SETUP_PATH, "utf8");
|
||||
const match = script.match(
|
||||
@@ -188,6 +200,64 @@ function runInstallE2eInstallerFixture(params: {
|
||||
return { curlArgsPath, markerPath, outputPathCapture, result };
|
||||
}
|
||||
|
||||
function runNonrootInstallerFixture(curlExitCode: number) {
|
||||
const root = tempDirs.make("openclaw-install-nonroot-download-");
|
||||
const binDir = join(root, "bin");
|
||||
const curlArgsPath = join(root, "curl-args.txt");
|
||||
const markerPath = join(root, "installer-marker.txt");
|
||||
const outputPathCapture = join(root, "curl-output-path.txt");
|
||||
mkdirSync(binDir, { recursive: true });
|
||||
writeFileSync(
|
||||
join(binDir, "curl"),
|
||||
[
|
||||
"#!/bin/sh",
|
||||
"set -eu",
|
||||
`printf '%s\\0' "$@" >"$CURL_ARGS_PATH"`,
|
||||
'output=""',
|
||||
'while [ "$#" -gt 0 ]; do',
|
||||
' if [ "$1" = "-o" ]; then',
|
||||
" shift",
|
||||
' output="$1"',
|
||||
" fi",
|
||||
" shift",
|
||||
"done",
|
||||
`printf '%s\\n' 'touch "$INSTALL_MARKER"' >"$output"`,
|
||||
'chmod +x "$output"',
|
||||
'printf "%s" "$output" >"$OUTPUT_PATH_CAPTURE"',
|
||||
'exit "$FAKE_CURL_EXIT"',
|
||||
"",
|
||||
].join("\n"),
|
||||
{ mode: 0o755 },
|
||||
);
|
||||
|
||||
const result = spawnSync(
|
||||
"/bin/bash",
|
||||
[
|
||||
"--noprofile",
|
||||
"--norc",
|
||||
"-c",
|
||||
[
|
||||
"set -euo pipefail",
|
||||
'INSTALL_URL="https://installer.example.test/install.sh"',
|
||||
extractNonrootInstallerStep(),
|
||||
].join("\n"),
|
||||
],
|
||||
{
|
||||
encoding: "utf8",
|
||||
env: {
|
||||
...process.env,
|
||||
CURL_ARGS_PATH: curlArgsPath,
|
||||
FAKE_CURL_EXIT: String(curlExitCode),
|
||||
INSTALL_MARKER: markerPath,
|
||||
OUTPUT_PATH_CAPTURE: outputPathCapture,
|
||||
PATH: `${binDir}:${process.env.PATH ?? ""}`,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
return { curlArgsPath, markerPath, outputPathCapture, result };
|
||||
}
|
||||
|
||||
function runNonrootNodePreflight(
|
||||
version: string,
|
||||
options: { sqlite?: boolean; sqliteVersion?: string } = {},
|
||||
@@ -1227,8 +1297,39 @@ printf 'status=%s\\n' "$status"
|
||||
`'set -o pipefail; curl -fsSL --connect-timeout 30 --max-time 300 -- "$OPENCLAW_INSTALL_CLI_URL" | bash -s -- --set-npm-prefix --no-onboard'`,
|
||||
);
|
||||
expect(nonrootRunner).toContain(
|
||||
'curl -fsSL --connect-timeout 30 --max-time 300 -- "$INSTALL_URL" | bash',
|
||||
'curl -fsSL --connect-timeout 30 --max-time 300 -o "$installer" -- "$INSTALL_URL"',
|
||||
);
|
||||
expect(nonrootRunner.indexOf('-o "$installer"')).toBeLessThan(
|
||||
nonrootRunner.indexOf('bash "$installer"'),
|
||||
);
|
||||
});
|
||||
|
||||
it("does not execute or retain a non-root installer after curl fails", () => {
|
||||
const fixture = runNonrootInstallerFixture(28);
|
||||
const outputPath = readFileSync(fixture.outputPathCapture, "utf8");
|
||||
|
||||
expect(fixture.result.status).toBe(28);
|
||||
expect(readNulSeparatedArgs(fixture.curlArgsPath)).toEqual([
|
||||
"-fsSL",
|
||||
"--connect-timeout",
|
||||
"30",
|
||||
"--max-time",
|
||||
"300",
|
||||
"-o",
|
||||
outputPath,
|
||||
"--",
|
||||
"https://installer.example.test/install.sh",
|
||||
]);
|
||||
expect(existsSync(fixture.markerPath)).toBe(false);
|
||||
expect(existsSync(outputPath)).toBe(false);
|
||||
});
|
||||
|
||||
it("executes and cleans the non-root installer after curl succeeds", () => {
|
||||
const fixture = runNonrootInstallerFixture(0);
|
||||
|
||||
expect(fixture.result.status, fixture.result.stderr).toBe(0);
|
||||
expect(existsSync(fixture.markerPath)).toBe(true);
|
||||
expect(existsSync(readFileSync(fixture.outputPathCapture, "utf8"))).toBe(false);
|
||||
});
|
||||
|
||||
it("uses public npm latest as the non-root installer expectation", () => {
|
||||
|
||||
Reference in New Issue
Block a user