Add a new `cli-module` template to the Backstage CLI that scaffolds
CLI module packages. This includes adding the `cli-module` role to the
template system, with proper naming conventions and prompts.
The generated package includes:
- A bin entry point for standalone execution
- An index.ts with createCliModule setup
- An example command using cleye
- Standard package.json with cli-module role
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Fix argument parsing bugs in the execute command where actionId at index 0
was incorrectly skipped when --instance was absent, and flag values matching
the actionId string were erroneously removed. Add --help support to the
execute command for CLI report generation. Add missing bin script and
cli-report.md for cli-module-actions. Add resolveAuth tests. Bump
backend-defaults changeset to minor for the security-relevant auth change.
Replace cross-fetch with native fetch in cli-module-auth to avoid punycode
deprecation warnings during CLI report generation.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Update the new frontend plugin template to use createDevApp in its dev entry point and teach cli-module-new to resolve frontend-dev-utils versions for generated packages.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
- Use cli-defaults instead of listing individual CLI modules in
create-app template and root package.json
- Move nodeTransform config files from cli-module-build to cli-node
to avoid cross-module direct imports
- Rename cli-module-create-github-app to cli-module-github
- Start createCliModule init chain with Promise.resolve()
- Deduplicate exitWithError in runCliModule.ts
- Extract shared isCommandNodeHidden to @internal/cli
- Add explanatory comment for fromArray deduplication field
- Restore error for cli role packages missing bin in runCliExtraction
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Move jest config files to cli-module-test-jest/config and node
transform + webpack-public-path to cli-module-build/config. Replace
originals in @backstage/cli/config with lazy proxies that forward
to the appropriate module or throw if it is not installed.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Individual CLI modules now silently take precedence over array-sourced
modules (e.g. from cli-defaults) when their commands overlap. Conflict
errors between non-array modules include both package names for easier
debugging.
Commands reference their parent module instead of storing a raw package
name string. createCliModule now validates that packageJson has a name.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Introduces a new `@backstage/cli-defaults` package that re-exports all
standard CLI modules as a single array, simplifying dependency management
for consumers. The CLI's `CliInitializer` is updated to support array
exports alongside single module exports. The create-app template,
changesets, and CLI fallback are updated to use `@backstage/cli-defaults`
instead of listing 11 individual modules.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
On Windows, require.resolve() returns paths like D:\...\index.cjs.js
which when passed to import() causes ERR_UNSUPPORTED_ESM_URL_SCHEME
because the D: prefix is interpreted as a URL protocol. Use
pathToFileURL() to produce proper file:// URLs.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
The CLI provides tsconfig presets that include webpack-env in the
types array, so @types/webpack-env must remain a dependency of the
CLI package for consuming apps to compile correctly.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Align dependency versions in CLI modules to match the original CLI
package versions. Move dependencies that are only used by modules out
of the main CLI package, and add missing dependencies to the modules
that actually use them. Revert import-to-require conversions in
cli-module-build that were incorrectly introduced during the split.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Resolve CLI module entry points relative to the target project root
rather than relying on bare module name resolution. This ensures modules
are found even when the CLI package is symlinked from a separate location,
such as in the E2E test workspace setup.
Also add the missing cli-module-* entries to the create-app tasks test
mock that were omitted in a previous commit.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
The CLI now scans the project root's dependencies and devDependencies
for packages with the cli-module role, loading them automatically.
Falls back to the built-in set with a deprecation warning when no
modules are found. Updated create-app templates and the monorepo root
to include all CLI modules as explicit devDependencies.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Rename createCliPlugin to createCliModule, CliPlugin to CliModule, and
the cli-plugin package role to cli-module to better distinguish CLI
modules from other plugin types.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Move createCliPlugin and related types from the standalone
@backstage/cli-plugin-api package into @backstage/cli-node and
remove the now-empty package.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Switch CommandGraph and CliInitializer to use OpaqueCommandTreeNode and
OpaqueCommandLeafNode from @internal/cli instead of raw $$type markers.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Add thorough TSDoc comments to createCliPlugin, BackstageCommand,
CommandContext, and CliPlugin. Remove the CliFeature type alias in
favor of using CliPlugin directly.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Replace pluginId with packageJson input for createCliPlugin, remove
CommandExecuteFn type alias by inlining it, and rename
CommandContext.info.description to info.name.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Move OpaqueCliPlugin to a new @internal/cli inline package, following the
same pattern as @internal/frontend. Both cli-plugin-api and cli import it
directly, and it gets bundled into their dists at build time.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Move error handling and lazy utilities back to @backstage/cli since they
are host-only concerns. The cli-plugin-api internals subpath provides
isCliPlugin and initializeCliPlugin for the CLI host.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Bump cleye to ^2.3.0 (which pulls in type-flag 4.1.0) and enable
booleanFlagNegation: true in all cli() invocations so that boolean
flags automatically support --no-<flag> prefix negation.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
* feat(cli): add auth commands for OIDC login
Signed-off-by: benjdlambert <ben@blam.sh>
* address PR review feedback
- move CIMD check before callback server start
- add try/finally for callback server cleanup
- validate URLs with human-readable errors
- deduplicate config URL candidates
- preserve selected flag on re-authentication
- delete accessToken on logout
- log token refresh to stderr in show command
- fix command descriptions to reference CIMD not DCR
- type keytar as optionalDependency, rename storage paths
- add auth-backend changeset
Signed-off-by: benjdlambert <ben@blam.sh>
* migrate auth module from yargs to cleye pattern
Signed-off-by: benjdlambert <ben@blam.sh>
* address PR review feedback
- consolidate storage imports in auth.ts
- add withMetadataLock to setSelectedInstance
- skip file permission tests on Windows
- clarify changeset endpoint path
Signed-off-by: benjdlambert <ben@blam.sh>
* address review feedback from Rugvip and Copilot
- use stdout for user-facing messages instead of stderr
- remove clientSecret remnants from logout
- make refresh_token optional in token response schema
- add timeout to CIMD metadata fetch
- pass same state to callback server and authorize URL
- remove inaccurate test comment
Signed-off-by: benjdlambert <ben@blam.sh>
* validate state in callback server, add CIMD endpoint tests
- localServer now validates the OAuth state parameter in the request
handler and returns 400 on mismatch
- Added tests for the CIMD metadata endpoint in OidcRouter covering
both disabled and enabled cases
Signed-off-by: benjdlambert <ben@blam.sh>
* revert validateRequest to use Zod error details
Signed-off-by: benjdlambert <ben@blam.sh>
* fix callback server hanging by closing keep-alive connections
Signed-off-by: benjdlambert <ben@blam.sh>
* rename secret store service prefix to backstage-cli:auth-instance
Signed-off-by: benjdlambert <ben@blam.sh>
---------
Signed-off-by: benjdlambert <ben@blam.sh>
* feat(org): migrate MembersListCard to BUI EntityInfoCard
Signed-off-by: Johan Persson <johanopersson@gmail.com>
* feat(org)!: migrate OwnershipCard to BUI EntityInfoCard
Replaced MUI InfoCard with BUI EntityInfoCard in OwnershipCard.
Removed the `variant` and `maxScrollHeight` props since card sizing
and scrolling are now handled by the BUI layout. Wrapped body content
in a flex column div to keep the relations toggle pinned while the
grid scrolls. Updated app-legacy and create-app templates to remove
the dropped `variant` prop.
Signed-off-by: Johan Persson <johanopersson@gmail.com>
* feat(catalog-graph)!: migrate CatalogGraphCard to BUI EntityInfoCard
Replace MUI InfoCard with BUI EntityInfoCard in CatalogGraphCard.
The `variant` prop is removed — card sizing is now handled by the
BUI layout system. The deep link is replaced with a footer Link.
Remove `variant="gridItem"` from all EntityCatalogGraphCard usages
in app-legacy and create-app templates.
Signed-off-by: Johan Persson <johanopersson@gmail.com>
* feat(catalog-react): export useEntityRoute hook
Signed-off-by: Johan Persson <johanopersson@gmail.com>
* fix(cli): update translation extraction test for renamed org keys
Signed-off-by: Johan Persson <johanopersson@gmail.com>
---------
Signed-off-by: Johan Persson <johanopersson@gmail.com>
Log a warning to stderr when users pass the camelCase form of flags
that now have kebab-case as the canonical spelling. The old forms
still work (type-flag handles both natively) but users should migrate.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
type-flag natively supports both camelCase and kebab-case for all
flags, so no deprecation warnings or normalization are needed for
casing variants. Only the --alwaysYarnPack alias (a genuinely
different name) still requires normalization in buildWorkspace.
Also inlined flagDefs at each call site and updated the changeset
to reflect that both flag forms work transparently.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Remove the central warnDeprecatedFlags helper and replace with
module-specific deprecation checks at each call site. This avoids
cross-module dependencies and makes the deprecated flag mappings
explicit where they are consumed.
Also fix buildWorkspace.ts to emit the deprecation warning during
flag normalization (where the old flags are actually intercepted),
and add positional parameter declaration to package lint so that
directories show in help output.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Handle --alwaysPack=value and --alwaysYarnPack=value variants in the
legacy flag normalization, not just the bare flag forms.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
- Remove unnecessary optional chaining on getRoleInfo().role since it
throws for unknown roles.
- Add parameters declaration to repo start so [packages...] shows in
help output.
- Add tests verifying cleye strips Backstage flags from args before
forwarding to Jest, including legacy camelCase flag support.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Instead of a hard breaking change, the old camelCase flag names
(--baseVersion, --successCache, --successCacheDir, --alwaysPack) still
work via type-flag's built-in camelCase/kebab-case mapping, but now
print a deprecation warning pointing to the new kebab-case spelling.
Downgrades the changeset from minor (breaking) to patch.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Move the empty-string-to-boolean conversion from cleye's String type
into the command handlers so that startPackage/runBackend keep their
existing boolean | string interface.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
- 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
- Handle --inspect/--inspect-brk optional host value by extracting
them from raw args before passing to cleye (supports both bare
--inspect and --inspect=host:port forms)
- Change require flag from [String] to String in package start since
downstream only accepts a single value
- Preserve legacy --alwaysYarnPack alias in build-workspace command
- Update changeset to mention camelCase → kebab-case flag changes
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
- Handle quoted arguments in createScriptOptionsParser using a proper
shell-like splitter instead of naive whitespace splitting
- Pass CommandContext directly in bump tests instead of using a helper
- Regenerate cli-report.md
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
All command handlers in the CLI now use cleye or node:util.parseArgs
for argument parsing instead of commander. The top-level command
registration in CliInitializer still uses commander, but all individual
command implementations are now independent of it.
Modules migrated: build, lint, test, maintenance, migrate, new, and
create-github-app. Also replaced createScriptOptionsParser in both
build and lint modules to use node:util.parseArgs instead of commander.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Each file now has a default export matching the CommandExecuteFn
pattern, removing the need for import wrapping in the loader.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor