Refactor Windows installer scripts and enhance build process
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 farmcontrol-server.nsi to simplify setup file handling by defining APP_SOURCE_DIR and removing unnecessary variables. - Modified installer.nsh to reference the correct launcher executable path. - Refactored build-windows-nsis.ps1 to accept APP_DIR instead of individual setup file parameters, streamlining the build process. - Introduced expand-windows-installer.mjs for handling decompression and extraction of Windows app archives, improving artifact management. - Enhanced finalize-desktop-artifacts.mjs to integrate the new expansion process and ensure proper cleanup of temporary files.
This commit is contained in:
parent
ebc3920d65
commit
72cea3a740
@ -9,16 +9,8 @@
|
|||||||
!define VERSION "1.0.0"
|
!define VERSION "1.0.0"
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
!ifndef SETUP_EXE_NAME
|
!ifndef APP_SOURCE_DIR
|
||||||
!define SETUP_EXE_NAME "Farm Control Server-Setup.exe"
|
!define APP_SOURCE_DIR "."
|
||||||
!endif
|
|
||||||
|
|
||||||
!ifndef SETUP_ARCHIVE_NAME
|
|
||||||
!define SETUP_ARCHIVE_NAME "Farm Control Server-Setup.tar.zst"
|
|
||||||
!endif
|
|
||||||
|
|
||||||
!ifndef SETUP_METADATA_NAME
|
|
||||||
!define SETUP_METADATA_NAME "Farm Control Server-Setup.metadata.json"
|
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
Name "Farm Control Server"
|
Name "Farm Control Server"
|
||||||
@ -39,20 +31,8 @@ RequestExecutionLevel admin
|
|||||||
|
|
||||||
Section "Farm Control Server" SecMain
|
Section "Farm Control Server" SecMain
|
||||||
SetOutPath $INSTDIR
|
SetOutPath $INSTDIR
|
||||||
|
File /r "${APP_SOURCE_DIR}\*"
|
||||||
|
|
||||||
File "${SETUP_EXE_NAME}"
|
|
||||||
File "${SETUP_ARCHIVE_NAME}"
|
|
||||||
File "${SETUP_METADATA_NAME}"
|
|
||||||
|
|
||||||
DetailPrint "Running Farm Control Server setup..."
|
|
||||||
ExecWait '"$INSTDIR\${SETUP_EXE_NAME}" /S' $0
|
|
||||||
StrCmp $0 "0" setup_ok setup_failed
|
|
||||||
|
|
||||||
setup_failed:
|
|
||||||
MessageBox MB_ICONSTOP "Farm Control Server setup failed (exit code $0)."
|
|
||||||
Abort
|
|
||||||
|
|
||||||
setup_ok:
|
|
||||||
!insertmacro customInstall
|
!insertmacro customInstall
|
||||||
|
|
||||||
WriteRegStr HKLM "Software\Tom Butcher\Farm Control Server" "InstallDir" $INSTDIR
|
WriteRegStr HKLM "Software\Tom Butcher\Farm Control Server" "InstallDir" $INSTDIR
|
||||||
@ -75,12 +55,7 @@ SectionEnd
|
|||||||
Section "Uninstall"
|
Section "Uninstall"
|
||||||
!insertmacro customUnInstall
|
!insertmacro customUnInstall
|
||||||
|
|
||||||
Delete "$INSTDIR\${SETUP_EXE_NAME}"
|
|
||||||
Delete "$INSTDIR\${SETUP_ARCHIVE_NAME}"
|
|
||||||
Delete "$INSTDIR\${SETUP_METADATA_NAME}"
|
|
||||||
Delete "$INSTDIR\launcher.exe"
|
|
||||||
Delete "$INSTDIR\Uninstall.exe"
|
Delete "$INSTDIR\Uninstall.exe"
|
||||||
|
|
||||||
RMDir /r "$INSTDIR"
|
RMDir /r "$INSTDIR"
|
||||||
|
|
||||||
DeleteRegKey HKLM "Software\Tom Butcher\Farm Control Server"
|
DeleteRegKey HKLM "Software\Tom Butcher\Farm Control Server"
|
||||||
|
|||||||
@ -3,10 +3,10 @@
|
|||||||
DeleteRegKey HKCR "farmcontrolserver"
|
DeleteRegKey HKCR "farmcontrolserver"
|
||||||
WriteRegStr HKCR "farmcontrolserver" "" "URL:farmcontrolserver"
|
WriteRegStr HKCR "farmcontrolserver" "" "URL:farmcontrolserver"
|
||||||
WriteRegStr HKCR "farmcontrolserver" "URL Protocol" ""
|
WriteRegStr HKCR "farmcontrolserver" "URL Protocol" ""
|
||||||
WriteRegStr HKCR "farmcontrolserver\DefaultIcon" "" "$INSTDIR\launcher.exe"
|
WriteRegStr HKCR "farmcontrolserver\DefaultIcon" "" "$INSTDIR\bin\launcher.exe"
|
||||||
WriteRegStr HKCR "farmcontrolserver\shell" "" ""
|
WriteRegStr HKCR "farmcontrolserver\shell" "" ""
|
||||||
WriteRegStr HKCR "farmcontrolserver\shell\Open" "" ""
|
WriteRegStr HKCR "farmcontrolserver\shell\Open" "" ""
|
||||||
WriteRegStr HKCR "farmcontrolserver\shell\Open\command" "" '"$INSTDIR\launcher.exe" "%1"'
|
WriteRegStr HKCR "farmcontrolserver\shell\Open\command" "" '"$INSTDIR\bin\launcher.exe" "%1"'
|
||||||
!macroend
|
!macroend
|
||||||
|
|
||||||
!macro customUnInstall
|
!macro customUnInstall
|
||||||
|
|||||||
@ -1,12 +1,6 @@
|
|||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[string]$SetupExe,
|
[string]$AppDir,
|
||||||
|
|
||||||
[Parameter(Mandatory = $true)]
|
|
||||||
[string]$SetupArchive,
|
|
||||||
|
|
||||||
[Parameter(Mandatory = $true)]
|
|
||||||
[string]$SetupMetadata,
|
|
||||||
|
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[string]$OutputExe,
|
[string]$OutputExe,
|
||||||
@ -47,17 +41,8 @@ if (Test-Path $workDir) {
|
|||||||
}
|
}
|
||||||
New-Item -ItemType Directory -Path $workDir | Out-Null
|
New-Item -ItemType Directory -Path $workDir | Out-Null
|
||||||
|
|
||||||
$setupExePath = (Resolve-Path -LiteralPath $SetupExe).Path
|
$appDirPath = (Resolve-Path -LiteralPath $AppDir).Path
|
||||||
$setupArchivePath = (Resolve-Path -LiteralPath $SetupArchive).Path
|
|
||||||
$setupMetadataPath = (Resolve-Path -LiteralPath $SetupMetadata).Path
|
|
||||||
|
|
||||||
$setupExeName = Split-Path $setupExePath -Leaf
|
|
||||||
$setupArchiveName = Split-Path $setupArchivePath -Leaf
|
|
||||||
$setupMetadataName = Split-Path $setupMetadataPath -Leaf
|
|
||||||
|
|
||||||
Copy-Item -LiteralPath $setupExePath -Destination (Join-Path $workDir $setupExeName)
|
|
||||||
Copy-Item -LiteralPath $setupArchivePath -Destination (Join-Path $workDir $setupArchiveName)
|
|
||||||
Copy-Item -LiteralPath $setupMetadataPath -Destination (Join-Path $workDir $setupMetadataName)
|
|
||||||
Copy-Item -LiteralPath $nsiPath -Destination (Join-Path $workDir "farmcontrol-server.nsi")
|
Copy-Item -LiteralPath $nsiPath -Destination (Join-Path $workDir "farmcontrol-server.nsi")
|
||||||
Copy-Item -LiteralPath $installerInclude -Destination (Join-Path $workDir "installer.nsh")
|
Copy-Item -LiteralPath $installerInclude -Destination (Join-Path $workDir "installer.nsh")
|
||||||
|
|
||||||
@ -72,9 +57,7 @@ $makensisArgs = @(
|
|||||||
"/NOCD"
|
"/NOCD"
|
||||||
"/DOUTFILE=$outputExePath"
|
"/DOUTFILE=$outputExePath"
|
||||||
"/DVERSION=$Version"
|
"/DVERSION=$Version"
|
||||||
"/DSETUP_EXE_NAME=$setupExeName"
|
"/DAPP_SOURCE_DIR=$appDirPath"
|
||||||
"/DSETUP_ARCHIVE_NAME=$setupArchiveName"
|
|
||||||
"/DSETUP_METADATA_NAME=$setupMetadataName"
|
|
||||||
(Join-Path $workDir "farmcontrol-server.nsi")
|
(Join-Path $workDir "farmcontrol-server.nsi")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
123
scripts/expand-windows-installer.mjs
Normal file
123
scripts/expand-windows-installer.mjs
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
import {
|
||||||
|
existsSync,
|
||||||
|
mkdirSync,
|
||||||
|
readdirSync,
|
||||||
|
rmSync,
|
||||||
|
statSync,
|
||||||
|
} from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
import { spawnSync } from "node:child_process";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
|
|
||||||
|
function findZstdDecompressCommand() {
|
||||||
|
const systemZstd = spawnSync("zstd", ["--version"], { encoding: "utf8" });
|
||||||
|
if (systemZstd.status === 0) {
|
||||||
|
return { command: "zstd", args: (inputPath, outputPath) => [
|
||||||
|
"-d",
|
||||||
|
"-f",
|
||||||
|
"-o",
|
||||||
|
outputPath,
|
||||||
|
inputPath,
|
||||||
|
] };
|
||||||
|
}
|
||||||
|
|
||||||
|
const hostArch = process.arch === "arm64" ? "arm64" : "x64";
|
||||||
|
const candidates = [
|
||||||
|
path.join(
|
||||||
|
rootDir,
|
||||||
|
"node_modules/electrobun/dist-win-x64/zig-zstd",
|
||||||
|
hostArch,
|
||||||
|
"zig-zstd.exe",
|
||||||
|
),
|
||||||
|
path.join(
|
||||||
|
rootDir,
|
||||||
|
"node_modules/electrobun/dist-win-x64/zig-zstd",
|
||||||
|
"x64",
|
||||||
|
"zig-zstd.exe",
|
||||||
|
),
|
||||||
|
path.join(rootDir, "node_modules/electrobun/dist-win-x64", "zig-zstd"),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const candidate of candidates) {
|
||||||
|
if (existsSync(candidate)) {
|
||||||
|
return {
|
||||||
|
command: candidate,
|
||||||
|
args: (inputPath, outputPath) => [
|
||||||
|
"decompress",
|
||||||
|
"-i",
|
||||||
|
inputPath,
|
||||||
|
"-o",
|
||||||
|
outputPath,
|
||||||
|
"--no-timing",
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function decompressTarZst(inputPath, outputPath) {
|
||||||
|
const zstd = findZstdDecompressCommand();
|
||||||
|
if (!zstd) {
|
||||||
|
throw new Error(
|
||||||
|
"expand-windows-installer: zstd not found (install zstd or use electrobun dist binaries)",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = spawnSync(zstd.command, zstd.args(inputPath, outputPath), {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.status !== 0) {
|
||||||
|
throw new Error(
|
||||||
|
`expand-windows-installer: decompression failed (exit ${result.status ?? 1})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function expandWindowsAppFromArchive(setupArchivePath, parentDir) {
|
||||||
|
const resolvedArchive = path.resolve(setupArchivePath);
|
||||||
|
if (!existsSync(resolvedArchive)) {
|
||||||
|
throw new Error(`expand-windows-installer: archive not found: ${resolvedArchive}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const workDir = path.join(path.resolve(parentDir), ".expanded-app");
|
||||||
|
const tarPath = path.join(workDir, "app.tar");
|
||||||
|
|
||||||
|
rmSync(workDir, { recursive: true, force: true });
|
||||||
|
mkdirSync(workDir, { recursive: true });
|
||||||
|
|
||||||
|
decompressTarZst(resolvedArchive, tarPath);
|
||||||
|
|
||||||
|
const extractTar = spawnSync("tar", ["-xf", tarPath, "-C", workDir], {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (extractTar.status !== 0) {
|
||||||
|
rmSync(workDir, { recursive: true, force: true });
|
||||||
|
throw new Error(
|
||||||
|
`expand-windows-installer: tar extraction failed (exit ${extractTar.status ?? 1})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const appDir = readdirSync(workDir)
|
||||||
|
.filter((entry) => entry !== "app.tar" && entry !== "__MACOSX")
|
||||||
|
.map((entry) => path.join(workDir, entry))
|
||||||
|
.find((entryPath) => statSync(entryPath).isDirectory());
|
||||||
|
|
||||||
|
if (!appDir) {
|
||||||
|
rmSync(workDir, { recursive: true, force: true });
|
||||||
|
throw new Error("expand-windows-installer: app folder not found in archive");
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`expand-windows-installer: expanded ${appDir}`);
|
||||||
|
return appDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function cleanExpandedWindowsApp(parentDir) {
|
||||||
|
const workDir = path.join(path.resolve(parentDir), ".expanded-app");
|
||||||
|
rmSync(workDir, { recursive: true, force: true });
|
||||||
|
}
|
||||||
@ -16,6 +16,10 @@ import {
|
|||||||
getReleaseArtifactName,
|
getReleaseArtifactName,
|
||||||
getReleaseVersion,
|
getReleaseVersion,
|
||||||
} from "./release-artifact-utils.mjs";
|
} from "./release-artifact-utils.mjs";
|
||||||
|
import {
|
||||||
|
cleanExpandedWindowsApp,
|
||||||
|
expandWindowsAppFromArchive,
|
||||||
|
} from "./expand-windows-installer.mjs";
|
||||||
|
|
||||||
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
const packageJson = JSON.parse(
|
const packageJson = JSON.parse(
|
||||||
@ -299,7 +303,15 @@ function buildMacPkg(appBundlePath, arch) {
|
|||||||
return pkgPath;
|
return pkgPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildWindowsNsis(installerFiles, arch) {
|
function cleanWinBuildDir(arch) {
|
||||||
|
const platformDir = path.join(getBuildRoot(), `stable-win-${arch}`);
|
||||||
|
if (existsSync(platformDir)) {
|
||||||
|
rmSync(platformDir, { recursive: true, force: true });
|
||||||
|
console.log(`Removed build output ${platformDir}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildWindowsNsis(appDir, arch) {
|
||||||
const scriptPath = path.join(rootDir, "scripts/build-windows-nsis.ps1");
|
const scriptPath = path.join(rootDir, "scripts/build-windows-nsis.ps1");
|
||||||
const exePath = path.join(
|
const exePath = path.join(
|
||||||
artifactDir,
|
artifactDir,
|
||||||
@ -324,12 +336,8 @@ function buildWindowsNsis(installerFiles, arch) {
|
|||||||
"Bypass",
|
"Bypass",
|
||||||
"-File",
|
"-File",
|
||||||
scriptPath,
|
scriptPath,
|
||||||
"-SetupExe",
|
"-AppDir",
|
||||||
installerFiles.setupExe,
|
appDir,
|
||||||
"-SetupArchive",
|
|
||||||
installerFiles.setupArchive,
|
|
||||||
"-SetupMetadata",
|
|
||||||
installerFiles.setupMetadata,
|
|
||||||
"-OutputExe",
|
"-OutputExe",
|
||||||
exePath,
|
exePath,
|
||||||
"-Version",
|
"-Version",
|
||||||
@ -376,19 +384,31 @@ if (targetOs === "macos") {
|
|||||||
const arch = getReleaseArch(process.env.ELECTROBUN_ARCH || "x64");
|
const arch = getReleaseArch(process.env.ELECTROBUN_ARCH || "x64");
|
||||||
const installerFiles = findWindowsInstallerFiles();
|
const installerFiles = findWindowsInstallerFiles();
|
||||||
|
|
||||||
if (!installerFiles) {
|
if (!installerFiles?.setupArchive) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Could not find the Windows installer files (setup exe, archive, and metadata)",
|
"Could not find the Windows setup archive (.tar.zst) to expand",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const published = [buildWindowsNsis(installerFiles, arch)];
|
const platformDir = path.dirname(installerFiles.setupArchive);
|
||||||
|
const appDir = expandWindowsAppFromArchive(
|
||||||
|
installerFiles.setupArchive,
|
||||||
|
platformDir,
|
||||||
|
);
|
||||||
|
|
||||||
|
let published;
|
||||||
|
try {
|
||||||
|
published = [buildWindowsNsis(appDir, arch)];
|
||||||
|
|
||||||
if (installerFiles.setupZip) {
|
if (installerFiles.setupZip) {
|
||||||
published.push(publishArtifact(installerFiles.setupZip, arch, "zip"));
|
published.push(publishArtifact(installerFiles.setupZip, arch, "zip"));
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
cleanExpandedWindowsApp(platformDir);
|
||||||
|
}
|
||||||
|
|
||||||
cleanStagingArtifacts(published.map((filePath) => path.basename(filePath)));
|
cleanStagingArtifacts(published.map((filePath) => path.basename(filePath)));
|
||||||
|
cleanWinBuildDir(arch);
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
console.log(
|
||||||
"finalize-desktop-artifacts: no desktop packaging configured for",
|
"finalize-desktop-artifacts: no desktop packaging configured for",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user