fix(e2e): bound official installer download (#108937)

* fix(e2e): bound official installer download

* test(e2e): cover downloaded installer execution

* fix(e2e): harden installer download proof

Co-authored-by: Alix-007 <li.long15@xydigit.com>

* test(e2e): type installer fixture environment

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
Alix-007
2026-07-16 20:26:00 +08:00
committed by GitHub
parent 02f494b51e
commit 66a4205c57
3 changed files with 128 additions and 7 deletions
+11 -5
View File
@@ -150,15 +150,21 @@ preinstall_previous_version() {
fi
}
run_official_installer() {
run_official_installer() (
local installer
# time_phase disables errexit, so setup and download failures must return explicitly.
installer="$(mktemp)" || return
trap 'rm -f "$installer"' EXIT
curl -fsSL --connect-timeout 10 --max-time 120 "$INSTALL_URL" -o "$installer" || return
if [[ "$INSTALL_TAG" == "beta" ]]; then
curl -fsSL "$INSTALL_URL" | OPENCLAW_BETA=1 bash
OPENCLAW_BETA=1 bash "$installer"
elif [[ "$INSTALL_TAG" != "latest" ]]; then
curl -fsSL "$INSTALL_URL" | OPENCLAW_VERSION="$INSTALL_TAG" bash
OPENCLAW_VERSION="$INSTALL_TAG" bash "$installer"
else
curl -fsSL "$INSTALL_URL" | bash
bash "$installer"
fi
}
)
verify_installed_version() {
INSTALLED_VERSION="$(openclaw --version 2>/dev/null | head -n 1 | tr -d '\r')"
+2 -2
View File
@@ -4348,8 +4348,8 @@ heartbeat_elapsed="\${BASH_REMATCH[1]}"
it("passes installer tag env to bash, not curl", () => {
const runner = readFileSync(INSTALL_E2E_RUNNER_PATH, "utf8");
expect(runner).toContain('curl -fsSL "$INSTALL_URL" | OPENCLAW_BETA=1 bash');
expect(runner).toContain('curl -fsSL "$INSTALL_URL" | OPENCLAW_VERSION="$INSTALL_TAG" bash');
expect(runner).toContain('OPENCLAW_BETA=1 bash "$installer"');
expect(runner).toContain('OPENCLAW_VERSION="$INSTALL_TAG" bash "$installer"');
expect(runner).not.toContain('OPENCLAW_BETA=1 curl -fsSL "$INSTALL_URL" | bash');
expect(runner).not.toContain(
'OPENCLAW_VERSION="$INSTALL_TAG" curl -fsSL "$INSTALL_URL" | bash',
+115
View File
@@ -59,6 +59,87 @@ function extractNonrootNodePreflight(): string {
return expectDefined(match[1], "non-root smoke Node preflight capture");
}
function extractInstallE2eInstallerFunction(): string {
const script = readFileSync(INSTALL_E2E_RUNNER_PATH, "utf8");
const startMarker = "run_official_installer() (\n";
const endMarker = "\n\nverify_installed_version()";
const start = script.indexOf(startMarker);
const end = script.indexOf(endMarker, start + startMarker.length);
if (start < 0 || end <= start) {
throw new Error("install E2E installer function was not found");
}
return script.slice(start, end);
}
function runInstallE2eInstallerFixture(params: {
curlExitCode?: number;
installTag: string;
installerBody: string;
}) {
const root = tempDirs.make("openclaw-install-e2e-download-");
const binDir = join(root, "bin");
const curlPath = join(binDir, "curl");
const curlArgsPath = join(root, "curl-args.txt");
const installerSourcePath = join(root, "installer-source.sh");
const markerPath = join(root, "installer-marker.txt");
const outputPathCapture = join(root, "curl-output-path.txt");
mkdirSync(binDir, { recursive: true });
writeFileSync(installerSourcePath, params.installerBody);
writeFileSync(
curlPath,
[
"#!/bin/sh",
"set -eu",
'printf \'%s\\n\' "$*" >"$CURL_ARGS_PATH"',
'output=""',
'while [ "$#" -gt 0 ]; do',
' if [ "$1" = "-o" ]; then',
" shift",
' output="$1"',
" fi",
" shift",
"done",
'cp "$FAKE_INSTALLER_SOURCE" "$output"',
'printf "%s" "$output" >"$OUTPUT_PATH_CAPTURE"',
'exit "$FAKE_CURL_EXIT"',
"",
].join("\n"),
{ mode: 0o755 },
);
const env: NodeJS.ProcessEnv = {
...process.env,
CURL_ARGS_PATH: curlArgsPath,
FAKE_CURL_EXIT: String(params.curlExitCode ?? 0),
FAKE_INSTALLER_SOURCE: installerSourcePath,
INSTALL_MARKER: markerPath,
OUTPUT_PATH_CAPTURE: outputPathCapture,
PATH: `${binDir}:${process.env.PATH ?? ""}`,
};
delete env.OPENCLAW_BETA;
delete env.OPENCLAW_VERSION;
const result = spawnSync(
"/bin/bash",
[
"-c",
[
"set -u",
extractInstallE2eInstallerFunction(),
'INSTALL_URL="https://installer.example.test/install.sh"',
`INSTALL_TAG=${JSON.stringify(params.installTag)}`,
"run_official_installer",
].join("\n"),
],
{
encoding: "utf8",
env,
},
);
return { curlArgsPath, markerPath, outputPathCapture, result };
}
function runNonrootNodePreflight(
version: string,
options: { sqlite?: boolean; sqliteVersion?: string } = {},
@@ -960,6 +1041,40 @@ printf 'status=%s\\n' "$status"
});
describe("install-sh E2E runner", () => {
it("does not execute a partial installer after a bounded download fails", () => {
const fixture = runInstallE2eInstallerFixture({
curlExitCode: 28,
installerBody: 'touch "$INSTALL_MARKER"\n',
installTag: "latest",
});
expect(fixture.result.status).toBe(28);
expect(readFileSync(fixture.curlArgsPath, "utf8")).toContain(
"-fsSL --connect-timeout 10 --max-time 120 https://installer.example.test/install.sh -o",
);
expect(existsSync(fixture.markerPath)).toBe(false);
expect(existsSync(readFileSync(fixture.outputPathCapture, "utf8"))).toBe(false);
});
it.each([
["latest", "|"],
["beta", "1|"],
["2026.7.1", "|2026.7.1"],
])(
"executes a complete %s installer with the expected tag environment",
(installTag, expected) => {
const fixture = runInstallE2eInstallerFixture({
installTag,
installerBody:
'printf "%s|%s" "${OPENCLAW_BETA-}" "${OPENCLAW_VERSION-}" >"$INSTALL_MARKER"\n',
});
expect(fixture.result.status, fixture.result.stderr).toBe(0);
expect(readFileSync(fixture.markerPath, "utf8")).toBe(expected);
expect(existsSync(readFileSync(fixture.outputPathCapture, "utf8"))).toBe(false);
},
);
it("normalizes Docker wrapper timing and toggle knobs before forwarding", () => {
const wrapper = readFileSync(INSTALL_E2E_DOCKER_PATH, "utf8");