farmcontrol-ui/scripts/ensure-hutch.mjs
Tom Butcher 6690516be3
Some checks failed
farmcontrol/farmcontrol-ui/pipeline/head There was a failure building this commit
Update dependencies and enhance build scripts for Electrobun
- Updated `electrobun` dependency to version `1.18.4-beta.19` in `package.json` and `bun.lock`.
- Added `rcedit` and `@tweenjs/tween.js` dependencies to `bun.lock`.
- Modified `Jenkinsfile` to clean up additional staging directories for production builds.
- Refactored `electrobun.config.ts` to dynamically read the `package.json` path.
- Introduced new scripts for managing Hutch installation and execution, improving the build process.
- Enhanced artifact finalization logic to support multiple build environments and streamline platform directory resolution.
2026-08-07 21:35:16 +01:00

128 lines
3.5 KiB
JavaScript

import { spawnSync } from "node:child_process";
import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { get } from "node:https";
import { homedir, platform, tmpdir } from "node:os";
import path from "node:path";
import {
getElectrobunVersion,
hutchIsInstalled,
resolveHutchCommand,
} from "./resolve-hutch-command.mjs";
const installerBaseUrl = "https://hutch.blackboard.sh/hutch";
const maxInstallerBytes = 1024 * 1024;
function download(url, redirects = 0) {
if (redirects > 5) {
return Promise.reject(new Error("too many installer redirects"));
}
return new Promise((resolve, reject) => {
const request = get(url, (response) => {
if (
response.statusCode >= 300 &&
response.statusCode < 400 &&
response.headers.location
) {
response.resume();
resolve(
download(new URL(response.headers.location, url).href, redirects + 1),
);
return;
}
if (response.statusCode !== 200) {
response.resume();
reject(
new Error(`installer download returned HTTP ${response.statusCode}`),
);
return;
}
const chunks = [];
let size = 0;
response.on("data", (chunk) => {
size += chunk.length;
if (size > maxInstallerBytes) {
request.destroy(new Error("installer download exceeded 1 MiB"));
return;
}
chunks.push(chunk);
});
response.on("end", () => resolve(Buffer.concat(chunks)));
});
request.on("error", reject);
});
}
function checkedSpawn(command, args, options) {
const result = spawnSync(command, args, options);
if (result.error) {
throw result.error;
}
if (result.status !== 0) {
throw new Error(`${command} exited with status ${result.status ?? "unknown"}`);
}
}
async function installHutch(channel) {
const temporary = mkdtempSync(path.join(tmpdir(), "electrobun-hutch-"));
try {
if (platform() === "win32") {
const installer = path.join(temporary, "install.ps1");
writeFileSync(installer, await download(`${installerBaseUrl}/install.ps1`));
checkedSpawn(
"powershell.exe",
[
"-NoProfile",
"-NonInteractive",
"-ExecutionPolicy",
"Bypass",
"-File",
installer,
"-Channel",
channel,
],
{ env: process.env, stdio: "inherit" },
);
} else {
const installer = path.join(temporary, "install.sh");
writeFileSync(installer, await download(`${installerBaseUrl}/install.sh`), {
mode: 0o700,
});
checkedSpawn("sh", [installer, "--channel", channel, "--no-modify-path"], {
env: process.env,
stdio: "inherit",
});
}
} finally {
rmSync(temporary, { force: true, recursive: true });
}
}
const command = resolveHutchCommand();
if (hutchIsInstalled(command)) {
console.log(`ensure-hutch: ${command} already present`);
process.exit(0);
}
const version = getElectrobunVersion();
const channel = version.includes("-") ? "canary" : "production";
if (process.env.ELECTROBUN_HUTCH_BINARY) {
console.error(`ensure-hutch: ELECTROBUN_HUTCH_BINARY does not exist: ${command}`);
process.exit(1);
}
console.error(
`ensure-hutch: installing Hutch ${channel} for electrobun ${version}...`,
);
await installHutch(channel);
if (!existsSync(command)) {
console.error(`ensure-hutch: Hutch was not installed at ${command}`);
process.exit(1);
}
console.log(`ensure-hutch: ${command} ready`);