Skip to content

Commit

Permalink
feat: use self-containe fpm on OS X — don't need to install ruby anymore
Browse files Browse the repository at this point in the history
  • Loading branch information
develar committed May 4, 2016
1 parent d77c8da commit e7cee5e
Show file tree
Hide file tree
Showing 16 changed files with 109 additions and 27 deletions.
1 change: 0 additions & 1 deletion .idea/libraries/electron_builder_for_tests.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/runConfigurations/linuxPackagerTest.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ env:
- NODE_VERSION=4
- NODE_VERSION=6

language: ruby
language: c

cache:
apt: true
bundler: true
directories:
- node_modules
- test/testApp/node_modules
- $HOME/.electron
- $HOME/.npm

addons:
apt:
Expand All @@ -33,16 +34,15 @@ before_install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install gnu-tar dpkg libicns graphicsmagick git-lfs; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then git lfs pull; fi
- gem install --no-rdoc --no-ri fpm
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then test/install-linux-dependencies.sh; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then curl -L https://github.com/github/git-lfs/releases/download/v1.2.0/git-lfs-linux-amd64-1.2.0.tar.gz | tar -xz; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then git-lfs-1.2.0/git-lfs pull; fi

install:
- nvm install $NODE_VERSION
- npm install npm -g
- npm prune
- npm install
- npm prune

script:
- npm run test
Expand Down
3 changes: 1 addition & 2 deletions docs/Multi Platform Build.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ brew install Caskroom/cask/xquartz wine mono

To build app in distributable format for Linux on OS X:
```
brew install ruby gnu-tar libicns graphicsmagick
gem install fpm
brew install gnu-tar libicns graphicsmagick
```

