Skip to content

Commit

Permalink
test: docker & circleci
Browse files Browse the repository at this point in the history
  • Loading branch information
develar committed May 21, 2016
1 parent f5c6fcf commit f781217
Show file tree
Hide file tree
Showing 13 changed files with 150 additions and 31 deletions.
1 change: 1 addition & 0 deletions .idea/dictionaries/develar.xml

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

2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
os:
- osx
- linux
- osx

osx_image: xcode7

Expand Down
21 changes: 21 additions & 0 deletions circle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
machine:
services:
- docker

dependencies:
cache_directories:
- "~/.electron"
- "~/.cache"

# https://discuss.circleci.com/t/installing-git-lfs/867
# circleci doesn't cache after test, only after deps, so, we do test in this phase
override:
- curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
- sudo apt-get install git-lfs=1.2.0
- ssh [email protected] git-lfs-authenticate $CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME.git download
- git lfs pull
- docker run --rm -v ${PWD}:/project -v ~/.electron:/root/.electron -v ~/.cache:/root/.cache electronuserland/electron-builder:wine /test.sh

test:
override:
- echo "done"
45 changes: 45 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
FROM buildpack-deps:xenial-curl

# rpm is required for FPM to build rpm package

RUN apt-get update -y && \
apt-get install --no-install-recommends -y build-essential icnsutils graphicsmagick gcc-multilib g++-multilib libgnome-keyring-dev zip rpm && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

RUN set -ex \
&& for key in \
9554F04D7259F04124DE6B476D5A82AC7E37093B \
94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
0034A06D9D9B0064CE8ADF6BF1747F4AD2306D93 \
FD3A5288F042B6850C66B31F09FE44734EB7990E \
71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
B9AE9905FFD7803F25714661B63B535A4C206CA9 \
C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
; do \
gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \
done

ENV NODE_VERSION 6.2.0
ENV XZ_VERSION 5.2.2

# https://github.com/npm/npm/issues/4531

# install modern multi-thread xz
# ldconfig - see 4.6. liblzma.so (or similar) not found when running xz
RUN curl -L http://tukaani.org/xz/xz-$XZ_VERSION.tar.xz | tar -xJ && cd xz-$XZ_VERSION && ./configure && make && make install && cd .. && rm -rf xz-$XZ_VERSION && ldconfig && \
curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
&& grep " node-v$NODE_VERSION-linux-x64.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
&& tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components=1 \
&& rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \
&& curl -L https://npmjs.org/install.sh | sh && npm cache clean && npm config set unsafe-perm true && npm completion >> ~/.bashrc

COPY test.sh /test.sh

WORKDIR /project

ENV DEBUG_COLORS true
ENV FORCE_COLOR true
29 changes: 29 additions & 0 deletions docker/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Development machine

```sh
docker run --rm -ti -v `pwd`:/project -v `pwd`/node_modules/.linux:/project/node_modules -v ~/.electron:/root/.electron electronuserland/electron-builder
```

Wine:
```sh
docker run --rm -ti -v ${PWD}:/project -v ${PWD##*/}-node-modules:/project/node_modules -v ~/.electron:/root/.electron electronuserland/electron-builder:wine
```

# CI Server

```sh
docker run --rm -v ${PWD}:/project -v ~/.electron:/root/.electron -v ~/.cache:/root/.cache electronuserland/electron-builder:wine /test.sh
```

# Build

```
docker build -t electronuserland/electron-builder docker
docker build -t electronuserland/electron-builder:wine docker/wine
```

