Merge pull request #1423 from balena-io/1419-fix-pkg-target-node

Fix Node.js version errors in standalone package on Windows
This commit is contained in:
Paulo Castro 2019-09-11 11:47:09 +01:00 committed by GitHub
commit c9db5fd856
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 116 additions and 35 deletions

View File

@ -19,11 +19,13 @@ import { run as oclifRun } from '@oclif/dev-cli';
import * as archiver from 'archiver';
import * as Bluebird from 'bluebird';
import { execFile, spawn } from 'child_process';
import { stripIndent } from 'common-tags';
import * as filehound from 'filehound';
import * as fs from 'fs-extra';
import * as path from 'path';
import { exec as execPkg } from 'pkg';
import * as rimraf from 'rimraf';
import * as semver from 'semver';
import * as shellEscape from 'shell-escape';
import * as util from 'util';
@ -106,7 +108,7 @@ export async function runUnderMsys(argv?: string[]) {
async function buildPkg() {
const args = [
'--target',
'node10',
'host',
'--output',
'build-bin/balena',
'package.json',
@ -151,6 +153,43 @@ async function buildPkg() {
);
}
/**
* Run some basic tests on the built pkg executable.
* TODO: test more than just `balena version -j`; integrate with the
* existing mocha/chai CLI command testing.
*/
async function testPkg() {
type JsonVersions = import('../lib/actions-oclif/version').JsonVersions;
const pkgBalenaPath = path.join(
ROOT,
'build-bin',
process.platform === 'win32' ? 'balena.exe' : 'balena',
);
console.log(`Testing standalone package "${pkgBalenaPath}"...`);
// Run `balena version -j`, parse its stdout as JSON, and check that the
// reported Node.js major version matches semver.major(process.version)
const stdout = await getSubprocessStdout(pkgBalenaPath, ['version', '-j']);
let pkgNodeVersion = '';
let pkgNodeMajorVersion = 0;
try {
const balenaVersions: JsonVersions = JSON.parse(stdout);
pkgNodeVersion = balenaVersions['Node.js'];
pkgNodeMajorVersion = semver.major(pkgNodeVersion);
} catch (err) {
throw new Error(stripIndent`
Error parsing JSON output of "balena version -j": ${err}
Original output: "${stdout}"`);
}
if (semver.major(process.version) !== pkgNodeMajorVersion) {
throw new Error(
`Mismatched major version: built-in pkg Node version="${pkgNodeVersion}" vs process.version="${
process.version
}"`,
);
}
console.log('Success! (standalone package test successful)');
}
/**
* Create the zip file for the standalone 'pkg' bundle previously created
* by the buildPkg() function in 'build-bin.ts'.
@ -188,9 +227,10 @@ export async function buildStandaloneZip() {
console.log(`Building standalone zip package for CLI ${version}`);
try {
await buildPkg();
await testPkg();
await zipPkg();
} catch (error) {
console.log(`Error creating standalone zip package: ${error}`);
console.log(`Error creating or testing standalone zip package:\n ${error}`);
process.exit(1);
}
console.log(`Standalone zip package build completed`);
@ -280,3 +320,45 @@ export async function buildOclifInstaller() {
export function fixPathForMsys(p: string): string {
return p.replace(/\\/g, '/').replace(/^([a-zA-Z]):/, '/$1');
}
/**
* Run the executable at execPath as a child process, and resolve a promise
* to the executable's stdout output as a string. Reject the promise if
* anything is printed to stderr, or if the child process exits with a
* non-zero exit code.
* @param execPath Executable path
* @param args Command-line argument for the executable
*/
async function getSubprocessStdout(
execPath: string,
args: string[],
): Promise<string> {
const child = spawn(execPath, args);
return new Promise((resolve, reject) => {
let stdout = '';
child.stdout.on('error', reject);
child.stderr.on('error', reject);
child.stdout.on('data', (data: Buffer) => {
try {
stdout = data.toString();
} catch (err) {
reject(err);
}
});
child.stderr.on('data', (data: Buffer) => {
try {
const stderr = data.toString();
reject(new Error(`"${execPath}": non-empty stderr "${stderr}"`));
} catch (err) {
reject(err);
}
});
child.on('exit', (code: number) => {
if (code) {
reject(new Error(`"${execPath}": non-zero exit code "${code}"`));
} else {
resolve(stdout);
}
});
});
}

View File

@ -24,6 +24,11 @@ interface FlagsDef {
help: void;
}
export interface JsonVersions {
'balena-cli': string;
'Node.js': string;
}
export default class VersionCmd extends Command {
public static description = stripIndent`
Display version information for the balena CLI and/or Node.js.
@ -58,7 +63,7 @@ export default class VersionCmd extends Command {
public async run() {
const { flags: options } = this.parse<FlagsDef, {}>(VersionCmd);
const versions = {
const versions: JsonVersions = {
'balena-cli': (await import('../../package.json')).version,
'Node.js':
process.version && process.version.startsWith('v')

56
npm-shrinkwrap.json generated
View File

@ -819,13 +819,6 @@
"integrity": "sha512-1qhcYMLJ0I2HcRG3G/nBcRZ0KrrTdGdUNcCkEVgcga4KMlDXWh6LZJjVA6MiWEDa+BOaQTEfGJfuNaQ71IQOpg==",
"requires": {
"@types/node": "*"
},
"dependencies": {
"@types/node": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.10.tgz",
"integrity": "sha512-LcsGbPomWsad6wmMNv7nBLw7YYYyfdYcz6xryKYQhx89c3XXan+8Q6AJ43G5XDIaklaVkK3mE4fCb0SBvMiPSQ=="
}
}
},
"@yarnpkg/lockfile": {
@ -4707,9 +4700,9 @@
}
},
"etcher-sdk": {
"version": "2.0.13",
"resolved": "https://registry.npmjs.org/etcher-sdk/-/etcher-sdk-2.0.13.tgz",
"integrity": "sha512-+5KQQXa7psHUQIket7VPpWStdVdEnm4L9jub7fB664nyMLMybVnYHwlskpuG/hDrh/rLLXD2EgF08MIqKRxuJQ==",
"version": "2.0.14",
"resolved": "https://registry.npmjs.org/etcher-sdk/-/etcher-sdk-2.0.14.tgz",
"integrity": "sha512-MWmmKrZc3geatDQHnd5h66HHujdVCnaAU1+t3M/BTam93GHVeNSDjauqicM8gA9mqi6YZSqa5AaTV9Ug3YLGHQ==",
"requires": {
"@types/node": "^6.0.112",
"axios": "^0.18.0",
@ -4733,14 +4726,14 @@
"unbzip2-stream": "github:balena-io-modules/unbzip2-stream#942fc218013c14adab01cf693b0500cf6ac83193",
"unzip-stream": "^0.3.0",
"winusb-driver-generator": "^1.2.3",
"xxhash": "github:balena-io-modules/node-xxhash#cc9d14d8409cd81e77ca1cfd6bcf58cccb68435e",
"xxhash": "^0.3.0",
"yauzl": "^2.9.2"
},
"dependencies": {
"@types/node": {
"version": "6.14.6",
"resolved": "https://registry.npmjs.org/@types/node/-/node-6.14.6.tgz",
"integrity": "sha512-rFs9zCFtSHuseiNXxYxFlun8ibu+jtZPgRM+2ILCmeLiGeGLiIGxuOzD+cNyHegI1GD+da3R/cIbs9+xCLp13w=="
"version": "6.14.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-6.14.7.tgz",
"integrity": "sha512-YbPXbaynBTe0pVExPhL76TsWnxSPeFAvImIsmylpBWn/yfw+lHy+Q68aawvZHsgskT44ZAoeE67GM5f+Brekew=="
},
"debug": {
"version": "3.2.6",
@ -7011,9 +7004,9 @@
"integrity": "sha512-vdqWBp7MyzdmHkkRWV5nY+PfGRbYbahfuvsBCh277tq+w9zyNi7h5CYJCK0kmzti9kU+O/cB7sE8HvKv6aXAKQ=="
},
"ignore-walk": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz",
"integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.2.tgz",
"integrity": "sha512-EXyErtpHbn75ZTsOADsfx6J/FPo6/5cjev46PXrcTpd8z3BoRkXgYu9/JVqrI7tusjmwCZutGeRJeU0Wo1e4Cw==",
"requires": {
"minimatch": "^3.0.4"
}
@ -8526,9 +8519,9 @@
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
},
"minipass": {
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz",
"integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.5.1.tgz",
"integrity": "sha512-dmpSnLJtNQioZFI5HfQ55Ad0DzzsMAb+HfokwRTNXwEQjepbTkl5mtIlSVxGIkOkxlpX7wIn5ET/oAd9fZ/Y/Q==",
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@ -12641,20 +12634,20 @@
}
},
"node-raspberrypi-usbboot": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/node-raspberrypi-usbboot/-/node-raspberrypi-usbboot-0.2.4.tgz",
"integrity": "sha512-+lYrwn7qlJwvnI1B19ZIZXzhfaZb7R8U21dwyvmeYmqw/H36UqI4ri851Mv8vVsulBZvlIqtZdsx477T1grgag==",
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/node-raspberrypi-usbboot/-/node-raspberrypi-usbboot-0.2.5.tgz",
"integrity": "sha512-iRe9x5B3EDuq09hnk1SZTuzKGpWtlNBychVU/nwo7sL9WSqkmcj22qGpKoT/tJqwDe5YCTsJ5JX1X1FfMtYXdQ==",
"requires": {
"@types/node": "^6.0.112",
"@types/usb": "^1.5.1",
"debug": "^3.1.0",
"usb": "github:resin-io/node-usb#v1.3.10"
"usb": "github:balena-io/node-usb#v1.3.12"
},
"dependencies": {
"@types/node": {
"version": "6.14.6",
"resolved": "https://registry.npmjs.org/@types/node/-/node-6.14.6.tgz",
"integrity": "sha512-rFs9zCFtSHuseiNXxYxFlun8ibu+jtZPgRM+2ILCmeLiGeGLiIGxuOzD+cNyHegI1GD+da3R/cIbs9+xCLp13w=="
"version": "6.14.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-6.14.7.tgz",
"integrity": "sha512-YbPXbaynBTe0pVExPhL76TsWnxSPeFAvImIsmylpBWn/yfw+lHy+Q68aawvZHsgskT44ZAoeE67GM5f+Brekew=="
},
"debug": {
"version": "3.2.6",
@ -17403,8 +17396,8 @@
"integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k="
},
"usb": {
"version": "github:resin-io/node-usb#8cad6c9ecd1597af16af435bf629fc462b08c1a5",
"from": "github:resin-io/node-usb#v1.3.10",
"version": "github:balena-io/node-usb#1fb1bb01d04281432083b96801c6be6d528bd213",
"from": "github:balena-io/node-usb#v1.3.12",
"requires": {
"nan": "2.13.2",
"node-pre-gyp": "^0.11.0"
@ -17902,8 +17895,9 @@
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
},
"xxhash": {
"version": "github:balena-io-modules/node-xxhash#cc9d14d8409cd81e77ca1cfd6bcf58cccb68435e",
"from": "github:balena-io-modules/node-xxhash#cc9d14d8409cd81e77ca1cfd6bcf58cccb68435e",
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/xxhash/-/xxhash-0.3.0.tgz",
"integrity": "sha512-1ud2yyPiR1DJhgyF1ZVMt+Ijrn0VNS/wzej1Z8eSFfkNfRPp8abVZNV2u9tYy9574II0ZayZYZgJm8KJoyGLCw==",
"requires": {
"nan": "^2.13.2"
}

View File

@ -172,7 +172,7 @@
"dockerode": "^2.5.8",
"dockerode-options": "^0.2.1",
"ejs": "^2.5.7",
"etcher-sdk": "^2.0.5",
"etcher-sdk": "^2.0.14",
"event-stream": "3.3.4",
"express": "^4.13.3",
"fast-boot2": "^1.0.9",