Build, Sign & Notarise macOS builds (#486)

This commit is contained in:
Michael Telatynski
2023-01-31 13:22:30 +00:00
committed by GitHub
parent 7f3bbc2156
commit e5117f9736
8 changed files with 390 additions and 9 deletions

View File

@@ -8,12 +8,21 @@ exports.default = async function (context) {
if (electronPlatformName === "darwin") {
const appName = context.packager.appInfo.productFilename;
const keychainProfile = process.env.NOTARIZE_KEYCHAIN_PROFILE;
if (keychainProfile === undefined) {
const notarizeToolCredentials = {};
if (process.env.NOTARIZE_KEYCHAIN_PROFILE) {
notarizeToolCredentials.keychainProfile = process.env.NOTARIZE_KEYCHAIN_PROFILE;
notarizeToolCredentials.keychain = process.env.NOTARIZE_KEYCHAIN;
} if (process.env.NOTARIZE_APPLE_ID && process.env.NOTARIZE_APPLE_ID_PASSWORD && process.env.NOTARIZE_TEAM_ID) {
notarizeToolCredentials.appleId = process.env.NOTARIZE_APPLE_ID;
notarizeToolCredentials.appleIdPassword = process.env.NOTARIZE_APPLE_ID_PASSWORD;
notarizeToolCredentials.teamId = process.env.NOTARIZE_TEAM_ID;
} else {
if (!warned) {
console.log("*****************************************");
console.log("* NOTARIZE_KEYCHAIN_PROFILE is not set. *");
console.log("* This build will NOT be notarised. *");
console.log("* Provide NOTARIZE_KEYCHAIN_PROFILE or *");
console.log("* NOTARIZE_APPLE_ID, NOTARIZE_TEAM_ID *");
console.log("* and NOTARIZE_APPLE_ID_PASSWORD *");
console.log("*****************************************");
warned = true;
}
@@ -25,8 +34,7 @@ exports.default = async function (context) {
tool: "notarytool",
appBundleId: appId,
appPath: `${appOutDir}/${appName}.app`,
keychainProfile,
keychain: process.env.NOTARIZE_KEYCHAIN,
...notarizeToolCredentials,
});
}
};

View File

@@ -0,0 +1,131 @@
#!/usr/bin/env -S npx ts-node
/**
* Script to generate electron-builder.json config files for builds which don't match package.json, e.g. nightlies
* This script has different outputs depending on your os platform.
*
* On Windows:
* Prefixes the nightly version with `0.0.1-nightly.` as it breaks if it is not semver
*
* On Linux:
* Replaces spaces in the product name with dashes as spaces in paths can cause issues
* Passes --deb-custom-control to build.deb.fpm if specified
*/
import parseArgs from "minimist";
import fsProm from "fs/promises";
import * as os from "os";
const ELECTRON_BUILDER_CFG_FILE = "electron-builder.json";
const NIGHTLY_APP_ID = "im.riot.nightly";
const NIGHTLY_APP_NAME = "element-desktop-nightly";
const argv = parseArgs<{
nightly?: string;
"deb-custom-control"?: string;
}>(process.argv.slice(2), {
string: ["nightly", "deb-custom-control"],
});
interface File {
from: string;
to: string;
}
interface PackageBuild {
appId: string;
asarUnpack: string;
files: Array<string | File>;
extraResources: Array<string | File>;
linux: {
target: string;
category: string;
maintainer: string;
desktop: {
StartupWMClass: string;
};
};
mac: {
category: string;
darkModeSupport: boolean;
};
win: {
target: {
target: string;
};
sign: string;
};
deb?: {
fpm?: string[];
};
directories: {
output: string;
};
afterPack: string;
afterSign: string;
protocols: Array<{
name: string;
schemes: string[];
}>;
extraMetadata?: {
productName?: string;
name?: string;
version?: string;
};
}
interface Package {
build: PackageBuild;
productName: string;
}
async function main(): Promise<number | void> {
// Electron builder doesn't overlay with the config in package.json, so load it here
const pkg: Package = JSON.parse(await fsProm.readFile("package.json", "utf8"));
const cfg: PackageBuild = {
...pkg.build,
extraMetadata: {
productName: pkg.productName,
},
};
if (argv.nightly) {
cfg.appId = NIGHTLY_APP_ID;
cfg.extraMetadata!.productName += " Nightly";
cfg.extraMetadata!.name = NIGHTLY_APP_NAME;
let version = argv.nightly;
if (os.platform() === "win32") {
// The windows packager relies on parsing this as semver, so we have to make it look like one.
// This will give our update packages really stupid names, but we probably can't change that either
// because squirrel windows parses them for the version too. We don't really care: nobody sees them.
// We just give the installer a static name, so you'll just see this in the 'about' dialog.
// Turns out if you use 0.0.0 here it makes Squirrel windows crash, so we use 0.0.1.
version = "0.0.1-nightly." + version;
}
cfg.extraMetadata!.version = version;
}
if (os.platform() === "linux") {
// Electron crashes on debian if there's a space in the path.
// https://github.com/vector-im/element-web/issues/13171
cfg.extraMetadata!.productName = cfg.extraMetadata!.productName!.replace(/ /g, "-");
if (argv["deb-custom-control"]) {
cfg.deb = {
fpm: [`--deb-custom-control=${argv["deb-custom-control"]}`],
};
}
}
await fsProm.writeFile(ELECTRON_BUILDER_CFG_FILE, JSON.stringify(cfg, null, 4));
}
main().then((ret) => {
process.exit(ret!);
}).catch((e) => {
console.error(e);
process.exit(1);
});

View File

@@ -0,0 +1,41 @@
#!/usr/bin/env -S npx ts-node
/**
* Script to generate incremental Nightly build versions, based on the latest Nightly build version of that kind.
* The version format is YYYYMMDDNN where NN is in case we need to do multiple versions in a day.
*
* NB. on windows, squirrel will try to parse the version number parts, including this string, into 32-bit integers,
* which is fine as long as we only add two digits to the end...
*/
import parseArgs from "minimist";
const argv = parseArgs<{
latest?: string;
}>(process.argv.slice(2), {
string: ["latest"],
});
function parseVersion(version: string): [Date, number] {
const year = parseInt(version.slice(0, 4), 10);
const month = parseInt(version.slice(4, 2), 10);
const day = parseInt(version.slice(6, 2), 10);
const num = parseInt(version.slice(8, 2), 10);
return [new Date(year, month - 1, day), num];
}
const [latestDate, latestNum] = argv.latest ? parseVersion(argv.latest) : [];
const now = new Date();
const month = (now.getMonth() + 1).toString().padStart(2, '0');
const date = now.getDate().toString().padStart(2, '0');
let buildNum = 1;
if (latestDate && new Date(latestDate).getDate().toString().padStart(2, '0') === date) {
buildNum = latestNum! + 1;
}
if (buildNum > 99) {
throw new Error("Maximum number of Nightlies exceeded on this day.");
}
console.log(now.getFullYear() + month + date + buildNum.toString().padStart(2, '0') + buildNum);