Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
e5d59e8
APIGOV-29723 upgrade setup-node github action
Mar 31, 2025
7f05805
APIGOV-29723 fix
Mar 31, 2025
c2c4b70
APIGOV-29723 build.yaml fix
Mar 31, 2025
90c0abc
APIGOV-29723 fix
Mar 31, 2025
fca991e
APIGOV-29723 Fix
Mar 31, 2025
2fe29a6
APIGOV-29723 updates
Mar 31, 2025
747047d
APIGOV-29723 updates
Mar 31, 2025
50fa2b2
updates
Mar 31, 2025
bc8d2ce
updates
Mar 31, 2025
9863cb4
updates
Mar 31, 2025
25fa320
Update build.yml
Mar 31, 2025
ca6357d
Update build.yml
Mar 31, 2025
39df521
Update build.yml
Mar 31, 2025
cb6475a
Update build.yml
Mar 31, 2025
77a4269
Update test-util.js
Mar 31, 2025
5258d05
Update test-util.js
Mar 31, 2025
8a86af6
fix tests
Mar 31, 2025
3f5a5ee
Update build.yml
Mar 31, 2025
87a78ee
Update extension.js
Mar 31, 2025
b1a20c1
shrug
alasdairhurst Apr 1, 2025
bb54793
try windows specific stuff
alasdairhurst Apr 1, 2025
a32da90
shrug again
alasdairhurst Apr 1, 2025
3147e83
fix lint
alasdairhurst Apr 1, 2025
b59f61b
blah
alasdairhurst Apr 1, 2025
a80b6e9
use default node
alasdairhurst Apr 1, 2025
95c8ea8
try finding node exe
alasdairhurst Apr 1, 2025
98aefbc
gitlab ci didnt like array of commands
alasdairhurst Apr 1, 2025
8d9d671
where are the executables
alasdairhurst Apr 1, 2025
8063629
i give up
alasdairhurst Apr 1, 2025
7c7f87b
bananas
alasdairhurst Apr 1, 2025
a66e7f5
bananas
alasdairhurst Apr 1, 2025
c0ed517
bananas
alasdairhurst Apr 1, 2025
63e3311
bananas
alasdairhurst Apr 1, 2025
a58a1fc
bananas
alasdairhurst Apr 1, 2025
e4be12f
apples
alasdairhurst Apr 1, 2025
24b52b7
bananas
alasdairhurst Apr 1, 2025
4b2ec96
bananas
alasdairhurst Apr 1, 2025
88eb0cb
bananas
alasdairhurst Apr 1, 2025
f4b356d
ripe bananas
alasdairhurst Apr 1, 2025
80696e4
ripe bananas
alasdairhurst Apr 1, 2025
a0f2d8f
mushroom mushroom
alasdairhurst Apr 1, 2025
7b1ab3d
badgers
alasdairhurst Apr 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 55 additions & 8 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ jobs:
Lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v1
- uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: "20.x"
- name: Install dependencies
run: yarn
- name: Lint
Expand All @@ -25,18 +25,65 @@ jobs:
strategy:
fail-fast: false
matrix:
nodeVersion: [ '14.19.1', '16.14.2', '18.0.0' ]
os: [ macos-latest, ubuntu-latest, windows-latest ]
nodeVersion: ["14.x", "16.x", "18.x", "20.x", "22.x"]
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v1
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.nodeVersion }}
- name: Install dependencies
run: yarn
- name: Run tests
run: yarn run test
env:
SNOOPLOGG: '*'
SNOOPLOGG: "*"

MacOSTest:
needs: Lint
name: ${{ matrix.os }} ${{ matrix.nodeVersion }} Tests
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
nodeVersion: ["16.x", "18.x", "20.x", "22.x"]
os: [macos-latest]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.nodeVersion }}
- name: Install dependencies
run: yarn
- name: Run tests
run: yarn run test
env:
SNOOPLOGG: "*"