## Linux
Expand Down
20 changes: 14 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"test": "node ./test/out/helpers/runTests.js",
"semantic-release": "semantic-release pre && npm publish && semantic-release post",
"//": "Update wiki if docs changed. Update only if functionalily are generally available (latest release, not next)",
"update-wiki": "git subtree split -b wiki --prefix docs/ && git push wiki wiki:master"
"update-wiki": "git subtree split -b wiki --prefix docs/ && git push wiki wiki:master",
"whitespace": "whitespace src/*.ts"
},
"repository": {
"type": "git",
Expand Down Expand Up @@ -64,7 +65,7 @@
"electron-osx-sign-tf": "~0.5.0-beta.0",
"electron-packager-tf": "^7.0.2-beta.0",
"electron-winstaller-fixed": "~2.4.0-beta.1",
"fs-extra-p": "^1.0.0",
"fs-extra-p": "^1.0.1",
"globby": "^4.0.0",
"hosted-git-info": "^2.1.4",
"image-size": "^0.5.0",
Expand All @@ -76,15 +77,18 @@
"signcode-tf": "^0.5.0",
"source-map-support": "^0.4.0",
"tmp": "0.0.28",
"typescript": "^1.9.0-dev.20160502"
"typescript": "^1.9.0-dev.20160503"
},
"optionalDependencies": {
"appdmg-tf": "^0.3.11"
},
"config": {
"pre-git": {
"commit-msg": "conventional"
}
},
"pre-commit": [
"npm run whitespace"
]
},
"devDependencies": {
"ava-tf": "^0.12.4-beta.6",
Expand All @@ -102,7 +106,8 @@
"ts-babel": "^0.8.6",
"tsconfig-glob": "^0.4.3",
"tslint": "next",
"typescript": "^1.9.0-dev.20160414"
"typescript": "^1.9.0-dev.20160414",
"whitespace": "^2.0.0"
},
"babel": {
"plugins": [
Expand All @@ -118,5 +123,8 @@
"test/out/*"
]
},
"typings": "./out/electron-builder.d.ts"
"typings": "./out/electron-builder.d.ts",
"publishConfig": {
"tag": "next"
}
}
2 changes: 1 addition & 1 deletion src/build-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ if (args.help) {
}
else {
if (args.appDir) {
warn(`-appDir CLI parameter is deprecated, please configure build.directories.app instead
warn(`-appDir CLI parameter is deprecated, please configure build.directories.app instead
See https://github.com/electron-userland/electron-builder/wiki/Options#MetadataDirectories-app`)
}

Expand Down
6 changes: 3 additions & 3 deletions src/errorMessages.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const buildIsMissed = `Please specify 'build' configuration in the development package.json ('%s'), at least
build: {
"app-bundle-id": "your.id",
"app-category-type": "your.app.category.type",
Expand All @@ -14,11 +14,11 @@ export const authorEmailIsMissed = `Please specify author 'email' in the applica
See https://docs.npmjs.com/files/package.json#people-fields-author-contributors
It is required to set Linux .deb package maintainer. Or you can set maintainer in the custom linux options.
It is required to set Linux .deb package maintainer. Or you can set maintainer in the custom linux options.
(see https://github.com/electron-userland/electron-builder#distributable-format-configuration).
`

export const buildInAppSpecified = `'build' in the application package.json ('%s') is not supported since 3.0 anymore
export const buildInAppSpecified = `'build' in the application package.json ('%s') is not supported since 3.0 anymore
Please move 'build' into the development package.json ('%s')
`
59 changes: 59 additions & 0 deletions src/fpmDownload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { statOrNull, spawn, debug } from "./util"
import { emptyDir, move, remove } from "fs-extra-p"
import { download } from "./httpRequest"
import { path7za } from "7zip-bin"
import * as path from "path"
import { tmpdir } from "os"
import { Promise as BluebirdPromise } from "bluebird"

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

let tmpDirCounter = 0

function getTempName(prefix?: string | n): string {
return `${prefix == null ? "" : prefix + "-"}${process.pid}-${tmpDirCounter++}-${Date.now()}`
}

const versionToPromise = new Map<string, BluebirdPromise<string>>()

// can be called in parallel, all calls for the same version will get the same promise - will be downloaded only once
export function downloadFpm(version: string): Promise<string> {
let promise = versionToPromise.get(version)
// if rejected, we will try to download again
if (<any>promise != null && !promise!.isRejected()) {
return promise!
}

promise = <BluebirdPromise<string>>doDownloadFpm(version)
versionToPromise.set(version, promise)
return promise
}

async function doDownloadFpm(version: string): Promise<string> {
const dirName = `fpm-${version}-osx`
const url = `https://github.com/develar/fpm-self-contained/releases/download/v${version}/${dirName}.7z`
const cache = path.join(__dirname, "..", "node_modules", ".fpm")
const fpmDir = path.join(cache, dirName)

const stat = await statOrNull(fpmDir)
if (stat != null && stat.isDirectory()) {
return path.join(fpmDir, "fpm")
}

// the only version currently supported (i.e. all clients are consumed the same version
await emptyDir(cache)

const archiveName = path.join(tmpdir(), getTempName("fpm-download") + ".7z")
await download(url, archiveName)
const tempUnpackDir = path.join(cache, getTempName())
await spawn(path7za, ["x", archiveName, "-o" + tempUnpackDir, "-bb" + (debug.enabled ? "3" : "0"), "-bd"], {
cwd: cache,
stdio: ["ignore", "inherit", "inherit"],
})

await move(path.join(tempUnpackDir, dirName), fpmDir, {clobber: true})
await BluebirdPromise.all([remove(tempUnpackDir), remove(archiveName)])

return path.join(fpmDir, "fpm")
}
2 changes: 1 addition & 1 deletion src/gitHubRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function doGitHubRequest<T>(options: RequestOptions, token: string | null
if (response.statusCode === 404) {
// error is clear, we don't need to read detailed error description
reject(new HttpError(response, `method: ${options.method} url: https://${options.hostname}${options.path}
Please double check that your GitHub Token is correct. Due to security reasons GitHub doesn't report actual status, but 404.
`))
}
Expand Down
2 changes: 1 addition & 1 deletion src/httpRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function doDownload(url: string, destination: string, redirectCount: number, cal
hostname: parsedUrl.hostname,
path: parsedUrl.path,
headers: {
"User-Agent": "electron-complete-builder"
"User-Agent": "electron-builder"
}
}, (response: IncomingMessage) => {
if (response.statusCode >= 400) {
Expand Down
12 changes: 11 additions & 1 deletion src/linuxPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Platform, LinuxBuildOptions } from "./metadata"
import { dir as _tpmDir, TmpOptions } from "tmp"
import { exec, log, use } from "./util"
import { outputFile, readFile, readdir } from "fs-extra-p"
import { downloadFpm } from "./fpmDownload"
const template = require("lodash.template")

//noinspection JSUnusedLocalSymbols
Expand All @@ -18,6 +19,8 @@ export class LinuxPackager extends PlatformPackager<LinuxBuildOptions> {
private readonly packageFiles: Promise<Array<string>>
private readonly scriptFiles: Promise<Array<string>>

private readonly fpmPath: Promise<string>

constructor(info: BuildInfo) {
super(info)

Expand All @@ -33,6 +36,13 @@ export class LinuxPackager extends PlatformPackager<LinuxBuildOptions> {
})
this.packageFiles = this.computePackageFiles(tempDir)
this.scriptFiles = this.createScripts(tempDir)

if (process.platform === "darwin" && process.env.USE_SYSTEM_FPM !== "true") {
this.fpmPath = downloadFpm("1.5.0-1")
}
else {
this.fpmPath = BluebirdPromise.resolve("fpm")
}
}
}

Expand Down Expand Up @@ -201,7 +211,7 @@ Icon=${this.metadata.name}

args.push(`${appOutDir}/=/opt/${this.appName}`)
args.push(...<any>(await this.packageFiles)!)
await exec("fpm", args)
await exec(await this.fpmPath, args)
return destination
}
}
Expand Down
2 changes: 2 additions & 0 deletions test/install-linux-dependencies.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
gem install --no-rdoc --no-ri fpm

wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add -

sudo dpkg --add-architecture i386
Expand Down
6 changes: 6 additions & 0 deletions test/src/helpers/avaEx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ declare module "ava-tf" {
export const ifNotWindows: typeof test;
export const ifOsx: typeof test;
export const ifNotCi: typeof test;
export const ifNotCiOsx: typeof test;
export const ifNotTravis: typeof test;
}

Expand All @@ -24,6 +25,11 @@ Object.defineProperties(test, {
return process.env.CI ? this.skip : this
}
},
"ifNotCiOsx": {
get: function () {
return process.env.CI && process.platform === "darwin" ? this.skip : this
}
},
"ifNotTravis": {
get: function () {
return process.env.TRAVIS ? this.skip : this
Expand Down
4 changes: 1 addition & 3 deletions test/src/linuxPackagerTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ import { Platform } from "out"
//noinspection JSUnusedLocalSymbols
const __awaiter = require("out/awaiter")

test.ifNotWindows("linux", async () => {
await assertPack("test-app-one", platform(Platform.LINUX))
})
test.ifNotWindows("linux", () => assertPack("test-app-one", platform(Platform.LINUX)))

test.ifNotWindows("linux - icons from ICNS", async () => {
await assertPack("test-app-one", {
Expand Down
6 changes: 3 additions & 3 deletions test/src/winPackagerTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import * as assertThat from "should/as-function"
//noinspection JSUnusedLocalSymbols
const __awaiter = require("out/awaiter")

test.ifNotTravis("win", () => assertPack("test-app-one", platform(Platform.WINDOWS),
test.ifNotCiOsx("win", () => assertPack("test-app-one", platform(Platform.WINDOWS),
{
tempDirCreated: process.env.TEST_DELTA ? it => modifyPackageJson(it, data => {
data.build.win = {
Expand All @@ -21,7 +21,7 @@ test.ifNotTravis("win", () => assertPack("test-app-one", platform(Platform.WINDO
}
))

test.ifNotTravis("noMsi as string", t => t.throws(assertPack("test-app-one", platform(Platform.WINDOWS),
test.ifNotCiOsx("noMsi as string", t => t.throws(assertPack("test-app-one", platform(Platform.WINDOWS),
{
tempDirCreated: it => modifyPackageJson(it, data => {
data.build.win = {
Expand Down Expand Up @@ -67,7 +67,7 @@ test("detect install-spinner", () => {
})
})

test.ifNotTravis("icon < 256", (t: any) => t.throws(assertPack("test-app-one", platform(Platform.WINDOWS), {
test.ifNotCiOsx("icon < 256", (t: any) => t.throws(assertPack("test-app-one", platform(Platform.WINDOWS), {
tempDirCreated: projectDir => move(path.join(projectDir, "build", "incorrect.ico"), path.join(projectDir, "build", "icon.ico"), {clobber: true})
}), /Windows icon image size must be at least 256x256/))

Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"src/builder.ts",
"src/codeSign.ts",
"src/errorMessages.ts",
"src/fpmDownload.ts",
"src/gitHubPublisher.ts",
"src/gitHubRequest.ts",
"src/httpRequest.ts",
Expand Down

0 comments on commit e7cee5e

Please sign in to comment.