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
Each CLI module package now includes a bin script and cli.ts entry
point, allowing modules to be executed directly via npx without
being wired into the main @backstage/cli package.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
The info command now tries to resolve the @backstage/cli version at
runtime instead of using a hardcoded relative path. This allows the
module to work standalone when the CLI package is not present. The
module's own version is always reported as infoModuleVersion.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Add a public `runCliModule` function to `@backstage/cli-node` that
allows CLI module packages to be executed directly as standalone
programs, without needing to be wired into a larger CLI host.
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
Automatically apply `target="_blank"` and `rel="noopener noreferrer"` on
`Row` when `href` is an external link, so external links in default BUI
Table rows open in a new tab instead of navigating the current page.
`rel` tokens are merged rather than replaced, so consumer-provided tokens
(e.g. `rel="nofollow"`) are preserved while `noopener noreferrer` is
always enforced whenever `target="_blank"` is in effect.
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
- Changed Container default bottom spacing from padding-bottom to margin-bottom
- Prevented the Container margin-bottom from applying when used as the Header root element via mb="0"
- Renamed Header CSS classes from bui-HeaderPage* to bui-Header* to match the component name
Fixes https://linear.app/spotify/issue/BACUI-249
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
Made-with: Cursor
Replaces the invalid `min(auto, calc(100vh - 3rem))` CSS pattern with a
flex-based layout. The dialog now grows with its content by default and
scrolls when the content exceeds the viewport height. A fixed height can
still be applied via the `height` prop.
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
Made-with: Cursor
Use spread for conditional selection props. Add a dedicated loading
prop and data-loading data attribute to TableRoot, distinct from
stale. Both set aria-busy and default to the same opacity, but
consumers can now style them independently.
Signed-off-by: Jonathan Roebuck <jroebuck@spotify.com>
Remove inaccurate aria-busy claim from changeset — react-aria-components
does not forward it to the DOM.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Jonathan Roebuck <jroebuck@spotify.com>
Removed per reviewer feedback — BUI Table relies on Storybook visual
tests rather than unit tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Jonathan Roebuck <jroebuck@spotify.com>
- Add @testing-library/jest-dom and @testing-library/react as explicit
devDependencies for @backstage/ui
- Disable selection on TableRoot during initial loading to prevent
interaction with skeleton rows
- Clarify test comment about aria-busy vs data-stale behavior
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Jonathan Roebuck <jroebuck@spotify.com>
Add a skeleton loading state to the BUI Table component that shows the
table header with animated skeleton rows instead of plain "Loading..."
text. Includes accessibility support via aria-busy and live region
announcements.
BUCKS-2919
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Jonathan Roebuck <jroebuck@spotify.com>