Gepubliceerde bron
Download bron ZIP
CH-J Server Manager
Blader door mappen en bestanden voor een specifieke toepassing release.
CH-J / Server Manager
339 bestanden
core-20261014T184258Z-3fbed0b93fdf
Toegevoegd: Datum niet geregistreerd · Gebouwd:
1
"use strict";3
const fs = require("node:fs");4
const os = require("node:os");5
const path = require("node:path");6
const { execFileSync, spawn, spawnSync } = require("node:child_process");7
const { signAsync } = require("@electron/osx-sign");8
const { prepareMacNetworkIdentity, verifyMacNetworkIdentity } = require("./macNetworkIdentity");10
const projectRoot = path.resolve(__dirname, "..");11
const packageJson = require(path.join(projectRoot, "package.json"));12
const productName = packageJson.build?.productName || packageJson.productName;13
const distRoot = path.resolve(projectRoot, process.env.CHJ_DIST_DIR || "dist");14
const appPath = path.join(distRoot, "mac-arm64", `${productName}.app`);15
const outputPath = path.join(distRoot, `${productName}-${packageJson.version}-arm64.dmg`);16
const networkIdentity = { appId: packageJson.build.appId, version: packageJson.version };18
function run(command, args, options = {}) {19
return execFileSync(command, args, { encoding: "utf8", stdio: options.capture ? "pipe" : "inherit" });20
}22
function signatureIsValid(bundlePath) {23
try {24
run("codesign", ["--verify", "--deep", "--strict", "--verbose=2", bundlePath], { capture: true });25
return true;26
} catch (_) {27
return false;28
}29
}31
function signatureDescription(bundlePath) {32
const result = spawnSync("codesign", ["-dv", "--verbose=4", bundlePath], { encoding: "utf8" });33
return `${result.stdout || ""}\n${result.stderr || ""}`;34
}36
async function ensureValidSignature() {37
const identities = run("security", ["find-identity", "-v", "-p", "codesigning"], { capture: true });38
const developerId = identities.match(/\b([A-Fa-f0-9]{40})\s+"Developer ID Application:[^"]+"/);39
const hasDeveloperId = Boolean(developerId);40
if (signatureIsValid(appPath)) {41
const description = signatureDescription(appPath);42
if (description.includes("Authority=Developer ID Application")) return "developer-id";43
if (!hasDeveloperId && description.includes("Signature=adhoc") && !description.includes("runtime)")) return "adhoc";44
}46
const options = {47
app: appPath,48
platform: "darwin",49
// Preserve the link-signed, hash-pinned native client. The outer app seal covers it.50
ignore: (filePath) => /native-runtime\/.*\/curl$/.test(filePath),51
preAutoEntitlements: false,52
preEmbedProvisioningProfile: false,53
};54
if (hasDeveloperId) options.identity = developerId[1];55
if (!hasDeveloperId) {56
options.identity = "-";57
options.identityValidation = false;58
options.optionsForFile = () => ({59
hardenedRuntime: false,60
signatureFlags: [],61
timestamp: "none",62
});63
}64
await signAsync(options);65
if (!signatureIsValid(appPath)) throw new Error("Kontrola codesign po podepsání .app selhala.");66
return hasDeveloperId ? "developer-id" : "adhoc";67
}69
async function smokeTestApp(bundlePath) {70
const executable = path.join(bundlePath, "Contents", "MacOS", productName);71
const userDataDir = fs.mkdtempSync(path.join(os.tmpdir(), "chj-mac-smoke-data-"));72
try {73
// Fixture consent for this isolated packaging smoke test only. Production74
// startup always checks the record; the environment does not bypass it.75
const { LicenseAcceptance } = require("../src/main/legal/licenseAcceptance");76
const acceptance = new LicenseAcceptance({ storageRoot: userDataDir,77
licensePath: path.join(bundlePath, "Contents", "Resources", "licenses", "APPLICATION_LICENSE.txt"),78
docsRoot: path.join(bundlePath, "Contents", "Resources", "docs"),79
appVersion: packageJson.version, buildId: require("../src/shared/buildInfo.json").buildId });80
acceptance.accept({ accepted: true, sha256: acceptance.identity.sha256, guidanceShown: true, guidanceSha256: acceptance.identity.guidanceSha256 });81
await new Promise((resolve, reject) => {82
let output = "";83
const smokeEnvironment = {84
...process.env,85
CHJ_BUILD_SMOKE_USER_DATA_DIR: userDataDir,86
ELECTRON_ENABLE_LOGGING: "1",87
};88
delete smokeEnvironment.ELECTRON_RUN_AS_NODE;89
delete smokeEnvironment.NODE_OPTIONS;90
const child = spawn(executable, [], {91
env: smokeEnvironment,92
stdio: ["ignore", "pipe", "pipe"],93
});94
child.stdout.on("data", (chunk) => { output += chunk; });95
child.stderr.on("data", (chunk) => { output += chunk; });96
const timeout = setTimeout(() => {97
child.kill("SIGTERM");98
reject(new Error(`Aplikace nedokončila smoke test do 12 sekund.\n${output.trim()}`));99
}, 12000);100
child.once("error", (error) => {101
clearTimeout(timeout);102
reject(error);103
});104
child.once("exit", (code, signal) => {105
clearTimeout(timeout);106
if (code === 0 && output.includes("CHJ_BUILD_SMOKE_READY")) resolve();107
else reject(new Error(`Aplikace nedokončila smoke test (code=${code}, signal=${signal}).\n${output.trim()}`));108
});109
});110
} finally {111
fs.rmSync(userDataDir, { recursive: true, force: true });112
}113
}115
async function main() {116
if (process.platform !== "darwin") throw new Error("macOS instalační DMG lze vytvářet pouze na macOS.");117
if (!productName || !fs.statSync(appPath, { throwIfNoEntry: false })?.isDirectory()) {118
throw new Error(`Chybí sestavená aplikace ${appPath}. Nejdřív spusťte macOS build.`);119
}121
const { validateRuntime, runtimeEnvironment } = require("../src/main/diagnostics/httpRuntime");122
const originalRuntime = validateRuntime({ resourcesPath: path.join(projectRoot, "build") });123
const resourcesPath = path.join(appPath, "Contents", "Resources");124
const packagedClient = path.join(resourcesPath, "native-runtime", "darwin-arm64", "curl");125
// A packager may re-sign nested Mach-O files. Restore the verified client before126
// creating the app's final resource seal; never edit a finished/signed DMG.127
fs.copyFileSync(originalRuntime.executable, packagedClient);128
fs.chmodSync(packagedClient, 0o755);129
prepareMacNetworkIdentity(appPath, networkIdentity);130
const signature = await ensureValidSignature();131
verifyMacNetworkIdentity(appPath, networkIdentity);132
const finalRuntime = validateRuntime({ resourcesPath });133
const runtimeVersion = execFileSync(finalRuntime.executable, ["--disable", "--version"], { encoding: "utf8", env: runtimeEnvironment() });134
if (!/Features:.*HTTP3/.test(runtimeVersion)) throw new Error("Signed app lacks its working HTTP/3 runtime");135
fs.rmSync(outputPath, { force: true });136
const staging = fs.mkdtempSync(path.join(os.tmpdir(), "chj-dmg-stage-"));137
try {138
run("ditto", [appPath, path.join(staging, `${productName}.app`)]);139
fs.symlinkSync("/Applications", path.join(staging, "Applications"));140
run("hdiutil", ["create", "-volname", productName, "-srcfolder", staging, "-format", "UDZO", "-ov", outputPath]);141
} finally { fs.rmSync(staging, { recursive: true, force: true }); }142
run("hdiutil", ["verify", outputPath]);144
const verifyRoot = fs.mkdtempSync(path.join(os.tmpdir(), "chj-mac-installer-"));145
try {146
run("hdiutil", ["attach", "-readonly", "-nobrowse", "-mountpoint", verifyRoot, outputPath]);147
if (fs.readlinkSync(path.join(verifyRoot, "Applications")) !== "/Applications") throw new Error("DMG lacks Applications shortcut");148
const extractedApp = path.join(verifyRoot, `${productName}.app`);149
if (!fs.statSync(extractedApp, { throwIfNoEntry: false })?.isDirectory() || !signatureIsValid(extractedApp)) {150
throw new Error("Výsledný DMG neobsahuje kompletní aplikaci s platným podpisem bundle.");151
}152
verifyMacNetworkIdentity(extractedApp, networkIdentity);153
await smokeTestApp(extractedApp);154
} finally {155
run("hdiutil", ["detach", verifyRoot]);156
fs.rmSync(verifyRoot, { recursive: true, force: true });157
}159
console.log(`Instalační balíček: ${outputPath}`);160
console.log(`Podpis: ${signature}`);161
if (signature !== "developer-id") {162
console.warn("VAROVÁNÍ: Jde o testovací ad-hoc sestavení. Pro bezobslužnou instalaci z webu je nutný Developer ID podpis a Apple notarizace.");163
}164
}166
main().catch((error) => {167
console.error(error.message || error);168
process.exitCode = 1;169
});SHA-256
570b85476fba29bad4099b490cbd342eaf33248c5e3041692b05663aafafc2aaCH-J Proprietary Software License 1.14 · Bron wordt geleverd onder de CH-J Proprietary Software License 1.14. De beschikbaarheid verandert de licentievoorwaarden niet of verleent geen extra rechten.
Archief SHA-256
3df08cf5e899262a6ce92d7ec2caf5c42b683f1f2b57055662b845ff7dde67a8