Commit 2d59f34
feat(install-dynamic-plugins): add @red-hat-developer-hub/cli-module-install-dynamic-plugins (#3246)
* feat(install-dynamic-plugins): import package from redhat-developer/rhdh
Migrates scripts/install-dynamic-plugins/ from redhat-developer/rhdh#4574
into this repo as @red-hat-developer-hub/install-dynamic-plugins so it
can be published to npm and consumed by the RHDH init-container without
curl-by-SHA.
Runtime contract (CLI args, env vars, plugin-hash format, on-disk layout,
tar/OCI security guards) preserved verbatim. Build remains a single
self-contained .cjs via esbuild. Tests migrated from vitest to jest to
align with the repo's backstage-cli pipeline (14 suites / 166 tests pass).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(install-dynamic-plugins): address self-review feedback
- Add bin/install-dynamic-plugins shim and have package.json bin point at
it (matches the convention used by extensions-cli, translations-cli, and
rhdh-repo-tools). Split src/cli.ts as the esbuild entry so the bundle
no longer needs the require.main guard or a shebang banner.
- Stop committing dist/install-dynamic-plugins.cjs; the release pipeline
rebuilds via the customBuild path, and a new prepack script makes
yarn npm publish self-healing for local runs.
- Drop the .js suffix from relative imports across src/ so the package
matches the rest of the repo and the jest moduleNameMapper workaround
is no longer needed.
- Consolidate the tsconfigs: the inner package extends the workspace
tsconfig and only declares what differs.
- Add why-it's-intentional comments to the two eslint-disable lines
(PullPolicy const+type pair, tar.x filter inside a sequential loop).
- README now leads with the npm/npx usage path; the RHDH init-container
section is below.
tar/yaml stay in dependencies (not devDependencies as the review
suggested) — @backstage/no-undeclared-imports flagged the source
imports, and the repo convention treats bundling as opaque.
166/166 tests pass, tsc/lint/prettier clean, bin shim and bundle both
exit 0 on the empty-config smoke run.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(install-dynamic-plugins): unblock CI api-reports step
The CI step "check api reports and generate API reference" runs
`backstage-repo-tools api-reports --ci` before the build, and that tool
requires the bin file to introspect the CLI. The previous shim did a
plain `require('../dist/install-dynamic-plugins.cjs')`, which failed
under CI because dist/ is no longer committed and the build hasn't run
yet.
- Switch the bin shim to the local-vs-installed pattern used by every
other CLI in the repo (extensions-cli, translations-cli,
rhdh-repo-tools): when `src/` exists (monorepo), load TS directly via
`@backstage/cli/config/nodeTransform`; otherwise require the built
bundle (npm-installed scenario).
- Add `--help` / `-h` handling to main() so the api-reports tool can
introspect the CLI usage without creating a stray `--help/` directory.
- Commit the generated `cli-report.md`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(install-dynamic-plugins): address SonarCloud findings
- Use String.raw for strings containing backslash literals so the source
reads with one '\' instead of '\\\\' (catalog-index.ts log message,
extra-catalog-index.test.ts subdirectory fixtures, skopeo.test.ts shell
escape).
- Switch the OCI regex builder to a joined string array — eliminates the
nested template literals SonarCloud was flagging on oci-key.ts (and
reads much better).
- Object.prototype.hasOwnProperty.call -> Object.hasOwn in
merger.test.ts (ES2022, available since Node 16.9).
- String#replace(/'/g, ...) -> String#replaceAll("'", ...) in
skopeo.test.ts (ES2021).
- Hoist test helpers (stageLayer, fakeImageCache) out of their describe
blocks so they aren't re-defined on every test.
- Drop the redundant parseMaxEntrySize(undefined) call in types.test.ts —
the parameter already defaults to process.env.MAX_ENTRY_SIZE.
166/166 tests still pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(install-dynamic-plugins): parse argv with cleye
Switches the hand-rolled `process.argv` + USAGE-string handling in
main() to `cleye` — the same parser every `@backstage/cli-module-*`
package uses (already in our transitive deps). Aligns with the
Backstage CLI convention requested during PR review.
Existing surface preserved:
- positional `<dynamic-plugins-root>` (required, exit 1 if absent)
- `--help` / `-h` prints usage and exits 0
- normal run still exits with the installer's status code
Bundle grew from 226 kB -> 267 kB (cleye + type-flag minified).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(install-dynamic-plugins): adopt cli-module convention while keeping the bundled bin
Aligns with the @backstage/cli-module-* convention without losing the
self-contained bundled artifact:
- Rename to @red-hat-developer-hub/cli-module-install-dynamic-plugins,
backstage.role: cli-module.
- src/installer.ts holds the install pipeline and main() (formerly
src/index.ts).
- New src/index.ts default-exports `createCliModule(...)` registering an
`install` command whose loader is src/command.ts. Exposes the package
through backstage-cli discovery — `backstage-cli install <dir>` works
when the package is a dependency.
- src/cli.ts (the esbuild entry) keeps invoking installer.main() directly,
so the bundled .cjs stays self-contained: no @backstage/cli-node and no
keytar gymnastics in the bin path.
- Build is dual now — `backstage-cli package build && node esbuild.config.mjs`.
backstage-cli emits dist/index.cjs.js (the cli-module export) and the
unbundled supporting modules; esbuild emits dist/install-dynamic-plugins.cjs
(the standalone bin). Both are published.
- bin shim's installed branch now requires the bundled .cjs explicitly
rather than going through `main` — that keeps direct/npx/init-container
invocations at ~60 ms cold start instead of paying the cli-module
dispatch cost.
- main() now takes optional `args` and `programName` so the cli-module
loader can pass the command's argv slice and have `--help` print the
real invocation (`install-dynamic-plugins install …`).
- @backstage/cli-node added as a runtime dependency. It is only loaded by
the cli-module discovery path; the bundled bin never imports it.
166/166 tests pass; tsc/lint/prettier/api-reports clean. Bundle size
unchanged at ~267 KB.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(install-dynamic-plugins): drop custom esbuild bundle, ship unbundled cli-module
Replaces the dual build (esbuild bundle + backstage-cli) with plain
`backstage-cli package build` — the standard Backstage cli-module pattern.
The bundle and the keytar gymnastics only existed to satisfy RHDH's
init-container `COPY` of a single self-contained `.cjs`; that consumption
model is moving to `npm install` (redhat-developer/rhdh#4908), so the
single-file requirement is going away.
What's left in the package:
- `src/installer.ts`: install pipeline + `main(args, programName)`.
- `src/index.ts`: `createCliModule(...)` default export, registers the
`install` command. Discovered by `backstage-cli` when this package is a
dependency of a host project.
- `src/command.ts`: thin loader that calls `installer.main`.
- `bin/install-dynamic-plugins`: fast-path shim that loads
`dist/installer.cjs.js` directly and runs `main(process.argv.slice(2))`,
bypassing `@backstage/cli-node`'s `runCliModule` dispatch — saves ~80 ms
of cold start for direct/`npx`/init-container invocations. The
cli-module discovery path still goes through `runCliModule` and pays the
dispatch cost where it belongs.
Removed:
- `esbuild.config.mjs` (the custom bundle config)
- `src/cli.ts` (the esbuild entry)
- `dist/install-dynamic-plugins.cjs` from `files` (no longer produced)
- `esbuild` devDependency
166/166 tests pass; tsc/lint/prettier/api-reports clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(install-dynamic-plugins): drop stale references to the esbuild bundle
The README and the createCliModule docstring still referenced the
self-contained bundle that the package no longer ships:
- `npm run build` description and committed-bundle CI-check section.
- `node install-dynamic-plugins.cjs "$1"` wrapper line in "How RHDH
consumes it" — replaced with a pointer to redhat-developer/rhdh#4908.
- `src/index.ts` describing the bin path as the bundle.
- Source layout was missing `index.ts` / `command.ts` / `installer.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(install-dynamic-plugins): address PR review — align with upstream cli-module contract
Applies the four findings from @schultzp2020's review:
- package.json reshaped to match the upstream `@backstage/cli-module-*`
contract: `main`/`types` point at `src/index.ts` for local dev,
`publishConfig` overrides with `dist/index.cjs.js`/`dist/index.d.ts`,
`prepack` and `postpack` wire up `backstage-cli package prepack/postpack`
so the published artifact has the correct entry points, and `files` is
`["bin", "dist"]` (the old `dist/**/*.js` glob excluded `.d.ts`).
- bin wrapper now uses `@backstage/cli-node/config/nodeTransform.cjs`
(the cli-node variant) instead of `@backstage/cli/config/nodeTransform.cjs`.
`@backstage/cli` is only a devDependency — the previous import would have
broken `npx`/installed-package invocations.
- bin wrapper now goes through `runCliModule(...)` like every other
`@backstage/cli-module-*` package. The earlier fast path bypassed it to
save ~80 ms of cold start, but per @schultzp2020 that cost is one-time
per init-container run (not per-plugin), and going through the standard
dispatch gives us `--version`/`--help` and future runCliModule
improvements for free.
- installer.ts: added an `isPlainObject` guard for the parsed main config,
mirroring the existing guard on include files. A YAML scalar or array in
`dynamic-plugins.yaml` now throws a clear `InstallException` instead of
a confusing downstream `TypeError`.
Also drops the stale `install-dynamic-plugins.sh` wrapper from the package
— it pointed at the long-removed esbuild bundle and was no longer listed
in `files`.
166/166 tests pass; tsc/lint/prettier/api-reports clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 5c9083a commit 2d59f34
55 files changed
Lines changed: 24070 additions & 0 deletions
File tree
- workspaces/install-dynamic-plugins
- .changeset
- packages/install-dynamic-plugins
- bin
- src
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
Lines changed: 10 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
Lines changed: 5 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
Lines changed: 6 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
Lines changed: 5 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
0 commit comments