Refactor macOS build process and update configuration
Some checks failed
farmcontrol/farmcontrol-server/pipeline/head There was a failure building this commit

- Updated electrobun.config.ts to disable DMG creation during the build process, streamlining artifact management.
- Enhanced Jenkinsfile with a new function to prepare the macOS build workspace, ensuring proper cleanup of previous volumes and staging directories.
- Introduced new functions in finalize-desktop-artifacts.mjs for building and cleaning macOS DMG files, improving the overall build workflow and artifact handling.
This commit is contained in:
Tom Butcher 2026-08-01 21:57:03 +01:00
parent 5f97ac2cff
commit 1669c7a72c
3 changed files with 106 additions and 29 deletions

24
Jenkinsfile vendored
View File

@ -86,9 +86,24 @@ def buildLinux() {
}
}
def prepareMacBuildWorkspace() {
if (isUnix()) {
sh '''
df -h .
for vol in /Volumes/Farm\\ Control\\ Server*; do
if [ -d "$vol" ]; then
hdiutil detach "$vol" -force || true
fi
done
rm -rf build/stable-macos-*/.dmg-staging build/stable-macos-*/.finalize-dmg-staging 2>/dev/null || true
'''
}
}
def buildOnLabel(label, buildCommand) {
return {
node(label) {
try {
stage("Checkout (${label})") {
checkout scm
}
@ -98,6 +113,12 @@ def buildOnLabel(label, buildCommand) {
checkBun()
}
if (label.startsWith('macos')) {
stage("Prepare macOS workspace (${label})") {
prepareMacBuildWorkspace()
}
}
stage("Install Dependencies (${label})") {
if (isUnix()) {
sh 'bun install --frozen-lockfile'
@ -118,6 +139,9 @@ def buildOnLabel(label, buildCommand) {
stage("Archive Artifacts (${label})") {
archiveArtifacts artifacts: 'app_dist/farmcontrol-server-*', fingerprint: true
}
} finally {
cleanWs()
}
}
}
}

View File

@ -56,6 +56,8 @@ export default {
watchIgnore: ["dist/**", "build/**", "app_dist/**"],
mac: {
bundleCEF: false,
// DMG is built in finalize-desktop-artifacts (symlink staging saves disk).
createDmg: false,
codesign: isStable && canCodesign,
notarize: isStable && canCodesign,
},

View File

@ -6,6 +6,7 @@ import {
readFileSync,
rmSync,
statSync,
symlinkSync,
} from "node:fs";
import path from "node:path";
import { spawnSync } from "node:child_process";
@ -184,6 +185,54 @@ function cleanStagingArtifacts(keepNames) {
}
}
function buildMacDmg(appBundlePath, arch) {
const dmgPath = path.join(
artifactDir,
getReleaseArtifactName(version, arch, "dmg"),
);
const stagingDir = path.join(path.dirname(appBundlePath), ".finalize-dmg-staging");
rmSync(stagingDir, { recursive: true, force: true });
mkdirSync(stagingDir, { recursive: true });
const appName = path.basename(appBundlePath);
symlinkSync(appBundlePath, path.join(stagingDir, appName), "dir");
symlinkSync("/Applications", path.join(stagingDir, "Applications"));
const result = spawnSync(
"hdiutil",
[
"create",
"-volname",
"Farm Control Server",
"-srcfolder",
stagingDir,
"-ov",
"-format",
"UDZO",
dmgPath,
],
{ stdio: "inherit" },
);
rmSync(stagingDir, { recursive: true, force: true });
if (result.status !== 0) {
throw new Error(`hdiutil create failed with exit code ${result.status ?? 1}`);
}
console.log(`Published ${dmgPath}`);
return dmgPath;
}
function cleanMacBuildDir(arch) {
const platformDir = path.join(getBuildRoot(), `stable-macos-${arch}`);
if (existsSync(platformDir)) {
rmSync(platformDir, { recursive: true, force: true });
console.log(`Removed build output ${platformDir}`);
}
}
function buildMacPkg(appBundlePath, arch) {
const pkgPath = path.join(
artifactDir,
@ -269,22 +318,24 @@ if (buildEnv === "dev") {
}
if (targetOs === "macos") {
const dmgSource = findMacDmgSource(buildArch);
const appBundle = findMacAppBundle(buildArch);
if (!dmgSource || !appBundle) {
if (!appBundle) {
console.log(
`finalize-desktop-artifacts: no macOS ${buildArch} release artifacts found, skipping`,
`finalize-desktop-artifacts: no macOS ${buildArch} app bundle found, skipping`,
);
process.exit(0);
}
const published = [
publishArtifact(dmgSource, buildArch, "dmg"),
buildMacPkg(appBundle, buildArch),
];
const existingDmg = findMacDmgSource(buildArch);
const dmgPath = existingDmg
? publishArtifact(existingDmg, buildArch, "dmg")
: buildMacDmg(appBundle, buildArch);
const published = [dmgPath, buildMacPkg(appBundle, buildArch)];
cleanStagingArtifacts(published.map((filePath) => path.basename(filePath)));
cleanMacBuildDir(buildArch);
} else if (targetOs === "win") {
const arch = getReleaseArch(process.env.ELECTROBUN_ARCH || "x64");
const installerFiles = findWindowsInstallerFiles();