Публикуван източник
Изтегляне на източник ZIP
CH-J Server Manager
Преглед на директории и файлове за конкретна версия на приложението.
CH-J / Server Manager
193 Файлове
core-20261011T184039Z-4148710795d0
Добавено: Дата, която не е регистрирана · Построена:
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.dmg`);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
// Preserve the link-signed, hash-pinned native client. The outer app seal covers it.47
ignore: (filePath) => /native-runtime\/.*\/curl$/.test(filePath),48
preAutoEntitlements: false,49
preEmbedProvisioningProfile: false,50
};51
if (!hasDeveloperId) {52
options.identity = "-";53
options.identityValidation = false;54
options.optionsForFile = () => ({55
hardenedRuntime: false,56
signatureFlags: [],57
timestamp: "none",58
});59
}60
await signAsync(options);61
if (!signatureIsValid(appPath)) throw new Error("Kontrola codesign po podepsání .app selhala.");62
return hasDeveloperId ? "developer-id" : "adhoc";63
}65
async function smokeTestApp(bundlePath) {66
const executable = path.join(bundlePath, "Contents", "MacOS", productName);67
const userDataDir = fs.mkdtempSync(path.join(os.tmpdir(), "chj-mac-smoke-data-"));68
try {69
// Fixture consent for this isolated packaging smoke test only. Production70
// startup always checks the record; the environment does not bypass it.71
const { LicenseAcceptance } = require("../src/main/legal/licenseAcceptance");72
const acceptance = new LicenseAcceptance({ storageRoot: userDataDir,73
licensePath: path.join(bundlePath, "Contents", "Resources", "licenses", "APPLICATION_LICENSE.txt"),74
docsRoot: path.join(bundlePath, "Contents", "Resources", "docs"),75
appVersion: packageJson.version, buildId: require("../src/shared/buildInfo.json").buildId });76
acceptance.accept({ accepted: true, sha256: acceptance.identity.sha256, guidanceShown: true, guidanceSha256: acceptance.identity.guidanceSha256 });77
await new Promise((resolve, reject) => {78
let output = "";79
const smokeEnvironment = {80
...process.env,81
CHJ_BUILD_SMOKE_USER_DATA_DIR: userDataDir,82
ELECTRON_ENABLE_LOGGING: "1",83
};84
delete smokeEnvironment.ELECTRON_RUN_AS_NODE;85
delete smokeEnvironment.NODE_OPTIONS;86
const child = spawn(executable, [], {87
env: smokeEnvironment,88
stdio: ["ignore", "pipe", "pipe"],89
});90
child.stdout.on("data", (chunk) => { output += chunk; });91
child.stderr.on("data", (chunk) => { output += chunk; });92
const timeout = setTimeout(() => {93
child.kill("SIGTERM");94
reject(new Error(`Aplikace nedokončila smoke test do 12 sekund.\n${output.trim()}`));95
}, 12000);96
child.once("error", (error) => {97
clearTimeout(timeout);98
reject(error);99
});100
child.once("exit", (code, signal) => {101
clearTimeout(timeout);102
if (code === 0 && output.includes("CHJ_BUILD_SMOKE_READY")) resolve();103
else reject(new Error(`Aplikace nedokončila smoke test (code=${code}, signal=${signal}).\n${output.trim()}`));104
});105
});106
} finally {107
fs.rmSync(userDataDir, { recursive: true, force: true });108
}109
}111
async function main() {112
if (process.platform !== "darwin") throw new Error("macOS instalační DMG lze vytvářet pouze na macOS.");113
if (!productName || !fs.statSync(appPath, { throwIfNoEntry: false })?.isDirectory()) {114
throw new Error(`Chybí sestavená aplikace ${appPath}. Nejdřív spusťte macOS build.`);115
}117
const { validateRuntime, runtimeEnvironment } = require("../src/main/diagnostics/httpRuntime");118
const originalRuntime = validateRuntime({ resourcesPath: path.join(projectRoot, "build") });119
const resourcesPath = path.join(appPath, "Contents", "Resources");120
const packagedClient = path.join(resourcesPath, "native-runtime", "darwin-arm64", "curl");121
// A packager may re-sign nested Mach-O files. Restore the verified client before122
// creating the app's final resource seal; never edit a finished/signed DMG.123
fs.copyFileSync(originalRuntime.executable, packagedClient);124
fs.chmodSync(packagedClient, 0o755);125
const signature = await ensureValidSignature();126
const finalRuntime = validateRuntime({ resourcesPath });127
const runtimeVersion = execFileSync(finalRuntime.executable, ["--disable", "--version"], { encoding: "utf8", env: runtimeEnvironment() });128
if (!/Features:.*HTTP3/.test(runtimeVersion)) throw new Error("Signed app lacks its working HTTP/3 runtime");129
fs.rmSync(outputPath, { force: true });130
const staging = fs.mkdtempSync(path.join(os.tmpdir(), "chj-dmg-stage-"));131
try {132
run("ditto", [appPath, path.join(staging, `${productName}.app`)]);133
fs.symlinkSync("/Applications", path.join(staging, "Applications"));134
run("hdiutil", ["create", "-volname", productName, "-srcfolder", staging, "-format", "UDZO", "-ov", outputPath]);135
} finally { fs.rmSync(staging, { recursive: true, force: true }); }136
run("hdiutil", ["verify", outputPath]);138
const verifyRoot = fs.mkdtempSync(path.join(os.tmpdir(), "chj-mac-installer-"));139
try {140
run("hdiutil", ["attach", "-readonly", "-nobrowse", "-mountpoint", verifyRoot, outputPath]);141
if (fs.readlinkSync(path.join(verifyRoot, "Applications")) !== "/Applications") throw new Error("DMG lacks Applications shortcut");142
const extractedApp = path.join(verifyRoot, `${productName}.app`);143
if (!fs.statSync(extractedApp, { throwIfNoEntry: false })?.isDirectory() || !signatureIsValid(extractedApp)) {144
throw new Error("Výsledný DMG neobsahuje kompletní aplikaci s platným podpisem bundle.");145
}146
await smokeTestApp(extractedApp);147
} finally {148
run("hdiutil", ["detach", verifyRoot]);149
fs.rmSync(verifyRoot, { recursive: true, force: true });150
}152
console.log(`Instalační balíček: ${outputPath}`);153
console.log(`Podpis: ${signature}`);154
if (signature !== "developer-id") {155
console.warn("VAROVÁNÍ: Jde o testovací ad-hoc sestavení. Pro bezobslužnou instalaci z webu je nutný Developer ID podpis a Apple notarizace.");156
}157
}159
main().catch((error) => {160
console.error(error.message || error);161
process.exitCode = 1;162
});SHA-256
2a73fa890b1ac95cb8ce3cf6e358280f6522a87b7b21aef04b05091d8318ebc3CH-J Proprietary Software License 1.14 · Източникът е предоставен под CH-J Proprietary Software License 1.14. Неговата наличност не променя лицензионните условия или не предоставя допълнителни права.
Архив SHA-256
5a8ea02d06a5643cf2330fe9f54b8767a06c1c59d36527705e536fa9dbca7614