From 09f20ecc1c750ef29cc7cfdaff5a66f98c76aac8 Mon Sep 17 00:00:00 2001 From: Paulo Castro Date: Tue, 10 Sep 2019 16:08:07 +0100 Subject: [PATCH 1/2] Update etcher-sdk to v2.0.14 (pre-requisite to supporting Node 12) Change-type: patch Signed-off-by: Paulo Castro --- npm-shrinkwrap.json | 56 ++++++++++++++++++++------------------------- package.json | 2 +- 2 files changed, 26 insertions(+), 32 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 4ec1ce17..6c5c5ef1 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -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" } diff --git a/package.json b/package.json index 889d1a76..ce671278 100644 --- a/package.json +++ b/package.json @@ -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", From d54a709e7cf7f0a188c1ceb41bdccd5e48e02beb Mon Sep 17 00:00:00 2001 From: Paulo Castro Date: Tue, 10 Sep 2019 23:51:53 +0100 Subject: [PATCH 2/2] Fix mismatched Node.js version errors in standalone package on Windows Resolves: #1419 Change-type: patch Signed-off-by: Paulo Castro --- automation/build-bin.ts | 86 +++++++++++++++++++++++++++++++++++- lib/actions-oclif/version.ts | 7 ++- 2 files changed, 90 insertions(+), 3 deletions(-) diff --git a/automation/build-bin.ts b/automation/build-bin.ts index 7758a51f..f5d6149f 100644 --- a/automation/build-bin.ts +++ b/automation/build-bin.ts @@ -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 { + 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); + } + }); + }); +} diff --git a/lib/actions-oclif/version.ts b/lib/actions-oclif/version.ts index b0e0f43d..b5743968 100644 --- a/lib/actions-oclif/version.ts +++ b/lib/actions-oclif/version.ts @@ -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(VersionCmd); - const versions = { + const versions: JsonVersions = { 'balena-cli': (await import('../../package.json')).version, 'Node.js': process.version && process.version.startsWith('v')