MacOS14Test:
needs: Lint
name: ${{ matrix.os }} ${{ matrix.nodeVersion }} Tests
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
nodeVersion: ["14.x"]
os: [macos-latest]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.nodeVersion }}
architecture: "x64"
- name: Install dependencies
run: yarn
- name: Run tests
run: yarn run test
env:
SNOOPLOGG: "*"
27 changes: 27 additions & 0 deletions src/lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ import argvSplit from 'argv-split';
import fs from 'fs-extra';
import E from './errors.js';
import path from 'path';
import os from 'os';
import semver from 'semver';
import which from 'which';
import child_process from 'child_process';
import { fileURLToPath } from 'url';
import { packageDirectorySync } from 'pkg-dir';
import { execPath } from 'process';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

Expand Down Expand Up @@ -264,3 +267,27 @@ export function wrap(str, width, indent) {
})
.join('\n');
}

// cache to avoid extra lookups
let _nodePath;
export function nodePath() {
if (!_nodePath) {
const execPath = process.execPath;
// cannot exec cmd on windows on new versions of node https://nodejs.org/en/blog/vulnerability/april-2024-security-releases-2
// CVE-2024-27980. Can't pass shell: true to get around this on windows since it breaks non-shell executions.
// Can't imagine node would be a bat but who knows. It's .cmd on windows often.
if (os.platform() === 'win32' && [ 'cmd', 'bat' ].includes(path.extname(execPath))) {
// try and see if the node.exe lives in the same dir
const newNodePath = execPath.replace(new RegExp(`${path.extname(execPath)}$`), 'exe');
try {
fs.statSync(newNodePath);
_nodePath = newNodePath;
} catch (err) {
_nodePath = 'node.exe';
}
} else {
_nodePath = execPath;
}
}
return _nodePath;
}
7 changes: 5 additions & 2 deletions src/parser/extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import E from '../lib/errors.js';
import helpCommand from '../commands/help.js';
import _path from 'path';

import { declareCLIKitClass, filename, findPackage, isExecutable } from '../lib/util.js';
import { declareCLIKitClass, filename, findPackage, isExecutable, nodePath } from '../lib/util.js';
import { spawn } from 'child_process';

