fix(ci): bound native tool downloads (#108685)

* fix(ci): bound native tool downloads

* fix(ci): bound historical SwiftFormat downloads

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
Alix-007
2026-07-16 01:44:30 -07:00
committed by GitHub
co-authored by Peter Steinberger
parent a0f8f451cd
commit e0394c2ab4
5 changed files with 81 additions and 4 deletions
+6 -2
View File
@@ -2445,7 +2445,9 @@ jobs:
esac
swiftformat_archive="$RUNNER_TEMP/swiftformat-$swiftformat_version.zip"
swift_tools_dir="$RUNNER_TEMP/openclaw-legacy-swift-tools"
curl --fail --location --silent --show-error --retry 3 \
curl --fail --location --silent --show-error \
--connect-timeout 10 --max-time 120 \
--retry 3 --retry-max-time 120 \
--output "$swiftformat_archive" \
"https://github.com/nicklockwood/SwiftFormat/releases/download/$swiftformat_version/swiftformat.zip"
if [[ "$(shasum -a 256 "$swiftformat_archive" | awk '{print $1}')" != "$swiftformat_checksum" ]]; then
@@ -2650,7 +2652,9 @@ jobs:
esac
swiftformat_archive="$RUNNER_TEMP/swiftformat-$swiftformat_version.zip"
swift_tools_dir="$RUNNER_TEMP/openclaw-legacy-swift-tools"
curl --fail --location --silent --show-error --retry 3 \
curl --fail --location --silent --show-error \
--connect-timeout 10 --max-time 120 \
--retry 3 --retry-max-time 120 \
--output "$swiftformat_archive" \
"https://github.com/nicklockwood/SwiftFormat/releases/download/$swiftformat_version/swiftformat.zip"
if [[ "$(shasum -a 256 "$swiftformat_archive" | awk '{print $1}')" != "$swiftformat_checksum" ]]; then
+6 -1
View File
@@ -18,7 +18,12 @@ install_archive() {
local archive="$temp_dir/$name.zip"
local extract_dir="$temp_dir/$name"
curl --fail --location --silent --show-error --retry 3 --output "$archive" "$url"
# Bound individual transfers and the retry window. curl resets --max-time for
# each retry, while a started retry can outlive --retry-max-time.
curl --fail --location --silent --show-error \
--connect-timeout 10 --max-time 120 \
--retry 3 --retry-max-time 120 \
--output "$archive" "$url"
if [[ "$(shasum -a 256 "$archive" | awk '{print $1}')" != "$checksum" ]]; then
echo "$name archive checksum mismatch" >&2
exit 1
+5 -1
View File
@@ -17,7 +17,11 @@ trap 'rm -rf "$temp_dir"' EXIT
archive="$temp_dir/xcodegen.zip"
extract_dir="$temp_dir/extract"
curl --fail --location --silent --show-error --retry 3 \
# Bound individual transfers and the retry window. curl resets --max-time for
# each retry, while a started retry can outlive --retry-max-time.
curl --fail --location --silent --show-error \
--connect-timeout 10 --max-time 120 \
--retry 3 --retry-max-time 120 \
--output "$archive" \
"https://github.com/yonaskolb/XcodeGen/releases/download/$xcodegen_version/xcodegen.zip"
if [[ "$(shasum -a 256 "$archive" | awk '{print $1}')" != "$xcodegen_checksum" ]]; then
+2
View File
@@ -2024,6 +2024,8 @@ describe("ci workflow guards", () => {
expect(installStep.run).toContain(
"https://github.com/nicklockwood/SwiftFormat/releases/download/$swiftformat_version/swiftformat.zip",
);
expect(installStep.run).toContain("--connect-timeout 10 --max-time 120");
expect(installStep.run).toContain("--retry 3 --retry-max-time 120");
expect(installStep.run).toContain(
'swiftformat_checksum="b990400779aceb7d7020796eb9ba814d4480543f671d38fc0ff48cb72f04c584"',
);
+62
View File
@@ -0,0 +1,62 @@
import { spawnSync } from "node:child_process";
import { chmodSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { useAutoCleanupTempDirTracker } from "../helpers/temp-dir.js";
const tempDirs = useAutoCleanupTempDirTracker(afterEach);
const installers = [
{
script: "scripts/install-xcodegen.sh",
url: "https://github.com/yonaskolb/XcodeGen/releases/download/2.45.4/xcodegen.zip",
},
{
script: "scripts/install-swift-tools.sh",
url: "https://github.com/nicklockwood/SwiftFormat/releases/download/0.62.1/swiftformat.zip",
},
] as const;
function expectOption(args: string[], option: string, value: string): void {
const index = args.indexOf(option);
expect(index, `missing curl option ${option}`).toBeGreaterThanOrEqual(0);
expect(args[index + 1]).toBe(value);
}
describe.runIf(process.platform !== "win32")("native tool installers", () => {
it.each(installers)("bounds stalled downloads in $script", ({ script, url }) => {
const root = tempDirs.make("openclaw-native-tool-installer-");
const binDir = path.join(root, "bin");
const argsPath = path.join(root, "curl-args.txt");
const curlPath = path.join(binDir, "curl");
mkdirSync(binDir);
writeFileSync(
curlPath,
[
"#!/usr/bin/env bash",
'printf "%s\\n" "$@" >"$OPENCLAW_TEST_CURL_ARGS_PATH"',
"exit 28",
"",
].join("\n"),
);
chmodSync(curlPath, 0o755);
const result = spawnSync("bash", [script, path.join(root, "install")], {
cwd: process.cwd(),
encoding: "utf8",
env: {
...process.env,
OPENCLAW_TEST_CURL_ARGS_PATH: argsPath,
PATH: `${binDir}${path.delimiter}${process.env.PATH ?? ""}`,
},
});
expect(result.status, `${result.stdout}\n${result.stderr}`).toBe(28);
const args = readFileSync(argsPath, "utf8").trimEnd().split("\n");
expectOption(args, "--connect-timeout", "10");
expectOption(args, "--max-time", "120");
expectOption(args, "--retry", "3");
expectOption(args, "--retry-max-time", "120");
expect(args).toContain(url);
});
});