Skip to content

Commit 80b5afa

Browse files
feat: Add @electron/windows-sign (#1609)
* feat: Add @electron/windows-sign * Update src/win32.js Co-authored-by: Samuel Attard <[email protected]> --------- Co-authored-by: Samuel Attard <[email protected]>
1 parent ccf6df1 commit 80b5afa

File tree

7 files changed

+112
-8
lines changed

7 files changed

+112
-8
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"@electron/notarize": "^2.1.0",
3131
"@electron/osx-sign": "^1.0.5",
3232
"@electron/universal": "^2.0.1",
33+
"@electron/windows-sign": "^1.0.0",
3334
"cross-spawn-windows-exe": "^1.2.0",
3435
"debug": "^4.0.1",
3536
"extract-zip": "^2.0.0",

src/cli.js

+13
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,19 @@ module.exports = {
6464
args.asar = true
6565
}
6666

67+
// windows-sign: `Object` or `true`
68+
if (args.windowsSign === 'true') {
69+
warning('--windows-sign does not take any arguments, it only has sub-properties (see --help)', args.quiet)
70+
args.windowsSign = true
71+
} else if (typeof args['windows-sign'] === 'object') {
72+
if (Array.isArray(args['windows-sign'])) {
73+
warning('Remove --windows-sign (the bare flag) from the command line, only specify sub-properties (see --help)', args.quiet)
74+
} else {
75+
// Keep kebab case of sub properties
76+
args.windowsSign = args['windows-sign']
77+
}
78+
}
79+
6780
// osx-sign: `Object` or `true`
6881
if (args.osxSign === 'true') {
6982
warning('--osx-sign does not take any arguments, it only has sub-properties (see --help)', args.quiet)

src/index.d.ts

+25-8
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
import { CreateOptions as AsarOptions } from '@electron/asar';
1212
import { ElectronDownloadRequestOptions as ElectronDownloadOptions } from '@electron/get';
1313
import { NotaryToolCredentials } from '@electron/notarize/lib/types';
14-
import { SignOptions } from '@electron/osx-sign/dist/esm/types';
14+
import { SignOptions as OSXInternalSignOptions } from '@electron/osx-sign/dist/esm/types';
15+
import { SignOptions as WindowsInternalSignOptions } from '@electron/windows-sign/dist/esm/types';
1516
import type { makeUniversalApp } from '@electron/universal';
1617

1718
type MakeUniversalOpts = Parameters<typeof makeUniversalApp>[0]
@@ -108,12 +109,12 @@ declare namespace electronPackager {
108109
* @param callback - Must be called once you have completed your actions.
109110
*/
110111
(
111-
buildPath: string,
112-
electronVersion: string,
113-
platform: TargetArch,
114-
arch: TargetArch,
115-
callback: (err?: Error | null) => void
116-
) => void;
112+
buildPath: string,
113+
electronVersion: string,
114+
platform: TargetArch,
115+
arch: TargetArch,
116+
callback: (err?: Error | null) => void
117+
) => void;
117118

118119
type TargetDefinition = {
119120
arch: TargetArch;
@@ -122,7 +123,7 @@ declare namespace electronPackager {
122123
type FinalizePackageTargetsHookFunction = (targets: TargetDefinition[], callback: (err?: Error | null) => void) => void;
123124

124125
/** See the documentation for [`@electron/osx-sign`](https://npm.im/@electron/osx-sign#opts) for details. */
125-
type OsxSignOptions = Omit<SignOptions, 'app' | 'binaries' | 'platform' | 'version'>;
126+
type OsxSignOptions = Omit<OSXInternalSignOptions, 'app' | 'binaries' | 'platform' | 'version'>;
126127

127128
/**
128129
* See the documentation for [`@electron/universal`](https://github.com/electron/universal)
@@ -146,6 +147,14 @@ declare namespace electronPackager {
146147
schemes: string[];
147148
}
148149

150+
/**
151+
* See the documentation for [`@electron/windows-sign`](https://github.com/electron/windows-sign)
152+
* for details.
153+
*/
154+
interface WindowsSignOptions extends Omit<WindowsInternalSignOptions, 'appDirectory'> {
155+
continueOnError?: boolean
156+
}
157+
149158
/**
150159
* A collection of application metadata to embed into the Windows executable.
151160
*
@@ -487,6 +496,14 @@ declare namespace electronPackager {
487496
*
488497
* Defaults to the current working directory.
489498
*/
499+
/**
500+
* If present, signs Windows binary files.
501+
* When the value is `true`, pass default configuration to the signing module. See
502+
* [@electron/windows-sign](https://npm.im/@electron/windows-sign) for sub-option descriptions and
503+
* their defaults.
504+
* @category Windows
505+
*/
506+
windowsSign?: true | WindowsSignOptions;
490507
out?: string;
491508
/**
492509
* Whether to replace an already existing output directory for a given platform (`true`) or

src/win32.js

+37
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const debug = require('debug')('electron-packager')
44
const path = require('path')
55
const { WrapperError } = require('cross-spawn-windows-exe')
6+
const { sign } = require('@electron/windows-sign')
67

78
const App = require('./platform')
89
const common = require('./common')
@@ -98,15 +99,51 @@ class WindowsApp extends App {
9899
}
99100
}
100101

102+
async signAppIfSpecified () {
103+
const windowsSignOpt = this.opts.windowsSign
104+
const windowsMetaData = this.opts.win32metadata
105+
106+
if (windowsSignOpt) {
107+
const signOpts = createSignOpts(windowsSignOpt, windowsMetaData, this.renamedAppPath)
108+
debug(`Running @electron/windows-sign with the options ${JSON.stringify(signOpts)}`)
109+
try {
110+
await sign(signOpts)
111+
} catch (err) {
112+
// Although not signed successfully, the application is packed.
113+
if (signOpts.continueOnError) {
114+
common.warning(`Code sign failed; please retry manually. ${err}`, this.opts.quiet)
115+
} else {
116+
throw err
117+
}
118+
}
119+
}
120+
}
121+
101122
async create () {
102123
await this.initialize()
103124
await this.renameElectron()
104125
await this.copyExtraResources()
105126
await this.runRcedit()
127+
await this.signAppIfSpecified()
106128
return this.move()
107129
}
108130
}
109131

132+
function createSignOpts (properties, windowsMetaData, appDirectory) {
133+
let result = { appDirectory }
134+
135+
if (typeof properties === 'object') {
136+
result = { ...properties, appDirectory }
137+
}
138+
139+
// A little bit of convenience
140+
if (windowsMetaData && windowsMetaData.FileDescription && !result.description) {
141+
result.description = windowsMetaData.FileDescription
142+
}
143+
144+
return result
145+
}
146+
110147
module.exports = {
111148
App: WindowsApp,
112149
updateWineMissingException: updateWineMissingException

test/cli.js

+18
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,24 @@ test('CLI argument: --out without a value is the same as not passing --out', t =
8686
t.is(args.out, null)
8787
})
8888

89+
test('CLI argument: --windows-sign=true', t => {
90+
const args = cli.parseArgs(['--windows-sign=true'])
91+
t.true(args.windowsSign)
92+
})
93+
94+
test('CLI argument: --windows-sign and --windows-sign subproperties should not be mixed', t => {
95+
util.setupConsoleWarnSpy()
96+
cli.parseArgs(['--windows-sign', '--windows-sign.identity=identity'])
97+
util.assertWarning(t, 'WARNING: Remove --windows-sign (the bare flag) from the command line, only specify sub-properties (see --help)')
98+
})
99+
100+
test('CLI argument: --windows-sign is object', t => {
101+
const args = cli.parseArgs([
102+
'--windows-sign.identity=identity'
103+
])
104+
t.is(args.windowsSign.identity, 'identity')
105+
})
106+
89107
test('CLI argument: --protocol with a corresponding --protocol-name', t => {
90108
const args = cli.parseArgs(['--protocol=foo', '--protocol-name=Foo'])
91109
t.deepEqual(args.protocols, [{ schemes: ['foo'], name: 'Foo' }])

usage.txt

+4
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ osx-universal (macOS host platform only, requires --arch=universal) Options
103103
e.g. --osx-universal.mergeASARs="true"
104104
For info on supported values see
105105
https://electron.github.io/packager/main/modules/electronpackager.html#osxuniversaloptions
106+
windows-sign Whether to sign Windows binary files with a codesigning certificate. You can either
107+
pass --windows-sign by itself to use the default configuration or use dot notation to configure
108+
a list of sub-properties, e.g. --windows-sign.certificateFile="C:\cert.pfx".
109+
For info on supported values see https://npm.im/@electron/windows-sign.
106110
protocol URL protocol scheme to register the app as an opener of.
107111
For example, `--protocol=myapp` would register the app to open
108112
URLs such as `myapp://path`. This argument requires a `--protocol-name`

yarn.lock

+14
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,15 @@
333333
minimatch "^9.0.3"
334334
plist "^3.1.0"
335335

336+
"@electron/windows-sign@^1.0.0":
337+
version "1.0.0"
338+
resolved "https://registry.yarnpkg.com/@electron/windows-sign/-/windows-sign-1.0.0.tgz#f08a0a5d4b96840ab637ce11228a59ee8b665287"
339+
integrity sha512-sdkQYAR/TQCEyYgz2jMbusL/ljdj6qA7vyIm/S9HICMAitXhXROFHUOLLgiORj1uiaf2EOB2U33DatGubUuZaQ==
340+
dependencies:
341+
debug "^4.3.4"
342+
fs-extra "^11.1.1"
343+
minimist "^1.2.8"
344+
336345
"@eslint/eslintrc@^0.4.3":
337346
version "0.4.3"
338347
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c"
@@ -3376,6 +3385,11 @@ minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
33763385
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18"
33773386
integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==
33783387

3388+
minimist@^1.2.8:
3389+
version "1.2.8"
3390+
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
3391+
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
3392+
33793393
33803394
version "2.0.0"
33813395
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"

0 commit comments

Comments
 (0)