Skip to content

Commit cabf352

Browse files
authored
Package plugin with pkg, chrome and grpc binaries (#19)
* Package plugin via pkg * Download proper chrome and grpc binaries * Cleanup build add arch variable * Updated build and fixes for windows * Build zip instead of tar.gz * Update readme with packaging
1 parent 3989c1d commit cabf352

File tree

12 files changed

+1578
-15
lines changed

12 files changed

+1578
-15
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,6 @@ dist/**/*
3737

3838
# Ignore output from coverage report
3939
coverage
40+
41+
# Dirs and tar.gz files generated from build
42+
plugin-*

Makefile

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,23 @@
1+
ARCH = darwin-x64-unknown
2+
13
all: clean build
24

35
clean:
4-
rm -rf dist
6+
rm -rf build
57

68
build:
7-
tsc
9+
./node_modules/.bin/tsc
10+
11+
clean_package:
12+
rm -rf ./plugin-${ARCH}
13+
rm -f ./plugin-${ARCH}.tar.gz
14+
15+
package:
16+
node scripts/pkg.js ${ARCH}
17+
node scripts/download_chromium.js ${ARCH}
18+
node scripts/download_grpc.js ${ARCH}
19+
node scripts/rename_executable.js ${ARCH}
20+
cp plugin.json plugin-${ARCH}/
21+
zip -yqr plugin-${ARCH}.zip plugin-${ARCH}
22+
23+
build_package: clean clean_package build package

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,21 @@ cd docker
3333
docker-compose up
3434
```
3535

36+
# Packaging
37+
This plugin can be packaged into single archive without dependencies.
38+
```bash
39+
make build_package ARCH=<arch_string>
40+
```
41+
42+
Where <arch_string> is a combination of
43+
- linux, darwin, win32
44+
- ia32, x64, arm, arm64
45+
- unknown, glibc, musl
46+
47+
This follows combinations allowed for grpc plugin and you can see options [here](https://console.cloud.google.com/storage/browser/node-precompiled-binaries.grpc.io/grpc/?project=grpc-testing)
48+
So far these builds were tested from Mac:
49+
- darwin-x64-unknown
50+
- linux-x64-glibc
51+
- win32-x64-unknown
52+
3653

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"devDependencies": {
2828
"husky": "^0.14.3",
2929
"lint-staged": "^6.0.0",
30+
"pkg": "4.3.8",
3031
"prettier": "1.9.2",
3132
"tsc-watch": "^1.0.21"
3233
},
@@ -48,5 +49,9 @@
4849
"trailingComma": "es5",
4950
"singleQuote": true,
5051
"printWidth": 120
51-
}
52+
},
53+
"pkg": {
54+
"assets": "proto/*"
55+
},
56+
"bin": "build/app.js"
5257
}

scripts/download_chromium.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
const path = require('path');
2+
const child_process = require('child_process');
3+
const Puppeteer = require('puppeteer');
4+
const puppeteerPackageJson = require('puppeteer/package.json');
5+
6+
const archArg = process.argv[2];
7+
const pluginDir = `plugin-${archArg}`;
8+
let [
9+
// Should be one of linux, mac, win32, win64 as per options in BrowserFetcher but we reuse the same arch string
10+
// as for grpc download (ie darwin-x64-unknown) so we need to transform it a bit
11+
platform,
12+
arch
13+
] = archArg.split('-');
14+
15+
if (platform === 'win32' && arch === 'x64') {
16+
platform = 'win64'
17+
}
18+
19+
if (platform === 'darwin') {
20+
platform = 'mac'
21+
}
22+
23+
const browserFetcher = Puppeteer.createBrowserFetcher({ platform });
24+
const revision = puppeteerPackageJson.puppeteer.chromium_revision;
25+
26+
browserFetcher
27+
.download(revision, null)
28+
.then(() => {
29+
console.log("Chromium downloaded");
30+
const parts = browserFetcher.revisionInfo(revision).executablePath.split(path.sep);
31+
32+
// based on where puppeteer puts the binaries see BrowserFetcher.revisionInfo()
33+
while (!parts[parts.length - 1].startsWith('chrome-')) {
34+
parts.pop()
35+
}
36+
37+
let execPath = parts.join(path.sep);
38+
39+
child_process.execSync(`cp -RP ${execPath} ${pluginDir}`);
40+
41+
console.log(`Chromium moved from ${execPath} to ${pluginDir}/`);
42+
process.exit(0);
43+
})
44+
.catch((err) => {
45+
console.error(err);
46+
process.exit(1);
47+
});

scripts/download_grpc.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
const path = require('path');
2+
const childProcess = require('child_process');
3+
const https = require('https');
4+
const fs = require('fs');
5+
6+
// /grpc-precompiled-binaries/node/grpc/v1.11.3/node-v64-darwin-x64-unknown
7+
const grpcPackageJson = require('grpc/package.json');
8+
9+
// Taken from https://github.com/mapbox/node-pre-gyp/blob/674fda7b28b86bb3b11889db86c15c4d06722d02/lib/util/versioning.js
10+
// so we can evaluate templates used for node-pre-gyp in grpc package
11+
function eval_template(template, opts) {
12+
Object.keys(opts).forEach(function(key) {
13+
var pattern = '{' + key + '}';
14+
while (template.indexOf(pattern) > -1) {
15+
template = template.replace(pattern, opts[key]);
16+
}
17+
});
18+
return template;
19+
}
20+
21+
// This is taken from grpc package that uses node-pre-gyp to download or build native grpc core.
22+
23+
// This matches abi version for node10 which is latest version pkg supports (as it is latest LTS)
24+
// see https://nodejs.org/en/download/releases/
25+
const node_abi = 'node-v64';
26+
const name = grpcPackageJson.name;
27+
const version = grpcPackageJson.version;
28+
29+
const archString = process.argv[2];
30+
const pluginDir = `plugin-${archString}`;
31+
// See https://console.cloud.google.com/storage/browser/node-precompiled-binaries.grpc.io/grpc/?project=grpc-testing
32+
// for existing prebuild binaries (though there are only ones for newer version).
33+
const [
34+
// linux, darwin, win32
35+
platform,
36+
// ia32, x64, arm, arm64
37+
arch,
38+
// unknown, glibc, musl
39+
libc,
40+
] = archString.split('-');
41+
42+
const host = grpcPackageJson.binary.host;
43+
const remote_path = eval_template(grpcPackageJson.binary.remote_path, { name, version });
44+
const package_name = eval_template(grpcPackageJson.binary.package_name, { node_abi, platform, arch, libc });
45+
const url = host + path.join(remote_path, package_name);
46+
47+
console.log(`Getting ${url}`);
48+
new Promise((resolve, reject) => {
49+
const file = fs.createWriteStream(`plugin-${archString}/grpc_node.tar.gz`);
50+
https
51+
.get(url, function(response) {
52+
if (response.statusCode !== 200) {
53+
const err = new Error(`response.statusCode = ${response.statusCode}`);
54+
err.response = response;
55+
reject(err);
56+
}
57+
response.pipe(file).on('finish', () => {
58+
resolve();
59+
});
60+
})
61+
.on('error', e => reject(e));
62+
})
63+
.then(() => {
64+
console.log(`Grpc module downloaded`);
65+
const dirName = package_name.split('.')[0];
66+
childProcess.execSync(`tar -xzf ${pluginDir}/grpc_node.tar.gz --directory ${pluginDir}`);
67+
childProcess.execSync(`mv ${pluginDir}/${dirName}/grpc_node.node ${pluginDir}/`);
68+
childProcess.execSync(`rm -rf ${pluginDir}/${dirName}`);
69+
childProcess.execSync(`rm -rf ${pluginDir}/grpc_node.tar.gz`);
70+
process.exit(0);
71+
})
72+
.catch(err => {
73+
console.error(err);
74+
process.exit(1);
75+
});

scripts/pkg.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const childProcess = require('child_process');
2+
3+
const archArg = process.argv[2];
4+
let [
5+
// linux, darwin, win32
6+
platform,
7+
// ia32, x64, arm, arm64
8+
arch,
9+
] = archArg.split('-');
10+
11+
const platformTransform = {
12+
darwin: 'macos',
13+
win32: 'win',
14+
};
15+
16+
const archTransform = {
17+
ia32: 'x84',
18+
arm: 'armv6',
19+
// I only assume this is correct
20+
arm64: 'armv6',
21+
};
22+
23+
platform = platformTransform[platform] || platform;
24+
arch = archTransform[arch] || arch;
25+
26+
childProcess.execSync(`./node_modules/.bin/pkg -t node10-${platform}-${arch} . --out-path plugin-${archArg}`);

scripts/rename_executable.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const childProcess = require('child_process');
2+
3+
const archArg = process.argv[2];
4+
5+
let [
6+
// linux, darwin, win32
7+
platform,
8+
// ia32, x64, arm, arm64
9+
arch,
10+
] = archArg.split('-');
11+
12+
const platformTransform = {
13+
win32: 'windows'
14+
};
15+
16+
const archTransform = {
17+
x64: 'amd64',
18+
ia32: '386'
19+
};
20+
21+
let ext = platform === 'win32' ? '.exe' : '';
22+
23+
const execFileName = `plugin_start_${platformTransform[platform] || platform}_${archTransform[arch] || arch}${ext}`;
24+
childProcess.execSync(`mv plugin-${archArg}/renderer${ext} plugin-${archArg}/${execFileName}`);
25+

src/app.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ async function main() {
3131
}
3232
}
3333

34-
main();
34+
main().catch(err => {
35+
console.error(err);
36+
process.exit(1);
37+
});
3538

3639

3740
// const puppeteer = require('puppeteer');

src/browser.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import * as path from 'path';
12
import * as os from 'os';
23
import * as puppeteer from 'puppeteer';
34
import { Logger } from './logger';
@@ -33,7 +34,24 @@ export class Browser {
3334
// set env timezone
3435
env.TZ = options.timezone || process.env.TZ;
3536

36-
browser = await puppeteer.launch({env: env, args: ['--no-sandbox']});
37+
if ((process as any).pkg) {
38+
const parts = puppeteer.executablePath().split(path.sep);
39+
while(!parts[0].startsWith('chrome-')) {
40+
parts.shift();
41+
}
42+
const executablePath = [path.dirname(process.execPath), ...parts].join(path.sep);
43+
console.log('executablePath', executablePath);
44+
browser = await puppeteer.launch({
45+
executablePath,
46+
env: env,
47+
args: ['--no-sandbox'],
48+
});
49+
} else {
50+
browser = await puppeteer.launch({
51+
env: env,
52+
args: ['--no-sandbox'],
53+
});
54+
}
3755
page = await browser.newPage();
3856

3957
await page.setViewport({

0 commit comments

Comments
 (0)