From 6617b29028ab1ff3883323693cc3f64a850be2f3 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 3 Jan 2024 16:29:48 +0000 Subject: [PATCH] Move electron-builder config to javascript file (#1402) --- .github/workflows/build_linux.yaml | 11 +- .github/workflows/build_macos.yaml | 10 +- .github/workflows/build_windows.yaml | 15 ++- electron-builder.js | 175 +++++++++++++++++++++++++++ package.json | 76 ------------ scripts/generate-builder-config.ts | 129 -------------------- 6 files changed, 191 insertions(+), 225 deletions(-) create mode 100644 electron-builder.js delete mode 100755 scripts/generate-builder-config.ts diff --git a/.github/workflows/build_linux.yaml b/.github/workflows/build_linux.yaml index 25bcf34..acf5414 100644 --- a/.github/workflows/build_linux.yaml +++ b/.github/workflows/build_linux.yaml @@ -103,24 +103,19 @@ jobs: run: "yarn build:native --target ${{ steps.config.outputs.target }}" - name: "[Nightly] Resolve version" - id: nightly if: inputs.version != '' run: | - echo "config-args=--nightly '${{ inputs.version }}'" >> $GITHUB_OUTPUT + echo "ED_NIGHTLY=${{ inputs.version }}" >> $GITHUB_ENV - name: Generate debian files and arguments - id: debian run: | if [ -f changelog.Debian ]; then - echo "config-args=--deb-changelog changelog.Debian" >> $GITHUB_OUTPUT + echo "ED_DEBIAN_CHANGELOG=changelog.Debian" >> $GITHUB_ENV fi - name: Build App run: | - npx ts-node scripts/generate-builder-config.ts \ - ${{ steps.nightly.outputs.config-args }} \ - ${{ steps.debian.outputs.config-args }} - yarn build --publish never -l --config electron-builder.json ${{ steps.config.outputs.build-args }} + yarn build --publish never -l ${{ steps.config.outputs.build-args }} - name: Check native libraries run: | diff --git a/.github/workflows/build_macos.yaml b/.github/workflows/build_macos.yaml index ed3c06a..c795e6e 100644 --- a/.github/workflows/build_macos.yaml +++ b/.github/workflows/build_macos.yaml @@ -73,18 +73,17 @@ jobs: yarn build:native:universal - name: "[Nightly] Resolve version" - id: nightly if: inputs.version != '' run: | - echo "config-args=--nightly '${{ inputs.version }}'" >> $GITHUB_OUTPUT + echo "ED_NIGHTLY=${{ inputs.version }}" >> $GITHUB_ENV # We split these because electron-builder gets upset if we set CSC_LINK even to an empty string - name: "[Signed] Build App" if: inputs.sign != '' run: | - scripts/generate-builder-config.ts ${{ steps.nightly.outputs.config-args }} --notarytool-team-id='${{ secrets.APPLE_TEAM_ID }}' - yarn build:universal --publish never --config electron-builder.json + yarn build:universal --publish never env: + ED_NOTARYTOOL_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} CSC_KEY_PASSWORD: ${{ secrets.APPLE_CSC_KEY_PASSWORD }} @@ -101,8 +100,7 @@ jobs: - name: "[Unsigned] Build App" if: inputs.sign == '' run: | - scripts/generate-builder-config.ts ${{ steps.nightly.outputs.config-args }} - yarn build:universal --publish never --config electron-builder.json + yarn build:universal --publish never env: CSC_IDENTITY_AUTO_DISCOVERY: false diff --git a/.github/workflows/build_windows.yaml b/.github/workflows/build_windows.yaml index 62b65f0..7b2bb52 100644 --- a/.github/workflows/build_windows.yaml +++ b/.github/workflows/build_windows.yaml @@ -115,7 +115,6 @@ jobs: yarn build:native --target ${{ steps.config.outputs.target }} - name: Install and configure eSigner CKA - id: esigner if: inputs.sign run: | Set-StrictMode -Version 'Latest' @@ -144,22 +143,26 @@ jobs: # Extract thumbprint and subject name $Thumbprint = $CodeSigningCert.Thumbprint $SubjectName = ($CodeSigningCert.Subject -replace ", ?", "`n" | ConvertFrom-StringData).CN - echo "config-args=--signtool-thumbprint '$Thumbprint' --signtool-subject-name '$SubjectName'" >> $env:GITHUB_OUTPUT + + echo "ED_SIGNTOOL_THUMBPRINT=$Thumbprint" >> $GITHUB_ENV + echo "ED_SIGNTOOL_SUBJECT_NAME=$SubjectName" >> $GITHUB_ENV env: INSTALL_DIR: C:\Users\runneradmin\eSignerCKA MASTER_KEY_FILE: C:\Users\runneradmin\eSignerCKA\master.key - name: "[Nightly] Resolve version" - id: nightly if: inputs.version != '' shell: bash run: | - echo "config-args=--nightly '${{ inputs.version }}'" >> $GITHUB_OUTPUT + echo "ED_NIGHTLY=${{ inputs.version }}" >> $GITHUB_ENV + + # XXX: For whatever reason if we use `yarn build ...` it freezes, but splitting it into parts it is fine + - run: yarn run build:ts + - run: yarn run build:res - name: Build App run: | - yarn ts-node scripts/generate-builder-config.ts ${{ steps.nightly.outputs.config-args }} ${{ steps.esigner.outputs.config-args }} - yarn build --publish never -w --config electron-builder.json ${{ steps.config.outputs.build-args }} + yarn electron-builder --publish never -w ${{ steps.config.outputs.build-args }} - name: Check app was signed successfully if: inputs.sign != '' diff --git a/electron-builder.js b/electron-builder.js new file mode 100644 index 0000000..1edef2b --- /dev/null +++ b/electron-builder.js @@ -0,0 +1,175 @@ +const os = require("os"); +const fs = require("fs"); + +// Typescript conversion blocked on https://github.com/electron-userland/electron-builder/issues/7775 + +/** + * 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 + * Passes $ED_SIGNTOOL_THUMBPRINT and $ED_SIGNTOOL_SUBJECT_NAME to + * build.win.signingHashAlgorithms and build.win.certificateSubjectName respectively if specified. + * + * On macOS: + * Passes $ED_NOTARYTOOL_TEAM_ID to build.mac.notarize.notarize if specified + * + * On Linux: + * Replaces spaces in the product name with dashes as spaces in paths can cause issues + * Removes libsqlcipher0 recommended dependency if env SQLCIPHER_BUNDLED is asserted. + * Passes $ED_DEBIAN_CHANGELOG to build.deb.fpm if specified + */ + +const NIGHTLY_APP_ID = "im.riot.nightly"; +const NIGHTLY_APP_NAME = "element-desktop-nightly"; +const NIGHTLY_DEB_NAME = "element-nightly"; + +const pkg = JSON.parse(fs.readFileSync("package.json", "utf8")); + +/** + * @type {import('electron-builder').Configuration} + * @see https://www.electron.build/configuration/configuration + */ +const config = { + appId: "im.riot.app", + asarUnpack: "**/*.node", + files: [ + "package.json", + { + from: ".hak/hakModules", + to: "node_modules", + }, + "lib/**", + ], + extraResources: [ + { + from: "res/img", + to: "img", + }, + "webapp.asar", + ], + extraMetadata: { + productName: pkg.productName, + description: pkg.description, + }, + linux: { + target: ["tar.gz", "deb"], + category: "Network;InstantMessaging;Chat", + maintainer: "support@element.io", + icon: "build/icons", + desktop: { + MimeType: "x-scheme-handler/element", + }, + }, + deb: { + packageCategory: "net", + depends: [ + "libgtk-3-0", + "libnotify4", + "libnss3", + "libxss1", + "libxtst6", + "xdg-utils", + "libatspi2.0-0", + "libuuid1", + "libsecret-1-0", + "libasound2", + "libgbm1", + ], + recommends: ["libsqlcipher0", "element-io-archive-keyring"], + fpm: [ + "--deb-field", + "Replaces: riot-desktop (<< 1.7.0), riot-web (<< 1.7.0)", + "--deb-field", + "Breaks: riot-desktop (<< 1.7.0), riot-web (<< 1.7.0)", + ], + }, + mac: { + category: "public.app-category.social-networking", + darkModeSupport: true, + hardenedRuntime: true, + gatekeeperAssess: true, + entitlements: "./build/entitlements.mac.plist", + icon: "build/icons/icon.icns", + }, + win: { + target: ["squirrel"], + signingHashAlgorithms: ["sha256"], + icon: "build/icons/icon.ico", + }, + directories: { + output: "dist", + }, + protocols: [ + { + name: "element", + schemes: ["element"], + }, + ], +}; + +/** + * Allow specifying windows signing cert via env vars + * @param {string} process.env.ED_SIGNTOOL_SUBJECT_NAME + * @param {string} process.env.ED_SIGNTOOL_THUMBPRINT + */ +if (process.env.ED_SIGNTOOL_SUBJECT_NAME && process.env.ED_SIGNTOOL_THUMBPRINT) { + config.win.certificateSubjectName = process.env.ED_SIGNTOOL_SUBJECT_NAME; + config.win.certificateSha1 = process.env.ED_SIGNTOOL_THUMBPRINT; +} + +/** + * Allow specifying macOS notary team id via env var + * @param {string} process.env.ED_NOTARYTOOL_TEAM_ID + */ +if (process.env.ED_NOTARYTOOL_TEAM_ID) { + config.mac.notarize = { + teamId: process.env.ED_NOTARYTOOL_TEAM_ID, + }; +} + +/** + * Allow specifying nightly version via env var + * @param {string} process.env.ED_NIGHTLY + */ +if (process.env.ED_NIGHTLY) { + config.deb.fpm = []; // Clear the fpm as the breaks deb fields don't apply to nightly + + config.appId = NIGHTLY_APP_ID; + config.extraMetadata.productName += " Nightly"; + config.extraMetadata.name = NIGHTLY_APP_NAME; + config.extraMetadata.description += " (nightly unstable build)"; + config.deb.fpm.push("--name", NIGHTLY_DEB_NAME); + + let version = process.env.ED_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; + } + config.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 + config.extraMetadata.productName = config.extraMetadata.productName.replace(/ /g, "-"); + + /** + * Allow specifying deb changelog via env var + * @param {string} process.env.ED_DEB_CHANGELOG + */ + if (process.env.ED_DEBIAN_CHANGELOG) { + config.deb.fpm.push(`--deb-changelog=${process.env.ED_DEBIAN_CHANGELOG}`); + } + + if (process.env.SQLCIPHER_BUNDLED) { + // Remove sqlcipher dependency when using bundled + config.deb.recommends = config.deb.recommends?.filter((d) => d !== "libsqlcipher0"); + } +} + +exports.default = config; diff --git a/package.json b/package.json index 446830c..5754668 100644 --- a/package.json +++ b/package.json @@ -126,82 +126,6 @@ "resolutions": { "@types/node": "16.18.68" }, - "build": { - "appId": "im.riot.app", - "asarUnpack": "**/*.node", - "files": [ - "package.json", - { - "from": ".hak/hakModules", - "to": "node_modules" - }, - "lib/**" - ], - "extraResources": [ - { - "from": "res/img", - "to": "img" - }, - "webapp.asar" - ], - "linux": { - "target": [ - "tar.gz", - "deb" - ], - "category": "Network;InstantMessaging;Chat", - "maintainer": "support@element.io", - "icon": "build/icons" - }, - "deb": { - "packageCategory": "net", - "depends": [ - "libgtk-3-0", - "libnotify4", - "libnss3", - "libxss1", - "libxtst6", - "xdg-utils", - "libatspi2.0-0", - "libuuid1", - "libsecret-1-0", - "libasound2", - "libgbm1" - ], - "recommends": [ - "libsqlcipher0", - "element-io-archive-keyring" - ] - }, - "mac": { - "category": "public.app-category.social-networking", - "darkModeSupport": true, - "hardenedRuntime": true, - "gatekeeperAssess": true, - "entitlements": "./build/entitlements.mac.plist", - "icon": "build/icons/icon.icns" - }, - "win": { - "target": [ - "squirrel" - ], - "signingHashAlgorithms": [ - "sha256" - ], - "icon": "build/icons/icon.ico" - }, - "directories": { - "output": "dist" - }, - "protocols": [ - { - "name": "element", - "schemes": [ - "element" - ] - } - ] - }, "jest": { "testEnvironment": "node", "testMatch": [ diff --git a/scripts/generate-builder-config.ts b/scripts/generate-builder-config.ts deleted file mode 100755 index 718edca..0000000 --- a/scripts/generate-builder-config.ts +++ /dev/null @@ -1,129 +0,0 @@ -#!/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 macOS: - * Passes --notarytool-team-id to build.mac.notarize.notarize if specified - * - * 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 - * Removes libsqlcipher0 recommended dependency if env SQLCIPHER_BUNDLED is asserted. - */ - -import parseArgs from "minimist"; -import fsProm from "fs/promises"; -import * as os from "os"; -import { Configuration } from "app-builder-lib"; - -const ELECTRON_BUILDER_CFG_FILE = "electron-builder.json"; - -const NIGHTLY_APP_ID = "im.riot.nightly"; -const NIGHTLY_APP_NAME = "element-desktop-nightly"; -const NIGHTLY_DEB_NAME = "element-nightly"; - -const argv = parseArgs<{ - "nightly"?: string; - "signtool-thumbprint"?: string; - "signtool-subject-name"?: string; - "notarytool-team-id"?: string; - "deb-changelog"?: string; -}>(process.argv.slice(2), { - string: ["nightly", "deb-changelog", "signtool-thumbprint", "signtool-subject-name", "notarytool-team-id"], -}); - -type DeepWriteable = { -readonly [P in keyof T]: DeepWriteable }; - -interface PackageBuild extends DeepWriteable> { - extraMetadata?: { - productName?: string; - name?: string; - version?: string; - description?: string; - }; -} - -interface Package { - build: PackageBuild; - productName: string; - description: string; -} - -async function main(): Promise { - // 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, - description: pkg.description, - }, - }; - - if (!cfg.deb!.fpm) cfg.deb!.fpm = []; - - if (argv.nightly) { - cfg.appId = NIGHTLY_APP_ID; - cfg.extraMetadata!.productName += " Nightly"; - cfg.extraMetadata!.name = NIGHTLY_APP_NAME; - cfg.extraMetadata!.description += " (nightly unstable build)"; - cfg.deb!.fpm!.push("--name", NIGHTLY_DEB_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; - } else { - cfg.deb!.fpm!.push("--deb-field", "Replaces: riot-desktop (<< 1.7.0), riot-web (<< 1.7.0)"); - cfg.deb!.fpm!.push("--deb-field", "Breaks: riot-desktop (<< 1.7.0), riot-web (<< 1.7.0)"); - } - - if (argv["signtool-thumbprint"] && argv["signtool-subject-name"]) { - cfg.win!.certificateSubjectName = argv["signtool-subject-name"]; - cfg.win!.certificateSha1 = argv["signtool-thumbprint"]; - } - - if (argv["notarytool-team-id"]) { - cfg.mac!.notarize = { - teamId: argv["notarytool-team-id"], - }; - } - - 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-changelog"]) { - cfg.deb!.fpm!.push(`--deb-changelog=${argv["deb-changelog"]}`); - } - - if (process.env.SQLCIPHER_BUNDLED) { - // Remove sqlcipher dependency when using bundled - cfg.deb!.recommends = cfg.deb!.recommends?.filter((d) => d !== "libsqlcipher0"); - } - } - - 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); - });