diff --git a/.changeset/afraid-experts-explain.md b/.changeset/afraid-experts-explain.md deleted file mode 100644 index 38eb3709d0..0000000000 --- a/.changeset/afraid-experts-explain.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli-node': patch ---- - -Added `type` field to `BackstagePackageJson` type. diff --git a/.changeset/afraid-kids-jog.md b/.changeset/afraid-kids-jog.md deleted file mode 100644 index 39e4e5c5a1..0000000000 --- a/.changeset/afraid-kids-jog.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-permission-node': patch ---- - -The returned router from `createPermissionIntegrationRouter` is now mutable, allowing for permissions and resources to be added after creation of the router. diff --git a/.changeset/beige-dingos-destroy.md b/.changeset/beige-dingos-destroy.md deleted file mode 100644 index 325c150119..0000000000 --- a/.changeset/beige-dingos-destroy.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -'@backstage/cli': minor ---- - -**BREAKING**: Add support for native ESM in Node.js code. This changes the behavior of dynamic import expressions in Node.js code. Typically this can be fixed by replacing `import(...)` with `require(...)`, with an `as typeof import(...)` cast if needed for types. This is because dynamic imports will no longer be transformed to `require(...)` calls, but instead be left as-is. This in turn allows you to load ESM modules from CommonJS code using `import(...)`. - -This change adds support for the following in Node.js packages, across type checking, package builds, runtime transforms and Jest tests: - -- Dynamic imports that load ESM modules from CommonJS code. -- Both `.mjs` and `.mts` files as explicit ESM files, as well as `.cjs` and `.cts` as explicit CommonJS files. -- Support for the `"type": "module"` field in `package.json` to indicate that the package is an ESM package. - -There are a few caveats to be aware of: - -- To enable support for native ESM in tests, you need to run the tests with the `--experimental-vm-modules` flag enabled, typically via `NODE_OPTIONS='--experimental-vm-modules'`. -- Declaring a package as `"type": "module"` in `package.json` is supported, but in tests it will cause all local transitive dependencies to also be treated as ESM, regardless of whether they declare `"type": "module"` or not. -- Node.js has an [ESM interoperability layer with CommonJS](https://nodejs.org/docs/latest-v22.x/api/esm.html#interoperability-with-commonjs) that allows for imports from ESM to identify named exports in CommonJS packages. This interoperability layer is **only** enabled when importing packages with a `.cts` or `.cjs` extension. This is because the interoperability layer is not fully compatible with the NPM ecosystem, and would break package if it was enabled for `.js` files. -- Dynamic imports of CommonJS packages will vary in shape depending on the runtime, i.e. test vs local development, etc. It is therefore recommended to avoid dynamic imports of CommonJS packages and instead use `require`, or to use the explicit CommonJS extensions as mentioned above. If you do need to dynamically import CommonJS packages, avoid using `default` exports, as the shape of them vary across different environments and you would otherwise need to manually unwrap the import based on the shape of the module object. diff --git a/.changeset/bigint-convert.md b/.changeset/bigint-convert.md deleted file mode 100644 index fed91ad2c1..0000000000 --- a/.changeset/bigint-convert.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-kubernetes-react': patch ---- - -Fixed bug in string-to-integer conversion to properly handle decimal values with BigInt. diff --git a/.changeset/chilly-sheep-scream.md b/.changeset/chilly-sheep-scream.md new file mode 100644 index 0000000000..eb568ffd8f --- /dev/null +++ b/.changeset/chilly-sheep-scream.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': minor +--- + +Added support of filtering based on system columns in catalog table diff --git a/.changeset/clean-squids-build.md b/.changeset/clean-squids-build.md deleted file mode 100644 index 3c1e0b56a7..0000000000 --- a/.changeset/clean-squids-build.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-notifications-backend': patch -'@backstage/plugin-notifications': patch ---- - -added topic filter for notifications diff --git a/.changeset/clever-tomatoes-jump.md b/.changeset/clever-tomatoes-jump.md new file mode 100644 index 0000000000..b18ca53189 --- /dev/null +++ b/.changeset/clever-tomatoes-jump.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-defaults': minor +--- + +Allow pass through of redis client and cluster options to Cache core service diff --git a/.changeset/create-app-1737468383.md b/.changeset/create-app-1742907012.md similarity index 100% rename from .changeset/create-app-1737468383.md rename to .changeset/create-app-1742907012.md diff --git a/.changeset/cuddly-dodos-allow.md b/.changeset/cuddly-dodos-allow.md new file mode 100644 index 0000000000..0901d630f1 --- /dev/null +++ b/.changeset/cuddly-dodos-allow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-node': patch +--- + +Update AWS file retrieval logic from storing file in buffer array to piping to res for better memory efficiency. diff --git a/.changeset/cuddly-kids-sell.md b/.changeset/cuddly-kids-sell.md new file mode 100644 index 0000000000..3b7cb16841 --- /dev/null +++ b/.changeset/cuddly-kids-sell.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Bump @module-federation/enhanced ^0.9.0 to fix GHSA-593f-38f6-jp5m diff --git a/.changeset/cuddly-mirrors-ask.md b/.changeset/cuddly-mirrors-ask.md new file mode 100644 index 0000000000..4fe611d067 --- /dev/null +++ b/.changeset/cuddly-mirrors-ask.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': patch +--- + +Updated styles for the Menu component in Canon. diff --git a/.changeset/curly-humans-prove.md b/.changeset/curly-humans-prove.md deleted file mode 100644 index 4e0ca9c90e..0000000000 --- a/.changeset/curly-humans-prove.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/backend-test-utils': patch -'@backstage/backend-defaults': patch -'@backstage/config-loader': patch ---- - -Internal refactor to use explicit `require` for lazy-loading dependency. diff --git a/.changeset/curvy-ways-play.md b/.changeset/curvy-ways-play.md deleted file mode 100644 index c69b855098..0000000000 --- a/.changeset/curvy-ways-play.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': minor ---- - -Added mocks for the new `PermissionsRegistryService`. diff --git a/.changeset/cyan-grapes-confess.md b/.changeset/cyan-grapes-confess.md deleted file mode 100644 index a113f91fd9..0000000000 --- a/.changeset/cyan-grapes-confess.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/repo-tools': patch ---- - -The `api-reports` command is now also able to generate SQL reports, enabled by the `--sql-reports` flag. diff --git a/.changeset/deep-flies-vanish.md b/.changeset/deep-flies-vanish.md new file mode 100644 index 0000000000..30aa10f290 --- /dev/null +++ b/.changeset/deep-flies-vanish.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-unprocessed-entities': patch +--- + +Added confirmation popup for delete entities in Catalog Unprocessed Entities plugin diff --git a/.changeset/dry-flies-rhyme.md b/.changeset/dry-flies-rhyme.md deleted file mode 100644 index 4257b7c2c5..0000000000 --- a/.changeset/dry-flies-rhyme.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-search-react': patch -'@backstage/plugin-search': patch ---- - -Added new extension points to extend search filters `SearchFilterBlueprint` and `SearchFilterResultTypeBlueprint` diff --git a/.changeset/dry-horses-report.md b/.changeset/dry-horses-report.md deleted file mode 100644 index b7a0b4cd46..0000000000 --- a/.changeset/dry-horses-report.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': patch ---- - -Sync feature installation compatibility logic with `@backstage/backend-app-api`. diff --git a/.changeset/early-feet-lay.md b/.changeset/early-feet-lay.md new file mode 100644 index 0000000000..71a557e5e5 --- /dev/null +++ b/.changeset/early-feet-lay.md @@ -0,0 +1,17 @@ +--- +'@backstage/plugin-auth-backend-module-oidc-provider': patch +--- + +Added custom timeout setting for oidc provider + +Here is an example of how to use a custom timeout with the configuration: + +```yaml +auth: + oidc: + production: + clientId: ${AUTH_GOOGLE_CLIENT_ID} + clientSecret: ${AUTH_GOOGLE_CLIENT_SECRET} + timeout: + seconds: 30 +``` diff --git a/.changeset/eight-cougars-collect-due.md b/.changeset/eight-cougars-collect-due.md deleted file mode 100644 index ff997f876a..0000000000 --- a/.changeset/eight-cougars-collect-due.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-kubernetes-cluster': patch -'@backstage/plugin-kubernetes-react': patch ---- - -Improved rendering of Kubernetes resources' metadata. diff --git a/.changeset/eight-cougars-collect.md b/.changeset/eight-cougars-collect.md deleted file mode 100644 index edaa18d826..0000000000 --- a/.changeset/eight-cougars-collect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Added `nestedValuesAsYaml` option to `StructuredMetadataTable` to render data as yaml. diff --git a/.changeset/eleven-mice-sleep.md b/.changeset/eleven-mice-sleep.md deleted file mode 100644 index d1b14aa098..0000000000 --- a/.changeset/eleven-mice-sleep.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Ignore benign database conflict errors during stitching, now logged with debug level instead. diff --git a/.changeset/every-ties-wink.md b/.changeset/every-ties-wink.md new file mode 100644 index 0000000000..31eff3fb9a --- /dev/null +++ b/.changeset/every-ties-wink.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Fixed an issue causing the `repo lint` command to fail when the `--max-warnings` option was used. diff --git a/.changeset/fair-mangos-sleep.md b/.changeset/fair-mangos-sleep.md deleted file mode 100644 index 8f0a6371c3..0000000000 --- a/.changeset/fair-mangos-sleep.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Cleanup `refresh_state_references` for entity processors and providers that are no longer in control of a `refresh_state` row for entity diff --git a/.changeset/fair-rocks-dream.md b/.changeset/fair-rocks-dream.md deleted file mode 100644 index d1f7f3f0f7..0000000000 --- a/.changeset/fair-rocks-dream.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Fixed an issue where invalid expressions or non-object values in `step.each` caused an error. diff --git a/.changeset/famous-dragons-bake.md b/.changeset/famous-dragons-bake.md new file mode 100644 index 0000000000..17b156de06 --- /dev/null +++ b/.changeset/famous-dragons-bake.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-gitlab': patch +--- + +add filter for repos by membership and topics diff --git a/.changeset/few-shrimps-kiss.md b/.changeset/few-shrimps-kiss.md deleted file mode 100644 index 8135ade1b7..0000000000 --- a/.changeset/few-shrimps-kiss.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/canon': minor ---- - -This is the first alpha release for Canon. As part of this release we are introducing 5 layout components and 7 components. All theming is done through CSS variables. diff --git a/.changeset/fifty-turtles-count.md b/.changeset/fifty-turtles-count.md deleted file mode 100644 index 76bea0dcaa..0000000000 --- a/.changeset/fifty-turtles-count.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Add missing route ref to the `/alpha` entity content extension. diff --git a/.changeset/funny-hotels-cut.md b/.changeset/funny-hotels-cut.md new file mode 100644 index 0000000000..7972b68bbb --- /dev/null +++ b/.changeset/funny-hotels-cut.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-sentry': patch +--- + +Made "sentry:project:create" action idempotent diff --git a/.changeset/gentle-actors-sleep.md b/.changeset/gentle-actors-sleep.md deleted file mode 100644 index 8ecea3e367..0000000000 --- a/.changeset/gentle-actors-sleep.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-kubernetes-backend': patch -'@backstage/plugin-kubernetes-common': patch -'@backstage/plugin-kubernetes-node': patch ---- - -Fixed the lack of `secrets` to fetch from the kubernetes api by adding option to specify additional Objects which are not part of Default Objects diff --git a/.changeset/giant-donkeys-punch.md b/.changeset/giant-donkeys-punch.md new file mode 100644 index 0000000000..522055832a --- /dev/null +++ b/.changeset/giant-donkeys-punch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-azure': patch +--- + +Made "publish:azure" action idempotent diff --git a/.changeset/green-jokes-provide.md b/.changeset/green-jokes-provide.md deleted file mode 100644 index f9fb78252f..0000000000 --- a/.changeset/green-jokes-provide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-unprocessed': patch ---- - -Use new `PermissionsRegistryService` instead of the deprecated `catalogPermissionExtensionPoint`. diff --git a/.changeset/grumpy-crews-sneeze.md b/.changeset/grumpy-crews-sneeze.md deleted file mode 100644 index 92aeff14a8..0000000000 --- a/.changeset/grumpy-crews-sneeze.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-app-api': patch ---- - -The log message written when plugins fail to initialize now includes the error that caused the plugin startup to fail. diff --git a/.changeset/honest-ties-worry.md b/.changeset/honest-ties-worry.md new file mode 100644 index 0000000000..74d8c591c1 --- /dev/null +++ b/.changeset/honest-ties-worry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': patch +--- + +Scaffolding - Template card - button to show template entity detail diff --git a/.changeset/hungry-mirrors-sniff.md b/.changeset/hungry-mirrors-sniff.md deleted file mode 100644 index f855c1e1a9..0000000000 --- a/.changeset/hungry-mirrors-sniff.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-defaults': patch ---- - -Added default implementation for the new `PermissionsRegistryService`. diff --git a/.changeset/itchy-times-behave.md b/.changeset/itchy-times-behave.md new file mode 100644 index 0000000000..dc883487b0 --- /dev/null +++ b/.changeset/itchy-times-behave.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-bitbucket': patch +--- + +Made "publish:bitbucket" action idempotent diff --git a/.changeset/large-kings-protect.md b/.changeset/large-kings-protect.md new file mode 100644 index 0000000000..363e2b7759 --- /dev/null +++ b/.changeset/large-kings-protect.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-github': patch +--- + +Added `validateLocationsExist` to the config definition where it was missing. diff --git a/.changeset/lemon-shoes-enter.md b/.changeset/lemon-shoes-enter.md new file mode 100644 index 0000000000..a950989d93 --- /dev/null +++ b/.changeset/lemon-shoes-enter.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': patch +--- + +Add global CSS reset for anchor tags. diff --git a/.changeset/loud-walls-build.md b/.changeset/loud-walls-build.md deleted file mode 100644 index 0ddad96f2f..0000000000 --- a/.changeset/loud-walls-build.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -The catalog backend now supports the new `PermissionsRegistryService`, which can be used to add custom permission rules. diff --git a/.changeset/metal-animals-notice.md b/.changeset/metal-animals-notice.md new file mode 100644 index 0000000000..c1a844ddb0 --- /dev/null +++ b/.changeset/metal-animals-notice.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-github': patch +--- + +Made "github:autolinks:create" action idempotent diff --git a/.changeset/neat-singers-rhyme.md b/.changeset/neat-singers-rhyme.md deleted file mode 100644 index 5c12339d84..0000000000 --- a/.changeset/neat-singers-rhyme.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Fixed the file path pattern of many static assets output as part of the frontend build process, where there was an extra `.` before the extension, leading to names like `image-af7946b..png`. diff --git a/.changeset/odd-bobcats-hang.md b/.changeset/odd-bobcats-hang.md new file mode 100644 index 0000000000..9b3aeccffc --- /dev/null +++ b/.changeset/odd-bobcats-hang.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +'@backstage/plugin-scaffolder-node': patch +--- + +Document the internal built-in filters, and ensure that the types are validated when using `createTemplateFilter` and `createTemplateGlobalFunction` from the `zod` schema. diff --git a/.changeset/odd-countries-vanish.md b/.changeset/odd-countries-vanish.md deleted file mode 100644 index 4d56b1fdeb..0000000000 --- a/.changeset/odd-countries-vanish.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-ldap': patch ---- - -Make `ldapOrg` config key optional diff --git a/.changeset/old-moons-end.md b/.changeset/old-moons-end.md deleted file mode 100644 index d550ae6325..0000000000 --- a/.changeset/old-moons-end.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-node': patch ---- - -Deprecated the alpha `catalogPermissionExtensionPoint` and related types, since the same functionality is now available via the new `PermissionsRegistryService`. diff --git a/.changeset/old-phones-rest.md b/.changeset/old-phones-rest.md deleted file mode 100644 index 20edd78d8d..0000000000 --- a/.changeset/old-phones-rest.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@techdocs/cli': minor -'@backstage/plugin-techdocs-node': minor ---- - -Allow configurable optional retries for publisher AWS S3 operations. diff --git a/.changeset/olive-boxes-hide-backend-defaults.md b/.changeset/olive-boxes-hide-backend-defaults.md deleted file mode 100644 index 9d4ff05f17..0000000000 --- a/.changeset/olive-boxes-hide-backend-defaults.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-defaults': minor ---- - -This change introduces the `auditor` service implementation details. diff --git a/.changeset/olive-boxes-hide-backend-plugin-api.md b/.changeset/olive-boxes-hide-backend-plugin-api.md deleted file mode 100644 index 32e4d41813..0000000000 --- a/.changeset/olive-boxes-hide-backend-plugin-api.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-plugin-api': minor ---- - -This change introduces the `auditor` service definition. diff --git a/.changeset/olive-boxes-hide-backend-test-utils.md b/.changeset/olive-boxes-hide-backend-test-utils.md deleted file mode 100644 index 41b2016f5d..0000000000 --- a/.changeset/olive-boxes-hide-backend-test-utils.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': minor ---- - -This change introduces mocks for the `auditor` service. diff --git a/.changeset/olive-boxes-hide-catalog-backend.md b/.changeset/olive-boxes-hide-catalog-backend.md deleted file mode 100644 index 09d88bf6e2..0000000000 --- a/.changeset/olive-boxes-hide-catalog-backend.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -This change integrates the `auditor` service into the Catalog plugin. diff --git a/.changeset/olive-boxes-hide-scaffolder-backend.md b/.changeset/olive-boxes-hide-scaffolder-backend.md deleted file mode 100644 index be67064091..0000000000 --- a/.changeset/olive-boxes-hide-scaffolder-backend.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': minor ---- - -This change integrates the `auditor` service into the Scaffolder plugin. diff --git a/.changeset/olive-boxes-hide-scaffolder-node.md b/.changeset/olive-boxes-hide-scaffolder-node.md deleted file mode 100644 index f3c18f0991..0000000000 --- a/.changeset/olive-boxes-hide-scaffolder-node.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-node': minor ---- - -This change introduces an optional `taskId` property to `TaskContext`. diff --git a/.changeset/orange-brooms-lick.md b/.changeset/orange-brooms-lick.md deleted file mode 100644 index 17a8ef7476..0000000000 --- a/.changeset/orange-brooms-lick.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-openapi': patch ---- - -Fix `resolveUrl` for split openapi definition relative path diff --git a/.changeset/orange-queens-grin.md b/.changeset/orange-queens-grin.md new file mode 100644 index 0000000000..66955655d7 --- /dev/null +++ b/.changeset/orange-queens-grin.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': minor +--- + +add template-extensions scaffolder service endpoint diff --git a/.changeset/pre.json b/.changeset/pre.json index 46e41b0c24..c7911415f8 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -2,239 +2,233 @@ "mode": "pre", "tag": "next", "initialVersions": { - "example-app": "0.2.105", - "@backstage/app-defaults": "1.5.16", - "example-app-next": "0.0.19", - "app-next-example-plugin": "0.0.19", - "example-backend": "0.0.34", - "@backstage/backend-app-api": "1.1.1", - "@backstage/backend-defaults": "0.7.0", + "example-app": "0.2.107", + "@backstage/app-defaults": "1.6.0", + "example-app-next": "0.0.21", + "app-next-example-plugin": "0.0.21", + "example-backend": "0.0.36", + "@backstage/backend-app-api": "1.2.1", + "@backstage/backend-defaults": "0.8.2", "@backstage/backend-dev-utils": "0.1.5", - "@backstage/backend-dynamic-feature-service": "0.5.3", - "example-backend-legacy": "0.2.106", - "@backstage/backend-openapi-utils": "0.4.1", - "@backstage/backend-plugin-api": "1.1.1", - "@backstage/backend-test-utils": "1.2.1", - "@backstage/canon": "0.0.0", + "@backstage/backend-dynamic-feature-service": "0.6.1", + "example-backend-legacy": "0.2.108", + "@backstage/backend-openapi-utils": "0.5.1", + "@backstage/backend-plugin-api": "1.2.1", + "@backstage/backend-test-utils": "1.3.1", + "@backstage/canon": "0.2.0", "@backstage/catalog-client": "1.9.1", "@backstage/catalog-model": "1.7.3", - "@backstage/cli": "0.29.5", + "@backstage/cli": "0.31.0", "@backstage/cli-common": "0.1.15", - "@backstage/cli-node": "0.2.12", + "@backstage/cli-node": "0.2.13", "@backstage/codemods": "0.1.52", "@backstage/config": "1.3.2", - "@backstage/config-loader": "1.9.5", - "@backstage/core-app-api": "1.15.4", - "@backstage/core-compat-api": "0.3.5", - "@backstage/core-components": "0.16.3", - "@backstage/core-plugin-api": "1.10.3", - "@backstage/create-app": "0.5.24", - "@backstage/dev-utils": "1.1.6", - "e2e-test": "0.2.24", + "@backstage/config-loader": "1.10.0", + "@backstage/core-app-api": "1.16.0", + "@backstage/core-compat-api": "0.4.0", + "@backstage/core-components": "0.17.0", + "@backstage/core-plugin-api": "1.10.5", + "@backstage/create-app": "0.6.0", + "@backstage/dev-utils": "1.1.8", + "e2e-test": "0.2.26", "@backstage/e2e-test-utils": "0.1.1", "@backstage/errors": "1.2.7", "@backstage/eslint-plugin": "0.1.10", - "@backstage/frontend-app-api": "0.10.4", - "@backstage/frontend-defaults": "0.1.5", - "@internal/frontend": "0.0.5", - "@backstage/frontend-plugin-api": "0.9.4", - "@backstage/frontend-test-utils": "0.2.5", - "@backstage/integration": "1.16.1", + "@backstage/frontend-app-api": "0.11.0", + "@backstage/frontend-defaults": "0.2.0", + "@internal/frontend": "0.0.7", + "@backstage/frontend-plugin-api": "0.10.0", + "@backstage/frontend-test-utils": "0.3.0", + "@backstage/integration": "1.16.2", "@backstage/integration-aws-node": "0.1.15", - "@backstage/integration-react": "1.2.3", + "@backstage/integration-react": "1.2.5", "@internal/opaque": "0.0.1", "@backstage/release-manifests": "0.0.12", - "@backstage/repo-tools": "0.12.1", - "@internal/scaffolder": "0.0.5", - "@techdocs/cli": "1.8.25", - "techdocs-cli-embedded-app": "0.2.104", - "@backstage/test-utils": "1.7.4", - "@backstage/theme": "0.6.3", + "@backstage/repo-tools": "0.13.1", + "@internal/scaffolder": "0.0.7", + "@techdocs/cli": "1.9.1", + "techdocs-cli-embedded-app": "0.2.106", + "@backstage/test-utils": "1.7.6", + "@backstage/theme": "0.6.4", "@backstage/types": "1.2.1", - "@backstage/version-bridge": "1.0.10", + "@backstage/version-bridge": "1.0.11", "yarn-plugin-backstage": "0.0.4", - "@backstage/plugin-api-docs": "0.12.3", - "@backstage/plugin-api-docs-module-protoc-gen-doc": "0.1.8", - "@backstage/plugin-app": "0.1.5", - "@backstage/plugin-app-backend": "0.4.4", - "@backstage/plugin-app-node": "0.1.29", - "@backstage/plugin-app-visualizer": "0.1.15", - "@backstage/plugin-auth-backend": "0.24.2", - "@backstage/plugin-auth-backend-module-atlassian-provider": "0.3.4", - "@backstage/plugin-auth-backend-module-auth0-provider": "0.1.4", - "@backstage/plugin-auth-backend-module-aws-alb-provider": "0.3.2", - "@backstage/plugin-auth-backend-module-azure-easyauth-provider": "0.2.4", - "@backstage/plugin-auth-backend-module-bitbucket-provider": "0.2.4", - "@backstage/plugin-auth-backend-module-bitbucket-server-provider": "0.1.4", - "@backstage/plugin-auth-backend-module-cloudflare-access-provider": "0.3.4", - "@backstage/plugin-auth-backend-module-gcp-iap-provider": "0.3.4", - "@backstage/plugin-auth-backend-module-github-provider": "0.2.4", - "@backstage/plugin-auth-backend-module-gitlab-provider": "0.2.4", - "@backstage/plugin-auth-backend-module-google-provider": "0.2.4", - "@backstage/plugin-auth-backend-module-guest-provider": "0.2.4", - "@backstage/plugin-auth-backend-module-microsoft-provider": "0.2.4", - "@backstage/plugin-auth-backend-module-oauth2-provider": "0.3.4", - "@backstage/plugin-auth-backend-module-oauth2-proxy-provider": "0.2.4", - "@backstage/plugin-auth-backend-module-oidc-provider": "0.3.4", - "@backstage/plugin-auth-backend-module-okta-provider": "0.1.4", - "@backstage/plugin-auth-backend-module-onelogin-provider": "0.2.4", - "@backstage/plugin-auth-backend-module-pinniped-provider": "0.2.4", - "@backstage/plugin-auth-backend-module-vmware-cloud-provider": "0.4.3", - "@backstage/plugin-auth-node": "0.5.6", - "@backstage/plugin-auth-react": "0.1.11", - "@backstage/plugin-bitbucket-cloud-common": "0.2.27", - "@backstage/plugin-catalog": "1.26.1", - "@backstage/plugin-catalog-backend": "1.30.0", - "@backstage/plugin-catalog-backend-module-aws": "0.4.7", - "@backstage/plugin-catalog-backend-module-azure": "0.3.1", - "@backstage/plugin-catalog-backend-module-backstage-openapi": "0.4.4", - "@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.4.4", - "@backstage/plugin-catalog-backend-module-bitbucket-server": "0.3.1", - "@backstage/plugin-catalog-backend-module-gcp": "0.3.4", - "@backstage/plugin-catalog-backend-module-gerrit": "0.2.6", - "@backstage/plugin-catalog-backend-module-github": "0.7.9", - "@backstage/plugin-catalog-backend-module-github-org": "0.3.6", - "@backstage/plugin-catalog-backend-module-gitlab": "0.6.2", - "@backstage/plugin-catalog-backend-module-gitlab-org": "0.2.5", - "@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.6.2", - "@backstage/plugin-catalog-backend-module-ldap": "0.11.1", - "@backstage/plugin-catalog-backend-module-logs": "0.1.6", - "@backstage/plugin-catalog-backend-module-msgraph": "0.6.6", - "@backstage/plugin-catalog-backend-module-openapi": "0.2.6", - "@backstage/plugin-catalog-backend-module-puppetdb": "0.2.6", - "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.2.4", - "@backstage/plugin-catalog-backend-module-unprocessed": "0.5.4", + "@backstage/plugin-api-docs": "0.12.5", + "@backstage/plugin-api-docs-module-protoc-gen-doc": "0.1.9", + "@backstage/plugin-app": "0.1.7", + "@backstage/plugin-app-backend": "0.5.0", + "@backstage/plugin-app-node": "0.1.31", + "@backstage/plugin-app-visualizer": "0.1.17", + "@backstage/plugin-auth-backend": "0.24.4", + "@backstage/plugin-auth-backend-module-atlassian-provider": "0.4.1", + "@backstage/plugin-auth-backend-module-auth0-provider": "0.2.1", + "@backstage/plugin-auth-backend-module-aws-alb-provider": "0.4.1", + "@backstage/plugin-auth-backend-module-azure-easyauth-provider": "0.2.6", + "@backstage/plugin-auth-backend-module-bitbucket-provider": "0.3.1", + "@backstage/plugin-auth-backend-module-bitbucket-server-provider": "0.2.1", + "@backstage/plugin-auth-backend-module-cloudflare-access-provider": "0.4.1", + "@backstage/plugin-auth-backend-module-gcp-iap-provider": "0.4.1", + "@backstage/plugin-auth-backend-module-github-provider": "0.3.1", + "@backstage/plugin-auth-backend-module-gitlab-provider": "0.3.1", + "@backstage/plugin-auth-backend-module-google-provider": "0.3.1", + "@backstage/plugin-auth-backend-module-guest-provider": "0.2.6", + "@backstage/plugin-auth-backend-module-microsoft-provider": "0.3.1", + "@backstage/plugin-auth-backend-module-oauth2-provider": "0.4.1", + "@backstage/plugin-auth-backend-module-oauth2-proxy-provider": "0.2.6", + "@backstage/plugin-auth-backend-module-oidc-provider": "0.4.1", + "@backstage/plugin-auth-backend-module-okta-provider": "0.2.1", + "@backstage/plugin-auth-backend-module-onelogin-provider": "0.3.1", + "@backstage/plugin-auth-backend-module-pinniped-provider": "0.3.1", + "@backstage/plugin-auth-backend-module-vmware-cloud-provider": "0.5.1", + "@backstage/plugin-auth-node": "0.6.1", + "@backstage/plugin-auth-react": "0.1.13", + "@backstage/plugin-bitbucket-cloud-common": "0.2.28", + "@backstage/plugin-catalog": "1.28.0", + "@backstage/plugin-catalog-backend": "1.32.0", + "@backstage/plugin-catalog-backend-module-aws": "0.4.9", + "@backstage/plugin-catalog-backend-module-azure": "0.3.3", + "@backstage/plugin-catalog-backend-module-backstage-openapi": "0.5.0", + "@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.4.6", + "@backstage/plugin-catalog-backend-module-bitbucket-server": "0.3.3", + "@backstage/plugin-catalog-backend-module-gcp": "0.3.6", + "@backstage/plugin-catalog-backend-module-gerrit": "0.3.0", + "@backstage/plugin-catalog-backend-module-github": "0.7.11", + "@backstage/plugin-catalog-backend-module-github-org": "0.3.8", + "@backstage/plugin-catalog-backend-module-gitlab": "0.6.4", + "@backstage/plugin-catalog-backend-module-gitlab-org": "0.2.7", + "@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.6.4", + "@backstage/plugin-catalog-backend-module-ldap": "0.11.3", + "@backstage/plugin-catalog-backend-module-logs": "0.1.8", + "@backstage/plugin-catalog-backend-module-msgraph": "0.6.8", + "@backstage/plugin-catalog-backend-module-openapi": "0.2.8", + "@backstage/plugin-catalog-backend-module-puppetdb": "0.2.8", + "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.2.6", + "@backstage/plugin-catalog-backend-module-unprocessed": "0.5.6", "@backstage/plugin-catalog-common": "1.1.3", - "@backstage/plugin-catalog-graph": "0.4.15", - "@backstage/plugin-catalog-import": "0.12.9", - "@backstage/plugin-catalog-node": "1.15.1", - "@backstage/plugin-catalog-react": "1.15.1", - "@backstage/plugin-catalog-unprocessed-entities": "0.2.13", + "@backstage/plugin-catalog-graph": "0.4.17", + "@backstage/plugin-catalog-import": "0.12.11", + "@backstage/plugin-catalog-node": "1.16.1", + "@backstage/plugin-catalog-react": "1.16.0", + "@backstage/plugin-catalog-unprocessed-entities": "0.2.15", "@backstage/plugin-catalog-unprocessed-entities-common": "0.0.7", - "@backstage/plugin-config-schema": "0.1.64", - "@backstage/plugin-devtools": "0.1.23", - "@backstage/plugin-devtools-backend": "0.5.1", + "@backstage/plugin-config-schema": "0.1.66", + "@backstage/plugin-devtools": "0.1.25", + "@backstage/plugin-devtools-backend": "0.5.3", "@backstage/plugin-devtools-common": "0.1.15", - "@backstage/plugin-events-backend": "0.4.1", - "@backstage/plugin-events-backend-module-aws-sqs": "0.4.7", - "@backstage/plugin-events-backend-module-azure": "0.2.16", - "@backstage/plugin-events-backend-module-bitbucket-cloud": "0.2.16", - "@backstage/plugin-events-backend-module-gerrit": "0.2.16", - "@backstage/plugin-events-backend-module-github": "0.2.16", - "@backstage/plugin-events-backend-module-gitlab": "0.2.16", - "@backstage/plugin-events-backend-test-utils": "0.1.40", - "@backstage/plugin-events-node": "0.4.7", - "@internal/plugin-todo-list": "1.0.35", - "@internal/plugin-todo-list-backend": "1.0.35", + "@backstage/plugin-events-backend": "0.5.0", + "@backstage/plugin-events-backend-module-aws-sqs": "0.4.9", + "@backstage/plugin-events-backend-module-azure": "0.2.18", + "@backstage/plugin-events-backend-module-bitbucket-cloud": "0.2.18", + "@backstage/plugin-events-backend-module-gerrit": "0.2.18", + "@backstage/plugin-events-backend-module-github": "0.2.18", + "@backstage/plugin-events-backend-module-gitlab": "0.2.18", + "@backstage/plugin-events-backend-test-utils": "0.1.42", + "@backstage/plugin-events-node": "0.4.9", + "@internal/plugin-todo-list": "1.0.37", + "@internal/plugin-todo-list-backend": "1.0.37", "@internal/plugin-todo-list-common": "1.0.24", - "@backstage/plugin-home": "0.8.4", - "@backstage/plugin-home-react": "0.1.22", - "@backstage/plugin-kubernetes": "0.12.3", - "@backstage/plugin-kubernetes-backend": "0.19.2", - "@backstage/plugin-kubernetes-cluster": "0.0.21", - "@backstage/plugin-kubernetes-common": "0.9.2", - "@backstage/plugin-kubernetes-node": "0.2.2", - "@backstage/plugin-kubernetes-react": "0.5.3", - "@backstage/plugin-notifications": "0.5.1", - "@backstage/plugin-notifications-backend": "0.5.1", - "@backstage/plugin-notifications-backend-module-email": "0.3.5", + "@backstage/plugin-home": "0.8.6", + "@backstage/plugin-home-react": "0.1.24", + "@backstage/plugin-kubernetes": "0.12.5", + "@backstage/plugin-kubernetes-backend": "0.19.4", + "@backstage/plugin-kubernetes-cluster": "0.0.23", + "@backstage/plugin-kubernetes-common": "0.9.4", + "@backstage/plugin-kubernetes-node": "0.2.4", + "@backstage/plugin-kubernetes-react": "0.5.5", + "@backstage/plugin-notifications": "0.5.3", + "@backstage/plugin-notifications-backend": "0.5.4", + "@backstage/plugin-notifications-backend-module-email": "0.3.7", "@backstage/plugin-notifications-common": "0.0.8", - "@backstage/plugin-notifications-node": "0.2.11", - "@backstage/plugin-org": "0.6.35", - "@backstage/plugin-org-react": "0.1.34", - "@backstage/plugin-permission-backend": "0.5.53", - "@backstage/plugin-permission-backend-module-allow-all-policy": "0.2.4", + "@backstage/plugin-notifications-node": "0.2.13", + "@backstage/plugin-org": "0.6.37", + "@backstage/plugin-org-react": "0.1.36", + "@backstage/plugin-permission-backend": "0.5.55", + "@backstage/plugin-permission-backend-module-allow-all-policy": "0.2.6", "@backstage/plugin-permission-common": "0.8.4", - "@backstage/plugin-permission-node": "0.8.7", - "@backstage/plugin-permission-react": "0.4.30", - "@backstage/plugin-proxy-backend": "0.5.10", - "@backstage/plugin-proxy-node": "0.1.0", - "@backstage/plugin-scaffolder": "1.27.4", - "@backstage/plugin-scaffolder-backend": "1.29.0", - "@backstage/plugin-scaffolder-backend-module-azure": "0.2.5", - "@backstage/plugin-scaffolder-backend-module-bitbucket": "0.3.6", - "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "0.2.5", - "@backstage/plugin-scaffolder-backend-module-bitbucket-server": "0.2.5", - "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.3.5", - "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.3.6", - "@backstage/plugin-scaffolder-backend-module-gcp": "0.2.5", - "@backstage/plugin-scaffolder-backend-module-gerrit": "0.2.5", - "@backstage/plugin-scaffolder-backend-module-gitea": "0.2.5", - "@backstage/plugin-scaffolder-backend-module-github": "0.5.5", - "@backstage/plugin-scaffolder-backend-module-gitlab": "0.7.1", - "@backstage/plugin-scaffolder-backend-module-notifications": "0.1.6", - "@backstage/plugin-scaffolder-backend-module-rails": "0.5.5", - "@backstage/plugin-scaffolder-backend-module-sentry": "0.2.5", - "@backstage/plugin-scaffolder-backend-module-yeoman": "0.4.6", - "@backstage/plugin-scaffolder-common": "1.5.9", - "@backstage/plugin-scaffolder-node": "0.6.3", - "@backstage/plugin-scaffolder-node-test-utils": "0.1.18", - "@backstage/plugin-scaffolder-react": "1.14.3", - "@backstage/plugin-search": "1.4.22", - "@backstage/plugin-search-backend": "1.8.1", - "@backstage/plugin-search-backend-module-catalog": "0.3.0", - "@backstage/plugin-search-backend-module-elasticsearch": "1.6.4", - "@backstage/plugin-search-backend-module-explore": "0.2.7", - "@backstage/plugin-search-backend-module-pg": "0.5.40", - "@backstage/plugin-search-backend-module-stack-overflow-collator": "0.3.5", - "@backstage/plugin-search-backend-module-techdocs": "0.3.5", - "@backstage/plugin-search-backend-node": "1.3.7", + "@backstage/plugin-permission-node": "0.9.0", + "@backstage/plugin-permission-react": "0.4.32", + "@backstage/plugin-proxy-backend": "0.6.0", + "@backstage/plugin-proxy-node": "0.1.2", + "@backstage/plugin-scaffolder": "1.29.0", + "@backstage/plugin-scaffolder-backend": "1.31.0", + "@backstage/plugin-scaffolder-backend-module-azure": "0.2.7", + "@backstage/plugin-scaffolder-backend-module-bitbucket": "0.3.8", + "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "0.2.7", + "@backstage/plugin-scaffolder-backend-module-bitbucket-server": "0.2.7", + "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.3.7", + "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.3.8", + "@backstage/plugin-scaffolder-backend-module-gcp": "0.2.7", + "@backstage/plugin-scaffolder-backend-module-gerrit": "0.2.7", + "@backstage/plugin-scaffolder-backend-module-gitea": "0.2.7", + "@backstage/plugin-scaffolder-backend-module-github": "0.6.1", + "@backstage/plugin-scaffolder-backend-module-gitlab": "0.8.1", + "@backstage/plugin-scaffolder-backend-module-notifications": "0.1.8", + "@backstage/plugin-scaffolder-backend-module-rails": "0.5.7", + "@backstage/plugin-scaffolder-backend-module-sentry": "0.2.7", + "@backstage/plugin-scaffolder-backend-module-yeoman": "0.4.8", + "@backstage/plugin-scaffolder-common": "1.5.10", + "@backstage/plugin-scaffolder-node": "0.8.0", + "@backstage/plugin-scaffolder-node-test-utils": "0.2.0", + "@backstage/plugin-scaffolder-react": "1.14.6", + "@backstage/plugin-search": "1.4.24", + "@backstage/plugin-search-backend": "2.0.0", + "@backstage/plugin-search-backend-module-catalog": "0.3.2", + "@backstage/plugin-search-backend-module-elasticsearch": "1.7.0", + "@backstage/plugin-search-backend-module-explore": "0.3.0", + "@backstage/plugin-search-backend-module-pg": "0.5.42", + "@backstage/plugin-search-backend-module-stack-overflow-collator": "0.3.7", + "@backstage/plugin-search-backend-module-techdocs": "0.4.0", + "@backstage/plugin-search-backend-node": "1.3.9", "@backstage/plugin-search-common": "1.2.17", - "@backstage/plugin-search-react": "1.8.5", - "@backstage/plugin-signals": "0.0.15", - "@backstage/plugin-signals-backend": "0.3.0", - "@backstage/plugin-signals-node": "0.1.16", - "@backstage/plugin-signals-react": "0.0.9", - "@backstage/plugin-techdocs": "1.12.1", - "@backstage/plugin-techdocs-addons-test-utils": "1.0.44", - "@backstage/plugin-techdocs-backend": "1.11.5", + "@backstage/plugin-search-react": "1.8.7", + "@backstage/plugin-signals": "0.0.17", + "@backstage/plugin-signals-backend": "0.3.2", + "@backstage/plugin-signals-node": "0.1.18", + "@backstage/plugin-signals-react": "0.0.11", + "@backstage/plugin-techdocs": "1.12.4", + "@backstage/plugin-techdocs-addons-test-utils": "1.0.46", + "@backstage/plugin-techdocs-backend": "2.0.0", "@backstage/plugin-techdocs-common": "0.1.0", - "@backstage/plugin-techdocs-module-addons-contrib": "1.1.20", - "@backstage/plugin-techdocs-node": "1.12.16", - "@backstage/plugin-techdocs-react": "1.2.13", - "@backstage/plugin-user-settings": "0.8.18", - "@backstage/plugin-user-settings-backend": "0.2.29", + "@backstage/plugin-techdocs-module-addons-contrib": "1.1.22", + "@backstage/plugin-techdocs-node": "1.13.1", + "@backstage/plugin-techdocs-react": "1.2.15", + "@backstage/plugin-user-settings": "0.8.20", + "@backstage/plugin-user-settings-backend": "0.3.0", "@backstage/plugin-user-settings-common": "0.0.1" }, "changesets": [ - "afraid-experts-explain", - "afraid-kids-jog", - "beige-dingos-destroy", - "bigint-convert", - "clean-squids-build", - "create-app-1737468383", - "curly-humans-prove", - "curvy-ways-play", - "cyan-grapes-confess", - "dry-flies-rhyme", - "dry-horses-report", - "eleven-mice-sleep", - "fair-mangos-sleep", - "few-shrimps-kiss", - "gentle-actors-sleep", - "green-jokes-provide", - "hungry-mirrors-sniff", - "loud-walls-build", - "old-moons-end", - "old-phones-rest", - "olive-boxes-hide-backend-defaults", - "olive-boxes-hide-backend-plugin-api", - "olive-boxes-hide-backend-test-utils", - "olive-boxes-hide-catalog-backend", - "olive-boxes-hide-scaffolder-backend", - "olive-boxes-hide-scaffolder-node", - "orange-brooms-lick", - "proud-dryers-act", - "proud-hornets-cheer", - "quiet-phones-sell", - "sharp-vans-protect", - "sharp-years-drive", - "short-vans-reflect", - "soft-planets-mate", - "tall-scissors-sip", - "tame-hats-shout", - "twelve-eyes-stare", - "warm-masks-ring", - "wise-apes-juggle" + "chilly-sheep-scream", + "clever-tomatoes-jump", + "create-app-1742907012", + "cuddly-dodos-allow", + "cuddly-kids-sell", + "cuddly-mirrors-ask", + "deep-flies-vanish", + "early-feet-lay", + "every-ties-wink", + "famous-dragons-bake", + "funny-hotels-cut", + "giant-donkeys-punch", + "honest-ties-worry", + "itchy-times-behave", + "large-kings-protect", + "lemon-shoes-enter", + "metal-animals-notice", + "odd-bobcats-hang", + "orange-queens-grin", + "sad-pots-try", + "silver-rocks-invite", + "spotty-towns-show", + "strange-planes-kneel", + "sweet-maps-invent", + "swift-boats-add", + "tame-sloths-brake", + "thin-snails-judge", + "tiny-swans-warn", + "twenty-forks-cheat", + "twenty-walls-join", + "wet-penguins-beg", + "wide-planets-camp", + "witty-planets-sing" ] } diff --git a/.changeset/proud-dryers-act.md b/.changeset/proud-dryers-act.md deleted file mode 100644 index 4bc7a98fdb..0000000000 --- a/.changeset/proud-dryers-act.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Changed the base URL in addLinkClickListener from window.location.origin to app.baseUrl for improved path handling. This fixes an issue where Backstage, when running on a subpath, was unable to handle non-Backstage URLs of the same origin correctly. diff --git a/.changeset/proud-hornets-cheer.md b/.changeset/proud-hornets-cheer.md deleted file mode 100644 index 6ac0a7846b..0000000000 --- a/.changeset/proud-hornets-cheer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -Fixed a bug in the BitbucketRepoBranchPicker component that crashed the scaffolder diff --git a/.changeset/quiet-phones-sell.md b/.changeset/quiet-phones-sell.md deleted file mode 100644 index f41f5d685e..0000000000 --- a/.changeset/quiet-phones-sell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/repo-tools': patch ---- - -Internal refactor to support native ESM. diff --git a/.changeset/sad-pots-try.md b/.changeset/sad-pots-try.md new file mode 100644 index 0000000000..68c442fc6e --- /dev/null +++ b/.changeset/sad-pots-try.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +Add `operation` to alpha `defaultEntityContentGroups`. diff --git a/.changeset/sharp-vans-protect.md b/.changeset/sharp-vans-protect.md deleted file mode 100644 index 651c38be8b..0000000000 --- a/.changeset/sharp-vans-protect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-plugin-api': patch ---- - -Added new `PermissionsRegistryService` that is used by plugins to register permissions, resource types, and rules into the permission system. This replaces the existing `createPermissionIntegrationRouter` from `@backstage/plugin-permission-node`. diff --git a/.changeset/sharp-years-drive.md b/.changeset/sharp-years-drive.md deleted file mode 100644 index 92ade2b972..0000000000 --- a/.changeset/sharp-years-drive.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search-backend-module-catalog': patch ---- - -Modified the logic for generating the location URL by encoding the entity property values with `encodeURIComponent`. This enhancement improves the safety and reliability of the URL. diff --git a/.changeset/short-vans-reflect.md b/.changeset/short-vans-reflect.md deleted file mode 100644 index a0290c7c27..0000000000 --- a/.changeset/short-vans-reflect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/repo-tools': patch ---- - -Internal refactor of API report generation. diff --git a/.changeset/silver-rocks-invite.md b/.changeset/silver-rocks-invite.md new file mode 100644 index 0000000000..3a08bc72af --- /dev/null +++ b/.changeset/silver-rocks-invite.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-bitbucket-cloud': patch +--- + +Made "publish:bitbucketCloud" action idempotent diff --git a/.changeset/soft-planets-mate.md b/.changeset/soft-planets-mate.md deleted file mode 100644 index 94dd790f4b..0000000000 --- a/.changeset/soft-planets-mate.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch -'@backstage/plugin-scaffolder-react': patch ---- - -Add schema output return type to the `makeFieldSchema` function return diff --git a/.changeset/spotty-towns-show.md b/.changeset/spotty-towns-show.md new file mode 100644 index 0000000000..8ec69f3f5e --- /dev/null +++ b/.changeset/spotty-towns-show.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-github': patch +--- + +Made "github:branch-protection:create" action idempotent diff --git a/.changeset/strange-planes-kneel.md b/.changeset/strange-planes-kneel.md new file mode 100644 index 0000000000..8e57057aee --- /dev/null +++ b/.changeset/strange-planes-kneel.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-scaffolder-react': minor +'@backstage/plugin-scaffolder': minor +--- + +add api to retrieve template extensions info from scaffolder-backend diff --git a/.changeset/sweet-maps-invent.md b/.changeset/sweet-maps-invent.md new file mode 100644 index 0000000000..390ce57dc7 --- /dev/null +++ b/.changeset/sweet-maps-invent.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-unprocessed-entities': patch +--- + +Fixed the `convertTimeToLocalTimezone` function in the FailedEntities component to correctly parse ISO 8601 date strings and set the timezone to the current local timezone. diff --git a/.changeset/swift-boats-add.md b/.changeset/swift-boats-add.md new file mode 100644 index 0000000000..42682437b0 --- /dev/null +++ b/.changeset/swift-boats-add.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-github': patch +--- + +Made "publish:github" action idempotent diff --git a/.changeset/tall-scissors-sip.md b/.changeset/tall-scissors-sip.md deleted file mode 100644 index 7d4cdc7059..0000000000 --- a/.changeset/tall-scissors-sip.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@techdocs/cli': patch ---- - -Internal update to work with dynamic imports. diff --git a/.changeset/tame-hats-shout.md b/.changeset/tame-hats-shout.md deleted file mode 100644 index 1576463c85..0000000000 --- a/.changeset/tame-hats-shout.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/frontend-plugin-api': patch -'@backstage/frontend-app-api': patch ---- - -Added `getNodesByRoutePath` method to the `AppTreeApi`. diff --git a/.changeset/tame-sloths-brake.md b/.changeset/tame-sloths-brake.md new file mode 100644 index 0000000000..eae1321175 --- /dev/null +++ b/.changeset/tame-sloths-brake.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-notifications': patch +--- + +Made "notification:send" action idempotent diff --git a/.changeset/thin-snails-judge.md b/.changeset/thin-snails-judge.md new file mode 100644 index 0000000000..c2328ed64f --- /dev/null +++ b/.changeset/thin-snails-judge.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Resolved a problem where the `start` command did not correctly handle multiple `--require` flags, ensuring all specified modules are now properly loaded. diff --git a/.changeset/tiny-swans-warn.md b/.changeset/tiny-swans-warn.md new file mode 100644 index 0000000000..45c6435a5d --- /dev/null +++ b/.changeset/tiny-swans-warn.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-home-react': patch +--- + +Fixes auto-hiding of content divider when title not specified diff --git a/.changeset/twelve-eyes-stare.md b/.changeset/twelve-eyes-stare.md deleted file mode 100644 index bd2db50c9b..0000000000 --- a/.changeset/twelve-eyes-stare.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-dynamic-feature-service': patch ---- - -Make sure changes are successfully tracked before starting up scanner. diff --git a/.changeset/twenty-forks-cheat.md b/.changeset/twenty-forks-cheat.md new file mode 100644 index 0000000000..c0a7f03ee8 --- /dev/null +++ b/.changeset/twenty-forks-cheat.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +Fix offset pagination to reset when updating filters in `useEntityList` diff --git a/.changeset/twenty-walls-join.md b/.changeset/twenty-walls-join.md new file mode 100644 index 0000000000..2282e28775 --- /dev/null +++ b/.changeset/twenty-walls-join.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-github': patch +--- + +Made "github:actions:dispatch" action idempotent diff --git a/.changeset/warm-masks-ring.md b/.changeset/warm-masks-ring.md deleted file mode 100644 index bfb521a005..0000000000 --- a/.changeset/warm-masks-ring.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Add optional props to `TechDocCustomHome` to allow for more flexibility: - -```tsx -import { TechDocsCustomHome } from '@backstage/plugin-techdocs'; -//... - -const options = { emptyRowsWhenPaging: false }; -const linkDestination = (entity: Entity): string | undefined => { - return entity.metadata.annotations?.['external-docs']; -}; -const techDocsTabsConfig = [ - { - label: 'Recommended Documentation', - panels: [ - { - title: 'Golden Path', - description: 'Documentation about standards to follow', - panelType: 'DocsCardGrid', - panelProps: { CustomHeader: () => }, - filterPredicate: entity => - entity?.metadata?.tags?.includes('golden-path') ?? false, - }, - { - title: 'Recommended', - description: 'Useful documentation', - panelType: 'InfoCardGrid', - panelProps: { - CustomHeader: () => - linkDestination: linkDestination, - }, - filterPredicate: entity => - entity?.metadata?.tags?.includes('recommended') ?? false, - }, - ], - }, - { - label: 'Browse All', - panels: [ - { - description: 'Browse all docs', - filterPredicate: filterEntity, - panelType: 'TechDocsIndexPage', - title: 'All', - panelProps: { PageWrapper: React.Fragment, CustomHeader: React.Fragment, options: options }, - }, - ], - }, -]; - -const AppRoutes = () => { - - ) => ({children})} - /> - } - /> - ; -}; -``` - -Add new Grid option called `InfoCardGrid` which is a more customizable card option for the Docs grid. - -```tsx - entity.metadata['external-docs']} -/> -``` - -Expose existing `CustomDocsPanel` so that it can be used independently if desired. - -```tsx -const panels: PanelConfig[] = [ - { - description: '', - filterPredicate: entity => {}, - panelType: 'InfoCardGrid', - title: 'Standards', - panelProps: { - CustomHeader: () => - linkDestination: linkDestination, - }, - }, - { - description: '', - filterPredicate: entity => {}, - panelType: 'DocsCardGrid', - title: 'Contribute', - }, -]; -{ - panels.map((config, index) => ( - - )); -} -``` diff --git a/.changeset/wet-penguins-beg.md b/.changeset/wet-penguins-beg.md new file mode 100644 index 0000000000..c4248f86f8 --- /dev/null +++ b/.changeset/wet-penguins-beg.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': minor +--- + +Internal update to move the `clean`, `pre/postpack` and `fix` commands into their own separate module. diff --git a/.changeset/wide-planets-camp.md b/.changeset/wide-planets-camp.md new file mode 100644 index 0000000000..c36ed69dff --- /dev/null +++ b/.changeset/wide-planets-camp.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +--- + +fixed misleading example location annotations in docs diff --git a/.changeset/wise-apes-juggle.md b/.changeset/wise-apes-juggle.md deleted file mode 100644 index 1b027771f9..0000000000 --- a/.changeset/wise-apes-juggle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Ensure that both global-agent and undici agents are enabled when proxying is enabled. diff --git a/.changeset/witty-pets-march.md b/.changeset/witty-pets-march.md deleted file mode 100644 index 163d146027..0000000000 --- a/.changeset/witty-pets-march.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-plugin-api': patch ---- - -Allow route references to be installed in multiple app instances as long as their name is the same. diff --git a/.changeset/witty-planets-sing.md b/.changeset/witty-planets-sing.md new file mode 100644 index 0000000000..4c58393d0e --- /dev/null +++ b/.changeset/witty-planets-sing.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': patch +--- + +Fix the Icon component when the name is not found to return null instead of an empty SVG. diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b31cca1080..76a6afe4d6 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -53,3 +53,8 @@ yarn.lock @backstage/maintainers @backst /plugins/user-settings @backstage/maintainers @backstage/reviewers @backstage/sda-se-reviewers /plugins/user-settings-backend @backstage/maintainers @backstage/reviewers @backstage/sda-se-reviewers /plugins/user-settings-common @backstage/maintainers @backstage/reviewers @backstage/sda-se-reviewers + +/packages/backend-plugin-api/src/services/definitions/AuditorService.ts @backstage/maintainers @backstage/auditor-maintainers +/packages/backend-defaults/src/entrypoints/auditor @backstage/maintainers @backstage/auditor-maintainers +/packages/backend-defaults/report-auditor.api.md @backstage/maintainers @backstage/auditor-maintainers +/docs/backend-system/core-services/auditor.md @backstage/maintainers @backstage/auditor-maintainers @backstage/documentation-maintainers diff --git a/.github/vale/config/vocabularies/Backstage/accept.txt b/.github/vale/config/vocabularies/Backstage/accept.txt index 9de05aab88..7a83dc6e92 100644 --- a/.github/vale/config/vocabularies/Backstage/accept.txt +++ b/.github/vale/config/vocabularies/Backstage/accept.txt @@ -14,6 +14,8 @@ allowlisted Anddddd Apdex api +apis +approvers asciidoc async Atlassian @@ -72,6 +74,7 @@ config Config configmaps configs +configurability conformant const cookiecutter @@ -88,7 +91,7 @@ Datadog dataflow dayjs debounce -Debounce +debounces debuggability declaratively deduplicate @@ -103,11 +106,14 @@ destructured destructuring Deutsche dev +devcontainer +devcontainers devops devs dequeue dequeueing dialogs +disambiguator discoverability Discoverability dls @@ -136,6 +142,7 @@ Expedia facto failover Fargate +featureful Figma firehydrant FireHydrant @@ -157,6 +164,7 @@ Gitiles gitlab GitLab globals +globbing Gource Grafana graphql @@ -189,9 +197,11 @@ Indal indexable ingestors inlined +inlining inlinehilite integrator's interop +interoperate iterable JaCoCo JavaScript @@ -221,12 +231,14 @@ learnings Leasot lerna Lerna +Levenshtein lightbox Lightsail limitranges LocalStack lockdown lockfile +lockfiles lookbehind lowercased lunr @@ -254,6 +266,7 @@ misconfiguration misconfigured mkdocs Mkdocs +modularization monorepo Monorepo monorepos @@ -273,6 +286,7 @@ neuro newrelic nginx nodegit +nodejs nohoist nonces noop @@ -325,9 +339,11 @@ PR pre prebaked preconfigured +prefilled prepack Preprarer productional +projectSlug Protobuf proxied proxying @@ -339,7 +355,7 @@ pygments pymdownx rankdir readme -Readme +readmes readonly rebase rebasing @@ -391,6 +407,7 @@ serializable Serverless shoutout SIG +signoff SIGs siloed Sinon @@ -425,6 +442,7 @@ subheaders subkey subpath subroutes +substring subtree superfences Superfences @@ -477,6 +495,7 @@ unregister unregistering unregistration unstarred +untemplated untracked upsert upstreams @@ -514,3 +533,4 @@ zoomable zsh scrollable severities +intellij diff --git a/.github/workflows/api-breaking-changes-comment.yml b/.github/workflows/api-breaking-changes-comment.yml index be66d93fbb..af625f67ab 100644 --- a/.github/workflows/api-breaking-changes-comment.yml +++ b/.github/workflows/api-breaking-changes-comment.yml @@ -20,9 +20,10 @@ jobs: git-ref: ${{ steps.event.outputs.GIT_REF }} pr-number: ${{ steps.event.outputs.PR_NUMBER }} action: ${{ steps.event.outputs.ACTION }} + comment-cache-key: ${{ steps.hash.outputs.COMMENT_FILE_HASH }} steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: disable-sudo: true egress-policy: block @@ -64,21 +65,29 @@ jobs: echo ACTION=$(jq --raw-output '.action | tostring | [scan("\\w+")][0]' < event.json) >> $GITHUB_OUTPUT echo GIT_REF=$(jq --raw-output '.pull_request.head.sha | tostring | [scan("\\w+")][0]' < event.json) >> $GITHUB_OUTPUT + - name: Fetch Command and Calculate Hash + id: hash + run: | + unzip preview-spec.zip comment.md + ls + echo "COMMENT_FILE_HASH=$(md5sum comment.md | awk '{ print $1 }')" >> $GITHUB_OUTPUT + + - name: Cache Comment + if: ${{ steps.event.outputs.ACTION != 'closed' }} + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: comment.md + key: ${{ steps.hash.outputs.COMMENT_FILE_HASH }} + - name: DEBUG - Print Job Outputs if: ${{ runner.debug }} run: | echo "PR number: ${{ steps.event.outputs.PR_NUMBER }}" echo "Git Ref: ${{ steps.event.outputs.GIT_REF }}" echo "Action: ${{ steps.event.outputs.ACTION }}" + echo "Hash: ${{ steps.hash.outputs.COMMENT_FILE_HASH }}" cat event.json - - name: Get Comment - id: get-comment - run: | - unzip preview-spec.zip comment.md - ls - grep - add-comment: name: Write comment about issues needs: @@ -92,6 +101,13 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - name: Fetch cached Manifests File + id: cache + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4 + with: + path: comment.md + key: ${{ needs.setup.outputs.comment-cache-key }} + # Identify comment to be updated - name: Find comment for API Changes uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e # v3 diff --git a/.github/workflows/api-breaking-changes.yml b/.github/workflows/api-breaking-changes.yml index e9d321d6e5..fb2a443f58 100644 --- a/.github/workflows/api-breaking-changes.yml +++ b/.github/workflows/api-breaking-changes.yml @@ -14,7 +14,7 @@ jobs: if: ${{ github.event_name != 'pull_request' || github.event.action != 'closed' }} steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit @@ -27,7 +27,7 @@ jobs: run: git fetch --depth 1 origin ${{ github.base_ref }} - name: setup-node - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: 20.x registry-url: https://registry.npmjs.org/ @@ -46,7 +46,7 @@ jobs: cat ${{ github.event_path }} > event.json - name: Upload Artifacts - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: preview-spec path: | diff --git a/.github/workflows/automate_area-labels.yml b/.github/workflows/automate_area-labels.yml index 45125e74d3..ec6dd0c85c 100644 --- a/.github/workflows/automate_area-labels.yml +++ b/.github/workflows/automate_area-labels.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/automate_changeset_feedback.yml b/.github/workflows/automate_changeset_feedback.yml index 4380b900a4..c1245c59b9 100644 --- a/.github/workflows/automate_changeset_feedback.yml +++ b/.github/workflows/automate_changeset_feedback.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/automate_merge_message.yml b/.github/workflows/automate_merge_message.yml index 11e7d6ef47..ebe2ef739d 100644 --- a/.github/workflows/automate_merge_message.yml +++ b/.github/workflows/automate_merge_message.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/automate_stale.yml b/.github/workflows/automate_stale.yml index 453f976ca0..c34c1312b1 100644 --- a/.github/workflows/automate_stale.yml +++ b/.github/workflows/automate_stale.yml @@ -15,11 +15,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit - - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0 + - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0 id: stale with: stale-issue-message: > diff --git a/.github/workflows/ci-noop.yml b/.github/workflows/ci-noop.yml index d51b67d1f9..472a7a4e72 100644 --- a/.github/workflows/ci-noop.yml +++ b/.github/workflows/ci-noop.yml @@ -40,7 +40,7 @@ jobs: name: Test ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bcf5ed94a0..76898bc8d2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,14 +28,14 @@ jobs: name: Install ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth @@ -64,14 +64,14 @@ jobs: name: Verify ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth @@ -127,6 +127,10 @@ jobs: - name: build all packages run: yarn backstage-cli repo build --all + # For now canon has a custom build script and needs to be built separately + - name: build canon + run: yarn --cwd packages/canon build + - name: verify type dependencies run: yarn lint:type-deps @@ -157,8 +161,8 @@ jobs: name: Test ${{ matrix.node-version }} services: - postgres16: - image: postgres:16 + postgres17: + image: postgres:17 env: POSTGRES_PASSWORD: postgres options: >- @@ -168,8 +172,8 @@ jobs: --health-retries 5 ports: - 5432/tcp - postgres12: - image: postgres:12 + postgres13: + image: postgres:13 env: POSTGRES_PASSWORD: postgres options: >- @@ -219,7 +223,7 @@ jobs: run: git fetch origin ${{ github.event.pull_request.base.ref }} - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth @@ -235,7 +239,7 @@ jobs: # Use the lower-level cache actions for the success cache, so that we can store the cache even on failed builds - name: restore backstage-cli cache - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4 + uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4 with: path: .cache/backstage-cli key: ${{ runner.os }}-v${{ matrix.node-version }}-backstage-cli-${{ github.run_id }} @@ -249,14 +253,14 @@ jobs: run: yarn backstage-cli repo test --maxWorkers=3 --workerIdleMemoryLimit=1300M --since origin/master --successCache --successCacheDir .cache/backstage-cli env: BACKSTAGE_TEST_DISABLE_DOCKER: 1 - BACKSTAGE_TEST_DATABASE_POSTGRES16_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres16.ports[5432] }} - BACKSTAGE_TEST_DATABASE_POSTGRES12_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres12.ports[5432] }} + BACKSTAGE_TEST_DATABASE_POSTGRES17_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres17.ports[5432] }} + BACKSTAGE_TEST_DATABASE_POSTGRES13_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres13.ports[5432] }} BACKSTAGE_TEST_DATABASE_MYSQL8_CONNECTION_STRING: mysql://root:root@localhost:${{ job.services.mysql8.ports[3306] }}/ignored BACKSTAGE_TEST_CACHE_REDIS7_CONNECTION_STRING: redis://localhost:${{ job.services.redis.ports[6379] }} # Always save success cache even if there were failures, that way it can be used in re-triggered builds - name: save backstage-cli cache - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4 + uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4 if: always() with: path: .cache/backstage-cli diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index d47e78f537..b48bd2683d 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -10,7 +10,7 @@ jobs: timeout-minutes: 10 steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml index 0cbba0d30d..555cc351c8 100644 --- a/.github/workflows/deploy_docker-image.yml +++ b/.github/workflows/deploy_docker-image.yml @@ -20,7 +20,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit @@ -31,7 +31,7 @@ jobs: ref: ${{ github.event.client_payload.version && env.RELEASE_VERSION || github.ref }} - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth @@ -59,7 +59,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0 + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 - name: Build and push uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d # v6.12.0 diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml index 2f9510c0cd..a700b21d5e 100644 --- a/.github/workflows/deploy_microsite.yml +++ b/.github/workflows/deploy_microsite.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit @@ -59,7 +59,7 @@ jobs: ref: refs/tags/${{ steps.find-release.outputs.result }} - name: Use Node.js 20.x - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: 20.x registry-url: https://registry.npmjs.org/ # Needed for auth @@ -73,13 +73,29 @@ jobs: run: yarn build:api-docs - name: upload API reference - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: stable-reference path: docs/reference/ if-no-files-found: error retention-days: 1 + - name: microsite yarn install + run: yarn install --immutable + working-directory: microsite + + - name: build OpenAPI API docs + working-directory: microsite + run: yarn docusaurus gen-api-docs all + + - name: upload OpenAPI API docs + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: stable-openapi-docs + path: docs/**/*.api.mdx + if-no-files-found: error + retention-days: 1 + next: runs-on: ubuntu-latest concurrency: @@ -91,7 +107,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit @@ -99,7 +115,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Use Node.js 20.x - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: 20.x registry-url: https://registry.npmjs.org/ # Needed for auth @@ -113,7 +129,7 @@ jobs: run: yarn build:api-docs - name: upload API reference - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: next-reference path: docs/reference/ @@ -130,13 +146,29 @@ jobs: working-directory: storybook - name: storybook upload - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: storybook path: storybook/dist/ if-no-files-found: error retention-days: 1 + - name: microsite yarn install + run: yarn install --immutable + working-directory: microsite + + - name: build OpenAPI API docs + working-directory: microsite + run: yarn docusaurus gen-api-docs all + + - name: upload OpenAPI API docs + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: next-openapi-docs + path: docs/**/*.api.mdx + if-no-files-found: error + retention-days: 1 + deploy-microsite-and-storybook: permissions: contents: write # for JamesIves/github-pages-deploy-action to push changes in repo @@ -158,12 +190,12 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit - name: Use Node.js 20.x - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: 20.x registry-url: https://registry.npmjs.org/ # Needed for auth @@ -179,11 +211,17 @@ jobs: working-directory: microsite - name: download stable reference - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: name: stable-reference path: docs/reference + - name: download stable OpenAPI API docs + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 + with: + name: stable-openapi-docs + path: docs/**/*.api.mdx + - name: grab lastest releases docs run: | git fetch origin master --depth 1 @@ -196,6 +234,9 @@ jobs: - name: clear API reference run: rm -r docs/reference + - name: clear OpenAPI reference + run: find . -name '*.api.mdx' -type f -delete + # Next docs - name: checkout master uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 @@ -207,16 +248,22 @@ jobs: working-directory: microsite - name: download next reference - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: name: next-reference path: docs/reference + - name: download next OpenAPI API docs + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 + with: + name: next-openapi-docs + path: docs/**/*.api.mdx + - name: build microsite run: yarn build working-directory: microsite - - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4 + - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: name: storybook path: microsite/build/storybook diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index d59bb189d0..e363fa4680 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -16,8 +16,8 @@ jobs: node-version: [20.x, 22.x] services: - postgres16: - image: postgres:16 + postgres17: + image: postgres:17 env: POSTGRES_PASSWORD: postgres options: >- @@ -27,8 +27,8 @@ jobs: --health-retries 5 ports: - 5432/tcp - postgres12: - image: postgres:12 + postgres13: + image: postgres:13 env: POSTGRES_PASSWORD: postgres options: >- @@ -71,7 +71,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth @@ -94,7 +94,7 @@ jobs: run: yarn backstage-cli config:check --lax - name: backstage-cli cache - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4 + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4 with: path: .cache/backstage-cli key: ${{ runner.os }}-v${{ matrix.node-version }}-backstage-cli-${{ github.run_id }} @@ -110,6 +110,10 @@ jobs: - name: build run: yarn backstage-cli repo build --all + # For now canon has a custom build script and needs to be built separately + - name: build canon + run: yarn --cwd packages/canon build + - name: verify type dependencies run: yarn lint:type-deps @@ -118,8 +122,8 @@ jobs: yarn backstage-cli repo test --maxWorkers=3 --workerIdleMemoryLimit=1300M --coverage --successCache --successCacheDir .cache/backstage-cli env: BACKSTAGE_TEST_DISABLE_DOCKER: 1 - BACKSTAGE_TEST_DATABASE_POSTGRES16_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres16.ports[5432] }} - BACKSTAGE_TEST_DATABASE_POSTGRES12_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres12.ports[5432] }} + BACKSTAGE_TEST_DATABASE_POSTGRES17_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres17.ports[5432] }} + BACKSTAGE_TEST_DATABASE_POSTGRES13_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres13.ports[5432] }} BACKSTAGE_TEST_DATABASE_MYSQL8_CONNECTION_STRING: mysql://root:root@localhost:${{ job.services.mysql8.ports[3306] }}/ignored BACKSTAGE_TEST_CACHE_REDIS7_CONNECTION_STRING: redis://localhost:${{ job.services.redis.ports[6379] }} @@ -147,7 +151,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/issue.yaml b/.github/workflows/issue.yaml index 71fb301aad..8e30170aca 100644 --- a/.github/workflows/issue.yaml +++ b/.github/workflows/issue.yaml @@ -16,7 +16,7 @@ jobs: if: github.repository == 'backstage/backstage' steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/pr-review-comment-trigger.yaml b/.github/workflows/pr-review-comment-trigger.yaml index a9653fe65e..61252e7567 100644 --- a/.github/workflows/pr-review-comment-trigger.yaml +++ b/.github/workflows/pr-review-comment-trigger.yaml @@ -20,7 +20,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit @@ -30,7 +30,7 @@ jobs: run: | mkdir -p ./pr echo $PR_NUMBER > ./pr/pr_number - - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + - uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 with: name: pr_number-${{ github.event.pull_request.number }} path: pr/ diff --git a/.github/workflows/pr-review-comment.yaml b/.github/workflows/pr-review-comment.yaml index c6fd02dd2f..e108f3a4d7 100644 --- a/.github/workflows/pr-review-comment.yaml +++ b/.github/workflows/pr-review-comment.yaml @@ -17,7 +17,7 @@ jobs: steps: # Inspired by https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#using-data-from-the-triggering-workflow - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 08694ee095..ab2630c2d9 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -18,7 +18,7 @@ jobs: if: github.repository == 'backstage/backstage' && ( github.event.pull_request || github.event.issue.pull_request ) steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index acad33eb2f..4a5707087e 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -29,7 +29,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit @@ -58,7 +58,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: 'Upload artifact' - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 with: name: SARIF file path: results.sarif @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 + uses: github/codeql-action/upload-sarif@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 with: sarif_file: results.sarif diff --git a/.github/workflows/sync_canon.yml b/.github/workflows/sync_canon.yml index d3593fc017..a23e039b06 100644 --- a/.github/workflows/sync_canon.yml +++ b/.github/workflows/sync_canon.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit @@ -16,7 +16,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Use Node.js 20.x - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: 20.x registry-url: https://registry.npmjs.org/ # Needed for auth diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml index d7d4616202..90a3f62aba 100644 --- a/.github/workflows/sync_code-formatting.yml +++ b/.github/workflows/sync_code-formatting.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit @@ -20,7 +20,7 @@ jobs: fetch-depth: 0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth diff --git a/.github/workflows/sync_dependabot-changesets.yml b/.github/workflows/sync_dependabot-changesets.yml index e357c2b0d0..42efaa1142 100644 --- a/.github/workflows/sync_dependabot-changesets.yml +++ b/.github/workflows/sync_dependabot-changesets.yml @@ -11,7 +11,7 @@ jobs: if: github.actor == 'dependabot[bot]' && github.repository == 'backstage/backstage' steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/sync_release-manifest.yml b/.github/workflows/sync_release-manifest.yml index 52594d58e6..1a47978b8c 100644 --- a/.github/workflows/sync_release-manifest.yml +++ b/.github/workflows/sync_release-manifest.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit @@ -19,7 +19,7 @@ jobs: ref: v${{ github.event.client_payload.version }} - name: Use Node.js 20.x - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: 20.x registry-url: https://registry.npmjs.org/ # Needed for auth diff --git a/.github/workflows/sync_renovate-changesets.yml b/.github/workflows/sync_renovate-changesets.yml index b87b4c4752..2eb8f13dbc 100644 --- a/.github/workflows/sync_renovate-changesets.yml +++ b/.github/workflows/sync_renovate-changesets.yml @@ -11,7 +11,7 @@ jobs: if: github.actor == 'renovate[bot]' && github.repository == 'backstage/backstage' steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml index 2252aa0ddb..f9e202e3e0 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -12,14 +12,14 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Use Node.js 20.x - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: 20.x registry-url: https://registry.npmjs.org/ # Needed for auth diff --git a/.github/workflows/sync_snyk-monitor.yml b/.github/workflows/sync_snyk-monitor.yml index c21b0bbff1..aec03d09ee 100644 --- a/.github/workflows/sync_snyk-monitor.yml +++ b/.github/workflows/sync_snyk-monitor.yml @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit @@ -58,6 +58,6 @@ jobs: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} NODE_OPTIONS: --max-old-space-size=7168 - name: Upload Snyk report - uses: github/codeql-action/upload-sarif@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 + uses: github/codeql-action/upload-sarif@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 with: sarif_file: snyk.sarif diff --git a/.github/workflows/sync_version-packages.yml b/.github/workflows/sync_version-packages.yml index a2faaa10a3..4a33b2241e 100644 --- a/.github/workflows/sync_version-packages.yml +++ b/.github/workflows/sync_version-packages.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit @@ -23,6 +23,10 @@ jobs: fetch-depth: 20000 fetch-tags: true token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} + + - name: Fetch tags # See https://github.com/actions/checkout/issues/2041 + run: git fetch --tags + - name: Install Dependencies run: yarn --immutable - name: Create Release Pull Request diff --git a/.github/workflows/verify_accessibility-noop.yml b/.github/workflows/verify_accessibility-noop.yml index d637788814..c33acfd86d 100644 --- a/.github/workflows/verify_accessibility-noop.yml +++ b/.github/workflows/verify_accessibility-noop.yml @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/verify_accessibility.yml b/.github/workflows/verify_accessibility.yml index b9eb7f1bec..b1ed9448c0 100644 --- a/.github/workflows/verify_accessibility.yml +++ b/.github/workflows/verify_accessibility.yml @@ -20,13 +20,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Use Node.js 20.x - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: 20.x - name: yarn install diff --git a/.github/workflows/verify_codeql.yml b/.github/workflows/verify_codeql.yml index 5b3aa7479a..d028be98d8 100644 --- a/.github/workflows/verify_codeql.yml +++ b/.github/workflows/verify_codeql.yml @@ -42,7 +42,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit @@ -55,7 +55,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 + uses: github/codeql-action/init@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -66,7 +66,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 + uses: github/codeql-action/autobuild@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -80,4 +80,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 + uses: github/codeql-action/analyze@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 diff --git a/.github/workflows/verify_docs-quality.yml b/.github/workflows/verify_docs-quality.yml index dab2f421b5..a3b80f498a 100644 --- a/.github/workflows/verify_docs-quality.yml +++ b/.github/workflows/verify_docs-quality.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/verify_e2e-linux-noop.yml b/.github/workflows/verify_e2e-linux-noop.yml index 94ad720d51..65fc6eccc9 100644 --- a/.github/workflows/verify_e2e-linux-noop.yml +++ b/.github/workflows/verify_e2e-linux-noop.yml @@ -29,7 +29,7 @@ jobs: name: E2E Linux ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml index 69d1d2eb4b..7ae7e298e7 100644 --- a/.github/workflows/verify_e2e-linux.yml +++ b/.github/workflows/verify_e2e-linux.yml @@ -21,7 +21,7 @@ jobs: services: postgres: - image: postgres:12 + image: postgres:13 env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres @@ -43,7 +43,7 @@ jobs: name: E2E Linux ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit @@ -55,7 +55,7 @@ jobs: git config --global user.name 'GitHub e2e user' - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth diff --git a/.github/workflows/verify_e2e-techdocs.yml b/.github/workflows/verify_e2e-techdocs.yml index 4d4b32eaef..e5fe78cd8e 100644 --- a/.github/workflows/verify_e2e-techdocs.yml +++ b/.github/workflows/verify_e2e-techdocs.yml @@ -32,12 +32,12 @@ jobs: name: Techdocs steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 + - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 with: python-version: '3.9' diff --git a/.github/workflows/verify_e2e-windows-noop.yml b/.github/workflows/verify_e2e-windows-noop.yml index 269e70d8b4..e713f33ed6 100644 --- a/.github/workflows/verify_e2e-windows-noop.yml +++ b/.github/workflows/verify_e2e-windows-noop.yml @@ -25,7 +25,7 @@ jobs: name: E2E Windows ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/verify_e2e-windows.yml b/.github/workflows/verify_e2e-windows.yml index b9d76da02a..6a27f119e3 100644 --- a/.github/workflows/verify_e2e-windows.yml +++ b/.github/workflows/verify_e2e-windows.yml @@ -33,7 +33,7 @@ jobs: name: E2E Windows ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit @@ -52,13 +52,13 @@ jobs: git config --global user.name 'GitHub e2e user' - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: setup python - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 + uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 with: python-version: '3.10' diff --git a/.github/workflows/verify_fossa.yml b/.github/workflows/verify_fossa.yml index 1b85a9469b..7bc612bf64 100644 --- a/.github/workflows/verify_fossa.yml +++ b/.github/workflows/verify_fossa.yml @@ -14,7 +14,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/verify_microsite-noop.yml b/.github/workflows/verify_microsite-noop.yml index 63e759f0ba..da4bc6ba25 100644 --- a/.github/workflows/verify_microsite-noop.yml +++ b/.github/workflows/verify_microsite-noop.yml @@ -21,7 +21,7 @@ jobs: name: Microsite steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/verify_microsite.yml b/.github/workflows/verify_microsite.yml index c4a2934c57..c46ba57e97 100644 --- a/.github/workflows/verify_microsite.yml +++ b/.github/workflows/verify_microsite.yml @@ -24,17 +24,17 @@ jobs: name: Microsite steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Use Node.js 20.x - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: 20.x - - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5 + - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5 with: python-version: '3.9' diff --git a/.github/workflows/verify_microsite_accessibility-noop.yml b/.github/workflows/verify_microsite_accessibility-noop.yml index 2640c215a1..d6f9d24b5e 100644 --- a/.github/workflows/verify_microsite_accessibility-noop.yml +++ b/.github/workflows/verify_microsite_accessibility-noop.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/verify_microsite_accessibility.yml b/.github/workflows/verify_microsite_accessibility.yml index 008895357f..fc461965a3 100644 --- a/.github/workflows/verify_microsite_accessibility.yml +++ b/.github/workflows/verify_microsite_accessibility.yml @@ -15,14 +15,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Use Node.js 20.x - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: 20.x diff --git a/.github/workflows/verify_storybook-noop.yml b/.github/workflows/verify_storybook-noop.yml index 4bb54136ab..392a218a83 100644 --- a/.github/workflows/verify_storybook-noop.yml +++ b/.github/workflows/verify_storybook-noop.yml @@ -28,7 +28,7 @@ jobs: name: Storybook steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml index c43ed0c622..1181273bb0 100644 --- a/.github/workflows/verify_storybook.yml +++ b/.github/workflows/verify_storybook.yml @@ -28,7 +28,7 @@ jobs: name: Storybook steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit @@ -37,7 +37,7 @@ jobs: fetch-depth: 0 # Required to retrieve git history - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth @@ -54,7 +54,7 @@ jobs: - run: yarn --cwd packages/canon build-storybook - - uses: chromaui/action@64a9c0ca3bfb724389b0d536e544f56b7b5ff5b3 # v11 + - uses: chromaui/action@c93e0bc3a63aa176e14a75b61a31847cbfdd341c # v11 with: token: ${{ secrets.GITHUB_TOKEN }} # projectToken intentionally shared to allow collaborators to run Chromatic on forks diff --git a/.github/workflows/verify_windows.yml b/.github/workflows/verify_windows.yml index 1eee6e61f3..0ee95463d8 100644 --- a/.github/workflows/verify_windows.yml +++ b/.github/workflows/verify_windows.yml @@ -29,14 +29,14 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth diff --git a/.gitignore b/.gitignore index 865918c1f7..25280b40b0 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,11 @@ bower_components # Documentation reference, generated by build:api-docs docs/reference +# OpenAPI auto-generated API documentation. +docs/**/*.api.mdx +docs/**/*.info.mdx +docs/**/sidebar.ts + # node-waf configuration .lock-wscript @@ -174,3 +179,8 @@ knip.json # Schemathesis temporary files .hypothesis/ .cassettes/ + +# Typedocs temporary files +type-docs +docs.json +tsconfig.typedoc.tmp.json \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index cb744faa4c..04ca7d780d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -4,6 +4,7 @@ microsite canon-docs/.next canon-docs/public canon-docs/out +packages/canon/css coverage *.hbs templates diff --git a/.yarn/patches/ast-types-npm-0.14.2-43c4ac4b0d.patch b/.yarn/patches/ast-types-npm-0.14.2-43c4ac4b0d.patch new file mode 100644 index 0000000000..add3e4c556 --- /dev/null +++ b/.yarn/patches/ast-types-npm-0.14.2-43c4ac4b0d.patch @@ -0,0 +1,15 @@ +diff --git a/main.d.ts b/main.d.ts +index 6b9a8d05d61821a7e7dc831a52a9f7b505bfee42..1010bb5352d975a171a4019768ff6f6f2967c301 100644 +--- a/main.d.ts ++++ b/main.d.ts +@@ -1,7 +1,7 @@ +-import { ASTNode, Type, AnyType, Field } from "./lib/types"; +-import { NodePath } from "./lib/node-path"; ++import { ASTNode, type Type, AnyType, Field } from "./lib/types"; ++import { type NodePath } from "./lib/node-path"; + import { namedTypes } from "./gen/namedTypes"; +-import { builders } from "./gen/builders"; ++import { type builders } from "./gen/builders"; + import { Visitor } from "./gen/visitor"; + declare const astNodesAreEquivalent: { + (a: any, b: any, problemPath?: any): boolean; diff --git a/ADOPTERS.md b/ADOPTERS.md index 1eacd4c104..17ebefd4c6 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -5,7 +5,7 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/ | Organization | Contact | Description of Use | |-----------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [Spotify](https://www.spotify.com) | [@helengreul](https://github.com/helengreul) | Main interface towards all of Spotify's infrastructure and technical documentation. | +| [Spotify](https://www.spotify.com) | [@mihaitabara](https://github.com/mihaitabara) | Main interface towards all of Spotify's infrastructure and technical documentation. | | [bol.com](https://www.bol.com) | [@acierto](https://github.com/acierto), [@clanghout](https://github.com/clanghout) | Initial work being done to unify platform tooling. | | [DFDS](https://www.dfds.com) | [@carlsendk](https://github.com/carlsendk) | V2 self-service platform. | | [Roadie](https://roadie.io) | [@dtuite](https://github.com/dtuite) | Hosted, managed Backstage with easy set-up | @@ -282,4 +282,4 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/ | [Axelerant](https://www.axelerant.com/) | [Zeshan Ziya](https://github.com/zeshanziya) | Developer portal, main gateway to infrastructure, documentation, internal tooling, and service catalog with a focus on project visibility. | [KnowBe4](https://www.knowbe4.com) | [Brandon Vicinus](https://www.linkedin.com/in/bvicinus/) | Internal Developer Portal managed by the Developer Experience Team. IDP hosts many different internal tools as plugins created by multiple teams, many of which are directly integrated with the Service Catalog. | | [Scalepoint](https://scalepoint.com) | [Yuriy Ostapenko](https://github.com/yuriyostapenko), [Dmytro Pasko](https://github.com/dimapasko), [Yuri Sedykh ](https://github.com/yuiri-sedykh), [Bartosz Wisniewski](https://github.com/Epgor) | Internal Developer Portal: Software Catalog with infrastructure resources and dependencies, Software Templates, TechDocs, Tech Radar, Kubernetes and Observability, as well as custom CI/CD components | - +| [VR](https://www.vr.com.br) | [Felipe Gomes](https://www.linkedin.com/in/felipe-gomes-da-silva), [Tiago Garcia](https://www.linkedin.com/in/tiago-garcia-6301a925) | Internal portal for development squads, service catalog, documentation hub, and application mapping for the entire company ecosystem, simplifying cloud infrastructure construction through templates. | diff --git a/OWNERS.md b/OWNERS.md index 335ab60ad7..8190e31bfd 100644 --- a/OWNERS.md +++ b/OWNERS.md @@ -53,7 +53,6 @@ Scope: The Backstage home page and information architecture | Emma Indal | Spotify | Infinite Buck$ | [emmaindal](http://github.com/emmaindal) | emmaindal#7503 | | Djamaile Rahamat | Spotify | Infinite Buck$ | [djamaile](http://github.com/djamaile) | dyoqi | | Raghunandan Balachandran | Spotify | Infinite Buck$ | [soapraj](http://github.com/soapraj) | raghunandanb#1114 | -| Bailey Brooks | Spotify | Infinite Buck$ | [bailey](http://github.com/bailey) | \_bailey4 | ### Search @@ -133,7 +132,6 @@ Scope: Tooling and Community Repo Maintainers for the Backstage [Community Plugi | André Wanlin | Spotify | [awanlin](https://github.com/awanlin) | `ahhhndre` | | Bethany Griggs | Red Hat | [BethGriggs](https://github.com/BethGriggs) | `bethgriggs` | | Kashish Mittal | Red Hat | [04kash](https://github.com/04kash) | `kashh._.` | -| Nick Boldt | Red Hat | [nickboldt](https://github.com/nickboldt) | `nboldt` | | Vincenzo Scamporlino | Spotify | [vinzscam](https://github.com/vinzscam) | `vinzscam` | ### Events @@ -176,6 +174,16 @@ Scope: The Scaffolder frontend and backend plugins, and related tooling. | ------------------- | ------------ | ------------------------------------- | ---------------- | | Bogdan Nechyporenko | Bol.com | [acierto](https://github.com/acierto) | `bogdan_haarlem` | +### Auditor + +Team: @backstage/auditor-maintainers + +Scope: The auditor core service, along with auditor usage in the main repository + +| Name | Organization | GitHub | Discord | +| ------------ | ------------ | ----------------------------------------------- | -------------- | +| Paul Schultz | Red Hat | [schultzp2020](https://github.com/schultzp2020) | `schultzp2020` | + ### Documentation Team: @backstage/documentation-maintainers @@ -190,11 +198,11 @@ Scope: The Backstage Documentation ## Sponsors -| Name | Organization | GitHub | Email | -| ----------------- | ------------ | ------------------------------------------- | ----------------- | -| Niklas Gustavsson | Spotify | [protocol7](https://github.com/protocol7) | ngn@spotify.com | -| Dave Zolotusky | Spotify | [dzolotusky](https://github.com/dzolotusky) | dzolo@spotify.com | -| Pia Nilsson | Spotify | [pianilsson](https://github.com/pianilsson) | pia@spotify.com | +| Name | Organization | GitHub | Email | +| ----------------- | ------------ | ------------------------------------------- | ------------------- | +| Niklas Gustavsson | Spotify | [protocol7](https://github.com/protocol7) | | +| Dave Zolotusky | Spotify | [dzolotusky](https://github.com/dzolotusky) | | +| Pia Nilsson | Spotify | [pianilsson](https://github.com/pianilsson) | | ## Organization Members diff --git a/README-fr_FR.md b/README-fr_FR.md index e0cffaa5c5..a54e9c8c49 100644 --- a/README-fr_FR.md +++ b/README-fr_FR.md @@ -66,7 +66,7 @@ Si vous voulez contribuer et vous impliquer dans notre communauté, voici les re ## Licence -Copyright 2020-2024 © Les auteurs de Backstage. Tous droits réservés. La Linux Foundation détient des marques déposées et utilise des marques commerciales. Pour une liste des marques de commerce de la Linux Foundation, veuillez consulter notre page d'utilisation des marques: https://www.linuxfoundation.org/trademark-usage +Copyright 2020-2025 © Les auteurs de Backstage. Tous droits réservés. La Linux Foundation détient des marques déposées et utilise des marques commerciales. Pour une liste des marques de commerce de la Linux Foundation, veuillez consulter notre page d'utilisation des marques: https://www.linuxfoundation.org/trademark-usage Sous licence Apache, version 2.0: http://www.apache.org/licenses/LICENSE-2.0 diff --git a/README-ko_kr.md b/README-ko_kr.md index b2bba41567..e43aa60c43 100644 --- a/README-ko_kr.md +++ b/README-ko_kr.md @@ -65,7 +65,7 @@ Backstage의 문서는 다음을 포함합니다: ## License -Copyright 2020-2024 © The Backstage Authors. All rights reserved. The Linux Foundation has registered trademarks and uses trademarks. For a list of trademarks of The Linux Foundation, please see our Trademark Usage page: https://www.linuxfoundation.org/trademark-usage +Copyright 2020-2025 © The Backstage Authors. All rights reserved. The Linux Foundation has registered trademarks and uses trademarks. For a list of trademarks of The Linux Foundation, please see our Trademark Usage page: https://www.linuxfoundation.org/trademark-usage Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 diff --git a/README-zh_Hans.md b/README-zh_Hans.md index 129c7e7aa4..4661564725 100644 --- a/README-zh_Hans.md +++ b/README-zh_Hans.md @@ -65,7 +65,7 @@ Backstage 的文档包括: ## 许可 -版权所有 2020-2024 © Backstage 作者。版权所有。Linux 基金会已注册商标并使用商标。有关 Linux 基金会的商标列表,请参阅我们的商标使用页面:https://www.linuxfoundation.org/trademark-usage +版权所有 2020-2025 © Backstage 作者。版权所有。Linux 基金会已注册商标并使用商标。有关 Linux 基金会的商标列表,请参阅我们的商标使用页面:https://www.linuxfoundation.org/trademark-usage 采用 Apache v2.0 许可:http://www.apache.org/licenses/LICENSE-2.0 diff --git a/README.md b/README.md index 64a7b34b64..e3e9bd77dd 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ See the [GOVERNANCE.md](https://github.com/backstage/community/blob/main/GOVERNA ## License -Copyright 2020-2024 © The Backstage Authors. All rights reserved. The Linux Foundation has registered trademarks and uses trademarks. For a list of trademarks of The Linux Foundation, please see our Trademark Usage page: https://www.linuxfoundation.org/trademark-usage +Copyright 2020-2025 © The Backstage Authors. All rights reserved. The Linux Foundation has registered trademarks and uses trademarks. For a list of trademarks of The Linux Foundation, please see our Trademark Usage page: https://www.linuxfoundation.org/trademark-usage Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 diff --git a/app-config.yaml b/app-config.yaml index 64c2fa5c4c..89e417fad3 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -244,6 +244,7 @@ integrations: secretAccessKey: ${AWS_SECRET_ACCESS_KEY} catalog: + useUrlReadersSearch: true import: entityFilename: catalog-info.yaml pullRequestBranchName: backstage-integration diff --git a/beps/0004-scaffolder-task-idempotency/README.md b/beps/0004-scaffolder-task-idempotency/README.md index 208446158e..e23cc519d1 100644 --- a/beps/0004-scaffolder-task-idempotency/README.md +++ b/beps/0004-scaffolder-task-idempotency/README.md @@ -154,30 +154,36 @@ export function createGithubRepoCreateAction(options: { username: owner, }); - await ctx.checkpoint('repo.creation', async () => { - const repoCreationPromise = - user.data.type === 'Organization' - ? client.rest.repos.createInOrg({ - name: repo, - org: owner, - }) - : client.rest.repos.createForAuthenticatedUser({ - name: repo, - }); - const { repoUrl } = await repoCreationPromise; - return { repoUrl }; + await ctx.checkpoint({ + key: 'repo.creation.v1', + fn: async () => { + const repoCreationPromise = + user.data.type === 'Organization' + ? client.rest.repos.createInOrg({ + name: repo, + org: owner, + }) + : client.rest.repos.createForAuthenticatedUser({ + name: repo, + }); + const { repoUrl } = await repoCreationPromise; + return { repoUrl }; + }, }); if (secrets) { - await ctx.checkpoint('repo.create.variables', async () => { - for (const [key, value] of Object.entries(repoVariables ?? {})) { - await client.rest.actions.createRepoVariable({ - owner, - repo, - name: key, - value: value, - }); - } + await ctx.checkpoint({ + key: 'repo.create.variables', + fn: async () => { + for (const [key, value] of Object.entries(repoVariables ?? {})) { + await client.rest.actions.createRepoVariable({ + owner, + repo, + name: key, + value: value, + }); + } + }, }); } @@ -202,9 +208,12 @@ Checkpoints will allow action authors to create actions where code paths are ign This will be provided on a context object and action of author provide a key and a callback. ```typescript -await ctx.checkpoint('repo.creation', async () => { - const { repoUrl } = await client.rest.Repository.create({}); - return { repoUrl }; +await ctx.checkpoint({ + key: 'repo.creation', + fn: async () => { + const { repoUrl } = await client.rest.Repository.create({}); + return { repoUrl }; + }, }); ``` diff --git a/canon-docs/package.json b/canon-docs/package.json index 3ab78ff7ec..25ffb047a8 100644 --- a/canon-docs/package.json +++ b/canon-docs/package.json @@ -6,7 +6,7 @@ "build": "npm run build:css && next build", "build:css": "node scripts/build-css.js", "lint": "next lint", - "start": "next dev" + "start": "npm run build:css && next dev" }, "dependencies": { "@codemirror/lang-sass": "^6.0.2", @@ -17,9 +17,10 @@ "@storybook/react": "^8.4.7", "@uiw/codemirror-themes": "^4.23.7", "@uiw/react-codemirror": "^4.23.7", - "next": "14.2.23", - "react": "^18", - "react-dom": "^18", + "motion": "^12.4.1", + "next": "14.2.25", + "react": "^18.0.2", + "react-dom": "^18.0.2", "react-frame-component": "^5.2.7", "shiki": "^1.26.1", "storybook": "^8.4.7" @@ -27,8 +28,8 @@ "devDependencies": { "@types/mdx": "^2.0.13", "@types/node": "^20", - "@types/react": "^18", - "@types/react-dom": "^18", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", "eslint": "^8", "eslint-config-next": "14.2.23", "lightningcss": "^1.28.2", diff --git a/canon-docs/scripts/build-css.js b/canon-docs/scripts/build-css.js index be85164347..dd9775150f 100644 --- a/canon-docs/scripts/build-css.js +++ b/canon-docs/scripts/build-css.js @@ -9,11 +9,6 @@ const source1 = path.join(__dirname, `${source}/core.css`); const destination1 = path.join(__dirname, `${destination}/core.css`); const source2 = path.join(__dirname, `${source}/components.css`); const destination2 = path.join(__dirname, `${destination}/components.css`); -const source3 = path.join( - __dirname, - `../../packages/canon/.storybook/themes/backstage.css`, -); -const destination3 = path.join(__dirname, `${destination}/backstage.css`); // Function to bundle and copy the CSS file const bundleAndCopyFile = async (source, destination) => { @@ -34,7 +29,6 @@ const bundleAndCopyFile = async (source, destination) => { Promise.all([ bundleAndCopyFile(source1, destination1), bundleAndCopyFile(source2, destination2), - bundleAndCopyFile(source3, destination3), ]) .then(() => { // Add an empty line after all operations are complete - It looks better in the terminal :) diff --git a/canon-docs/src/app/(docs)/components/box/page.mdx b/canon-docs/src/app/(docs)/components/box/page.mdx index 2e1d00a274..c1413dbe19 100644 --- a/canon-docs/src/app/(docs)/components/box/page.mdx +++ b/canon-docs/src/app/(docs)/components/box/page.mdx @@ -1,9 +1,10 @@ import { CodeBlock } from '@/components/CodeBlock'; import { PropsTable } from '@/components/PropsTable'; -import { spacePropsList } from '@/utils/spaceProps'; import { Tabs } from '@/components/Tabs'; import { Snippet } from '@/components/Snippet'; import { BoxPreview } from '@/snippets/box'; +import { boxPropDefs } from './props'; +import { spacingPropDefs } from '../../../../utils/propDefs'; # Box @@ -36,60 +37,13 @@ Box is the lowest-level component in Canon. It provides a consistent API for sty This is the Box component, our lowest-level component. Here are all the available properties. - + Padding and margin are used to create space around your component using our predefined spacing tokens. We would recommend to use padding over margin to avoid collapsing margins but both are available. - + ## Examples diff --git a/canon-docs/src/app/(docs)/components/box/props.ts b/canon-docs/src/app/(docs)/components/box/props.ts new file mode 100644 index 0000000000..f3e38984dd --- /dev/null +++ b/canon-docs/src/app/(docs)/components/box/props.ts @@ -0,0 +1,24 @@ +import { + classNamePropDefs, + displayPropDefs, + heightPropDefs, + positionPropDefs, + stylePropDefs, + widthPropDefs, +} from '../../../../utils/propDefs'; +import type { PropDef } from '../../../../utils/propDefs'; + +export const boxPropDefs: Record = { + as: { + type: 'enum', + values: ['div', 'span'], + default: 'div', + responsive: true, + }, + ...widthPropDefs, + ...heightPropDefs, + ...positionPropDefs, + ...displayPropDefs, + ...classNamePropDefs, + ...stylePropDefs, +}; diff --git a/canon-docs/src/app/(docs)/components/button/page.mdx b/canon-docs/src/app/(docs)/components/button/page.mdx index c35c4888f3..a92a6675d1 100644 --- a/canon-docs/src/app/(docs)/components/button/page.mdx +++ b/canon-docs/src/app/(docs)/components/button/page.mdx @@ -11,6 +11,7 @@ import { ButtonResponsive, } from '@/snippets/button'; import { buttonVariants } from '@/snippets/_snippets'; +import { buttonPropDefs } from './props'; # Button @@ -58,34 +59,7 @@ A button component that can be used to trigger actions. ## API reference - + ## Examples @@ -141,9 +115,9 @@ Here's a view when buttons are full width. py={4} open preview={} - code={` + code={` -`} +`} /> ### Disabled @@ -167,9 +141,7 @@ Here's a view when buttons are responsive. py={4} open preview={} - code={``} + code={``} /> diff --git a/canon-docs/src/app/(docs)/components/button/props.ts b/canon-docs/src/app/(docs)/components/button/props.ts new file mode 100644 index 0000000000..813dcaa6f0 --- /dev/null +++ b/canon-docs/src/app/(docs)/components/button/props.ts @@ -0,0 +1,19 @@ +import { classNamePropDefs, stylePropDefs } from '../../../../utils/propDefs'; +import type { PropDef } from '../../../../utils/propDefs'; + +export const buttonPropDefs: Record = { + variant: { + type: 'enum', + values: ['primary', 'secondary'], + default: 'primary', + responsive: true, + }, + size: { + type: 'enum', + values: ['small', 'medium'], + default: 'medium', + responsive: true, + }, + ...classNamePropDefs, + ...stylePropDefs, +}; diff --git a/canon-docs/src/app/(docs)/components/checkbox/page.mdx b/canon-docs/src/app/(docs)/components/checkbox/page.mdx index 26a5d0f955..fd2ec42e1b 100644 --- a/canon-docs/src/app/(docs)/components/checkbox/page.mdx +++ b/canon-docs/src/app/(docs)/components/checkbox/page.mdx @@ -4,6 +4,7 @@ import { Snippet } from '@/components/Snippet'; import { Tabs } from '@/components/Tabs'; import { CodeBlock } from '@/components/CodeBlock'; import { BaseUI } from '@/components/HeadlessBanners/BaseUI'; +import { checkboxPropDefs } from './props'; # Checkbox @@ -42,50 +43,7 @@ A checkbox component that can be used to trigger actions. - void", - responsive: false, - }, - disabled: { - type: 'boolean', - responsive: false, - }, - required: { - type: 'boolean', - responsive: false, - }, - name: { - type: 'string', - responsive: false, - }, - value: { - type: 'string', - responsive: false, - }, - className: { - type: 'string', - responsive: false, - }, - style: { - type: 'CSSProperties', - responsive: false, - }, - }} -/> + ## Examples diff --git a/canon-docs/src/app/(docs)/components/checkbox/props.ts b/canon-docs/src/app/(docs)/components/checkbox/props.ts new file mode 100644 index 0000000000..8abbac1ec9 --- /dev/null +++ b/canon-docs/src/app/(docs)/components/checkbox/props.ts @@ -0,0 +1,44 @@ +import { classNamePropDefs, stylePropDefs } from '../../../../utils/propDefs'; +import type { PropDef } from '../../../../utils/propDefs'; + +export const checkboxPropDefs: Record = { + label: { + type: 'string', + responsive: false, + }, + defaultChecked: { + type: 'enum', + values: ['boolean', "'indeterminate'"], + responsive: false, + }, + checked: { + type: 'enum', + values: ['boolean', "'indeterminate'"], + responsive: false, + }, + onChange: { + type: 'enum', + values: ["(checked: boolean | 'indeterminate') => void"], + responsive: false, + }, + disabled: { + type: 'enum', + values: ['boolean'], + responsive: false, + }, + required: { + type: 'enum', + values: ['boolean'], + responsive: false, + }, + name: { + type: 'string', + responsive: false, + }, + value: { + type: 'string', + responsive: false, + }, + ...classNamePropDefs, + ...stylePropDefs, +}; diff --git a/canon-docs/src/app/(docs)/components/container/page.mdx b/canon-docs/src/app/(docs)/components/container/page.mdx index ace3bdcaeb..0dbe0223e5 100644 --- a/canon-docs/src/app/(docs)/components/container/page.mdx +++ b/canon-docs/src/app/(docs)/components/container/page.mdx @@ -1,9 +1,9 @@ import { CodeBlock } from '@/components/CodeBlock'; import { PropsTable } from '@/components/PropsTable'; -import { spacePropsList } from '@/utils/spaceProps'; import { Tabs } from '@/components/Tabs'; import { Snippet } from '@/components/Snippet'; import { ContainerPreview } from '@/snippets/container'; +import { containerPropDefs } from './props'; # Container @@ -32,46 +32,7 @@ content on the page. ## API reference - + ## Examples diff --git a/canon-docs/src/app/(docs)/components/container/props.ts b/canon-docs/src/app/(docs)/components/container/props.ts new file mode 100644 index 0000000000..4a3410ec12 --- /dev/null +++ b/canon-docs/src/app/(docs)/components/container/props.ts @@ -0,0 +1,12 @@ +import { + classNamePropDefs, + stylePropDefs, + gapPropDefs, +} from '../../../../utils/propDefs'; +import type { PropDef } from '../../../../utils/propDefs'; + +export const containerPropDefs: Record = { + ...gapPropDefs, + ...classNamePropDefs, + ...stylePropDefs, +}; diff --git a/canon-docs/src/app/(docs)/components/field/page.mdx b/canon-docs/src/app/(docs)/components/field/page.mdx index 83029be506..54c091faeb 100644 --- a/canon-docs/src/app/(docs)/components/field/page.mdx +++ b/canon-docs/src/app/(docs)/components/field/page.mdx @@ -4,6 +4,12 @@ import { Tabs } from '@/components/Tabs'; import { CodeBlock } from '@/components/CodeBlock'; import { FieldPreview } from '@/snippets/field'; import { BaseUI } from '@/components/HeadlessBanners/BaseUI'; +import { + fieldRootPropDefs, + fieldLabelPropDefs, + fieldDescriptionPropDefs, + fieldErrorPropDefs, +} from './props'; # Field @@ -49,113 +55,25 @@ A wrapper around `Input` or `Select` component to add label, description and err Groups all parts of the field. Renders a `
` element. - string | string[] | null | Promise', - responsive: false, - }, - validationMode: { - type: ['onBlur', 'onChange'], - responsive: false, - }, - validationDebounceTime: { - type: 'number', - responsive: false, - }, - className: { - type: 'string', - responsive: false, - }, - style: { - type: 'CSSProperties', - responsive: false, - }, - }} -/> + ### Field.Label An accessible label that is automatically associated with the field control. Renders a `
- - + + -
Stack
+
Flex
Arrange your components vertically
diff --git a/canon-docs/src/components/LayoutComponents/svgs/stack.tsx b/canon-docs/src/components/LayoutComponents/svgs/flex.tsx similarity index 98% rename from canon-docs/src/components/LayoutComponents/svgs/stack.tsx rename to canon-docs/src/components/LayoutComponents/svgs/flex.tsx index c54cba57cf..7bc3466ce8 100644 --- a/canon-docs/src/components/LayoutComponents/svgs/stack.tsx +++ b/canon-docs/src/components/LayoutComponents/svgs/flex.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -export const StackSvg = () => { +export const FlexSvg = () => { return ( >({ }: { data: T; }) => { + if (!data) return null; + return ( - Prop - Type - Responsive + Prop + Type + Default + + Responsive + - {Object.keys(data).map(n => ( - - - {n} - - -
- {Array.isArray(data[n].type) ? ( - data[n].type.map(t => {t}) - ) : ( - {data[n].type} - )} -
- - - {data[n].responsive ? 'Yes' : 'No'} - - - ))} + {Object.keys(data).map(n => { + const enumValues = + data[n].values === 'icon' + ? Object.keys(icons).map(icon => {icon}) + : Array.isArray(data[n].values) && + data[n].values.map(t => {t}); + + return ( + + + {n} + + +
+ {data[n].type === 'string' && string} + {data[n].type === 'number' && number} + {data[n].type === 'boolean' && boolean} + {data[n].type === 'enum' && enumValues} + {data[n].type === 'enum | string' && ( + <> + {enumValues} + string + + )} +
+
+ + {data[n].default ? data[n].default : '-'} + + + {data[n].responsive ? 'Yes' : 'No'} + +
+ ); + })} ); diff --git a/canon-docs/src/components/Sidebar/Sidebar.module.css b/canon-docs/src/components/Sidebar/Sidebar.module.css index 43f1681812..fba98420d0 100644 --- a/canon-docs/src/components/Sidebar/Sidebar.module.css +++ b/canon-docs/src/components/Sidebar/Sidebar.module.css @@ -6,27 +6,39 @@ .sidebar { display: block; position: fixed; - top: 0; - left: 0; + top: 16px; + left: 16px; + border-radius: 8px; width: 300px; - height: 100vh; - color: var(--canon-text-primary); - background-color: var(--canon-bg-elevated); - border-right: 1px solid var(--canon-border); - padding-left: 20px; - padding-right: 20px; + height: calc(100vh - 32px); + box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.025); + color: var(--primary); + background-color: var(--panel); transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out; overflow: hidden; } } +.root { + height: 100%; +} + +.viewport { + overflow: scroll; + height: 100%; +} + +.content { + padding: 0 20px 20px; +} + .logoContainer { padding-left: 6px; padding-top: 32px; } .logo path { - fill: var(--canon-text-primary); + fill: var(--primary); } .menu { @@ -43,10 +55,11 @@ } .sectionTitle { - font-family: var(--docs-font); font-size: var(--canon-font-size-3); font-weight: var(--canon-font-weight-bold); padding: 12px 0; + color: var(--primary); + margin-top: 24px; } .line { @@ -63,23 +76,57 @@ transition: background-color 0.2s ease-in-out; &:hover { - background-color: var(--canon-bg); + background-color: var(--bg); } } .line.active { - background-color: var(--canon-bg); + background-color: var(--bg); +} + +.line.active .lineTitle { + color: var(--primary); } .lineTitle { - font-family: var(--docs-font); font-size: var(--canon-font-size-3); font-weight: var(--canon-font-weight-regular); - color: var(--canon-text-primary); + color: var(--secondary); } .lineStatus { - font-family: var(--docs-font); font-size: var(--canon-font-size-3); - color: var(--canon-text-secondary); + color: var(--secondary); +} + +.scrollbar { + display: flex; + justify-content: center; + background-color: rgba(0, 0, 0, 0.1); + width: 0.25rem; + border-radius: 0.375rem; + margin: 0.5rem; + opacity: 0; + transition: opacity 150ms 300ms; + right: -20px; + + &[data-hovering], + &[data-scrolling] { + opacity: 1; + transition-duration: 75ms; + transition-delay: 0ms; + } + + &::before { + content: ''; + position: absolute; + width: 1.25rem; + height: 100%; + } +} + +.thumb { + width: 100%; + border-radius: inherit; + background-color: rgba(0, 0, 0, 0.2); } diff --git a/canon-docs/src/components/Sidebar/docs.tsx b/canon-docs/src/components/Sidebar/docs.tsx index f207036cfa..da501b151a 100644 --- a/canon-docs/src/components/Sidebar/docs.tsx +++ b/canon-docs/src/components/Sidebar/docs.tsx @@ -2,8 +2,7 @@ import Link from 'next/link'; import { components, overview, layoutComponents, theme } from '@/utils/data'; -import { Box } from '../../../../packages/canon'; -import { motion } from 'framer-motion'; +import { motion } from 'motion/react'; import styles from './Sidebar.module.css'; import { usePathname } from 'next/navigation'; import { Fragment } from 'react'; @@ -53,9 +52,8 @@ export const Docs = () => { {data.map(section => { return ( - -
{section.title}
-
+
{section.title}
+ {section.content.map(item => { const isActive = pathname === `${section.url}/${item.slug}`; diff --git a/canon-docs/src/components/Sidebar/index.tsx b/canon-docs/src/components/Sidebar/index.tsx index 455ab4be9b..ad6df68b97 100644 --- a/canon-docs/src/components/Sidebar/index.tsx +++ b/canon-docs/src/components/Sidebar/index.tsx @@ -2,28 +2,38 @@ import styles from './Sidebar.module.css'; import { Docs } from './docs'; import { Playground } from './playground'; import Link from 'next/link'; +import { ScrollArea } from '@base-ui-components/react/scroll-area'; export const Sidebar = () => { return (
-
- - - - - - -
-
- - -
+ + +
+
+ + + + + + +
+
+ + +
+
+
+ + + +
); }; diff --git a/canon-docs/src/components/Sidebar/playground.tsx b/canon-docs/src/components/Sidebar/playground.tsx index 59502f6314..5773807d74 100644 --- a/canon-docs/src/components/Sidebar/playground.tsx +++ b/canon-docs/src/components/Sidebar/playground.tsx @@ -1,10 +1,8 @@ 'use client'; import { components } from '@/utils/data'; -import { Box } from '../../../../packages/canon/src/components/Box'; -import { Checkbox } from '../../../../packages/canon/src/components/Checkbox'; -import { Text } from '../../../../packages/canon/src/components/Text'; -import { motion } from 'framer-motion'; +import { Checkbox } from '../../../../packages/canon'; +import { motion } from 'motion/react'; import styles from './Sidebar.module.css'; import { usePathname } from 'next/navigation'; import { screenSizes } from '@/utils/data'; @@ -54,28 +52,20 @@ export const Playground = () => { transition={{ duration: 0.2 }} style={{ position: 'absolute' }} > - - - Components - - +
Components
{components.map(({ slug, title }) => (
- {title} +
{title}
handleComponentCheckboxChange(slug)} />
))} - - - Screen sizes - - +
Screen sizes
{screenSizes.map(({ slug, title }) => (
- {title} +
{title}
handleCheckboxChange(slug)} diff --git a/canon-docs/src/components/Snippet/index.tsx b/canon-docs/src/components/Snippet/index.tsx index 2c7c4c5a02..e1af88cb12 100644 --- a/canon-docs/src/components/Snippet/index.tsx +++ b/canon-docs/src/components/Snippet/index.tsx @@ -1,6 +1,5 @@ import { ReactNode } from 'react'; import { CodeBlock } from '../CodeBlock'; -import { Text } from '../../../../packages/canon/src/components/Text'; import { Collapsible } from '@base-ui-components/react/collapsible'; import styles from './styles.module.css'; @@ -31,7 +30,7 @@ export const Snippet = ({ {preview}
- View code + View code
diff --git a/canon-docs/src/components/Snippet/styles.module.css b/canon-docs/src/components/Snippet/styles.module.css index 65bdc62d05..f04b304afa 100644 --- a/canon-docs/src/components/Snippet/styles.module.css +++ b/canon-docs/src/components/Snippet/styles.module.css @@ -6,8 +6,8 @@ .preview { border-radius: 4px; - box-shadow: inset 0 0 0 1px var(--canon-border); - background-color: var(--canon-bg); + box-shadow: inset 0 0 0 1px var(--border); + background-color: var(--bg); transition: all 0.2s ease-in-out; padding: 1px; position: relative; @@ -33,11 +33,12 @@ right: 16px; bottom: 12px; cursor: pointer; + font-size: 14px; } [data-theme='dark'] .previewContent { background-image: radial-gradient( - rgba(255, 255, 255, 0.1) 1px, + rgba(255, 255, 255, 0.14) 1px, transparent 0 ); } diff --git a/canon-docs/src/components/Table/Table.tsx b/canon-docs/src/components/Table/Table.tsx index 19ae69822e..d817ce3b1b 100644 --- a/canon-docs/src/components/Table/Table.tsx +++ b/canon-docs/src/components/Table/Table.tsx @@ -1,19 +1,3 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - import React from 'react'; import styles from './styles.module.css'; @@ -37,9 +21,18 @@ export const HeaderRow = ({ children }: { children: React.ReactNode }) => { return {children}; }; -export const HeaderCell = ({ children }: { children: React.ReactNode }) => { +export const HeaderCell = ({ + children, + style, +}: { + children: React.ReactNode; + style?: React.CSSProperties; +}) => { return ( - + {children} ); @@ -49,6 +42,16 @@ export const Row = ({ children }: { children: React.ReactNode }) => { return {children}; }; -export const Cell = ({ children }: { children: React.ReactNode }) => { - return {children}; +export const Cell = ({ + children, + style, +}: { + children: React.ReactNode; + style?: React.CSSProperties; +}) => { + return ( + + {children} + + ); }; diff --git a/canon-docs/src/components/Table/styles.module.css b/canon-docs/src/components/Table/styles.module.css index 7ac48709eb..3381f39e58 100644 --- a/canon-docs/src/components/Table/styles.module.css +++ b/canon-docs/src/components/Table/styles.module.css @@ -1,21 +1,5 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - .wrapper { - border: 1px solid var(--canon-border); + border: 1px solid var(--border); border-radius: 4px; overflow: hidden; margin-bottom: 1rem; @@ -33,24 +17,24 @@ padding: 12px 16px !important; border: none !important; text-align: left; - background-color: var(--canon-bg-elevated) !important; + background-color: var(--panel) !important; font-size: 16px; transition: background-color 0.2s ease-in-out; & p { - margin: 0; + margin: 0 !important; } } .tableHeaderCell { - border-bottom: 1px solid var(--canon-border) !important; + border-bottom: 1px solid var(--border) !important; font-weight: 500; font-size: 14px; } .tableRow { border: none; - border-bottom: 1px solid var(--canon-border); + border-bottom: 1px solid var(--border); &:last-child { border-bottom: none; } @@ -59,7 +43,7 @@ .tableChip { display: inline-block; font-size: 14px !important; - border: 1px solid var(--canon-border); + border: 1px solid var(--border); border-radius: 6px; padding: 0px 6px; height: 24px; diff --git a/canon-docs/src/components/Tabs/parts.tsx b/canon-docs/src/components/Tabs/parts.tsx index e0ae296136..3d02683cef 100644 --- a/canon-docs/src/components/Tabs/parts.tsx +++ b/canon-docs/src/components/Tabs/parts.tsx @@ -1,8 +1,8 @@ 'use client'; import { Tabs as TabsPrimitive } from '@base-ui-components/react/tabs'; +import { Text } from '../../../../packages/canon'; import styles from './styles.module.css'; -import { Text } from '../../../../packages/canon/src/components/Text'; export const Root = ({ className, @@ -31,12 +31,7 @@ export const Tab = (props: React.ComponentProps) => ( {children} diff --git a/canon-docs/src/components/Tabs/styles.module.css b/canon-docs/src/components/Tabs/styles.module.css index 8d898fd727..82e744b8b2 100644 --- a/canon-docs/src/components/Tabs/styles.module.css +++ b/canon-docs/src/components/Tabs/styles.module.css @@ -5,7 +5,7 @@ .list { display: flex; gap: var(--canon-space-6); - border-bottom: 1px solid var(--canon-border); + border-bottom: 1px solid var(--border); position: relative; margin-bottom: var(--canon-space-6); } @@ -22,6 +22,6 @@ left: var(--active-tab-left); width: var(--active-tab-width); height: 1px; - background-color: var(--canon-text-primary); + background-color: var(--primary); transition: all 0.2s ease-in-out; } diff --git a/canon-docs/src/components/Toolbar/nav.module.css b/canon-docs/src/components/Toolbar/nav.module.css index 90730b1403..95228fa917 100644 --- a/canon-docs/src/components/Toolbar/nav.module.css +++ b/canon-docs/src/components/Toolbar/nav.module.css @@ -12,7 +12,7 @@ .tabsTheme { width: 142px; border-radius: 0.375rem; - background-color: var(--canon-bg); + background-color: var(--bg); transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out; } @@ -26,22 +26,21 @@ .tab { all: unset; height: 60px; - font-family: var(--docs-font); - color: var(--canon-text-secondary); + color: var(--secondary); font-size: var(--canon-font-size-3); font-weight: var(--canon-font-weight-bold); cursor: pointer; transition: color 0.2s ease-in-out; &:hover { - color: var(--canon-text-primary); + color: var(--primary); } &[data-selected] { - color: var(--canon-text-primary); + color: var(--primary); & p { - color: var(--canon-text-primary); + color: var(--primary); } } @@ -53,14 +52,14 @@ position: absolute; inset: 0.25rem 0; border-radius: 0.25rem; - outline: 2px solid var(--canon-bg-elevated); + outline: 2px solid var(--panel); outline-offset: -1px; } } } .tab p { - color: var(--canon-text-secondary) !important; + color: var(--secondary) !important; } .indicator { @@ -72,7 +71,7 @@ width: var(--active-tab-width); height: 1px; border-radius: 0.25rem; - background-color: var(--canon-text-primary); + background-color: var(--primary); transition-property: translate, width, background-color; transition-duration: 200ms; transition-timing-function: ease-in-out; diff --git a/canon-docs/src/components/Toolbar/styles.module.css b/canon-docs/src/components/Toolbar/styles.module.css index 3b0378a03e..ff85129441 100644 --- a/canon-docs/src/components/Toolbar/styles.module.css +++ b/canon-docs/src/components/Toolbar/styles.module.css @@ -1,17 +1,18 @@ .toolbar { position: sticky; - top: 0; + top: 16px; left: 0; right: 0; + border-radius: 8px; z-index: 10; - background-color: var(--canon-bg-elevated); - border-bottom: 1px solid var(--canon-border); + background-color: var(--panel); height: 60px; display: flex; align-items: center; justify-content: space-between; padding: 0 var(--canon-space-6); transition: background-color 0.2s ease-in-out; + box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.025); } .actions { diff --git a/canon-docs/src/components/Toolbar/theme-name.module.css b/canon-docs/src/components/Toolbar/theme-name.module.css index 0ae2675e31..ca06762e23 100644 --- a/canon-docs/src/components/Toolbar/theme-name.module.css +++ b/canon-docs/src/components/Toolbar/theme-name.module.css @@ -17,7 +17,7 @@ color: var(--color-gray-900); cursor: pointer; user-select: none; - background-color: var(--canon-bg); + background-color: var(--bg); transition: background-color 0.2s ease-in-out; &:focus-visible { @@ -43,9 +43,9 @@ box-sizing: border-box; padding-block: 0.25rem; border-radius: 0.375rem; - background-color: var(--canon-bg-elevated); + background-color: var(--panel); color: var(--color-gray-900); - border: 1px solid var(--canon-border); + border: 1px solid var(--border); padding-inline: 0.25rem; transform-origin: var(--transform-origin); transition: transform 150ms, opacity 150ms; @@ -104,7 +104,7 @@ z-index: 0; position: relative; color: var(--color-gray-50); - background-color: var(--canon-bg); + background-color: var(--bg); } &[data-highlighted]::before { diff --git a/canon-docs/src/components/Toolbar/theme-name.tsx b/canon-docs/src/components/Toolbar/theme-name.tsx index 07b734de34..277ecad9df 100644 --- a/canon-docs/src/components/Toolbar/theme-name.tsx +++ b/canon-docs/src/components/Toolbar/theme-name.tsx @@ -6,8 +6,7 @@ import { Icon } from '@backstage/canon'; import { usePlayground } from '@/utils/playground-context'; const themes = [ - { name: 'Backstage Default', value: 'default' }, - { name: 'Backstage Legacy', value: 'legacy' }, + { name: 'Backstage', value: 'default' }, { name: 'Custom theme', value: 'custom' }, ]; @@ -25,7 +24,7 @@ export const ThemeNameSelector = () => { placeholder="Select a theme" /> - + diff --git a/canon-docs/src/components/Toolbar/theme.module.css b/canon-docs/src/components/Toolbar/theme.module.css index 564f5be4ca..37ccb25249 100644 --- a/canon-docs/src/components/Toolbar/theme.module.css +++ b/canon-docs/src/components/Toolbar/theme.module.css @@ -1,14 +1,14 @@ .tabs { border-radius: 0.375rem; width: 100%; - background-color: var(--canon-bg); + background-color: var(--bg); transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out; } .tabsTheme { width: 100px; border-radius: 0.375rem; - background-color: var(--canon-bg); + background-color: var(--bg); transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out; } @@ -29,23 +29,23 @@ outline: 0; background: none; appearance: none; - color: var(--canon-text-secondary); + color: var(--secondary); user-select: none; height: 2rem; flex: 1; cursor: pointer; &[data-selected] { - color: var(--canon-text-primary); + color: var(--primary); & p { - color: var(--canon-text-primary); + color: var(--primary); } } @media (hover: hover) { &:hover { - color: var(--canon-text-primary); + color: var(--primary); } } @@ -57,14 +57,14 @@ position: absolute; inset: 0.25rem 0; border-radius: 0.25rem; - outline: 2px solid var(--canon-bg-elevated); + outline: 2px solid var(--panel); outline-offset: -1px; } } } .tab p { - color: var(--canon-text-secondary) !important; + color: var(--secondary) !important; } .indicator { @@ -76,7 +76,7 @@ width: var(--active-tab-width); height: 1.5rem; border-radius: 0.25rem; - background-color: var(--canon-bg-elevated); + background-color: var(--panel); transition-property: translate, width, background-color; transition-duration: 200ms; transition-timing-function: ease-in-out; diff --git a/canon-docs/src/app/globals.css b/canon-docs/src/css/globals.css similarity index 64% rename from canon-docs/src/app/globals.css rename to canon-docs/src/css/globals.css index 71f7b8be9c..d7e64c3341 100644 --- a/canon-docs/src/app/globals.css +++ b/canon-docs/src/css/globals.css @@ -1,13 +1,33 @@ +:root { + --bg: #f8f8f8; + --panel: #fff; + --primary: #000; + --secondary: #757575; + --font-regular: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, + 'Helvetica Neue', Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', + 'Segoe UI Symbol', 'Noto Color Emoji'; + --font-mono: ui-monospace, 'Menlo', 'Monaco', 'Consolas', 'Liberation Mono', + 'Courier New', monospace; + --font-weight-regular: 400; + --font-weight-bold: 600; + --border: rgba(0, 0, 0, 0.1); +} + +[data-theme='dark'] { + --bg: #000; + --panel: #222222; + --primary: #fff; + --secondary: #9e9e9e; + --border: rgba(255, 255, 255, 0.1); +} + body { display: flex; flex-direction: row; - background-color: var(--canon-bg); - color: var(--canon-text-primary); + background-color: var(--bg); + color: var(--primary); + font-family: var(--font-regular); transition: background-color 0.2s ease-in-out; - - --docs-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, - 'Helvetica Neue', Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', - 'Segoe UI Symbol', 'Noto Color Emoji'; } iframe { @@ -22,7 +42,7 @@ iframe { .shiki, .shiki span { background-color: transparent !important; - font-family: var(--canon-font-monospace); + font-family: var(--font-mono); font-size: 0.875rem; line-height: 1.7; } @@ -41,8 +61,8 @@ iframe { } .ͼ2 .cm-gutters { - background-color: var(--canon-bg); - border-right: 1px solid var(--canon-border); + background-color: var(--bg); + border-right: 1px solid var(--border); transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out; } diff --git a/canon-docs/src/css/mdx.module.css b/canon-docs/src/css/mdx.module.css new file mode 100644 index 0000000000..9fb977214d --- /dev/null +++ b/canon-docs/src/css/mdx.module.css @@ -0,0 +1,32 @@ +.h1 { + font-size: 2.5rem; + margin-top: 4rem; + margin-bottom: 1.5rem; + color: var(--primary); +} + +.h2 { + font-size: 1.5rem; + margin-top: 3rem; + margin-bottom: 1.5rem; + color: var(--primary); +} + +.h3 { + font-size: 1.25rem; + margin-top: 2rem; + margin-bottom: 0.5rem; + color: var(--primary); +} + +.p { + font-size: 1rem; + line-height: 1.5; + margin-top: 0; + margin-bottom: 1rem; + color: var(--secondary); +} + +.p:first-of-type { + margin-bottom: 2rem; +} diff --git a/canon-docs/src/app/page.module.css b/canon-docs/src/css/page.module.css similarity index 88% rename from canon-docs/src/app/page.module.css rename to canon-docs/src/css/page.module.css index b0fbed71c1..3a0bb492d8 100644 --- a/canon-docs/src/app/page.module.css +++ b/canon-docs/src/css/page.module.css @@ -4,11 +4,12 @@ .container { width: 100%; + padding: 0 16px; } @media (min-width: 768px) { .container { - padding-left: 300px; + padding-left: 332px; } } @@ -17,7 +18,7 @@ } .page p { - color: var(--canon-text-primary); + color: var(--primary); font-size: 1rem; line-height: 1.5rem; margin-top: 0; diff --git a/canon-docs/src/mdx-components.tsx b/canon-docs/src/mdx-components.tsx index 85df3315c4..8ef40f3924 100644 --- a/canon-docs/src/mdx-components.tsx +++ b/canon-docs/src/mdx-components.tsx @@ -2,70 +2,28 @@ import React, { ReactNode } from 'react'; import type { MDXComponents } from 'mdx/types'; import Image, { ImageProps } from 'next/image'; import { CodeBlock } from '@/components/CodeBlock'; -import { Box } from '../../packages/canon/src/components/Box'; +import styles from './css/mdx.module.css'; export function useMDXComponents(components: MDXComponents): MDXComponents { return { - // Allows customizing built-in components, e.g. to add styling. h1: ({ children }) => ( - -

- {children as ReactNode} -

-
+

{children as ReactNode}

), h2: ({ children }) => ( - -

- {children as ReactNode} -

-
+

{children as ReactNode}

), h3: ({ children }) => ( -

- {children as ReactNode} -

- ), - p: ({ children }) => ( -

- {children as ReactNode} -

+

{children as ReactNode}

), + p: ({ children }) =>

{children as ReactNode}

, a: ({ children, href }) => ( - + {children as ReactNode} ), + li: ({ children }) => ( +
  • {children as ReactNode}
  • + ), pre: ({ children }) => { const codeContent = React.isValidElement(children) ? (children.props as { children: string }).children @@ -76,12 +34,12 @@ export function useMDXComponents(components: MDXComponents): MDXComponents { code: ({ children }) => ( diff --git a/canon-docs/src/snippets/_snippets.ts b/canon-docs/src/snippets/_snippets.ts index 417ff853b5..00a9c1462d 100644 --- a/canon-docs/src/snippets/_snippets.ts +++ b/canon-docs/src/snippets/_snippets.ts @@ -1,5 +1,36 @@ // Sometimes codes are not formatted correctly in the docs, so we need to use snippets +export const customTheme = `:root { + --canon-font-regular: system-ui; + --canon-font-weight-regular: 400; + --canon-font-weight-bold: 600; + --canon-bg: #f8f8f8; + --canon-bg-surface-1: #fff; + /* ... other CSS variables */ + + /* Add your custom components styles here */ + .canon-Button { + background-color: #000; + color: #fff; + } +} + +[data-theme='dark'] { + --canon-font-regular: system-ui; + --canon-font-weight-regular: 400; + --canon-font-weight-bold: 600; + --canon-bg: #f8f8f8; + --canon-bg-surface-1: #fff; + /* ... other CSS variables */ + + /* Add your custom components styles here */ + .canon-Button { + background-color: #000; + color: #fff; + } +} +`; + export const grid = `import { Grid } from '@backstage/canon'; @@ -7,7 +38,7 @@ export const grid = `import { Grid } from '@backstage/canon'; `; -export const buttonVariants = ` +export const buttonVariants = ` @@ -17,29 +48,35 @@ export const buttonVariants = ` - + `; -export const stackFAQ1 = ` +export const iconButtonVariants = ` + + + +`; + +export const flexFAQ1 = ` Hello World Hello World Hello World `; -export const stackSimple = ` +export const flexSimple = ` Hello World Hello World Hello World -`; +`; -export const stackResponsive = ` +export const flexResponsive = ` Hello World Hello World Hello World -`; +`; -export const stackAlign = ` +export const flexAlign = ` Hello World Hello World Hello World -`; +`; diff --git a/canon-docs/src/snippets/button.tsx b/canon-docs/src/snippets/button.tsx index 59e6bbd486..aa20b3e46a 100644 --- a/canon-docs/src/snippets/button.tsx +++ b/canon-docs/src/snippets/button.tsx @@ -1,59 +1,50 @@ 'use client'; -import { - Inline, - Button, - Stack, - ButtonProps, - Text, -} from '../../../packages/canon'; +import { Button, Flex, ButtonProps, Text } from '../../../packages/canon'; export const ButtonPreview = () => { return ( - + - - + ); }; export const ButtonSizes = () => { return ( - + - + ); }; export const ButtonWithIcons = () => { return ( - + - - + - + ); }; export const ButtonFullWidth = () => { return ( - + - - + - + ); }; @@ -62,20 +53,23 @@ export const ButtonDisabled = () => { }; export const ButtonResponsive = () => { - // TODO: Add responsive button - return null; + return ( + + ); }; export const ButtonPlayground = () => { const variants: string[] = ['primary', 'secondary', 'tertiary']; return ( - + {variants.map(variant => ( - + {variant} {['small', 'medium'].map(size => ( - + - + ))} - + ))} - + ); }; diff --git a/canon-docs/src/snippets/checkbox.tsx b/canon-docs/src/snippets/checkbox.tsx index 88c6de4a99..fe2a5b0219 100644 --- a/canon-docs/src/snippets/checkbox.tsx +++ b/canon-docs/src/snippets/checkbox.tsx @@ -1,6 +1,6 @@ 'use client'; -import { Inline, Checkbox, Stack, Text } from '../../../packages/canon'; +import { Checkbox, Flex, Text } from '../../../packages/canon'; export const CheckboxPreview = () => { return ; @@ -8,25 +8,25 @@ export const CheckboxPreview = () => { export const CheckboxAllVariants = () => { return ( - + - + ); }; export const CheckboxPlayground = () => { return ( - + All variants - + - - + + ); }; diff --git a/canon-docs/src/snippets/container.tsx b/canon-docs/src/snippets/container.tsx index 40ffc69c8c..27c0ba9922 100644 --- a/canon-docs/src/snippets/container.tsx +++ b/canon-docs/src/snippets/container.tsx @@ -4,7 +4,6 @@ import { Box, Container } from '../../../packages/canon'; const DecorativeBox = () => ( { diff --git a/canon-docs/src/snippets/stack.tsx b/canon-docs/src/snippets/flex.tsx similarity index 86% rename from canon-docs/src/snippets/stack.tsx rename to canon-docs/src/snippets/flex.tsx index 4bada6f7ba..8bfab8878e 100644 --- a/canon-docs/src/snippets/stack.tsx +++ b/canon-docs/src/snippets/flex.tsx @@ -1,6 +1,6 @@ 'use client'; -import { Stack } from '../../../packages/canon'; +import { Flex } from '../../../packages/canon'; const DecorativeBox = () => { return ( @@ -18,14 +18,14 @@ const DecorativeBox = () => { ); }; -export const StackPreview = () => { +export const FlexPreview = () => { return (
    - + - +
    ); }; diff --git a/canon-docs/src/snippets/grid.tsx b/canon-docs/src/snippets/grid.tsx index 161747cbf6..87012b7630 100644 --- a/canon-docs/src/snippets/grid.tsx +++ b/canon-docs/src/snippets/grid.tsx @@ -4,7 +4,6 @@ import { Box, Grid } from '../../../packages/canon'; const FakeBox = () => ( { return Look mum, no hands!; @@ -8,36 +8,35 @@ export const HeadingPreview = () => { export const HeadingAllVariants = () => { return ( - + Display Title 1 Title 2 Title 3 Title 4 - + ); }; export const HeadingResponsive = () => { - return null; return ( - - + + Responsive heading - + ); }; export const HeadingPlayground = () => { return ( - + All variants Display Title 1 Title 2 Title 3 Title 4 - + ); }; diff --git a/canon-docs/src/snippets/icon-button.tsx b/canon-docs/src/snippets/icon-button.tsx new file mode 100644 index 0000000000..2079041456 --- /dev/null +++ b/canon-docs/src/snippets/icon-button.tsx @@ -0,0 +1,57 @@ +'use client'; + +import { IconButton, Flex, ButtonProps, Text } from '../../../packages/canon'; + +export const IconButtonPreview = () => { + return ( + + + + + ); +}; + +export const IconButtonSizes = () => { + return ( + + + + + ); +}; + +export const IconButtonDisabled = () => { + return ; +}; + +export const IconButtonResponsive = () => { + return ( + + ); +}; + +export const IconButtonPlayground = () => { + const variants: string[] = ['primary', 'secondary']; + + return ( + + {variants.map(variant => ( + + {variant} + {['small', 'medium'].map(size => ( + + + + ))} + + ))} + + ); +}; diff --git a/canon-docs/src/snippets/inline.tsx b/canon-docs/src/snippets/inline.tsx index 73b619e3af..43fd56c650 100644 --- a/canon-docs/src/snippets/inline.tsx +++ b/canon-docs/src/snippets/inline.tsx @@ -1,6 +1,6 @@ 'use client'; -import { Box, Inline } from '../../../packages/canon'; +import { Box, Flex } from '../../../packages/canon'; const fakeBlockList = [ { width: 45, height: 60 }, @@ -24,7 +24,6 @@ const FakeBox = ({ height?: number; }) => ( { return ( - + {fakeBlockList.map((block, index) => ( ))} - + ); }; diff --git a/canon-docs/src/snippets/input.tsx b/canon-docs/src/snippets/input.tsx index d320f3a24a..69d0b62b7f 100644 --- a/canon-docs/src/snippets/input.tsx +++ b/canon-docs/src/snippets/input.tsx @@ -1,3 +1,5 @@ +'use client'; + import { Input, Grid } from '../../../packages/canon'; export const InputPreview = () => { diff --git a/canon-docs/src/snippets/text.tsx b/canon-docs/src/snippets/text.tsx index 633b3b45d7..4d39cbf6dd 100644 --- a/canon-docs/src/snippets/text.tsx +++ b/canon-docs/src/snippets/text.tsx @@ -1,6 +1,6 @@ 'use client'; -import { Stack, Text } from '../../../packages/canon'; +import { Flex, Text } from '../../../packages/canon'; export const TextPreview = () => { return ( @@ -14,7 +14,7 @@ export const TextPreview = () => { export const TextAllVariants = () => { return ( - + A man looks at a painting in a museum and says, “Brothers and sisters I have none, but that man's father is my father's son.” Who is @@ -35,13 +35,13 @@ export const TextAllVariants = () => { have none, but that man's father is my father's son.” Who is in the painting? - + ); }; export const TextAllWeights = () => { return ( - + A man looks at a painting in a museum and says, “Brothers and sisters I have none, but that man's father is my father's son.” Who is @@ -52,18 +52,19 @@ export const TextAllWeights = () => { have none, but that man's father is my father's son.” Who is in the painting? - + ); }; export const TextResponsive = () => { - // TODO: Add responsive text - return null; + return ( + Responsive text + ); }; export const TextPlayground = () => { return ( - + Subtitle A man looks at a painting in a museum and says, “Brothers and sisters I @@ -88,6 +89,6 @@ export const TextPlayground = () => { have none, but that man's father is my father's son.” Who is in the painting? - + ); }; diff --git a/canon-docs/src/utils/data.ts b/canon-docs/src/utils/data.ts index 1109d6fa0a..6aa487d93a 100644 --- a/canon-docs/src/utils/data.ts +++ b/canon-docs/src/utils/data.ts @@ -55,13 +55,8 @@ export const layoutComponents: Page[] = [ status: 'alpha', }, { - title: 'Inline', - slug: 'inline', - status: 'alpha', - }, - { - title: 'Stack', - slug: 'stack', + title: 'Flex', + slug: 'flex', status: 'alpha', }, ]; @@ -92,6 +87,11 @@ export const components: Page[] = [ slug: 'icon', status: 'alpha', }, + { + title: 'IconButton', + slug: 'icon-button', + status: 'alpha', + }, { title: 'Input', slug: 'input', diff --git a/canon-docs/src/utils/propDefs.ts b/canon-docs/src/utils/propDefs.ts new file mode 100644 index 0000000000..f087d6188f --- /dev/null +++ b/canon-docs/src/utils/propDefs.ts @@ -0,0 +1,205 @@ +import type { Breakpoint } from '@backstage/canon/src/types'; + +const breakpoints = ['initial', 'xs', 'sm', 'md', 'lg', 'xl'] as Breakpoint[]; + +export type PropDef = { + type: 'string' | 'enum' | 'enum | string' | 'number' | 'boolean'; + values?: string | string[]; + default?: string; + required?: boolean; + responsive?: boolean; +}; + +export { breakpoints }; +export type { Breakpoint }; + +export const spacingValues = [ + '0.5', + '1', + '1.5', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '10', + '11', + '12', + '13', + '14', +]; + +export const paddingPropDefs = ( + spacingValues: string[], +): Record => ({ + p: { + type: 'enum | string', + values: spacingValues, + responsive: true, + }, + px: { + type: 'enum | string', + values: spacingValues, + responsive: true, + }, + py: { + type: 'enum | string', + values: spacingValues, + responsive: true, + }, + pt: { + type: 'enum | string', + values: spacingValues, + responsive: true, + }, + pr: { + type: 'enum | string', + values: spacingValues, + responsive: true, + }, + pb: { + type: 'enum | string', + values: spacingValues, + responsive: true, + }, + pl: { + type: 'enum | string', + values: spacingValues, + responsive: true, + }, +}); + +export const marginPropDefs = ( + spacingValues: string[], +): Record => ({ + m: { + type: 'enum | string', + values: spacingValues, + responsive: true, + }, + mx: { + type: 'enum | string', + values: spacingValues, + responsive: true, + }, + my: { + type: 'enum | string', + values: spacingValues, + responsive: true, + }, + mt: { + type: 'enum | string', + values: spacingValues, + responsive: true, + }, + mr: { + type: 'enum | string', + values: spacingValues, + responsive: true, + }, + mb: { + type: 'enum | string', + values: spacingValues, + responsive: true, + }, + ml: { + type: 'enum | string', + values: spacingValues, + responsive: true, + }, +}); + +export const spacingPropDefs = { + ...paddingPropDefs(spacingValues), + ...marginPropDefs(spacingValues), +}; + +export const displayPropDefs: Record = { + display: { + type: 'enum', + values: ['none', 'inline', 'inline-block', 'block'], + default: 'block', + responsive: true, + }, +}; + +export const gapPropDefs: Record = { + gap: { + type: 'enum | string', + values: spacingValues, + responsive: true, + default: '4', + }, +}; + +export const widthPropDefs: Record = { + width: { + type: 'string', + default: '0', + responsive: true, + }, + minWidth: { + type: 'string', + default: '0', + responsive: true, + }, + maxWidth: { + type: 'string', + default: '0', + responsive: true, + }, +}; + +export const heightPropDefs: Record = { + height: { + type: 'string', + default: '0', + responsive: true, + }, + minHeight: { + type: 'string', + default: '0', + responsive: true, + }, + maxHeight: { + type: 'string', + default: '0', + responsive: true, + }, +}; + +export const positionPropDefs: Record = { + position: { + type: 'enum', + values: ['static', 'relative', 'absolute', 'fixed', 'sticky'], + default: 'static', + responsive: true, + }, +}; + +export const classNamePropDefs: Record = { + className: { + type: 'string', + responsive: false, + }, +}; + +export const stylePropDefs: Record = { + style: { + type: 'enum', + values: ['CSSProperties'], + responsive: false, + }, +}; + +export const childrenPropDefs: Record = { + children: { + type: 'enum', + values: ['ReactNode'], + required: true, + responsive: false, + }, +}; diff --git a/canon-docs/yarn.lock b/canon-docs/yarn.lock index 912da3edc2..2320a6a2dd 100644 --- a/canon-docs/yarn.lock +++ b/canon-docs/yarn.lock @@ -132,177 +132,177 @@ __metadata: languageName: node linkType: hard -"@esbuild/aix-ppc64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/aix-ppc64@npm:0.24.2" +"@esbuild/aix-ppc64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/aix-ppc64@npm:0.25.0" conditions: os=aix & cpu=ppc64 languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/android-arm64@npm:0.24.2" +"@esbuild/android-arm64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/android-arm64@npm:0.25.0" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@esbuild/android-arm@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/android-arm@npm:0.24.2" +"@esbuild/android-arm@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/android-arm@npm:0.25.0" conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-x64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/android-x64@npm:0.24.2" +"@esbuild/android-x64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/android-x64@npm:0.25.0" conditions: os=android & cpu=x64 languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/darwin-arm64@npm:0.24.2" +"@esbuild/darwin-arm64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/darwin-arm64@npm:0.25.0" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/darwin-x64@npm:0.24.2" +"@esbuild/darwin-x64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/darwin-x64@npm:0.25.0" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/freebsd-arm64@npm:0.24.2" +"@esbuild/freebsd-arm64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/freebsd-arm64@npm:0.25.0" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/freebsd-x64@npm:0.24.2" +"@esbuild/freebsd-x64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/freebsd-x64@npm:0.25.0" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/linux-arm64@npm:0.24.2" +"@esbuild/linux-arm64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/linux-arm64@npm:0.25.0" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/linux-arm@npm:0.24.2" +"@esbuild/linux-arm@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/linux-arm@npm:0.25.0" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/linux-ia32@npm:0.24.2" +"@esbuild/linux-ia32@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/linux-ia32@npm:0.25.0" conditions: os=linux & cpu=ia32 languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/linux-loong64@npm:0.24.2" +"@esbuild/linux-loong64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/linux-loong64@npm:0.25.0" conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/linux-mips64el@npm:0.24.2" +"@esbuild/linux-mips64el@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/linux-mips64el@npm:0.25.0" conditions: os=linux & cpu=mips64el languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/linux-ppc64@npm:0.24.2" +"@esbuild/linux-ppc64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/linux-ppc64@npm:0.25.0" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/linux-riscv64@npm:0.24.2" +"@esbuild/linux-riscv64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/linux-riscv64@npm:0.25.0" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/linux-s390x@npm:0.24.2" +"@esbuild/linux-s390x@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/linux-s390x@npm:0.25.0" conditions: os=linux & cpu=s390x languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/linux-x64@npm:0.24.2" +"@esbuild/linux-x64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/linux-x64@npm:0.25.0" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-arm64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/netbsd-arm64@npm:0.24.2" +"@esbuild/netbsd-arm64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/netbsd-arm64@npm:0.25.0" conditions: os=netbsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/netbsd-x64@npm:0.24.2" +"@esbuild/netbsd-x64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/netbsd-x64@npm:0.25.0" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-arm64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/openbsd-arm64@npm:0.24.2" +"@esbuild/openbsd-arm64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/openbsd-arm64@npm:0.25.0" conditions: os=openbsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/openbsd-x64@npm:0.24.2" +"@esbuild/openbsd-x64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/openbsd-x64@npm:0.25.0" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/sunos-x64@npm:0.24.2" +"@esbuild/sunos-x64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/sunos-x64@npm:0.25.0" conditions: os=sunos & cpu=x64 languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/win32-arm64@npm:0.24.2" +"@esbuild/win32-arm64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/win32-arm64@npm:0.25.0" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/win32-ia32@npm:0.24.2" +"@esbuild/win32-ia32@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/win32-ia32@npm:0.25.0" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.24.2": - version: 0.24.2 - resolution: "@esbuild/win32-x64@npm:0.24.2" +"@esbuild/win32-x64@npm:0.25.0": + version: 0.25.0 + resolution: "@esbuild/win32-x64@npm:0.25.0" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -501,10 +501,10 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:14.2.23": - version: 14.2.23 - resolution: "@next/env@npm:14.2.23" - checksum: dad74ff7de68992a0753f728a5b926ed6eb0af8a62deece6bbb32ba254b1f7d870e256b61db8d4c40fa811695cfc5e69ba964339f3cb8b40237cf9c28dfe747f +"@next/env@npm:14.2.25": + version: 14.2.25 + resolution: "@next/env@npm:14.2.25" + checksum: c937d4e8b62c7ae9c74bd607888e791b78445e93d523d22d0838e816c3fbeb7b1b62766d110ef235229e4c4ca8587f493e6ec761eb0a2c774dabaee2b58f581b languageName: node linkType: hard @@ -518,8 +518,8 @@ __metadata: linkType: hard "@next/mdx@npm:^15.1.4": - version: 15.1.5 - resolution: "@next/mdx@npm:15.1.5" + version: 15.1.6 + resolution: "@next/mdx@npm:15.1.6" dependencies: source-map: ^0.7.0 peerDependencies: @@ -530,69 +530,69 @@ __metadata: optional: true "@mdx-js/react": optional: true - checksum: f73103abce4ca2e15a6d06b0c6e16988e5651ca09890d6a0017c913b30018dc87d275dc7a8fed30dab338af5e1c3822f1a74af83d6fa6bee02edb936bbd51566 + checksum: 3b46e99934543df94bcb335dddab794db4fcaff09223343e9e00597d3df1e094f16dd619c433fb2fa7fff38c3da57b3118cbc010cdeb9790d0cf01e6c37016e8 languageName: node linkType: hard -"@next/swc-darwin-arm64@npm:14.2.23": - version: 14.2.23 - resolution: "@next/swc-darwin-arm64@npm:14.2.23" +"@next/swc-darwin-arm64@npm:14.2.25": + version: 14.2.25 + resolution: "@next/swc-darwin-arm64@npm:14.2.25" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@next/swc-darwin-x64@npm:14.2.23": - version: 14.2.23 - resolution: "@next/swc-darwin-x64@npm:14.2.23" +"@next/swc-darwin-x64@npm:14.2.25": + version: 14.2.25 + resolution: "@next/swc-darwin-x64@npm:14.2.25" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@next/swc-linux-arm64-gnu@npm:14.2.23": - version: 14.2.23 - resolution: "@next/swc-linux-arm64-gnu@npm:14.2.23" +"@next/swc-linux-arm64-gnu@npm:14.2.25": + version: 14.2.25 + resolution: "@next/swc-linux-arm64-gnu@npm:14.2.25" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-arm64-musl@npm:14.2.23": - version: 14.2.23 - resolution: "@next/swc-linux-arm64-musl@npm:14.2.23" +"@next/swc-linux-arm64-musl@npm:14.2.25": + version: 14.2.25 + resolution: "@next/swc-linux-arm64-musl@npm:14.2.25" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@next/swc-linux-x64-gnu@npm:14.2.23": - version: 14.2.23 - resolution: "@next/swc-linux-x64-gnu@npm:14.2.23" +"@next/swc-linux-x64-gnu@npm:14.2.25": + version: 14.2.25 + resolution: "@next/swc-linux-x64-gnu@npm:14.2.25" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-x64-musl@npm:14.2.23": - version: 14.2.23 - resolution: "@next/swc-linux-x64-musl@npm:14.2.23" +"@next/swc-linux-x64-musl@npm:14.2.25": + version: 14.2.25 + resolution: "@next/swc-linux-x64-musl@npm:14.2.25" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@next/swc-win32-arm64-msvc@npm:14.2.23": - version: 14.2.23 - resolution: "@next/swc-win32-arm64-msvc@npm:14.2.23" +"@next/swc-win32-arm64-msvc@npm:14.2.25": + version: 14.2.25 + resolution: "@next/swc-win32-arm64-msvc@npm:14.2.25" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@next/swc-win32-ia32-msvc@npm:14.2.23": - version: 14.2.23 - resolution: "@next/swc-win32-ia32-msvc@npm:14.2.23" +"@next/swc-win32-ia32-msvc@npm:14.2.25": + version: 14.2.25 + resolution: "@next/swc-win32-ia32-msvc@npm:14.2.25" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@next/swc-win32-x64-msvc@npm:14.2.23": - version: 14.2.23 - resolution: "@next/swc-win32-x64-msvc@npm:14.2.23" +"@next/swc-win32-x64-msvc@npm:14.2.25": + version: 14.2.25 + resolution: "@next/swc-win32-x64-msvc@npm:14.2.25" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -722,23 +722,23 @@ __metadata: languageName: node linkType: hard -"@storybook/components@npm:8.4.7": - version: 8.4.7 - resolution: "@storybook/components@npm:8.4.7" +"@storybook/components@npm:8.6.7": + version: 8.6.7 + resolution: "@storybook/components@npm:8.6.7" peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: e39fb81e8386db4f3f76cbf4f82e50512fed2f65a581951c0b61e00c9834c20cfff7f717e936353275dadfe6a25ffaac5d47151adbe1e3be85e709f8a64f6a15 + checksum: cb20f8baa76deef1af1739d6c1b1a9f57eb22d158fa046d9919a91840e7a00f1b48e96b7ffe7994365b60808f864c963a3476ee98b4c8b63968a3a877068da3a languageName: node linkType: hard -"@storybook/core@npm:8.4.7": - version: 8.4.7 - resolution: "@storybook/core@npm:8.4.7" +"@storybook/core@npm:8.6.7": + version: 8.6.7 + resolution: "@storybook/core@npm:8.6.7" dependencies: - "@storybook/csf": ^0.1.11 + "@storybook/theming": 8.6.7 better-opn: ^3.0.2 browser-assert: ^1.2.1 - esbuild: ^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 + esbuild: ^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 esbuild-register: ^3.5.0 jsdoc-type-pratt-parser: ^4.0.0 process: ^0.11.10 @@ -751,16 +751,7 @@ __metadata: peerDependenciesMeta: prettier: optional: true - checksum: 969cde2203c9c2c744f2a1d2858b2adeb7d57fc75e703f64187fcf0056eb7da48d0507d919718c0866952dda084eb51d79e65a90abec8bb0dcb404b542a6872f - languageName: node - linkType: hard - -"@storybook/csf@npm:^0.1.11": - version: 0.1.13 - resolution: "@storybook/csf@npm:0.1.13" - dependencies: - type-fest: ^2.19.0 - checksum: 78cfd8348e74fdd22bc7d14b443b8ad28b7e797ce147beeab4a1bed6c4e6885287fdaebbcad6efc104819a924121175d461c16e425a4b4f5903cec8f6be6f440 + checksum: b150b7472766fccbbc1dec74cba3c16e009a9f24c13f01198923f553d12e2a2070ee2a35f5514f9af350b79e34577946ea65a4a495fd1fa18a27655f897c013a languageName: node linkType: hard @@ -771,66 +762,66 @@ __metadata: languageName: node linkType: hard -"@storybook/manager-api@npm:8.4.7": - version: 8.4.7 - resolution: "@storybook/manager-api@npm:8.4.7" +"@storybook/manager-api@npm:8.6.7": + version: 8.6.7 + resolution: "@storybook/manager-api@npm:8.6.7" peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: 2b826ec55de7ea0b5b5151dfa896f3e7eddfd36ede61f8a7ad14a37733d5d5645565f863dbde7e2272f1e9b5717f26de7802ae60e297a2647ee2c4c072ed3069 + checksum: 6bb0860c3795945189832613da5866e5159b2adb376478a2b596c113928c64f5962efc325f927a6bcb7a48d7257f42cf6489b0c44397876129626ac68c44aa28 languageName: node linkType: hard -"@storybook/preview-api@npm:8.4.7": - version: 8.4.7 - resolution: "@storybook/preview-api@npm:8.4.7" +"@storybook/preview-api@npm:8.6.7": + version: 8.6.7 + resolution: "@storybook/preview-api@npm:8.6.7" peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: 1c467bb2c16c5998b9bc4c2c013e6786936d5f6a373ad8d8ab1beb626616c3187329fdfc3a709663b4af963c7e5789a1401166c6e2a3a66a12f66e858aa94e91 + checksum: 0d24d62444b7b153bde89d3949ab6539a163e15bc80c5bfcc73b7d49bbb34fb02eb74a99434793b8a6446aeec491e07f006c0f4e404f98486c6d1d614d01defa languageName: node linkType: hard -"@storybook/react-dom-shim@npm:8.4.7": - version: 8.4.7 - resolution: "@storybook/react-dom-shim@npm:8.4.7" +"@storybook/react-dom-shim@npm:8.6.7": + version: 8.6.7 + resolution: "@storybook/react-dom-shim@npm:8.6.7" peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.4.7 - checksum: 4de29cbb990bfb2f310440aa995b024faa93fd1d5c7c942d6d661d590693eb56e0567a141c14faca63e8b24fc2f6b6b44c02af37cd2d5b469c1129b0e78fc79d + storybook: ^8.6.7 + checksum: 51c20259ac4485d9a996266341a4d9898c949049e2a9af9a08bec58c2ace3a40be1a534005c52fc2db2c81bb010dbd36030bb70581b36c05cf4b34d58f140d3a languageName: node linkType: hard "@storybook/react@npm:^8.4.7": - version: 8.4.7 - resolution: "@storybook/react@npm:8.4.7" + version: 8.6.7 + resolution: "@storybook/react@npm:8.6.7" dependencies: - "@storybook/components": 8.4.7 + "@storybook/components": 8.6.7 "@storybook/global": ^5.0.0 - "@storybook/manager-api": 8.4.7 - "@storybook/preview-api": 8.4.7 - "@storybook/react-dom-shim": 8.4.7 - "@storybook/theming": 8.4.7 + "@storybook/manager-api": 8.6.7 + "@storybook/preview-api": 8.6.7 + "@storybook/react-dom-shim": 8.6.7 + "@storybook/theming": 8.6.7 peerDependencies: - "@storybook/test": 8.4.7 + "@storybook/test": 8.6.7 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.4.7 + storybook: ^8.6.7 typescript: ">= 4.2.x" peerDependenciesMeta: "@storybook/test": optional: true typescript: optional: true - checksum: 5ad2137f8f5f0a34cb90e2582fd574aff888c544f0f9907472d930d4fb1f444124aa84188a0b5d661cc6c4c0bf7210b1e616a53b4be3f2df2479165571fa9085 + checksum: c98438ddfd764300e1a805623fab976f9ef94a2d939984d6caf98ce92ed29d8a7307389b98e2df2d1302b302dc549c7c95050464731d9c588347cd154c360834 languageName: node linkType: hard -"@storybook/theming@npm:8.4.7": - version: 8.4.7 - resolution: "@storybook/theming@npm:8.4.7" +"@storybook/theming@npm:8.6.7": + version: 8.6.7 + resolution: "@storybook/theming@npm:8.6.7" peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: 47d29993c33bb29994d227af30e099579b7cf760652ed743020f5d7e5a5974f59a6ebeb1cc8995e6158da9cf768a8d2f559d1d819cc082d0bcdb056d85fdcb29 + checksum: 747a2377df65d5f0962dc8606d06247ad89fb7ecabab0bd9611055d599b5bd0fa15769e4c76e948ae34ae232ba756bf6795ccb3467b1adf35ff961db7350f4de languageName: node linkType: hard @@ -925,11 +916,11 @@ __metadata: linkType: hard "@types/node@npm:^20": - version: 20.17.16 - resolution: "@types/node@npm:20.17.16" + version: 20.17.24 + resolution: "@types/node@npm:20.17.24" dependencies: undici-types: ~6.19.2 - checksum: dd19c04c592b602f20448187b4b6ab0293f22173a8bbe53aa3b559188f078b5261d748a107b84ee0580e2074cda760049b13d6e210f9850039bead01cb666a3f + checksum: 05d3ca5d8741d10368edeff01318e4e615a7654b0c6bd05415f8cd0a2f851ac8e04c2cac319442c20fe372d1bdba9dd1f40dda014e97902516f82058b68ef6c4 languageName: node linkType: hard @@ -940,7 +931,7 @@ __metadata: languageName: node linkType: hard -"@types/react-dom@npm:^18": +"@types/react-dom@npm:^18.0.0": version: 18.3.5 resolution: "@types/react-dom@npm:18.3.5" peerDependencies: @@ -949,7 +940,7 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:^18": +"@types/react@npm:^18.0.0": version: 18.3.18 resolution: "@types/react@npm:18.3.18" dependencies: @@ -1109,8 +1100,8 @@ __metadata: linkType: hard "@uiw/codemirror-themes@npm:^4.23.7": - version: 4.23.7 - resolution: "@uiw/codemirror-themes@npm:4.23.7" + version: 4.23.10 + resolution: "@uiw/codemirror-themes@npm:4.23.10" dependencies: "@codemirror/language": ^6.0.0 "@codemirror/state": ^6.0.0 @@ -1119,7 +1110,7 @@ __metadata: "@codemirror/language": ">=6.0.0" "@codemirror/state": ">=6.0.0" "@codemirror/view": ">=6.0.0" - checksum: 8c2a9a7ee8df2de3f09ad1f18979c4b407f7dd03e1f6ddfe47837b9e4769b566a70259ec8c398473b6b6db79cdb8809d4acc2f2ed7851743e13ff95308f52e33 + checksum: 3b05d6e019616a474aa9ea38fd88a38952f81d21ee9574ad065e350c0de25c940679f2c6edddc0e6ead1da9e4c2893eadfa958e5b9373fb69ed5af561bc417f6 languageName: node linkType: hard @@ -1503,16 +1494,17 @@ __metadata: "@storybook/react": ^8.4.7 "@types/mdx": ^2.0.13 "@types/node": ^20 - "@types/react": ^18 - "@types/react-dom": ^18 + "@types/react": ^18.0.0 + "@types/react-dom": ^18.0.0 "@uiw/codemirror-themes": ^4.23.7 "@uiw/react-codemirror": ^4.23.7 eslint: ^8 eslint-config-next: 14.2.23 lightningcss: ^1.28.2 - next: 14.2.23 - react: ^18 - react-dom: ^18 + motion: ^12.4.1 + next: 14.2.25 + react: ^18.0.2 + react-dom: ^18.0.2 react-frame-component: ^5.2.7 shiki: ^1.26.1 storybook: ^8.4.7 @@ -1762,12 +1754,10 @@ __metadata: languageName: node linkType: hard -"detect-libc@npm:^1.0.3": - version: 1.0.3 - resolution: "detect-libc@npm:1.0.3" - bin: - detect-libc: ./bin/detect-libc.js - checksum: daaaed925ffa7889bd91d56e9624e6c8033911bb60f3a50a74a87500680652969dbaab9526d1e200a4c94acf80fc862a22131841145a0a8482d60a99c24f4a3e +"detect-libc@npm:^2.0.3": + version: 2.0.3 + resolution: "detect-libc@npm:2.0.3" + checksum: 2ba6a939ae55f189aea996ac67afceb650413c7a34726ee92c40fb0deb2400d57ef94631a8a3f052055eea7efb0f99a9b5e6ce923415daa3e68221f963cfc27d languageName: node linkType: hard @@ -2020,35 +2010,35 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0": - version: 0.24.2 - resolution: "esbuild@npm:0.24.2" +"esbuild@npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0": + version: 0.25.0 + resolution: "esbuild@npm:0.25.0" dependencies: - "@esbuild/aix-ppc64": 0.24.2 - "@esbuild/android-arm": 0.24.2 - "@esbuild/android-arm64": 0.24.2 - "@esbuild/android-x64": 0.24.2 - "@esbuild/darwin-arm64": 0.24.2 - "@esbuild/darwin-x64": 0.24.2 - "@esbuild/freebsd-arm64": 0.24.2 - "@esbuild/freebsd-x64": 0.24.2 - "@esbuild/linux-arm": 0.24.2 - "@esbuild/linux-arm64": 0.24.2 - "@esbuild/linux-ia32": 0.24.2 - "@esbuild/linux-loong64": 0.24.2 - "@esbuild/linux-mips64el": 0.24.2 - "@esbuild/linux-ppc64": 0.24.2 - "@esbuild/linux-riscv64": 0.24.2 - "@esbuild/linux-s390x": 0.24.2 - "@esbuild/linux-x64": 0.24.2 - "@esbuild/netbsd-arm64": 0.24.2 - "@esbuild/netbsd-x64": 0.24.2 - "@esbuild/openbsd-arm64": 0.24.2 - "@esbuild/openbsd-x64": 0.24.2 - "@esbuild/sunos-x64": 0.24.2 - "@esbuild/win32-arm64": 0.24.2 - "@esbuild/win32-ia32": 0.24.2 - "@esbuild/win32-x64": 0.24.2 + "@esbuild/aix-ppc64": 0.25.0 + "@esbuild/android-arm": 0.25.0 + "@esbuild/android-arm64": 0.25.0 + "@esbuild/android-x64": 0.25.0 + "@esbuild/darwin-arm64": 0.25.0 + "@esbuild/darwin-x64": 0.25.0 + "@esbuild/freebsd-arm64": 0.25.0 + "@esbuild/freebsd-x64": 0.25.0 + "@esbuild/linux-arm": 0.25.0 + "@esbuild/linux-arm64": 0.25.0 + "@esbuild/linux-ia32": 0.25.0 + "@esbuild/linux-loong64": 0.25.0 + "@esbuild/linux-mips64el": 0.25.0 + "@esbuild/linux-ppc64": 0.25.0 + "@esbuild/linux-riscv64": 0.25.0 + "@esbuild/linux-s390x": 0.25.0 + "@esbuild/linux-x64": 0.25.0 + "@esbuild/netbsd-arm64": 0.25.0 + "@esbuild/netbsd-x64": 0.25.0 + "@esbuild/openbsd-arm64": 0.25.0 + "@esbuild/openbsd-x64": 0.25.0 + "@esbuild/sunos-x64": 0.25.0 + "@esbuild/win32-arm64": 0.25.0 + "@esbuild/win32-ia32": 0.25.0 + "@esbuild/win32-x64": 0.25.0 dependenciesMeta: "@esbuild/aix-ppc64": optional: true @@ -2102,7 +2092,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: e2303f8331887e31330b5a972fb9640ad93dfc5af76cb2156faa9eaa32bac5c403244096cbdafc45622829913e63664dfd88410987e3468df4354492f908a094 + checksum: 4d1e0cb7c059a373ea3edb20ca5efcea29efada03e4ea82b2b8ab1f2f062e4791e9744213308775d26e07a0225a7d8250da93da5c8e07ef61bb93d58caab8cf9 languageName: node linkType: hard @@ -2584,6 +2574,28 @@ __metadata: languageName: node linkType: hard +"framer-motion@npm:^12.5.0": + version: 12.5.0 + resolution: "framer-motion@npm:12.5.0" + dependencies: + motion-dom: ^12.5.0 + motion-utils: ^12.5.0 + tslib: ^2.4.0 + peerDependencies: + "@emotion/is-prop-valid": "*" + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + "@emotion/is-prop-valid": + optional: true + react: + optional: true + react-dom: + optional: true + checksum: aebf78b75000c783d12a8ae2534e62f0a5781490c0cfdf39c051b6dee2c7e11a5b8dd1077cc659e55dc24f582aa5d620c28999f3c17e17d38e49b14c6298d86b + languageName: node + linkType: hard + "fs.realpath@npm:^1.0.0": version: 1.0.0 resolution: "fs.realpath@npm:1.0.0" @@ -3410,91 +3422,91 @@ __metadata: languageName: node linkType: hard -"lightningcss-darwin-arm64@npm:1.29.1": - version: 1.29.1 - resolution: "lightningcss-darwin-arm64@npm:1.29.1" +"lightningcss-darwin-arm64@npm:1.29.3": + version: 1.29.3 + resolution: "lightningcss-darwin-arm64@npm:1.29.3" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"lightningcss-darwin-x64@npm:1.29.1": - version: 1.29.1 - resolution: "lightningcss-darwin-x64@npm:1.29.1" +"lightningcss-darwin-x64@npm:1.29.3": + version: 1.29.3 + resolution: "lightningcss-darwin-x64@npm:1.29.3" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"lightningcss-freebsd-x64@npm:1.29.1": - version: 1.29.1 - resolution: "lightningcss-freebsd-x64@npm:1.29.1" +"lightningcss-freebsd-x64@npm:1.29.3": + version: 1.29.3 + resolution: "lightningcss-freebsd-x64@npm:1.29.3" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"lightningcss-linux-arm-gnueabihf@npm:1.29.1": - version: 1.29.1 - resolution: "lightningcss-linux-arm-gnueabihf@npm:1.29.1" +"lightningcss-linux-arm-gnueabihf@npm:1.29.3": + version: 1.29.3 + resolution: "lightningcss-linux-arm-gnueabihf@npm:1.29.3" conditions: os=linux & cpu=arm languageName: node linkType: hard -"lightningcss-linux-arm64-gnu@npm:1.29.1": - version: 1.29.1 - resolution: "lightningcss-linux-arm64-gnu@npm:1.29.1" +"lightningcss-linux-arm64-gnu@npm:1.29.3": + version: 1.29.3 + resolution: "lightningcss-linux-arm64-gnu@npm:1.29.3" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"lightningcss-linux-arm64-musl@npm:1.29.1": - version: 1.29.1 - resolution: "lightningcss-linux-arm64-musl@npm:1.29.1" +"lightningcss-linux-arm64-musl@npm:1.29.3": + version: 1.29.3 + resolution: "lightningcss-linux-arm64-musl@npm:1.29.3" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"lightningcss-linux-x64-gnu@npm:1.29.1": - version: 1.29.1 - resolution: "lightningcss-linux-x64-gnu@npm:1.29.1" +"lightningcss-linux-x64-gnu@npm:1.29.3": + version: 1.29.3 + resolution: "lightningcss-linux-x64-gnu@npm:1.29.3" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"lightningcss-linux-x64-musl@npm:1.29.1": - version: 1.29.1 - resolution: "lightningcss-linux-x64-musl@npm:1.29.1" +"lightningcss-linux-x64-musl@npm:1.29.3": + version: 1.29.3 + resolution: "lightningcss-linux-x64-musl@npm:1.29.3" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"lightningcss-win32-arm64-msvc@npm:1.29.1": - version: 1.29.1 - resolution: "lightningcss-win32-arm64-msvc@npm:1.29.1" +"lightningcss-win32-arm64-msvc@npm:1.29.3": + version: 1.29.3 + resolution: "lightningcss-win32-arm64-msvc@npm:1.29.3" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"lightningcss-win32-x64-msvc@npm:1.29.1": - version: 1.29.1 - resolution: "lightningcss-win32-x64-msvc@npm:1.29.1" +"lightningcss-win32-x64-msvc@npm:1.29.3": + version: 1.29.3 + resolution: "lightningcss-win32-x64-msvc@npm:1.29.3" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "lightningcss@npm:^1.28.2": - version: 1.29.1 - resolution: "lightningcss@npm:1.29.1" + version: 1.29.3 + resolution: "lightningcss@npm:1.29.3" dependencies: - detect-libc: ^1.0.3 - lightningcss-darwin-arm64: 1.29.1 - lightningcss-darwin-x64: 1.29.1 - lightningcss-freebsd-x64: 1.29.1 - lightningcss-linux-arm-gnueabihf: 1.29.1 - lightningcss-linux-arm64-gnu: 1.29.1 - lightningcss-linux-arm64-musl: 1.29.1 - lightningcss-linux-x64-gnu: 1.29.1 - lightningcss-linux-x64-musl: 1.29.1 - lightningcss-win32-arm64-msvc: 1.29.1 - lightningcss-win32-x64-msvc: 1.29.1 + detect-libc: ^2.0.3 + lightningcss-darwin-arm64: 1.29.3 + lightningcss-darwin-x64: 1.29.3 + lightningcss-freebsd-x64: 1.29.3 + lightningcss-linux-arm-gnueabihf: 1.29.3 + lightningcss-linux-arm64-gnu: 1.29.3 + lightningcss-linux-arm64-musl: 1.29.3 + lightningcss-linux-x64-gnu: 1.29.3 + lightningcss-linux-x64-musl: 1.29.3 + lightningcss-win32-arm64-msvc: 1.29.3 + lightningcss-win32-x64-msvc: 1.29.3 dependenciesMeta: lightningcss-darwin-arm64: optional: true @@ -3516,7 +3528,7 @@ __metadata: optional: true lightningcss-win32-x64-msvc: optional: true - checksum: d1c4dba66dfe7f6a76532bdb84c35742bee61149550e5eb5b0e84e282f21aecd335f917ca9619bb7ca95fc1eb3092dc7e22f2c16b01e9a0ee472b76452343cce + checksum: 80cad5e1eb1c5eaae22ca6f17b127d65b5c93e859da124d57a90e256d7cb7802afa8dc7a6e1ec1e6aa208d0b23c8b9ec07078e69e61b10748bffdc8cadebed7e languageName: node linkType: hard @@ -4104,6 +4116,43 @@ __metadata: languageName: node linkType: hard +"motion-dom@npm:^12.5.0": + version: 12.5.0 + resolution: "motion-dom@npm:12.5.0" + dependencies: + motion-utils: ^12.5.0 + checksum: abe92c72fb09eba9a6071fb77aa2020d1489df31c2291f5e3ff15def091d8b2bacb8a60854c5617f40f99e70178c0407519ca846a57e48051c4f49808e0f5927 + languageName: node + linkType: hard + +"motion-utils@npm:^12.5.0": + version: 12.5.0 + resolution: "motion-utils@npm:12.5.0" + checksum: 347169ab97d8b3720b363afad6c9f4e8999490d1d95c70aaa8f83333be1b8b4e11c5f25564a9809fb091160fad2184403222e5b383be1bba004243c8b47497fe + languageName: node + linkType: hard + +"motion@npm:^12.4.1": + version: 12.5.0 + resolution: "motion@npm:12.5.0" + dependencies: + framer-motion: ^12.5.0 + tslib: ^2.4.0 + peerDependencies: + "@emotion/is-prop-valid": "*" + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + "@emotion/is-prop-valid": + optional: true + react: + optional: true + react-dom: + optional: true + checksum: a32231ea53a3f3b659630a86b40b5cd61daaa4428db06746c7aa06124c6c27ba2772a6482d652d1b4c71d2d9f01e30602eb700655f32fd1c0ccba74b1695fd8c + languageName: node + linkType: hard + "ms@npm:^2.1.1, ms@npm:^2.1.3": version: 2.1.3 resolution: "ms@npm:2.1.3" @@ -4127,20 +4176,20 @@ __metadata: languageName: node linkType: hard -"next@npm:14.2.23": - version: 14.2.23 - resolution: "next@npm:14.2.23" +"next@npm:14.2.25": + version: 14.2.25 + resolution: "next@npm:14.2.25" dependencies: - "@next/env": 14.2.23 - "@next/swc-darwin-arm64": 14.2.23 - "@next/swc-darwin-x64": 14.2.23 - "@next/swc-linux-arm64-gnu": 14.2.23 - "@next/swc-linux-arm64-musl": 14.2.23 - "@next/swc-linux-x64-gnu": 14.2.23 - "@next/swc-linux-x64-musl": 14.2.23 - "@next/swc-win32-arm64-msvc": 14.2.23 - "@next/swc-win32-ia32-msvc": 14.2.23 - "@next/swc-win32-x64-msvc": 14.2.23 + "@next/env": 14.2.25 + "@next/swc-darwin-arm64": 14.2.25 + "@next/swc-darwin-x64": 14.2.25 + "@next/swc-linux-arm64-gnu": 14.2.25 + "@next/swc-linux-arm64-musl": 14.2.25 + "@next/swc-linux-x64-gnu": 14.2.25 + "@next/swc-linux-x64-musl": 14.2.25 + "@next/swc-win32-arm64-msvc": 14.2.25 + "@next/swc-win32-ia32-msvc": 14.2.25 + "@next/swc-win32-x64-msvc": 14.2.25 "@swc/helpers": 0.5.5 busboy: 1.6.0 caniuse-lite: ^1.0.30001579 @@ -4181,7 +4230,7 @@ __metadata: optional: true bin: next: dist/bin/next - checksum: 4f9f744439fb860ba7c64ae1c61bc361bdd36e41d56760c52eabb404f4143c854b78ba9a79b7aefc322d93edbbd66d966cbdaf86772a88a8bf2e6b289987f14f + checksum: ca47d0f1d41351adaf75a37c8e8ce39dd76ebc62b054266ef84b5fc1ea41241ad5f16ab7a1ca47b6613b2c3e4c6f48b179f8cd3b0f087912ec7164c4e72981f0 languageName: node linkType: hard @@ -4480,7 +4529,7 @@ __metadata: languageName: node linkType: hard -"react-dom@npm:^18": +"react-dom@npm:^18.0.2": version: 18.3.1 resolution: "react-dom@npm:18.3.1" dependencies: @@ -4510,7 +4559,7 @@ __metadata: languageName: node linkType: hard -"react@npm:^18": +"react@npm:^18.0.2": version: 18.3.1 resolution: "react@npm:18.3.1" dependencies: @@ -5003,10 +5052,10 @@ __metadata: linkType: hard "storybook@npm:^8.4.7": - version: 8.4.7 - resolution: "storybook@npm:8.4.7" + version: 8.6.7 + resolution: "storybook@npm:8.6.7" dependencies: - "@storybook/core": 8.4.7 + "@storybook/core": 8.6.7 peerDependencies: prettier: ^2 || ^3 peerDependenciesMeta: @@ -5016,7 +5065,7 @@ __metadata: getstorybook: ./bin/index.cjs sb: ./bin/index.cjs storybook: ./bin/index.cjs - checksum: 6cd44f8d51b68f2c2363d5e996bc8bf1e47a5acc2050da351d0fb49acd3d99ed093eef1b148145a1af9c08ead8592a87ee569c4456941a37dc374f9f21ea45c3 + checksum: fe21ce4d9cd17069a5b409ed518603f97ec6ec421b7f41cff3e43b409820fcbc2c8dbcb3aed99dd7d0a99a0c6138c7576ddf72f78186b6f86085d503b3c8b32f languageName: node linkType: hard @@ -5307,13 +5356,6 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^2.19.0": - version: 2.19.0 - resolution: "type-fest@npm:2.19.0" - checksum: a4ef07ece297c9fba78fc1bd6d85dff4472fe043ede98bd4710d2615d15776902b595abf62bd78339ed6278f021235fb28a96361f8be86ed754f778973a0d278 - languageName: node - linkType: hard - "typed-array-buffer@npm:^1.0.3": version: 1.0.3 resolution: "typed-array-buffer@npm:1.0.3" @@ -5368,22 +5410,22 @@ __metadata: linkType: hard "typescript@npm:^5": - version: 5.7.3 - resolution: "typescript@npm:5.7.3" + version: 5.8.2 + resolution: "typescript@npm:5.8.2" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 6c38b1e989918e576f0307e6ee013522ea480dfce5f3ca85c9b2d8adb1edeffd37f4f30cd68de0c38a44563d12ba922bdb7e36aa2dac9c51de5d561e6e9a2e9c + checksum: 7f9e3d7ac15da6df713e439e785e51facd65d6450d5f51fab3e8d2f2e3f4eb317080d895480b8e305450cdbcb37e17383e8bf521e7395f8b556e2f2a4730ed86 languageName: node linkType: hard "typescript@patch:typescript@^5#~builtin": - version: 5.7.3 - resolution: "typescript@patch:typescript@npm%3A5.7.3#~builtin::version=5.7.3&hash=5adc0c" + version: 5.8.2 + resolution: "typescript@patch:typescript@npm%3A5.8.2#~builtin::version=5.8.2&hash=5adc0c" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 633cd749d6cd7bc842c6b6245847173bba99742a60776fae3c0fbcc0d1733cd51a733995e5f4dadd8afb0e64e57d3c7dbbeae953a072ee303940eca69e22f311 + checksum: a58d19ff9811c1764a299dd83ca20ed8020f0ab642906dafc880121b710751227201531fdc99878158205c356ac79679b0b61ac5b42eda0e28bfb180947a258d languageName: node linkType: hard diff --git a/contrib/catalog/ImmediateEntityProvider.ts b/contrib/catalog/ImmediateEntityProvider.ts index 33ae6697f6..b5580b775a 100644 --- a/contrib/catalog/ImmediateEntityProvider.ts +++ b/contrib/catalog/ImmediateEntityProvider.ts @@ -61,12 +61,12 @@ export class ImmediateEntityProvider implements EntityProvider { this.entityValidator = entitySchemaValidator(); } - /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.getProviderName} */ + /** {@inheritdoc @backstage/plugin-catalog-node#EntityProvider.getProviderName} */ getProviderName() { return `ImmediateEntityProvider`; } - /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.connect} */ + /** {@inheritdoc @backstage/plugin-catalog-node#EntityProvider.connect} */ async connect(connection: EntityProviderConnection) { this.connection = connection; } diff --git a/contrib/catalog/LoadTestingEntityProvider.ts b/contrib/catalog/LoadTestingEntityProvider.ts index 598099fce9..573d8a5fe0 100644 --- a/contrib/catalog/LoadTestingEntityProvider.ts +++ b/contrib/catalog/LoadTestingEntityProvider.ts @@ -6,7 +6,7 @@ import { import { EntityProvider, EntityProviderConnection, -} from '@backstage/plugin-catalog-backend'; +} from '@backstage/plugin-catalog-node'; import { Logger } from 'winston'; /** @@ -41,12 +41,12 @@ import { Logger } from 'winston'; export class LoadTestingEntityProvider implements EntityProvider { constructor(private readonly options: LoadTestingEntityProviderOptions) {} - /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.getProviderName} */ + /** {@inheritdoc @backstage/plugin-catalog-node#EntityProvider.getProviderName} */ getProviderName() { return `LoadTestingEntityProvider`; } - /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.connect} */ + /** {@inheritdoc @backstage/plugin-catalog-node#EntityProvider.connect} */ async connect(connection: EntityProviderConnection) { const delayStartup = this.options.delayStartup ?? 10_000; const logger = this.options.logger.child({ diff --git a/docs/architecture-decisions/index.md b/docs/architecture-decisions/index.md index 3432264453..b4ba84da0e 100644 --- a/docs/architecture-decisions/index.md +++ b/docs/architecture-decisions/index.md @@ -27,7 +27,7 @@ Records should be stored under the `architecture-decisions` directory. - Address and integrate feedback from the community - Eventually, assign a number - Add the path of the ADR to the microsite sidebar in - [`sidebars.js`](https://github.com/backstage/backstage/blob/master/microsite/sidebars.js) + [`sidebars.ts`](https://github.com/backstage/backstage/blob/master/microsite/sidebars.ts) - Add the path of the ADR to the [`mkdocs.yml`](https://github.com/backstage/backstage/blob/master/mkdocs.yml) - Merge the pull request diff --git a/docs/auth/atlassian/provider.md b/docs/auth/atlassian/provider.md index a1009b586e..ffee3454a9 100644 --- a/docs/auth/atlassian/provider.md +++ b/docs/auth/atlassian/provider.md @@ -51,6 +51,8 @@ auth: additionalScopes: - 'read:jira-user' - 'read:jira-work' + ## uncomment to set lifespan of user session + # sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code signIn: resolvers: # See https://backstage.io/docs/auth/atlassian/provider#resolvers for more resolvers @@ -67,6 +69,10 @@ The Atlassian provider is a structure with the following configuration keys: **NOTE:** The scopes `offline_access`, `read:jira-work`, and `read:jira-user` are provided by default. +### Optional + +- `sessionDuration`: Lifespan of the user session. + ### Resolvers This provider includes several resolvers out of the box that you can use: diff --git a/docs/auth/auth0/provider.md b/docs/auth/auth0/provider.md index 2873a2cace..44a5bb0e43 100644 --- a/docs/auth/auth0/provider.md +++ b/docs/auth/auth0/provider.md @@ -44,6 +44,8 @@ auth: audience: ${AUTH_AUTH0_AUDIENCE} connection: ${AUTH_AUTH0_CONNECTION} connectionScope: ${AUTH_AUTH0_CONNECTION_SCOPE} + ## uncomment to set lifespan of user session + # sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code session: secret: ${AUTH_SESSION_SECRET} ``` @@ -66,6 +68,7 @@ Auth0 requires a session, so you need to give the session a secret key. - `audience`: The intended recipients of the token. - `connection`: Social identity provider name. To check the available social connections, please visit [Auth0 Social Connections](https://marketplace.auth0.com/features/social-connections). - `connectionScope`: Additional scopes in the interactive token request. It should always be used in combination with the `connection` parameter. +- `sessionDuration`: Lifespan of the user session. ### Resolvers diff --git a/docs/auth/aws-alb/provider.md b/docs/auth/aws-alb/provider.md index 5380877f86..5f289170d2 100644 --- a/docs/auth/aws-alb/provider.md +++ b/docs/auth/aws-alb/provider.md @@ -23,6 +23,8 @@ auth: signer: 'arn:aws:elasticloadbalancing:us-east-2:123456789012:loadbalancer/app/my-load-balancer/1234567890123456' # this is the region where your ALB instance resides region: 'us-west-2' + ## uncomment to set lifespan of user session + # sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code signIn: resolvers: # See https://backstage.io/docs/auth/aws-alb/provider#resolvers for more resolvers @@ -31,6 +33,10 @@ auth: Ensure that you have set the signer correctly. It is also recommended that you restrict your target groups' security policy to only accept connections from that ALB. +### Optional + +- `sessionDuration`: Lifespan of the user session. + ### Resolvers This provider includes several resolvers out of the box that you can use: diff --git a/docs/auth/bitbucket/provider.md b/docs/auth/bitbucket/provider.md index e58ad622fc..f8a1fb2ab2 100644 --- a/docs/auth/bitbucket/provider.md +++ b/docs/auth/bitbucket/provider.md @@ -37,6 +37,8 @@ auth: development: clientId: ${AUTH_BITBUCKET_CLIENT_ID} clientSecret: ${AUTH_BITBUCKET_CLIENT_SECRET} + ## uncomment to set lifespan of user session + # sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code signIn: resolvers: # See https://backstage.io/docs/auth/bitbucket/provider#resolvers for more resolvers @@ -49,26 +51,30 @@ The Bitbucket provider is a structure with two configuration keys: `b59241722e3c3b4816e2` - `clientSecret`: The Secret tied to the generated Key. +### Optional + +- `sessionDuration`: Lifespan of the user session. + ### Resolvers This provider includes several resolvers out of the box that you can use: -- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found it will throw a `NotFoundError`. -- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`. -- `userIdMatchingUserEntityAnnotation`: Matches the `userId` from the auth provider with the User entity that has a matching `bitbucket.org/user-id` annotation. If no match is found it will throw a `NotFoundError`. -- `usernameMatchingUserEntityAnnotation`: Matches the `username` from the auth provider with the User entity that has a matching `bitbucket.org/username` annotation. If no match is found it will throw a `NotFoundError`. +- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found, it will throw a `NotFoundError`. +- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found, it will throw a `NotFoundError`. +- `userIdMatchingUserEntityAnnotation`: Matches the `userId` from the auth provider with the User entity that has a matching `bitbucket.org/user-id` annotation. If no match is found, it will throw a `NotFoundError`. +- `usernameMatchingUserEntityAnnotation`: Matches the `username` from the auth provider with the User entity that has a matching `bitbucket.org/username` annotation. If no match is found, it will throw a `NotFoundError`. :::note Note -The resolvers will be tried in order, but will only be skipped if they throw a `NotFoundError`. +The resolvers will be tried in order but will only be skipped if they throw a `NotFoundError`. ::: -If these resolvers do not fit your needs you can build a custom resolver, this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation. +If these resolvers do not fit your needs, you can build a custom resolver; this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation. ## Backend Installation -To add the provider to the backend we will first need to install the package by running this command: +To add the provider to the backend, we will first need to install the package by running this command: ```bash title="from your Backstage root directory" yarn --cwd packages/backend add @backstage/plugin-auth-backend-module-bitbucket-provider diff --git a/docs/auth/bitbucketServer/provider.md b/docs/auth/bitbucketServer/provider.md index c41457d09c..0da600d3fd 100644 --- a/docs/auth/bitbucketServer/provider.md +++ b/docs/auth/bitbucketServer/provider.md @@ -34,6 +34,8 @@ auth: host: bitbucket.example.org clientId: ${AUTH_BITBUCKET_SERVER_CLIENT_ID} clientSecret: ${AUTH_BITBUCKET_SERVER_CLIENT_SECRET} + ## uncomment to set lifespan of user session + # sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code ``` The Bitbucket Server provider is a structure with two configuration keys: @@ -41,24 +43,28 @@ The Bitbucket Server provider is a structure with two configuration keys: - `clientId`: The client ID that was generated by Bitbucket, e.g. `b0f868455c15dcdff5c5fb5d173ae684`. - `clientSecret`: The client secret tied to the generated client ID. +### Optional + +- `sessionDuration`: Lifespan of the user session. + ### Resolvers This provider includes several resolvers out of the box that you can use: -- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found it will throw a `NotFoundError`. -- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`. +- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found, it will throw a `NotFoundError`. +- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found, it will throw a `NotFoundError`. :::note Note -The resolvers will be tried in order, but will only be skipped if they throw a `NotFoundError`. +The resolvers will be tried in order but will only be skipped if they throw a `NotFoundError`. ::: -If these resolvers do not fit your needs you can build a custom resolver, this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation. +If these resolvers do not fit your needs, you can build a custom resolver; this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation. ## Backend Installation -To add the provider to the backend we will first need to install the package by running this command: +To add the provider to the backend, we will first need to install the package by running this command: ```bash title="from your Backstage root directory" yarn --cwd packages/backend add @backstage/plugin-auth-backend-module-bitbucket-server-provider @@ -87,4 +93,4 @@ To add the provider to the frontend, add the `bitbucketServerAuthApiRef` referen ### ScmAuth -For backstage to be able to use the oauth token of the logged in user to access the Bitbucket Server API, you need to add it to list of ScmAuth providers as shown in [Custom ScmAuthApi Implementation](../index.md#custom-scmauthapi-implementation) using the `ScmAuth.forBitbucketServer` method. +For Backstage to be able to use the OAuth token of the logged-in user to access the Bitbucket Server API, you need to add it to the list of ScmAuth providers as shown in [Custom ScmAuthApi Implementation](../index.md#custom-scmauthapi-implementation) using the `ScmAuth.forBitbucketServer` method. diff --git a/docs/auth/cloudflare/provider.md b/docs/auth/cloudflare/provider.md index 224a64f056..e8d72dc3ba 100644 --- a/docs/auth/cloudflare/provider.md +++ b/docs/auth/cloudflare/provider.md @@ -38,6 +38,8 @@ auth: # You can customize the authorization cookie name, by default # CF_Authorization is used authorizationCookieName: + ## uncomment to set lifespan of user session + # sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code # This picks what sign in resolver(s) you want to use. signIn: resolvers: @@ -47,24 +49,28 @@ auth: This config section must be in place for the provider to load at all. +### Optional + +- `sessionDuration`: Lifespan of the user session. + ### Resolvers This provider includes several resolvers out of the box that you can use: -- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found it will throw a `NotFoundError`. -- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`. +- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found, it will throw a `NotFoundError`. +- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found, it will throw a `NotFoundError`. :::note Note -The resolvers will be tried in order, but will only be skipped if they throw a `NotFoundError`. +The resolvers will be tried in order but will only be skipped if they throw a `NotFoundError`. ::: -If these resolvers do not fit your needs you can build a custom resolver, this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation. +If these resolvers do not fit your needs, you can build a custom resolver; this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation. ## Backend Installation -To add the provider to the backend we will first need to install the package by running this command: +To add the provider to the backend, we will first need to install the package by running this command: ```bash title="from your Backstage root directory" yarn --cwd packages/backend add @backstage/plugin-auth-backend-module-cloudflare-access-provider @@ -83,6 +89,6 @@ backend.add( ## Adding the provider to the Backstage frontend -See [Sign-In with Proxy Providers](../index.md#sign-in-with-proxy-providers) for pointers on how to set up the sign-in page, and to also make it work smoothly for local development. You'll use `cfaccess` as the provider name. +See [Sign-In with Proxy Providers](../index.md#sign-in-with-proxy-providers) for pointers on how to set up the sign-in page and also make it work smoothly for local development. You'll use `cfaccess` as the provider name. -If you [provide a custom sign in resolver](https://backstage.io/docs/auth/identity-resolver#building-custom-resolvers), you can skip the `signIn` block entirely. +If you [provide a custom sign-in resolver](https://backstage.io/docs/auth/identity-resolver#building-custom-resolvers), you can skip the `signIn` block entirely. diff --git a/docs/auth/github/provider.md b/docs/auth/github/provider.md index 3b61815017..fa44ae9405 100644 --- a/docs/auth/github/provider.md +++ b/docs/auth/github/provider.md @@ -10,7 +10,7 @@ provider that can authenticate users using GitHub or GitHub Enterprise OAuth. ## Create an OAuth App on GitHub -To add GitHub authentication, you must create either a GitHub App, or an OAuth +To add GitHub authentication, you must create either a GitHub App or an OAuth App from the GitHub [developer settings](https://github.com/settings/developers). The `Homepage URL` should point to Backstage's frontend, while the `Authorization callback URL` @@ -49,6 +49,8 @@ auth: clientSecret: ${AUTH_GITHUB_CLIENT_SECRET} ## uncomment if using GitHub Enterprise # enterpriseInstanceUrl: ${AUTH_GITHUB_ENTERPRISE_INSTANCE_URL} + ## uncomment to set lifespan of user session + # sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code signIn: resolvers: # See https://backstage.io/docs/auth/github/provider#resolvers for more resolvers @@ -57,15 +59,16 @@ auth: The GitHub provider is a structure with these configuration keys: -- `clientId`: The client ID that you generated on GitHub, e.g. +- `clientId`: The client ID that you generated on GitHub, e.g., `b59241722e3c3b4816e2` - `clientSecret`: The client secret tied to the generated client ID. - `enterpriseInstanceUrl` (optional): The base URL for a GitHub Enterprise - instance, e.g. `https://ghe..com`. Only needed for GitHub Enterprise. + instance, e.g., `https://ghe..com`. Only needed for GitHub Enterprise. - `callbackUrl` (optional): The callback URL that GitHub will use when - initiating an OAuth flow, e.g. + initiating an OAuth flow, e.g., `https://your-intermediate-service.com/handler`. Only needed if Backstage is - not the immediate receiver (e.g. one OAuth app for many backstage instances). + not the immediate receiver (e.g., one OAuth app for many backstage instances). +- `sessionDuration` (optional): Lifespan of the user session. - `signIn`: The configuration for the sign-in process, including the **resolvers** that should be used to match the user from the auth provider with the user entity in the Backstage catalog (typically a single resolver is sufficient). @@ -74,17 +77,17 @@ The GitHub provider is a structure with these configuration keys: This provider includes several resolvers out of the box that you can use: -- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found it will throw a `NotFoundError`. -- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`. -- `usernameMatchingUserEntityName`: Matches the username from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`. +- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found, it will throw a `NotFoundError`. +- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found, it will throw a `NotFoundError`. +- `usernameMatchingUserEntityName`: Matches the username from the auth provider with the User entity that has a matching `name`. If no match is found, it will throw a `NotFoundError`. :::note Note -The resolvers will be tried in order, but will only be skipped if they throw a `NotFoundError`. +The resolvers will be tried in order but will only be skipped if they throw a `NotFoundError`. ::: -If these resolvers do not fit your needs you can build a custom resolver, this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation. +If these resolvers do not fit your needs, you can build a custom resolver; this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation. ## Backend Installation diff --git a/docs/auth/gitlab/provider.md b/docs/auth/gitlab/provider.md index 65d1909f41..a76c03d10f 100644 --- a/docs/auth/gitlab/provider.md +++ b/docs/auth/gitlab/provider.md @@ -45,6 +45,8 @@ auth: # audience: https://gitlab.company.com ## uncomment if using a custom redirect URI # callbackUrl: https://${BASE_URL}/api/auth/gitlab/handler/frame + ## uncomment to set lifespan of user session + # sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code signIn: resolvers: # See https://backstage.io/docs/auth/gitlab/provider#resolvers for more resolvers @@ -61,26 +63,27 @@ The GitLab provider is a structure with three configuration keys: - `callbackUrl` (optional): The URL matching the Redirect URI registered when creating your GitLab OAuth App, e.g. `https://$backstage.acme.corp/api/auth/gitlab/handler/frame` Note: Due to a peculiarity with GitLab OAuth, ensure there is no trailing `/` after 'frame' in the URL. +- `sessionDuration` (optional): Lifespan of the user session. ### Resolvers This provider includes several resolvers out of the box that you can use: -- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found it will throw a `NotFoundError`. -- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`. -- `usernameMatchingUserEntityName`: Matches the username from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`. +- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found, it will throw a `NotFoundError`. +- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found, it will throw a `NotFoundError`. +- `usernameMatchingUserEntityName`: Matches the username from the auth provider with the User entity that has a matching `name`. If no match is found, it will throw a `NotFoundError`. :::note Note -The resolvers will be tried in order, but will only be skipped if they throw a `NotFoundError`. +The resolvers will be tried in order but will only be skipped if they throw a `NotFoundError`. ::: -If these resolvers do not fit your needs you can build a custom resolver, this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation. +If these resolvers do not fit your needs, you can build a custom resolver; this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation. ## Backend Installation -To add the provider to the backend we will first need to install the package by running this command: +To add the provider to the backend, we will first need to install the package by running this command: ```bash title="from your Backstage root directory" yarn --cwd packages/backend add @backstage/plugin-auth-backend-module-gitlab-provider diff --git a/docs/auth/google/provider.md b/docs/auth/google/provider.md index e03985d432..9a550d5ee0 100644 --- a/docs/auth/google/provider.md +++ b/docs/auth/google/provider.md @@ -42,6 +42,8 @@ auth: development: clientId: ${AUTH_GOOGLE_CLIENT_ID} clientSecret: ${AUTH_GOOGLE_CLIENT_SECRET} + ## uncomment to set lifespan of user session + # sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code signIn: resolvers: # See https://backstage.io/docs/auth/google/provider#resolvers for more resolvers @@ -54,6 +56,10 @@ The Google provider is a structure with two configuration keys: `10023341500512-beui241gjwwkrdkr2eh7dprewj2pp1q.apps.googleusercontent.com` - `clientSecret`: The client secret tied to the generated client ID. +### Optional + +- `sessionDuration`: Lifespan of the user session. + ### Resolvers This provider includes several resolvers out of the box that you can use: diff --git a/docs/auth/guest/provider.md b/docs/auth/guest/provider.md index b541178571..5072aabe50 100644 --- a/docs/auth/guest/provider.md +++ b/docs/auth/guest/provider.md @@ -63,3 +63,20 @@ auth: # highlight-add-next-line guest: {} ``` + +The above is all you need to get working with the guest provider. However, you can also add additional configuration if you need to such as the following: + +```yaml title="app-config.local.yaml" +auth: + providers: + guest: + userEntityRef: user:default/john-smith + ownershipEntityRefs: [group:default/smith-family] + dangerouslyAllowOutsideDevelopment: false +``` + +The `userEntityRef` is used as the entity reference for the guest user and the `ownershipEntityRefs` is a list of entity references to use for ownership of the guest user, if the user is not found in the catalog. + +The `dangerouslyAllowOutsideDevelopment` flag is used to allow users to sign in with the guest provider outside of their development environments, e.g. in production. + +You can find this information by looking at the config file [here](https://github.com/backstage/backstage/blob/master/plugins/auth-backend-module-guest-provider/config.d.ts). diff --git a/docs/auth/identity-resolver--old.md b/docs/auth/identity-resolver--old.md index c1659f46d8..f6310ace64 100644 --- a/docs/auth/identity-resolver--old.md +++ b/docs/auth/identity-resolver--old.md @@ -140,7 +140,7 @@ export default async function createPlugin( const { profile: { email }, } = info; - // Profiles are not always guaranteed to to have an email address. + // Profiles are not always guaranteed to have an email address. // You can also find more provider-specific information in `info.result`. // It typically contains a `fullProfile` object as well as ID and/or access // tokens that you can use for additional lookups. diff --git a/docs/auth/identity-resolver.md b/docs/auth/identity-resolver.md index 293300f429..cce8f08b7a 100644 --- a/docs/auth/identity-resolver.md +++ b/docs/auth/identity-resolver.md @@ -256,7 +256,7 @@ an example: async signInResolver(info, ctx) { const { profile: { email } } = info; - // Profiles are not always guaranteed to to have an email address. + // Profiles are not always guaranteed to have an email address. // You can also find more provider-specific information in `info.result`. // It typically contains a `fullProfile` object as well as ID and/or access // tokens that you can use for additional lookups. @@ -298,10 +298,9 @@ of lower-level calls: ```ts // File: packages/backend/src/plugins/auth.ts -import { getDefaultOwnershipEntityRefs } from '@backstage/plugin-auth-backend'; // ... -async signInResolver({ profile: { email} }, ctx) { +async signInResolver({ profile: { email } }, ctx) { if (!email) { throw new Error('User profile contained no email'); } @@ -323,19 +322,19 @@ async signInResolver({ profile: { email} }, ctx) { // // You might also replace it if you for example want to filter out certain groups. // - // Note that `getDefaultOwnershipEntityRefs` only includes groups to which the - // user has a direct MEMBER_OF relationship. It's perfectly fine to include - // groups that the user is transitively part of in the claims array, but the - // catalog doesn't currently provide a direct way of accessing this list of - // groups. - const ownershipRefs = getDefaultOwnershipEntityRefs(entity); + // Note that `ctx.resolveOwnershipEntityRefs(...)` by default only includes groups + // to which the user has a direct MEMBER_OF relationship. + // It's perfectly fine to include groups that the user is transitively part of + // in the claims array, but the catalog doesn't currently provide a direct + // way of accessing this list of groups. + const { ownershipEntityRefs } = await ctx.resolveOwnershipEntityRefs(entity); // The last step is to issue the token, where we might provide more options in the // future. return ctx.issueToken({ claims: { sub: stringifyEntityRef(entity), - ent: ownershipRefs, + ent: ownershipEntityRefs, }, }); } diff --git a/docs/auth/microsoft/provider.md b/docs/auth/microsoft/provider.md index 74416f853e..39eed92cba 100644 --- a/docs/auth/microsoft/provider.md +++ b/docs/auth/microsoft/provider.md @@ -84,6 +84,7 @@ The Microsoft provider is a structure with three mandatory configuration keys: For more details, see [Home Realm Discovery](https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/home-realm-discovery-policy) - `additionalScopes` (optional): List of scopes for the App Registration, to be requested in addition to the required ones. - `skipUserProfile` (optional): If true, skips loading the user profile even if the `User.Read` scope is present. This is a performance optimization during login and can be used with resolvers that only needs the email address in `spec.profile.email` obtained when the `email` OAuth2 scope is present. +- `sessionDuration` (optional): Lifespan of the user session. ### Resolvers diff --git a/docs/auth/oidc.md b/docs/auth/oidc.md index 6d2a937320..838ac51f1f 100644 --- a/docs/auth/oidc.md +++ b/docs/auth/oidc.md @@ -263,6 +263,7 @@ check the App Registration you created: basically the same thing. - `prompt`: Recommended to use `auto` so the browser will request login to the IDP if the user has no active session. +- `sessionDuration` (optional): Lifespan of the user session. Note that for the time being, any change in this yaml file requires a restart of the app, also you need to have the `session.secret` part to use OIDC (some other providers might @@ -274,13 +275,15 @@ The last step is to add the provider to the `SignInPage` so users can sign in wi new provider, please follow the [Sign In Configuration][3] docs, here's where you import and use the API reference we defined earlier. -## Note +:::note Note These steps apply to most if not all the providers, including custom providers, the main difference between different providers will be the contents of the API factory, the code in the Auth Provider Factory, the resolver, and the different variables each provider needs in the YAML config or env variables. +::: + [1]: https://backstage.io/docs/auth/identity-resolver [2]: https://backstage.io/docs/auth/microsoft/provider#create-an-app-registration-on-azure [3]: https://backstage.io/docs/auth/#sign-in-configuration diff --git a/docs/auth/okta/provider.md b/docs/auth/okta/provider.md index abc6231839..1e88aa4cf6 100644 --- a/docs/auth/okta/provider.md +++ b/docs/auth/okta/provider.md @@ -45,6 +45,8 @@ auth: audience: ${AUTH_OKTA_DOMAIN} authServerId: ${AUTH_OKTA_AUTH_SERVER_ID} # Optional idp: ${AUTH_OKTA_IDP} # Optional + ## uncomment to set lifespan of user session + # sessionDuration: { hours: 24 } # Optional: supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code # https://developer.okta.com/docs/reference/api/oidc/#scope-dependent-claims-not-always-returned additionalScopes: ${AUTH_OKTA_ADDITIONAL_SCOPES} # Optional signIn: @@ -62,6 +64,7 @@ The values referenced are found on the Application page on your Okta site. `https://company.okta.com` - `authServerId`: The authorization server ID for the Application - `idp`: The identity provider for the application, e.g. `0oaulob4BFVa4zQvt0g3` +- `sessionDuration`: Lifespan of the user session. `additionalScopes` is an optional value, a string of space separated scopes, that will be combined with the default `scope` value of `openid profile email offline_access` to adjust the `scope` sent to Okta during OAuth. This will have an impact on [the dependent claims returned](https://developer.okta.com/docs/reference/api/oidc/#scope-dependent-claims-not-always-returned). For example, setting the `additionalScopes` value to `groups` will result in the claim returning a list of the groups that the user is a member of that also match the ID token group filter of the client app. diff --git a/docs/auth/onelogin/provider.md b/docs/auth/onelogin/provider.md index edceb1de62..d3f57f0615 100644 --- a/docs/auth/onelogin/provider.md +++ b/docs/auth/onelogin/provider.md @@ -38,6 +38,8 @@ auth: clientId: ${AUTH_ONELOGIN_CLIENT_ID} clientSecret: ${AUTH_ONELOGIN_CLIENT_SECRET} issuer: https://.onelogin.com/oidc/2 + ## uncomment to set lifespan of user session + # sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code signIn: resolvers: # See https://backstage.io/docs/auth/onelogin/provider#resolvers for more resolvers @@ -51,6 +53,10 @@ found on the SSO tab** for the OneLogin Application: - `clientSecret`: The client secret - `issuer`: The issuer URL +### Optional + +- `sessionDuration`: Lifespan of the user session. + ### Resolvers This provider includes several resolvers out of the box that you can use: diff --git a/docs/auth/vmware-cloud/provider.md b/docs/auth/vmware-cloud/provider.md index d654331178..3f747f494e 100644 --- a/docs/auth/vmware-cloud/provider.md +++ b/docs/auth/vmware-cloud/provider.md @@ -47,6 +47,8 @@ auth: development: clientId: ${APP_ID} organizationId: ${ORG_ID} + ## uncomment to set lifespan of user session + # sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code signIn: resolvers: # See https://backstage.io/docs/auth/vmware-cloud/provider#resolvers for more resolvers @@ -68,6 +70,10 @@ key for signing session cookies set by Backstage. ::: +### Optional + +- `sessionDuration`: Lifespan of the user session. + ### Resolvers This provider includes several resolvers out of the box that you can use: diff --git a/docs/backend-system/building-plugins-and-modules/02-testing.md b/docs/backend-system/building-plugins-and-modules/02-testing.md index 1ec100cff3..439fed597a 100644 --- a/docs/backend-system/building-plugins-and-modules/02-testing.md +++ b/docs/backend-system/building-plugins-and-modules/02-testing.md @@ -190,7 +190,7 @@ describe('MyDatabaseClass', () => { // "physical" databases to test against is much costlier than creating the // "logical" databases within them that the individual tests use. const databases = TestDatabases.create({ - ids: ['POSTGRES_16', 'POSTGRES_12', 'SQLITE_3', 'MYSQL_8'], + ids: ['POSTGRES_17', 'POSTGRES_13', 'SQLITE_3', 'MYSQL_8'], }); // Just an example of how to conveniently bundle up the setup code @@ -236,8 +236,8 @@ your CI environment is able to supply databases natively, the `TestDatabases` support custom connection strings through the use of environment variables that it'll take into account when present. +- `BACKSTAGE_TEST_DATABASE_POSTGRES17_CONNECTION_STRING` - `BACKSTAGE_TEST_DATABASE_POSTGRES13_CONNECTION_STRING` -- `BACKSTAGE_TEST_DATABASE_POSTGRES9_CONNECTION_STRING` - `BACKSTAGE_TEST_DATABASE_MYSQL8_CONNECTION_STRING` ## Testing Service Factories diff --git a/docs/backend-system/core-services/auditor.md b/docs/backend-system/core-services/auditor.md index d4cbf70325..43e789a70f 100644 --- a/docs/backend-system/core-services/auditor.md +++ b/docs/backend-system/core-services/auditor.md @@ -7,7 +7,7 @@ description: Documentation for the Auditor service ## Overview -This document describes the Auditor Service, a software service designed to record and report on security-relevant events within an application. This service utilizes the `winston` library for logging and provides a flexible way to capture and format audit events. +This document describes the Auditor Service, a core service designed to record and report on security-relevant events within an application. By default, this service utilizes the `rootLogger` core service for logging. ## Key Features @@ -16,15 +16,13 @@ This document describes the Auditor Service, a software service designed to reco - Supports detailed metadata for each event. - Offers success/failure reporting for events. - Integrates with authentication and plugin services for enhanced context. -- Uses `winston` for flexible log formatting and transport. - Provides a service factory for easy integration with Backstage plugins. -- Supports configurable log transports (console, file). ## How it Works -The Auditor Service defines a core class, `Auditor`, which implements the `AuditorService` interface. This class uses `winston` to log audit events with varying levels of severity and associated metadata. It also integrates with authentication and plugin services to capture actor details and plugin context. +The Auditor Service defines a class, `Auditor`, which implements the `AuditorService` interface. This class uses a `logFn` to log audit events with varying levels of severity and associated metadata. It also integrates with authentication and plugin services to capture actor details and plugin context. -The `auditorServiceFactory` creates an `Auditor` instance for the root context and provides a factory function for creating child loggers for individual plugins. This allows each plugin to have its own logger with inherited and additional metadata. +The `auditorServiceFactory` wraps the `rootLogger` core service and provides a factory function for creating child loggers for individual plugins. This allows each plugin to have its own logger with inherited and additional metadata. ## Usage Guidance @@ -78,10 +76,78 @@ In this example, an audit event is created for each request to `/my-endpoint`. T ## Naming Conventions -When defining `eventId` and `subEventId` for your audit events, follow these guidelines: +When defining audit events, follow these guidelines to ensure consistency and clarity: -- Use kebab-case (e.g., `user-login`, `file-download`, `fetch`, `entity-create`, `entity-update`). -- The `eventId` represents a logical group of similar events or operations. For example, "fetch" could be used as an `eventId` encompassing various fetch methods like `by-id` or `by-location`. -- Use `subEventId` to further categorize events within a logical group. For example, if the `eventId` is "fetch", the `subEventId` could be "by-id" or "by-location" to specify the method used for fetching. -- Avoid redundant prefixes related to the plugin ID, as that context is already provided. -- Choose names that clearly and concisely describe the event being audited. +- **Use kebab-case:** Event IDs should be in kebab-case (e.g., `user-session`, `file-download`, `entity-fetch`). +- **`eventId` for Logical Grouping:** The `eventId` represents a broad category or logical group of related operations. For example, `entity-fetch` would group all entity retrieval events. `location-mutate` would group all actions that mutate a location. +- **`meta.queryType` (or related field) for Specific Actions within a Group:** Use a `meta` field (like `queryType`, `actionType` or similar) to specify the particular action or query that occurred within the broader `eventId` group. + - For instance, with `eventId: entity-fetch`, use `meta: { queryType: 'by-id' }` to represent fetching an entity by its ID. Other examples could be: + - `meta: { queryType: 'all' }` for fetching all entities. + - `meta: { queryType: 'by-query' }` for fetching entities by a query. + - `meta: { actionType: 'delete' }` for `eventId: entity-mutate` when an entity was deleted. + - `meta: { actionType: 'create' }` for `eventId: location-mutate` when a location was added. + - Use `meta` fields to add more context to the event being tracked. +- **Avoid Redundant Prefixes:** Do not include redundant prefixes related to the plugin ID in your event names. The plugin context is already provided separately. +- **Clear and Concise:** Choose names that clearly and concisely describe the event being audited. + +## Common Meta Keys and Values + +The following table details common keys found within the `meta` object of audit events and their formats: + +| Key | Description | Format | Example(s) | +| ------------- | ------------------------------------------------------------------------------ | ------------------------------------- | ------------------------------------------------------------------------- | +| `queryType` | Specifies the type of query performed when fetching data. | A kebab-case string | `all`, `by-id`, `by-name`, `by-query`, `by-refs`, `ancestry`, `by-entity` | +| `actionType` | Specifies the type of action performed when modifying data. | A kebab-case string | `create`, `delete`, `refresh` | +| `entityRef` | The full reference of an entity, including kind, namespace, and name. | `[kind]:[namespace]/[name]` | `component:default/my-component`, `group:my-org/team-a` | +| `locationRef` | A specific reference to a location being operated on. | Any string representing the location. | `url:https://example.com/catalog-info.yaml`, `custom:default/my-location` | +| `uid` | The unique identifier of a location or other object involved in the operation. | Any valid unique ID string | `9a4e740b-e557-427f-b9f2-0d4f092b1c1e` | + +By following these conventions, you create a more structured and informative audit trail that is easier to search, filter, and understand. This allows you to better group and understand the events being logged. + +## Audit Event Examples + +To illustrate how these naming conventions and the meta field are used in practice, the following examples demonstrate typical audit events for common operations. + +**Typical Read Operation Example:** + +For an operation that fetches all entities, a typical audit event would look like this: + +```json +{ + "eventId": "entity-fetch", + "meta": { + "queryType": "all" + } + ... +} +``` + +**Typical Write Operation Example:** + +For an operation that deletes an entity, a typical audit event would look like this: + +```json +{ + "eventId": "entity-mutate", + "meta": { + "actionType": "delete", + "uid": "some-entity-uid", + "entityRef": "component:default/petstore" + }, + "severityLevel": "medium" + ... +} +``` + +## Practical Examples for Auditor Implementation + +To clarify how to utilize the Auditor feature effectively, we recommend exploring the Catalog Backend. It offers two valuable resources: + +- **Code Implementation Example (createRouter.ts):** + - The [`createRouter.ts`](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/src/service/createRouter.ts) file within the Catalog Backend showcases a practical integration of the `AuditorService` within a Backstage backend plugin. + - Specifically, the lines that demonstrate the creation of an audit event. This includes setting critical parameters such as `eventId` and `severityLevel`, as well as incorporating relevant metadata like `queryType` and `entityRef`. +- **Documentation Example (README.md):** + - The "Audit Events" section of the Catalog Backend's [`README.md`](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/README.md#audit-events) provides a well-structured example of documenting emitted audit events. + - It illustrates how to detail various `eventId` values and their corresponding `meta` fields (e.g., `queryType`, `actionType`) for different plugin operations. + +These examples provide both a code-level demonstration and a documentation guideline for effectively utilizing the `AuditorService` to manage audit events within your Backstage plugins. diff --git a/docs/backend-system/core-services/permissionsRegistry.md b/docs/backend-system/core-services/permissionsRegistry.md index 4b0b87b894..79d8274986 100644 --- a/docs/backend-system/core-services/permissionsRegistry.md +++ b/docs/backend-system/core-services/permissionsRegistry.md @@ -1,5 +1,5 @@ --- -id: permissions +id: permissions-registry title: Permissions Registry Service sidebar_label: Permissions Registry description: Documentation for the Permissions Registry service diff --git a/docs/conf/writing.md b/docs/conf/writing.md index 85a719e1d0..36a6f330e0 100644 --- a/docs/conf/writing.md +++ b/docs/conf/writing.md @@ -239,7 +239,8 @@ privateKey: | -----END RSA PRIVATE KEY----- ``` -> [!WARNING] -> Sensitive information, such as private keys, should not be hard coded. +:::warning +Sensitive information, such as private keys, should not be hard coded. +::: We recommend that this entire file should be a secret and stored as such in a secure storage solution like Vault, to ensure they are neither exposed nor misused. This example key part only shows the format on how to use the yaml | syntax to make sure that the key is valid. diff --git a/docs/contribute/project-structure.md b/docs/contribute/project-structure.md index 32a692e700..984cfe98d6 100644 --- a/docs/contribute/project-structure.md +++ b/docs/contribute/project-structure.md @@ -39,7 +39,7 @@ the code. - [`docs/`](https://github.com/backstage/backstage/tree/master/docs) - This is where we keep all of our documentation Markdown files. These end up on https://backstage.io/docs. Just keep in mind that changes to the - [`sidebars.js`](https://github.com/backstage/backstage/blob/master/microsite/sidebars.js) + [`sidebars.ts`](https://github.com/backstage/backstage/blob/master/microsite/sidebars.ts) file may be needed as sections are added/removed. - [`.editorconfig`](https://github.com/backstage/backstage/tree/master/.editorconfig) - diff --git a/docs/deployment/docker.md b/docs/deployment/docker.md index 546d027b86..8f83acfc51 100644 --- a/docs/deployment/docker.md +++ b/docs/deployment/docker.md @@ -221,9 +221,6 @@ USER node WORKDIR /app COPY --from=packages --chown=node:node /app . -COPY --from=packages --chown=node:node /app/.yarn ./.yarn -COPY --from=packages --chown=node:node /app/.yarnrc.yml ./ -COPY --from=packages --chown=node:node /app/backstage.json ./ RUN --mount=type=cache,target=/home/node/.cache/yarn,sharing=locked,uid=1000,gid=1000 \ yarn install --immutable diff --git a/docs/faq/product.md b/docs/faq/product.md index edbb1ffb4d..f09b5696b8 100644 --- a/docs/faq/product.md +++ b/docs/faq/product.md @@ -1,6 +1,6 @@ --- id: product -title: Product FAQ +title: Non-technical FAQ description: Questions related to product and design. --- diff --git a/docs/features/kubernetes/configuration.md b/docs/features/kubernetes/configuration.md index 1a921103b1..c323d5118a 100644 --- a/docs/features/kubernetes/configuration.md +++ b/docs/features/kubernetes/configuration.md @@ -80,11 +80,13 @@ The default value is `false`. #### Internationalization -To customize or translate the **Delete Pod** text, use the following approach: +To customize or translate text in some of the components, use the following approach: ```js import { createTranslationMessages } from '@backstage/core-plugin-api/alpha'; import { kubernetesReactTranslationRef } from '@backstage/plugin-kubernetes-react/alpha'; +import { kubernetesTranslationRef } from '@backstage/plugin-kubernetes/alpha'; +import { kubernetesClusterTranslationRef } from '@backstage/plugin-kubernetes-cluster/alpha'; const app = createApp({ __experimentalTranslations: { @@ -94,7 +96,21 @@ const app = createApp({ messages: { "podDrawer.buttons.delete": 'Restart Pod' } - }) + }), + createTranslationMessages({ + ref: kubernetesTranslationRef, + messages: { + 'kubernetesContentPage.permissionAlert.title': 'Insufficient permissions', + 'kubernetesContentPage.permissionAlert.message': 'You do not have permissions to view Kubernetes objects.', + }, + }), + createTranslationMessages({ + ref: kubernetesClusterTranslationRef, + messages: { + 'kubernetesClusterContentPage.permissionAlert.title': 'Insufficient permissions', + 'kubernetesClusterContentPage.permissionAlert.message': 'You do not have permissions to view Kubernetes objects.', + }, + }), ] }, ... diff --git a/docs/features/kubernetes/installation.md b/docs/features/kubernetes/installation.md index aca4c19ac1..a99bd0b429 100644 --- a/docs/features/kubernetes/installation.md +++ b/docs/features/kubernetes/installation.md @@ -7,20 +7,17 @@ description: Installing Kubernetes plugin into Backstage The Kubernetes feature is a plugin to Backstage, and it is exposed as a tab when viewing entities in the software catalog. -If you haven't setup Backstage already, read the -[Getting Started](../../getting-started/index.md) guide. +If you haven't set up Backstage already, read the [Getting Started](../../getting-started/index.md) guide. ## Adding the Kubernetes frontend plugin -The first step is to add the Kubernetes frontend plugin to your Backstage -application. +The first step is to add the Kubernetes frontend plugin to your Backstage application. ```bash title="From your Backstage root directory" yarn --cwd packages/app add @backstage/plugin-kubernetes ``` -Once the package has been installed, you need to import the plugin in your app -by adding the "Kubernetes" tab to the respective catalog pages. +Once the package has been installed, you need to import the plugin in your app by adding the "Kubernetes" tab to the respective catalog pages. ```tsx title="packages/app/src/components/catalog/EntityPage.tsx" /* highlight-add-next-line */ @@ -40,73 +37,17 @@ const serviceEntityPage = ( ); ``` -**Notes:** +:::note Note -- The optional `refreshIntervalMs` property on the `EntityKubernetesContent` defines the interval in which the content automatically refreshes, if not set this will default to 10 seconds. +The optional `refreshIntervalMs` property on the `EntityKubernetesContent` defines the interval in which the content automatically refreshes, if not set this will default to 10 seconds. -That's it! But now, we need the Kubernetes Backend plugin for the frontend to -work. +::: + +That's it! But now, we need the Kubernetes Backend plugin for the frontend to work. ## Adding Kubernetes Backend plugin -Navigate to `packages/backend` of your Backstage app, and install the -`@backstage/plugin-kubernetes-backend` package. - -```bash title="From your Backstage root directory" -yarn --cwd packages/backend add @backstage/plugin-kubernetes-backend -``` - -Create a file called `kubernetes.ts` inside `packages/backend/src/plugins/` and -add the following: - -```ts title="packages/backend/src/plugins/kubernetes.ts" -import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend'; -import { Router } from 'express'; -import { PluginEnvironment } from '../types'; -import { CatalogClient } from '@backstage/catalog-client'; - -export default async function createPlugin( - env: PluginEnvironment, -): Promise { - const catalogApi = new CatalogClient({ discoveryApi: env.discovery }); - const { router } = await KubernetesBuilder.createBuilder({ - logger: env.logger, - config: env.config, - catalogApi, - discovery: env.discovery, - permissions: env.permissions, - }).build(); - return router; -} -``` - -And import the plugin to `packages/backend/src/index.ts`. There are three lines -of code you'll need to add, and they should be added near similar code in your -existing Backstage backend. - -```typescript title="packages/backend/src/index.ts" -// .. -/* highlight-add-next-line */ -import kubernetes from './plugins/kubernetes'; - -async function main() { - // ... - /* highlight-add-next-line */ - const kubernetesEnv = useHotMemoize(module, () => createEnv('kubernetes')); - // ... - /* highlight-add-next-line */ - apiRouter.use('/kubernetes', await kubernetes(kubernetesEnv)); -} -``` - -That's it! The Kubernetes frontend and backend have now been added to your -Backstage app. - -### New Backend System - -To get the Kubernetes plugin install using the New Backend System you will need to do the following: - -Run this command to add the package: +First, we need to add the backend package: ```bash title="From your Backstage root directory" yarn --cwd packages/backend add @backstage/plugin-kubernetes-backend @@ -126,6 +67,9 @@ backend.add(import('@backstage/plugin-kubernetes-backend')); backend.start(); ``` +That's it! The Kubernetes frontend and backend have now been added to your +Backstage app. + ### Custom cluster discovery If either existing @@ -133,22 +77,18 @@ If either existing don't work for your use-case, it is possible to implement a custom [KubernetesClustersSupplier](https://backstage.io/docs/reference/plugin-kubernetes-backend.kubernetesclusterssupplier). -Change the following in `packages/backend/src/plugins/kubernetes.ts`: +Here's a very simplified example: -```ts title="packages/backend/src/plugins/kubernetes.ts" -import { - /* highlight-add-next-line */ - ClusterDetails, - KubernetesBuilder, - /* highlight-add-next-line */ - KubernetesClustersSupplier, -} from '@backstage/plugin-kubernetes-backend'; -import { Router } from 'express'; -import { PluginEnvironment } from '../types'; -/* highlight-add-next-line */ +```ts title="packages/backend/src/index.ts" +import { createBackend } from '@backstage/backend-defaults'; +import { createBackendModule } from '@backstage/backend-plugin-api'; import { Duration } from 'luxon'; +import { + ClusterDetails, + KubernetesClustersSupplier, + kubernetesClusterSupplierExtensionPoint, +} from '@backstage/plugin-kubernetes-node'; -/* highlight-add-start */ export class CustomClustersSupplier implements KubernetesClustersSupplier { constructor(private clusterDetails: ClusterDetails[] = []) {} @@ -170,43 +110,6 @@ export class CustomClustersSupplier implements KubernetesClustersSupplier { return this.clusterDetails; } } -/* highlight-add-end */ - -export default async function createPlugin( - env: PluginEnvironment, -): Promise { - - /* highlight-remove-next-line */ - const { router } = await KubernetesBuilder.createBuilder({ - /* highlight-add-next-line */ - const builder = await KubernetesBuilder.createBuilder({ - logger: env.logger, - config: env.config, - /* highlight-remove-next-line */ - }).build(); - /* highlight-add-start */ - }); - builder.setClusterSupplier( - CustomClustersSupplier.create(Duration.fromObject({ minutes: 60 })), - ); - const { router } = await builder.build(); - /* highlight-add-end */ - - // .. - return router; -} -``` - -### New Backend System Custom cluster discovery - -To use Custom cluster discovery with the New Backend System you'll need to create a module and add it to your backend. Here's a very simplified example: - -```ts title="packages/backend/src/index.ts" -import { createBackend } from '@backstage/backend-defaults'; -import { createBackendModule } from '@backstage/backend-plugin-api'; -import { Duration } from 'luxon'; -import { kubernetesClusterSupplierExtensionPoint } from '@backstage/plugin-kubernetes-node'; -import { CustomClustersSupplier } from './path/to/class'; const backend = createBackend(); @@ -236,7 +139,7 @@ backend.start(); :::note Note -This example assumes the `CustomClustersSupplier` class is the same from the [previous example](#custom-cluster-discovery) +This example uses items from the `@backstage/plugin-kubernetes-node` and `luxon` packages, you'll need to add those for this example to work as is. ::: diff --git a/docs/features/kubernetes/permissions.md b/docs/features/kubernetes/permissions.md new file mode 100644 index 0000000000..5f1475d4b3 --- /dev/null +++ b/docs/features/kubernetes/permissions.md @@ -0,0 +1,18 @@ +--- +id: permissions +title: Permissions +description: Configuring permissions for Kubernetes plugin +--- + +The Kubernetes plugin integrates with the permission framework. Administrators can define PermissionPolicies +to restrict access to the `/clusters`, `/services/:serviceId`, `/resources` and `/proxy` endpoints. + +This feature assumes your Backstage instance has enabled the [permissions framework](https://backstage.io/docs/permissions/getting-started). + +### Available permissions + +| Name | Policy | Description | +| ------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------- | +| kubernetes.clusters.read | read | Allows the user to read Kubernetes clusters information under `/clusters` | +| kubernetes.resources.read | read | Allows the user to read Kubernetes resources information under `/services/:serviceId` and `/resources` | +| kubernetes.proxy | | Allows the user to make arbitrary requests to the [REST API](https://kubernetes.io/docs/reference/using-api/api-concepts/) under `/proxy` | diff --git a/docs/features/search/collators.md b/docs/features/search/collators.md index 0282bc845e..d87258f65b 100644 --- a/docs/features/search/collators.md +++ b/docs/features/search/collators.md @@ -35,6 +35,10 @@ backend.start(); ### Configuring the Catalog Collator +The following sections outlines the available configurations for this collator. + +#### Scheduling + The default schedule for the Catalog Collator is to run every 10 minutes, you can provide your own schedule by adding it to your config: ```yaml title="app-config.yaml @@ -50,6 +54,42 @@ search: timeout: { minutes: 3 } ``` +#### Filtering + +You may wish to collate specific subsets of entities in your Catalog, this can be accomplished using the `filter` configuration option. Here's a basic example: + +```yaml title"app-config.yaml" +search: + collators: + catalog: + filter: + kind: ['component', 'api'] + spec.lifecycle: production +``` + +The above example will only collate entities that are `kind` equal to `component` or `api` AND have a `spec.lifecycle` set to `production` + +You can also apply a more advanced filter like this: + +```yaml title"app-config.yaml" +search: + collators: + catalog: + filter: + - kind: ['API'] + spec.type: openapi + - kind: ['Component'] + spec.lifecycle: experimental +``` + +Now with this example it will collate all entities that are `kind` equal to `api` with a `spec.type` equal to `openapi` OR all entities that are `kind` equal to `component` AND have a `spec.lifecycle` set to `experimental` + +:::tip + +The filter configuration is implemented using the `EntityFilterQuery` syntax. The [reference documentation on `EntityFilterQuery`](https://backstage.io/docs/reference/catalog-client.entityfilterquery/) provides more details. + +::: + ## TechDocs The TechDocs collator will index all the TechDocs in your Catalog. It is installed by default but if you need to add it manually here's how. @@ -94,6 +134,38 @@ search: timeout: { minutes: 3 } ``` +### Filtering through the catalog collator + +The TechDocs collator by default filters through catalog entities where the annotation `metadata.annotations.backstage.io/techdocs-ref` exists. If you wish to further filter out entities, there are two ways to do so through the `techDocsCollatorEntityFilterExtensionPoint`. + +```typescript +export const exampleCustomCatalogFiltering = createBackendModule({ + pluginId: 'search', + moduleId: 'search-techdocs-collator-entity-filter', + register(reg) { + reg.registerInit({ + deps: { + customCollatorFilter: techDocsCollatorEntityFilterExtensionPoint, + }, + async init({ customCollatorFilter }) { + /* filtering by catalog params */ + customCollatorFilter.setCustomCatalogApiFilters([ + { kind: ['API', 'Component', ...] }, + { metadata: ['...more filters'] }, + ]); + + /* filtering by a custom function */ + customCollatorFilter.setEntityFilterFunction((entities: Entity[]) => + entities.filter( + entity => entity.metadata?.annotations?.abc === 'xyz', + ), + ); + }, + }); + }, +}); +``` + ## Community Collators Here are some of the known Search Collators available in from the Backstage Community: diff --git a/docs/features/search/how-to-guides.md b/docs/features/search/how-to-guides.md index 007b108df5..0476ef6c24 100644 --- a/docs/features/search/how-to-guides.md +++ b/docs/features/search/how-to-guides.md @@ -111,40 +111,6 @@ indexBuilder.addCollator({ }); ``` -## How to limit what can be searched in the Software Catalog - -The Software Catalog includes a wealth of information about the components, -systems, groups, users, and other aspects of your software ecosystem. However, -you may not always want _every_ aspect to appear when a user searches the -catalog. Examples include: - -- Entities of kind `Location`, which are often not useful to Backstage users. -- Entities of kind `User` or `Group`, if you'd prefer that users and groups be - exposed to search in a different way (or not at all). - -It's possible to write your own [Collator](./concepts.md#collators) to control -exactly what's available to search, (or a [Decorator](./concepts.md#decorators) -to filter things out here and there), but the `DefaultCatalogCollator` that's -provided by `@backstage/plugin-catalog-backend` offers some configuration too! - -```ts title="packages/backend/src/plugins/search.ts" -indexBuilder.addCollator({ - defaultRefreshIntervalSeconds: 600, - collator: DefaultCatalogCollator.fromConfig(env.config, { - discovery: env.discovery, - tokenManager: env.tokenManager, - /* highlight-add-start */ - filter: { - kind: ['API', 'Component', 'Domain', 'Group', 'System', 'User'], - }, - /* highlight-add-end */ - }), -}); -``` - -As shown above, you can add a catalog entity filter to narrow down what catalog -entities are indexed by the search engine. - ## How to customize search results highlighting styling The default highlighting styling for matched terms in search results is your diff --git a/docs/features/search/search-engines.md b/docs/features/search/search-engines.md index 8209ae951d..b61be1e0c8 100644 --- a/docs/features/search/search-engines.md +++ b/docs/features/search/search-engines.md @@ -238,3 +238,36 @@ search: ``` > You can also increase the batch size if you are using a large ES instance. + +### Elasticsearch Index Name Customization + +By default, the Elasticsearch indexer creates index names based on their type, a separator, and the current date as a postfix. You can configure a custom prefix for all indices by adding the following section to your app configuration. + +An example of a default index name would look like this: +`software-catalog-index__20250219` + +To prefix all indices with a custom string (e.g., `custom-prefix`), use the following configuration: + +```yaml +search: + elasticsearch: + indexPrefix: custom-prefix- +``` + +After applying this setting, an index name would look like this: `custom-prefix-software-catalog-index__20250219` + +### Elasticsearch query config + +By default the default settings for the Elasticsearch queries is used. If you need to tweak the fuzziness of the query results you can do this with 2 parameters, `fuzziness` and `prefixLength`. + +Fuzziness allows you to define the maximum Levenshtein distance, AUTO is the default and widely accepted standard. +`prefixLength` allows you to control the minimum number of characters that must match exactly at the beginning of the query term. This defaults to 0 +[More info](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-fuzzy-query.html) + +```yaml +search: + elasticsearch: + queryConfig: + fuzziness: AUTO + prefixLength: 3; +``` diff --git a/docs/features/software-catalog/api.md b/docs/features/software-catalog/api.md index ec699d2760..2a431d337b 100644 --- a/docs/features/software-catalog/api.md +++ b/docs/features/software-catalog/api.md @@ -214,7 +214,11 @@ if `prevCursor` exists, it can be used to retrieve the previous batch of entitie Lists entities. -**NOTE**: This endpoint is deprecated in favor of `GET /entities/by-query`, which provides a more efficient implementation and cursor based pagination. +:::note Note + +This endpoint is deprecated in favor of `GET /entities/by-query`, which provides a more efficient implementation and cursor based pagination. + +::: The endpoint supports the following query parameters, described in sections below: diff --git a/docs/features/software-catalog/catalog-customization.md b/docs/features/software-catalog/catalog-customization.md index c56f763a4e..38c4b2a951 100644 --- a/docs/features/software-catalog/catalog-customization.md +++ b/docs/features/software-catalog/catalog-customization.md @@ -17,7 +17,7 @@ Initial support for pagination of the `CatalogIndexPage` was added in v1.21.0 of ## Initially Selected Filter -By default the initially selected filter defaults to Owned. If you are still building up your catalog this may show an empty list to start. If you would prefer this to show All as the default, here's how you can make that change: +By default, the initially selected filter defaults to Owned. If you are still building up your catalog this may show an empty list to start. If you would prefer this to show All as the default, here's how you can make that change: ```tsx title="packages/app/src/App.tsx" } /> @@ -70,9 +70,7 @@ The columns you see in the `CatalogIndexPage` were selected to be a good startin Suppose we want to add a new User Email column to the `User` kind in the Catalog. We can do this by overriding the `columns` that we pass into the `CatalogIndexPage` component in our `App.tsx`. First, we need to match the entity kind that we want to override, and then define the columns to show: ```tsx title="packages/app/src/App.tsx" -{ - /* highlight-add-start */ -} +{/* prettier-ignore */ /* highlight-add-start */} const myColumnsFunc: CatalogTableColumnsFunc = entityListContext => { if (entityListContext.filters.kind?.value === 'user') { return [ @@ -84,9 +82,7 @@ const myColumnsFunc: CatalogTableColumnsFunc = entityListContext => { return CatalogTable.defaultColumnsFunc(entityListContext); }; -{ - /* highlight-add-end */ -} +{/* prettier-ignore */ /* highlight-add-end */} ``` Then, we can implement the `createUserEmailColumn` function and add it to the list of columns. `field` is used to access the data from the entity, while `render` lets us customize how we display the data: @@ -107,7 +103,6 @@ const createUserEmailColumn = (): TableColumn => ({ const myColumnsFunc: CatalogTableColumnsFunc = entityListContext => { if (entityListContext.filters.kind?.value === 'user') { - return [ return [ // Render existing columns ...CatalogTable.defaultColumnsFunc(entityListContext), @@ -391,13 +386,9 @@ export const EntitySecurityTierPicker = () => { Now we can add the component to `CatalogIndexPage`: ```tsx title="packages/app/src/App.tsx" -{ - /* highlight-add-start */ -} +{/* prettier-ignore */ /* highlight-add-start */} import { DefaultFilters } from '@backstage/plugin-catalog-react'; -{ - /* highlight-add-end */ -} +{/* prettier-ignore */ /* highlight-add-end */} const routes = ( @@ -511,3 +502,201 @@ const routes = ( ); ``` + +## New Frontend System + +This section of the documentation explains how to create and configure catalog extensions in the [new frontend system](../../frontend-system/index.md). + +:::warning Warning + +This section is a work in progress. + +::: + +### Entity filters + +Many extensions that attach within the catalog entity pages accept a `filter` configuration. The purpose of the `filter` configuration is to select what entities the extension should be applied to or be present on. Many of these extension will have a default filter defined, but you can override it by providing your own. When defining filters in code you can use either a predicate function or a entity predicate query, while in configuration you can only use an entity predicate query. + +### Entity predicate queries + +The entity predicate syntax is a minimal JSON-based query language for filtering catalog entities. It is loosely inspired by the [MongoDB query syntax](https://www.mongodb.com/docs/manual/tutorial/query-documents/), behaving roughly the same way but with a different set of operators. + +The most simple entity predicate is an object expression with key-value mappings where the key is the full dot-separated path to the value in the entity, and the value is the value to do a case insensitive match against. Each entry in this object is evaluated separately, but all of them must match for the overall predicate to result in a match. For example, the following will match any component entities of the type `service`: + +```json +{ + "filter": { + "kind": "component", + "spec.type": "service" + } +} +``` + +Or when utilizing YAML syntax: + +```yaml +filter: + kind: component + spec.type: service +``` + +In addition to this basic syntax, entity predicates support logical operators that can be nested and applied around these object expressions. For example, the following will match all components entities that are of type `service` or `website`: + +```json +{ + "filter": { + "$all": [ + { + "kind": "component" + }, + { + "$any": [{ "spec.type": "service" }, { "spec.type": "website" }] + } + ] + } +} +``` + +Or when utilizing YAML syntax: + +```yaml +filter: + $all: + - kind: component + - $any: + - spec.type: service + - spec.type: website +``` + +Finally, entity predicates also support value operators that can be used in place of the values in the object expression. For example, the following is a simpler way to express the previous example: + +```json +{ + "filter": { + { + "kind": "component", + "spec.type": { "$in": ["service", "website"] } + }, + } +} +``` + +Or when utilizing YAML syntax: + +```yaml +filter: + kind: component + spec.type: + $in: [service, website] +``` + +### Entity predicate logical operators + +The following section lists all logical operators for entity predicates. + +#### `$all` + +The `$all` operator has the following syntax: + +```json +{ $all: [ { }, { }, ...] } +``` + +The `$all` operator evaluates to `true` if all expressions within the provided array evaluate to `true`. This includes an empty array, which means that `{ "$all": [] }` always evaluates to `true`. + +```yaml title="Example usage of $all" +filter: + $all: + - kind: component + - $not: + spec.type: service +``` + +#### `$any` + +The `$any` operator has the following syntax: + +```json +{ $any: [ { }, { }, ...] } +``` + +The `$any` operator evaluates to `true` if at least one of the expressions within the provided array evaluate to `true`. This includes an empty array, which means that `{ "$any": [] }` always evaluates to `false`. + +```yaml title="Example usage of $any" +filter: + $any: + - kind: component + - metadata.annotations.github.com/project-slug: { $exists: true } +``` + +#### `$not` + +The `$not` operator has the following syntax: + +```json +{ $not: { } } +``` + +The `$not` operator inverts the result of the provided express. If the expression evaluates to `true` then `$not` will evaluate to false, and the other way around. + +```yaml title="Example usage of $not" +filter: + $not: + kind: template +``` + +### Entity predicate value operators + +The following section lists all value operators for entity predicates. + +#### `$exists` + +The `$exists` operator has the following syntax: + +```json +{ field: { $exists: } } +``` + +The `$exists` operator will evaluate to `true` if the existence of the value it matches against matches the provided boolean. That is `{ $exists: true }` will evaluate to `true` if and only if the value is defined, and `{ $exists: false }` will evaluate to `true` if and only if the value is not defined. + +```yaml title="Example usage of $exists" +filter: + metadata.annotations.github.com/project-slug: { $exists: true } +``` + +#### `$in` + +The `$in` operator has the following syntax: + +```json +{ field: { $in: [ , , ... ] } } +``` + +The `$in` operator will evaluate to `true` if the value it is matched against is exists within the array of primitives. The comparison is case insensitive and can only be done across primitive values. If the value matched against is an object or array, the operator will always evaluate to `false`. + +```yaml title="Example usage of $in" +filter: + kind: + $in: [component, api] +``` + +#### `$contains` + +The `$contains` operator has the following syntax: + +```json +{ field: { $contains: { } } } +``` + +The `$contains` operator will evaluate to `true` if the value it is matched against is an array, and at least one of the elements in the array fully matches the provided expression. If the value matched against is not an array, or if the array is empty, the operator will always evaluate to `false`. + +The expression used to match against the array can be any valid entity predicate expression, including logical operators and value operators. + +```yaml title="Example usage of $contains" +filter: + relations: + $contains: + type: ownedBy + target: + $in: [group:default/admins, group:default/viewers] +``` diff --git a/docs/features/software-catalog/configuration.md b/docs/features/software-catalog/configuration.md index 6ed5a1d4b6..f8de3034fd 100644 --- a/docs/features/software-catalog/configuration.md +++ b/docs/features/software-catalog/configuration.md @@ -163,6 +163,17 @@ catalog: orphanStrategy: delete ``` +## Clean up entities from orphaned entity providers + +By default, if an entity provider which has provided entities to the catalog, is no longer configured, then the entities remain in the catalog until they are manually unregistered. + +To remove these entities automatically, you can use the following configuration. + +```yaml +catalog: + orphanProviderStrategy: delete +``` + ## Processing Interval The [processing loop](./life-of-an-entity.md#processing) is diff --git a/docs/features/software-catalog/descriptor-format.md b/docs/features/software-catalog/descriptor-format.md index 17bdac56e9..28ddfae282 100644 --- a/docs/features/software-catalog/descriptor-format.md +++ b/docs/features/software-catalog/descriptor-format.md @@ -375,7 +375,9 @@ Fields of a link are: | `icon` | String | [Optional] A key representing a visual icon to be displayed in the UI. | | `type` | String | [Optional] An optional value to categorize links into specific groups. | -_NOTE_: The `icon` field value is meant to be a semantic key that will map to a +:::note Note + +The `icon` field value is meant to be a semantic key that will map to a specific icon that may be provided by an icon library (e.g. `material-ui` icons). These keys should be a sequence of `[a-z0-9A-Z]`, possibly separated by one of `[-_.]`. Backstage may support some basic icons out of the box such as those [defined in app-defaults](https://github.com/backstage/backstage/blob/master/packages/app-defaults/src/defaults/icons.tsx), but the @@ -383,6 +385,8 @@ Backstage integrator will ultimately be left to provide the appropriate icon component mappings. A generic fallback icon would be provided if a mapping cannot be resolved. +::: + The semantics of the `type` field are undefined. The adopter is free to define their own set of types and utilize them as they wish. Some potential use cases can be to utilize the type field to validate certain links exist on entities or to create customized UI components for specific link types. ## Common to All Kinds: Relations diff --git a/docs/features/software-catalog/extending-the-model--old.md b/docs/features/software-catalog/extending-the-model--old.md index 7368a4a339..668d1d8311 100644 --- a/docs/features/software-catalog/extending-the-model--old.md +++ b/docs/features/software-catalog/extending-the-model--old.md @@ -495,8 +495,8 @@ want to have an isomorphic package that houses these types. Within the Backstage main repo the package naming pattern of `-common` is used for isomorphic packages, and you may choose to adopt this pattern as well. -You can generate an isomorphic plugin package by running:`yarn new --select plugin-common` -or you can run `yarn new` and then select "plugin-common" from the list of options +You can generate an isomorphic plugin package by running: `yarn new` and then +select "plugin-common" from the list of options There's at this point no existing templates for generating isomorphic plugins using the `@backstage/cli`. Perhaps the simplest way to get started right now is diff --git a/docs/features/software-catalog/extending-the-model.md b/docs/features/software-catalog/extending-the-model.md index f9d20d03c2..d289886a09 100644 --- a/docs/features/software-catalog/extending-the-model.md +++ b/docs/features/software-catalog/extending-the-model.md @@ -495,8 +495,8 @@ want to have an isomorphic package that houses these types. Within the Backstage main repo the package naming pattern of `-common` is used for isomorphic packages, and you may choose to adopt this pattern as well. -You can generate an isomorphic plugin package by running:`yarn new --select plugin-common` -or you can run `yarn new` and then select "plugin-common" from the list of options +You can generate an isomorphic plugin package by running: `yarn new` and then +selecting "plugin-common" from the list of options There's at this point no existing templates for generating isomorphic plugins using the `@backstage/cli`. Perhaps the simplest way to get started right now is @@ -520,7 +520,7 @@ validate entities of our new kind. Just like with the definition package, you can find inspiration in for example the existing [ScaffolderEntitiesProcessor](https://github.com/backstage/backstage/tree/master/plugins/catalog-backend-module-scaffolder-entity-model/src/processor/ScaffolderEntitiesProcessor.ts). -The custom processor should be created as a separate module for the catalog plugin. For information on how to set that up, see the [plugin docs](../../plugins/backend-plugin.md#creating-a-backend-plugin). Use `yarn new --select backend-module` instead to create a module. For our case, the module ID will be `foobar` and the plugin ID will be `catalog`. +The custom processor should be created as a separate module for the catalog plugin. For information on how to set that up, see the [plugin docs](../../plugins/backend-plugin.md#creating-a-backend-plugin). Use `yarn new` and select `backend-module` instead to create a module. For our case, the module ID will be `foobar` and the plugin ID will be `catalog`. We also provide a high-level example of what a catalog process for a custom entity might look like: diff --git a/docs/features/software-catalog/external-integrations.md b/docs/features/software-catalog/external-integrations.md index f721c50ec2..64468f7f41 100644 --- a/docs/features/software-catalog/external-integrations.md +++ b/docs/features/software-catalog/external-integrations.md @@ -72,7 +72,7 @@ putting all extensions like this in a backend module package of their own in the `plugins` folder of your Backstage repo: ```sh -yarn new --select backend-module --option id=catalog +yarn new --select backend-module --option pluginId=catalog ``` The class will have this basic structure: @@ -650,7 +650,7 @@ putting all extensions like this in a backend module package of their own in the `plugins` folder of your Backstage repo: ```sh -yarn new --select backend-module --option id=catalog +yarn new --select backend-module --option pluginId=catalog ``` The class will have this basic structure: @@ -686,9 +686,8 @@ export class SystemXReaderProcessor implements CatalogProcessor { try { // Use the builtin reader facility to grab data from the - // API. If you prefer, you can just use plain fetch here - // (from the node-fetch package), or any other method of - // your choosing. + // API. If you prefer, you can just use plain fetch here, + // or any other method of your choosing. const response = await this.reader.readUrl(location.target); const json = JSON.parse((await response.buffer()).toString()); // Repeatedly call emit(processingResult.entity(location, )) @@ -1158,13 +1157,21 @@ export class MyIncrementalEntityProvider The last step is to implement the actual `next` method that will accept the cursor, call the API, process the result and return the result. ```ts +import { + ANNOTATION_LOCATION, + ANNOTATION_ORIGIN_LOCATION, +} from '@backstage/catalog-model'; +import { IncrementalEntityProvider } from '@backstage/plugin-catalog-backend-module-incremental-ingestion'; + export class MyIncrementalEntityProvider implements IncrementalEntityProvider { private readonly token: string; + private readonly mySource: string; - constructor(token: string) { + constructor(token: string, mySource: string) { this.token = token; + this.mySource = mySource; } getProviderName() { @@ -1182,6 +1189,7 @@ export class MyIncrementalEntityProvider cursor: Cursor = { page: 1 }, ): Promise> { const { apiClient } = context; + const location = `${this.getProviderName()}:${this.mySource}`; // call your API with the current cursor const data = await apiClient.getServices(cursor); @@ -1201,8 +1209,8 @@ export class MyIncrementalEntityProvider name: item.name, annotations: { // You need to define these, otherwise they'll fail validation - [ANNOTATION_LOCATION]: this.getProviderName(), - [ANNOTATION_ORIGIN_LOCATION]: this.getProviderName(), + [ANNOTATION_LOCATION]: location, + [ANNOTATION_ORIGIN_LOCATION]: location, }, }, spec: { diff --git a/docs/features/software-catalog/faq.md b/docs/features/software-catalog/faq.md index 974a4ee119..f4eb79d119 100644 --- a/docs/features/software-catalog/faq.md +++ b/docs/features/software-catalog/faq.md @@ -27,7 +27,7 @@ On the user experience side, a Backstage experience without complete organizatio ## Can I call the catalog itself from inside a processor / provider? -Any backend module, including those that provide processors and entity providers to the catalog, are technically able to get hold of a catalog client via the `catalogServiceRef` from `@backstage/plugin-catalog-node`. However, it is almost never the right thing to do - especially from processors - and we strongly discourage from doing so. +While it's possible to get hold of a catalog client via the `catalogServiceRef` from `@backstage/plugin-catalog-node`, it's almost never the right thing to do, and we strongly discourage from doing so. The catalog processing loop is a very high-speed system where your entire catalog cluster collaborates to race through all entities at the highest possible rate. The ideal processor does an absolute minimum of work, and immediately relinquishes control back. Performing asynchronous requests to external systems - including the catalog - from processors, can quickly become overwhelming for that external system and starve their resources if they aren't prepared to deal with very high rates of small requests. It also significantly slows down the procesing loop, when each step needs to wait for responses. This can lead to work "piling up" in the catalog and delays in seeing entities get updated. The [life of an entity](./life-of-an-entity.md) article shows the sequence of events that happen when an entity goes from original ingestion, through processing, and to becoming final entities. diff --git a/docs/features/software-templates/experimental.md b/docs/features/software-templates/experimental.md index e37971ad82..432bc3fecc 100644 --- a/docs/features/software-templates/experimental.md +++ b/docs/features/software-templates/experimental.md @@ -13,7 +13,64 @@ Please leave feedback on these features in the [Backstage Discord](https://disco ## Retries and Recovery -### TODO +Running tasks, especially longer running ones can be at risk of being lost when the `scaffolder-backend` plugin is redeployed. These tasks will just be stuck in a `processing` state, with no real way to recover them. + +The experimental Retries and Recovery is here to help mitigate this. + +Whenever you do redeploy, on startup there will be a check of all tasks in `processing` state that you identified in your template as being capable of starting over. + +More details about the motivation and the goals of this feature can be found in [the `Scaffolder Retries and Idempotency` BEP](https://github.com/backstage/backstage/tree/master/beps/0004-scaffolder-task-idempotency) + +Here is an example of how you can enable this in your `template.yaml` manifest: + +```yaml +apiVersion: scaffolder.backstage.io/v1beta3 +kind: Template +metadata: + name: recoverable-template +spec: + EXPERIMENTAL_recovery: + EXPERIMENTAL_strategy: startOver +``` + +You'll also need enable the recovery feature, add this snippet into your `app-config.yaml` file: + +```yaml +scaffolder: + EXPERIMENTAL_recoverTasks: true +``` + +By default, the tasks that are in a `processing` state and have not reported back with a heartbeat for longer than 30 seconds will be automatically recovered. + +This implies that the task's status will shift to `open` initiating and will be restarted from the beginning. This means that it's important that your actions that you have in the template run are idempotent. + +You can look at how to incorporate [checkpoints](https://backstage.io/docs/features/software-templates/writing-custom-actions#using-checkpoints-in-custom-actions-experimental) into your custom actions to achieve that. + +In the case that you would like to make the heartbeat threshold shorter or longer than the default 30 seconds, you can customize it for your needs with the configuration: + +```yaml +scaffolder: + EXPERIMENTAL_recoverTasksTimeout: { minutes: 1 } +``` + +If your task works with the filesystem and stores files in the workspace and you want to store these workspaces across runs, you can enable this with some additional config to `app-config.yaml` + +```yaml +scaffolder: + EXPERIMENTAL_workspaceSerialization: true +``` + +By default, the serialized workspace will be stored in the database, however if there's larger files, or if you're worried about the size of these files taking up space in the database you can configure bucket storage and have a sensible retention policy there to cleanup older files. + +At the moment we also support integration with Google GCS; to switch the serialization to this provider, you can do so with: + +```yaml +scaffolder: + EXPERIMENTAL_workspaceSerializationProvider: gcpBucket + EXPERIMENTAL_workspaceSerializationGcpBucketName: name-of-your-bucket +``` + +You don't need to provide any extra configuration, but you have to be sure that you are using [workload identity](https://cloud.google.com/iam/docs/workload-identity-federation). ## Form Decorators diff --git a/docs/features/software-templates/index.md b/docs/features/software-templates/index.md index 8018b76d91..b7f35f44c5 100644 --- a/docs/features/software-templates/index.md +++ b/docs/features/software-templates/index.md @@ -11,7 +11,7 @@ Components inside Backstage. By default, it has the ability to load skeletons of code, template in some variables, and then publish the template to some locations like GitHub or GitLab. -