Skip to content

Commit

Permalink
feat: build.osx.target to specify dmg, zip or both
Browse files Browse the repository at this point in the history
Closes #322
  • Loading branch information
develar committed Apr 21, 2016
1 parent 0ac4596 commit 23df6a1
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 36 deletions.
1 change: 1 addition & 0 deletions docs/Options.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ See all [appdmg options](https://www.npmjs.com/package/appdmg#json-specification
| --- | ---
| icon | <a name="OsXBuildOptions-icon"></a>The path to icon, which will be shown when mounted (default: `build/icon.icns`).
| background | <a name="OsXBuildOptions-background"></a>The path to background (default: `build/background.png`).
| target | <a name="OsXBuildOptions-target"></a>Target package type: list of `default`, `dmg`, `zip`.

<a name="WinBuildOptions"></a>
### `.build.win`
Expand Down
1 change: 0 additions & 1 deletion src/build-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ const cli = cla([
{name: "publish", type: String, alias: "p", description: "Publish artifacts (to GitHub Releases): onTag (on tag push only) or onTagOrDraft (on tag push or if draft release exists)."},
{name: "platform", type: String, multiple: true, description: "darwin, linux, win32 or all. Current platform (" + process.platform + ") by default."},
{name: "arch", type: String, description: "ia32, x64 or all. Defaults to architecture you're running on."},
{name: "target", type: String, multiple: true, description: "Installer or package type."},
{name: "sign", type: String},
{name: "help", alias: "h", type: Boolean, description: "Display this usage guide."},
{name: "appDir", type: String}
Expand Down
47 changes: 31 additions & 16 deletions src/macPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ import { PlatformPackager, BuildInfo } from "./platformPackager"
import { Platform, OsXBuildOptions } from "./metadata"
import * as path from "path"
import { Promise as BluebirdPromise } from "bluebird"
import { log, spawn } from "./util"
import { log, spawn, statOrNull } from "./util"
import { createKeychain, deleteKeychain, CodeSigningInfo, generateKeychainName, sign } from "./codeSign"
import { stat } from "fs-extra-p"
import { path7za } from "7zip-bin"
import deepAssign = require("deep-assign")

//noinspection JSUnusedLocalSymbols
const __awaiter = require("./awaiter")

export default class MacPackager extends PlatformPackager<OsXBuildOptions> {
export default class OsXPackager extends PlatformPackager<OsXBuildOptions> {
codeSigningInfo: Promise<CodeSigningInfo>

readonly target: Array<string>

constructor(info: BuildInfo, cleanupTasks: Array<() => Promise<any>>) {
super(info)

Expand All @@ -25,6 +26,18 @@ export default class MacPackager extends PlatformPackager<OsXBuildOptions> {
else {
this.codeSigningInfo = BluebirdPromise.resolve(null)
}

let target = this.customBuildOptions == null ? null : this.customBuildOptions.target
if (target != null) {
target = Array.isArray(target) ? target : [target]
target = target.map(it => it.toLowerCase().trim())
for (let t of target) {
if (t !== "default" && t !== "dmg" && t !== "zip") {
throw new Error("Unknown target: " + t)
}
}
}
this.target = target == null ? ["default"] : target
}

get platform() {
Expand Down Expand Up @@ -68,13 +81,9 @@ export default class MacPackager extends PlatformPackager<OsXBuildOptions> {

if (this.customBuildOptions == null || !("background" in this.customBuildOptions)) {
const background = path.join(this.buildResourcesDir, "background.png")
try {
if ((await stat(background)).isFile()) {
specification.background = background
}
}
catch (e) {
// ignored
const info = await statOrNull(background)
if (info != null && info.isFile()) {
specification.background = background
}
}

Expand All @@ -84,8 +93,10 @@ export default class MacPackager extends PlatformPackager<OsXBuildOptions> {

packageInDistributableFormat(outDir: string, appOutDir: string, arch: string): Promise<any> {
const artifactPath = path.join(appOutDir, `${this.appName}-${this.metadata.version}.dmg`)
return BluebirdPromise.all([
new BluebirdPromise<any>(async (resolve, reject) => {
const promises: Array<Promise<any>> = []

if (this.target.includes("dmg") || this.target.includes("default")) {
promises.push(new BluebirdPromise<any>(async(resolve, reject) => {
log("Creating DMG")
const emitter = require("appdmg")({
target: artifactPath,
Expand All @@ -95,11 +106,15 @@ export default class MacPackager extends PlatformPackager<OsXBuildOptions> {
emitter.on("error", reject)
emitter.on("finish", () => resolve())
})
.then(() => this.dispatchArtifactCreated(artifactPath, `${this.metadata.name}-${this.metadata.version}.dmg`)),
.then(() => this.dispatchArtifactCreated(artifactPath, `${this.metadata.name}-${this.metadata.version}.dmg`)))
}

if (this.target.includes("zip") || this.target.includes("default")) {
promises.push(this.zipMacApp(appOutDir)
.then(it => this.dispatchArtifactCreated(it, `${this.metadata.name}-${this.metadata.version}-mac.zip`)))
}

this.zipMacApp(appOutDir)
.then(it => this.dispatchArtifactCreated(it, `${this.metadata.name}-${this.metadata.version}-mac.zip`))
])
return BluebirdPromise.all(promises)
}

private zipMacApp(outDir: string): Promise<string> {
Expand Down
9 changes: 7 additions & 2 deletions src/metadata.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export interface Metadata {
readonly repository: string | RepositoryInfo
readonly repository?: string | RepositoryInfo
}

/*
Expand Down Expand Up @@ -138,7 +138,7 @@ export interface BuildMetadata {
*/
readonly compression?: "store" | "normal" | "maximum"

readonly "build-version": string
readonly "build-version"?: string
}

/*
Expand All @@ -156,6 +156,11 @@ export interface OsXBuildOptions extends PlatformSpecificBuildOptions {
The path to background (default: `build/background.png`).
*/
readonly background?: string

/*
Target package type: list of `default`, `dmg`, `zip`.
*/
readonly target?: Array<string>
}

/*
Expand Down
1 change: 0 additions & 1 deletion src/platformPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export interface PackagerOptions {
sign?: string

platform?: Array<Platform>
target?: Array<string>

// deprecated
appDir?: string
Expand Down
31 changes: 19 additions & 12 deletions test/src/helpers/packTester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ if (process.env.TRAVIS !== "true") {
export const outDirName = "dist"

interface AssertPackOptions {
readonly useTempDir?: boolean
readonly tempDirCreated?: (projectDir: string) => Promise<any>
readonly packed?: (projectDir: string) => Promise<any>
readonly expectedContents?: Array<string>
}

export async function assertPack(fixtureName: string, packagerOptions: PackagerOptions, checkOptions?: AssertPackOptions): Promise<void> {
const tempDirCreated = checkOptions == null ? null : checkOptions.tempDirCreated
const useTempDir = tempDirCreated != null || packagerOptions.target != null
const useTempDir = tempDirCreated != null || packagerOptions.devMetadata != null

let projectDir = path.join(__dirname, "..", "..", "fixtures", fixtureName)
// const isDoNotUseTempDir = platform === "darwin"
Expand Down Expand Up @@ -102,7 +103,7 @@ async function packAndCheck(projectDir: string, packagerOptions: PackagerOptions

for (let platform of packagerOptions.platform) {
if (platform === Platform.OSX) {
await checkOsXResult(packager, artifacts.get(Platform.OSX))
await checkOsXResult(packager, checkOptions, artifacts.get(Platform.OSX))
}
else if (platform === Platform.LINUX) {
await checkLinuxResult(projectDir, packager, packagerOptions)
Expand Down Expand Up @@ -165,7 +166,7 @@ function parseDebControl(info: string): any {
return metadata
}

async function checkOsXResult(packager: Packager, artifacts: Array<ArtifactCreated>) {
async function checkOsXResult(packager: Packager, checkOptions: AssertPackOptions, artifacts: Array<ArtifactCreated>) {
const productName = getProductName(packager.metadata, packager.devMetadata)
const packedAppDir = path.join(path.dirname(artifacts[0].file), (productName || packager.metadata.name) + ".app")
const info = parsePlist(await readFile(path.join(packedAppDir, "Contents", "Info.plist"), "utf8"))
Expand All @@ -179,15 +180,21 @@ async function checkOsXResult(packager: Packager, artifacts: Array<ArtifactCreat
const result = await exec("codesign", ["--verify", packedAppDir])
assertThat(result[0].toString()).not.match(/is not signed at all/)

assertThat(artifacts.map(it => path.basename(it.file)).sort()).deepEqual([
`${productName}-1.1.0-mac.zip`,
`${productName}-1.1.0.dmg`,
].sort())

assertThat(artifacts.map(it => it.artifactName).sort()).deepEqual([
"TestApp-1.1.0-mac.zip",
"TestApp-1.1.0.dmg",
].sort())
const actualFiles = artifacts.map(it => path.basename(it.file)).sort()
if (checkOptions != null && checkOptions.expectedContents != null) {
assertThat(actualFiles).deepEqual(checkOptions.expectedContents)
}
else {
assertThat(actualFiles).deepEqual([
`${productName}-1.1.0-mac.zip`,
`${productName}-1.1.0.dmg`,
].sort())

assertThat(artifacts.map(it => it.artifactName).sort()).deepEqual([
"TestApp-1.1.0-mac.zip",
"TestApp-1.1.0.dmg",
].sort())
}
}

async function checkWindowsResult(packager: Packager, packagerOptions: PackagerOptions, checkOptions: AssertPackOptions, artifacts: Array<ArtifactCreated>) {
Expand Down
28 changes: 24 additions & 4 deletions test/src/osxPackagerTest.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import test from "./helpers/avaEx"
import { assertPack, platform, modifyPackageJson } from "./helpers/packTester"
import { Platform } from "out"
import MacPackager from "out/macPackager"
import OsXPackager from "out/macPackager"
import { move } from "fs-extra-p"
import * as path from "path"
import { BuildInfo } from "out/platformPackager"
Expand All @@ -11,12 +11,32 @@ import * as assertThat from "should/as-function"
//noinspection JSUnusedLocalSymbols
const __awaiter = require("out/awaiter")

test.ifOsx("mac: two-package.json", () => assertPack("test-app", {
test.ifOsx("two-package.json", () => assertPack("test-app", {
platform: [Platform.OSX],
arch: "all",
}))

test.ifOsx("mac: one-package.json", () => assertPack("test-app-one", platform(Platform.OSX)))
test.ifOsx("one-package.json", () => assertPack("test-app-one", platform(Platform.OSX)))

function createTargetTest(target: string, expectedContents: Array<string>) {
return () => assertPack("test-app-one", {
platform: [Platform.OSX],
devMetadata: {
build: {
osx: {
target: [target]
}
}
}
}, {
useTempDir: true,
expectedContents: expectedContents
})
}

test.ifOsx("only dmg", createTargetTest("dmg", ["TestApp-1.1.0.dmg"]))
test.ifOsx("only zip", createTargetTest("zip", ["TestApp-1.1.0-mac.zip"]))
test.ifOsx("invalid target", (t: any) => t.throws(createTargetTest("ttt", [])(), "Unknown target: ttt"))

// test.ifOsx("no background", (t: any) => assertPack("test-app-one", platform(Platform.OSX), {
// tempDirCreated: projectDir => deleteFile(path.join(projectDir, "build", "background.png"))
Expand Down Expand Up @@ -46,7 +66,7 @@ test.ifOsx("custom background", () => {
})
})

class CheckingOsXPackager extends MacPackager {
class CheckingOsXPackager extends OsXPackager {
effectiveDistOptions: any

constructor(info: BuildInfo, cleanupTasks: Array<() => Promise<any>>) {
Expand Down

0 comments on commit 23df6a1

Please sign in to comment.