@@ -65,6 +65,7 @@ import {
|
65 | 65 | resolveRequestedSuites, |
66 | 66 | resolveRunnerMatrix, |
67 | 67 | resolveStaticFileContentType, |
| 68 | +startStaticFileServer, |
68 | 69 | shouldExerciseManagedGatewayLifecycleAfterInstall, |
69 | 70 | shouldRunPackagedUpgradeStatusProbe, |
70 | 71 | shouldRunWindowsInstalledBrowserOverrideImportSmoke, |
@@ -659,6 +660,42 @@ describe("scripts/openclaw-cross-os-release-checks", () => {
|
659 | 660 | expect(resolveStaticFileContentType("openclaw-2026.4.14.tgz")).toBe("application/octet-stream"); |
660 | 661 | }); |
661 | 662 | |
| 663 | +it("streams release artifacts from the static file server", async () => { |
| 664 | +const dir = mkdtempSync(join(tmpdir(), "openclaw-cross-os-static-server-")); |
| 665 | +const filePath = join(dir, "openclaw-2026.4.14.tgz"); |
| 666 | +const logPath = join(dir, "server.log"); |
| 667 | +let server: Awaited<ReturnType<typeof startStaticFileServer>> | undefined; |
| 668 | + |
| 669 | +try { |
| 670 | +const payload = Buffer.from(`artifact-head\n${"x".repeat(1024 * 1024)}\nartifact-tail`); |
| 671 | +writeFileSync(filePath, payload); |
| 672 | + |
| 673 | +server = await startStaticFileServer({ filePath, logPath }); |
| 674 | +const response = await fetch(server.url); |
| 675 | +const body = Buffer.from(await response.arrayBuffer()); |
| 676 | + |
| 677 | +expect(response.status).toBe(200); |
| 678 | +expect(response.headers.get("content-length")).toBe(String(payload.length)); |
| 679 | +expect(response.headers.get("content-type")).toBe("application/octet-stream"); |
| 680 | +expect(body.equals(payload)).toBe(true); |
| 681 | +expect(readFileSync(logPath, "utf8")).toContain(`GET /${filePath.split(/[/\\]/u).at(-1)}`); |
| 682 | +} finally { |
| 683 | +await server?.close(); |
| 684 | +rmSync(dir, { recursive: true, force: true }); |
| 685 | +} |
| 686 | +}); |
| 687 | + |
| 688 | +it("does not preload static release artifacts before serving them", () => { |
| 689 | +const source = readFileSync("scripts/openclaw-cross-os-release-checks.ts", "utf8"); |
| 690 | +const serverSource = source.slice( |
| 691 | +source.indexOf("export async function startStaticFileServer"), |
| 692 | +source.indexOf("export function resolveStaticFileContentType"), |
| 693 | +); |
| 694 | + |
| 695 | +expect(serverSource).toContain("createReadStream(params.filePath)"); |
| 696 | +expect(serverSource).not.toContain("readFileSync(params.filePath)"); |
| 697 | +}); |
| 698 | + |
662 | 699 | it("uses the published installer URLs for native installer lanes", () => { |
663 | 700 | expect(resolvePublishedInstallerUrl("darwin")).toBe("https://openclaw.ai/install.sh"); |
664 | 701 | expect(resolvePublishedInstallerUrl("linux")).toBe("https://openclaw.ai/install.sh"); |
|