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) {
|
def buildOnLabel(label, buildCommand) {
|
||||||
return {
|
return {
|
||||||
node(label) {
|
node(label) {
|
||||||
@ -96,9 +99,9 @@ def buildOnLabel(label, buildCommand) {
|
|||||||
|
|
||||||
stage("Build (${label})") {
|
stage("Build (${label})") {
|
||||||
if (isUnix()) {
|
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 {
|
} 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 {
|
export default {
|
||||||
app: {
|
app: {
|
||||||
name: "Farm Control Server",
|
name: "Farm Control Server",
|
||||||
identifier: "com.tombutcher.farmcontrolserver",
|
identifier: "com.tombutcher.farmcontrolserver",
|
||||||
version: "1.0.0",
|
version: packageJson.version,
|
||||||
description: "Farm Control Server desktop host application",
|
description: "Farm Control Server desktop host application",
|
||||||
},
|
},
|
||||||
|
runtime: {
|
||||||
|
exitOnLastWindowClosed: false,
|
||||||
|
},
|
||||||
build: {
|
build: {
|
||||||
buildFolder: "build",
|
buildFolder: "build",
|
||||||
artifactFolder: "app_dist",
|
artifactFolder: "app_dist",
|
||||||
@ -17,7 +24,8 @@ export default {
|
|||||||
"dist/app/assets": "views/mainview/assets",
|
"dist/app/assets": "views/mainview/assets",
|
||||||
"config.json": "config.json",
|
"config.json": "config.json",
|
||||||
},
|
},
|
||||||
watchIgnore: ["dist/**"],
|
watch: ["scripts"],
|
||||||
|
watchIgnore: ["dist/**", "app_dist/**"],
|
||||||
mac: {
|
mac: {
|
||||||
bundleCEF: false,
|
bundleCEF: false,
|
||||||
},
|
},
|
||||||
@ -28,10 +36,14 @@ export default {
|
|||||||
bundleCEF: false,
|
bundleCEF: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
runtime: {
|
|
||||||
exitOnLastWindowClosed: false,
|
|
||||||
},
|
|
||||||
scripts: {
|
scripts: {
|
||||||
|
preBuild: "scripts/pre-build.mjs",
|
||||||
postPackage: "scripts/finalize-desktop-artifacts.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";
|
import path from "node:path";
|
||||||
|
|
||||||
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
const hostArch = process.arch === "arm64" ? "arm64" : "x64";
|
|
||||||
const targetArchs = ["arm64", "x64"];
|
const targetArchs = ["arm64", "x64"];
|
||||||
|
|
||||||
function run(command, args, options = {}) {
|
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"]);
|
run("bun", ["run", "build"]);
|
||||||
|
|
||||||
for (const targetArch of targetArchs) {
|
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`);
|
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(
|
const packageJson = JSON.parse(
|
||||||
readFileSync(path.join(rootDir, "package.json"), "utf8"),
|
readFileSync(path.join(rootDir, "package.json"), "utf8"),
|
||||||
);
|
);
|
||||||
const version = getReleaseVersion(packageJson);
|
const buildEnv = process.env.ELECTROBUN_BUILD_ENV || "stable";
|
||||||
const artifactDir = path.join(rootDir, "app_dist");
|
const targetOs =
|
||||||
const identifier = "com.tombutcher.farmcontrolserver";
|
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}-`;
|
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) {
|
function walkFiles(dir) {
|
||||||
const files = [];
|
const files = [];
|
||||||
if (!existsSync(dir)) {
|
if (!existsSync(dir)) {
|
||||||
@ -51,7 +81,7 @@ function findByExtension(root, extension) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function findMacAppBundle(arch) {
|
function findMacAppBundle(arch) {
|
||||||
const platformDir = path.join(rootDir, "build", `stable-macos-${arch}`);
|
const platformDir = path.join(getBuildRoot(), `stable-macos-${arch}`);
|
||||||
if (!existsSync(platformDir)) {
|
if (!existsSync(platformDir)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -76,7 +106,7 @@ function findMacDmgSource(arch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const buildDmg = findByExtension(
|
const buildDmg = findByExtension(
|
||||||
path.join(rootDir, "build", `stable-macos-${arch}`),
|
path.join(getBuildRoot(), `stable-macos-${arch}`),
|
||||||
".dmg",
|
".dmg",
|
||||||
);
|
);
|
||||||
if (buildDmg) {
|
if (buildDmg) {
|
||||||
@ -87,30 +117,26 @@ function findMacDmgSource(arch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function findWindowsInstallerFiles() {
|
function findWindowsInstallerFiles() {
|
||||||
const buildDir = path.join(rootDir, "build");
|
const buildRoot = getBuildRoot();
|
||||||
if (!existsSync(buildDir)) {
|
if (!existsSync(buildRoot)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const entry of readdirSync(buildDir)) {
|
for (const entry of readdirSync(buildRoot)) {
|
||||||
if (!entry.startsWith("stable-win-")) {
|
if (!entry.startsWith("stable-win-")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const platformDir = path.join(buildDir, entry);
|
const platformDir = path.join(buildRoot, entry);
|
||||||
const files = walkFiles(platformDir);
|
const files = walkFiles(platformDir);
|
||||||
const setupExe = files.find((filePath) =>
|
const setupExe = files.find((filePath) => /-setup\.exe$/i.test(filePath));
|
||||||
/-setup\.exe$/i.test(filePath),
|
|
||||||
);
|
|
||||||
const setupArchive = files.find((filePath) =>
|
const setupArchive = files.find((filePath) =>
|
||||||
/-setup\.tar\.zst$/i.test(filePath),
|
/-setup\.tar\.zst$/i.test(filePath),
|
||||||
);
|
);
|
||||||
const setupMetadata = files.find((filePath) =>
|
const setupMetadata = files.find((filePath) =>
|
||||||
/-setup\.metadata\.json$/i.test(filePath),
|
/-setup\.metadata\.json$/i.test(filePath),
|
||||||
);
|
);
|
||||||
const setupZip = files.find((filePath) =>
|
const setupZip = files.find((filePath) => /-setup\.zip$/i.test(filePath));
|
||||||
/-setup\.zip$/i.test(filePath),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (setupExe && setupArchive && setupMetadata) {
|
if (setupExe && setupArchive && setupMetadata) {
|
||||||
return { setupExe, setupArchive, setupMetadata, setupZip };
|
return { setupExe, setupArchive, setupMetadata, setupZip };
|
||||||
@ -235,10 +261,12 @@ function buildWindowsMsi(installerFiles, arch) {
|
|||||||
return msiPath;
|
return msiPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.platform === "darwin") {
|
if (buildEnv === "dev") {
|
||||||
const buildArch = getReleaseArch(
|
console.log("finalize-desktop-artifacts: skipping dev build");
|
||||||
process.env.ELECTROBUN_ARCH || process.arch,
|
process.exit(0);
|
||||||
);
|
}
|
||||||
|
|
||||||
|
if (targetOs === "macos") {
|
||||||
const dmgSource = findMacDmgSource(buildArch);
|
const dmgSource = findMacDmgSource(buildArch);
|
||||||
const appBundle = findMacAppBundle(buildArch);
|
const appBundle = findMacAppBundle(buildArch);
|
||||||
|
|
||||||
@ -255,8 +283,8 @@ if (process.platform === "darwin") {
|
|||||||
];
|
];
|
||||||
|
|
||||||
cleanStagingArtifacts(published.map((filePath) => path.basename(filePath)));
|
cleanStagingArtifacts(published.map((filePath) => path.basename(filePath)));
|
||||||
} else if (process.platform === "win32") {
|
} else if (targetOs === "win") {
|
||||||
const arch = "x64";
|
const arch = getReleaseArch(process.env.ELECTROBUN_ARCH || "x64");
|
||||||
const installerFiles = findWindowsInstallerFiles();
|
const installerFiles = findWindowsInstallerFiles();
|
||||||
|
|
||||||
if (!installerFiles) {
|
if (!installerFiles) {
|
||||||
@ -273,6 +301,9 @@ if (process.platform === "darwin") {
|
|||||||
|
|
||||||
cleanStagingArtifacts(published.map((filePath) => path.basename(filePath)));
|
cleanStagingArtifacts(published.map((filePath) => path.basename(filePath)));
|
||||||
} else {
|
} 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);
|
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