Vydané zdroje
Stáhnout zdroje ZIP
CH-J Server Manager
Procházejte adresáře a soubory konkrétního vydání aplikace.
Zdroje jsou zveřejněny pod CH-J Proprietary Software License 1.14. Jejich dostupnost nemění licenční podmínky ani neposkytuje další oprávnění.
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");9
const projectRoot = path.resolve(__dirname, "..");10
const packageJson = require(path.join(projectRoot, "package.json"));11
const productName = packageJson.build?.productName || packageJson.productName;12
const distRoot = path.resolve(projectRoot, process.env.CHJ_DIST_DIR || "dist");13
const appPath = path.join(distRoot, "mac-arm64", `${productName}.app`);14
const outputPath = path.join(distRoot, `${productName}-${packageJson.version}-arm64.app.zip`);16
function run(command, args, options = {}) {17
return execFileSync(command, args, { encoding: "utf8", stdio: options.capture ? "pipe" : "inherit" });18
}20
function signatureIsValid(bundlePath) {21
try {22
run("codesign", ["--verify", "--deep", "--strict", "--verbose=2", bundlePath], { capture: true });23
return true;24
} catch (_) {25
return false;26
}27
}29
function signatureDescription(bundlePath) {30
const result = spawnSync("codesign", ["-dv", "--verbose=4", bundlePath], { encoding: "utf8" });31
return `${result.stdout || ""}\n${result.stderr || ""}`;32
}34
async function ensureValidSignature() {35
if (signatureIsValid(appPath)) {36
const description = signatureDescription(appPath);37
if (description.includes("Authority=Developer ID Application")) return "developer-id";38
if (description.includes("Signature=adhoc") && !description.includes("runtime)")) return "adhoc";39
}41
const identities = run("security", ["find-identity", "-v", "-p", "codesigning"], { capture: true });42
const hasDeveloperId = identities.includes("Developer ID Application:");43
const options = {44
app: appPath,45
platform: "darwin",46
preAutoEntitlements: false,47
preEmbedProvisioningProfile: false,48
};49
if (!hasDeveloperId) {50
options.identity = "-";51
options.identityValidation = false;52
options.optionsForFile = () => ({53
hardenedRuntime: false,54
signatureFlags: [],55
timestamp: "none",56
});57
}58
await signAsync(options);59
if (!signatureIsValid(appPath)) throw new Error("Kontrola codesign po podepsání .app selhala.");60
return hasDeveloperId ? "developer-id" : "adhoc";61
}63
async function smokeTestApp(bundlePath) {64
const executable = path.join(bundlePath, "Contents", "MacOS", productName);65
const userDataDir = fs.mkdtempSync(path.join(os.tmpdir(), "chj-mac-smoke-data-"));66
try {67
// Fixture consent for this isolated packaging smoke test only. Production68
// startup always checks the record; the environment does not bypass it.69
const { LicenseAcceptance } = require("../src/main/legal/licenseAcceptance");70
const acceptance = new LicenseAcceptance({ storageRoot: userDataDir,71
licensePath: path.join(bundlePath, "Contents", "Resources", "licenses", "APPLICATION_LICENSE.txt"),72
docsRoot: path.join(bundlePath, "Contents", "Resources", "docs"),73
appVersion: packageJson.version, buildId: require("../src/shared/buildInfo.json").buildId });74
acceptance.accept({ accepted: true, sha256: acceptance.identity.sha256, guidanceShown: true, guidanceSha256: acceptance.identity.guidanceSha256 });75
await new Promise((resolve, reject) => {76
let output = "";77
const smokeEnvironment = {78
...process.env,79
CHJ_BUILD_SMOKE_USER_DATA_DIR: userDataDir,80
ELECTRON_ENABLE_LOGGING: "1",81
};82
delete smokeEnvironment.ELECTRON_RUN_AS_NODE;83
delete smokeEnvironment.NODE_OPTIONS;84
const child = spawn(executable, [], {85
env: smokeEnvironment,86
stdio: ["ignore", "pipe", "pipe"],87
});88
child.stdout.on("data", (chunk) => { output += chunk; });89
child.stderr.on("data", (chunk) => { output += chunk; });90
const timeout = setTimeout(() => {91
child.kill("SIGTERM");92
reject(new Error(`Aplikace nedokončila smoke test do 12 sekund.\n${output.trim()}`));93
}, 12000);94
child.once("error", (error) => {95
clearTimeout(timeout);96
reject(error);97
});98
child.once("exit", (code, signal) => {99
clearTimeout(timeout);100
if (code === 0 && output.includes("CHJ_BUILD_SMOKE_READY")) resolve();101
else reject(new Error(`Aplikace nedokončila smoke test (code=${code}, signal=${signal}).\n${output.trim()}`));102
});103
});104
} finally {105
fs.rmSync(userDataDir, { recursive: true, force: true });106
}107
}109
async function main() {110
if (process.platform !== "darwin") throw new Error("macOS instalační ZIP lze vytvářet pouze na macOS.");111
if (!productName || !fs.statSync(appPath, { throwIfNoEntry: false })?.isDirectory()) {112
throw new Error(`Chybí sestavená aplikace ${appPath}. Nejdřív spusťte macOS build.`);113
}115
const signature = await ensureValidSignature();116
fs.rmSync(outputPath, { force: true });117
run("ditto", ["-c", "-k", "--sequesterRsrc", "--keepParent", appPath, outputPath]);119
const verifyRoot = fs.mkdtempSync(path.join(os.tmpdir(), "chj-mac-installer-"));120
try {121
run("ditto", ["-x", "-k", outputPath, verifyRoot]);122
const extractedApp = path.join(verifyRoot, `${productName}.app`);123
if (!fs.statSync(extractedApp, { throwIfNoEntry: false })?.isDirectory() || !signatureIsValid(extractedApp)) {124
throw new Error("Výsledný ZIP neobsahuje kompletní aplikaci s platným podpisem bundle.");125
}126
await smokeTestApp(extractedApp);127
} finally {128
fs.rmSync(verifyRoot, { recursive: true, force: true });129
}131
console.log(`Instalační balíček: ${outputPath}`);132
console.log(`Podpis: ${signature}`);133
if (signature !== "developer-id") {134
console.warn("VAROVÁNÍ: Jde o testovací ad-hoc sestavení. Pro bezobslužnou instalaci z webu je nutný Developer ID podpis a Apple notarizace.");135
}136
}138
main().catch((error) => {139
console.error(error.message || error);140
process.exitCode = 1;141
});SHA-256: b48c92294b4b7c7bcbc7c2bcb5cd0f8c1a47ce5a828f5db6cba33465291d6197
SHA-256 archivu: 5ac91caf4fa32a6fdb114f2430deed486fbe7489d5eea343d1f034169fafb5e0