Enhance Electrobun configuration and build scripts
Some checks reported errors
farmcontrol/farmcontrol-server/pipeline/head Something is wrong with the build of this commit
Some checks reported errors
farmcontrol/farmcontrol-server/pipeline/head Something is wrong with the build of this commit
- Updated electrobun.config.ts to dynamically set the application version from package.json and added a release configuration for base URL. - Modified Jenkinsfile to include the ELECTROBUN_RELEASE_BASE_URL environment variable during the build process. - Refactored build-macos.mjs to streamline the build command execution for different architectures. - Enhanced finalize-desktop-artifacts.mjs to improve artifact handling and introduced a new pre-build script for validation of required files and environment variables. - Improved error handling and logging for better build process visibility.
This commit is contained in:
parent
8b8475d11d
commit
d867d017bb
7
Jenkinsfile
vendored
7
Jenkinsfile
vendored
@ -70,6 +70,9 @@ def buildLinux() {
|
||||
}
|
||||
}
|
||||
|
||||
def releaseBaseUrl =
|
||||
"https://dist.farmcontrol.app/jenkins/farmcontrol/farmcontrol-server"
|
||||
|
||||
def buildOnLabel(label, buildCommand) {
|
||||
return {
|
||||
node(label) {
|
||||
@ -96,9 +99,9 @@ def buildOnLabel(label, buildCommand) {
|
||||
|
||||
stage("Build (${label})") {
|
||||
if (isUnix()) {
|
||||
sh "VITE_BUILD_NUMBER=${env.BUILD_NUMBER} NODE_ENV=production ${buildCommand}"
|
||||
sh "VITE_BUILD_NUMBER=${env.BUILD_NUMBER} NODE_ENV=production ELECTROBUN_RELEASE_BASE_URL=${releaseBaseUrl} ${buildCommand}"
|
||||
} else {
|
||||
bat "set VITE_BUILD_NUMBER=${env.BUILD_NUMBER} && set NODE_ENV=production && ${buildCommand}"
|
||||
bat "set VITE_BUILD_NUMBER=${env.BUILD_NUMBER} && set NODE_ENV=production && set ELECTROBUN_RELEASE_BASE_URL=${releaseBaseUrl} && ${buildCommand}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,18 @@
|
||||
// Electrobun requires this filename; application code remains JavaScript.
|
||||
import type { ElectrobunConfig } from "electrobun";
|
||||
import { readFileSync } from "node:fs";
|
||||
|
||||
const packageJson = JSON.parse(readFileSync("./package.json", "utf8"));
|
||||
|
||||
export default {
|
||||
app: {
|
||||
name: "Farm Control Server",
|
||||
identifier: "com.tombutcher.farmcontrolserver",
|
||||
version: "1.0.0",
|
||||
version: packageJson.version,
|
||||
description: "Farm Control Server desktop host application",
|
||||
},
|
||||
runtime: {
|
||||
exitOnLastWindowClosed: false,
|
||||
},
|
||||
build: {
|
||||
buildFolder: "build",
|
||||
artifactFolder: "app_dist",
|
||||
@ -17,7 +24,8 @@ export default {
|
||||
"dist/app/assets": "views/mainview/assets",
|
||||
"config.json": "config.json",
|
||||
},
|
||||
watchIgnore: ["dist/**"],
|
||||
watch: ["scripts"],
|
||||
watchIgnore: ["dist/**", "app_dist/**"],
|
||||
mac: {
|
||||
bundleCEF: false,
|
||||
},
|
||||
@ -28,10 +36,14 @@ export default {
|
||||
bundleCEF: false,
|
||||
},
|
||||
},
|
||||
runtime: {
|
||||
exitOnLastWindowClosed: false,
|
||||
},
|
||||
scripts: {
|
||||
preBuild: "scripts/pre-build.mjs",
|
||||
postPackage: "scripts/finalize-desktop-artifacts.mjs",
|
||||
},
|
||||
};
|
||||
release: {
|
||||
baseUrl:
|
||||
process.env.ELECTROBUN_RELEASE_BASE_URL ||
|
||||
process.env.RELEASE_BASE_URL ||
|
||||
"",
|
||||
},
|
||||
} satisfies ElectrobunConfig;
|
||||
|
||||
@ -3,7 +3,6 @@ import { fileURLToPath } from "node:url";
|
||||
import path from "node:path";
|
||||
|
||||
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const hostArch = process.arch === "arm64" ? "arm64" : "x64";
|
||||
const targetArchs = ["arm64", "x64"];
|
||||
|
||||
function run(command, args, options = {}) {
|
||||
@ -19,35 +18,15 @@ function run(command, args, options = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
function getElectrobunCommand(targetArch) {
|
||||
const electrobunArgs = ["electrobun", "build", "--env=stable"];
|
||||
|
||||
if (targetArch === hostArch) {
|
||||
return { command: "bun", args: electrobunArgs };
|
||||
}
|
||||
|
||||
if (hostArch === "arm64" && targetArch === "x64") {
|
||||
return { command: "arch", args: ["-x86_64", "bun", ...electrobunArgs] };
|
||||
}
|
||||
|
||||
if (hostArch === "x64" && targetArch === "arm64") {
|
||||
return { command: "arch", args: ["-arm64", "bun", ...electrobunArgs] };
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
run("bun", ["run", "build"]);
|
||||
|
||||
for (const targetArch of targetArchs) {
|
||||
const invocation = getElectrobunCommand(targetArch);
|
||||
if (!invocation) {
|
||||
console.warn(
|
||||
`Skipping macOS ${targetArch} build: unsupported cross-compile from ${hostArch}.`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
console.log(`\n=== Building macOS ${targetArch} ===\n`);
|
||||
run(invocation.command, invocation.args);
|
||||
|
||||
run("bun", ["electrobun", "build", "--env=stable"], {
|
||||
env: {
|
||||
...process.env,
|
||||
ELECTROBUN_ARCH: targetArch,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@ -20,11 +20,41 @@ const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..")
|
||||
const packageJson = JSON.parse(
|
||||
readFileSync(path.join(rootDir, "package.json"), "utf8"),
|
||||
);
|
||||
const version = getReleaseVersion(packageJson);
|
||||
const artifactDir = path.join(rootDir, "app_dist");
|
||||
const identifier = "com.tombutcher.farmcontrolserver";
|
||||
const buildEnv = process.env.ELECTROBUN_BUILD_ENV || "stable";
|
||||
const targetOs =
|
||||
process.env.ELECTROBUN_OS ||
|
||||
(process.platform === "darwin"
|
||||
? "macos"
|
||||
: process.platform === "win32"
|
||||
? "win"
|
||||
: process.platform === "linux"
|
||||
? "linux"
|
||||
: null);
|
||||
const buildArch = getReleaseArch(
|
||||
process.env.ELECTROBUN_ARCH || process.arch,
|
||||
);
|
||||
const version =
|
||||
process.env.ELECTROBUN_APP_VERSION || getReleaseVersion(packageJson);
|
||||
const artifactDir =
|
||||
process.env.ELECTROBUN_ARTIFACT_DIR || path.join(rootDir, "app_dist");
|
||||
const identifier =
|
||||
process.env.ELECTROBUN_APP_IDENTIFIER || "com.tombutcher.farmcontrolserver";
|
||||
const artifactPrefix = `farmcontrol-server-${version}-`;
|
||||
|
||||
function getBuildRoot() {
|
||||
const electrobunBuildDir = process.env.ELECTROBUN_BUILD_DIR;
|
||||
if (!electrobunBuildDir) {
|
||||
return path.join(rootDir, "build");
|
||||
}
|
||||
|
||||
const baseName = path.basename(electrobunBuildDir);
|
||||
if (baseName.startsWith("stable-")) {
|
||||
return path.dirname(electrobunBuildDir);
|
||||
}
|
||||
|
||||
return electrobunBuildDir;
|
||||
}
|
||||
|
||||
function walkFiles(dir) {
|
||||
const files = [];
|
||||
if (!existsSync(dir)) {
|
||||
@ -51,7 +81,7 @@ function findByExtension(root, extension) {
|
||||
}
|
||||
|
||||
function findMacAppBundle(arch) {
|
||||
const platformDir = path.join(rootDir, "build", `stable-macos-${arch}`);
|
||||
const platformDir = path.join(getBuildRoot(), `stable-macos-${arch}`);
|
||||
if (!existsSync(platformDir)) {
|
||||
return null;
|
||||
}
|
||||
@ -76,7 +106,7 @@ function findMacDmgSource(arch) {
|
||||
}
|
||||
|
||||
const buildDmg = findByExtension(
|
||||
path.join(rootDir, "build", `stable-macos-${arch}`),
|
||||
path.join(getBuildRoot(), `stable-macos-${arch}`),
|
||||
".dmg",
|
||||
);
|
||||
if (buildDmg) {
|
||||
@ -87,30 +117,26 @@ function findMacDmgSource(arch) {
|
||||
}
|
||||
|
||||
function findWindowsInstallerFiles() {
|
||||
const buildDir = path.join(rootDir, "build");
|
||||
if (!existsSync(buildDir)) {
|
||||
const buildRoot = getBuildRoot();
|
||||
if (!existsSync(buildRoot)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (const entry of readdirSync(buildDir)) {
|
||||
for (const entry of readdirSync(buildRoot)) {
|
||||
if (!entry.startsWith("stable-win-")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const platformDir = path.join(buildDir, entry);
|
||||
const platformDir = path.join(buildRoot, entry);
|
||||
const files = walkFiles(platformDir);
|
||||
const setupExe = files.find((filePath) =>
|
||||
/-setup\.exe$/i.test(filePath),
|
||||
);
|
||||
const setupExe = files.find((filePath) => /-setup\.exe$/i.test(filePath));
|
||||
const setupArchive = files.find((filePath) =>
|
||||
/-setup\.tar\.zst$/i.test(filePath),
|
||||
);
|
||||
const setupMetadata = files.find((filePath) =>
|
||||
/-setup\.metadata\.json$/i.test(filePath),
|
||||
);
|
||||
const setupZip = files.find((filePath) =>
|
||||
/-setup\.zip$/i.test(filePath),
|
||||
);
|
||||
const setupZip = files.find((filePath) => /-setup\.zip$/i.test(filePath));
|
||||
|
||||
if (setupExe && setupArchive && setupMetadata) {
|
||||
return { setupExe, setupArchive, setupMetadata, setupZip };
|
||||
@ -235,10 +261,12 @@ function buildWindowsMsi(installerFiles, arch) {
|
||||
return msiPath;
|
||||
}
|
||||
|
||||
if (process.platform === "darwin") {
|
||||
const buildArch = getReleaseArch(
|
||||
process.env.ELECTROBUN_ARCH || process.arch,
|
||||
);
|
||||
if (buildEnv === "dev") {
|
||||
console.log("finalize-desktop-artifacts: skipping dev build");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (targetOs === "macos") {
|
||||
const dmgSource = findMacDmgSource(buildArch);
|
||||
const appBundle = findMacAppBundle(buildArch);
|
||||
|
||||
@ -255,8 +283,8 @@ if (process.platform === "darwin") {
|
||||
];
|
||||
|
||||
cleanStagingArtifacts(published.map((filePath) => path.basename(filePath)));
|
||||
} else if (process.platform === "win32") {
|
||||
const arch = "x64";
|
||||
} else if (targetOs === "win") {
|
||||
const arch = getReleaseArch(process.env.ELECTROBUN_ARCH || "x64");
|
||||
const installerFiles = findWindowsInstallerFiles();
|
||||
|
||||
if (!installerFiles) {
|
||||
@ -273,6 +301,9 @@ if (process.platform === "darwin") {
|
||||
|
||||
cleanStagingArtifacts(published.map((filePath) => path.basename(filePath)));
|
||||
} else {
|
||||
console.log("finalize-desktop-artifacts: skipping unsupported platform", process.platform);
|
||||
console.log(
|
||||
"finalize-desktop-artifacts: no desktop packaging configured for",
|
||||
targetOs ?? "unknown target",
|
||||
);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
38
scripts/pre-build.mjs
Normal file
38
scripts/pre-build.mjs
Normal file
@ -0,0 +1,38 @@
|
||||
import { existsSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const buildEnv = process.env.ELECTROBUN_BUILD_ENV || "dev";
|
||||
|
||||
const requiredFiles = [
|
||||
"src/bun/index.js",
|
||||
"electrobun.config.ts",
|
||||
"package.json",
|
||||
];
|
||||
|
||||
for (const relativePath of requiredFiles) {
|
||||
const filePath = path.join(rootDir, relativePath);
|
||||
if (!existsSync(filePath)) {
|
||||
console.error(`pre-build: required file not found: ${relativePath}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (buildEnv === "stable" && process.env.ELECTROBUN_OS === "macos") {
|
||||
const codesignVars = [
|
||||
"ELECTROBUN_DEVELOPER_ID",
|
||||
"ELECTROBUN_APPLEID",
|
||||
"ELECTROBUN_APPLEIDPASS",
|
||||
"ELECTROBUN_TEAMID",
|
||||
];
|
||||
const missing = codesignVars.filter((name) => !process.env[name]);
|
||||
|
||||
if (missing.length > 0) {
|
||||
console.warn(
|
||||
`pre-build: stable macOS build without code signing credentials (${missing.join(", ")}); Electrobun will skip signing.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`pre-build: validation passed (${buildEnv})`);
|
||||
Loading…
x
Reference in New Issue
Block a user