diff --git a/.idea/dictionaries/develar.xml b/.idea/dictionaries/develar.xml index a62216d6c60..b1c442d8da3 100644 --- a/.idea/dictionaries/develar.xml +++ b/.idea/dictionaries/develar.xml @@ -24,6 +24,7 @@ lzma makedeb mkdirp + mpass nokeys nomacver noninteractive diff --git a/docs/Code Signing.md b/docs/Code Signing.md index b0c8bb27287..a64ed321acb 100644 --- a/docs/Code Signing.md +++ b/docs/Code Signing.md @@ -30,4 +30,4 @@ travis encrypt 'CSC_KEY_PASSWORD=beAwareAboutBashEscaping!!!' --add # Where to buy certificate [StartSSL](https://startssl.com/Support?v=34) is recommended. -It can be used to sign OS X app also, so, you don't need to buy Apple Certificate in addition (please note, it works, but we are waiting official confirmation). \ No newline at end of file +It can be used to sign OS X app also, so, you don't need to buy Apple Certificate in addition. \ No newline at end of file diff --git a/package.json b/package.json index ac4f01b1122..4687220b605 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "globby": "^4.0.0", "hosted-git-info": "^2.1.4", "image-size": "^0.5.0", - "lodash.template": "^4.2.4", + "lodash.template": "^4.2.5", "mime": "^1.3.4", "progress": "^1.1.8", "progress-stream": "^1.2.0", diff --git a/src/osxPackager.ts b/src/osxPackager.ts index ad4eedea11f..93f45e80c66 100644 --- a/src/osxPackager.ts +++ b/src/osxPackager.ts @@ -2,7 +2,7 @@ import { PlatformPackager, BuildInfo, normalizeTargets } from "./platformPackage import { Platform, OsXBuildOptions, MasBuildOptions } from "./metadata" import * as path from "path" import { Promise as BluebirdPromise } from "bluebird" -import { log, debug, debug7z, spawn, statOrNull } from "./util" +import { log, debug, debug7z, spawn, statOrNull, warn } from "./util" import { createKeychain, deleteKeychain, CodeSigningInfo, generateKeychainName } from "./codeSign" import { path7za } from "7zip-bin" import deepAssign = require("deep-assign") @@ -82,11 +82,15 @@ export default class OsXPackager extends PlatformPackager { const identity = codeSigningInfo.name if (identity == null) { - log("App is not signed: CSC_LINK or CSC_NAME are not specified") + const message = "App is not signed: CSC_LINK or CSC_NAME are not specified, see https://github.com/electron-userland/electron-builder/wiki/Code-Signing" + if (masOptions != null) { + throw new Error(message) + } + warn(message) return } - log(`Signing app (${identity})`) + log(`Signing app (identity: ${identity})`) const baseSignOptions: BaseSignOptions = { app: path.join(appOutDir, this.appName + ".app"), diff --git a/src/util.ts b/src/util.ts index 3a59cb28e31..9e869470d9b 100644 --- a/src/util.ts +++ b/src/util.ts @@ -17,7 +17,7 @@ export const debug: Debugger = debugFactory("electron-builder") export const debug7z: Debugger = debugFactory("electron-builder:7z") export function warn(message: string) { - console.warn(yellow(message)) + console.warn(yellow(`Warning: ${message}`)) } const DEFAULT_APP_DIR_NAMES = ["app", "www"] diff --git a/src/winPackager.ts b/src/winPackager.ts index 611b134ea8d..ccb9938cad9 100644 --- a/src/winPackager.ts +++ b/src/winPackager.ts @@ -3,8 +3,8 @@ import { Promise as BluebirdPromise } from "bluebird" import { PlatformPackager, BuildInfo } from "./platformPackager" import { Platform, WinBuildOptions } from "./metadata" import * as path from "path" -import { log, statOrNull } from "./util" -import { readFile, deleteFile, rename, copy, emptyDir, writeFile, open, close, read, move } from "fs-extra-p" +import { log, statOrNull, warn } from "./util" +import { deleteFile, rename, emptyDir, open, close, read, move } from "fs-extra-p" import { sign } from "signcode-tf" import ElectronPackagerOptions = ElectronPackager.ElectronPackagerOptions @@ -52,6 +52,10 @@ export class WinPackager extends PlatformPackager { } async pack(outDir: string, arch: string, postAsyncTasks: Array>): Promise { + if (arch === "ia32") { + warn("For windows consider only distributing 64-bit, see https://github.com/electron-userland/electron-builder/issues/359#issuecomment-214851130") + } + // we must check icon before pack because electron-packager uses icon and it leads to cryptic error message "spawn wine ENOENT" await this.iconPath @@ -64,7 +68,7 @@ export class WinPackager extends PlatformPackager { } const unpackedDir = path.join(outDir, `win${arch === "x64" ? "" : `-${arch}`}-unpacked`) - const finalAppOut = path.join(outDir, `win${arch === "x64" ? "" : `-${arch}`}-unpacked`, "lib", "net45") + const finalAppOut = path.join(unpackedDir, "lib", "net45") const installerOut = computeDistOut(outDir, arch) log("Removing %s and %s", path.relative(this.projectDir, installerOut), path.relative(this.projectDir, unpackedDir)) await BluebirdPromise.all([ @@ -166,38 +170,13 @@ export class WinPackager extends PlatformPackager { const version = this.metadata.version const archSuffix = arch === "x64" ? "" : ("-" + arch) - const releasesFile = path.join(installerOutDir, "RELEASES") - const nupkgVersion = winstaller.convertVersion(version) - const nupkgPathOriginal = `${this.metadata.name}-${nupkgVersion}-full.nupkg` - const nupkgPathWithArch = `${this.metadata.name}-${nupkgVersion}${archSuffix}-full.nupkg` - - async function changeFileNameInTheReleasesFile(): Promise { - const data = (await readFile(releasesFile, "utf8")).replace(new RegExp(" " + nupkgPathOriginal + " ", "g"), " " + nupkgPathWithArch + " ") - await writeFile(releasesFile, data) - } - - const promises: Array> = [ - rename(path.join(installerOutDir, "Setup.exe"), path.join(installerOutDir, `${this.appName} Setup ${version}${archSuffix}.exe`)) - .then(it => this.dispatchArtifactCreated(it, `${this.metadata.name}-Setup-${version}${archSuffix}.exe`)), - ] + const nupkgPath = `${this.metadata.name}-${winstaller.convertVersion(version)}-full.nupkg` - if (archSuffix === "") { - this.dispatchArtifactCreated(path.join(installerOutDir, nupkgPathOriginal)) - this.dispatchArtifactCreated(path.join(installerOutDir, "RELEASES")) - } - else { - promises.push( - rename(path.join(installerOutDir, nupkgPathOriginal), path.join(installerOutDir, nupkgPathWithArch)) - .then(it => this.dispatchArtifactCreated(it)) - ) - promises.push( - changeFileNameInTheReleasesFile() - .then(() => copy(releasesFile, path.join(installerOutDir, "RELEASES-ia32"))) - .then(it => this.dispatchArtifactCreated(it)) - ) - } + this.dispatchArtifactCreated(path.join(installerOutDir, nupkgPath)) + this.dispatchArtifactCreated(path.join(installerOutDir, "RELEASES")) - await BluebirdPromise.all(promises) + await rename(path.join(installerOutDir, "Setup.exe"), path.join(installerOutDir, `${this.appName} Setup ${version}${archSuffix}.exe`)) + .then(it => this.dispatchArtifactCreated(it, `${this.metadata.name}-Setup-${version}${archSuffix}.exe`)) } } diff --git a/test/src/helpers/avaEx.ts b/test/src/helpers/avaEx.ts index 41ed600fa07..b3e88200e48 100644 --- a/test/src/helpers/avaEx.ts +++ b/test/src/helpers/avaEx.ts @@ -6,6 +6,7 @@ declare module "ava-tf" { export const ifOsx: typeof test; export const ifNotCi: typeof test; export const ifNotCiOsx: typeof test; + export const ifDevOrWinCi: typeof test; export const ifNotTravis: typeof test; } @@ -39,6 +40,11 @@ Object.defineProperties(test, { get: function () { return process.platform === "darwin" ? this : this.skip } + }, + "ifDevOrWinCi": { + get: function () { + return !process.env.CI || process.platform === "win32" ? this : this.skip + } } }) diff --git a/test/src/helpers/packTester.ts b/test/src/helpers/packTester.ts index 3b82980a6a5..bd23edde2ef 100755 --- a/test/src/helpers/packTester.ts +++ b/test/src/helpers/packTester.ts @@ -60,10 +60,6 @@ export async function assertPack(fixtureName: string, packagerOptions: PackagerO await packAndCheck(projectDir, Object.assign({ projectDir: projectDir, - cscLink: CSC_LINK, - cscKeyPassword: CSC_KEY_PASSWORD, - cscInstallerLink: CSC_INSTALLER_LINK, - cscInstallerKeyPassword: CSC_INSTALLER_KEY_PASSWORD, dist: true, }, packagerOptions), checkOptions) @@ -206,7 +202,7 @@ async function checkWindowsResult(packager: Packager, packagerOptions: PackagerO function getWinExpected(archSuffix: string) { return [ - `RELEASES${archSuffix}`, + `RELEASES`, `${productName} Setup 1.1.0${archSuffix}.exe`, `TestApp-1.1.0${archSuffix}-full.nupkg`, ] @@ -221,16 +217,9 @@ async function checkWindowsResult(packager: Packager, packagerOptions: PackagerO return } - let i = filenames.indexOf("RELEASES-ia32") - if (i !== -1) { - assertThat((await readFile(artifacts[i].file, "utf8")).indexOf("ia32")).not.equal(-1) - } - - if (archSuffix == "") { - const expectedArtifactNames = expected.slice() - expectedArtifactNames[1] = `TestAppSetup-1.1.0${archSuffix}.exe` - assertThat(artifacts.map(it => it.artifactName).filter(it => it != null)).deepEqual([`TestApp-Setup-1.1.0${archSuffix}.exe`]) - } + const expectedArtifactNames = expected.slice() + expectedArtifactNames[1] = `TestAppSetup-1.1.0${archSuffix}.exe` + assertThat(artifacts.map(it => it.artifactName).filter(it => it != null)).deepEqual([`TestApp-Setup-1.1.0${archSuffix}.exe`]) const packageFile = path.join(path.dirname(artifacts[0].file), `TestApp-1.1.0${archSuffix}-full.nupkg`) const unZipper = new DecompressZip(packageFile) @@ -292,4 +281,12 @@ export function platform(platform: Platform): PackagerOptions { return { platform: [platform] } +} + +export function signed(packagerOptions: PackagerOptions): PackagerOptions { + packagerOptions.cscLink = CSC_LINK + packagerOptions.cscKeyPassword = CSC_KEY_PASSWORD + packagerOptions.cscInstallerLink = CSC_INSTALLER_LINK + packagerOptions.cscInstallerKeyPassword = CSC_INSTALLER_KEY_PASSWORD + return packagerOptions } \ No newline at end of file diff --git a/test/src/osxPackagerTest.ts b/test/src/osxPackagerTest.ts index 7a5a1d0c3ba..e7229b75a8c 100644 --- a/test/src/osxPackagerTest.ts +++ b/test/src/osxPackagerTest.ts @@ -1,10 +1,10 @@ import test from "./helpers/avaEx" -import { assertPack, platform, modifyPackageJson } from "./helpers/packTester" +import { assertPack, platform, modifyPackageJson, signed } from "./helpers/packTester" import { Platform } from "out" import OsXPackager from "out/osxPackager" import { move, writeFile } from "fs-extra-p" import * as path from "path" -import { BuildInfo } from "out/platformPackager" +import { BuildInfo, PackagerOptions } from "out/platformPackager" import { Promise as BluebirdPromise } from "bluebird" import * as assertThat from "should/as-function" import ElectronPackagerOptions = ElectronPackager.ElectronPackagerOptions @@ -14,15 +14,15 @@ import { SignOptions, FlatOptions } from "electron-osx-sign-tf" //noinspection JSUnusedLocalSymbols const __awaiter = require("out/awaiter") -test.ifOsx("two-package", () => assertPack("test-app", { +test.ifOsx("two-package", () => assertPack("test-app", signed({ platform: [Platform.OSX], arch: "all", -})) +}))) -test.ifOsx("one-package", () => assertPack("test-app-one", platform(Platform.OSX))) +test.ifOsx("one-package", () => assertPack("test-app-one", signed(platform(Platform.OSX)))) function createTargetTest(target: Array, expectedContents: Array) { - const options = { + let options: PackagerOptions = { platform: [Platform.OSX], devMetadata: { build: { @@ -32,6 +32,10 @@ function createTargetTest(target: Array, expectedContents: Array } } } + if (target.includes("mas")) { + options = signed(options) + } + return () => assertPack("test-app-one", options, { expectedContents: expectedContents }) @@ -49,8 +53,6 @@ test.ifOsx("custom mas", () => { return assertPack("test-app-one", { platform: [Platform.OSX], platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingOsXPackager(packager, cleanupTasks), - cscLink: null, - cscInstallerLink: null, devMetadata: { build: { osx: { @@ -84,8 +86,6 @@ test.ifOsx("identity in package.json", () => { return assertPack("test-app-one", { platform: [Platform.OSX], platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingOsXPackager(packager, cleanupTasks), - cscLink: null, - cscInstallerLink: null, devMetadata: { build: { osx: { @@ -112,8 +112,6 @@ test.ifOsx("entitlements in build dir", () => { return assertPack("test-app-one", { platform: [Platform.OSX], platformPackagerFactory: (packager, platform, cleanupTasks) => platformPackager = new CheckingOsXPackager(packager, cleanupTasks), - cscLink: null, - cscInstallerLink: null, devMetadata: { build: { osx: { diff --git a/test/src/winPackagerTest.ts b/test/src/winPackagerTest.ts index c92ca8b7bb0..f48d59d0c04 100755 --- a/test/src/winPackagerTest.ts +++ b/test/src/winPackagerTest.ts @@ -1,6 +1,6 @@ import { Platform } from "out" import test from "./helpers/avaEx" -import { assertPack, platform, modifyPackageJson } from "./helpers/packTester" +import { assertPack, platform, modifyPackageJson, signed } from "./helpers/packTester" import { move, outputFile } from "fs-extra-p" import * as path from "path" import { WinPackager, computeDistOut } from "out/winPackager" @@ -12,7 +12,7 @@ import ElectronPackagerOptions = ElectronPackager.ElectronPackagerOptions //noinspection JSUnusedLocalSymbols const __awaiter = require("out/awaiter") -test.ifNotCiOsx("win", () => assertPack("test-app-one", platform(Platform.WINDOWS), +test.ifNotCiOsx("win", () => assertPack("test-app-one", signed(platform(Platform.WINDOWS)), { tempDirCreated: process.env.TEST_DELTA ? it => modifyPackageJson(it, data => { data.build.win = { @@ -22,17 +22,15 @@ test.ifNotCiOsx("win", () => assertPack("test-app-one", platform(Platform.WINDOW } )) -test.ifNotCiOsx("win f", () => { +test.ifDevOrWinCi("win f", () => { const metadata: any = { version: "3.0.0-beta.2" } return assertPack("test-app-one", { - platform: [Platform.WINDOWS], - cscLink: null, - cscInstallerLink: null, - devMetadata: metadata - }, { + platform: [Platform.WINDOWS], + devMetadata: metadata + }, { expectedArtifacts: [ "RELEASES", "TestApp Setup 3.0.0-beta.2.exe",