Remove custom inspect flag handling, switch repo test to cleye
- Use cleye's `type: String` for --inspect/--inspect-brk instead of custom extractInspectFlags pre-processing in both package start and repo start commands. - Switch repo test from node:util parseArgs to cleye so that --help shows Backstage-specific flags rather than dumping Jest's full help. - Fix create-github-app help output to include <github-org> positional. - Update downstream inspect types from `boolean | string` to `string`. Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com> Made-with: Cursor
This commit is contained in:
+11
-107
@@ -131,7 +131,7 @@ Options:
|
||||
### `backstage-cli create-github-app`
|
||||
|
||||
```
|
||||
Usage: backstage-cli create-github-app
|
||||
Usage: backstage-cli create-github-app <github-org>
|
||||
|
||||
Options:
|
||||
-h, --help
|
||||
@@ -310,6 +310,8 @@ Options:
|
||||
--check
|
||||
--config <string>
|
||||
--entrypoint <string>
|
||||
--inspect <string>
|
||||
--inspect-brk <string>
|
||||
--link <string>
|
||||
--require <string>
|
||||
--role <string>
|
||||
@@ -513,6 +515,8 @@ Usage: backstage-cli repo start
|
||||
|
||||
Options:
|
||||
--config <string>
|
||||
--inspect <string>
|
||||
--inspect-brk <string>
|
||||
--link <string>
|
||||
--plugin <string>
|
||||
--require <string>
|
||||
@@ -522,114 +526,14 @@ Options:
|
||||
### `backstage-cli repo test`
|
||||
|
||||
```
|
||||
Usage: <none>
|
||||
Usage: backstage-cli repo test
|
||||
|
||||
Options:
|
||||
--all
|
||||
--automock
|
||||
--cache
|
||||
--cacheDirectory
|
||||
--changedFilesWithAncestor
|
||||
--changedSince
|
||||
--ci
|
||||
--clearCache
|
||||
--clearMocks
|
||||
--collectCoverage
|
||||
--collectCoverageFrom
|
||||
--color
|
||||
--colors
|
||||
--coverage
|
||||
--coverageDirectory
|
||||
--coveragePathIgnorePatterns
|
||||
--coverageProvider
|
||||
--coverageReporters
|
||||
--coverageThreshold
|
||||
--debug
|
||||
--detectLeaks
|
||||
--detectOpenHandles
|
||||
--errorOnDeprecated
|
||||
--filter
|
||||
--findRelatedTests
|
||||
--forceExit
|
||||
--globalSetup
|
||||
--globalTeardown
|
||||
--globals
|
||||
--haste
|
||||
--help
|
||||
--ignoreProjects
|
||||
--injectGlobals
|
||||
--json
|
||||
--lastCommit
|
||||
--listTests
|
||||
--logHeapUsage
|
||||
--maxConcurrency
|
||||
--moduleDirectories
|
||||
--moduleFileExtensions
|
||||
--moduleNameMapper
|
||||
--modulePathIgnorePatterns
|
||||
--modulePaths
|
||||
--noStackTrace
|
||||
--notify
|
||||
--notifyMode
|
||||
--openHandlesTimeout
|
||||
--outputFile
|
||||
--passWithNoTests
|
||||
--preset
|
||||
--prettierPath
|
||||
--projects
|
||||
--randomize
|
||||
--reporters
|
||||
--resetMocks
|
||||
--resetModules
|
||||
--resolver
|
||||
--restoreMocks
|
||||
--rootDir
|
||||
--roots
|
||||
--runTestsByPath
|
||||
--runner
|
||||
--seed
|
||||
--selectProjects
|
||||
--setupFiles
|
||||
--setupFilesAfterEnv
|
||||
--shard
|
||||
--showConfig
|
||||
--showSeed
|
||||
--silent
|
||||
--skipFilter
|
||||
--snapshotSerializers
|
||||
--testEnvironment, --env
|
||||
--testEnvironmentOptions
|
||||
--testFailureExitCode
|
||||
--testLocationInResults
|
||||
--testMatch
|
||||
--testPathIgnorePatterns
|
||||
--testPathPatterns
|
||||
--testRegex
|
||||
--testResultsProcessor
|
||||
--testRunner
|
||||
--testSequencer
|
||||
--testTimeout
|
||||
--transform
|
||||
--transformIgnorePatterns
|
||||
--unmockedModulePathPatterns
|
||||
--useStderr
|
||||
--verbose
|
||||
--version
|
||||
--waitForUnhandledRejections
|
||||
--watch
|
||||
--watchAll
|
||||
--watchPathIgnorePatterns
|
||||
--watchman
|
||||
--workerThreads
|
||||
-b, --bail
|
||||
-c, --config
|
||||
-e, --expand
|
||||
-f, --onlyFailures
|
||||
-i, --runInBand
|
||||
-o, --onlyChanged
|
||||
-t, --testNamePattern
|
||||
-u, --updateSnapshot
|
||||
-w, --maxWorkers
|
||||
--jest-help
|
||||
--since <string>
|
||||
--success-cache
|
||||
--success-cache-dir <string>
|
||||
-h, --help
|
||||
```
|
||||
|
||||
### `backstage-cli translations`
|
||||
|
||||
@@ -22,11 +22,17 @@ import { targetPaths } from '@backstage/cli-common';
|
||||
import type { CommandContext } from '../../../../../wiring/types';
|
||||
|
||||
export default async ({ args, info }: CommandContext) => {
|
||||
const { inspectEnabled, inspectBrkEnabled, filteredArgs } =
|
||||
extractInspectFlags(args);
|
||||
|
||||
const {
|
||||
flags: { config, role, check, require: requirePath, link, entrypoint },
|
||||
flags: {
|
||||
config,
|
||||
role,
|
||||
check,
|
||||
require: requirePath,
|
||||
link,
|
||||
entrypoint,
|
||||
inspect,
|
||||
inspectBrk,
|
||||
},
|
||||
} = cli(
|
||||
{
|
||||
help: info,
|
||||
@@ -57,10 +63,20 @@ export default async ({ args, info }: CommandContext) => {
|
||||
description:
|
||||
'The entrypoint to start from, relative to the package root. Can point to either a file (without extension) or a directory (in which case the index file in that directory is used). Defaults to "dev"',
|
||||
},
|
||||
inspect: {
|
||||
type: String,
|
||||
description:
|
||||
'Enable the Node.js inspector, optionally at a specific host:port',
|
||||
},
|
||||
inspectBrk: {
|
||||
type: String,
|
||||
description:
|
||||
'Enable the Node.js inspector and break before user code starts',
|
||||
},
|
||||
},
|
||||
},
|
||||
undefined,
|
||||
filteredArgs,
|
||||
args,
|
||||
);
|
||||
|
||||
await startPackage({
|
||||
@@ -70,38 +86,8 @@ export default async ({ args, info }: CommandContext) => {
|
||||
configPaths: config,
|
||||
checksEnabled: Boolean(check),
|
||||
linkedWorkspace: await resolveLinkedWorkspace(link),
|
||||
inspectEnabled,
|
||||
inspectBrkEnabled,
|
||||
inspectEnabled: inspect,
|
||||
inspectBrkEnabled: inspectBrk,
|
||||
require: requirePath,
|
||||
});
|
||||
};
|
||||
|
||||
// --inspect and --inspect-brk accept an optional host value, which cleye
|
||||
// can't express (it only supports required or no value). We extract them
|
||||
// from the raw args before passing the rest to cleye.
|
||||
function extractInspectFlags(args: string[]) {
|
||||
let inspectEnabled: boolean | string | undefined;
|
||||
let inspectBrkEnabled: boolean | string | undefined;
|
||||
const filteredArgs: string[] = [];
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i];
|
||||
if (arg === '--inspect' || arg === '--inspect-brk') {
|
||||
const next = args[i + 1];
|
||||
const value = next && !next.startsWith('-') ? args[++i] : true;
|
||||
if (arg === '--inspect') {
|
||||
inspectEnabled = value;
|
||||
} else {
|
||||
inspectBrkEnabled = value;
|
||||
}
|
||||
} else if (arg.startsWith('--inspect=')) {
|
||||
inspectEnabled = arg.slice('--inspect='.length);
|
||||
} else if (arg.startsWith('--inspect-brk=')) {
|
||||
inspectBrkEnabled = arg.slice('--inspect-brk='.length);
|
||||
} else {
|
||||
filteredArgs.push(arg);
|
||||
}
|
||||
}
|
||||
|
||||
return { inspectEnabled, inspectBrkEnabled, filteredArgs };
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ import { runBackend } from '../../../lib/runner';
|
||||
interface StartBackendOptions {
|
||||
targetDir: string;
|
||||
checksEnabled: boolean;
|
||||
inspectEnabled?: boolean | string;
|
||||
inspectBrkEnabled?: boolean | string;
|
||||
inspectEnabled?: string;
|
||||
inspectBrkEnabled?: string;
|
||||
linkedWorkspace?: string;
|
||||
require?: string;
|
||||
}
|
||||
|
||||
@@ -38,8 +38,8 @@ export async function startPackage(options: {
|
||||
targetDir: string;
|
||||
configPaths: string[];
|
||||
checksEnabled: boolean;
|
||||
inspectEnabled?: boolean | string;
|
||||
inspectBrkEnabled?: boolean | string;
|
||||
inspectEnabled?: string;
|
||||
inspectBrkEnabled?: string;
|
||||
linkedWorkspace?: string;
|
||||
require?: string;
|
||||
}): Promise<void> {
|
||||
|
||||
@@ -36,11 +36,8 @@ const ACCEPTED_PACKAGE_ROLES: Array<PackageRole | undefined> = [
|
||||
];
|
||||
|
||||
export default async ({ args, info }: CommandContext) => {
|
||||
const { inspectEnabled, inspectBrkEnabled, filteredArgs } =
|
||||
extractInspectFlags(args);
|
||||
|
||||
const {
|
||||
flags: { plugin, config, require: requirePath, link },
|
||||
flags: { plugin, config, require: requirePath, link, inspect, inspectBrk },
|
||||
_: namesOrPaths,
|
||||
} = cli(
|
||||
{
|
||||
@@ -66,10 +63,20 @@ export default async ({ args, info }: CommandContext) => {
|
||||
type: String,
|
||||
description: 'Link an external workspace for module resolution',
|
||||
},
|
||||
inspect: {
|
||||
type: String,
|
||||
description:
|
||||
'Enable the Node.js inspector, optionally at a specific host:port',
|
||||
},
|
||||
inspectBrk: {
|
||||
type: String,
|
||||
description:
|
||||
'Enable the Node.js inspector and break before user code starts',
|
||||
},
|
||||
},
|
||||
},
|
||||
undefined,
|
||||
filteredArgs,
|
||||
args,
|
||||
);
|
||||
|
||||
const targetPackages = await findTargetPackages(namesOrPaths, plugin);
|
||||
@@ -77,8 +84,8 @@ export default async ({ args, info }: CommandContext) => {
|
||||
const packageOptions = await resolvePackageOptions(targetPackages, {
|
||||
plugin,
|
||||
config,
|
||||
inspect: inspectEnabled,
|
||||
inspectBrk: inspectBrkEnabled,
|
||||
inspect,
|
||||
inspectBrk,
|
||||
require: requirePath,
|
||||
link,
|
||||
});
|
||||
@@ -204,8 +211,8 @@ export async function findTargetPackages(
|
||||
type CommandOptions = {
|
||||
plugin: string[];
|
||||
config: string[];
|
||||
inspect?: boolean | string;
|
||||
inspectBrk?: boolean | string;
|
||||
inspect?: string;
|
||||
inspectBrk?: string;
|
||||
require?: string;
|
||||
link?: string;
|
||||
};
|
||||
@@ -263,33 +270,3 @@ async function resolvePackageOptions(
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
// --inspect and --inspect-brk accept an optional host value, which cleye
|
||||
// can't express (it only supports required or no value). We extract them
|
||||
// from the raw args before passing the rest to cleye.
|
||||
function extractInspectFlags(args: string[]) {
|
||||
let inspectEnabled: boolean | string | undefined;
|
||||
let inspectBrkEnabled: boolean | string | undefined;
|
||||
const filteredArgs: string[] = [];
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i];
|
||||
if (arg === '--inspect' || arg === '--inspect-brk') {
|
||||
const next = args[i + 1];
|
||||
const value = next && !next.startsWith('-') ? args[++i] : true;
|
||||
if (arg === '--inspect') {
|
||||
inspectEnabled = value;
|
||||
} else {
|
||||
inspectBrkEnabled = value;
|
||||
}
|
||||
} else if (arg.startsWith('--inspect=')) {
|
||||
inspectEnabled = arg.slice('--inspect='.length);
|
||||
} else if (arg.startsWith('--inspect-brk=')) {
|
||||
inspectBrkEnabled = arg.slice('--inspect-brk='.length);
|
||||
} else {
|
||||
filteredArgs.push(arg);
|
||||
}
|
||||
}
|
||||
|
||||
return { inspectEnabled, inspectBrkEnabled, filteredArgs };
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ describe('runBackend', () => {
|
||||
|
||||
runBackend({
|
||||
entry: 'src/index',
|
||||
inspectEnabled: true,
|
||||
inspectEnabled: '',
|
||||
});
|
||||
|
||||
// Fast-forward past the debounce delay (100ms)
|
||||
|
||||
@@ -38,9 +38,9 @@ export type RunBackendOptions = {
|
||||
/** relative entry point path without extension, e.g. 'src/index' */
|
||||
entry: string;
|
||||
/** Whether to forward the --inspect flag to the node process */
|
||||
inspectEnabled?: boolean | string;
|
||||
inspectEnabled?: string;
|
||||
/** Whether to forward the --inspect-brk flag to the node process */
|
||||
inspectBrkEnabled?: boolean | string;
|
||||
inspectBrkEnabled?: string;
|
||||
/** Additional module to require via the --require flag to the node process */
|
||||
require?: string | string[];
|
||||
/** An external linked workspace to override module resolution towards */
|
||||
@@ -96,18 +96,18 @@ export async function runBackend(options: RunBackendOptions) {
|
||||
}
|
||||
|
||||
const optionArgs = new Array<string>();
|
||||
if (options.inspectEnabled) {
|
||||
const inspect =
|
||||
typeof options.inspectEnabled === 'string'
|
||||
if (options.inspectEnabled !== undefined) {
|
||||
optionArgs.push(
|
||||
options.inspectEnabled
|
||||
? `--inspect=${options.inspectEnabled}`
|
||||
: '--inspect';
|
||||
optionArgs.push(inspect);
|
||||
} else if (options.inspectBrkEnabled) {
|
||||
const inspect =
|
||||
typeof options.inspectBrkEnabled === 'string'
|
||||
: '--inspect',
|
||||
);
|
||||
} else if (options.inspectBrkEnabled !== undefined) {
|
||||
optionArgs.push(
|
||||
options.inspectBrkEnabled
|
||||
? `--inspect-brk=${options.inspectBrkEnabled}`
|
||||
: '--inspect-brk';
|
||||
optionArgs.push(inspect);
|
||||
: '--inspect-brk',
|
||||
);
|
||||
}
|
||||
if (options.require) {
|
||||
const requires = [options.require].flat();
|
||||
|
||||
@@ -31,7 +31,7 @@ import type { CommandContext } from '../../../../wiring/types';
|
||||
export default async ({ args, info }: CommandContext) => {
|
||||
const { _: positionals } = cli(
|
||||
{
|
||||
help: info,
|
||||
help: { ...info, usage: `${info.usage} <github-org>` },
|
||||
parameters: ['<github-org>'],
|
||||
},
|
||||
undefined,
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import os from 'node:os';
|
||||
import crypto from 'node:crypto';
|
||||
import { parseArgs } from 'node:util';
|
||||
import { cli } from 'cleye';
|
||||
import yargs from 'yargs';
|
||||
// 'jest-cli' is included with jest and should be kept in sync with the installed jest version
|
||||
// eslint-disable-next-line @backstage/no-undeclared-imports
|
||||
@@ -131,41 +131,41 @@ export function createFlagFinder(args: string[]) {
|
||||
};
|
||||
}
|
||||
|
||||
function removeOptionArg(args: string[], option: string, size: number = 2) {
|
||||
let changed = false;
|
||||
do {
|
||||
changed = false;
|
||||
|
||||
const index = args.indexOf(option);
|
||||
if (index >= 0) {
|
||||
changed = true;
|
||||
args.splice(index, size);
|
||||
}
|
||||
const indexEq = args.findIndex(arg => arg.startsWith(`${option}=`));
|
||||
if (indexEq >= 0) {
|
||||
changed = true;
|
||||
args.splice(indexEq, 1);
|
||||
}
|
||||
} while (changed);
|
||||
}
|
||||
|
||||
export default async ({ args }: CommandContext) => {
|
||||
export default async ({ args, info }: CommandContext) => {
|
||||
const testGlobal = global as TestGlobal;
|
||||
|
||||
// Parse our own flags from the raw args using strict: false to allow Jest flags through
|
||||
const { values: opts } = parseArgs({
|
||||
args,
|
||||
strict: false,
|
||||
options: {
|
||||
since: { type: 'string' },
|
||||
successCache: { type: 'boolean' },
|
||||
successCacheDir: { type: 'string' },
|
||||
'jest-help': { type: 'boolean' },
|
||||
// Parse Backstage-specific flags; unknown flags and arguments are left in
|
||||
// args so they can be forwarded to Jest.
|
||||
const { flags: opts } = cli(
|
||||
{
|
||||
help: info,
|
||||
flags: {
|
||||
since: {
|
||||
type: String,
|
||||
description:
|
||||
'Only include test packages changed since the specified ref',
|
||||
},
|
||||
successCache: {
|
||||
type: Boolean,
|
||||
description: 'Cache and skip tests for unchanged packages',
|
||||
},
|
||||
successCacheDir: {
|
||||
type: String,
|
||||
description: 'Directory for the success cache',
|
||||
},
|
||||
jestHelp: {
|
||||
type: Boolean,
|
||||
description: "Show Jest's own help output",
|
||||
},
|
||||
},
|
||||
ignoreArgv: type => type === 'unknown-flag' || type === 'argument',
|
||||
},
|
||||
});
|
||||
undefined,
|
||||
args,
|
||||
);
|
||||
|
||||
const hasFlags = createFlagFinder(args);
|
||||
const sinceRef = typeof opts.since === 'string' ? opts.since : undefined;
|
||||
const sinceRef = opts.since || undefined;
|
||||
|
||||
// Parse the args to ensure that no file filters are provided, in which case we refuse to run
|
||||
const { _: parsedArgs } = await yargs(args).options(jestYargsOptions).argv;
|
||||
@@ -252,10 +252,6 @@ export default async ({ args }: CommandContext) => {
|
||||
args.push('--maxWorkers=2');
|
||||
}
|
||||
|
||||
if (opts.since) {
|
||||
removeOptionArg(args, '--since');
|
||||
}
|
||||
|
||||
let packageGraph: PackageGraph | undefined;
|
||||
async function getPackageGraph() {
|
||||
if (packageGraph) {
|
||||
@@ -310,17 +306,13 @@ export default async ({ args }: CommandContext) => {
|
||||
}--no-node-snapshot`;
|
||||
}
|
||||
|
||||
if (opts['jest-help']) {
|
||||
removeOptionArg(args, '--jest-help');
|
||||
if (opts.jestHelp) {
|
||||
args.push('--help');
|
||||
}
|
||||
|
||||
// This code path is enabled by the --successCache flag, which is specific to
|
||||
// the `repo test` command in the Backstage CLI.
|
||||
if (opts.successCache) {
|
||||
removeOptionArg(args, '--successCache', 1);
|
||||
removeOptionArg(args, '--successCacheDir');
|
||||
|
||||
// Refuse to run if file filters are provided
|
||||
if (parsedArgs.length > 0) {
|
||||
throw new Error(
|
||||
@@ -338,7 +330,7 @@ export default async ({ args }: CommandContext) => {
|
||||
|
||||
const cache = SuccessCache.create({
|
||||
name: 'test',
|
||||
basePath: opts.successCacheDir as string | undefined,
|
||||
basePath: opts.successCacheDir,
|
||||
});
|
||||
const graph = await getPackageGraph();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user