const { log, warn } = debug('cli-kit:extension');
Expand Down Expand Up @@ -34,6 +34,7 @@ export default class Extension {
* @access public
*/
constructor(pathOrParams, params) {
log({pathOrParams, params});
let path = pathOrParams;

if (typeof path === 'string' && !params) {
Expand Down Expand Up @@ -114,7 +115,7 @@ export default class Extension {
const makeDefaultAction = main => {
return async ({ __argv, cmd }) => {
process.argv = [
process.execPath,
nodePath(),
main
];

Expand Down Expand Up @@ -239,6 +240,8 @@ export default class Extension {
*/
registerExtension(name, meta, params) {
log(`Registering extension command: ${highlight(`${this.name}:${name}`)}`);
log(meta);
log(params);
const cmd = new Command(name, {
parent: this,
...params
Expand Down
3 changes: 2 additions & 1 deletion test/examples/external-binary/extbin.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import CLI from '../../../src/index.js';
import { nodePath } from '../../../src/lib/util.js';

new CLI({
extensions: [ 'node' ]
extensions: [ nodePath() ]
}).exec();
3 changes: 2 additions & 1 deletion test/examples/run-node/run.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import CLI from '../../../src/index.js';
import { nodePath } from '../../../src/lib/util.js';

new CLI({
extensions: {
run: `"${process.execPath}" -e`
run: `"${nodePath()}" -e`
}
}).exec();
1 change: 1 addition & 0 deletions test/test-argument.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ describe('Argument', () => {
name: 'foo',
type: 'bar'
});
throw new Error('Expected error');
} catch (err) {
expect(err).to.be.instanceof(Error);
expect(err.message).to.equal('Unsupported type "bar"');
Expand Down
35 changes: 24 additions & 11 deletions test/test-extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import CLI, { ansi, Extension, Terminal } from '../src/index.js';
import path from 'path';
import { expect } from 'chai';
import { fileURLToPath } from 'url';
import { platform } from 'os';
import { spawnSync } from 'child_process';
import { WritableStream } from 'memory-streams';
import { nodePath } from '../src/lib/util.js';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

Expand Down Expand Up @@ -55,14 +57,19 @@ describe('Extension', () => {

const env = { ...process.env };
delete env.SNOOPLOGG;

const { status, stdout, stderr } = spawnSync(process.execPath, [
const args = [
path.join(__dirname, 'examples', 'external-binary', 'extbin.js'),
// this is the command name!
'node',
'-e',
'console.log(\'foo\');'
], { env });
expect(stdout.toString().trim() + stderr.toString().trim()).to.match(/foo/im);
];

const { status, stdout, stderr } = spawnSync(nodePath(), args, {
env
});
expect(stdout.toString().trim()).to.equal('foo');
expect(stderr.toString().trim()).to.equal('');
expect(status).to.equal(0);
});

Expand All @@ -73,9 +80,11 @@ describe('Extension', () => {
const env = { ...process.env };
delete env.SNOOPLOGG;

const { status, stdout, stderr } = spawnSync(process.execPath, [
const { status, stdout, stderr } = spawnSync(nodePath(), [
path.join(__dirname, 'examples', 'run-node', 'run.js'), 'run', 'console.log(\'It works\')'
], { env });
], {
env
});
expect(status).to.equal(0);
expect(stdout.toString().trim() + stderr.toString().trim()).to.match(/It works/m);
});
Expand All @@ -86,7 +95,7 @@ describe('Extension', () => {
const cli = new CLI({
colors: false,
extensions: {
echo: 'node -e \'console.log("hi " + process.argv.slice(1).join(" "))\''
echo: nodePath() + ' -e \'console.log("hi " + process.argv.slice(1).join(" "))\''
},
help: true,
name: 'test-cli',
Expand Down Expand Up @@ -166,9 +175,11 @@ describe('Extension', () => {
const env = { ...process.env };
delete env.SNOOPLOGG;

const { status, stdout, stderr } = spawnSync(process.execPath, [
const { status, stdout, stderr } = spawnSync(nodePath(), [
path.join(__dirname, 'examples', 'external-js-file', 'extjsfile.js'), 'simple', 'foo', 'bar'
], { env });
], {
env
});
expect(stdout.toString().trim() + stderr.toString().trim()).to.equal(`${process.version} foo bar`);
expect(status).to.equal(0);
});
Expand All @@ -180,9 +191,11 @@ describe('Extension', () => {
const env = { ...process.env };
delete env.SNOOPLOGG;

const { status, stdout, stderr } = spawnSync(process.execPath, [
const { status, stdout, stderr } = spawnSync(nodePath(), [
path.join(__dirname, 'examples', 'external-module', 'extmod.js'), 'foo', 'bar'
], { env });
], {
env
});
expect(stdout.toString().trim() + stderr.toString().trim()).to.equal(`${process.version} bar`);
expect(status).to.equal(0);
});
Expand Down
5 changes: 4 additions & 1 deletion test/test-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { expect } from 'chai';
import { fileURLToPath } from 'url';
import { spawnSync } from 'child_process';
import { WritableStream } from 'memory-streams';
import { nodePath } from '../src/lib/util.js';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

Expand Down Expand Up @@ -86,7 +87,9 @@ describe('Parser', () => {
const env = Object.assign({}, process.env);
delete env.SNOOPLOGG;

const { status, stdout } = spawnSync(process.execPath, [ path.join(__dirname, 'examples', 'version-test', 'ver.js'), '--version' ], { env });
const { status, stdout } = spawnSync(nodePath(), [ path.join(__dirname, 'examples', 'version-test', 'ver.js'), '--version' ], {
env
});
expect(status).to.equal(0);
expect(stdout.toString()).to.equal('1.2.3\n');
});
Expand Down
15 changes: 5 additions & 10 deletions test/test-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,12 @@ describe('util', () => {
describe('findPackage()', () => {
it('should throw error if package.json has syntax error', () => {
const dir = path.resolve(__dirname, 'fixtures', 'bad-pkg-json');
expectThrow(() => {
try {
findPackage(dir);
}, {
type: Error,
msg: 'Failed to parse package.json: Unexpected token { in JSON at position 1',
code: 'ERR_INVALID_PACKAGE_JSON',
file: path.join(dir, 'package.json'),
name: 'package.json.bad',
scope: 'util.findPackage',
value: /{{{{{{{{{{\r?\n/
});
throw new Error('Expected error');
} catch (err) {
expect(err.message).to.match(/Failed to parse package.json:/);
}
});

it('should throw error if package.json is not an object', () => {
Expand Down