Use standard oclif run.js & dev.js

Change-type: patch
This commit is contained in:
Otavio Jacobi 2024-03-11 14:33:30 -03:00
parent 556e50c87c
commit 742c015f21
11 changed files with 135 additions and 129 deletions

View File

@ -1,21 +0,0 @@
#!/usr/bin/env node
// We boost the threadpool size as ext2fs can deadlock with some
// operations otherwise, if the pool runs out.
process.env.UV_THREADPOOL_SIZE = '64';
// Disable oclif registering ts-node
process.env.OCLIF_TS_NODE = 0;
async function run() {
// Use fast-boot to cache require lookups, speeding up startup
await require('../build/fast-boot').start();
// Set the desired es version for downstream modules that support it
require('@balena/es-version').set('es2018');
// Run the CLI
await require('../build/app').run(undefined, { dir: __dirname });
}
run();

1
bin/balena Symbolic link
View File

@ -0,0 +1 @@
run.js

View File

@ -1,87 +0,0 @@
#!/usr/bin/env node
// ****************************************************************************
// THIS IS FOR DEV PURPOSES ONLY AND WILL NOT BE PART OF THE PUBLISHED PACKAGE
// Before opening a PR you should build and test your changes using bin/balena
// ****************************************************************************
// We boost the threadpool size as ext2fs can deadlock with some
// operations otherwise, if the pool runs out.
process.env.UV_THREADPOOL_SIZE = '64';
// Note on `fast-boot2`: We do not use `fast-boot2` with `balena-dev` because:
// * fast-boot2's cacheKiller option is configured to include the timestamps of
// the package.json and npm-shrinkwrap.json files, to avoid unexpected CLI
// behavior when changes are made to dependencies during development. This is
// generally a good thing, however, `balena-dev` (a few lines below) edits
// `package.json` to modify oclif paths, and this results in cache
// invalidation and a performance hit rather than speedup.
// * Even if the timestamps are removed from cacheKiller, so that there is no
// cache invalidation, fast-boot's speedup is barely noticeable when ts-node
// is used, e.g. 1.43s vs 1.4s when running `balena version`.
// * `fast-boot` causes unexpected behavior when used with `npm link` or
// when the `node_modules` folder is manually modified (affecting transitive
// dependencies) during development (e.g. bug investigations). A workaround
// is to use `balena-dev` without `fast-boot`. See also notes in
// `CONTRIBUTING.md`.
const path = require('path');
const rootDir = path.join(__dirname, '..');
// Allow balena-dev to work with oclif by temporarily
// pointing oclif config options to lib/ instead of build/
modifyOclifPaths();
// Undo changes on exit
process.on('exit', function () {
modifyOclifPaths(true);
});
// Undo changes in case of ctrl-c
process.on('SIGINT', function () {
modifyOclifPaths(true);
// Note process exit here will interfere with commands that do their own SIGINT handling,
// but without it commands can not be exited.
// So currently using balena-dev does not guarantee proper exit behaviour when using ctrl-c.
// Ideally a better solution is needed.
process.exit();
});
// Set the desired es version for downstream modules that support it
require('@balena/es-version').set('es2018');
// Note: before ts-node v6.0.0, 'transpile-only' (no type checking) was the
// default option. We upgraded ts-node and found that adding 'transpile-only'
// was necessary to avoid a mysterious 'null' error message. On the plus side,
// it is supposed to run faster. We still benefit from type checking when
// running 'npm run build'.
require('ts-node').register({
project: path.join(rootDir, 'tsconfig.json'),
transpileOnly: true,
});
require('../lib/app').run(undefined, { dir: __dirname, development: true });
// Modify package.json oclif paths from build/ -> lib/, or vice versa
function modifyOclifPaths(revert) {
const fs = require('fs');
const packageJsonPath = path.join(rootDir, 'package.json');
const packageJson = fs.readFileSync(packageJsonPath, 'utf8');
const packageObj = JSON.parse(packageJson);
if (!packageObj.oclif) {
return;
}
let oclifSectionText = JSON.stringify(packageObj.oclif);
if (!revert) {
oclifSectionText = oclifSectionText.replace(/\/build\//g, '/lib/');
} else {
oclifSectionText = oclifSectionText.replace(/\/lib\//g, '/build/');
}
packageObj.oclif = JSON.parse(oclifSectionText);
fs.writeFileSync(
packageJsonPath,
`${JSON.stringify(packageObj, null, 2)}\n`,
'utf8',
);
}

1
bin/balena-dev Symbolic link
View File

@ -0,0 +1 @@
dev.js

3
bin/dev.cmd Normal file
View File

@ -0,0 +1,3 @@
@echo off
node "%~dp0\run" %*

87
bin/dev.js Normal file
View File

@ -0,0 +1,87 @@
#!/usr/bin/env node
// ****************************************************************************
// THIS IS FOR DEV PURPOSES ONLY AND WILL NOT BE PART OF THE PUBLISHED PACKAGE
// Before opening a PR you should build and test your changes using bin/balena
// ****************************************************************************
// We boost the threadpool size as ext2fs can deadlock with some
// operations otherwise, if the pool runs out.
process.env.UV_THREADPOOL_SIZE = '64';
// Note on `fast-boot2`: We do not use `fast-boot2` with `balena-dev` because:
// * fast-boot2's cacheKiller option is configured to include the timestamps of
// the package.json and npm-shrinkwrap.json files, to avoid unexpected CLI
// behavior when changes are made to dependencies during development. This is
// generally a good thing, however, `balena-dev` (a few lines below) edits
// `package.json` to modify oclif paths, and this results in cache
// invalidation and a performance hit rather than speedup.
// * Even if the timestamps are removed from cacheKiller, so that there is no
// cache invalidation, fast-boot's speedup is barely noticeable when ts-node
// is used, e.g. 1.43s vs 1.4s when running `balena version`.
// * `fast-boot` causes unexpected behavior when used with `npm link` or
// when the `node_modules` folder is manually modified (affecting transitive
// dependencies) during development (e.g. bug investigations). A workaround
// is to use `balena-dev` without `fast-boot`. See also notes in
// `CONTRIBUTING.md`.
const path = require('path');
const rootDir = path.join(__dirname, '..');
// Allow balena-dev to work with oclif by temporarily
// pointing oclif config options to lib/ instead of build/
modifyOclifPaths();
// Undo changes on exit
process.on('exit', function () {
modifyOclifPaths(true);
});
// Undo changes in case of ctrl-c
process.on('SIGINT', function () {
modifyOclifPaths(true);
// Note process exit here will interfere with commands that do their own SIGINT handling,
// but without it commands can not be exited.
// So currently using balena-dev does not guarantee proper exit behaviour when using ctrl-c.
// Ideally a better solution is needed.
process.exit();
});
// Set the desired es version for downstream modules that support it
require('@balena/es-version').set('es2018');
// Note: before ts-node v6.0.0, 'transpile-only' (no type checking) was the
// default option. We upgraded ts-node and found that adding 'transpile-only'
// was necessary to avoid a mysterious 'null' error message. On the plus side,
// it is supposed to run faster. We still benefit from type checking when
// running 'npm run build'.
require('ts-node').register({
project: path.join(rootDir, 'tsconfig.json'),
transpileOnly: true,
});
require('../lib/app').run(undefined, { dir: __dirname, development: true });
// Modify package.json oclif paths from build/ -> lib/, or vice versa
function modifyOclifPaths(revert) {
const fs = require('fs');
const packageJsonPath = path.join(rootDir, 'package.json');
const packageJson = fs.readFileSync(packageJsonPath, 'utf8');
const packageObj = JSON.parse(packageJson);
if (!packageObj.oclif) {
return;
}
let oclifSectionText = JSON.stringify(packageObj.oclif);
if (!revert) {
oclifSectionText = oclifSectionText.replace(/\/build\//g, '/lib/');
} else {
oclifSectionText = oclifSectionText.replace(/\/lib\//g, '/build/');
}
packageObj.oclif = JSON.parse(oclifSectionText);
fs.writeFileSync(
packageJsonPath,
`${JSON.stringify(packageObj, null, 2)}\n`,
'utf8',
);
}

3
bin/run.cmd Normal file
View File

@ -0,0 +1,3 @@
@echo off
node "%~dp0\run" %*

21
bin/run.js Normal file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env node
// We boost the threadpool size as ext2fs can deadlock with some
// operations otherwise, if the pool runs out.
process.env.UV_THREADPOOL_SIZE = '64';
// Disable oclif registering ts-node
process.env.OCLIF_TS_NODE = 0;
async function run() {
// Use fast-boot to cache require lookups, speeding up startup
await require('../build/fast-boot').start();
// Set the desired es version for downstream modules that support it
require('@balena/es-version').set('es2018');
// Run the CLI
await require('../build/app').run(undefined, { dir: __dirname });
}
run();

View File

@ -157,7 +157,7 @@ async function oclifRun(command: string[], options: AppOptions) {
await Promise.all([trackPromise, deprecationPromise, runPromise]); await Promise.all([trackPromise, deprecationPromise, runPromise]);
} }
/** CLI entrypoint. Called by the `bin/balena` and `bin/balena-dev` scripts. */ /** CLI entrypoint. Called by the `bin/run.js` and `bin/dev.js` scripts. */
export async function run(cliArgs = process.argv, options: AppOptions) { export async function run(cliArgs = process.argv, options: AppOptions) {
try { try {
const { setOfflineModeEnvVars, normalizeEnvVars, pkgExec } = await import( const { setOfflineModeEnvVars, normalizeEnvVars, pkgExec } = await import(

View File

@ -20,7 +20,7 @@
* we have permissions over the cache file before even attempting to load * we have permissions over the cache file before even attempting to load
* fast boot. * fast boot.
* DON'T IMPORT BALENA-CLI MODULES HERE, as this module is loaded directly * DON'T IMPORT BALENA-CLI MODULES HERE, as this module is loaded directly
* from `bin/balena`, before the CLI's entrypoint in `lib/app.ts`. * from `bin/run.js`, before the CLI's entrypoint in `lib/app.ts`.
*/ */
import * as fs from 'fs'; import * as fs from 'fs';

26
npm-shrinkwrap.json generated
View File

@ -98,7 +98,7 @@
"window-size": "^1.1.0" "window-size": "^1.1.0"
}, },
"bin": { "bin": {
"balena": "bin/balena" "balena": "bin/run.js"
}, },
"devDependencies": { "devDependencies": {
"@balena/lint": "^7.2.1", "@balena/lint": "^7.2.1",
@ -4030,9 +4030,9 @@
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "20.11.26", "version": "20.11.27",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.26.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.27.tgz",
"integrity": "sha512-YwOMmyhNnAWijOBQweOJnQPl068Oqd4K3OFbTc6AHJwzweUwwWG3GIFY74OKks2PJUDkQPeddOQES9mLn1CTEQ==", "integrity": "sha512-qyUZfMnCg1KEz57r7pzFtSGt49f6RPkPBis3Vo4PbS7roQEDn22hiHzl/Lo1q4i4hDEgBJmBF/NTNg2XR0HbFg==",
"dependencies": { "dependencies": {
"undici-types": "~5.26.4" "undici-types": "~5.26.4"
} }
@ -6098,9 +6098,9 @@
} }
}, },
"node_modules/balena-sdk/node_modules/@types/node": { "node_modules/balena-sdk/node_modules/@types/node": {
"version": "18.19.23", "version": "18.19.24",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.23.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.24.tgz",
"integrity": "sha512-wtE3d0OUfNKtZYAqZb8HAWGxxXsImJcPUAgZNw+dWFxO6s5tIwIjyKnY76tsTatsNCLJPkVYwUpq15D38ng9Aw==", "integrity": "sha512-eghAz3gnbQbvnHqB+mgB2ZR3aH6RhdEmHGS48BnV75KceQPHqabkxKI0BbUSsqhqy2Ddhc2xD/VAR9ySZd57Lw==",
"dependencies": { "dependencies": {
"undici-types": "~5.26.4" "undici-types": "~5.26.4"
} }
@ -28545,9 +28545,9 @@
} }
}, },
"@types/node": { "@types/node": {
"version": "20.11.26", "version": "20.11.27",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.26.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.27.tgz",
"integrity": "sha512-YwOMmyhNnAWijOBQweOJnQPl068Oqd4K3OFbTc6AHJwzweUwwWG3GIFY74OKks2PJUDkQPeddOQES9mLn1CTEQ==", "integrity": "sha512-qyUZfMnCg1KEz57r7pzFtSGt49f6RPkPBis3Vo4PbS7roQEDn22hiHzl/Lo1q4i4hDEgBJmBF/NTNg2XR0HbFg==",
"requires": { "requires": {
"undici-types": "~5.26.4" "undici-types": "~5.26.4"
} }
@ -30152,9 +30152,9 @@
}, },
"dependencies": { "dependencies": {
"@types/node": { "@types/node": {
"version": "18.19.23", "version": "18.19.24",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.23.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.24.tgz",
"integrity": "sha512-wtE3d0OUfNKtZYAqZb8HAWGxxXsImJcPUAgZNw+dWFxO6s5tIwIjyKnY76tsTatsNCLJPkVYwUpq15D38ng9Aw==", "integrity": "sha512-eghAz3gnbQbvnHqB+mgB2ZR3aH6RhdEmHGS48BnV75KceQPHqabkxKI0BbUSsqhqy2Ddhc2xD/VAR9ySZd57Lw==",
"requires": { "requires": {
"undici-types": "~5.26.4" "undici-types": "~5.26.4"
} }

View File

@ -22,7 +22,7 @@
"oclif.manifest.json" "oclif.manifest.json"
], ],
"bin": { "bin": {
"balena": "./bin/balena" "balena": "./bin/run.js"
}, },
"pkg": { "pkg": {
"scripts": [ "scripts": [
@ -75,7 +75,7 @@
"ci": "npm run test && npm run catch-uncommitted", "ci": "npm run test && npm run catch-uncommitted",
"lint": "npm run lint-tsconfig && npm run lint-other", "lint": "npm run lint-tsconfig && npm run lint-other",
"lint-tsconfig": "balena-lint -e ts -e js -t tsconfig.dev.json --fix automation/ lib/ tests/ typings/", "lint-tsconfig": "balena-lint -e ts -e js -t tsconfig.dev.json --fix automation/ lib/ tests/ typings/",
"lint-other": "balena-lint -e ts -e js --fix bin/balena bin/balena-dev completion/ .mocharc.js .mocharc-standalone.js", "lint-other": "balena-lint -e ts -e js --fix bin/run.js bin/dev.js completion/ .mocharc.js .mocharc-standalone.js",
"update": "ts-node --transpile-only ./automation/update-module.ts", "update": "ts-node --transpile-only ./automation/update-module.ts",
"prepare": "echo {} > bin/.fast-boot.json", "prepare": "echo {} > bin/.fast-boot.json",
"prepublishOnly": "npm run build" "prepublishOnly": "npm run build"

View File

@ -16,7 +16,7 @@ index c0926bd..e4f645c 100644
File /r bin File /r bin
File /r client File /r client
diff --git a/node_modules/oclif/lib/tarballs/build.js b/node_modules/oclif/lib/tarballs/build.js diff --git a/node_modules/oclif/lib/tarballs/build.js b/node_modules/oclif/lib/tarballs/build.js
index 384ea4b..4d6593a 100644 index 384ea4b..c9607f3 100644
--- a/node_modules/oclif/lib/tarballs/build.js --- a/node_modules/oclif/lib/tarballs/build.js
+++ b/node_modules/oclif/lib/tarballs/build.js +++ b/node_modules/oclif/lib/tarballs/build.js
@@ -30,7 +30,9 @@ async function build(c, options = {}) { @@ -30,7 +30,9 @@ async function build(c, options = {}) {
@ -30,12 +30,10 @@ index 384ea4b..4d6593a 100644
await Promise.all((await fs.promises.readdir(path.join(c.workspace(), 'package'), { withFileTypes: true })) await Promise.all((await fs.promises.readdir(path.join(c.workspace(), 'package'), { withFileTypes: true }))
.map(i => fs.move(path.join(c.workspace(), 'package', i.name), path.join(c.workspace(), i.name)))); .map(i => fs.move(path.join(c.workspace(), 'package', i.name), path.join(c.workspace(), i.name))));
await Promise.all([ await Promise.all([
@@ -38,6 +40,13 @@ async function build(c, options = {}) { @@ -38,6 +40,11 @@ async function build(c, options = {}) {
fs.promises.rm(path.join(c.workspace(), path.basename(tarball)), { recursive: true }), fs.promises.rm(path.join(c.workspace(), path.basename(tarball)), { recursive: true }),
fs.remove(path.join(c.workspace(), 'bin', 'run.cmd')), fs.remove(path.join(c.workspace(), 'bin', 'run.cmd')),
]); ]);
+ // rename the original balena-cli ./bin/balena entry point for oclif compatibility
+ await fs.move(path.join(c.workspace(), 'bin', 'balena'), path.join(c.workspace(), 'bin', 'run'));
+ // The oclif installers are a production installation, while the source + // The oclif installers are a production installation, while the source
+ // `bin` folder may contain a `.fast-boot.json` file of a dev installation. + // `bin` folder may contain a `.fast-boot.json` file of a dev installation.
+ // This has previously led to issues preventing the CLI from starting, so + // This has previously led to issues preventing the CLI from starting, so