Skip to content

Commit

Permalink
feat: Add @electron/windows-sign (#1609)
Browse files Browse the repository at this point in the history
* feat: Add @electron/windows-sign

* Update src/win32.js

Co-authored-by: Samuel Attard <sam@electronjs.org>

---------

Co-authored-by: Samuel Attard <sam@electronjs.org>
  • Loading branch information
felixrieseberg and MarshallOfSound committed Nov 30, 2023
1 parent ccf6df1 commit 80b5afa
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 8 deletions.
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -30,6 +30,7 @@
"@electron/notarize": "^2.1.0",
"@electron/osx-sign": "^1.0.5",
"@electron/universal": "^2.0.1",
"@electron/windows-sign": "^1.0.0",
"cross-spawn-windows-exe": "^1.2.0",
"debug": "^4.0.1",
"extract-zip": "^2.0.0",
Expand Down
13 changes: 13 additions & 0 deletions src/cli.js
Expand Up @@ -64,6 +64,19 @@ module.exports = {
args.asar = true
}

// windows-sign: `Object` or `true`
if (args.windowsSign === 'true') {
warning('--windows-sign does not take any arguments, it only has sub-properties (see --help)', args.quiet)
args.windowsSign = true
} else if (typeof args['windows-sign'] === 'object') {
if (Array.isArray(args['windows-sign'])) {
warning('Remove --windows-sign (the bare flag) from the command line, only specify sub-properties (see --help)', args.quiet)
} else {
// Keep kebab case of sub properties
args.windowsSign = args['windows-sign']
}
}

// osx-sign: `Object` or `true`
if (args.osxSign === 'true') {
warning('--osx-sign does not take any arguments, it only has sub-properties (see --help)', args.quiet)
Expand Down
33 changes: 25 additions & 8 deletions src/index.d.ts
Expand Up @@ -11,7 +11,8 @@
import { CreateOptions as AsarOptions } from '@electron/asar';
import { ElectronDownloadRequestOptions as ElectronDownloadOptions } from '@electron/get';
import { NotaryToolCredentials } from '@electron/notarize/lib/types';
import { SignOptions } from '@electron/osx-sign/dist/esm/types';
import { SignOptions as OSXInternalSignOptions } from '@electron/osx-sign/dist/esm/types';
import { SignOptions as WindowsInternalSignOptions } from '@electron/windows-sign/dist/esm/types';
import type { makeUniversalApp } from '@electron/universal';

type MakeUniversalOpts = Parameters<typeof makeUniversalApp>[0]
Expand Down Expand Up @@ -108,12 +109,12 @@ declare namespace electronPackager {
* @param callback - Must be called once you have completed your actions.
*/
(
buildPath: string,
electronVersion: string,
platform: TargetArch,
arch: TargetArch,
callback: (err?: Error | null) => void
) => void;
buildPath: string,
electronVersion: string,
platform: TargetArch,
arch: TargetArch,
callback: (err?: Error | null) => void
) => void;

type TargetDefinition = {
arch: TargetArch;
Expand All @@ -122,7 +123,7 @@ declare namespace electronPackager {
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'>;
type OsxSignOptions = Omit<OSXInternalSignOptions, 'app' | 'binaries' | 'platform' | 'version'>;

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

/**
* See the documentation for [`@electron/windows-sign`](https://github.com/electron/windows-sign)
* for details.
*/
interface WindowsSignOptions extends Omit<WindowsInternalSignOptions, 'appDirectory'> {
continueOnError?: boolean
}

/**
* A collection of application metadata to embed into the Windows executable.
*
Expand Down Expand Up @@ -487,6 +496,14 @@ declare namespace electronPackager {
*
* Defaults to the current working directory.
*/
/**
* If present, signs Windows binary files.
* When the value is `true`, pass default configuration to the signing module. See
* [@electron/windows-sign](https://npm.im/@electron/windows-sign) for sub-option descriptions and
* their defaults.
* @category Windows
*/
windowsSign?: true | WindowsSignOptions;
out?: string;
/**
* Whether to replace an already existing output directory for a given platform (`true`) or
Expand Down
37 changes: 37 additions & 0 deletions src/win32.js
Expand Up @@ -3,6 +3,7 @@
const debug = require('debug')('electron-packager')
const path = require('path')
const { WrapperError } = require('cross-spawn-windows-exe')
const { sign } = require('@electron/windows-sign')

const App = require('./platform')
const common = require('./common')
Expand Down Expand Up @@ -98,15 +99,51 @@ class WindowsApp extends App {
}
}

async signAppIfSpecified () {
const windowsSignOpt = this.opts.windowsSign
const windowsMetaData = this.opts.win32metadata

if (windowsSignOpt) {
const signOpts = createSignOpts(windowsSignOpt, windowsMetaData, this.renamedAppPath)
debug(`Running @electron/windows-sign with the options ${JSON.stringify(signOpts)}`)
try {
await sign(signOpts)
} catch (err) {
// Although not signed successfully, the application is packed.
if (signOpts.continueOnError) {
common.warning(`Code sign failed; please retry manually. ${err}`, this.opts.quiet)
} else {
throw err
}
}
}
}

async create () {
await this.initialize()
await this.renameElectron()
await this.copyExtraResources()
await this.runRcedit()
await this.signAppIfSpecified()
return this.move()
}
}

function createSignOpts (properties, windowsMetaData, appDirectory) {
let result = { appDirectory }

if (typeof properties === 'object') {
result = { ...properties, appDirectory }
}

// A little bit of convenience
if (windowsMetaData && windowsMetaData.FileDescription && !result.description) {
result.description = windowsMetaData.FileDescription
}

return result
}

module.exports = {
App: WindowsApp,
updateWineMissingException: updateWineMissingException
Expand Down
18 changes: 18 additions & 0 deletions test/cli.js
Expand Up @@ -86,6 +86,24 @@ test('CLI argument: --out without a value is the same as not passing --out', t =
t.is(args.out, null)
})

test('CLI argument: --windows-sign=true', t => {
const args = cli.parseArgs(['--windows-sign=true'])
t.true(args.windowsSign)
})

test('CLI argument: --windows-sign and --windows-sign subproperties should not be mixed', t => {
util.setupConsoleWarnSpy()
cli.parseArgs(['--windows-sign', '--windows-sign.identity=identity'])
util.assertWarning(t, 'WARNING: Remove --windows-sign (the bare flag) from the command line, only specify sub-properties (see --help)')
})

test('CLI argument: --windows-sign is object', t => {
const args = cli.parseArgs([
'--windows-sign.identity=identity'
])
t.is(args.windowsSign.identity, 'identity')
})

test('CLI argument: --protocol with a corresponding --protocol-name', t => {
const args = cli.parseArgs(['--protocol=foo', '--protocol-name=Foo'])
t.deepEqual(args.protocols, [{ schemes: ['foo'], name: 'Foo' }])
Expand Down
4 changes: 4 additions & 0 deletions usage.txt
Expand Up @@ -103,6 +103,10 @@ osx-universal (macOS host platform only, requires --arch=universal) Options
e.g. --osx-universal.mergeASARs="true"
For info on supported values see
https://electron.github.io/packager/main/modules/electronpackager.html#osxuniversaloptions
windows-sign Whether to sign Windows binary files with a codesigning certificate. You can either
pass --windows-sign by itself to use the default configuration or use dot notation to configure
a list of sub-properties, e.g. --windows-sign.certificateFile="C:\cert.pfx".
For info on supported values see https://npm.im/@electron/windows-sign.
protocol URL protocol scheme to register the app as an opener of.
For example, `--protocol=myapp` would register the app to open
URLs such as `myapp://path`. This argument requires a `--protocol-name`
Expand Down
14 changes: 14 additions & 0 deletions yarn.lock
Expand Up @@ -333,6 +333,15 @@
minimatch "^9.0.3"
plist "^3.1.0"

"@electron/windows-sign@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@electron/windows-sign/-/windows-sign-1.0.0.tgz#f08a0a5d4b96840ab637ce11228a59ee8b665287"
integrity sha512-sdkQYAR/TQCEyYgz2jMbusL/ljdj6qA7vyIm/S9HICMAitXhXROFHUOLLgiORj1uiaf2EOB2U33DatGubUuZaQ==
dependencies:
debug "^4.3.4"
fs-extra "^11.1.1"
minimist "^1.2.8"

"@eslint/eslintrc@^0.4.3":
version "0.4.3"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c"
Expand Down Expand Up @@ -3376,6 +3385,11 @@ minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18"
integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==

minimist@^1.2.8:
version "1.2.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==

ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
Expand Down

0 comments on commit 80b5afa

Please sign in to comment.