From 13621f0a77b6a8f5ca0ae4178422b92756521856 Mon Sep 17 00:00:00 2001 From: macdja38 Date: Wed, 26 Oct 2022 23:59:05 -0400 Subject: [PATCH 1/3] Fix "packaging application" log never stopping when building for multiple architectures There's some kinda complex race condition ish behaviour in the current way the packagerSpinner is handled. At the moment there's one variable for all architectures, that gets created in one of the later afterCopyHooks, and dismissed both in the first hook, and at the end of all the hooks. This would work if architectures where built for sequentially, but, at least on my system, these builds happen in parallel. Meaning one of the architectures packageSpinners overwrites the other, before the first is dismissed. At the end of the build the second packageSpinner has success fired on it, while the first continues to spin, preventing the process from exiting. The solution in this commit is far less than ideal. Constraints: - Without access to the list of architectures (the function to generate that list is not exported from electron-packer) we don't even know how many architectures we're building for. - This one is a little self-imposed, and maybe not a constraint for the project, but the code aims not to change any public facing apis. So we need to have one spinner we can pass to the postPackage hook. https://www.electronforge.io/configuration#postpackage Given these constraints the solution in this commit has one initial prepare / package spinner. AS well as prepare / package spinners per architecture. One downside is if the afterCopyHooks are executed one architecture at a time, instead of parallelized by architecture, the overarching prepareSpinner could be ended early, (though architecture specific prepare spinners would still be accurate). --- packages/api/core/src/api/package.ts | 50 ++++++++++++++++------------ 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/packages/api/core/src/api/package.ts b/packages/api/core/src/api/package.ts index 5b0dd50ed3..9eb0ffad7e 100644 --- a/packages/api/core/src/api/package.ts +++ b/packages/api/core/src/api/package.ts @@ -6,7 +6,7 @@ import { ForgeArch, ForgePlatform } from '@electron-forge/shared-types'; import { getHostArch } from '@electron/get'; import chalk from 'chalk'; import debug from 'debug'; -import packager, { HookFunction } from 'electron-packager'; +import packager, { HookFunction, TargetArch } from 'electron-packager'; import glob from 'fast-glob'; import fs from 'fs-extra'; @@ -83,7 +83,8 @@ export default async ({ }: PackageOptions): Promise => { const ora = interactive ? realOra : fakeOra; - let prepareSpinner = ora(`Preparing to Package Application for arch: ${chalk.cyan(arch === 'all' ? 'ia32' : arch)}`).start(); + const prepareSpinner = ora(`Preparing to Package Application for arch: ${chalk.cyan(arch)}`).start(); + const prepareSpinnerPerArch: { [keyof: TargetArch]: OraImpl } = {}; let prepareCounter = 0; const resolvedDir = await resolveDir(dir); @@ -101,16 +102,13 @@ export default async ({ const calculatedOutDir = outDir || getCurrentOutDir(dir, forgeConfig); let packagerSpinner: OraImpl | undefined; + const packagerSpinnerPerArch: { [keyof: TargetArch]: OraImpl } = {}; const pruneEnabled = !('prune' in forgeConfig.packagerConfig) || forgeConfig.packagerConfig.prune; const afterCopyHooks: HookFunction[] = [ async (buildPath, electronVersion, pPlatform, pArch, done) => { - if (packagerSpinner) { - packagerSpinner.succeed(); - prepareCounter += 1; - prepareSpinner = ora(`Preparing to Package Application for arch: ${chalk.cyan(prepareCounter === 2 ? 'armv7l' : 'x64')}`).start(); - } + prepareSpinnerPerArch[pArch] = ora(`Preparing to Package Application for arch: ${chalk.cyan(pArch)}`).start(); const bins = await glob(path.join(buildPath, '**/.bin/**/*')); for (const bin of bins) { await fs.remove(bin); @@ -118,28 +116,37 @@ export default async ({ done(); }, async (buildPath, electronVersion, pPlatform, pArch, done) => { - prepareSpinner.succeed(); + prepareSpinnerPerArch[pArch].succeed(); + prepareCounter += 1; + if (Object.values(prepareSpinnerPerArch).length === prepareCounter) { + prepareSpinner.succeed(); + } await runHook(forgeConfig, 'packageAfterCopy', buildPath, electronVersion, pPlatform, pArch); done(); }, async (buildPath, electronVersion, pPlatform, pArch, done) => { await rebuildHook(buildPath, electronVersion, pPlatform, pArch, forgeConfig.rebuildConfig); - packagerSpinner = ora('Packaging Application').start(); + if (!packagerSpinner) { + packagerSpinner = ora(`Packaging Application for ${arch}`).start(); + } + packagerSpinnerPerArch[pArch] = ora(`Packaging Application for ${pArch}`).start(); + done(); + }, + async (buildPath, electronVersion, pPlatform, pArch, done) => { + const copiedPackageJSON = await readMutatedPackageJson(buildPath, forgeConfig); + if (copiedPackageJSON.config && copiedPackageJSON.config.forge) { + delete copiedPackageJSON.config.forge; + } + await fs.writeJson(path.resolve(buildPath, 'package.json'), copiedPackageJSON, { spaces: 2 }); + done(); + }, + ...resolveHooks(forgeConfig.packagerConfig.afterCopy, dir), + async (buildPath, electronVersion, pPlatform, pArch, done) => { + packagerSpinnerPerArch[pArch].succeed(); done(); }, ]; - afterCopyHooks.push(async (buildPath, electronVersion, pPlatform, pArch, done) => { - const copiedPackageJSON = await readMutatedPackageJson(buildPath, forgeConfig); - if (copiedPackageJSON.config && copiedPackageJSON.config.forge) { - delete copiedPackageJSON.config.forge; - } - await fs.writeJson(path.resolve(buildPath, 'package.json'), copiedPackageJSON, { spaces: 2 }); - done(); - }); - - afterCopyHooks.push(...resolveHooks(forgeConfig.packagerConfig.afterCopy, dir)); - const afterPruneHooks = []; if (pruneEnabled) { @@ -205,6 +212,5 @@ export default async ({ spinner: packagerSpinner, }); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - if (packagerSpinner) packagerSpinner!.succeed(); + if (packagerSpinner) packagerSpinner.succeed(); }; From e53671c653b2bb46126825cec3ea525a3c791e46 Mon Sep 17 00:00:00 2001 From: macdja38 Date: Sat, 29 Oct 2022 05:05:21 -0400 Subject: [PATCH 2/3] Simplify Package spinners, removing prepackage & making package smarter. --- packages/api/core/src/api/package.ts | 48 ++++++++++++++++------------ 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/packages/api/core/src/api/package.ts b/packages/api/core/src/api/package.ts index 9eb0ffad7e..705b92165a 100644 --- a/packages/api/core/src/api/package.ts +++ b/packages/api/core/src/api/package.ts @@ -1,12 +1,12 @@ import path from 'path'; import { promisify } from 'util'; -import { fakeOra, OraImpl, ora as realOra } from '@electron-forge/async-ora'; +import { fakeOra, ora as realOra } from '@electron-forge/async-ora'; import { ForgeArch, ForgePlatform } from '@electron-forge/shared-types'; import { getHostArch } from '@electron/get'; import chalk from 'chalk'; import debug from 'debug'; -import packager, { HookFunction, TargetArch } from 'electron-packager'; +import packager, { FinalizeTargetMatrixHookFunction, HookFunction, TargetDefinition } from 'electron-packager'; import glob from 'fast-glob'; import fs from 'fs-extra'; @@ -83,9 +83,7 @@ export default async ({ }: PackageOptions): Promise => { const ora = interactive ? realOra : fakeOra; - const prepareSpinner = ora(`Preparing to Package Application for arch: ${chalk.cyan(arch)}`).start(); - const prepareSpinnerPerArch: { [keyof: TargetArch]: OraImpl } = {}; - let prepareCounter = 0; + let spinner = ora(`Preparing to Package Application`).start(); const resolvedDir = await resolveDir(dir); if (!resolvedDir) { @@ -101,14 +99,24 @@ export default async ({ } const calculatedOutDir = outDir || getCurrentOutDir(dir, forgeConfig); - let packagerSpinner: OraImpl | undefined; - const packagerSpinnerPerArch: { [keyof: TargetArch]: OraImpl } = {}; + + let pending: TargetDefinition[] = []; + + function readableTargets(targets: TargetDefinition[]) { + return targets.map(({ platform, arch }) => `${platform}:${arch}`).join(', '); + } + + function afterFinalizeTargetMatrixHooks(matrix: TargetDefinition[], done: Parameters[1]) { + spinner.succeed(); + spinner = ora(`Packaging for ${chalk.cyan(readableTargets(matrix))}`).start(); + pending.push(...matrix); + done(); + } const pruneEnabled = !('prune' in forgeConfig.packagerConfig) || forgeConfig.packagerConfig.prune; const afterCopyHooks: HookFunction[] = [ async (buildPath, electronVersion, pPlatform, pArch, done) => { - prepareSpinnerPerArch[pArch] = ora(`Preparing to Package Application for arch: ${chalk.cyan(pArch)}`).start(); const bins = await glob(path.join(buildPath, '**/.bin/**/*')); for (const bin of bins) { await fs.remove(bin); @@ -116,20 +124,11 @@ export default async ({ done(); }, async (buildPath, electronVersion, pPlatform, pArch, done) => { - prepareSpinnerPerArch[pArch].succeed(); - prepareCounter += 1; - if (Object.values(prepareSpinnerPerArch).length === prepareCounter) { - prepareSpinner.succeed(); - } await runHook(forgeConfig, 'packageAfterCopy', buildPath, electronVersion, pPlatform, pArch); done(); }, async (buildPath, electronVersion, pPlatform, pArch, done) => { await rebuildHook(buildPath, electronVersion, pPlatform, pArch, forgeConfig.rebuildConfig); - if (!packagerSpinner) { - packagerSpinner = ora(`Packaging Application for ${arch}`).start(); - } - packagerSpinnerPerArch[pArch] = ora(`Packaging Application for ${pArch}`).start(); done(); }, async (buildPath, electronVersion, pPlatform, pArch, done) => { @@ -142,7 +141,15 @@ export default async ({ }, ...resolveHooks(forgeConfig.packagerConfig.afterCopy, dir), async (buildPath, electronVersion, pPlatform, pArch, done) => { - packagerSpinnerPerArch[pArch].succeed(); + spinner.text = `Packaging for ${chalk.cyan(pArch)} complete`; + spinner.succeed(); + pending = pending.filter(({ arch, platform }) => !(arch === pArch && platform === pPlatform)); + if (pending.length > 0) { + spinner = ora(`Packaging for ${chalk.cyan(readableTargets(pending))}`).start(); + } else { + spinner = ora(`Packaging complete`).start(); + } + done(); }, ]; @@ -175,6 +182,7 @@ export default async ({ dir, arch: arch as PackagerArch, platform, + afterFinalizeTargetMatrix: [afterFinalizeTargetMatrixHooks], afterCopy: sequentialHooks(afterCopyHooks), afterExtract: sequentialHooks(afterExtractHooks), afterPrune: sequentialHooks(afterPruneHooks), @@ -209,8 +217,8 @@ export default async ({ arch, outputPaths, platform, - spinner: packagerSpinner, + spinner, }); - if (packagerSpinner) packagerSpinner.succeed(); + if (spinner) spinner.succeed(); }; From 869256142dbace90757138c62d1fad947ca5172a Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Mon, 31 Oct 2022 13:08:30 -0700 Subject: [PATCH 3/3] build: update electron-packager --- package.json | 2 +- packages/api/core/package.json | 2 +- packages/plugin/webpack/package.json | 2 +- packages/utils/types/package.json | 2 +- yarn.lock | 26 +++++++++++++------------- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 8fb7e6ff3c..aded8e2970 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "cross-spawn": "^7.0.3", "cross-zip": "^4.0.0", "debug": "^4.3.1", - "electron-packager": "^17.0.0", + "electron-packager": "^17.1.0", "electron-rebuild": "^3.2.6", "express": "^4.17.1", "express-ws": "^5.0.2", diff --git a/packages/api/core/package.json b/packages/api/core/package.json index 9bd7f64f8c..1d6e04afa1 100644 --- a/packages/api/core/package.json +++ b/packages/api/core/package.json @@ -49,7 +49,7 @@ "@malept/cross-spawn-promise": "^2.0.0", "chalk": "^4.0.0", "debug": "^4.3.1", - "electron-packager": "^17.0.0", + "electron-packager": "^17.1.0", "electron-rebuild": "^3.2.6", "fast-glob": "^3.2.7", "filenamify": "^4.1.0", diff --git a/packages/plugin/webpack/package.json b/packages/plugin/webpack/package.json index fca0821e18..f5e580f5c5 100644 --- a/packages/plugin/webpack/package.json +++ b/packages/plugin/webpack/package.json @@ -14,7 +14,7 @@ "@malept/cross-spawn-promise": "^2.0.0", "@types/node": "^18.0.3", "chai": "^4.3.3", - "electron-packager": "^17.0.0", + "electron-packager": "^17.1.0", "mocha": "^9.0.1", "sinon": "^13.0.1", "which": "^2.0.2", diff --git a/packages/utils/types/package.json b/packages/utils/types/package.json index 8fbc31ee59..847778ac14 100644 --- a/packages/utils/types/package.json +++ b/packages/utils/types/package.json @@ -9,7 +9,7 @@ "typings": "dist/index.d.ts", "dependencies": { "@electron-forge/async-ora": "6.0.0-beta.68", - "electron-packager": "^17.0.0", + "electron-packager": "^17.1.0", "electron-rebuild": "^3.2.6", "ora": "^5.0.0" }, diff --git a/yarn.lock b/yarn.lock index db16ac366b..433a163613 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1124,6 +1124,14 @@ global-agent "^3.0.0" global-tunnel-ng "^2.7.1" +"@electron/notarize@^1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@electron/notarize/-/notarize-1.2.3.tgz#38056a629e5a0b5fd56c975c4828c0f74285b644" + integrity sha512-9oRzT56rKh5bspk3KpAVF8lPKHYQrBnRwcgiOeR0hdilVEQmszDaAu0IPCPrwwzJN0ugNs0rRboTreHMt/6mBQ== + dependencies: + debug "^4.1.1" + fs-extra "^9.0.1" + "@electron/osx-sign@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@electron/osx-sign/-/osx-sign-1.0.1.tgz#ab4fceded7fed9f2f18c25650f46c1e3a6f17054" @@ -3827,26 +3835,18 @@ electron-installer-snap@^5.1.0: which "^2.0.1" yargs "^15.0.1" -electron-notarize@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/electron-notarize/-/electron-notarize-1.1.1.tgz#3ed274b36158c1beb1dbef14e7faf5927e028629" - integrity sha512-kufsnqh86CTX89AYNG3NCPoboqnku/+32RxeJ2+7A4Rbm4bbOx0Nc7XTy3/gAlBfpj9xPAxHfhZLOHgfi6cJVw== - dependencies: - debug "^4.1.1" - fs-extra "^9.0.1" - -electron-packager@^17.0.0: - version "17.0.0" - resolved "https://registry.yarnpkg.com/electron-packager/-/electron-packager-17.0.0.tgz#09e86734da51049de08b14cee8fc6b2d424efeec" - integrity sha512-dDy/gMR7Zl9t5AOFNIDjX+7T0d6GEifh1o/ciDUUf/fnHpVVNjDG92HsWgToGN/H9CZi5NEdlHWUQ49Wj7TN5g== +electron-packager@^17.1.0: + version "17.1.0" + resolved "https://registry.yarnpkg.com/electron-packager/-/electron-packager-17.1.0.tgz#e9653aa57dc523cdb3e0de7ec1a8e0112a1befec" + integrity sha512-60TBoutfZuAcfJJL1IVWXDZnZ+Yn88HX3UhOLhHbdB/DKA8RAfwXUhSmsWWozh118gbqYRG/WEk9aDL1xVSMKQ== dependencies: "@electron/asar" "^3.2.1" "@electron/get" "^2.0.0" + "@electron/notarize" "^1.2.3" "@electron/osx-sign" "^1.0.1" "@electron/universal" "^1.3.2" cross-spawn-windows-exe "^1.2.0" debug "^4.0.1" - electron-notarize "^1.1.1" extract-zip "^2.0.0" filenamify "^4.1.0" fs-extra "^10.1.0"