Enhance build configuration and scripts
Some checks failed
farmcontrol/farmcontrol-server/pipeline/head There was a failure building this commit
Some checks failed
farmcontrol/farmcontrol-server/pipeline/head There was a failure building this commit
- Updated electrobun.config.ts to include environment-based settings for stability and external dependencies. - Refactored package.json scripts for improved build processes and streamlined commands. - Added new build scripts for Linux and renderer, while removing the obsolete build-server script. - Enhanced pre-build validation to ensure required files are present and added logging for better visibility. - Updated clean-build script to remove additional artifact directories for thorough cleanup.
This commit is contained in:
parent
c14a12648a
commit
8741a2c6fd
@ -2,6 +2,15 @@ import type { ElectrobunConfig } from "electrobun";
|
|||||||
import { readFileSync } from "node:fs";
|
import { readFileSync } from "node:fs";
|
||||||
|
|
||||||
const packageJson = JSON.parse(readFileSync("./package.json", "utf8"));
|
const packageJson = JSON.parse(readFileSync("./package.json", "utf8"));
|
||||||
|
const buildEnv = process.env.ELECTROBUN_BUILD_ENV || "dev";
|
||||||
|
const isStable = buildEnv === "stable";
|
||||||
|
|
||||||
|
const nativeExternals = [
|
||||||
|
"canvas",
|
||||||
|
"@napi-rs/canvas",
|
||||||
|
"@img/sharp-libvips*",
|
||||||
|
"@napi-rs/*",
|
||||||
|
];
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
app: {
|
app: {
|
||||||
@ -9,6 +18,7 @@ export default {
|
|||||||
identifier: "com.tombutcher.farmcontrolserver",
|
identifier: "com.tombutcher.farmcontrolserver",
|
||||||
version: packageJson.version,
|
version: packageJson.version,
|
||||||
description: "Farm Control Server desktop host application",
|
description: "Farm Control Server desktop host application",
|
||||||
|
urlSchemes: ["farmcontrolserver"],
|
||||||
},
|
},
|
||||||
runtime: {
|
runtime: {
|
||||||
exitOnLastWindowClosed: false,
|
exitOnLastWindowClosed: false,
|
||||||
@ -16,18 +26,23 @@ export default {
|
|||||||
build: {
|
build: {
|
||||||
buildFolder: "build",
|
buildFolder: "build",
|
||||||
artifactFolder: "app_dist",
|
artifactFolder: "app_dist",
|
||||||
|
useAsar: isStable,
|
||||||
|
asarUnpack: ["*.node", "*.dll", "*.dylib", "*.so"],
|
||||||
bun: {
|
bun: {
|
||||||
entrypoint: "src/bun/index.js",
|
entrypoint: "src/bun/index.js",
|
||||||
|
external: nativeExternals,
|
||||||
|
packages: "external",
|
||||||
},
|
},
|
||||||
copy: {
|
copy: {
|
||||||
"dist/app/index.html": "views/mainview/index.html",
|
"dist/mainview": "views/mainview",
|
||||||
"dist/app/assets": "views/mainview/assets",
|
|
||||||
"config.json": "config.json",
|
"config.json": "config.json",
|
||||||
},
|
},
|
||||||
watch: ["scripts"],
|
watch: ["scripts", "src/app"],
|
||||||
watchIgnore: ["dist/**", "app_dist/**"],
|
watchIgnore: ["dist/**", "build/**", "app_dist/**"],
|
||||||
mac: {
|
mac: {
|
||||||
bundleCEF: false,
|
bundleCEF: false,
|
||||||
|
codesign: isStable,
|
||||||
|
notarize: isStable,
|
||||||
},
|
},
|
||||||
linux: {
|
linux: {
|
||||||
bundleCEF: false,
|
bundleCEF: false,
|
||||||
|
|||||||
15
package.json
15
package.json
@ -2,23 +2,16 @@
|
|||||||
"name": "farmcontrol-server",
|
"name": "farmcontrol-server",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "Connects to moonraker and also manages the socket connection to the printer.",
|
"description": "Connects to moonraker and also manages the socket connection to the printer.",
|
||||||
"main": "build/index.js",
|
|
||||||
"bin": "build/index.js",
|
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "bun run build/server && bun build/index.js",
|
"start": "bun src/headless.js",
|
||||||
"dev": "cross-env NODE_ENV=development bun --watch src/index.js",
|
"dev": "cross-env NODE_ENV=development bun --watch src/index.js",
|
||||||
"dev:app": "concurrently \"cross-env NODE_ENV=development bun run dev:renderer\" \"cross-env NODE_ENV=development electrobun dev\"",
|
"dev:app": "concurrently \"cross-env NODE_ENV=development bun run dev:renderer\" \"cross-env NODE_ENV=development electrobun dev\"",
|
||||||
"dev:renderer": "vite src/app --port 5287 --no-open",
|
"dev:renderer": "vite src/app --port 5287 --no-open",
|
||||||
"build": "bun run cleanBuild && bun run build:server && bun run build:renderer",
|
"build:app": "electrobun build --env=stable",
|
||||||
"build:server": "bun run scripts/build-server.mjs",
|
|
||||||
"build:renderer": "vite build src/app",
|
|
||||||
"build:app": "bun run build && electrobun build --env=stable",
|
|
||||||
"build:app:mac": "bun scripts/build-macos.mjs",
|
"build:app:mac": "bun scripts/build-macos.mjs",
|
||||||
"build:linux": "bun run cleanBuild && bun run build:server && bun run build:linux-binary && bun run build:linux-packages",
|
"build:linux": "bun scripts/build-linux.mjs",
|
||||||
"build:linux-binary": "bun scripts/build-linux-binary.mjs",
|
"clean": "bun scripts/clean-build.mjs"
|
||||||
"build:linux-packages": "bash scripts/build-linux-packages.sh",
|
|
||||||
"cleanBuild": "bun scripts/clean-build.mjs"
|
|
||||||
},
|
},
|
||||||
"author": "Tom Butcher",
|
"author": "Tom Butcher",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
|
|||||||
15
readme.md
15
readme.md
@ -37,10 +37,19 @@ A Bun application that bridges communication between Farm Control cloud services
|
|||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
- Desktop app (current platform): `bun run build:app`
|
Build configuration lives in `electrobun.config.ts` and follows the [Electrobun build configuration](https://framework.blackboard.sh/electrobun/apis/cli/build-configuration/) model:
|
||||||
- Linux headless packages: `bun run build:linux`
|
|
||||||
|
|
||||||
Electrobun handles desktop packaging. Linux headless builds use `bun build --compile`.
|
- **preBuild** — validates sources, writes build metadata, and runs the Vite renderer build
|
||||||
|
- **postPackage** — normalizes release artifacts (DMG/PKG on macOS, MSI on Windows)
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
|
||||||
|
- Desktop app (current platform): `bun run build:app`
|
||||||
|
- macOS universal (arm64 + x64): `bun run build:app:mac`
|
||||||
|
- Linux headless packages: `bun run build:linux`
|
||||||
|
- Clean build outputs: `bun run clean`
|
||||||
|
|
||||||
|
Desktop artifacts are written to `app_dist/`. Linux headless builds produce `.deb` and `.rpm` packages in the same folder.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
|||||||
35
scripts/build-linux.mjs
Normal file
35
scripts/build-linux.mjs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { spawnSync } from "node:child_process";
|
||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
|
|
||||||
|
function run(scriptRelativePath) {
|
||||||
|
const scriptPath = path.join(rootDir, scriptRelativePath);
|
||||||
|
const result = spawnSync("bun", [scriptPath], {
|
||||||
|
cwd: rootDir,
|
||||||
|
stdio: "inherit",
|
||||||
|
env: process.env,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.status !== 0) {
|
||||||
|
process.exit(result.status ?? 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function runBash(scriptRelativePath) {
|
||||||
|
const scriptPath = path.join(rootDir, scriptRelativePath);
|
||||||
|
const result = spawnSync("bash", [scriptPath], {
|
||||||
|
cwd: rootDir,
|
||||||
|
stdio: "inherit",
|
||||||
|
env: process.env,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.status !== 0) {
|
||||||
|
process.exit(result.status ?? 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run("scripts/write-build-info.mjs");
|
||||||
|
run("scripts/build-linux-binary.mjs");
|
||||||
|
runBash("scripts/build-linux-packages.sh");
|
||||||
@ -41,8 +41,6 @@ function getElectrobunInvocation(targetArch) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
run("bun", ["run", "build"]);
|
|
||||||
|
|
||||||
for (const targetArch of targetArchs) {
|
for (const targetArch of targetArchs) {
|
||||||
const invocation = getElectrobunInvocation(targetArch);
|
const invocation = getElectrobunInvocation(targetArch);
|
||||||
if (!invocation) {
|
if (!invocation) {
|
||||||
|
|||||||
22
scripts/build-renderer.mjs
Normal file
22
scripts/build-renderer.mjs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { spawnSync } from "node:child_process";
|
||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
|
|
||||||
|
const result = spawnSync("bun", ["x", "vite", "build", "src/app"], {
|
||||||
|
cwd: rootDir,
|
||||||
|
stdio: "inherit",
|
||||||
|
env: {
|
||||||
|
...process.env,
|
||||||
|
NODE_ENV: process.env.NODE_ENV || "production",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.status !== 0) {
|
||||||
|
process.exit(result.status ?? 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`build-renderer: output at ${path.join(rootDir, "dist/mainview")}`,
|
||||||
|
);
|
||||||
@ -1,15 +0,0 @@
|
|||||||
import { cpSync, mkdirSync, rmSync } from "node:fs";
|
|
||||||
import path from "node:path";
|
|
||||||
import { fileURLToPath } from "node:url";
|
|
||||||
|
|
||||||
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
||||||
const buildDir = path.join(rootDir, "build");
|
|
||||||
|
|
||||||
rmSync(buildDir, { recursive: true, force: true });
|
|
||||||
mkdirSync(buildDir, { recursive: true });
|
|
||||||
|
|
||||||
cpSync(path.join(rootDir, "src"), buildDir, { recursive: true });
|
|
||||||
cpSync(path.join(rootDir, "package.json"), path.join(buildDir, "package.json"));
|
|
||||||
cpSync(path.join(rootDir, "config.json"), path.join(buildDir, "config.json"));
|
|
||||||
|
|
||||||
console.log(`Server sources copied to ${buildDir}`);
|
|
||||||
@ -4,6 +4,8 @@ import { fileURLToPath } from "node:url";
|
|||||||
|
|
||||||
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
|
|
||||||
for (const dir of ["build", "dist"]) {
|
for (const dir of ["build", "dist", "app_dist", "artifacts"]) {
|
||||||
rmSync(path.join(rootDir, dir), { recursive: true, force: true });
|
rmSync(path.join(rootDir, dir), { recursive: true, force: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("clean: removed build, dist, app_dist, and artifacts");
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { existsSync } from "node:fs";
|
import { existsSync } from "node:fs";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
|
import { spawnSync } from "node:child_process";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
@ -7,8 +8,11 @@ const buildEnv = process.env.ELECTROBUN_BUILD_ENV || "dev";
|
|||||||
|
|
||||||
const requiredFiles = [
|
const requiredFiles = [
|
||||||
"src/bun/index.js",
|
"src/bun/index.js",
|
||||||
|
"src/app/index.html",
|
||||||
|
"src/app/main.jsx",
|
||||||
"electrobun.config.ts",
|
"electrobun.config.ts",
|
||||||
"package.json",
|
"package.json",
|
||||||
|
"config.json",
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const relativePath of requiredFiles) {
|
for (const relativePath of requiredFiles) {
|
||||||
@ -35,4 +39,45 @@ if (buildEnv === "stable" && process.env.ELECTROBUN_OS === "macos") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`pre-build: validation passed (${buildEnv})`);
|
const writeBuildInfo = spawnSync(
|
||||||
|
"bun",
|
||||||
|
[path.join(rootDir, "scripts/write-build-info.mjs")],
|
||||||
|
{ cwd: rootDir, stdio: "inherit", env: process.env },
|
||||||
|
);
|
||||||
|
|
||||||
|
if (writeBuildInfo.status !== 0) {
|
||||||
|
process.exit(writeBuildInfo.status ?? 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buildEnv === "dev") {
|
||||||
|
console.log(
|
||||||
|
"pre-build: dev environment — skipping production renderer build (use dev:renderer for Vite)",
|
||||||
|
);
|
||||||
|
console.log(`pre-build: validation passed (${buildEnv})`);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const buildRenderer = spawnSync(
|
||||||
|
"bun",
|
||||||
|
[path.join(rootDir, "scripts/build-renderer.mjs")],
|
||||||
|
{
|
||||||
|
cwd: rootDir,
|
||||||
|
stdio: "inherit",
|
||||||
|
env: {
|
||||||
|
...process.env,
|
||||||
|
NODE_ENV: "production",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (buildRenderer.status !== 0) {
|
||||||
|
process.exit(buildRenderer.status ?? 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rendererIndex = path.join(rootDir, "dist/mainview/index.html");
|
||||||
|
if (!existsSync(rendererIndex)) {
|
||||||
|
console.error(`pre-build: renderer output not found: dist/mainview/index.html`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`pre-build: validation and renderer build passed (${buildEnv})`);
|
||||||
|
|||||||
15
scripts/write-build-info.mjs
Normal file
15
scripts/write-build-info.mjs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
|
const buildNumber =
|
||||||
|
process.env.BUILD_NUMBER || process.env.VITE_BUILD_NUMBER || "dev";
|
||||||
|
|
||||||
|
const buildInfoPath = path.join(rootDir, "src/buildInfo.json");
|
||||||
|
|
||||||
|
await Bun.write(
|
||||||
|
buildInfoPath,
|
||||||
|
`${JSON.stringify({ buildNumber }, null, 2)}\n`,
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(`write-build-info: ${buildInfoPath} (buildNumber=${buildNumber})`);
|
||||||
@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<link rel="stylesheet" href="./fonts.css" />
|
<link rel="stylesheet" href="/fonts.css" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Farm Control Server</title>
|
<title>Farm Control Server</title>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@ -13,7 +13,7 @@ export default defineConfig({
|
|||||||
plugins: [react(), svgr(), svgo()],
|
plugins: [react(), svgr(), svgo()],
|
||||||
root: path.resolve(__dirname),
|
root: path.resolve(__dirname),
|
||||||
build: {
|
build: {
|
||||||
outDir: path.resolve(__dirname, "../../dist/app"),
|
outDir: path.resolve(__dirname, "../../dist/mainview"),
|
||||||
emptyOutDir: true,
|
emptyOutDir: true,
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
input: {
|
input: {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user