* We use [named data volume](https://madcoda.com/2016/03/docker-named-volume-explained/) instead of mounted host directory to store `node_modules` because NPM is unreliable and NPM team [doesn't want to fix it](https://github.com/npm/npm/issues/3565).

`${PWD##*/}-node-modules` is used as name of data volume — it is your current directory name (e. g. `foo`) and suffix `-node-modules`.

As downside, you have to manually clear outdated data volumes, use `docker volume rm your-name`.
5 changes: 5 additions & 0 deletions docker/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/sh

npm install
npm prune
npm test
15 changes: 15 additions & 0 deletions docker/wine/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM electronuserland/electron-builder:latest

# libgnome-keyring-dev — to build keytar
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F9CB8DB0 && \
echo "deb http://ppa.launchpad.net/ubuntu-wine/ppa/ubuntu xenial main " | tee /etc/apt/sources.list.d/wine.list && \
dpkg --add-architecture i386 && \
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF && \
echo "deb http://download.mono-project.com/repo/debian wheezy main" | tee /etc/apt/sources.list.d/mono-xamarin.list && \
apt-get update -y && \
apt-get install -y --no-install-recommends wine1.8 mono-devel ca-certificates-mono && \
apt-get clean && rm -rf /var/lib/apt/lists/*

ENV WINEDEBUG -all,err+all

RUN wineboot --init || true
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
"lint": "tslint src/*.ts test/src/*.ts",
"pretest": "npm run compile && npm run lint",
"test": "node ./test/out/helpers/runTests.js",
"ci-test": "git-lfs pull && npm install && npm prune && npm run test",
"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",
"whitespace": "whitespace src/*.ts"
"whitespace": "whitespace src/*.ts",
"docker-images": "docker build -t electronuserland/electron-builder docker && docker build -t electronuserland/electron-builder:wine docker/wine"
},
"repository": {
"type": "git",
Expand Down
19 changes: 8 additions & 11 deletions src/fpmDownload.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { statOrNull, spawn, debug, debug7z } from "./util"
import { writeFile, rename, remove, stat, emptyDir } from "fs-extra-p"
import { writeFile, rename, remove, unlink, emptyDir } from "fs-extra-p"
import { download } from "./httpRequest"
import { path7za } from "7zip-bin"
import * as path from "path"
Expand Down Expand Up @@ -48,15 +48,12 @@ async function doDownloadFpm(version: string, osAndArch: string): Promise<string
}

// 7z cannot be extracted from the input stream, temp file is required
const tempName = getTempName()
const archiveName = path.join(cacheDir, `${tempName}.7z`)
const tempUnpackDir = path.join(cacheDir, tempName)
const tempUnpackDir = path.join(cacheDir, getTempName())
const archiveName = `${tempUnpackDir}.7z`
debug(`Download fpm from ${url} to ${archiveName}`)
await BluebirdPromise.all<any>([download(url, archiveName), emptyDir(tempUnpackDir)])

if (debug.enabled && (!(await stat(archiveName)).isFile())) {
throw new Error(`${archiveName} was not downloaded correctly`)
}
// 7z doesn't create out dir
await emptyDir(tempUnpackDir)
await download(url, archiveName, false)

const args = ["x", archiveName, "-o" + tempUnpackDir, "-bd"]
if (debug7z.enabled) {
Expand All @@ -71,12 +68,12 @@ async function doDownloadFpm(version: string, osAndArch: string): Promise<string
stdio: ["ignore", debug.enabled ? "inherit" : "ignore", "inherit"],
})

await BluebirdPromise.all<any>([
await BluebirdPromise.all([
rename(path.join(tempUnpackDir, dirName), fpmDir)
.catch(e => {
console.warn("Cannot move downloaded fpm into final location (another process downloaded faster?): " + e)
}),
remove(archiveName),
unlink(archiveName),
])
await BluebirdPromise.all([
remove(tempUnpackDir),
Expand Down
16 changes: 10 additions & 6 deletions src/httpRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ import * as path from "path"

const maxRedirects = 10

export const download = BluebirdPromise.promisify(_download)
export const download = <(url: string, destination: string, isCreateDir?: boolean | undefined) => BluebirdPromise<any>>(BluebirdPromise.promisify(_download))

function _download(url: string, destination: string, callback: (error: Error) => void): void {
doDownload(url, destination, 0, callback)
function _download(url: string, destination: string, isCreateDir: boolean | undefined, callback: (error: Error) => void): void {
if (callback == null) {
callback = <any>isCreateDir
isCreateDir = true
}
doDownload(url, destination, 0, isCreateDir === undefined ? true : isCreateDir, callback)
}

export function addTimeOutHandler(request: ClientRequest, callback: (error: Error) => void) {
Expand All @@ -23,8 +27,8 @@ export function addTimeOutHandler(request: ClientRequest, callback: (error: Erro
})
}

function doDownload(url: string, destination: string, redirectCount: number, callback: (error: Error) => void) {
const ensureDirPromise = ensureDir(path.dirname(destination))
function doDownload(url: string, destination: string, redirectCount: number, isCreateDir: boolean, callback: (error: Error) => void) {
const ensureDirPromise = isCreateDir ? ensureDir(path.dirname(destination)) : BluebirdPromise.resolve()

const parsedUrl = parseUrl(url)
// user-agent must be specified, otherwise some host can return 401 unauthorised
Expand All @@ -43,7 +47,7 @@ function doDownload(url: string, destination: string, redirectCount: number, cal
const redirectUrl = response.headers.location
if (redirectUrl != null) {
if (redirectCount < maxRedirects) {
doDownload(redirectUrl, destination, redirectCount++, callback)
doDownload(redirectUrl, destination, redirectCount++, isCreateDir, callback)
}
else {
callback(new Error("Too many redirects (> " + maxRedirects + ")"))
Expand Down
4 changes: 2 additions & 2 deletions src/linuxPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Promise as BluebirdPromise } from "bluebird"
import { PlatformPackager, BuildInfo } from "./platformPackager"
import { Platform, LinuxBuildOptions } from "./metadata"
import { dir as _tpmDir, TmpOptions } from "tmp"
import { exec, log, use } from "./util"
import { exec, debug, use } from "./util"
import { outputFile, readFile, readdir } from "fs-extra-p"
import { downloadFpm } from "./fpmDownload"
const template = require("lodash.template")
Expand Down Expand Up @@ -117,7 +117,7 @@ Icon=${this.metadata.name}
private async createFromIcns(tempDir: string): Promise<Array<string>> {
const outputs = await exec("icns2png", ["-x", "-o", tempDir, path.join(this.buildResourcesDir, "icon.icns")])
const output = outputs[0].toString()
log(output)
debug(output)

const imagePath = path.join(tempDir, "icon_256x256x32.png")

Expand Down
16 changes: 8 additions & 8 deletions test/src/helpers/runTests.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { spawn } from "child_process"
import * as path from "path"
import { Promise as BluebirdPromise } from "bluebird"
import * as fs from "fs-extra-p"
import { copy, readJson, emptyDir, unlink, readdir, outputFile, readFileSync } from "fs-extra-p"
import { Platform } from "out/metadata"

// we set NODE_PATH in this file, so, we cannot use 'out/awaiter' path here
Expand All @@ -23,7 +23,7 @@ async function main() {
await BluebirdPromise.all([
deleteOldElectronVersion(),
downloadAllRequiredElectronVersions(),
fs.outputFile(path.join(testPackageDir, "package.json"), `{
outputFile(path.join(testPackageDir, "package.json"), `{
"private": true,
"version": "1.0.0",
"name": "test",
Expand Down Expand Up @@ -56,10 +56,10 @@ async function deleteOldElectronVersion(): Promise<any> {
const cacheDir = path.join(require("os").homedir(), ".electron")
try {
const deletePromises: Array<Promise<any>> = []
for (let file of (await fs.readdir(cacheDir))) {
for (let file of (await readdir(cacheDir))) {
if (file.endsWith(".zip") && !file.includes(electronVersion)) {
console.log("Remove old electron " + file)
deletePromises.push(fs.unlink(path.join(cacheDir, file)))
deletePromises.push(unlink(path.join(cacheDir, file)))
}
}
return BluebirdPromise.all(deletePromises)
Expand Down Expand Up @@ -96,8 +96,8 @@ function downloadAllRequiredElectronVersions(): Promise<any> {

// npm is very slow and not reliable - so, just copy and then prune dev dependencies
async function copyDependencies() {
await fs.emptyDir(testNodeModules)
const devDeps = Object.keys((await fs.readJson(path.join(rootDir, "package.json"), "utf-8")).devDependencies)
await emptyDir(testNodeModules)
const devDeps = Object.keys((await readJson(path.join(rootDir, "package.json"), "utf-8")).devDependencies)
const filtered = new Set()
/*eslint prefer-const: 0*/
for (let name of devDeps) {
Expand All @@ -106,7 +106,7 @@ async function copyDependencies() {

filtered.add(path.join(rootDir, "node_modules", ".bin"))

return fs.copy(path.join(rootDir, "node_modules"), testNodeModules, {
return copy(path.join(rootDir, "node_modules"), testNodeModules, {
filter: it => {
if (it.includes("node_modules" + path.sep + "babel-")) {
return false
Expand Down Expand Up @@ -151,7 +151,7 @@ function exec(command: string, args: Array<string>) {
else {
if (command === "npm") {
try {
console.error(fs.readFileSync(path.join(testPackageDir, "npm-debug.log"), "utf8"))
console.error(readFileSync(path.join(testPackageDir, "npm-debug.log"), "utf8"))
}
catch (e) {
// ignore
Expand Down
4 changes: 2 additions & 2 deletions test/src/winPackagerTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ test.ifNotCiOsx("win", () => assertPack("test-app-one", signed({
}
))

test.ifNotCiOsx("delta", () => assertPack("test-app-one", {
test.ifDevOrWinCi("delta", () => assertPack("test-app-one", {
platform: [Platform.WINDOWS],
arch: "ia32",
devMetadata: {
Expand All @@ -46,7 +46,7 @@ test.ifNotCiOsx("delta", () => assertPack("test-app-one", {
}
))

test.ifDevOrWinCi("win f", () => {
test.ifDevOrWinCi("beta version", () => {
const metadata: any = {
version: "3.0.0-beta.2"
}
Expand Down

0 comments on commit f781217

Please sign in to comment.