Repository: electron/electron-packager
Pull request #1437 (2022-10-27 23:27:28)

feat: add new afterFinalizePackageTargets hook
Ref: https://github.com/electron/forge/pull/3006

codecov[bot]: # [Codecov](https://codecov.io/gh/electron/electron-packager/pull/1437?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=electron) Report
> Merging [#1437](https://codecov.io/gh/electron/electron-packager/pull/1437?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=electron) (9c5e647) into [main](https://codecov.io/gh/electron/electron-packager/commit/5aac8c91ba6dda634f5af0c1d163a74002f63791?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=electron) (5aac8c9) will **increase** coverage by `0.13%`.
> The diff coverage is `100.00%`.

```diff
@@            Coverage Diff             @@
##             main    #1437      +/-   ##
==========================================
+ Coverage   95.41%   95.54%   +0.13%     
==========================================
  Files          15       15              
  Lines         785      786       +1     
==========================================
+ Hits          749      751       +2     
+ Misses         36       35       -1     
```


| [Impacted Files](https://codecov.io/gh/electron/electron-packager/pull/1437?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=electron) | Coverage Δ | |
|---|---|---|
| [src/index.js](https://codecov.io/gh/electron/electron-packager/pull/1437/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=electron#diff-c3JjL2luZGV4Lmpz) | `98.95% <100.00%> (+0.01%)` | :arrow_up: |
| [src/copy-filter.js](https://codecov.io/gh/electron/electron-packager/pull/1437/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=electron#diff-c3JjL2NvcHktZmlsdGVyLmpz) | `100.00% <0.00%> (+2.04%)` | :arrow_up: |

:mega: We’re building smart automated test selection to slash your CI/CD build times. [Learn more](https://about.codecov.io/iterative-testing/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=electron)

malept: 🚲🏚️ hook name:

- success
- complete
- allDone

Something along those lines.
MarshallOfSound: @malept this hook is called before any packaging is actually done
malept: > this hook is called before any packaging is actually done
 Hrm, I misread the Forge issue. `afterTargetCalculation` or something similar?


Patch:
diff --git a/NEWS.md b/NEWS.md
index c5915bb..ebc477c 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -7,6 +7,7 @@
 ### Changed
 
 * Replaced `electron-notarize` with `@electron/notarize`.  The configuration options are unchanged. This migration is purely cosmetic.
+* Added new `afterFinalizePackageTargets` hook. This hook exposes the platform/arch combinations that are being packaged when the `arch:all` or `platform:all` options are set.
 
 ## [17.0.0]
 
diff --git a/src/index.d.ts b/src/index.d.ts
index 857ea3e..04bcca9 100644
--- a/src/index.d.ts
+++ b/src/index.d.ts
@@ -121,6 +121,12 @@ declare namespace electronPackager {
     callback: (err?: Error | null) => void
   ) => void;
 
+  type TargetDefinition = {
+    arch: TargetArch;
+    platform: TargetPlatform;
+  }
+  type FinalizePackageTargetsHookFunction = (targets: TargetDefinition[], callback: (err?: Error | null) => void) => void;
+
   /** See the documentation for [`@electron/osx-sign`](https://npm.im/@electron/osx-sign#opts) for details. */
   type OsxSignOptions = Omit<SignOptions, 'app' | 'binaries' | 'platform' | 'version'>;
 
@@ -204,6 +210,11 @@ declare namespace electronPackager {
     afterCopyExtraResources?: HookFunction[];
     /** Functions to be called after the prebuilt Electron binary has been extracted to a temporary directory. */
     afterExtract?: HookFunction[];
+    /**
+     * Functions to be called after the final matrix of platform/arch combination is determined.  Use this to
+     * learn what archs/platforms packager is targetting when you pass "all" as a value.
+     */
+    afterFinalizePackageTargets?: FinalizePackageTargetsHookFunction[];
     /**
      * Functions to be called after Node module pruning has been applied to the application.
      *
diff --git a/src/index.js b/src/index.js
index bab5fa9..d4e0411 100644
--- a/src/index.js
+++ b/src/index.js
@@ -198,6 +198,7 @@ module.exports = async function packager (opts) {
 
   copyFilter.populateIgnoredPaths(opts)
 
+  await hooks.promisifyHooks(opts.afterFinalizePackageTargets, [targets.createPlatformArchPairs(opts, platforms, archs).map(([platform, arch]) => ({ platform, arch }))])
   const appPaths = await packageAllSpecifiedCombos(opts, archs, platforms)
   // Remove falsy entries (e.g. skipped platforms)
   return appPaths.filter(appPath => appPath)


Test patch:
diff --git a/test/hooks.js b/test/hooks.js
index 7ad9348..0f4e931 100644
--- a/test/hooks.js
+++ b/test/hooks.js
@@ -6,19 +6,24 @@ const packager = require('..')
 const test = require('ava')
 const util = require('./_util')
 
-async function hookTest (wantHookCalled, hookName, t, opts) {
+async function hookTest (wantHookCalled, hookName, t, opts, validator) {
   let hookCalled = false
   opts.dir = util.fixtureSubdir('basic')
   opts.electronVersion = config.version
   opts.arch = 'ia32'
   opts.platform = 'all'
 
-  opts[hookName] = [(buildPath, electronVersion, platform, arch, callback) => {
-    hookCalled = true
-    t.is(electronVersion, opts.electronVersion, `${hookName} electronVersion should be the same as the options object`)
-    t.is(arch, opts.arch, `${hookName} arch should be the same as the options object`)
-    callback()
-  }]
+  opts[hookName] = [validator
+    ? (...args) => {
+      hookCalled = true
+      validator(t, ...args)
+    }
+    : (buildPath, electronVersion, platform, arch, callback) => {
+      hookCalled = true
+      t.is(electronVersion, opts.electronVersion, `${hookName} electronVersion should be the same as the options object`)
+      t.is(arch, opts.arch, `${hookName} arch should be the same as the options object`)
+      callback()
+    }]
 
   // 2 packages will be built during this test
   const finalPaths = await packager(opts)
@@ -28,12 +33,20 @@ async function hookTest (wantHookCalled, hookName, t, opts) {
   t.deepEqual(exists, [true, true], 'Packages should be generated for both 32-bit platforms')
 }
 
-function createHookTest (hookName) {
-  return util.packagerTest(async (t, opts) => hookTest(true, hookName, t, opts))
+function createHookTest (hookName, validator) {
+  return util.packagerTest(async (t, opts) => hookTest(true, hookName, t, opts, validator))
 }
 
 test.serial('platform=all (one arch) for beforeCopy hook', createHookTest('beforeCopy'))
 test.serial('platform=all (one arch) for afterCopy hook', createHookTest('afterCopy'))
+test.serial('platform=all (one arch) for afterFinalizePackageTargets hook', createHookTest('afterFinalizePackageTargets', (t, targets, callback) => {
+  t.is(targets.length, 2, 'target list should have two items')
+  t.is(targets[0].arch, 'ia32')
+  t.is(targets[0].platform, 'linux')
+  t.is(targets[1].arch, 'ia32')
+  t.is(targets[1].platform, 'win32')
+  callback()
+}))
 test.serial('platform=all (one arch) for afterPrune hook', createHookTest('afterPrune'))
 test.serial('platform=all (one arch) for afterExtract hook', createHookTest('afterExtract'))
 test.serial('platform=all (one arch) for afterComplete hook', createHookTest('afterComplete'))
diff --git a/test/index.test-d.ts b/test/index.test-d.ts
index a7fe94b..4497a5d 100644
--- a/test/index.test-d.ts
+++ b/test/index.test-d.ts
@@ -11,6 +11,9 @@ function completeFunction(
   callbackFn();
 }
 
+// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
+function finalizePackageTargetsFunction(targets: { arch: string; platform: string }[]): void {}
+
 // eslint-disable-next-line @typescript-eslint/no-unused-vars
 function ignoreFunction(path: string): boolean {
   return true;
@@ -90,6 +93,7 @@ await packager({
   afterCopy: [completeFunction],
   afterCopyExtraResources: [completeFunction],
   afterExtract: [completeFunction],
+  afterFinalizePackageTargets: [finalizePackageTargetsFunction],
   afterPrune: [completeFunction],
   beforeAsar: [completeFunction],
   beforeCopy: [completeFunction],