diff --git a/.changeset/afraid-shirts-train.md b/.changeset/afraid-shirts-train.md deleted file mode 100644 index bd83716dc4..0000000000 --- a/.changeset/afraid-shirts-train.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@backstage/plugin-tech-insights': patch ---- - -Added the possibility to customize the check description in the scorecard component. - -- The `CheckResultRenderer` type now exposes an optional `description` method that allows to overwrite the description with a different string or a React component for a provided check result. - -Until now only the `BooleanCheck` element could be overridden, but from now on it's also possible to override the description for a check. -As an example, the description could change depending on the check result. Refer to the [README](https://github.com/backstage/backstage/blob/master/plugins/tech-insights/README.md#adding-custom-rendering-components) file for more details diff --git a/.changeset/angry-jobs-ring.md b/.changeset/angry-jobs-ring.md new file mode 100644 index 0000000000..a216af1683 --- /dev/null +++ b/.changeset/angry-jobs-ring.md @@ -0,0 +1,5 @@ +--- +'@backstage/catalog-client': patch +--- + +Updated API docs diff --git a/.changeset/backend-like-a-tattoo.md b/.changeset/backend-like-a-tattoo.md deleted file mode 100644 index 0d2edfa7a9..0000000000 --- a/.changeset/backend-like-a-tattoo.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': patch ---- - -Added `POSTGRES_11` and `POSTGRES_12` as supported test database IDs. diff --git a/.changeset/beige-kangaroos-suffer.md b/.changeset/beige-kangaroos-suffer.md new file mode 100644 index 0000000000..249fb5a4b6 --- /dev/null +++ b/.changeset/beige-kangaroos-suffer.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes': patch +--- + +Fix cyclical dependency in built output diff --git a/.changeset/beige-tigers-matter.md b/.changeset/beige-tigers-matter.md deleted file mode 100644 index 248ce1fbf9..0000000000 --- a/.changeset/beige-tigers-matter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -Fix case GitLab workspace is a nested subgroup diff --git a/.changeset/beige-zebras-walk.md b/.changeset/beige-zebras-walk.md new file mode 100644 index 0000000000..26ad52dc1d --- /dev/null +++ b/.changeset/beige-zebras-walk.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-user-settings': patch +--- + +Reflect the updated sign on status for a provider after signing out. diff --git a/.changeset/breezy-kids-obey.md b/.changeset/breezy-kids-obey.md new file mode 100644 index 0000000000..131a1ec1f3 --- /dev/null +++ b/.changeset/breezy-kids-obey.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +Added analytics event for import entity button diff --git a/.changeset/brown-eyes-yell.md b/.changeset/brown-eyes-yell.md deleted file mode 100644 index 5ed4140bba..0000000000 --- a/.changeset/brown-eyes-yell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-github-pull-requests-board': patch ---- - -The `EntityTeamPullRequestsContent` and `EntityTeamPullRequestsCard` support the ability to view the labels/tags added to each PR diff --git a/.changeset/calm-wolves-taste.md b/.changeset/calm-wolves-taste.md deleted file mode 100644 index ec0a7fb4f0..0000000000 --- a/.changeset/calm-wolves-taste.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search': patch ---- - -Fixed 404 Error when fetching search results due to URL encoding changes diff --git a/.changeset/chatty-ads-attack.md b/.changeset/chatty-ads-attack.md new file mode 100644 index 0000000000..709db946dd --- /dev/null +++ b/.changeset/chatty-ads-attack.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': patch +--- + +fixed refresh problem when backstage backend disconnects without any feedback to user. Now we send a generic message and try to reconnect after 15 seconds diff --git a/.changeset/chilled-queens-wonder.md b/.changeset/chilled-queens-wonder.md deleted file mode 100644 index a10212792d..0000000000 --- a/.changeset/chilled-queens-wonder.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Ensure that entity cache state is only written to the database when actually changed diff --git a/.changeset/chilly-fireants-type.md b/.changeset/chilly-fireants-type.md deleted file mode 100644 index 6bff750d57..0000000000 --- a/.changeset/chilly-fireants-type.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Remove the direct dependency on deprecated "request" library diff --git a/.changeset/clean-lobsters-brake.md b/.changeset/clean-lobsters-brake.md deleted file mode 100644 index f6da6e986e..0000000000 --- a/.changeset/clean-lobsters-brake.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-kubernetes-backend': minor ---- - -Allow fetching pod metrics limited by a `labelSelector`. - -This is used by the Kubernetes tab on a components' page and leads to much smaller responses being received from Kubernetes, especially with larger Kubernetes clusters. diff --git a/.changeset/clean-months-bake.md b/.changeset/clean-months-bake.md new file mode 100644 index 0000000000..5886dea66b --- /dev/null +++ b/.changeset/clean-months-bake.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-octopus-deploy': patch +--- + +Improved getting started documentation diff --git a/.changeset/cold-drinks-exercise.md b/.changeset/cold-drinks-exercise.md deleted file mode 100644 index e47e133929..0000000000 --- a/.changeset/cold-drinks-exercise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-explore': patch ---- - -Make sure that the first support button row does not break across lines diff --git a/.changeset/create-app-1682437922.md b/.changeset/create-app-1684855417.md similarity index 100% rename from .changeset/create-app-1682437922.md rename to .changeset/create-app-1684855417.md diff --git a/.changeset/curvy-months-appear.md b/.changeset/curvy-months-appear.md deleted file mode 100644 index 487e60c437..0000000000 --- a/.changeset/curvy-months-appear.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Re-add the possibility to have trailing slashes in Techdocs navigation. diff --git a/.changeset/curvy-years-smoke.md b/.changeset/curvy-years-smoke.md new file mode 100644 index 0000000000..056056fdff --- /dev/null +++ b/.changeset/curvy-years-smoke.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Forward `Authorization` header for `EventSource` when credentials are available. diff --git a/.changeset/dry-boats-sniff.md b/.changeset/dry-boats-sniff.md deleted file mode 100644 index 0c359b5536..0000000000 --- a/.changeset/dry-boats-sniff.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@backstage/app-defaults': patch ---- - -Added a System Icon for resource entities. -This can be obtained using: - -```ts -useApp().getSystemIcon('kind:resource'); -``` diff --git a/.changeset/dull-bottles-teach.md b/.changeset/dull-bottles-teach.md new file mode 100644 index 0000000000..74203eb758 --- /dev/null +++ b/.changeset/dull-bottles-teach.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-home': patch +--- + +Allow more customization for the CustomHomepageGrid diff --git a/.changeset/dull-wombats-stare.md b/.changeset/dull-wombats-stare.md deleted file mode 100644 index 36ba412c02..0000000000 --- a/.changeset/dull-wombats-stare.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-openapi-utils': patch ---- - -Adjusted README accordingly after the generated output now has a `.generated.ts` extension diff --git a/.changeset/eighty-olives-live.md b/.changeset/eighty-olives-live.md deleted file mode 100644 index 16898701f4..0000000000 --- a/.changeset/eighty-olives-live.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Updated the `DatabaseManager` to include the plugin id in the Postgres application name of the database connections created for each plugin. diff --git a/.changeset/fast-ears-know.md b/.changeset/fast-ears-know.md new file mode 100644 index 0000000000..fa56c4c99d --- /dev/null +++ b/.changeset/fast-ears-know.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-user-settings': patch +--- + +Improved the user experience of the feature flags list. It now sorts the enabled flags to the top of the list to increase the visibilities of the toggled flags. diff --git a/.changeset/fast-zebras-watch.md b/.changeset/fast-zebras-watch.md new file mode 100644 index 0000000000..7466565e79 --- /dev/null +++ b/.changeset/fast-zebras-watch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-devtools-backend': patch +--- + +Expose permissions through the metadata endpoint. diff --git a/.changeset/few-games-swim.md b/.changeset/few-games-swim.md new file mode 100644 index 0000000000..d0cd13ab11 --- /dev/null +++ b/.changeset/few-games-swim.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-cicd-statistics-module-gitlab': patch +'@backstage/plugin-scaffolder-backend-module-gitlab': patch +--- + +Fixed publish configuration. diff --git a/.changeset/few-oranges-complain.md b/.changeset/few-oranges-complain.md new file mode 100644 index 0000000000..70eb921a92 --- /dev/null +++ b/.changeset/few-oranges-complain.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Fix handling of `optional` property in `catalog:register` scaffolder action diff --git a/.changeset/few-pugs-jam.md b/.changeset/few-pugs-jam.md new file mode 100644 index 0000000000..83908a2cc1 --- /dev/null +++ b/.changeset/few-pugs-jam.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-sonarqube-backend': patch +--- + +Provide full schema definition for sonarqube plugin, especially to protect api keys. diff --git a/.changeset/fifty-grapes-explode.md b/.changeset/fifty-grapes-explode.md deleted file mode 100644 index 999a105c4f..0000000000 --- a/.changeset/fifty-grapes-explode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Fixed a bug in the `queryEntities` endpoint that was causing filtered entities to be included in cursor requests. diff --git a/.changeset/fifty-laws-count.md b/.changeset/fifty-laws-count.md deleted file mode 100644 index f20e41fc20..0000000000 --- a/.changeset/fifty-laws-count.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-kubernetes': patch ---- - -Omit managed fields in the Kubernetes resource YAML display. diff --git a/.changeset/five-tigers-whisper.md b/.changeset/five-tigers-whisper.md deleted file mode 100644 index aa9758c3b5..0000000000 --- a/.changeset/five-tigers-whisper.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-stack-overflow': patch ---- - -StackOverflowSearchResultListItem can now accept an empty result prop so that it can be rendered in the suggested SearchResultListItem pattern. diff --git a/.changeset/fresh-moons-unite.md b/.changeset/fresh-moons-unite.md deleted file mode 100644 index 3d3af7e698..0000000000 --- a/.changeset/fresh-moons-unite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Adjusted the OpenAPI schema file name according to the new structure diff --git a/.changeset/funny-trains-sniff.md b/.changeset/funny-trains-sniff.md deleted file mode 100644 index 91dbd28c28..0000000000 --- a/.changeset/funny-trains-sniff.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -'@backstage/plugin-catalog-react': minor -'@backstage/plugin-catalog': minor ---- - -Added an entity namespace filter and column on the default catalog page. - -If you have a custom version of the catalog page, you can add this filter in your CatalogPage code: - -```ts - - - - - - /* if you want namespace picker */ - - - - - - -``` - -The namespace column can be added using `createNamespaceColumn();`. This is only needed if you customized the columns for CatalogTable. diff --git a/.changeset/good-lions-approve.md b/.changeset/good-lions-approve.md deleted file mode 100644 index f4065a6ab3..0000000000 --- a/.changeset/good-lions-approve.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/integration': patch ---- - -Fixed a bug where the wrong credentials would be selected when using multiple GitHub app integrations. diff --git a/.changeset/green-cheetahs-cover.md b/.changeset/green-cheetahs-cover.md deleted file mode 100644 index 2633a5af01..0000000000 --- a/.changeset/green-cheetahs-cover.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-app-api': minor ---- - -The analytics' `navigate` event will now include the route parameters as attributes of the navigate event diff --git a/.changeset/healthy-ladybugs-chew.md b/.changeset/healthy-ladybugs-chew.md deleted file mode 100644 index 83f53d5c2c..0000000000 --- a/.changeset/healthy-ladybugs-chew.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/repo-tools': minor ---- - -Generated OpenAPI files now have a `.generated.ts` file name and a warning header at the top, to highlight that they should not be edited by hand. diff --git a/.changeset/heavy-ravens-fold.md b/.changeset/heavy-ravens-fold.md new file mode 100644 index 0000000000..f5f88c7662 --- /dev/null +++ b/.changeset/heavy-ravens-fold.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-node': patch +--- + +Use latest techdocs docker image by default. The latest image contains security updates. diff --git a/.changeset/hungry-foxes-divide.md b/.changeset/hungry-foxes-divide.md deleted file mode 100644 index 589c899443..0000000000 --- a/.changeset/hungry-foxes-divide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-graph': patch ---- - -Expose all `EntityRelationsGraphProps` to Catalog Graph Page diff --git a/.changeset/khaki-radios-teach.md b/.changeset/khaki-radios-teach.md new file mode 100644 index 0000000000..05ede0593c --- /dev/null +++ b/.changeset/khaki-radios-teach.md @@ -0,0 +1,5 @@ +--- +'@backstage/config-loader': patch +--- + +Fix a bug where config items with `/` in the key were incorrectly handled. diff --git a/.changeset/lazy-keys-work.md b/.changeset/lazy-keys-work.md deleted file mode 100644 index 8a01662929..0000000000 --- a/.changeset/lazy-keys-work.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-circleci': patch ---- - -Fixes row display for in progress jobs to not display trailing "took" diff --git a/.changeset/light-cows-bow.md b/.changeset/light-cows-bow.md new file mode 100644 index 0000000000..ba1b1c7631 --- /dev/null +++ b/.changeset/light-cows-bow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Clearer error messages for action `publish:gitlab:merge-request` diff --git a/.changeset/little-boats-think.md b/.changeset/little-boats-think.md new file mode 100644 index 0000000000..d389bfbbb1 --- /dev/null +++ b/.changeset/little-boats-think.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-catalog-react': minor +--- + +The `EntityOwnerPicker` component has undergone improvements to enhance its performance. + +The component now loads entities asynchronously, resulting in improved performance and responsiveness. Instead of loading all entities upfront, they are now loaded in batches as the user scrolls. +The previous implementation inferred users and groups displayed by the `EntityOwnerPicker` component based on the entities available in the `EntityListContext`. The updated version no longer relies on the `EntityListContext` for inference, allowing for better decoupling and improved performance. diff --git a/.changeset/long-lobsters-brake.md b/.changeset/long-lobsters-brake.md new file mode 100644 index 0000000000..01ae3f4e93 --- /dev/null +++ b/.changeset/long-lobsters-brake.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-jenkins-common': patch +--- + +Export list of permissions diff --git a/.changeset/lovely-impalas-sell.md b/.changeset/lovely-impalas-sell.md new file mode 100644 index 0000000000..80447c066f --- /dev/null +++ b/.changeset/lovely-impalas-sell.md @@ -0,0 +1,16 @@ +--- +'@backstage/plugin-search-backend-module-explore': patch +--- + +Allows for an optional `tokenManager` to authenticate requests from the collator to the explore backend. For example: + +```diff + indexBuilder.addCollator({ + schedule: every10MinutesSchedule, + factory: ToolDocumentCollatorFactory.fromConfig(env.config, { + discovery: env.discovery, + logger: env.logger, + + tokenManager: env.tokenManager, + }), + }); +``` diff --git a/.changeset/honest-countries-deny.md b/.changeset/lucky-keys-behave.md similarity index 50% rename from .changeset/honest-countries-deny.md rename to .changeset/lucky-keys-behave.md index 14c9094592..a223f83fa6 100644 --- a/.changeset/honest-countries-deny.md +++ b/.changeset/lucky-keys-behave.md @@ -2,4 +2,4 @@ '@backstage/plugin-jenkins-backend': patch --- -Fix handling of slashes in branch names +Expose permissions through the metadata endpoint. diff --git a/.changeset/mighty-bears-glow.md b/.changeset/mighty-bears-glow.md deleted file mode 100644 index e540cdd8ae..0000000000 --- a/.changeset/mighty-bears-glow.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@backstage/plugin-search-react': minor -'@backstage/plugin-search': minor ---- - -Add close button & improve search input. - -MUI's Paper wrapping the SearchBar in the SearchPage was removed, we recommend users update their apps accordingly. - -SearchBarBase's TextField's label support added & aria-label uses label string if present, tests relying on the default placeholder value should still work unless custom placeholder was given. diff --git a/.changeset/mighty-cows-greet.md b/.changeset/mighty-cows-greet.md deleted file mode 100644 index 2e871db0c6..0000000000 --- a/.changeset/mighty-cows-greet.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-analytics-module-ga4': minor ---- - -Plugin provides Backstage Analytics API for Google Analytics 4. Once installed and configured, analytics events will be sent to GA4 as your users navigate and use your Backstage instance diff --git a/.changeset/modern-pumpkins-join.md b/.changeset/modern-pumpkins-join.md deleted file mode 100644 index dc0e4a6575..0000000000 --- a/.changeset/modern-pumpkins-join.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-app-api': patch ---- - -Switch `configServiceFactory` to use `ConfigSources` from `@backstage/config-loader` to load config. diff --git a/.changeset/moody-lizards-beam.md b/.changeset/moody-lizards-beam.md deleted file mode 100644 index 68fb9a9e40..0000000000 --- a/.changeset/moody-lizards-beam.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -'@backstage/config-loader': minor ---- - -Introduced a new config source system to replace `loadConfig`. There is a new `ConfigSource` interface along with utilities provided by `ConfigSources`, as well as a number of built-in configuration source implementations. The new system is more flexible and makes it easier to create new and reusable sources of configuration, such as loading configuration from secret providers. - -The following is an example of how to load configuration using the default behavior: - -```ts -const source = ConfigSources.default({ - argv: options?.argv, - remote: options?.remote, -}); -const config = await ConfigSources.toConfig(source); -``` - -The `ConfigSource` interface looks like this: - -```ts -export interface ConfigSource { - readConfigData(options?: ReadConfigDataOptions): AsyncConfigSourceIterator; -} -``` - -It is best implemented using an async iterator: - -```ts -class MyConfigSource implements ConfigSource { - async *readConfigData() { - yield { - config: [ - { - context: 'example', - data: { backend: { baseUrl: 'http://localhost' } }, - }, - ], - }; - } -} -``` diff --git a/.changeset/moody-shrimps-train.md b/.changeset/moody-shrimps-train.md deleted file mode 100644 index 397500e2cb..0000000000 --- a/.changeset/moody-shrimps-train.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend-module-gitlab': minor ---- - -Add a new scaffolder action for gitlab to ensure a group exists diff --git a/.changeset/nine-ties-smoke.md b/.changeset/nine-ties-smoke.md deleted file mode 100644 index f7ae8016be..0000000000 --- a/.changeset/nine-ties-smoke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-home': patch ---- - -Bump to using the later v5 versions of `@rjsf/*` diff --git a/.changeset/olive-turkeys-switch.md b/.changeset/olive-turkeys-switch.md deleted file mode 100644 index d208f3b197..0000000000 --- a/.changeset/olive-turkeys-switch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-github': patch ---- - -Fixed bug in queryWithPaging that caused secondary rate limit errors in GitHub with organizations having more than 1000 repositories. This change makes one request per second to avoid concurrency issues. diff --git a/.changeset/perfect-readers-attack.md b/.changeset/perfect-readers-attack.md new file mode 100644 index 0000000000..93d205eb9c --- /dev/null +++ b/.changeset/perfect-readers-attack.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-gitlab': patch +--- + +Tweak README diff --git a/.changeset/pink-goats-talk.md b/.changeset/pink-goats-talk.md new file mode 100644 index 0000000000..3b67af81f4 --- /dev/null +++ b/.changeset/pink-goats-talk.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-search-react': patch +'@backstage/plugin-search': patch +'@backstage/plugin-techdocs': patch +--- + +Fix SearchBar styles & update StoryBook stories for custom styles for `notchedOutline` class. diff --git a/.changeset/plenty-roses-raise.md b/.changeset/plenty-roses-raise.md new file mode 100644 index 0000000000..71605705e3 --- /dev/null +++ b/.changeset/plenty-roses-raise.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-devtools-common': patch +--- + +Export the list of permissions diff --git a/.changeset/polite-dingos-train.md b/.changeset/polite-dingos-train.md deleted file mode 100644 index 49ac56a000..0000000000 --- a/.changeset/polite-dingos-train.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -'@backstage/plugin-kubernetes': minor ---- - -Added Pod logs components for Kubernetes plugin - -**BREAKING**: `kubernetesProxyApi` for custom plugins built with components from the Kubernetes plugin apis, `kubernetesProxyApi` should be added to the plugin's API list. - -``` -... -export const kubernetesPlugin = createPlugin({ - id: 'kubernetes', - apis: [ -... - createApiFactory({ - api: kubernetesProxyApiRef, - deps: { - kubernetesApi: kubernetesApiRef, - }, - factory: ({ kubernetesApi }) => - new KubernetesProxyClient({ - kubernetesApi, - }), - }), -``` - -**BREAKING**: `KubernetesDrawer` is now called `KubernetesStructuredMetadataTableDrawer` so that we can do more than just show `StructuredMetadataTable` - -`import { KubernetesDrawer } from "@backstage/plugin-kubernetes"` - -should now be: - -`import { KubernetesStructuredMetadataTableDrawer } from "@backstage/plugin-kubernetes"` diff --git a/.changeset/pre.json b/.changeset/pre.json index 759b1b40e2..6ecb7483ef 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -2,270 +2,257 @@ "mode": "pre", "tag": "next", "initialVersions": { - "example-app": "0.2.82", - "@backstage/app-defaults": "1.3.0", - "example-backend": "0.2.82", - "@backstage/backend-app-api": "0.4.2", - "@backstage/backend-common": "0.18.4", - "@backstage/backend-defaults": "0.1.9", + "example-app": "0.2.83", + "@backstage/app-defaults": "1.3.1", + "example-backend": "0.2.83", + "@backstage/backend-app-api": "0.4.3", + "@backstage/backend-common": "0.18.5", + "@backstage/backend-defaults": "0.1.10", "@backstage/backend-dev-utils": "0.1.1", - "example-backend-next": "0.0.10", - "@backstage/backend-openapi-utils": "0.0.1", - "@backstage/backend-plugin-api": "0.5.1", - "@backstage/backend-tasks": "0.5.1", - "@backstage/backend-test-utils": "0.1.36", + "example-backend-next": "0.0.11", + "@backstage/backend-openapi-utils": "0.0.2", + "@backstage/backend-plugin-api": "0.5.2", + "@backstage/backend-tasks": "0.5.2", + "@backstage/backend-test-utils": "0.1.37", "@backstage/catalog-client": "1.4.1", "@backstage/catalog-model": "1.3.0", - "@backstage/cli": "0.22.6", + "@backstage/cli": "0.22.7", "@backstage/cli-common": "0.1.12", "@backstage/cli-node": "0.1.0", "@backstage/codemods": "0.1.44", "@backstage/config": "1.0.7", - "@backstage/config-loader": "1.2.0", - "@backstage/core-app-api": "1.7.0", - "@backstage/core-components": "0.13.0", + "@backstage/config-loader": "1.3.0", + "@backstage/core-app-api": "1.8.0", + "@backstage/core-components": "0.13.1", "@backstage/core-plugin-api": "1.5.1", - "@backstage/create-app": "0.5.0", - "@backstage/dev-utils": "1.0.14", - "e2e-test": "0.2.2", + "@backstage/create-app": "0.5.1", + "@backstage/dev-utils": "1.0.15", + "e2e-test": "0.2.3", "@backstage/errors": "1.1.5", "@backstage/eslint-plugin": "0.1.3", - "@backstage/integration": "1.4.4", - "@backstage/integration-aws-node": "0.1.2", - "@backstage/integration-react": "1.1.12", + "@backstage/integration": "1.4.5", + "@backstage/integration-aws-node": "0.1.3", + "@backstage/integration-react": "1.1.13", "@backstage/release-manifests": "0.0.9", - "@backstage/repo-tools": "0.2.0", - "@techdocs/cli": "1.4.1", - "techdocs-cli-embedded-app": "0.2.81", - "@backstage/test-utils": "1.3.0", - "@backstage/theme": "0.2.19", + "@backstage/repo-tools": "0.3.0", + "@techdocs/cli": "1.4.2", + "techdocs-cli-embedded-app": "0.2.82", + "@backstage/test-utils": "1.3.1", + "@backstage/theme": "0.3.0", "@backstage/types": "1.0.2", "@backstage/version-bridge": "1.0.4", - "@backstage/plugin-adr": "0.5.0", - "@backstage/plugin-adr-backend": "0.3.2", - "@backstage/plugin-adr-common": "0.2.8", - "@backstage/plugin-airbrake": "0.3.17", - "@backstage/plugin-airbrake-backend": "0.2.17", - "@backstage/plugin-allure": "0.1.33", - "@backstage/plugin-analytics-module-ga": "0.1.28", - "@backstage/plugin-apache-airflow": "0.2.10", - "@backstage/plugin-api-docs": "0.9.2", + "@backstage/plugin-adr": "0.6.0", + "@backstage/plugin-adr-backend": "0.3.3", + "@backstage/plugin-adr-common": "0.2.9", + "@backstage/plugin-airbrake": "0.3.18", + "@backstage/plugin-airbrake-backend": "0.2.18", + "@backstage/plugin-allure": "0.1.34", + "@backstage/plugin-analytics-module-ga": "0.1.29", + "@backstage/plugin-analytics-module-ga4": "0.1.0", + "@backstage/plugin-apache-airflow": "0.2.11", + "@backstage/plugin-api-docs": "0.9.3", "@backstage/plugin-api-docs-module-protoc-gen-doc": "0.1.2", - "@backstage/plugin-apollo-explorer": "0.1.10", - "@backstage/plugin-app-backend": "0.3.44", - "@backstage/plugin-auth-backend": "0.18.2", - "@backstage/plugin-auth-node": "0.2.13", - "@backstage/plugin-azure-devops": "0.2.8", - "@backstage/plugin-azure-devops-backend": "0.3.23", + "@backstage/plugin-apollo-explorer": "0.1.11", + "@backstage/plugin-app-backend": "0.3.45", + "@backstage/plugin-auth-backend": "0.18.3", + "@backstage/plugin-auth-node": "0.2.14", + "@backstage/plugin-azure-devops": "0.3.0", + "@backstage/plugin-azure-devops-backend": "0.3.24", "@backstage/plugin-azure-devops-common": "0.3.0", - "@backstage/plugin-azure-sites": "0.1.6", - "@backstage/plugin-azure-sites-backend": "0.1.6", + "@backstage/plugin-azure-sites": "0.1.7", + "@backstage/plugin-azure-sites-backend": "0.1.7", "@backstage/plugin-azure-sites-common": "0.1.0", - "@backstage/plugin-badges": "0.2.41", - "@backstage/plugin-badges-backend": "0.1.38", - "@backstage/plugin-bazaar": "0.2.7", - "@backstage/plugin-bazaar-backend": "0.2.7", - "@backstage/plugin-bitbucket-cloud-common": "0.2.5", - "@backstage/plugin-bitrise": "0.1.44", - "@backstage/plugin-catalog": "1.10.0", - "@backstage/plugin-catalog-backend": "1.9.0", - "@backstage/plugin-catalog-backend-module-aws": "0.1.18", - "@backstage/plugin-catalog-backend-module-azure": "0.1.15", - "@backstage/plugin-catalog-backend-module-bitbucket": "0.2.11", - "@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.1.11", - "@backstage/plugin-catalog-backend-module-bitbucket-server": "0.1.9", - "@backstage/plugin-catalog-backend-module-gerrit": "0.1.12", - "@backstage/plugin-catalog-backend-module-github": "0.2.7", - "@backstage/plugin-catalog-backend-module-gitlab": "0.2.0", - "@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.3.1", - "@backstage/plugin-catalog-backend-module-ldap": "0.5.11", - "@backstage/plugin-catalog-backend-module-msgraph": "0.5.3", - "@backstage/plugin-catalog-backend-module-openapi": "0.1.10", - "@backstage/plugin-catalog-backend-module-puppetdb": "0.1.1", + "@backstage/plugin-badges": "0.2.42", + "@backstage/plugin-badges-backend": "0.2.0", + "@backstage/plugin-bazaar": "0.2.8", + "@backstage/plugin-bazaar-backend": "0.2.8", + "@backstage/plugin-bitbucket-cloud-common": "0.2.6", + "@backstage/plugin-bitrise": "0.1.45", + "@backstage/plugin-catalog": "1.11.0", + "@backstage/plugin-catalog-backend": "1.9.1", + "@backstage/plugin-catalog-backend-module-aws": "0.2.0", + "@backstage/plugin-catalog-backend-module-azure": "0.1.16", + "@backstage/plugin-catalog-backend-module-bitbucket": "0.2.12", + "@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.1.12", + "@backstage/plugin-catalog-backend-module-bitbucket-server": "0.1.10", + "@backstage/plugin-catalog-backend-module-gerrit": "0.1.13", + "@backstage/plugin-catalog-backend-module-github": "0.3.0", + "@backstage/plugin-catalog-backend-module-gitlab": "0.2.1", + "@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.3.2", + "@backstage/plugin-catalog-backend-module-ldap": "0.5.12", + "@backstage/plugin-catalog-backend-module-msgraph": "0.5.4", + "@backstage/plugin-catalog-backend-module-openapi": "0.1.11", + "@backstage/plugin-catalog-backend-module-puppetdb": "0.1.2", "@backstage/plugin-catalog-common": "1.0.13", - "@internal/plugin-catalog-customized": "0.0.9", - "@backstage/plugin-catalog-graph": "0.2.29", + "@internal/plugin-catalog-customized": "0.0.10", + "@backstage/plugin-catalog-graph": "0.2.30", "@backstage/plugin-catalog-graphql": "0.3.20", - "@backstage/plugin-catalog-import": "0.9.7", - "@backstage/plugin-catalog-node": "1.3.5", - "@backstage/plugin-catalog-react": "1.5.0", - "@backstage/plugin-cicd-statistics": "0.1.19", - "@backstage/plugin-cicd-statistics-module-gitlab": "0.1.13", - "@backstage/plugin-circleci": "0.3.17", - "@backstage/plugin-cloudbuild": "0.3.17", - "@backstage/plugin-code-climate": "0.1.17", - "@backstage/plugin-code-coverage": "0.2.10", - "@backstage/plugin-code-coverage-backend": "0.2.10", - "@backstage/plugin-codescene": "0.1.12", - "@backstage/plugin-config-schema": "0.1.40", - "@backstage/plugin-cost-insights": "0.12.6", + "@backstage/plugin-catalog-import": "0.9.8", + "@backstage/plugin-catalog-node": "1.3.6", + "@backstage/plugin-catalog-react": "1.6.0", + "@backstage/plugin-cicd-statistics": "0.1.20", + "@backstage/plugin-cicd-statistics-module-gitlab": "0.1.14", + "@backstage/plugin-circleci": "0.3.18", + "@backstage/plugin-cloudbuild": "0.3.18", + "@backstage/plugin-code-climate": "0.1.18", + "@backstage/plugin-code-coverage": "0.2.11", + "@backstage/plugin-code-coverage-backend": "0.2.11", + "@backstage/plugin-codescene": "0.1.13", + "@backstage/plugin-config-schema": "0.1.41", + "@backstage/plugin-cost-insights": "0.12.7", "@backstage/plugin-cost-insights-common": "0.1.1", - "@backstage/plugin-dynatrace": "4.0.0", - "@backstage/plugin-entity-feedback": "0.2.0", - "@backstage/plugin-entity-feedback-backend": "0.1.2", + "@backstage/plugin-devtools": "0.1.0", + "@backstage/plugin-devtools-backend": "0.1.0", + "@backstage/plugin-devtools-common": "0.1.0", + "@backstage/plugin-dynatrace": "5.0.0", + "@backstage/plugin-entity-feedback": "0.2.1", + "@backstage/plugin-entity-feedback-backend": "0.1.3", "@backstage/plugin-entity-feedback-common": "0.1.1", - "@backstage/plugin-entity-validation": "0.1.2", - "@backstage/plugin-events-backend": "0.2.5", - "@backstage/plugin-events-backend-module-aws-sqs": "0.1.6", - "@backstage/plugin-events-backend-module-azure": "0.1.6", - "@backstage/plugin-events-backend-module-bitbucket-cloud": "0.1.6", - "@backstage/plugin-events-backend-module-gerrit": "0.1.6", - "@backstage/plugin-events-backend-module-github": "0.1.6", - "@backstage/plugin-events-backend-module-gitlab": "0.1.6", - "@backstage/plugin-events-backend-test-utils": "0.1.6", - "@backstage/plugin-events-node": "0.2.5", - "@internal/plugin-todo-list": "1.0.12", - "@internal/plugin-todo-list-backend": "1.0.12", + "@backstage/plugin-entity-validation": "0.1.3", + "@backstage/plugin-events-backend": "0.2.6", + "@backstage/plugin-events-backend-module-aws-sqs": "0.2.0", + "@backstage/plugin-events-backend-module-azure": "0.1.7", + "@backstage/plugin-events-backend-module-bitbucket-cloud": "0.1.7", + "@backstage/plugin-events-backend-module-gerrit": "0.1.7", + "@backstage/plugin-events-backend-module-github": "0.1.7", + "@backstage/plugin-events-backend-module-gitlab": "0.1.7", + "@backstage/plugin-events-backend-test-utils": "0.1.7", + "@backstage/plugin-events-node": "0.2.6", + "@internal/plugin-todo-list": "1.0.13", + "@internal/plugin-todo-list-backend": "1.0.13", "@internal/plugin-todo-list-common": "1.0.10", - "@backstage/plugin-explore": "0.4.2", - "@backstage/plugin-explore-backend": "0.0.6", + "@backstage/plugin-explore": "0.4.3", + "@backstage/plugin-explore-backend": "0.0.7", "@backstage/plugin-explore-common": "0.0.1", "@backstage/plugin-explore-react": "0.0.28", - "@backstage/plugin-firehydrant": "0.2.1", - "@backstage/plugin-fossa": "0.2.49", - "@backstage/plugin-gcalendar": "0.3.13", - "@backstage/plugin-gcp-projects": "0.3.36", - "@backstage/plugin-git-release-manager": "0.3.30", - "@backstage/plugin-github-actions": "0.5.17", - "@backstage/plugin-github-deployments": "0.1.48", - "@backstage/plugin-github-issues": "0.2.6", - "@backstage/plugin-github-pull-requests-board": "0.1.11", - "@backstage/plugin-gitops-profiles": "0.3.35", - "@backstage/plugin-gocd": "0.1.23", - "@backstage/plugin-graphiql": "0.2.49", - "@backstage/plugin-graphql-backend": "0.1.34", - "@backstage/plugin-graphql-voyager": "0.1.2", - "@backstage/plugin-home": "0.5.0", - "@backstage/plugin-ilert": "0.2.6", - "@backstage/plugin-jenkins": "0.7.16", - "@backstage/plugin-jenkins-backend": "0.1.34", + "@backstage/plugin-firehydrant": "0.2.2", + "@backstage/plugin-fossa": "0.2.50", + "@backstage/plugin-gcalendar": "0.3.14", + "@backstage/plugin-gcp-projects": "0.3.37", + "@backstage/plugin-git-release-manager": "0.3.31", + "@backstage/plugin-github-actions": "0.5.18", + "@backstage/plugin-github-deployments": "0.1.49", + "@backstage/plugin-github-issues": "0.2.7", + "@backstage/plugin-github-pull-requests-board": "0.1.12", + "@backstage/plugin-gitops-profiles": "0.3.36", + "@backstage/plugin-gocd": "0.1.24", + "@backstage/plugin-graphiql": "0.2.50", + "@backstage/plugin-graphql-backend": "0.1.35", + "@backstage/plugin-graphql-voyager": "0.1.3", + "@backstage/plugin-home": "0.5.2", + "@backstage/plugin-home-react": "0.0.0", + "@backstage/plugin-ilert": "0.2.7", + "@backstage/plugin-jenkins": "0.8.0", + "@backstage/plugin-jenkins-backend": "0.2.0", "@backstage/plugin-jenkins-common": "0.1.15", - "@backstage/plugin-kafka": "0.3.17", - "@backstage/plugin-kafka-backend": "0.2.37", - "@backstage/plugin-kubernetes": "0.8.0", - "@backstage/plugin-kubernetes-backend": "0.10.0", - "@backstage/plugin-kubernetes-common": "0.6.2", - "@backstage/plugin-lighthouse": "0.4.2", - "@backstage/plugin-lighthouse-backend": "0.2.0", + "@backstage/plugin-kafka": "0.3.18", + "@backstage/plugin-kafka-backend": "0.2.38", + "@backstage/plugin-kubernetes": "0.9.0", + "@backstage/plugin-kubernetes-backend": "0.11.0", + "@backstage/plugin-kubernetes-common": "0.6.3", + "@backstage/plugin-lighthouse": "0.4.3", + "@backstage/plugin-lighthouse-backend": "0.2.1", "@backstage/plugin-lighthouse-common": "0.1.1", - "@backstage/plugin-linguist": "0.1.2", - "@backstage/plugin-linguist-backend": "0.2.1", + "@backstage/plugin-linguist": "0.1.3", + "@backstage/plugin-linguist-backend": "0.2.2", "@backstage/plugin-linguist-common": "0.1.0", - "@backstage/plugin-microsoft-calendar": "0.1.2", - "@backstage/plugin-newrelic": "0.3.35", - "@backstage/plugin-newrelic-dashboard": "0.2.10", - "@backstage/plugin-octopus-deploy": "0.1.1", - "@backstage/plugin-org": "0.6.7", - "@backstage/plugin-org-react": "0.1.6", - "@backstage/plugin-pagerduty": "0.5.10", - "@backstage/plugin-periskop": "0.1.15", - "@backstage/plugin-periskop-backend": "0.1.15", - "@backstage/plugin-permission-backend": "0.5.19", + "@backstage/plugin-microsoft-calendar": "0.1.3", + "@backstage/plugin-newrelic": "0.3.36", + "@backstage/plugin-newrelic-dashboard": "0.2.11", + "@backstage/plugin-octopus-deploy": "0.2.0", + "@backstage/plugin-org": "0.6.8", + "@backstage/plugin-org-react": "0.1.7", + "@backstage/plugin-pagerduty": "0.5.11", + "@backstage/plugin-periskop": "0.1.16", + "@backstage/plugin-periskop-backend": "0.1.16", + "@backstage/plugin-permission-backend": "0.5.20", "@backstage/plugin-permission-common": "0.7.5", - "@backstage/plugin-permission-node": "0.7.7", + "@backstage/plugin-permission-node": "0.7.8", "@backstage/plugin-permission-react": "0.4.12", - "@backstage/plugin-playlist": "0.1.8", - "@backstage/plugin-playlist-backend": "0.3.0", + "@backstage/plugin-playlist": "0.1.9", + "@backstage/plugin-playlist-backend": "0.3.1", "@backstage/plugin-playlist-common": "0.1.6", - "@backstage/plugin-proxy-backend": "0.2.38", - "@backstage/plugin-puppetdb": "0.1.0", - "@backstage/plugin-rollbar": "0.4.17", - "@backstage/plugin-rollbar-backend": "0.1.41", - "@backstage/plugin-scaffolder": "1.13.0", - "@backstage/plugin-scaffolder-backend": "1.13.0", - "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.1.0", - "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.2.19", - "@backstage/plugin-scaffolder-backend-module-gitlab": "0.1.0", - "@backstage/plugin-scaffolder-backend-module-rails": "0.4.12", - "@backstage/plugin-scaffolder-backend-module-sentry": "0.1.4", - "@backstage/plugin-scaffolder-backend-module-yeoman": "0.2.17", - "@backstage/plugin-scaffolder-common": "1.2.7", - "@backstage/plugin-scaffolder-node": "0.1.2", - "@backstage/plugin-scaffolder-react": "1.3.0", - "@backstage/plugin-search": "1.2.0", - "@backstage/plugin-search-backend": "1.3.0", - "@backstage/plugin-search-backend-module-catalog": "0.1.0", - "@backstage/plugin-search-backend-module-elasticsearch": "1.2.0", - "@backstage/plugin-search-backend-module-explore": "0.1.0", - "@backstage/plugin-search-backend-module-pg": "0.5.5", - "@backstage/plugin-search-backend-module-techdocs": "0.1.0", - "@backstage/plugin-search-backend-node": "1.2.0", + "@backstage/plugin-proxy-backend": "0.2.39", + "@backstage/plugin-puppetdb": "0.1.1", + "@backstage/plugin-rollbar": "0.4.18", + "@backstage/plugin-rollbar-backend": "0.1.42", + "@backstage/plugin-scaffolder": "1.13.1", + "@backstage/plugin-scaffolder-backend": "1.14.0", + "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.1.2", + "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.2.21", + "@backstage/plugin-scaffolder-backend-module-gitlab": "0.2.0", + "@backstage/plugin-scaffolder-backend-module-rails": "0.4.14", + "@backstage/plugin-scaffolder-backend-module-sentry": "0.1.5", + "@backstage/plugin-scaffolder-backend-module-yeoman": "0.2.18", + "@backstage/plugin-scaffolder-common": "1.3.0", + "@backstage/plugin-scaffolder-node": "0.1.3", + "@backstage/plugin-scaffolder-react": "1.4.0", + "@backstage/plugin-search": "1.3.0", + "@backstage/plugin-search-backend": "1.3.1", + "@backstage/plugin-search-backend-module-catalog": "0.1.1", + "@backstage/plugin-search-backend-module-elasticsearch": "1.3.0", + "@backstage/plugin-search-backend-module-explore": "0.1.1", + "@backstage/plugin-search-backend-module-pg": "0.5.6", + "@backstage/plugin-search-backend-module-techdocs": "0.1.1", + "@backstage/plugin-search-backend-node": "1.2.1", "@backstage/plugin-search-common": "1.2.3", - "@backstage/plugin-search-react": "1.5.2", - "@backstage/plugin-sentry": "0.5.2", - "@backstage/plugin-shortcuts": "0.3.9", - "@backstage/plugin-sonarqube": "0.6.6", - "@backstage/plugin-sonarqube-backend": "0.1.9", + "@backstage/plugin-search-react": "1.6.0", + "@backstage/plugin-sentry": "0.5.3", + "@backstage/plugin-shortcuts": "0.3.10", + "@backstage/plugin-sonarqube": "0.6.7", + "@backstage/plugin-sonarqube-backend": "0.1.10", "@backstage/plugin-sonarqube-react": "0.1.5", - "@backstage/plugin-splunk-on-call": "0.4.6", - "@backstage/plugin-stack-overflow": "0.1.13", - "@backstage/plugin-stack-overflow-backend": "0.2.0", - "@backstage/plugin-stackstorm": "0.1.1", - "@backstage/plugin-tech-insights": "0.3.9", - "@backstage/plugin-tech-insights-backend": "0.5.10", - "@backstage/plugin-tech-insights-backend-module-jsonfc": "0.1.28", + "@backstage/plugin-splunk-on-call": "0.4.7", + "@backstage/plugin-stack-overflow": "0.1.15", + "@backstage/plugin-stack-overflow-backend": "0.2.1", + "@backstage/plugin-stackstorm": "0.1.2", + "@backstage/plugin-tech-insights": "0.3.10", + "@backstage/plugin-tech-insights-backend": "0.5.11", + "@backstage/plugin-tech-insights-backend-module-jsonfc": "0.1.29", "@backstage/plugin-tech-insights-common": "0.2.10", - "@backstage/plugin-tech-insights-node": "0.4.2", - "@backstage/plugin-tech-radar": "0.6.3", - "@backstage/plugin-techdocs": "1.6.1", - "@backstage/plugin-techdocs-addons-test-utils": "1.0.12", - "@backstage/plugin-techdocs-backend": "1.6.1", - "@backstage/plugin-techdocs-module-addons-contrib": "1.0.12", - "@backstage/plugin-techdocs-node": "1.7.0", - "@backstage/plugin-techdocs-react": "1.1.5", - "@backstage/plugin-todo": "0.2.19", - "@backstage/plugin-todo-backend": "0.1.41", - "@backstage/plugin-user-settings": "0.7.2", - "@backstage/plugin-user-settings-backend": "0.1.8", - "@backstage/plugin-vault": "0.1.11", - "@backstage/plugin-vault-backend": "0.3.0", - "@backstage/plugin-xcmetrics": "0.2.37", - "@backstage/plugin-analytics-module-ga4": "0.0.0" + "@backstage/plugin-tech-insights-node": "0.4.3", + "@backstage/plugin-tech-radar": "0.6.4", + "@backstage/plugin-techdocs": "1.6.2", + "@backstage/plugin-techdocs-addons-test-utils": "1.0.13", + "@backstage/plugin-techdocs-backend": "1.6.2", + "@backstage/plugin-techdocs-module-addons-contrib": "1.0.13", + "@backstage/plugin-techdocs-node": "1.7.1", + "@backstage/plugin-techdocs-react": "1.1.6", + "@backstage/plugin-todo": "0.2.20", + "@backstage/plugin-todo-backend": "0.1.42", + "@backstage/plugin-user-settings": "0.7.3", + "@backstage/plugin-user-settings-backend": "0.1.9", + "@backstage/plugin-vault": "0.1.12", + "@backstage/plugin-vault-backend": "0.3.1", + "@backstage/plugin-xcmetrics": "0.2.38" }, "changesets": [ - "afraid-shirts-train", - "backend-like-a-tattoo", - "beige-tigers-matter", - "brown-eyes-yell", - "calm-wolves-taste", - "chilly-fireants-type", - "clean-lobsters-brake", - "cold-drinks-exercise", - "create-app-1682437922", - "curvy-months-appear", - "dry-boats-sniff", - "dull-wombats-stare", - "eighty-olives-live", - "fifty-laws-count", - "five-tigers-whisper", - "fresh-moons-unite", - "funny-trains-sniff", - "good-lions-approve", - "green-cheetahs-cover", - "healthy-ladybugs-chew", - "honest-countries-deny", - "hungry-foxes-divide", - "lazy-keys-work", - "mighty-bears-glow", - "mighty-cows-greet", - "modern-pumpkins-join", - "moody-lizards-beam", - "nine-ties-smoke", - "olive-turkeys-switch", - "polite-dingos-train", - "pretty-gifts-greet", - "quick-flies-guess", - "red-cheetahs-invite", - "rotten-chefs-jog", - "serious-hornets-remember", - "six-mails-shout", - "slimy-turkeys-return", - "soft-readers-exist", - "swift-fishes-run", - "tame-games-rule", - "thick-parents-pump", - "tough-moles-whisper", - "unlucky-plants-give", - "warm-lamps-tease" + "angry-jobs-ring", + "beige-kangaroos-suffer", + "beige-zebras-walk", + "breezy-kids-obey", + "chatty-ads-attack", + "clean-months-bake", + "create-app-1684855417", + "curvy-years-smoke", + "few-oranges-complain", + "few-pugs-jam", + "khaki-radios-teach", + "light-cows-bow", + "little-boats-think", + "long-lobsters-brake", + "lovely-impalas-sell", + "lucky-keys-behave", + "perfect-readers-attack", + "selfish-mugs-study", + "shaggy-gorillas-occur", + "short-seahorses-kiss", + "silver-cars-type", + "violet-pots-push", + "weak-snails-spar", + "weak-snails-spark", + "weak-snails-sparkl", + "weak-snails-sparkle", + "yellow-crews-float" ] } diff --git a/.changeset/pretty-gifts-greet.md b/.changeset/pretty-gifts-greet.md deleted file mode 100644 index 965f714a61..0000000000 --- a/.changeset/pretty-gifts-greet.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-home': patch ---- - -Add missing @rjsf/core dependency diff --git a/.changeset/quick-flies-guess.md b/.changeset/quick-flies-guess.md deleted file mode 100644 index 73e5589b98..0000000000 --- a/.changeset/quick-flies-guess.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-app-api': patch ---- - -Added `FrontendHostDiscovery` for config driven discovery implementation diff --git a/.changeset/quiet-bikes-smash.md b/.changeset/quiet-bikes-smash.md deleted file mode 100644 index ca751adaf7..0000000000 --- a/.changeset/quiet-bikes-smash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-openapi-utils': patch ---- - -Corrected resolution of parameter nested schema to use central schemas. diff --git a/.changeset/red-cheetahs-invite.md b/.changeset/red-cheetahs-invite.md deleted file mode 100644 index ef1711c761..0000000000 --- a/.changeset/red-cheetahs-invite.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-octopus-deploy': minor ---- - -Added support for Octopus Deploy spaces. The octopus.com/project-id annotation can now (optionally) be prefixed by a space identifier, for example. Spaces-1/Projects-102. -Also note that some of this plugins exported API's have changed to accommodate this change, changing from separate arguments to a single object. diff --git a/.changeset/rotten-chefs-jog.md b/.changeset/rotten-chefs-jog.md deleted file mode 100644 index 120520c087..0000000000 --- a/.changeset/rotten-chefs-jog.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@backstage/plugin-scaffolder-react': patch -'@backstage/plugin-scaffolder': patch ---- - -Improvements to the `scaffolder/next` buttons UX: - -- Added padding around the "Create" button in the `Stepper` component -- Added a button bar that includes the "Cancel" and "Start Over" buttons to the `OngoingTask` component. The state of these buttons match their existing counter parts in the Context Menu -- Added a "Show Button Bar"/"Hide Button Bar" item to the `ContextMenu` component diff --git a/.changeset/selfish-mugs-study.md b/.changeset/selfish-mugs-study.md new file mode 100644 index 0000000000..0a2152aecc --- /dev/null +++ b/.changeset/selfish-mugs-study.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes': patch +--- + +Add errors to PodDrawer diff --git a/.changeset/serious-hornets-remember.md b/.changeset/serious-hornets-remember.md deleted file mode 100644 index 05221cd055..0000000000 --- a/.changeset/serious-hornets-remember.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-circleci': patch ---- - -Hide empty time field data for queued builds which haven't started yet diff --git a/.changeset/shaggy-gorillas-occur.md b/.changeset/shaggy-gorillas-occur.md new file mode 100644 index 0000000000..ce7c2aba3b --- /dev/null +++ b/.changeset/shaggy-gorillas-occur.md @@ -0,0 +1,16 @@ +--- +'@backstage/plugin-linguist-backend': minor +--- + +**BREAKING**: Removed public constructor from `LinguistBackendApi`. Removed export of `LinguistBackendDatabase` and `LinguistBackendStore` + +Several improvements to the Linguist backend have been made: + +- Added tests for the `LinguistBackendDatabase` and `LinguistBackendApi` +- Added support for using SQLite as a database, helpful for local development +- Removed the default from the `processes_date` column +- Converted the `LinguistBackendApi` into an Interface +- Added the `LinguistBackendClient` which implements the `LinguistBackendApi` Interface +- Unprocessed entities will get processed before stale entities +- Entities in the Linguist database but not in the Catalog anymore will be deleted +- Improved the README's headings diff --git a/.changeset/shaggy-terms-travel.md b/.changeset/shaggy-terms-travel.md new file mode 100644 index 0000000000..a131608487 --- /dev/null +++ b/.changeset/shaggy-terms-travel.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend-module-pg': patch +--- + +Updated Postgres search query filter in DatabaseDocumentStore to support field value search in array. diff --git a/.changeset/short-seahorses-kiss.md b/.changeset/short-seahorses-kiss.md new file mode 100644 index 0000000000..0127e4c575 --- /dev/null +++ b/.changeset/short-seahorses-kiss.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Change deprecated local references to import from shared `plugin-techdocs-react` plugin diff --git a/.changeset/silver-cars-type.md b/.changeset/silver-cars-type.md new file mode 100644 index 0000000000..0636eccd8f --- /dev/null +++ b/.changeset/silver-cars-type.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-github-actions': minor +--- + +Added support GitHub Enterprise hosted repositories. + +**BREAKING**: The `GithubActionsClient` is updated to take an `scmAuthApi` instead of the previous `githubAuthApi`. This does not require any code changes unless you construct your own `GithubActionsClient` diff --git a/.changeset/silver-ducks-drum.md b/.changeset/silver-ducks-drum.md new file mode 100644 index 0000000000..6cca57fdd4 --- /dev/null +++ b/.changeset/silver-ducks-drum.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +`EntityAutocompletePicker` add `initialSelectedOptions` prop diff --git a/.changeset/six-mails-shout.md b/.changeset/six-mails-shout.md deleted file mode 100644 index f803e0858e..0000000000 --- a/.changeset/six-mails-shout.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-shortcuts': patch ---- - -Marked `LocalStoredShortcuts` as deprecated, replacing it with `DefaultShortcutsApi` whose naming more clearly suggests that the shortcuts aren't necessarily stored locally (it depends on the storage implementation). diff --git a/.changeset/slimy-turkeys-return.md b/.changeset/slimy-turkeys-return.md deleted file mode 100644 index db10000509..0000000000 --- a/.changeset/slimy-turkeys-return.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -'@backstage/plugin-permission-node': patch ---- - -`createPermissionIntegrationRouter` now accepts rules and permissions for multiple resource types. Example: - -```typescript -createPermissionIntegrationRouter({ - resources: [ - { - resourceType: 'resourceType-1', - permissions: permissionsResourceType1, - rules: rulesResourceType1, - }, - { - resourceType: 'resourceType-2', - permissions: permissionsResourceType2, - rules: rulesResourceType2, - }, - ], -}); -``` diff --git a/.changeset/soft-readers-exist.md b/.changeset/soft-readers-exist.md deleted file mode 100644 index 8fce13caca..0000000000 --- a/.changeset/soft-readers-exist.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Added `HostDiscovery` to supersede deprecated `SingleHostDiscovery` (deprecated due to name) diff --git a/.changeset/swift-fishes-run.md b/.changeset/swift-fishes-run.md deleted file mode 100644 index ee3d1217ed..0000000000 --- a/.changeset/swift-fishes-run.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Bump minimum required version of `vm2` to be 3.9.17 diff --git a/.changeset/tame-games-rule.md b/.changeset/tame-games-rule.md deleted file mode 100644 index 408c8ca14b..0000000000 --- a/.changeset/tame-games-rule.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Pin some octokit dependencies to avoid failing typescript build under `tsc:full` diff --git a/.changeset/thick-parents-pump.md b/.changeset/thick-parents-pump.md deleted file mode 100644 index ba65e10610..0000000000 --- a/.changeset/thick-parents-pump.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch -'@backstage/plugin-scaffolder-node': patch ---- - -Update typing for `RouterOptions::actions` and `ScaffolderActionsExtensionPoint::addActions` to allow any kind of action being assigned to it. diff --git a/.changeset/thin-ways-exist.md b/.changeset/thin-ways-exist.md deleted file mode 100644 index fd1ecb62a4..0000000000 --- a/.changeset/thin-ways-exist.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search-react': patch ---- - -Fix text-overflow UI issue for Lifecycle spans in SearchFilter checkbox labels. diff --git a/.changeset/three-guests-beam.md b/.changeset/three-guests-beam.md new file mode 100644 index 0000000000..b46e80a13c --- /dev/null +++ b/.changeset/three-guests-beam.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +`EntityLifecycleFilter` loads data using the facets endpoint diff --git a/.changeset/tough-moles-whisper.md b/.changeset/tough-moles-whisper.md deleted file mode 100644 index 14dd76c116..0000000000 --- a/.changeset/tough-moles-whisper.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-tech-radar': patch ---- - -Added the ability to display a timeline to each entry in the details box diff --git a/.changeset/twelve-zebras-repair.md b/.changeset/twelve-zebras-repair.md deleted file mode 100644 index 8d74080c38..0000000000 --- a/.changeset/twelve-zebras-repair.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search-backend': patch ---- - -Added an OpenAPI 3.0 spec and enforced schema-first model on the router. diff --git a/.changeset/unlucky-plants-give.md b/.changeset/unlucky-plants-give.md deleted file mode 100644 index 504b475727..0000000000 --- a/.changeset/unlucky-plants-give.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Start capturing sidebar click events in analytics by default. diff --git a/.changeset/violet-pots-push.md b/.changeset/violet-pots-push.md new file mode 100644 index 0000000000..f0074ed82e --- /dev/null +++ b/.changeset/violet-pots-push.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-stack-overflow': patch +'@backstage/plugin-home-react': minor +'@backstage/plugin-home': patch +--- + +Extract new plugin-home-react package and deprecate createCardExtension in plugin-home diff --git a/.changeset/warm-lamps-tease.md b/.changeset/warm-lamps-tease.md deleted file mode 100644 index 954197dd13..0000000000 --- a/.changeset/warm-lamps-tease.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-kubernetes-backend': minor ---- - -Update `aws-sdk` client from v2 to v3. - -**BREAKING**: The `AwsIamKubernetesAuthTranslator` class no longer exposes the following methods `awsGetCredentials`, `getBearerToken`, `getCredentials` and `validCredentials`. There is no replacement for these methods. diff --git a/.changeset/weak-snails-spar.md b/.changeset/weak-snails-spar.md new file mode 100644 index 0000000000..3cd930d5b0 --- /dev/null +++ b/.changeset/weak-snails-spar.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-addons-test-utils': patch +--- + +Avoiding re-running tests on cleanup. diff --git a/.changeset/weak-snails-spark.md b/.changeset/weak-snails-spark.md new file mode 100644 index 0000000000..c82626ea39 --- /dev/null +++ b/.changeset/weak-snails-spark.md @@ -0,0 +1,5 @@ +--- +'@backstage/test-utils': minor +--- + +Test App Wrapper is now using `UnifiedThemeProvider` for supporting MUI v5 next to MUI v4 in tests. diff --git a/.changeset/weak-snails-sparkl.md b/.changeset/weak-snails-sparkl.md new file mode 100644 index 0000000000..9bbc7d843b --- /dev/null +++ b/.changeset/weak-snails-sparkl.md @@ -0,0 +1,17 @@ +--- +'@backstage/app-defaults': minor +'@backstage/theme': minor +--- + +**MUI v5 Support:** Adding platform-wide support for MUI v5 allowing a transition phase for migrating central plugins & components over. We still support v4 instances & plugins by adding a + +To allow the future support of plugins & components using MUI v5 you want to upgrade your `AppTheme`'s to using the `UnifiedThemeProvider` + +```diff + Provider: ({ children }) => ( +- +- {children} +- ++ + ), +``` diff --git a/.changeset/weak-snails-sparkle.md b/.changeset/weak-snails-sparkle.md new file mode 100644 index 0000000000..95a2255e56 --- /dev/null +++ b/.changeset/weak-snails-sparkle.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Enforcing MUI v5 specific linting to minimize bundle size. diff --git a/.changeset/yellow-crews-float.md b/.changeset/yellow-crews-float.md new file mode 100644 index 0000000000..ce3ce84ad7 --- /dev/null +++ b/.changeset/yellow-crews-float.md @@ -0,0 +1,11 @@ +--- +'@backstage/plugin-analytics-module-ga4': patch +'@backstage/plugin-entity-validation': patch +'@backstage/plugin-devtools-backend': patch +'@backstage/plugin-linguist-backend': patch +'@backstage/plugin-techdocs-react': patch +'@backstage/plugin-dynatrace': patch +'@backstage/plugin-pagerduty': patch +--- + +Update plugin installation docs to be more consistent across documentations diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3880a0facd..7518fbab96 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -56,6 +56,7 @@ yarn.lock @backstage/maintainers @back /plugins/gcalendar @backstage/maintainers @szubster @ptychu @kielosz @alexrybch /plugins/git-release-manager @backstage/maintainers @erikengervall /plugins/home @backstage/discoverability-maintainers +/plugins/home-* @backstage/discoverability-maintainers /plugins/ilert @backstage/maintainers @yacut /plugins/jenkins @backstage/maintainers @timja /plugins/jenkins-backend @backstage/maintainers @timja diff --git a/.github/uffizzi/docker-compose.uffizzi.yml b/.github/uffizzi/docker-compose.uffizzi.yml index 76a7b4eafc..f2e9bbeee6 100644 --- a/.github/uffizzi/docker-compose.uffizzi.yml +++ b/.github/uffizzi/docker-compose.uffizzi.yml @@ -14,6 +14,7 @@ services: POSTGRES_PORT: 5432 POSTGRES_USER: postgres POSTGRES_PASSWORD: kiTMoTsiEuyQ43GrL4Hv + REF_NAME: ${GITHUB_SHA} NODE_ENV: production deploy: resources: diff --git a/.github/uffizzi/uffizzi.production.app-config.yaml b/.github/uffizzi/uffizzi.production.app-config.yaml index 30cffa11c9..3b24c20b3d 100644 --- a/.github/uffizzi/uffizzi.production.app-config.yaml +++ b/.github/uffizzi/uffizzi.production.app-config.yaml @@ -28,6 +28,7 @@ backend: credentials: true csp: connect-src: ["'self'", 'http:', 'https:'] + img-src: ["'self'", 'data:', 'https://cdnjs.cloudflare.com'] # Content-Security-Policy directives follow the Helmet format: https://helmetjs.github.io/#reference # Default Helmet Content-Security-Policy values can be removed by setting the key to false @@ -41,15 +42,18 @@ auth: catalog: locations: - type: url - target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/all.yaml + target: https://github.com/backstage/backstage/blob/${REF_NAME}/packages/catalog-model/examples/all.yaml - type: url - target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme-corp.yaml + target: https://github.com/backstage/backstage/blob/${REF_NAME}/plugins/techdocs-backend/examples/documented-component-uffizzi/catalog-info.yaml + + - type: url + target: https://github.com/backstage/backstage/blob/${REF_NAME}/packages/catalog-model/examples/acme-corp.yaml rules: - allow: [User, Group] - type: url - target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/all-templates.yaml + target: https://github.com/backstage/backstage/blob/${REF_NAME}/plugins/scaffolder-backend/sample-templates/all-templates.yaml rules: - allow: [Template] @@ -124,7 +128,7 @@ proxy: techdocs: builder: 'local' # Alternatives - 'external' generator: - runIn: 'docker' + runIn: 'local' # dockerImage: my-org/techdocs # use a custom docker image # pullImage: true # or false to disable automatic pulling of image (e.g. if custom docker login is required) publisher: diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index 83fba8aa56..68fbdabb00 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -188,6 +188,7 @@ learnings Leasot lerna Lerna +lightbox limitranges LocalStack lockdown @@ -247,6 +248,7 @@ Olausson Oldsberg onboarding Onboarding +OpenSearch OpenShift orgs padding @@ -314,6 +316,7 @@ scaffolded scaffolder Scaffolder scrollbar +sdks seb semlas semver @@ -341,6 +344,8 @@ stdout storable stringified stringify +subcommand +subcommands subcomponent subcomponents subfolder @@ -389,6 +394,7 @@ transpilers truthy TSDoc typeahead +Uffizzi ui unbreak Unconference diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 86ac320ac7..ec0a791dcb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -96,7 +96,7 @@ jobs: run: node scripts/verify-api-reference.js - name: verify openapi yaml file matches generated ts file - run: yarn backstage-repo-tools schema:openapi:verify + run: yarn backstage-repo-tools schema openapi verify - name: verify doc links run: node scripts/verify-links.js diff --git a/.github/workflows/uffizzi-build.yml b/.github/workflows/uffizzi-build.yml index ee629bbafe..1b031f50ad 100644 --- a/.github/workflows/uffizzi-build.yml +++ b/.github/workflows/uffizzi-build.yml @@ -81,7 +81,7 @@ jobs: BACKSTAGE_IMAGE=$(echo ${{ needs.build-backstage.outputs.tags }}) export BACKSTAGE_IMAGE # Render simple template from environment variables. - envsubst '$BACKSTAGE_IMAGE' < .github/uffizzi/docker-compose.uffizzi.yml > docker-compose.rendered.yml + envsubst '$BACKSTAGE_IMAGE $GITHUB_SHA' < .github/uffizzi/docker-compose.uffizzi.yml > docker-compose.rendered.yml cat docker-compose.rendered.yml - name: Upload Rendered Compose File as Artifact uses: actions/upload-artifact@v3 diff --git a/.github/workflows/verify_e2e-kubernetes.yml b/.github/workflows/verify_e2e-kubernetes.yml index 6c01999506..87056957f5 100644 --- a/.github/workflows/verify_e2e-kubernetes.yml +++ b/.github/workflows/verify_e2e-kubernetes.yml @@ -35,7 +35,7 @@ jobs: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: bootstrap kind - uses: helm/kind-action@v1.5.0 + uses: helm/kind-action@v1.7.0 - name: kubernetes test working-directory: packages/backend-common diff --git a/.gitignore b/.gitignore index f3c687d49c..c0bf195947 100644 --- a/.gitignore +++ b/.gitignore @@ -155,4 +155,8 @@ tsconfig.tmp.json # Lighthouse CI Reports **/.lighthouseci/* -!**/.lighthouseci/scripts \ No newline at end of file +!**/.lighthouseci/scripts + +# VS Code backing up svg files +*svg.bkp +*svg.dtmp \ No newline at end of file diff --git a/ADOPTERS.md b/ADOPTERS.md index b66fbea0f6..98e156c9d4 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -14,7 +14,7 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/ | [American Airlines](https://www.aa.com) | [@paulpach](https://github.com/paulpach) | Central place for developers to develop and maintain applications | | [Kiwi.com](https://kiwi.com) | [@aexvir](https://github.com/aexvir) | Replacing the frontend of [The Zoo](https://github.com/kiwicom/the-zoo), their service registry. | | [Voi](https://www.voiscooters.com/) | [@K-Phoen](https://github.com/K-Phoen) | Developer portal, main gateway to our infrastructure, documentation and internal tooling. | -| [Talkdesk](https://www.talkdesk.com) | [@jaime-talkdesk](https://github.com/jaime-talkdesk) | Initial work for Engineering Portal and Self Provisioning to R&D | +| [Talkdesk](https://www.talkdesk.com) | [@atmcarmo](https://github.com/atmcarmo) | Engineering Portal with all of our apps and services, overview about our deployment regions and scaffolding new services. | | [Wealthsimple](https://www.wealthsimple.com) | [@andrewthauer](https://github.com/andrewthauer) | Developer portal, service catalog, documentation and tooling | | [Grab](https://www.grab.com) | [@althafh](https://github.com/althafh) | Initial work as a unified interface for all of Grab's internal tooling | | [Telenor Sweden](https://www.telenor.se) | [@O5ten](https://github.com/O5ten) | Building a developer portal for scaffolding projects towards our unified build environment and microservice stacks | @@ -132,7 +132,7 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/ | [Tink](https://tink.com/) | [Sebastian Olsson](https://github.com/Sebelino), [Błażej Szum](https://github.com/blazejszumtink), [Anders Eurenius Runvald](https://github.com/anders-er-at-tink) | Internal developer portal which provides templates for creating new Java or Go microservices seamlessly. Also includes a tech radar and a visualization of our CD pipeline. | | [Brandwatch](https://brandwatch.com) | [Stefan Buck](https://github.com/stefanbuck) | Our primary focus is on the service catalog. Backstage is replacing our homemade service catalog. The switch was quite simple due to the catalog processor API. | | [Laybuy](https://www.laybuy.com) | [Chris Simmons](https://github.com/contrarianchris) | Backstage is the heart of Laybuy’s new centralised Development Platform, bringing disparate development tools and experiences into a single easy-to-use portal. It simplifies software and API discovery, project scaffolding, and technical documentation, enabling us to embrace golden path development and automate software standards. | -| [Sendinblue](https://engineering.sendinblue.com/) | [Tanguy Antoine](mailto:antoine.tanguy@sendinblue.com) | Helps us drive the change at scale. Puts light on services, resources, and dependencies. One tool that rules them all through plugins we created for that purpose. We are aiming to put Backstage at the center of every developer's work (Actionable items, Debugging, Monitoring, Provisioning, etc...) to improve their happiness | +| [Brevo](https://engineering.brevo.com/) | [Tanguy Antoine](mailto:antoine.tanguy@brevo.com) | Helps us drive the change at scale. Puts light on services, resources, and dependencies. One tool that rules them all through plugins we created for that purpose. We are aiming to put Backstage at the center of every developer's work (Actionable items, Debugging, Monitoring, Provisioning, etc...) to improve their happiness | | [SafetyCulture](https://safetyculture.com/) | [@R-cen](https://github.com/R-cen), [@lachlancooper](https://github.com/lachlancooper), [@hkf57](https://github.com/hkf57) | Internal developer portal to provide a centralized place for engineers to see an overview of their team's services and information related to the service from other systems. Initially focused on the software catalog, techdocs and search. | | [Sana Life Science](https://sanalifescience.com) | [Joe Hillyard](mailto:joe@sanalifescience.com) | API Catalog, Tools Management & Control Hub | | [Ndustrial](https://ndustrial.io) | [Jonathan Skubic](mailto:jonathan@ndustrial.io) | Software Project Catalog | @@ -243,4 +243,9 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/ | [Chartboost](https://www.chartboost.com)| [@brucearctor](https://github.com/brucearctor), [@ArtemChekunov](https://github.com/ArtemChekunov) | We are building our internal develper portal on top of Backstage.| | [Quantum Metric](https://www.quantummetric.com/) | [Eric Irwin](https://www.linkedin.com/in/ericirwin1124/) | Backstage is used within our Developer Experience Platform (DXP) in order to increase self-service, standardization and discoverability across our Engineering teams. | | [VodafoneZiggo](https://www.vodafoneziggo.nl/) | [Peter Macdonald](https://github.com/Parsifal-M) | We use Backstage as our go-to platform for managing our internal tools and services. With Backstage, we can easily discover and access all the services we need to do our work, whether it's deploying code, managing infrastructure, or accessing documentation. We appreciate the standardized, consistent interface and the ability to easily create custom plugins to integrate with our existing workflows. Overall, Backstage is streamlining our internal operations and helps us work more efficiently as a team. | -| [Volvo Cars](https://www.volvocars.com) | [Martin Wänerskär](https://github.com/martin-wanerskar) | Internal developer portal with intent to unify infrastructure tooling, services, and developer documentation under a single, easy-to-use interface. | \ No newline at end of file +| [Volvo Cars](https://www.volvocars.com) | [Martin Wänerskär](https://github.com/martin-wanerskar) | Internal developer portal with intent to unify infrastructure tooling, services, and developer documentation under a single, easy-to-use interface. | +| [Mercantil Andina](https://www.mercantilandina.com.ar/) | [Sebastian Paredero](https://www.linkedin.com/in/sebastian-paredero/), [Matias Javier Gomez](https://www.linkedin.com/in/matias-javier-gomez-140540a3/), [Gustavo Wilgenhoff](https://github.com/wilgustavo) | Developer portal: documentation, service templates, org structure, service catalog, plugins for integration with internal systems. | +| [Livelo](https://www.livelo.com.br) | [Felipe Nardon](https://www.linkedin.com/in/felipe-nardon-dos-santos/), [Yves Galvão](https://www.linkedin.com/in/yvesgalvao/), [Isaque Rocha](https://www.linkedin.com/in/isaque-rocha/) | Internal platform that aims to reduce the teams' cognitive load through self-service, abstracting processes that are now part of the teams' daily lives, enabling a centralized management of documentation, catalog, metrics and knowledge. | +| [Worten](https://www.worten.pt) | [@elisiariocouto](https://github.com/elisiariocouto) | We are proud to be an adopter of Backstage. Our goal is to make our Backstage installation the go-to location for every developer. To achieve this, we developed a custom plugin to populate Backstage's catalog with information from our internal deployment tool. As a result, we now have full visibility of all Worten systems, components, APIs, messaging topics, and documentation. We also migrated the internal deployment tool's Web UI to Backstage. Currently, we are working on Backstage's Software Templates feature. | +| [Inventa](https://www.inventa.shop) | [João Munhoz](https://github.com/joaovitormunhoz), [Lucca Fonte](https://github.com/luccafonte) | We use Backstage at Inventa to share knowledge between squads, in the form of technical documentation, API contracts, and service status/ownership info, fomenting a self-service and scalable engineering culture. We also developed a plugin that allows us to have a centralized view of all the engineering tools we have for each environment, making it easy to access each one of our tools and increasing productivity. | +| [PITS Global Data Recovery Services](https://www.pitsdatarecovery.net/) | [@pheianox](https://github.com/pheianox) | The internal developer portal seeks to combine infrastructure tooling, services, and developer documentation into a single, user-friendly interface. By streamlining these components, the portal enhances productivity and simplifies the development process for the internal team. | diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7828791080..ed1baa133a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -92,10 +92,14 @@ For those contributors who have earned write access to the repository, when a pu ## Code of Conduct -This project adheres to the [Spotify FOSS Code of Conduct][code-of-conduct]. By participating, you are expected to honor this code. +This project adheres to the [CNCF Code of Conduct][code-of-conduct]. By participating, you are expected to honor this code. [code-of-conduct]: https://github.com/backstage/backstage/blob/master/CODE_OF_CONDUCT.md ## Security Issues? See [SECURITY](SECURITY.md). + +## Accessibility + +We encourage you to catch any accessibility issues already in the development phase of new features to Backstage, see our [Accessibility documentation](./docs/accessibility/index.md) for more details. diff --git a/OWNERS.md b/OWNERS.md index 0a567ee269..25ada5853e 100644 --- a/OWNERS.md +++ b/OWNERS.md @@ -77,6 +77,20 @@ Scope: The TechDocs plugin and related tooling | Morgan Bentell | Spotify | Pulp Fiction | [agentbellnorm](http://github.com/agentbellnorm) | morganbentell#9030 | | Raghunandan Balachandran | Spotify | Pulp Fiction | [soapraj](http://github.com/soapraj) | raghunandanb#1114 | +## Incubating Project Areas + +These incubating project areas have shared ownership with @backstage/maintainers. + +### OpenAPI Tooling + +Team: @backstage/openapi-tooling-maintainers + +Scope: Tooling for frontend and backend schema-first OpenAPI development. + +| Name | Organization | GitHub | Discord | +| -------------- | ------------ | --------------------------------------- | ------------- | +| Aramis Sennyey | | [sennyeya](https://github.com/sennyeya) | `Aramis#7984` | + ## Sponsors | Name | Organization | GitHub | Email | @@ -92,6 +106,7 @@ Scope: The TechDocs plugin and related tooling | Adam Harvey | Cisco | [adamdmharvey](https://github.com/adamdmharvey) | `adamharvey#3739` | | Andre Wanlin | Keyloop | [awanlin](https://github.com/awanlin) | `Ahhhndre#3095` | | Andrew Thauer | Wealthsimple | [andrewthauer](https://github.com/andrewthauer) | `andrewthauer#3060` | +| Aramis Sennyey | | [sennyeya](https://github.com/sennyeya) | `Aramis#7984` | | Brian Fletcher | Roadie.io | [punkle](https://github.com/punkle) | `Brian Fletcher#7051` | | Carlos Esteban Lopez Jaramillo | VMWare | [luchillo17](https://github.com/luchillo17) | `luchillo17#8777` | | David Tuite | Roadie.io | [dtuite](https://github.com/dtuite) | `David Tuite (roadie.io)#1010` | diff --git a/README.md b/README.md index 4952eab10f..5676e262f8 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ ![Code style](https://img.shields.io/badge/code_style-prettier-ff69b4.svg) [![Codecov](https://img.shields.io/codecov/c/github/backstage/backstage)](https://codecov.io/gh/backstage/backstage) [![](https://img.shields.io/github/v/release/backstage/backstage)](https://github.com/backstage/backstage/releases) +[![Uffizzi](https://img.shields.io/endpoint?url=https%3A%2F%2Fapp.uffizzi.com%2Fapi%2Fv1%2Fpublic%2Fshields%2Fgithub.com%2Fbackstage%2Fbackstage)](https://app.uffizzi.com/ephemeral-environments/backstage/backstage) ## What is Backstage? diff --git a/contrib/catalog/ImmediateEntityProvider.ts b/contrib/catalog/ImmediateEntityProvider.ts index b66c62e330..33ae6697f6 100644 --- a/contrib/catalog/ImmediateEntityProvider.ts +++ b/contrib/catalog/ImmediateEntityProvider.ts @@ -9,8 +9,8 @@ import { DeferredEntity, EntityProvider, EntityProviderConnection, - parseEntityYaml, -} from '@backstage/plugin-catalog-backend'; +} from '@backstage/plugin-catalog-node'; +import { parseEntityYaml } from '@backstage/plugin-catalog-backend'; import bodyParser from 'body-parser'; import express from 'express'; import Router from 'express-promise-router'; diff --git a/contrib/docs/tutorials/authenticate-api-requests.md b/contrib/docs/tutorials/authenticate-api-requests.md index 49b6ae0a4d..c14eaebb54 100644 --- a/contrib/docs/tutorials/authenticate-api-requests.md +++ b/contrib/docs/tutorials/authenticate-api-requests.md @@ -82,10 +82,20 @@ export const createAuthMiddleware = async ( }; ``` +Install cookie-parser: + +```bash +# From your Backstage root directory +yarn add --cwd packages/backend cookie-parser +``` + +Update routes in `packages/backend/src/index.ts`: + ```typescript // packages/backend/src/index.ts from a create-app deployment import { createAuthMiddleware } from './authMiddleware'; +import cookieParser from 'cookie-parser'; // ... diff --git a/docs/accessibility/index.md b/docs/accessibility/index.md new file mode 100644 index 0000000000..24685b95ce --- /dev/null +++ b/docs/accessibility/index.md @@ -0,0 +1,60 @@ +--- +id: index +title: Backstage Accessibility +description: Documentation on Backstage Accessibility +--- + +In an effort to bake accessibility practices further into our process of building features for Backstage, we support automated CI tests for some of our core features in the OSS project: Software Catalog, Software Templates, Search, and TechDocs. As these are just a few of the many plugins out there, we encourage you to consider the accessibility implications of your work on Backstage in order to build a great experience for everyone. + +## How to contribute + +There are multiple ways to contribute to making Backstage more accessible, you'll find below a list of examples to help you get started. + +### Run Lighthouse in CI on your plugin + +If your plugin lives in the [Backstage main repository](https://github.com/backstage/backstage/) you can modify the [urls in the Lighthouse config](https://github.com/backstage/backstage/blob/39ba2284d73885b7ca8290cb38e2b1e4d983c8d6/lighthouserc.js#L19-L34) to run the Lighthouse checks on urls where your plugin exists as well. E.g. + +```diff + ci: { + collect: { + url: [ ++ /** Your plugin paths */ ++ 'http://localhost:3000/your-plugin-path, + /** Software Catalog */ + 'http://localhost:3000/catalog', + 'http://localhost:3000/catalog-import', + 'http://localhost:3000/catalog/default/component/backstage', + ... + ], + settings: { + ... + }, + ... + }, + assert: { + ... + }, + }, +``` + +To make sure the [Accessibility Github workflow](https://github.com/backstage/backstage/blob/master/.github/workflows/verify_accessibility.yml) is running when changes are made to your plugin folders, modify the [list of paths](https://github.com/backstage/backstage/blob/10759b6ad2561bd86183ad940256f9a309c7a6b0/.github/workflows/verify_accessibility.yml#L7-L16). + +### Run the Lighthouse CLI locally when developing new features + +If you want to use the Lighthouse CLI and run the checks based on the config you can use the following command: + +``` +yarn dlx @lhci/cli@0.11.x autorun +``` + +> Note: running this command will use the [Lighthouse config](https://github.com/backstage/backstage/blob/39ba2284d73885b7ca8290cb38e2b1e4d983c8d6/lighthouserc.js#L19-L34) so make sure to adjust it to your needs if needed. + +### Use Lighthouse Github Action on your own repo + +If your Backstage plugin lives outside of the [Backstage main repository](https://github.com/backstage/backstage/), and you use GitHub Actions for continuous integration, we encourage you to add and modify the [Accessibility GitHub workflow](https://github.com/backstage/backstage/blob/master/.github/workflows/verify_accessibility.yml) to your needs. + +### Report identified issues + +It’s important to remember that automated checks can only catch a small number of accessibility issues, therefore we also encourage you to conduct manual testing of your plugins using Assistive technology (screen readers, alternative navigation, and screen magnifiers are a few examples). + +If you have identified accessibility issues and don’t have time to contribute a fix, please open an issue over at [Backstage Issues](https://github.com/backstage/backstage/issues) to let us know. diff --git a/docs/assets/software-catalog/entity.drawio.svg b/docs/assets/software-catalog/entity.drawio.svg new file mode 100644 index 0000000000..557d037ecd --- /dev/null +++ b/docs/assets/software-catalog/entity.drawio.svg @@ -0,0 +1,4 @@ + + + +
Envelope
Envelope
ApiVersion
version of the spec
ApiVersion...
Kind
entity type
Kind...
Spec
Describes the entity
Spec...
Metadata
Things that are not part of the spec
Metadata...
name
name
description
description
title
title
uid
uid
namespace
namespace
labels
labels
annotations
annotations
tags
tags
links
links
Entity
Entity
Text is not SVG - cannot display
\ No newline at end of file diff --git a/docs/auth/gitlab/provider.md b/docs/auth/gitlab/provider.md index dc41617812..ed7fa6aec3 100644 --- a/docs/auth/gitlab/provider.md +++ b/docs/auth/gitlab/provider.md @@ -14,15 +14,17 @@ To support GitLab authentication, you must create an Application from the [GitLab settings](https://gitlab.com/-/profile/applications). The `Redirect URI` should point to your Backstage backend auth handler. -Settings for local development: - -- Name: Backstage (or your custom app name) -- Redirect URI: `http://localhost:7007/api/auth/gitlab/handler/frame` -- Scopes: `read_user` for sign-in. If you also need ID tokens (e.g. if you are - using the Kubernetes plugin and have clusters with `authProvider: oidc` and - [`oidcTokenProvider: -gitlab`](https://backstage.io/docs/features/kubernetes/configuration/#clustersoidctokenprovider-optional)), - add the `openid` scope. +1. Set Application Name to `backstage-dev` or something along those lines. +2. The Authorization Callback URL should match the redirect URI set in Backstage. + 1. Set this to `http://localhost:7007/api/auth/gitlab/handler/frame` for local development. + 2. Set this to `http://{APP_FQDN}:{APP_BACKEND_PORT}/api/auth/gitlab/handler/frame` for non-local deployments. + 3. Select the following scopes from the list: + - [x] `read_user` Grants read-only access to the authenticated user's profile through the /user API endpoint, which includes username, public email, and full name. Also grants access to read-only API endpoints under /users. + - [x] `read_repository` Grants read-only access to repositories on private projects using Git-over-HTTP (not using the API). + - [x] `write_repository` Grants read-write access to repositories on private projects using Git-over-HTTP (not using the API). + - [x] `openid` Grants permission to authenticate with GitLab using OpenID Connect. Also gives read-only access to the user's profile and group memberships. + - [x] `profile` Grants read-only access to the user's profile data using OpenID Connect. + - [x] `email` Grants read-only access to the user's primary email address using OpenID Connect. ## Configuration diff --git a/docs/auth/index.md b/docs/auth/index.md index abe7fb8db6..b2aac47e2a 100644 --- a/docs/auth/index.md +++ b/docs/auth/index.md @@ -348,7 +348,28 @@ const gheAuthApiRef: ApiRef = }); ``` -The new ref is then used to add a new provider to the ApiFactory: +This new API ref will only work if you define an API factory for it. For example: + +```ts +createApiFactory({ + api: gheAuthApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + configApi: configApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi, configApi }) => + GithubAuth.create({ + configApi, + discoveryApi, + oauthRequestApi, + defaultScopes: ['read:user'], + environment: configApi.getOptionalString('auth.environment'), + }), +}); +``` + +The new API ref is then used to add a new provider to the ApiFactory: ```ts createApiFactory({ diff --git a/docs/features/kubernetes/authentication.md b/docs/features/kubernetes/authentication.md index d44d3a4a64..ddeabb5db0 100644 --- a/docs/features/kubernetes/authentication.md +++ b/docs/features/kubernetes/authentication.md @@ -66,6 +66,7 @@ as `401` or similar. The providers available as client side are: +- `aks` - `google` - `oidc` diff --git a/docs/features/kubernetes/configuration.md b/docs/features/kubernetes/configuration.md index 458637f316..9280c4f020 100644 --- a/docs/features/kubernetes/configuration.md +++ b/docs/features/kubernetes/configuration.md @@ -104,12 +104,13 @@ cluster. Valid values are: | Value | Description | | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `serviceAccount` | This will use a Kubernetes [service account](https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/) to access the Kubernetes API. When this is used the `serviceAccountToken` field should also be set. | -| `google` | This will use a user's Google auth token from the [Google auth plugin](https://backstage.io/docs/auth/) to access the Kubernetes API. | +| `aks` | This will use a user's AKS access token from the [Microsoft auth provider](https://backstage.io/docs/auth/microsoft/provider) to access the Kubernetes API on AKS clusters. | | `aws` | This will use AWS credentials to access resources in EKS clusters | -| `googleServiceAccount` | This will use the Google Cloud service account credentials to access resources in clusters | | `azure` | This will use [Azure Identity](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview) to access resources in clusters | +| `google` | This will use a user's Google access token from the [Google auth provider](https://backstage.io/docs/auth/google/provider) to access the Kubernetes API on GKE clusters. | +| `googleServiceAccount` | This will use the Google Cloud service account credentials to access resources in clusters | | `oidc` | This will use [Oidc Tokens](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#openid-connect-tokens) to authenticate to the Kubernetes API. When this is used the `oidcTokenProvider` field should also be set. Please note the cluster must support OIDC, at the time of writing AKS clusters do not support OIDC. | +| `serviceAccount` | This will use a Kubernetes [service account](https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/) to access the Kubernetes API. When this is used the `serviceAccountToken` field should also be set. | Check the [Kubernetes Authentication][4] section for additional explanation. diff --git a/docs/features/software-catalog/creating-the-catalog-graph.md b/docs/features/software-catalog/creating-the-catalog-graph.md new file mode 100644 index 0000000000..8b0f21a52c --- /dev/null +++ b/docs/features/software-catalog/creating-the-catalog-graph.md @@ -0,0 +1,98 @@ +# Creating the Catalog Graph + +## Overview + +The Software Catalog in Backstage is intended to capture human mental models using entities and their relationships rather than an exhaustive inventory of all possible things. The focus is on attaching functionality and views centered around these entities. Determining the "edge" where the catalog ends and the external world begins is crucial to ensure that the catalog's scope is appropriate. +The Backstage software catalog serves as a centralized hub for organizing and discovering software components and services. While it excels at providing a high-level overview of these concepts, it may not be the ideal solution for tracking dynamic relationships between components and services in real-time. You can achieve real time views by attaching appropriate tooling to the nodes in the graph through [annotations](https://backstage.io/docs/features/software-catalog/well-known-annotations) and developing custom front-end [plugins](http://localhost:3000/docs/plugins/) that display deployment information and other real-time data. +It is worth noting that the Backstage Software Catalog should not be considered the ultimate source of truth, instead, it is advisable to use the Backstage Catalog as a caching mechanism that utilizes a REST API to convey information to the catalog UI and other Backstage plugins. Adopting a GitOps approach is recommended to modify YAML files in Backstage, treating YAML files in repositories as the primary source of truth and using Scaffolder to make changes via the UI and generate a pull request in the repository with the updated changes. + +### Descriptor Components used to build the Catalog Graph + +[**Entities:**](https://backstage.io/docs/features/software-catalog/system-model) An entity refers to a node in the graph that represents a distinct object, concept, or thing. Nodes are the fundamental building blocks of a graph database and are used to represent entities and their properties. + +![](../../assets/software-catalog/entity.drawio.svg) + +[**Kinds:**](https://backstage.io/docs/features/software-catalog/descriptor-format#contents) These are broad categories used to group related entities. Kinds are used to provide a high-level categorization of entities, such as "service", "database", or "team". Kinds are often used to provide a way to filter entities in the catalog and to provide a high-level overview of the types of entities that are being managed. + +[**Relations:**](https://backstage.io/docs/features/software-catalog/descriptor-format#common-to-all-kinds-relations) These are links between different entities in the catalog. Relations express the relationships between different entities, such as dependencies or ownership. Adopters can use relations to help users navigate the catalog and understand the relationships between different entities. + +[**Spec:**](https://backstage.io/docs/features/software-catalog/descriptor-format#spec-varies) A specification or "spec" is a schema that outlines the data structure of an entity in the Backstage catalog. It defines the properties, relationships, data types, and constraints for an entity, ensuring consistency and accuracy of data while allowing for easy sharing and consumption of data across components and plugins. Specs are useful when creating or extending entities and can help make data more reusable and interoperable. The spec section is fully customizable, and users can create their own components and plugins to render the information. + +[**Types:**](https://backstage.io/docs/features/software-catalog/system-model#type) These are more specific categories used to classify entities within a given Kind. Types provide a more granular categorization of entities, such as "frontend-service" or "backend-service.". Types are often used to provide additional context and information about an entity and to help users understand the role and function of the entity within the broader system. + +[**Annotations:**](https://backstage.io/docs/features/software-catalog/well-known-annotations) These key-value pairs can be attached to an entity in the catalog. They are typically used to add additional information or metadata to an entity. Annotations are often used to provide information that is used by automated tools or scripts and to provide further context to humans working with the entity or refer plugins to the external world. + +## Use cases out of the box + +The catalog builds a graph using [descriptors](https://backstage.io/docs/features/software-catalog/descriptor-format) as nodes and [relations](https://backstage.io/docs/features/software-catalog/descriptor-format#common-to-all-kinds-relations) as edges. Out of the box you get the following use cases: + +- Ownership tracking +- Inventory +- Search +- Lifecycle tracking +- Tracking of real-time information sources +- Dependency mapping +- API exposure + +## Tracking Assets + +The recommended approach would be to represent information in catalog-info files, which the users themselves can manage. While automated classification based on repository contents can be helpful, it is recommended to use it only to generate the initial file and then allow humans to maintain it manually. The reason is that automation can sometimes fail, and it is essential to ensure the accuracy and reliability of this metadata. In short, humans should govern this piece of metadata to maintain its integrity. + +### Well-known trackable assets + +**Components** + +- Services +- Websites +- Libraries +- Data Pipelines +- Machine Learning Models +- Third-party software components: It is recommended to have a separate repo for all 3d party catalog-info files. +- Jira installation +- Pagerduty + +**Resources** + +- Physical resources: This is probably more useful for longer-lived ones (For example servers). +- Cloud Infrastructure services + +**Ownership - users - groups by** + +- Business units +- Team +- Product area + +**Naming strategies:** + +- Ldap: Internal ldap usernames as entity names. e.g., owner: user:myuser or user: my-team-name. + +**Ownership strategies:** + +**Ownership based on teams:** The concept of ownership in the system is team-centric; hence, the "owner" field must reference the LDAP name of a squad according to a prescribed set of regulations. While there may be instances where the ownership is attributed to an individual, such deviations might create challenges. In such cases, the user could receive a notification through the web interface, highlighting that this departure is an exception and needs rectification. To ensure adherence to this system, every entity in the model should have a designated owner, preferably a valid team within the LDAP hierarchy. + +**Ownership of features:** To track the ownership of specific features within your products and their interrelationships, two options are available: introducing a new component [type](https://backstage.io/docs/features/software-catalog/system-model/#type), such as "feature," or creating a new [Kind](https://backstage.io/docs/features/software-catalog/descriptor-format/#contents) altogether. Nonetheless, it is advisable to choose the former approach and introduce a new type, like "feature," is advisable as it is less complicated and poses a lower risk. + +**LDAP doesn’t reflect the organization structure:** If Workday or a similar system serves as the source of truth, and LDAP is utilized for user attributes, it is advisable to develop a layer on top of various systems to establish a unified API that the entire organization can query, rather than only Backstage. + +**APIs** + +- OpenApi +- AsyncApi +- graphQL +- gRPC + +APIs Could list networked services or libraries and it’s particularly useful to identify APIs that form boundaries between systems. There are some considerations to keep in mind: + +**API versions:** Major API versions can be treated as distinct APIs, and it is possible to create separate entity instances for each (e.g., metadata.name: my-api-v1 and metadata.name: my-api-v2). However, this approach is not recommended for minor or patch-level variations + +**Detail:** It’s not recommended going too granular because the catalog in its current form won't perhaps be a great platform to express it. + +**Relationships between APIs:** The idea is that you have a service component that exposes an api and then, it's not the api that consumes the other api, it's the component that consumes the other api. + +**Backend for front end API (BFF):** The suggestion is to create separate components for the frontend and backend services, with the frontend component having a type of "website" and the backend component having a type of "service". This is because the BFF API is tailored for a specific UI and is not meant to be used by others, making it unnecessary to include in the catalog. + +**API registry:** The exploration of all APIs within an organization is a typical use case for an API registry. + +## Reference models + +**C4 model:** For inspiration, you could review the [C4 model](https://c4model.com/), which defines a pattern for visualizing software architecture. diff --git a/docs/features/software-catalog/descriptor-format.md b/docs/features/software-catalog/descriptor-format.md index 9fb57cb82f..1c9825d5ca 100644 --- a/docs/features/software-catalog/descriptor-format.md +++ b/docs/features/software-catalog/descriptor-format.md @@ -239,17 +239,18 @@ Example: `visits-tracking-service`, `CircleciBuildsDumpV2_avro_gcs` ### `namespace` [optional] -The ID of a namespace that the entity belongs to. This is a string that follows -the same format restrictions as `name` above. +The ID of a namespace that the entity belongs to. This field is optional, and +currently has no special semantics apart from bounding the name uniqueness +constraint if specified. It is reserved for future use and may get broader +semantic implication later. -This field is optional, and currently has no special semantics apart from -bounding the name uniqueness constraint if specified. It is reserved for future -use and may get broader semantic implication later. For now, it is recommended -to not specify a namespace unless you have specific need to do so. This means -the entity belongs to the `"default"` namespace. +For now, it is recommended to not specify a namespace unless you have specific +need to do so. This means the entity belongs to the `"default"` namespace. -Namespaces may also be part of the catalog, and are `v1` / `Namespace` entities, -i.e. not Backstage specific but the same as in Kubernetes. +Namespaces must be sequences of `[a-zA-Z0-9]`, possibly separated by `-`, at +most 63 characters in total. Namespace names are case insensitive and will be rendered as lower case in most places. + +Example: `tracking-services`, `payment` ### `uid` [output] diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index 15e6a833cc..67bcb6c179 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -510,10 +510,8 @@ take a look at, or you can Each individual step can output some variables that can be used in the scaffolder frontend for after the job is finished. This is useful for things -like linking to the entity that has been created with the backend, and also -linking to the created repository. - -The main two that are used are the following: +like linking to the entity that has been created with the backend, linking +to the created repository, or showing Markdown text blobs. ```yaml output: @@ -523,6 +521,10 @@ output: - title: Open in catalog icon: catalog entityRef: ${{ steps['register'].output.entityRef }} # link to the entity that has been ingested to the catalog + text: + - title: More information + content: | + **Entity URL:** `${{ steps['publish'].output.remoteUrl }}` ``` ## The templating syntax diff --git a/docs/getting-started/configuration.md b/docs/getting-started/configuration.md index 2196a1a36d..87995746d8 100644 --- a/docs/getting-started/configuration.md +++ b/docs/getting-started/configuration.md @@ -243,6 +243,8 @@ integrations: token: ${GITHUB_TOKEN} # this will use the environment variable GITHUB_TOKEN ``` +> Note: If you've updated the configuration for your integration, it's likely that the backend will need a restart to apply these changes. To do this, stop the running instance in your terminal with `Control-C`, then start it again with `yarn dev`. Once the backend has restarted, retry the operation. + Some helpful links, for if you want to learn more about: - [Other available integrations](../integrations/) diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index 7398e9a311..820f5ef394 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -21,6 +21,9 @@ you to use the [Contributors](contributors.md) guide to do a repository-based in - Access to a Unix-based operating system, such as Linux, MacOS or [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/) +- A GNU-like build environment available at the command line. + For example, on Debian/Ubuntu you will want to have the `make` and `build-essential` packages installed. + On MacOS, you will want to have run `xcode-select --install` to get the XCode command line build tooling in place. - An account with elevated rights to install the dependencies - `curl` or `wget` installed - Node.js [Active LTS Release](https://nodejs.org/en/blog/release/) installed using one of these diff --git a/docs/integrations/datadog-rum/installation.md b/docs/integrations/datadog-rum/installation.md index 821d35db15..32eb2b3de8 100644 --- a/docs/integrations/datadog-rum/installation.md +++ b/docs/integrations/datadog-rum/installation.md @@ -24,7 +24,7 @@ app: # env: 'staging' ``` -If your [`app-config.yaml`](https://github.com/backstage/backstage/blob/master/app-config.yaml#L5) file does not have this configuration, you may have to adjust your [`packages/app/public/index.html`](https://github.com/backstage/backstage/blob/master/packages/app/public/index.html#L64) to include the Datadog RUM `init()` section manually. +If your [`app-config.yaml`](https://github.com/backstage/backstage/blob/e0506af8fc54074a160fb91c83d6cae8172d3bb3/app-config.yaml#L5) file does not have this configuration, you may have to adjust your [`packages/app/public/index.html`](https://github.com/backstage/backstage/blob/e0506af8fc54074a160fb91c83d6cae8172d3bb3/packages/app/public/index.html#L69) to include the Datadog RUM `init()` section manually. The `clientToken` and `applicationId` are generated from the Datadog RUM page following diff --git a/docs/integrations/github/discovery.md b/docs/integrations/github/discovery.md index 7f6cc057cd..f01085dd86 100644 --- a/docs/integrations/github/discovery.md +++ b/docs/integrations/github/discovery.md @@ -263,8 +263,7 @@ package, plus `@backstage/integration` for the basic credentials management: ```bash # From your Backstage root directory -yarn add --cwd packages/backend @backstage/integration -yarn add --cwd packages/backend @backstage/plugin-catalog-backend-module-github +yarn add --cwd packages/backend @backstage/integration @backstage/plugin-catalog-backend-module-github ``` And then add the processors to your catalog builder: diff --git a/docs/integrations/github/org.md b/docs/integrations/github/org.md index ccffe60bd1..39532e806f 100644 --- a/docs/integrations/github/org.md +++ b/docs/integrations/github/org.md @@ -65,6 +65,42 @@ export default async function createPlugin( } ``` +Alternatively, if you wish to ingest data from multiple GitHub organizations you can use +the `GithubMultiOrgEntityProvider` instead. Note that by default, this provider will namespace +groups according to the org they originate from to avoid potential name duplicates: + +```ts title="packages/backend/src/plugins/catalog.ts" +/* highlight-add-next-line */ +import { GithubMultiOrgEntityProvider } from '@backstage/plugin-catalog-backend-module-github'; + +export default async function createPlugin( + env: PluginEnvironment, +): Promise { + const builder = await CatalogBuilder.create(env); + + /* highlight-add-start */ + // The GitHub URL below needs to match a configured integrations.github entry + // specified in your app-config. + builder.addEntityProvider( + GithubMultiOrgEntityProvider.fromConfig(env.config, { + id: 'production', + githubUrl: 'https://github.com', + // Set the following to list the GitHub orgs you wish to ingest from. You can + // also omit this option to ingest all orgs accessible by your GitHub integration + orgs: ['org-a', 'org-b'], + logger: env.logger, + schedule: env.scheduler.createScheduledTaskRunner({ + frequency: { minutes: 60 }, + timeout: { minutes: 15 }, + }), + }), + ); + /* highlight-add-end */ + + // .. +} +``` + ## Installation with Events Support Please follow the installation instructions at @@ -110,6 +146,42 @@ export default async function createPlugin( } ``` +Or, alternatively, if using the `GithubMultiOrgEntityProvider`: + +```ts title="packages/backend/src/plugins/catalog.ts" +/* highlight-add-next-line */ +import { GithubMultiOrgEntityProvider } from '@backstage/plugin-catalog-backend-module-github'; + +export default async function createPlugin( + env: PluginEnvironment, +): Promise { + const builder = await CatalogBuilder.create(env); + + /* highlight-add-start */ + // The GitHub URL below needs to match a configured integrations.github entry + // specified in your app-config. + builder.addEntityProvider( + GithubMultiOrgEntityProvider.fromConfig(env.config, { + id: 'production', + githubUrl: 'https://github.com', + // Set the following to list the GitHub orgs you wish to ingest from. You can + // also omit this option to ingest all orgs accessible by your GitHub integration + orgs: ['org-a', 'org-b'], + logger: env.logger, + schedule: env.scheduler.createScheduledTaskRunner({ + frequency: { minutes: 60 }, + timeout: { minutes: 15 }, + }), + // Pass in the eventBroker to allow this provider to subscribe to GitHub events + eventBroker: env.eventBroker, + }), + ); + /* highlight-add-end */ + + // .. +} +``` + You can check the official docs to [configure your webhook](https://docs.github.com/en/developers/webhooks-and-events/webhooks/creating-webhooks) and to [secure your request](https://docs.github.com/en/developers/webhooks-and-events/webhooks/securing-your-webhooks). The webhook will need to be configured to forward `organization`,`team` and `membership` events. diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md index a5df84f8dc..61e94e9ef4 100644 --- a/docs/local-dev/cli-build-system.md +++ b/docs/local-dev/cli-build-system.md @@ -165,16 +165,17 @@ module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, { The configuration factory also provides utilities for extending the configuration in ways that are otherwise very cumbersome to do with plain ESLint, particularly for rules like `no-restricted-syntax`. These are the extra keys that are available: -| Key | Description | -| ----------------------- | ------------------------------------------------------------------ | -| `tsRules` | Additional rules to apply to TypeScript files | -| `testRules` | Additional rules to apply to tests files | -| `restrictedImports` | Additional paths to add to `no-restricted-imports` | -| `restrictedSrcImports` | Additional paths to add to `no-restricted-imports` in src files | -| `restrictedTestImports` | Additional paths to add to `no-restricted-imports` in test files | -| `restrictedSyntax` | Additional patterns to add to `no-restricted-syntax` | -| `restrictedSrcSyntax` | Additional patterns to add to `no-restricted-syntax` in src files | -| `restrictedTestSyntax` | Additional patterns to add to `no-restricted-syntax` in test files | +| Key | Description | +| -------------------------- | ------------------------------------------------------------------ | +| `tsRules` | Additional rules to apply to TypeScript files | +| `testRules` | Additional rules to apply to tests files | +| `restrictedImports` | Additional paths to add to `no-restricted-imports` | +| `restrictedImportPatterns` | Additional patterns to add to `no-restricted-imports` | +| `restrictedSrcImports` | Additional paths to add to `no-restricted-imports` in src files | +| `restrictedTestImports` | Additional paths to add to `no-restricted-imports` in test files | +| `restrictedSyntax` | Additional patterns to add to `no-restricted-syntax` | +| `restrictedSrcSyntax` | Additional patterns to add to `no-restricted-syntax` in src files | +| `restrictedTestSyntax` | Additional patterns to add to `no-restricted-syntax` in test files | ## Type Checking diff --git a/docs/local-dev/cli-commands.md b/docs/local-dev/cli-commands.md index c4c057ffe6..66a1855fca 100644 --- a/docs/local-dev/cli-commands.md +++ b/docs/local-dev/cli-commands.md @@ -290,7 +290,8 @@ Options: --package Only load config schema that applies to the given package --lax Do not require environment variables to be set --frontend Only validate the frontend configuration - --deprecated List all deprecated configuration settings + --deprecated Output deprecated configuration settings + --strict Ensure that the provided config(s) has no errors and does not contain keys not in the schema. --config Config files to load instead of app-config.yaml (default: []) -h, --help display help for command ``` diff --git a/docs/overview/support.md b/docs/overview/support.md index a0444c4d34..c968405a99 100644 --- a/docs/overview/support.md +++ b/docs/overview/support.md @@ -15,7 +15,7 @@ description: Support and Community Details and Links - [Code of Conduct](https://github.com/backstage/backstage/blob/master/CODE_OF_CONDUCT.md) - This is how we roll. - [Blog](https://backstage.io/blog/) - Announcements and updates. -- [Newsletter](https://mailchi.mp/spotify/backstage-community) - Subscribe to +- [Newsletter](https://info.backstage.spotify.com/newsletter_subscribe) - Subscribe to our email newsletter. - Give us a star ⭐️ - If you are using Backstage or think it is an interesting project, we would love a star! ❤️ diff --git a/docs/permissions/getting-started.md b/docs/permissions/getting-started.md index 8cb6dd953e..01a268f7ef 100644 --- a/docs/permissions/getting-started.md +++ b/docs/permissions/getting-started.md @@ -48,7 +48,7 @@ The permissions framework uses a new `permission-backend` plugin to accept autho ```bash # From your Backstage root directory - $ yarn add --cwd packages/backend @backstage/plugin-permission-backend + yarn add --cwd packages/backend @backstage/plugin-permission-backend ``` 2. Add the following to a new file, `packages/backend/src/plugins/permission.ts`. This adds the permission-backend router, and configures it with a policy which allows everything. diff --git a/docs/permissions/plugin-authors/01-setup.md b/docs/permissions/plugin-authors/01-setup.md index 6827096900..8134fc0c39 100644 --- a/docs/permissions/plugin-authors/01-setup.md +++ b/docs/permissions/plugin-authors/01-setup.md @@ -41,8 +41,8 @@ The source code is available here: ```sh # From your Backstage root directory - $ yarn add --cwd packages/backend @internal/plugin-todo-list-backend @internal/plugin-todo-list-common - $ yarn add --cwd packages/app @internal/plugin-todo-list + yarn add --cwd packages/backend @internal/plugin-todo-list-backend @internal/plugin-todo-list-common + yarn add --cwd packages/app @internal/plugin-todo-list ``` 3. Include the backend and frontend plugin in your application: diff --git a/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md b/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md index 6b4ac98646..a4d51b64d0 100644 --- a/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md +++ b/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md @@ -31,11 +31,12 @@ export const todoListUpdatePermission = createPermission({ /* highlight-remove-next-line */ export const todoListPermissions = [todoListCreatePermission]; -/* highlight-add-next-line */ +/* highlight-add-start */ export const todoListPermissions = [ todoListCreatePermission, todoListUpdatePermission, ]; +/* highlight-add-end */ ``` Notice that unlike `todoListCreatePermission`, the `todoListUpdatePermission` permission contains a `resourceType` field. This field indicates to the permission framework that this permission is intended to be authorized in the context of a resource with type `'todo-item'`. You can use whatever string you like as the resource type, as long as you use the same value consistently for each type of resource. diff --git a/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md b/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md index 0cae08a668..a9e62040c5 100644 --- a/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md +++ b/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md @@ -66,16 +66,12 @@ export const todoListReadPermission = createPermission({ }); /* highlight-add-end */ -/* highlight-add-next-line */ -export const todoListPermissions = [ - todoListCreatePermission, - todoListUpdatePermission, -]; -/* highlight-add-next-line */ export const todoListPermissions = [ todoListCreatePermission, todoListUpdatePermission, + /* highlight-add-start */ todoListReadPermission, + /* highlight-add-end */ ]; ``` diff --git a/docs/publishing.md b/docs/publishing.md index 142e019fb2..12e4878d5a 100644 --- a/docs/publishing.md +++ b/docs/publishing.md @@ -11,7 +11,7 @@ npm. ### Creating a new release Releases are handled by changesets and trigger whenever the "Version Packages" -PR is merged. This is typically done every Thursday around noon CET. +PR is merged. This is typically done every Tuesday around noon CET. ## Emergency Release Process diff --git a/docs/releases/v1.13.0-changelog.md b/docs/releases/v1.13.0-changelog.md index 823ff337bc..506800eb38 100644 --- a/docs/releases/v1.13.0-changelog.md +++ b/docs/releases/v1.13.0-changelog.md @@ -4,7 +4,7 @@ ### Minor Changes -- 7908d72e033: Introduce a new global config parameter, `auth.enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. +- 7908d72e033: Introduce a new global config parameter, `enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. ### Patch Changes @@ -61,7 +61,7 @@ ### Minor Changes -- 7908d72e033: Introduce a new global config parameter, `auth.enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. +- 7908d72e033: Introduce a new global config parameter, `enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. - c15e0cedbe1: The `AuthConnector` interface now supports specifying a set of scopes when refreshing a session. The `DefaultAuthConnector` implementation passes the `scope` query parameter to the auth-backend plugin appropriately. The @@ -106,7 +106,7 @@ - 67140d9f96f: Upgrade `react-virtualized-auto-sizer´ to version `^1.0.11\` - 6e0b71493df: Switched internal declaration of `DependencyGraphTypes` to use `namespace`. - c8779cc1d09: Updated `LogLine` component, which is used by the `LogViewer`, to turn URLs into clickable links. This feature is on by default -- 7908d72e033: Introduce a new global config parameter, `auth.enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. +- 7908d72e033: Introduce a new global config parameter, `enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. - 1e4f5e91b8e: Bump `zod` and `zod-to-json-schema` dependencies. - 29ba8267d69: Updated dependency `@material-ui/lab` to `4.0.0-alpha.61`. - 8e00acb28db: Small tweaks to remove warnings in the console during development (mainly focusing on techdocs) @@ -170,7 +170,7 @@ ### Minor Changes -- 7908d72e033: Introduce a new global config parameter, `auth.enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. +- 7908d72e033: Introduce a new global config parameter, `enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. ### Patch Changes @@ -1245,7 +1245,7 @@ - d8f774c30df: Enforce the secret visibility of certificates and client secrets in the auth backend. Also, document all known options for each auth plugin. -- 7908d72e033: Introduce a new global config parameter, `auth.enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. +- 7908d72e033: Introduce a new global config parameter, `enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. - 475abd1dc3f: The `microsoft` (i.e. Azure) auth provider now supports negotiating tokens for Azure resources besides Microsoft Graph (e.g. AKS, Virtual Machines, Machine diff --git a/docs/releases/v1.13.0-next.0-changelog.md b/docs/releases/v1.13.0-next.0-changelog.md index 3075d80f61..7de0a370f9 100644 --- a/docs/releases/v1.13.0-next.0-changelog.md +++ b/docs/releases/v1.13.0-next.0-changelog.md @@ -4,7 +4,7 @@ ### Minor Changes -- 7908d72e033: Introduce a new global config parameter, `auth.enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. +- 7908d72e033: Introduce a new global config parameter, `enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. ### Patch Changes @@ -19,7 +19,7 @@ ### Minor Changes -- 7908d72e033: Introduce a new global config parameter, `auth.enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. +- 7908d72e033: Introduce a new global config parameter, `enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. ### Patch Changes @@ -33,7 +33,7 @@ ### Minor Changes -- 7908d72e033: Introduce a new global config parameter, `auth.enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. +- 7908d72e033: Introduce a new global config parameter, `enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. ### Patch Changes @@ -336,7 +336,7 @@ ### Patch Changes -- 7908d72e033: Introduce a new global config parameter, `auth.enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. +- 7908d72e033: Introduce a new global config parameter, `enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. - 8e00acb28db: Small tweaks to remove warnings in the console during development (mainly focusing on techdocs) - 7245e744ab1: Fixed the font color on `BackstageHeaderLabel` to respect the active page theme. - Updated dependencies @@ -530,7 +530,7 @@ ### Patch Changes - d8f774c30df: Enforce the secret visibility of certificates and client secrets in the auth backend. Also, document all known options for each auth plugin. -- 7908d72e033: Introduce a new global config parameter, `auth.enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. +- 7908d72e033: Introduce a new global config parameter, `enableExperimentalRedirectFlow`. When enabled, auth will happen with an in-window redirect flow rather than through a popup window. - Updated dependencies - @backstage/backend-common@0.18.4-next.0 - @backstage/config@1.0.7 diff --git a/docs/releases/v1.13.0.md b/docs/releases/v1.13.0.md index 99253ac3d2..c8803453d4 100644 --- a/docs/releases/v1.13.0.md +++ b/docs/releases/v1.13.0.md @@ -86,7 +86,7 @@ Contributed by [@sennyeya](https://github.com/sennyeya) in [#15667](https://gith ### Experimental inline auth flows -There’s new support for running auth flows inline in the current page instead of in a separate popup window, enabled via the `auth.enableExperimentalRedirectFlow` app-config parameter. This will allow the use of some providers that do not support popup flows. It’s still an experimental feature, but do try it out if this applies to you! +There’s new support for running auth flows inline in the current page instead of in a separate popup window, enabled via the `enableExperimentalRedirectFlow` app-config parameter. This will allow the use of some providers that do not support popup flows. It’s still an experimental feature, but do try it out if this applies to you! Contributed by [@headphonejames](https://github.com/headphonejames) in [#15841](https://github.com/backstage/backstage/pull/15841) diff --git a/docs/releases/v1.14.0-changelog.md b/docs/releases/v1.14.0-changelog.md new file mode 100644 index 0000000000..eae0d82e71 --- /dev/null +++ b/docs/releases/v1.14.0-changelog.md @@ -0,0 +1,2795 @@ +# Release v1.14.0 + +## @backstage/config-loader@1.3.0 + +### Minor Changes + +- 201206132da: Introduced a new config source system to replace `loadConfig`. There is a new `ConfigSource` interface along with utilities provided by `ConfigSources`, as well as a number of built-in configuration source implementations. The new system is more flexible and makes it easier to create new and reusable sources of configuration, such as loading configuration from secret providers. + + The following is an example of how to load configuration using the default behavior: + + ```ts + const source = ConfigSources.default({ + argv: options?.argv, + remote: options?.remote, + }); + const config = await ConfigSources.toConfig(source); + ``` + + The `ConfigSource` interface looks like this: + + ```ts + export interface ConfigSource { + readConfigData(options?: ReadConfigDataOptions): AsyncConfigSourceIterator; + } + ``` + + It is best implemented using an async iterator: + + ```ts + class MyConfigSource implements ConfigSource { + async *readConfigData() { + yield { + config: [ + { + context: 'example', + data: { backend: { baseUrl: 'http://localhost' } }, + }, + ], + }; + } + } + ``` + +### Patch Changes + +- 7c116bcac7f: Fixed the way that some request errors are thrown +- 473db605a4f: Added a new `noUndeclaredProperties` option to `SchemaLoader` to support enforcing that there are no extra keys when verifying config. +- Updated dependencies + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/core-app-api@1.8.0 + +### Minor Changes + +- c89437db899: The analytics' `navigate` event will now include the route parameters as attributes of the navigate event + +### Patch Changes + +- b645d70034a: Fixed a bug in the Azure auth provider which prevented getting access tokens with multiple scopes for one resource +- 42d817e76ab: Added `FrontendHostDiscovery` for config driven discovery implementation +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.4 + +## @backstage/repo-tools@0.3.0 + +### Minor Changes + +- 799c33047ed: **BREAKING**: The OpenAPI commands are now found within the `schema openapi` sub-command. For example `yarn backstage-repo-tools schema:openapi:verify` is now `yarn backstage-repo-tools schema openapi verify`. +- 27956d78671: Generated OpenAPI files now have a `.generated.ts` file name and a warning header at the top, to highlight that they should not be edited by hand. + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.12 + - @backstage/cli-node@0.1.0 + - @backstage/errors@1.1.5 + +## @backstage/theme@0.3.0 + +### Minor Changes + +- 98c0c199b15: Updates light theme's primary foreground and `running` status indicator colours to meet WCAG. Previously #2E77D0 changed to #1F5493. + +### Patch Changes + +- 83b45f9df50: Fix accessibility issue with Backstage Table's header style + +## @backstage/plugin-adr@0.6.0 + +### Minor Changes + +- b12cd5dc221: render SupportButton only if config is set + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/plugin-search-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-adr-common@0.2.9 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-analytics-module-ga4@0.1.0 + +### Minor Changes + +- 22b46f7f562: Plugin provides Backstage Analytics API for Google Analytics 4. Once installed and configured, analytics events will be sent to GA4 as your users navigate and use your Backstage instance + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-azure-devops@0.3.0 + +### Minor Changes + +- 877df261085: The getBuildRuns function now checks contains multiple comma-separated builds and splits them to send multiple requests for each and concatenates the results. + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/plugin-azure-devops-common@0.3.0 + +## @backstage/plugin-badges-backend@0.2.0 + +### Minor Changes + +- a0108c49774: Fixing badges-backend plugin to get a token from the TokenManager instead of parsing the request header. Hence, it's now possible to disable the authMiddleware for the badges-backend plugin to expose publicly the badges. + + Implementing an obfuscation feature to protect an open badges endpoint from being enumerated. The feature is disabled by default and the change is compatible with the previous version. + + **BREAKING**: `createRouter` now require that `tokenManager`, `logger`, and `identityApi`, are passed in as options. + +### Patch Changes + +- 0cd552c28d8: Removed some unused dependencies +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## @backstage/plugin-catalog@1.11.0 + +### Minor Changes + +- 2258dcae970: Added an entity namespace filter and column on the default catalog page. + + If you have a custom version of the catalog page, you can add this filter in your CatalogPage code: + + ```ts + + + + + + /* if you want namespace picker */ + + + + + + + ``` + + The namespace column can be added using `createNamespaceColumn();`. This is only needed if you customized the columns for CatalogTable. + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/plugin-search-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-catalog-backend-module-aws@0.2.0 + +### Minor Changes + +- 1a3b5f1e390: **BREAKING**: AwsOrganizationCloudAccountProcessor.fromConfig now returns a promise instead of the instance directly. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/integration-aws-node@0.1.3 + - @backstage/plugin-kubernetes-common@0.6.3 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + +## @backstage/plugin-catalog-backend-module-github@0.3.0 + +### Minor Changes + +- 970678adbe2: Implement events support for `GithubMultiOrgEntityProvider` + + **BREAKING:** Passing in a custom `teamTransformer` will now correctly completely override the default transformer behavior + +### Patch Changes + +- 78bb674a713: Fixed bug in queryWithPaging that caused secondary rate limit errors in GitHub with organizations having more than 1000 repositories. This change makes one request per second to avoid concurrency issues. +- bd101cefd37: Updated the `team.edited` event emitted from `GithubOrgEntityProvider` to also include teams description. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.1 + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-events-node@0.2.6 + +## @backstage/plugin-catalog-react@1.6.0 + +### Minor Changes + +- 2258dcae970: Added an entity namespace filter and column on the default catalog page. + + If you have a custom version of the catalog page, you can add this filter in your CatalogPage code: + + ```ts + + + + + + /* if you want namespace picker */ + + + + + + + ``` + + The namespace column can be added using `createNamespaceColumn();`. This is only needed if you customized the columns for CatalogTable. + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.1 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.4 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-react@0.4.12 + +## @backstage/plugin-devtools@0.1.0 + +### Minor Changes + +- 347aeca204c: Introduced the DevTools plugin, checkout the plugin's [`README.md`](https://github.com/backstage/backstage/tree/master/plugins/devtools) for more details! + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-devtools-common@0.1.0 + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-react@0.4.12 + +## @backstage/plugin-devtools-backend@0.1.0 + +### Minor Changes + +- 347aeca204c: Introduced the DevTools plugin, checkout the plugin's [`README.md`](https://github.com/backstage/backstage/tree/master/plugins/devtools) for more details! + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-devtools-common@0.1.0 + - @backstage/backend-common@0.18.5 + - @backstage/config-loader@1.3.0 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.5 + +## @backstage/plugin-devtools-common@0.1.0 + +### Minor Changes + +- 347aeca204c: Introduced the DevTools plugin, checkout the plugin's [`README.md`](https://github.com/backstage/backstage/tree/master/plugins/devtools) for more details! + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.5 + +## @backstage/plugin-events-backend-module-aws-sqs@0.2.0 + +### Minor Changes + +- 2c5661f3899: Allow endpoint configuration for sqs, enabling use of localstack for testing. + +### Patch Changes + +- 3659c71c5d9: Standardize `@aws-sdk` v3 versions +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/types@1.0.2 + - @backstage/plugin-events-node@0.2.6 + +## @backstage/plugin-jenkins@0.8.0 + +### Minor Changes + +- cf95c5137c9: Updated rebuild to use Jenkins API replay build, which works for Jenkins jobs that have required parameters. Jenkins SDK could not be used for this request because it does not have support for replay. + + Added link to view build in Jenkins CI/CD table action column. + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/plugin-jenkins-common@0.1.15 + +## @backstage/plugin-jenkins-backend@0.2.0 + +### Minor Changes + +- cf95c5137c9: Updated rebuild to use Jenkins API replay build, which works for Jenkins jobs that have required parameters. Jenkins SDK could not be used for this request because it does not have support for replay. + + Added link to view build in Jenkins CI/CD table action column. + +### Patch Changes + +- 670a2dd6f4e: Fix handling of slashes in branch names +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-jenkins-common@0.1.15 + - @backstage/plugin-permission-common@0.7.5 + +## @backstage/plugin-kubernetes@0.9.0 + +### Minor Changes + +- 280ec10c18e: Added Pod logs components for Kubernetes plugin + + **BREAKING**: `kubernetesProxyApi` for custom plugins built with components from the Kubernetes plugin apis, `kubernetesProxyApi` should be added to the plugin's API list. + + ... + export const kubernetesPlugin = createPlugin({ + id: 'kubernetes', + apis: [ + ... + createApiFactory({ + api: kubernetesProxyApiRef, + deps: { + kubernetesApi: kubernetesApiRef, + }, + factory: ({ kubernetesApi }) => + new KubernetesProxyClient({ + kubernetesApi, + }), + }), + + **BREAKING**: `KubernetesDrawer` is now called `KubernetesStructuredMetadataTableDrawer` so that we can do more than just show `StructuredMetadataTable` + + `import { KubernetesDrawer } from "@backstage/plugin-kubernetes"` + + should now be: + + `import { KubernetesStructuredMetadataTableDrawer } from "@backstage/plugin-kubernetes"` + +### Patch Changes + +- c7bad1005ba: The Kubernetes plugin now requests AKS access tokens from Azure when retrieving + objects from clusters configured with `authProvider: aks` and sets `auth.aks` in + its request bodies appropriately. +- a160e02c3d7: Omit managed fields in the Kubernetes resource YAML display. +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/plugin-kubernetes-common@0.6.3 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-kubernetes-backend@0.11.0 + +### Minor Changes + +- f4114f02d49: Allow fetching pod metrics limited by a `labelSelector`. + + This is used by the Kubernetes tab on a components' page and leads to much smaller responses being received from Kubernetes, especially with larger Kubernetes clusters. + +- 890988341e9: Update `aws-sdk` client from v2 to v3. + + **BREAKING**: The `AwsIamKubernetesAuthTranslator` class no longer exposes the following methods `awsGetCredentials`, `getBearerToken`, `getCredentials` and `validCredentials`. There is no replacement for these methods. + +### Patch Changes + +- 05f1d74539d: Kubernetes clusters now support `authProvider: aks`. When configured this way, + the `retrieveObjectsByServiceId` action will use the `auth.aks` value in the + request body as a bearer token to authenticate with Kubernetes. +- 3659c71c5d9: Standardize `@aws-sdk` v3 versions +- a341129b754: Fixed a bug in the Kubernetes proxy endpoint where requests to clusters configured with client-side auth providers would always fail with a 500 status. +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration-aws-node@0.1.3 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/plugin-kubernetes-common@0.6.3 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-permission-common@0.7.5 + +## @backstage/plugin-octopus-deploy@0.2.0 + +### Minor Changes + +- 87211bc2873: Added support for Octopus Deploy spaces. The octopus.com/project-id annotation can now (optionally) be prefixed by a space identifier, for example. Spaces-1/Projects-102. + Also note that some of this plugins exported API's have changed to accommodate this change, changing from separate arguments to a single object. + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-scaffolder-backend@1.14.0 + +### Minor Changes + +- 67115f532b8: Expose both types of scaffolder permissions and rules through the metadata endpoint. + + The metadata endpoint now correctly exposes both types of scaffolder permissions and rules (for both the template and action resource types) through the metadata endpoint. + +- a73b3c0b097: Add ability to use `defaultNamespace` and `defaultKind` for scaffolder action `catalog:fetch` + +### Patch Changes + +- 1a48b84901c: Bump minimum required version of `vm2` to be 3.9.18 +- d20c87966a4: Bump minimum required version of `vm2` to be 3.9.17 +- 6d954de4b06: Update typing for `RouterOptions::actions` and `ScaffolderActionsExtensionPoint::addActions` to allow any kind of action being assigned to it. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.1 + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/plugin-scaffolder-common@1.3.0 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/plugin-scaffolder-node@0.1.3 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.2.0 + +### Minor Changes + +- 439e2986be1: Add a new scaffolder action for gitlab to ensure a group exists + +### Patch Changes + +- f1496d4ab6f: Fix input schema validation issue for gitlab actions: + + - gitlab:group:ensureExists + - gitlab:projectAccessToken:create + - gitlab:projectDeployToken:create + - gitlab:projectVariable:create + +- Updated dependencies + - @backstage/integration@1.4.5 + - @backstage/plugin-scaffolder-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## @backstage/plugin-scaffolder-common@1.3.0 + +### Minor Changes + +- 82e10a6939c: Add support for Markdown text blob outputs from templates +- 67115f532b8: Expose scaffolder permissions in new sub-aggregations. + + In addition to exporting a list of all scaffolder permissions in `scaffolderPermissions`, scaffolder-common now exports `scaffolderTemplatePermissions` and `scaffolderActionPermissions`, which contain subsets of the scaffolder permissions separated by resource type. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.3.0 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.5 + +## @backstage/plugin-scaffolder-react@1.4.0 + +### Minor Changes + +- 82e10a6939c: Add support for Markdown text blob outputs from templates + +### Patch Changes + +- ad1a1429de4: Improvements to the `scaffolder/next` buttons UX: + + - Added padding around the "Create" button in the `Stepper` component + - Added a button bar that includes the "Cancel" and "Start Over" buttons to the `OngoingTask` component. The state of these buttons match their existing counter parts in the Context Menu + - Added a "Show Button Bar"/"Hide Button Bar" item to the `ContextMenu` component + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/plugin-scaffolder-common@1.3.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.4 + +## @backstage/plugin-search@1.3.0 + +### Minor Changes + +- 750e45539ad: Add close button & improve search input. + + MUI's Paper wrapping the SearchBar in the SearchPage was removed, we recommend users update their apps accordingly. + + SearchBarBase's TextField's label support added & aria-label uses label string if present, tests relying on the default placeholder value should still work unless custom placeholder was given. + +### Patch Changes + +- 0e3d8d69318: Fixed 404 Error when fetching search results due to URL encoding changes +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/plugin-search-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.4 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-search-backend-module-elasticsearch@1.3.0 + +### Minor Changes + +- 3d72bdb41c7: Upgrade to aws-sdk v3 and include OpenSearch Serverless support + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration-aws-node@0.1.3 + - @backstage/plugin-search-backend-node@1.2.1 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-search-react@1.6.0 + +### Minor Changes + +- 750e45539ad: Add close button & improve search input. + + MUI's Paper wrapping the SearchBar in the SearchPage was removed, we recommend users update their apps accordingly. + + SearchBarBase's TextField's label support added & aria-label uses label string if present, tests relying on the default placeholder value should still work unless custom placeholder was given. + +- 1ce7f84b2e8: accepts InputProp property that can override keys from default + +### Patch Changes + +- f785f0804cd: `SearchPagination` now automatically resets the page cursor when the page limit is changed +- adb31096bc2: Fix text-overflow UI issue for Lifecycle spans in SearchFilter checkbox labels. +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.4 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/app-defaults@1.3.1 + +### Patch Changes + +- 575d9178eff: Added a System Icon for resource entities. + This can be obtained using: + + ```ts + useApp().getSystemIcon('kind:resource'); + ``` + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + +## @backstage/backend-app-api@0.4.3 + +### Patch Changes + +- cf13b482f9e: Switch `configServiceFactory` to use `ConfigSources` from `@backstage/config-loader` to load config. +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config-loader@1.3.0 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/backend-common@0.18.5 + +### Patch Changes + +- 0297f7a54af: Remove the direct dependency on deprecated "request" library +- 284db225083: Updated the `DatabaseManager` to include the plugin id in the Postgres application name of the database connections created for each plugin. +- 3659c71c5d9: Standardize `@aws-sdk` v3 versions +- 42d817e76ab: Added `HostDiscovery` to supersede deprecated `SingleHostDiscovery` (deprecated due to name) +- Updated dependencies + - @backstage/config-loader@1.3.0 + - @backstage/integration@1.4.5 + - @backstage/integration-aws-node@0.1.3 + - @backstage/backend-app-api@0.4.3 + - @backstage/backend-dev-utils@0.1.1 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/backend-defaults@0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-app-api@0.4.3 + - @backstage/backend-plugin-api@0.5.2 + +## @backstage/backend-openapi-utils@0.0.2 + +### Patch Changes + +- fe16bd39e83: Use permalinks for links including a line number reference +- 27956d78671: Adjusted README accordingly after the generated output now has a `.generated.ts` extension +- 021cfbb5152: Corrected resolution of parameter nested schema to use central schemas. +- 799c33047ed: Updated README to reflect changes in `@backstage/repo-tools`. + +## @backstage/backend-plugin-api@0.5.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/config@1.0.7 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.5 + +## @backstage/backend-tasks@0.5.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/backend-test-utils@0.1.37 + +### Patch Changes + +- 63af7f6d53f: Allow specifying custom Docker registry for database tests +- b1eb268bf9d: Added `POSTGRES_11` and `POSTGRES_12` as supported test database IDs. +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-app-api@0.4.3 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/types@1.0.2 + +## @backstage/cli@0.22.7 + +### Patch Changes + +- 473db605a4f: Enable strict config checking during `backstage-cli config:check` with the new `--strict` option which will surface schema errors. +- d548886872d: Deprecated the use of React 16 +- Updated dependencies + - @backstage/config-loader@1.3.0 + - @backstage/cli-common@0.1.12 + - @backstage/cli-node@0.1.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/eslint-plugin@0.1.3 + - @backstage/release-manifests@0.0.9 + - @backstage/types@1.0.2 + +## @backstage/core-components@0.13.1 + +### Patch Changes + +- 83b45f9df50: Fix accessibility issue with Backstage Table's header style +- e97769f7c0b: Fix accessibility issue on controlled select input on tab navigation + keyboard enter/space action. +- b1f13cb38aa: Fix accessibility issue with Edit Metadata Link on screen readers missing notice about opening in a new tab. +- 26cff1a5dfb: Start capturing sidebar click events in analytics by default. +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/version-bridge@1.0.4 + +## @backstage/create-app@0.5.1 + +### Patch Changes + +- 1d5e42655cd: Correct command to create new plugins +- e04bb20bdc4: Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.12 + +## @backstage/dev-utils@1.0.15 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/app-defaults@1.3.1 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/test-utils@1.3.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/integration@1.4.5 + +### Patch Changes + +- b026275bcc8: Fixed a bug where the wrong credentials would be selected when using multiple GitHub app integrations. +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## @backstage/integration-aws-node@0.1.3 + +### Patch Changes + +- 3659c71c5d9: Standardize `@aws-sdk` v3 versions +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## @backstage/integration-react@1.1.13 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @techdocs/cli@1.4.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-techdocs-node@1.7.1 + - @backstage/catalog-model@1.3.0 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.7 + +## @backstage/test-utils@1.3.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-app-api@1.8.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-react@0.4.12 + +## @backstage/plugin-adr-backend@0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-adr-common@0.2.9 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-adr-common@0.2.9 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.4.5 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-airbrake@0.3.18 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/dev-utils@1.0.15 + - @backstage/test-utils@1.3.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-airbrake-backend@0.2.18 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config@1.0.7 + +## @backstage/plugin-allure@0.1.34 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-analytics-module-ga@0.1.29 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-apache-airflow@0.2.11 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-api-docs@0.9.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/plugin-catalog@1.11.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-apollo-explorer@0.1.11 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-app-backend@0.3.45 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config-loader@1.3.0 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/types@1.0.2 + +## @backstage/plugin-auth-backend@0.18.3 + +### Patch Changes + +- 7c116bcac7f: Fixed the way that some request errors are thrown +- 473db605a4f: Fix config schema definition. +- 3ffcdac7d07: Added a persistent session store through the database +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/plugin-auth-node@0.2.14 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## @backstage/plugin-azure-devops-backend@0.3.24 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config@1.0.7 + - @backstage/plugin-azure-devops-common@0.3.0 + +## @backstage/plugin-azure-sites@0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-azure-sites-common@0.1.0 + +## @backstage/plugin-azure-sites-backend@0.1.7 + +### Patch Changes + +- d66d4f916aa: Updated URL to `/health` and corrected typos in the `README.md` +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config@1.0.7 + - @backstage/plugin-azure-sites-common@0.1.0 + +## @backstage/plugin-badges@0.2.42 + +### Patch Changes + +- a0108c49774: Fixing badges-backend plugin to get a token from the TokenManager instead of parsing the request header. Hence, it's now possible to disable the authMiddleware for the badges-backend plugin to expose publicly the badges. + + Implementing an obfuscation feature to protect an open badges endpoint from being enumerated. The feature is disabled by default and the change is compatible with the previous version. + + **BREAKING**: `createRouter` now require that `tokenManager`, `logger`, and `identityApi`, are passed in as options. + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-bazaar@0.2.8 + +### Patch Changes + +- 900880ab7c3: Fixed `validateDOMNesting` warnings +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/cli@0.22.7 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/plugin-catalog@1.11.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-bazaar-backend@0.2.8 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## @backstage/plugin-bitbucket-cloud-common@0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.4.5 + +## @backstage/plugin-bitrise@0.1.45 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-catalog-backend@1.9.1 + +### Patch Changes + +- ce8d203235b: Ensure that entity cache state is only written to the database when actually changed +- 485a6c5f7b5: Internal refactoring for performance in the service handlers +- 3587a968dcd: Fixed a bug in the `queryEntities` endpoint that was causing filtered entities to be included in cursor requests. +- ce335df9d1c: Improve the query for orphan pruning +- 27956d78671: Adjusted the OpenAPI schema file name according to the new structure +- 51064e6e5ee: Change orphan cleanup task to only log a message if it deleted entities. +- 12a345317ab: Remove unnecessary join in the entity facets endpoint, exclude nulls +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/plugin-scaffolder-common@1.3.0 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/plugin-search-backend-module-catalog@0.1.1 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-catalog-backend-module-azure@0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.6 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/plugin-bitbucket-cloud-common@0.2.6 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-events-node@0.2.6 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.13 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## @backstage/plugin-catalog-backend-module-gitlab@0.2.1 + +### Patch Changes + +- b12c41fafc4: Fix a corner case where returned users are null for bots +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.3.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.1 + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-events-node@0.2.6 + - @backstage/plugin-permission-common@0.7.5 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + +## @backstage/plugin-catalog-backend-module-msgraph@0.5.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/plugin-catalog-common@1.0.13 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.11 + +### Patch Changes + +- accaceadffa: Fixed bug in `jsonSchemaRefPlaceholderResolver` where relative $ref files were resolved through file system instead of base URL of file +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.1 + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.1.2 + +### Patch Changes + +- 95b2168d71b: Fixes import paths and updates documentation +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-graph@0.2.30 + +### Patch Changes + +- d446f8fb0a8: Expose all `EntityRelationsGraphProps` to Catalog Graph Page +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-catalog-import@0.9.8 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/plugin-catalog-common@1.0.13 + +## @backstage/plugin-catalog-node@1.3.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + +## @backstage/plugin-cicd-statistics@0.1.20 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.14 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-cicd-statistics@0.1.20 + +## @backstage/plugin-circleci@0.3.18 + +### Patch Changes + +- 451b3cadb3d: Fixes row display for in progress jobs to not display trailing "took" +- 1c4958d905f: Hide empty time field data for queued builds which haven't started yet +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-cloudbuild@0.3.18 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-code-climate@0.1.18 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-code-coverage@0.2.11 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-code-coverage-backend@0.2.11 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## @backstage/plugin-codescene@0.1.13 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-config-schema@0.1.41 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/plugin-cost-insights@0.12.7 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-cost-insights-common@0.1.1 + +## @backstage/plugin-dynatrace@5.0.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-entity-feedback@0.2.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/plugin-entity-feedback-common@0.1.1 + +## @backstage/plugin-entity-feedback-backend@0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/plugin-entity-feedback-common@0.1.1 + +## @backstage/plugin-entity-validation@0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/plugin-catalog-common@1.0.13 + +## @backstage/plugin-events-backend@0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/plugin-events-node@0.2.6 + +## @backstage/plugin-events-backend-module-azure@0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.2 + - @backstage/plugin-events-node@0.2.6 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.2 + - @backstage/plugin-events-node@0.2.6 + +## @backstage/plugin-events-backend-module-gerrit@0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.2 + - @backstage/plugin-events-node@0.2.6 + +## @backstage/plugin-events-backend-module-github@0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/plugin-events-node@0.2.6 + +## @backstage/plugin-events-backend-module-gitlab@0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/plugin-events-node@0.2.6 + +## @backstage/plugin-events-backend-test-utils@0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.6 + +## @backstage/plugin-events-node@0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.2 + +## @backstage/plugin-explore@0.4.3 + +### Patch Changes + +- 1996920782b: Make sure that the first support button row does not break across lines +- 4851581deb6: Display the title of the entity on the explore card if present, otherwise stick to the name +- a6025e25d99: Updated the example code in the "Customization" section of the README to make the imports match the components used. +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/plugin-search-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-explore-react@0.0.28 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-explore-backend@0.0.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-search-backend-module-explore@0.1.1 + - @backstage/config@1.0.7 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-firehydrant@0.2.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-fossa@0.2.50 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-gcalendar@0.3.14 + +### Patch Changes + +- f493ccb9589: Pass user info email scope on auth refresh to resolve invalid credentials error +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-gcp-projects@0.3.37 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-git-release-manager@0.3.31 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-github-actions@0.5.18 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-github-deployments@0.1.49 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-github-issues@0.2.7 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-github-pull-requests-board@0.1.12 + +### Patch Changes + +- cf125c36569: The `EntityTeamPullRequestsContent` and `EntityTeamPullRequestsCard` support the ability to view the labels/tags added to each PR +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-gitops-profiles@0.3.36 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-gocd@0.1.24 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-graphiql@0.2.50 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-graphql-backend@0.1.35 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config@1.0.7 + - @backstage/plugin-catalog-graphql@0.3.20 + +## @backstage/plugin-graphql-voyager@0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-home@0.5.2 + +### Patch Changes + +- acca8966465: Remove object-hash dependency +- 957cd9b8958: Use the semantic time tag for rendering world clocks on homepage headers. +- 0e19e7b0f3a: Bump to using the later v5 versions of `@rjsf/*` +- 5272cfabc3b: Add missing @rjsf/core dependency +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-ilert@0.2.7 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-kafka@0.3.18 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-kafka-backend@0.2.38 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## @backstage/plugin-kubernetes-common@0.6.3 + +### Patch Changes + +- 05f1d74539d: AKS access tokens can now be sent over the wire to the Kubernetes backend. +- Updated dependencies + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-permission-common@0.7.5 + +## @backstage/plugin-lighthouse@0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-lighthouse-common@0.1.1 + +## @backstage/plugin-lighthouse-backend@0.2.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/types@1.0.2 + - @backstage/plugin-lighthouse-common@0.1.1 + +## @backstage/plugin-linguist@0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/plugin-linguist-common@0.1.0 + +## @backstage/plugin-linguist-backend@0.2.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-linguist-common@0.1.0 + +## @backstage/plugin-microsoft-calendar@0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-newrelic@0.3.36 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-newrelic-dashboard@0.2.11 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-org@0.6.8 + +### Patch Changes + +- 6e387c077a4: Changed the MembersListCard component to allow displaying aggregated members when viewing a group. Now, a toggle switch can be displayed that lets you switch between showing direct members and aggregated members. + + To enable this new feature, set the showAggregateMembersToggle prop on EntityMembersListCard: + + ```jsx + // In packages/app/src/components/catalog/EntityPage.tsx + const groupPage = ( + // ... + + // ... + ); + ``` + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-org-react@0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-pagerduty@0.5.11 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-periskop@0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-periskop-backend@0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + +## @backstage/plugin-permission-backend@0.5.20 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-permission-common@0.7.5 + +## @backstage/plugin-permission-node@0.7.8 + +### Patch Changes + +- a788e715cfc: `createPermissionIntegrationRouter` now accepts rules and permissions for multiple resource types. Example: + + ```typescript + createPermissionIntegrationRouter({ + resources: [ + { + resourceType: 'resourceType-1', + permissions: permissionsResourceType1, + rules: rulesResourceType1, + }, + { + resourceType: 'resourceType-2', + permissions: permissionsResourceType2, + rules: rulesResourceType2, + }, + ], + }); + ``` + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-permission-common@0.7.5 + +## @backstage/plugin-playlist@0.1.9 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/plugin-search-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-react@0.4.12 + - @backstage/plugin-playlist-common@0.1.6 + +## @backstage/plugin-playlist-backend@0.3.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-playlist-common@0.1.6 + +## @backstage/plugin-proxy-backend@0.2.39 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + +## @backstage/plugin-puppetdb@0.1.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-rollbar@0.4.18 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-rollbar-backend@0.1.42 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config@1.0.7 + +## @backstage/plugin-scaffolder@1.13.1 + +### Patch Changes + +- d560d457c98: Fix case GitLab workspace is a nested subgroup + +- ad1a1429de4: Improvements to the `scaffolder/next` buttons UX: + + - Added padding around the "Create" button in the `Stepper` component + - Added a button bar that includes the "Cancel" and "Start Over" buttons to the `OngoingTask` component. The state of these buttons match their existing counter parts in the Context Menu + - Added a "Show Button Bar"/"Hide Button Bar" item to the `ContextMenu` component + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/integration@1.4.5 + - @backstage/plugin-scaffolder-common@1.3.0 + - @backstage/plugin-scaffolder-react@1.4.0 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-react@0.4.12 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.1.2 + +### Patch Changes + +- 7c116bcac7f: Fixed the way that some request errors are thrown +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.14.0 + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/plugin-scaffolder-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.21 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.14.0 + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/plugin-scaffolder-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.14 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.14.0 + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/plugin-scaffolder-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.5 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.18 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/types@1.0.2 + +## @backstage/plugin-scaffolder-node@0.1.3 + +### Patch Changes + +- 6d954de4b06: Update typing for `RouterOptions::actions` and `ScaffolderActionsExtensionPoint::addActions` to allow any kind of action being assigned to it. +- Updated dependencies + - @backstage/plugin-scaffolder-common@1.3.0 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/types@1.0.2 + +## @backstage/plugin-search-backend@1.3.1 + +### Patch Changes + +- 021cfbb5152: Added an OpenAPI 3.0 spec and enforced schema-first model on the router. +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/plugin-search-backend-node@1.2.1 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-search-backend-module-catalog@0.1.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-search-backend-node@1.2.1 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-search-backend-module-explore@0.1.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-search-backend-node@1.2.1 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-search-backend-module-pg@0.5.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-search-backend-node@1.2.1 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-search-backend-module-techdocs@0.1.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-techdocs-node@1.7.1 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-search-backend-node@1.2.1 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-search-backend-node@1.2.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-sentry@0.5.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-shortcuts@0.3.10 + +### Patch Changes + +- 8a7174e297c: Marked `LocalStoredShortcuts` as deprecated, replacing it with `DefaultShortcutsApi` whose naming more clearly suggests that the shortcuts aren't necessarily stored locally (it depends on the storage implementation). +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/types@1.0.2 + +## @backstage/plugin-sonarqube@0.6.7 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-sonarqube-react@0.1.5 + +## @backstage/plugin-sonarqube-backend@0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## @backstage/plugin-splunk-on-call@0.4.7 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-stack-overflow@0.1.15 + +### Patch Changes + +- c1ff65f315a: StackOverflowSearchResultListItem can now accept an empty result prop so that it can be rendered in the suggested SearchResultListItem pattern. +- Updated dependencies + - @backstage/plugin-home@0.5.2 + - @backstage/theme@0.3.0 + - @backstage/plugin-search-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-stack-overflow-backend@0.2.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config@1.0.7 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-stackstorm@0.1.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-tech-insights@0.3.10 + +### Patch Changes + +- 22963209d23: Added the possibility to customize the check description in the scorecard component. + + - The `CheckResultRenderer` type now exposes an optional `description` method that allows to overwrite the description with a different string or a React component for a provided check result. + + Until now only the `BooleanCheck` element could be overridden, but from now on it's also possible to override the description for a check. + As an example, the description could change depending on the check result. Refer to the [README](https://github.com/backstage/backstage/blob/master/plugins/tech-insights/README.md#adding-custom-rendering-components) file for more details + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10 + +## @backstage/plugin-tech-insights-backend@0.5.11 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-tech-insights-node@0.4.3 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.29 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-tech-insights-node@0.4.3 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-tech-insights-common@0.2.10 + +## @backstage/plugin-tech-insights-node@0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/config@1.0.7 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10 + +## @backstage/plugin-tech-radar@0.6.4 + +### Patch Changes + +- be4fa53fab8: Fix description links when clicking entry in radar. +- Added the ability to display a timeline to each entry in the details box +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-techdocs@1.6.2 + +### Patch Changes + +- 863beb49498: Re-add the possibility to have trailing slashes in Techdocs navigation. +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/integration@1.4.5 + - @backstage/plugin-search-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/plugin-techdocs-react@1.1.6 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.13 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-techdocs@1.6.2 + - @backstage/plugin-catalog@1.11.0 + - @backstage/core-app-api@1.8.0 + - @backstage/plugin-search-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/test-utils@1.3.1 + - @backstage/plugin-techdocs-react@1.1.6 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-techdocs-backend@1.6.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/plugin-techdocs-node@1.7.1 + - @backstage/plugin-search-backend-module-techdocs@0.1.1 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-techdocs-module-addons-contrib@1.0.13 + +### Patch Changes + +- 6afc7f052ca: Show cursor pointer when hovering on lightbox +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/plugin-techdocs-react@1.1.6 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-techdocs-node@1.7.1 + +### Patch Changes + +- 3659c71c5d9: Standardize `@aws-sdk` v3 versions +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/integration-aws-node@0.1.3 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-techdocs-react@1.1.6 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/version-bridge@1.0.4 + +## @backstage/plugin-todo@0.2.20 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-todo-backend@0.1.42 + +### Patch Changes + +- 901f1ada325: Added OpenAPI schema +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## @backstage/plugin-user-settings@0.7.3 + +### Patch Changes + +- 473db605a4f: Fix config schema definition. +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/plugin-user-settings-backend@0.1.9 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/plugin-vault@0.1.12 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-vault-backend@0.3.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## @backstage/plugin-xcmetrics@0.2.38 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## example-app@0.2.83 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-tech-insights@0.3.10 + - @backstage/plugin-scaffolder@1.13.1 + - @backstage/plugin-devtools@0.1.0 + - @backstage/plugin-kubernetes@0.9.0 + - @backstage/plugin-search@1.3.0 + - @backstage/plugin-home@0.5.2 + - @backstage/plugin-explore@0.4.3 + - @backstage/theme@0.3.0 + - @backstage/plugin-techdocs@1.6.2 + - @backstage/app-defaults@1.3.1 + - @backstage/plugin-badges@0.2.42 + - @backstage/plugin-tech-radar@0.6.4 + - @backstage/cli@0.22.7 + - @backstage/plugin-stack-overflow@0.1.15 + - @backstage/plugin-gcalendar@0.3.14 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-app-api@1.8.0 + - @backstage/plugin-scaffolder-react@1.4.0 + - @backstage/plugin-catalog-graph@0.2.30 + - @backstage/plugin-circleci@0.3.18 + - @backstage/plugin-search-react@1.6.0 + - @backstage/plugin-org@0.6.8 + - @backstage/core-components@0.13.1 + - @backstage/plugin-azure-devops@0.3.0 + - @backstage/plugin-jenkins@0.8.0 + - @backstage/plugin-octopus-deploy@0.2.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.13 + - @backstage/plugin-user-settings@0.7.3 + - @backstage/plugin-shortcuts@0.3.10 + - @backstage/integration-react@1.1.13 + - @backstage/plugin-airbrake@0.3.18 + - @backstage/plugin-api-docs@0.9.3 + - @backstage/plugin-azure-sites@0.1.7 + - @backstage/plugin-cloudbuild@0.3.18 + - @backstage/plugin-code-coverage@0.2.11 + - @backstage/plugin-cost-insights@0.12.7 + - @backstage/plugin-dynatrace@5.0.0 + - @backstage/plugin-entity-feedback@0.2.1 + - @backstage/plugin-gcp-projects@0.3.37 + - @backstage/plugin-github-actions@0.5.18 + - @backstage/plugin-gocd@0.1.24 + - @backstage/plugin-graphiql@0.2.50 + - @backstage/plugin-kafka@0.3.18 + - @backstage/plugin-lighthouse@0.4.3 + - @backstage/plugin-linguist@0.1.3 + - @backstage/plugin-microsoft-calendar@0.1.3 + - @backstage/plugin-newrelic@0.3.36 + - @backstage/plugin-pagerduty@0.5.11 + - @backstage/plugin-playlist@0.1.9 + - @backstage/plugin-puppetdb@0.1.1 + - @backstage/plugin-rollbar@0.4.18 + - @backstage/plugin-sentry@0.5.3 + - @backstage/plugin-stackstorm@0.1.2 + - @backstage/plugin-techdocs-react@1.1.6 + - @backstage/plugin-todo@0.2.20 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-apache-airflow@0.2.11 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-catalog-import@0.9.8 + - @backstage/plugin-linguist-common@0.1.0 + - @backstage/plugin-newrelic-dashboard@0.2.11 + - @backstage/plugin-permission-react@0.4.12 + - @backstage/plugin-search-common@1.2.3 + - @internal/plugin-catalog-customized@0.0.10 + +## example-backend@0.2.83 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.14.0 + - @backstage/plugin-devtools-backend@0.1.0 + - @backstage/plugin-catalog-backend@1.9.1 + - @backstage/backend-common@0.18.5 + - @backstage/plugin-kubernetes-backend@0.11.0 + - @backstage/plugin-auth-backend@0.18.3 + - @backstage/plugin-badges-backend@0.2.0 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.0 + - @backstage/integration@1.4.5 + - @backstage/plugin-todo-backend@0.1.42 + - @backstage/plugin-jenkins-backend@0.2.0 + - @backstage/plugin-azure-sites-backend@0.1.7 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/plugin-search-backend@1.3.1 + - example-app@0.2.83 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-app-backend@0.3.45 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/plugin-entity-feedback-backend@0.1.3 + - @backstage/plugin-events-backend@0.2.6 + - @backstage/plugin-playlist-backend@0.3.1 + - @backstage/plugin-rollbar-backend@0.1.42 + - @backstage/plugin-search-backend-module-pg@0.5.6 + - @backstage/plugin-tech-insights-backend@0.5.11 + - @backstage/plugin-techdocs-backend@1.6.2 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.14 + - @backstage/plugin-adr-backend@0.3.3 + - @backstage/plugin-azure-devops-backend@0.3.24 + - @backstage/plugin-code-coverage-backend@0.2.11 + - @backstage/plugin-explore-backend@0.0.7 + - @backstage/plugin-graphql-backend@0.1.35 + - @backstage/plugin-kafka-backend@0.2.38 + - @backstage/plugin-lighthouse-backend@0.2.1 + - @backstage/plugin-linguist-backend@0.2.2 + - @backstage/plugin-permission-backend@0.5.20 + - @backstage/plugin-proxy-backend@0.2.39 + - @backstage/plugin-search-backend-node@1.2.1 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.29 + - @backstage/plugin-tech-insights-node@0.4.3 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/plugin-events-node@0.2.6 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-common@1.2.3 + +## example-backend-next@0.0.11 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.14.0 + - @backstage/plugin-catalog-backend@1.9.1 + - @backstage/plugin-kubernetes-backend@0.11.0 + - @backstage/plugin-todo-backend@0.1.42 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/plugin-search-backend@1.3.1 + - @backstage/backend-defaults@0.1.10 + - @backstage/plugin-app-backend@0.3.45 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/plugin-search-backend-module-catalog@0.1.1 + - @backstage/plugin-search-backend-module-explore@0.1.1 + - @backstage/plugin-search-backend-module-techdocs@0.1.1 + - @backstage/plugin-techdocs-backend@1.6.2 + - @backstage/plugin-permission-backend@0.5.20 + - @backstage/plugin-search-backend-node@1.2.1 + - @backstage/plugin-permission-common@0.7.5 + +## e2e-test@0.2.3 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.1 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.1.5 + +## techdocs-cli-embedded-app@0.2.82 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-techdocs@1.6.2 + - @backstage/app-defaults@1.3.1 + - @backstage/cli@0.22.7 + - @backstage/plugin-catalog@1.11.0 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/test-utils@1.3.1 + - @backstage/plugin-techdocs-react@1.1.6 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @internal/plugin-catalog-customized@0.0.10 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/plugin-catalog@1.11.0 + +## @internal/plugin-todo-list@1.0.13 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + +## @internal/plugin-todo-list-backend@1.0.13 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 diff --git a/docs/releases/v1.14.0-next.2-changelog.md b/docs/releases/v1.14.0-next.2-changelog.md new file mode 100644 index 0000000000..95bbc63953 --- /dev/null +++ b/docs/releases/v1.14.0-next.2-changelog.md @@ -0,0 +1,1334 @@ +# Release v1.14.0-next.2 + +## @backstage/theme@0.3.0-next.0 + +### Minor Changes + +- 98c0c199b15: Updates light theme's primary foreground and `running` status indicator colours to meet WCAG. Previously #2E77D0 changed to #1F5493. + +### Patch Changes + +- 83b45f9df50: Fix accessibility issue with Backstage Table's header style + +## @backstage/plugin-azure-devops@0.3.0-next.2 + +### Minor Changes + +- 877df261085: The getBuildRuns function now checks contains multiple comma-separated builds and splits them to send multiple requests for each and concatenates the results. + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-badges-backend@0.2.0-next.2 + +### Minor Changes + +- a0108c49774: Fixing badges-backend plugin to get a token from the TokenManager instead of parsing the request header. Hence, it's now possible to disable the authMiddleware for the badges-backend plugin to expose publicly the badges. + + Implementing an obfuscation feature to protect an open badges endpoint from being enumerated. The feature is disabled by default and the change is compatible with the previous version. + + **BREAKING**: `createRouter` now require that `tokenManager`, `logger`, and `identityApi`, are passed in as options. + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.7 + +## @backstage/plugin-catalog-backend-module-github@0.3.0-next.2 + +### Minor Changes + +- 970678adbe2: Implement events support for `GithubMultiOrgEntityProvider` + + **BREAKING:** Passing in a custom `teamTransformer` will now correctly completely override the default transformer behavior + +### Patch Changes + +- bd101cefd37: Updated the `team.edited` event emitted from `GithubOrgEntityProvider` to also include teams description. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.1-next.2 + - @backstage/config@1.0.7 + +## @backstage/plugin-devtools@0.1.0-next.0 + +### Minor Changes + +- 347aeca204c: Introduced the DevTools plugin, checkout the plugin's [`README.md`](https://github.com/backstage/backstage/tree/master/plugins/devtools) for more details! + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-devtools-common@0.1.0-next.0 + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + +## @backstage/plugin-devtools-backend@0.1.0-next.0 + +### Minor Changes + +- 347aeca204c: Introduced the DevTools plugin, checkout the plugin's [`README.md`](https://github.com/backstage/backstage/tree/master/plugins/devtools) for more details! + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-devtools-common@0.1.0-next.0 + - @backstage/config@1.0.7 + +## @backstage/plugin-devtools-common@0.1.0-next.0 + +### Minor Changes + +- 347aeca204c: Introduced the DevTools plugin, checkout the plugin's [`README.md`](https://github.com/backstage/backstage/tree/master/plugins/devtools) for more details! + +## @backstage/plugin-events-backend-module-aws-sqs@0.2.0-next.2 + +### Minor Changes + +- 2c5661f3899: Allow endpoint configuration for sqs, enabling use of localstack for testing. + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.7 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.2.0-next.2 + +### Minor Changes + +- 439e2986be1: Add a new scaffolder action for gitlab to ensure a group exists + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.3-next.2 + - @backstage/config@1.0.7 + +## @backstage/plugin-scaffolder-common@1.3.0-next.0 + +### Minor Changes + +- 82e10a6939c: Add support for Markdown text blob outputs from templates + +## @backstage/plugin-scaffolder-react@1.4.0-next.2 + +### Minor Changes + +- 82e10a6939c: Add support for Markdown text blob outputs from templates + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/plugin-scaffolder-common@1.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-search-backend-module-elasticsearch@1.3.0-next.2 + +### Minor Changes + +- 3d72bdb41c7: Upgrade to aws-sdk v3 and include OpenSearch Serverless support + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/integration-aws-node@0.1.2 + +## @backstage/plugin-search-react@1.6.0-next.2 + +### Minor Changes + +- 1ce7f84b2e8: accepts InputProp property that can override keys from default + +### Patch Changes + +- adb31096bc2: Fix text-overflow UI issue for Lifecycle spans in SearchFilter checkbox labels. +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/app-defaults@1.3.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-app-api@1.8.0-next.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + +## @backstage/backend-openapi-utils@0.0.2-next.1 + +### Patch Changes + +- fe16bd39e83: Use permalinks for links including a line number reference +- 021cfbb5152: Corrected resolution of parameter nested schema to use central schemas. + +## @backstage/core-components@0.13.1-next.1 + +### Patch Changes + +- 83b45f9df50: Fix accessibility issue with Backstage Table's header style +- e97769f7c0b: Fix accessibility issue on controlled select input on tab navigation + keyboard enter/space action. +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/create-app@0.5.1-next.2 + +### Patch Changes + +- 1d5e42655cd: Correct command to create new plugins + +## @backstage/dev-utils@1.0.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/app-defaults@1.3.1-next.2 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/test-utils@1.3.1-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-app-api@1.8.0-next.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/integration-react@1.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/test-utils@1.3.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-app-api@1.8.0-next.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + +## @backstage/plugin-adr@0.5.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-search-react@1.6.0-next.2 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-airbrake@0.3.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/dev-utils@1.0.15-next.2 + - @backstage/test-utils@1.3.1-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-allure@0.1.34-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-analytics-module-ga@0.1.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-analytics-module-ga4@0.1.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-apache-airflow@0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-api-docs@0.9.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog@1.11.0-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-apollo-explorer@0.1.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-auth-backend@0.18.3-next.2 + +### Patch Changes + +- 3ffcdac7d07: Added a persistent session store through the database +- Updated dependencies + - @backstage/config@1.0.7 + +## @backstage/plugin-azure-sites@0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-badges@0.2.42-next.2 + +### Patch Changes + +- a0108c49774: Fixing badges-backend plugin to get a token from the TokenManager instead of parsing the request header. Hence, it's now possible to disable the authMiddleware for the badges-backend plugin to expose publicly the badges. + + Implementing an obfuscation feature to protect an open badges endpoint from being enumerated. The feature is disabled by default and the change is compatible with the previous version. + + **BREAKING**: `createRouter` now require that `tokenManager`, `logger`, and `identityApi`, are passed in as options. + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-bazaar@0.2.8-next.2 + +### Patch Changes + +- 900880ab7c3: Fixed `validateDOMNesting` warnings +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/cli@0.22.7-next.0 + - @backstage/plugin-catalog@1.11.0-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-bitrise@0.1.45-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-catalog@1.11.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-search-react@1.6.0-next.2 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-catalog-backend@1.9.1-next.2 + +### Patch Changes + +- ce8d203235b: Ensure that entity cache state is only written to the database when actually changed +- 485a6c5f7b5: Internal refactoring for performance in the service handlers +- 3587a968dcd: Fixed a bug in the `queryEntities` endpoint that was causing filtered entities to be included in cursor requests. +- 12a345317ab: Remove unnecessary join in the entity facets endpoint, exclude nulls +- Updated dependencies + - @backstage/plugin-scaffolder-common@1.3.0-next.0 + - @backstage/config@1.0.7 + +## @backstage/plugin-catalog-backend-module-aws@0.1.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-kubernetes-common@0.6.3-next.0 + - @backstage/config@1.0.7 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.3.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.1-next.2 + - @backstage/config@1.0.7 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.11-next.2 + +### Patch Changes + +- accaceadffa: Fixed bug in `jsonSchemaRefPlaceholderResolver` where relative $ref files were resolved through file system instead of base URL of file +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.1-next.2 + - @backstage/config@1.0.7 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.1.2-next.2 + +### Patch Changes + +- 95b2168d71b: Fixes import paths and updates documentation +- Updated dependencies + - @backstage/config@1.0.7 + +## @backstage/plugin-catalog-graph@0.2.30-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-catalog-import@0.9.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.1-next.1 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-catalog-react@1.6.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + +## @backstage/plugin-cicd-statistics@0.1.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-cicd-statistics@0.1.20-next.2 + +## @backstage/plugin-circleci@0.3.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-cloudbuild@0.3.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-code-climate@0.1.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-code-coverage@0.2.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-codescene@0.1.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-config-schema@0.1.41-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-cost-insights@0.12.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-dynatrace@5.0.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-entity-feedback@0.2.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-entity-validation@0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-explore@0.4.3-next.2 + +### Patch Changes + +- 4851581deb6: Display the title of the entity on the explore card if present, otherwise stick to the name +- a6025e25d99: Updated the example code in the "Customization" section of the README to make the imports match the components used. +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-search-react@1.6.0-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/plugin-explore-react@0.0.28 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-firehydrant@0.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-fossa@0.2.50-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-gcalendar@0.3.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-gcp-projects@0.3.37-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-git-release-manager@0.3.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-github-actions@0.5.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-github-deployments@0.1.49-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-github-issues@0.2.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-github-pull-requests-board@0.1.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-gitops-profiles@0.3.36-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-gocd@0.1.24-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-graphiql@0.2.50-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-graphql-voyager@0.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-home@0.5.2-next.2 + +### Patch Changes + +- acca8966465: Remove object-hash dependency +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-ilert@0.2.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-jenkins@0.7.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-kafka@0.3.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-kubernetes@0.9.0-next.2 + +### Patch Changes + +- c7bad1005ba: The Kubernetes plugin now requests AKS access tokens from Azure when retrieving + objects from clusters configured with `authProvider: aks` and sets `auth.aks` in + its request bodies appropriately. +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-kubernetes-common@0.6.3-next.0 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-kubernetes-backend@0.11.0-next.2 + +### Patch Changes + +- 05f1d74539d: Kubernetes clusters now support `authProvider: aks`. When configured this way, + the `retrieveObjectsByServiceId` action will use the `auth.aks` value in the + request body as a bearer token to authenticate with Kubernetes. +- Updated dependencies + - @backstage/plugin-kubernetes-common@0.6.3-next.0 + - @backstage/config@1.0.7 + - @backstage/integration-aws-node@0.1.2 + +## @backstage/plugin-kubernetes-common@0.6.3-next.0 + +### Patch Changes + +- 05f1d74539d: AKS access tokens can now be sent over the wire to the Kubernetes backend. + +## @backstage/plugin-lighthouse@0.4.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-linguist@0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-microsoft-calendar@0.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-newrelic@0.3.36-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-newrelic-dashboard@0.2.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-octopus-deploy@0.2.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-org@0.6.8-next.2 + +### Patch Changes + +- 6e387c077a4: Changed the MembersListCard component to allow displaying aggregated members when viewing a group. Now, a toggle switch can be displayed that lets you switch between showing direct members and aggregated members. + + To enable this new feature, set the showAggregateMembersToggle prop on EntityMembersListCard: + + ```jsx + // In packages/app/src/components/catalog/EntityPage.tsx + const groupPage = ( + // ... + + // ... + ); + ``` + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-org-react@0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-pagerduty@0.5.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-periskop@0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-playlist@0.1.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-search-react@1.6.0-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + +## @backstage/plugin-puppetdb@0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-rollbar@0.4.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-scaffolder@1.13.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/plugin-scaffolder-common@1.3.0-next.0 + - @backstage/plugin-scaffolder-react@1.4.0-next.2 + - @backstage/core-components@0.13.1-next.1 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + +## @backstage/plugin-scaffolder-backend@1.13.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.1-next.2 + - @backstage/plugin-scaffolder-common@1.3.0-next.0 + - @backstage/plugin-scaffolder-node@0.1.3-next.2 + - @backstage/config@1.0.7 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.13.2-next.2 + - @backstage/plugin-scaffolder-node@0.1.3-next.2 + - @backstage/config@1.0.7 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.13.2-next.2 + - @backstage/plugin-scaffolder-node@0.1.3-next.2 + - @backstage/config@1.0.7 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.13.2-next.2 + - @backstage/plugin-scaffolder-node@0.1.3-next.2 + - @backstage/config@1.0.7 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.3-next.2 + - @backstage/config@1.0.7 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.3-next.2 + - @backstage/config@1.0.7 + +## @backstage/plugin-scaffolder-node@0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-common@1.3.0-next.0 + +## @backstage/plugin-search@1.3.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-search-react@1.6.0-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-search-backend@1.3.1-next.2 + +### Patch Changes + +- 021cfbb5152: Added an OpenAPI 3.0 spec and enforced schema-first model on the router. +- Updated dependencies + - @backstage/config@1.0.7 + +## @backstage/plugin-sentry@0.5.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-shortcuts@0.3.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-sonarqube@0.6.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-splunk-on-call@0.4.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-stack-overflow@0.1.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-home@0.5.2-next.2 + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-search-react@1.6.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-stackstorm@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-tech-insights@0.3.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-tech-radar@0.6.4-next.2 + +### Patch Changes + +- be4fa53fab8: Fix description links when clicking entry in radar. +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-techdocs@1.6.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-search-react@1.6.0-next.2 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/plugin-techdocs-react@1.1.6-next.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-search-react@1.6.0-next.2 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/test-utils@1.3.1-next.2 + - @backstage/plugin-catalog@1.11.0-next.2 + - @backstage/plugin-techdocs@1.6.2-next.2 + - @backstage/plugin-techdocs-react@1.1.6-next.1 + - @backstage/core-app-api@1.8.0-next.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-techdocs-module-addons-contrib@1.0.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/plugin-techdocs-react@1.1.6-next.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-techdocs-react@1.1.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.1-next.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-todo@0.2.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-user-settings@0.7.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-app-api@1.8.0-next.1 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-vault@0.1.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-xcmetrics@0.2.38-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + +## example-app@0.2.83-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-devtools@0.1.0-next.0 + - @backstage/plugin-kubernetes@0.9.0-next.2 + - @backstage/plugin-home@0.5.2-next.2 + - @backstage/theme@0.3.0-next.0 + - @backstage/plugin-badges@0.2.42-next.2 + - @backstage/plugin-tech-radar@0.6.4-next.2 + - @backstage/plugin-scaffolder-react@1.4.0-next.2 + - @backstage/plugin-explore@0.4.3-next.2 + - @backstage/plugin-org@0.6.8-next.2 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-search-react@1.6.0-next.2 + - @backstage/plugin-azure-devops@0.3.0-next.2 + - @backstage/plugin-stack-overflow@0.1.15-next.2 + - @backstage/app-defaults@1.3.1-next.2 + - @backstage/cli@0.22.7-next.0 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/plugin-airbrake@0.3.18-next.2 + - @backstage/plugin-api-docs@0.9.3-next.2 + - @backstage/plugin-azure-sites@0.1.7-next.2 + - @backstage/plugin-catalog-graph@0.2.30-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/plugin-circleci@0.3.18-next.2 + - @backstage/plugin-cloudbuild@0.3.18-next.2 + - @backstage/plugin-code-coverage@0.2.11-next.2 + - @backstage/plugin-cost-insights@0.12.7-next.2 + - @backstage/plugin-dynatrace@5.0.0-next.2 + - @backstage/plugin-entity-feedback@0.2.1-next.2 + - @backstage/plugin-gcalendar@0.3.14-next.1 + - @backstage/plugin-gcp-projects@0.3.37-next.1 + - @backstage/plugin-github-actions@0.5.18-next.2 + - @backstage/plugin-gocd@0.1.24-next.2 + - @backstage/plugin-graphiql@0.2.50-next.1 + - @backstage/plugin-jenkins@0.7.17-next.2 + - @backstage/plugin-kafka@0.3.18-next.2 + - @backstage/plugin-lighthouse@0.4.3-next.2 + - @backstage/plugin-linguist@0.1.3-next.2 + - @backstage/plugin-microsoft-calendar@0.1.3-next.1 + - @backstage/plugin-newrelic@0.3.36-next.1 + - @backstage/plugin-octopus-deploy@0.2.0-next.2 + - @backstage/plugin-pagerduty@0.5.11-next.2 + - @backstage/plugin-playlist@0.1.9-next.2 + - @backstage/plugin-puppetdb@0.1.1-next.2 + - @backstage/plugin-rollbar@0.4.18-next.2 + - @backstage/plugin-scaffolder@1.13.1-next.2 + - @backstage/plugin-search@1.3.0-next.2 + - @backstage/plugin-sentry@0.5.3-next.2 + - @backstage/plugin-shortcuts@0.3.10-next.2 + - @backstage/plugin-stackstorm@0.1.2-next.1 + - @backstage/plugin-tech-insights@0.3.10-next.2 + - @backstage/plugin-techdocs@1.6.2-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.13-next.2 + - @backstage/plugin-techdocs-react@1.1.6-next.1 + - @backstage/plugin-todo@0.2.20-next.2 + - @backstage/plugin-user-settings@0.7.3-next.2 + - @backstage/plugin-apache-airflow@0.2.11-next.1 + - @backstage/plugin-catalog-import@0.9.8-next.2 + - @backstage/plugin-newrelic-dashboard@0.2.11-next.2 + - @backstage/config@1.0.7 + - @backstage/core-app-api@1.8.0-next.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + - @internal/plugin-catalog-customized@0.0.10-next.2 + +## example-backend@0.2.83-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-devtools-backend@0.1.0-next.0 + - @backstage/plugin-catalog-backend@1.9.1-next.2 + - @backstage/plugin-badges-backend@0.2.0-next.2 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.0-next.2 + - @backstage/plugin-kubernetes-backend@0.11.0-next.2 + - @backstage/plugin-auth-backend@0.18.3-next.2 + - @backstage/plugin-search-backend@1.3.1-next.2 + - example-app@0.2.83-next.2 + - @backstage/plugin-scaffolder-backend@1.13.2-next.2 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.14-next.2 + - @backstage/config@1.0.7 + +## example-backend-next@0.0.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.1-next.2 + - @backstage/plugin-kubernetes-backend@0.11.0-next.2 + - @backstage/plugin-search-backend@1.3.1-next.2 + - @backstage/plugin-scaffolder-backend@1.13.2-next.2 + +## e2e-test@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.1-next.2 + +## techdocs-cli-embedded-app@0.2.82-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/app-defaults@1.3.1-next.2 + - @backstage/cli@0.22.7-next.0 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/test-utils@1.3.1-next.2 + - @backstage/plugin-catalog@1.11.0-next.2 + - @backstage/plugin-techdocs@1.6.2-next.2 + - @backstage/plugin-techdocs-react@1.1.6-next.1 + - @backstage/config@1.0.7 + - @backstage/core-app-api@1.8.0-next.1 + - @backstage/core-plugin-api@1.5.1 + +## @internal/plugin-catalog-customized@0.0.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.11.0-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + +## @internal/plugin-todo-list@1.0.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 diff --git a/docs/releases/v1.14.0.md b/docs/releases/v1.14.0.md new file mode 100644 index 0000000000..2c565e2519 --- /dev/null +++ b/docs/releases/v1.14.0.md @@ -0,0 +1,80 @@ +--- +id: v1.14.0 +title: v1.14.0 +description: Backstage Release v1.14.0 +--- + +These are the release notes for the v1.14.0 release of [Backstage](https://backstage.io/). + +A huge thanks to the whole team of maintainers and contributors as well as the amazing Backstage Community for their hard work in getting this release developed and done. + +## Highlights + +This release has an important security fix, along with a lot of squashed bugs and exciting additions! Enjoy. + +### **BREAKING**: Tweaks to the OpenAPI tooling + +There’s been further work made on the OpenAPI tooling! One of the changes is that the commands for this feature are grouped under a `schema openapi` subcommand. This lets us structure things a bit better for the future. The generated file now also has a `.generated.ts` extension, to more easily be able to keep it apart in linting and similar. + +### **BREAKING**: Kubernetes plugin log viewer and tweaks + +There’s been some awesome additions made to the Kubernetes plugin, including the ability to show pod logs! To support this, some breaking changes were made in some of its interfaces. Check out [#17120](https://github.com/backstage/backstage/pull/17120) for some details of what changed. + +### **DEPRECATION**: React 16 + +We are preparing for React 18, and as part of doing that, we are now officially deprecating support for React 16. Nothing will break for you just yet, but if you are still on React 16 your `backstage-cli` commands will start to show helpful warning messages guiding you to bump to version 17 when you can. + +See [#17752](https://github.com/backstage/backstage/pull/17752) for some details about this, and links to the relevant issues. + +### New plugin: DevTools + +This plugin is focused on integrators rather than end users. It allows you to see useful information about your Backstage installation, such as what operating system and NodeJS version it’s running on, what Backstage and individual package versions you have, and more! This may serve as a foundation for adding even more ops focused features in the future. + +Contributed by [@awanlin](https://github.com/awanlin) in [#17393](https://github.com/backstage/backstage/pull/17393) + +### Migration to AWS-SDK version 3 + +There’s been work done under the hood to migrate AWS features over to using v3 of their client SDKs. While this should mostly go below the radar and ultimately work the same as it did before, do reach out to us if you encounter any problems that might be related to this migration. + +There’s actually a minor interface breakage as part of this, where `AwsIamKubernetesAuthTranslator` has some methods removed, but that’s one which may not have a lot of use outside of the package. + +Contributed by [@aochsner](https://github.com/aochsner), see PRs linked at the bottom of issue [#16470](https://github.com/backstage/backstage/issues/16470) + +### Persistent session store for the auth backend + +For auth providers that use session storage, those sessions are now persisted in the auth backend database, instead of in local memory. This should make session handling work better across scaled auth backend instances. + +### Markdown Output Support for Software Templates + +You can now output Markdown from the Software Template runs which can provide more data to the end user after a job has completed in the outputs section of `scaffolder/next` + +Contributed by [@voximity](https://github.com/voximity) in [#17641](https://github.com/backstage/backstage/pull/17641) + +### Refactored Configuration Loading + +The configuration loading system has been refactored to make it easier to extend the system with additional sources of configuration. See the [initial PR](https://github.com/backstage/backstage/pull/17209) and the [`@backstage/config-loader` changelog](https://github.com/backstage/backstage/blob/master/packages/config-loader/CHANGELOG.md#130) for more details. + +### Catalog database performance tweaks + +We found some hotspots in the catalog database operations, and streamlined them. Hopefully this should be noticeable in the form of slightly lower CPU and IOPS usage. + +## Security Fixes + +A [security flaw in the `vm2` package](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-32314) used by the Scaffolder plugin was patched by our automated security processes in [#17810](https://github.com/backstage/backstage/pull/17810). The fixed version of `vm2` was already covered by the required version range of the Scaffolder plugin, so adopters are able to address this vulnerability separately without upgrading Backstage itself, as part of their regular security processes. + +## Upgrade path + +We recommend that you keep your Backstage project up to date with this latest release. For more guidance on how to upgrade, check out the documentation for [keeping Backstage updated](https://backstage.io/docs/getting-started/keeping-backstage-updated). + +## Links and References + +Below you can find a list of links and references to help you learn about and start using this new release. + +- [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/) +- [GitHub repository](https://github.com/backstage/backstage) +- Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support +- [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.14.0-changelog.md) +- Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) + +Sign up for our [newsletter](https://mailchi.mp/spotify/backstage-community) if you want to be informed about what is happening in the world of Backstage. diff --git a/docs/releases/v1.15.0-next.0-changelog.md b/docs/releases/v1.15.0-next.0-changelog.md new file mode 100644 index 0000000000..ce28ca0bbf --- /dev/null +++ b/docs/releases/v1.15.0-next.0-changelog.md @@ -0,0 +1,2440 @@ +# Release v1.15.0-next.0 + +## @backstage/app-defaults@1.4.0-next.0 + +### Minor Changes + +- 1fd38bc4141a: **MUI v5 Support:** Adding platform-wide support for MUI v5 allowing a transition phase for migrating central plugins & components over. We still support v4 instances & plugins by adding a + + To allow the future support of plugins & components using MUI v5 you want to upgrade your `AppTheme`'s to using the `UnifiedThemeProvider` + + ```diff + Provider: ({ children }) => ( + - + - {children} + - + + + ), + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + +## @backstage/test-utils@1.4.0-next.0 + +### Minor Changes + +- 1fd38bc4141a: Test App Wrapper is now using `UnifiedThemeProvider` for supporting MUI v5 next to MUI v4 in tests. + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-app-api@1.8.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.5 + +## @backstage/theme@0.4.0-next.0 + +### Minor Changes + +- 1fd38bc4141a: **MUI v5 Support:** Adding platform-wide support for MUI v5 allowing a transition phase for migrating central plugins & components over. We still support v4 instances & plugins by adding a + + To allow the future support of plugins & components using MUI v5 you want to upgrade your `AppTheme`'s to using the `UnifiedThemeProvider` + + ```diff + Provider: ({ children }) => ( + - + - {children} + - + + + ), + ``` + +## @backstage/plugin-catalog-react@1.7.0-next.0 + +### Minor Changes + +- cb4c15989b6b: The `EntityOwnerPicker` component has undergone improvements to enhance its performance. + + The component now loads entities asynchronously, resulting in improved performance and responsiveness. Instead of loading all entities upfront, they are now loaded in batches as the user scrolls. + The previous implementation inferred users and groups displayed by the `EntityOwnerPicker` component based on the entities available in the `EntityListContext`. The updated version no longer relies on the `EntityListContext` for inference, allowing for better decoupling and improved performance. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.4 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + +## @backstage/plugin-github-actions@0.6.0-next.0 + +### Minor Changes + +- 96e1004e2a02: Added support GitHub Enterprise hosted repositories. + + **BREAKING**: The `GithubActionsClient` is updated to take an `scmAuthApi` instead of the previous `githubAuthApi`. This does not require any code changes unless you construct your own `GithubActionsClient` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-home-react@0.1.0-next.0 + +### Minor Changes + +- 41e8037a8a6d: Extract new plugin-home-react package and deprecate createCardExtension in plugin-home + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-linguist-backend@0.3.0-next.0 + +### Minor Changes + +- bbf91840a52a: **BREAKING**: Removed public constructor from `LinguistBackendApi`. Removed export of `LinguistBackendDatabase` and `LinguistBackendStore` + + Several improvements to the Linguist backend have been made: + + - Added tests for the `LinguistBackendDatabase` and `LinguistBackendApi` + - Added support for using SQLite as a database, helpful for local development + - Removed the default from the `processes_date` column + - Converted the `LinguistBackendApi` into an Interface + - Added the `LinguistBackendClient` which implements the `LinguistBackendApi` Interface + - Unprocessed entities will get processed before stale entities + - Entities in the Linguist database but not in the Catalog anymore will be deleted + - Improved the README's headings + +### Patch Changes + +- 3d11596a72b5: Update plugin installation docs to be more consistent across documentations +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-linguist-common@0.1.0 + +## @backstage/backend-app-api@0.4.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.3.1-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-permission-node@0.7.9-next.0 + +## @backstage/backend-common@0.18.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.3.1-next.0 + - @backstage/backend-app-api@0.4.4-next.0 + - @backstage/integration@1.4.5 + - @backstage/integration-aws-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/backend-dev-utils@0.1.1 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/backend-defaults@0.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-app-api@0.4.4-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/backend-plugin-api@0.5.3-next.0 + +## @backstage/backend-plugin-api@0.5.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-permission-common@0.7.5 + +## @backstage/backend-tasks@0.5.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/backend-test-utils@0.1.38-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-app-api@0.4.4-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.15-next.0 + +## @backstage/catalog-client@1.4.2-next.0 + +### Patch Changes + +- cc936b529676: Updated API docs +- Updated dependencies + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/cli@0.22.8-next.0 + +### Patch Changes + +- 20b7da6f1311: Enforcing MUI v5 specific linting to minimize bundle size. +- Updated dependencies + - @backstage/config-loader@1.3.1-next.0 + - @backstage/config@1.0.7 + - @backstage/release-manifests@0.0.9 + - @backstage/cli-common@0.1.12 + - @backstage/cli-node@0.1.0 + - @backstage/errors@1.1.5 + - @backstage/eslint-plugin@0.1.3 + - @backstage/types@1.0.2 + +## @backstage/config-loader@1.3.1-next.0 + +### Patch Changes + +- f25427f665f7: Fix a bug where config items with `/` in the key were incorrectly handled. +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/core-components@0.13.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/version-bridge@1.0.4 + +## @backstage/create-app@0.5.2-next.0 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.12 + +## @backstage/dev-utils@1.0.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/test-utils@1.4.0-next.0 + - @backstage/app-defaults@1.4.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/catalog-model@1.3.0 + +## @backstage/integration-react@1.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## @techdocs/cli@1.4.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/cli-common@0.1.12 + - @backstage/plugin-techdocs-node@1.7.2-next.0 + +## @backstage/plugin-adr@0.6.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/plugin-search-react@1.6.1-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-adr-common@0.2.9 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-adr-backend@0.3.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-adr-common@0.2.9 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-airbrake@0.3.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/test-utils@1.4.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/dev-utils@1.0.16-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-airbrake-backend@0.2.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + +## @backstage/plugin-allure@0.1.35-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-analytics-module-ga@0.1.30-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-analytics-module-ga4@0.1.1-next.0 + +### Patch Changes + +- 3d11596a72b5: Update plugin installation docs to be more consistent across documentations +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-apache-airflow@0.2.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-api-docs@0.9.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/plugin-catalog@1.11.1-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-apollo-explorer@0.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-app-backend@0.3.46-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.3.1-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/types@1.0.2 + +## @backstage/plugin-auth-backend@0.18.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.15-next.0 + +## @backstage/plugin-auth-node@0.2.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## @backstage/plugin-azure-devops@0.3.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-azure-devops-common@0.3.0 + +## @backstage/plugin-azure-devops-backend@0.3.25-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/plugin-azure-devops-common@0.3.0 + +## @backstage/plugin-azure-sites@0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-azure-sites-common@0.1.0 + +## @backstage/plugin-azure-sites-backend@0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/plugin-azure-sites-common@0.1.0 + +## @backstage/plugin-badges@0.2.43-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-badges-backend@0.2.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-auth-node@0.2.15-next.0 + +## @backstage/plugin-bazaar@0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/cli@0.22.8-next.0 + - @backstage/plugin-catalog@1.11.1-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-bazaar-backend@0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-auth-node@0.2.15-next.0 + +## @backstage/plugin-bitrise@0.1.46-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-catalog@1.11.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/plugin-search-react@1.6.1-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-catalog-backend@1.9.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-node@0.7.9-next.0 + - @backstage/plugin-scaffolder-common@1.3.0 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-catalog-backend-module-aws@0.2.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/integration-aws-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-kubernetes-common@0.6.3 + +## @backstage/plugin-catalog-backend-module-azure@0.1.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.6 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-bitbucket-cloud-common@0.2.6 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-events-node@0.2.7-next.0 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-catalog-backend-module-github@0.3.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-backend@1.9.2-next.0 + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-events-node@0.2.7-next.0 + +## @backstage/plugin-catalog-backend-module-gitlab@0.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.3.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.2-next.0 + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-events-node@0.2.7-next.0 + - @backstage/plugin-permission-common@0.7.5 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + +## @backstage/plugin-catalog-backend-module-msgraph@0.5.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-catalog-common@1.0.13 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.2-next.0 + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-graph@0.2.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-catalog-import@0.9.9-next.0 + +### Patch Changes + +- 2ef84c05aee7: Added analytics event for import entity button +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-catalog-common@1.0.13 + +## @backstage/plugin-catalog-node@1.3.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + +## @backstage/plugin-cicd-statistics@0.1.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-cicd-statistics@0.1.21-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-circleci@0.3.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-cloudbuild@0.3.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-code-climate@0.1.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-code-coverage@0.2.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-code-coverage-backend@0.2.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-codescene@0.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-config-schema@0.1.42-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/plugin-cost-insights@0.12.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-cost-insights-common@0.1.1 + +## @backstage/plugin-devtools@0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-devtools-common@0.1.0 + +## @backstage/plugin-devtools-backend@0.1.1-next.0 + +### Patch Changes + +- 3d11596a72b5: Update plugin installation docs to be more consistent across documentations +- Updated dependencies + - @backstage/config-loader@1.3.1-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-devtools-common@0.1.0 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-node@0.7.9-next.0 + +## @backstage/plugin-dynatrace@6.0.0-next.0 + +### Patch Changes + +- 3d11596a72b5: Update plugin installation docs to be more consistent across documentations +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-entity-feedback@0.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-entity-feedback-common@0.1.1 + +## @backstage/plugin-entity-feedback-backend@0.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-entity-feedback-common@0.1.1 + +## @backstage/plugin-entity-validation@0.1.4-next.0 + +### Patch Changes + +- 3d11596a72b5: Update plugin installation docs to be more consistent across documentations +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-catalog-common@1.0.13 + +## @backstage/plugin-events-backend@0.2.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/plugin-events-node@0.2.7-next.0 + +## @backstage/plugin-events-backend-module-aws-sqs@0.2.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/types@1.0.2 + - @backstage/plugin-events-node@0.2.7-next.0 + +## @backstage/plugin-events-backend-module-azure@0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/plugin-events-node@0.2.7-next.0 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/plugin-events-node@0.2.7-next.0 + +## @backstage/plugin-events-backend-module-gerrit@0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/plugin-events-node@0.2.7-next.0 + +## @backstage/plugin-events-backend-module-github@0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/plugin-events-node@0.2.7-next.0 + +## @backstage/plugin-events-backend-module-gitlab@0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/plugin-events-node@0.2.7-next.0 + +## @backstage/plugin-events-backend-test-utils@0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.7-next.0 + +## @backstage/plugin-events-node@0.2.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.3-next.0 + +## @backstage/plugin-explore@0.4.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-explore-react@0.0.28 + - @backstage/plugin-search-react@1.6.1-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-explore-backend@0.0.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-module-explore@0.1.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-firehydrant@0.2.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-fossa@0.2.51-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-gcalendar@0.3.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-gcp-projects@0.3.38-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-git-release-manager@0.3.32-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-github-deployments@0.1.50-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-github-issues@0.2.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-github-pull-requests-board@0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-gitops-profiles@0.3.37-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-gocd@0.1.25-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-graphiql@0.2.51-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-graphql-backend@0.1.36-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/plugin-catalog-graphql@0.3.20 + +## @backstage/plugin-graphql-voyager@0.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-home@0.5.3-next.0 + +### Patch Changes + +- 41e8037a8a6d: Extract new plugin-home-react package and deprecate createCardExtension in plugin-home +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/plugin-home-react@0.1.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-ilert@0.2.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-jenkins@0.8.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/plugin-jenkins-common@0.1.16-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-jenkins-backend@0.2.1-next.0 + +### Patch Changes + +- 6c244b42cb06: Expose permissions through the metadata endpoint. +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-jenkins-common@0.1.16-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-node@0.7.9-next.0 + +## @backstage/plugin-jenkins-common@0.1.16-next.0 + +### Patch Changes + +- 35e11314d7e9: Export list of permissions +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + +## @backstage/plugin-kafka@0.3.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-kafka-backend@0.2.39-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-kubernetes@0.9.2-next.0 + +### Patch Changes + +- dc3cddf51ab5: Fix cyclical dependency in built output +- 4b230b97660d: Add errors to PodDrawer +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-kubernetes-common@0.6.3 + +## @backstage/plugin-kubernetes-backend@0.11.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration-aws-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-kubernetes-common@0.6.3 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-node@0.7.9-next.0 + +## @backstage/plugin-lighthouse@0.4.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-lighthouse-common@0.1.1 + +## @backstage/plugin-lighthouse-backend@0.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/types@1.0.2 + - @backstage/plugin-lighthouse-common@0.1.1 + +## @backstage/plugin-linguist@0.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-linguist-common@0.1.0 + +## @backstage/plugin-microsoft-calendar@0.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-newrelic@0.3.37-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-newrelic-dashboard@0.2.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-octopus-deploy@0.2.1-next.0 + +### Patch Changes + +- 944a8ac6fcc0: Improved getting started documentation +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-org@0.6.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-org-react@0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-pagerduty@0.5.12-next.0 + +### Patch Changes + +- 3d11596a72b5: Update plugin installation docs to be more consistent across documentations +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-periskop@0.1.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-periskop-backend@0.1.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + +## @backstage/plugin-permission-backend@0.5.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-node@0.7.9-next.0 + +## @backstage/plugin-permission-node@0.7.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-permission-common@0.7.5 + +## @backstage/plugin-playlist@0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + - @backstage/plugin-search-react@1.6.1-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-playlist-common@0.1.6 + +## @backstage/plugin-playlist-backend@0.3.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-node@0.7.9-next.0 + - @backstage/plugin-playlist-common@0.1.6 + +## @backstage/plugin-proxy-backend@0.2.40-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + +## @backstage/plugin-puppetdb@0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-rollbar@0.4.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-rollbar-backend@0.1.43-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + +## @backstage/plugin-scaffolder@1.13.2-next.0 + +### Patch Changes + +- cda753a797b5: Forward `Authorization` header for `EventSource` when credentials are available. +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-scaffolder-react@1.4.1-next.0 + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/plugin-permission-react@0.4.12 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-scaffolder-common@1.3.0 + +## @backstage/plugin-scaffolder-backend@1.14.1-next.0 + +### Patch Changes + +- cc936b529676: Fix handling of `optional` property in `catalog:register` scaffolder action +- b269da39ac2d: Clearer error messages for action `publish:gitlab:merge-request` +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-backend@1.9.2-next.0 + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-node@0.7.9-next.0 + - @backstage/plugin-scaffolder-common@1.3.0 + - @backstage/plugin-scaffolder-node@0.1.4-next.0 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.14.1-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.4-next.0 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.14.1-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.4-next.0 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.2.1-next.0 + +### Patch Changes + +- f5a66052f04f: Tweak README +- Updated dependencies + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-scaffolder-node@0.1.4-next.0 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.14.1-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.4-next.0 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-scaffolder-node@0.1.4-next.0 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.4-next.0 + +## @backstage/plugin-scaffolder-node@0.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-common@1.3.0 + +## @backstage/plugin-scaffolder-react@1.4.1-next.0 + +### Patch Changes + +- 84a5c7724c7e: fixed refresh problem when backstage backend disconnects without any feedback to user. Now we send a generic message and try to reconnect after 15 seconds +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.4 + - @backstage/plugin-scaffolder-common@1.3.0 + +## @backstage/plugin-search@1.3.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-search-react@1.6.1-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.4 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-search-backend@1.3.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-node@0.7.9-next.0 + - @backstage/plugin-search-backend-node@1.2.2-next.0 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-search-backend-module-catalog@0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-backend-node@1.2.2-next.0 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-search-backend-module-elasticsearch@1.3.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration-aws-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/plugin-search-backend-node@1.2.2-next.0 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-search-backend-module-explore@0.1.2-next.0 + +### Patch Changes + +- a5baeea2cb87: Allows for an optional `tokenManager` to authenticate requests from the collator to the explore backend. For example: + + ```diff + indexBuilder.addCollator({ + schedule: every10MinutesSchedule, + factory: ToolDocumentCollatorFactory.fromConfig(env.config, { + discovery: env.discovery, + logger: env.logger, + + tokenManager: env.tokenManager, + }), + }); + ``` + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-backend-node@1.2.2-next.0 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-search-backend-module-pg@0.5.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/plugin-search-backend-node@1.2.2-next.0 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-search-backend-module-techdocs@0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-backend-node@1.2.2-next.0 + - @backstage/plugin-search-common@1.2.3 + - @backstage/plugin-techdocs-node@1.7.2-next.0 + +## @backstage/plugin-search-backend-node@1.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-search-react@1.6.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.4 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-sentry@0.5.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-shortcuts@0.3.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/types@1.0.2 + +## @backstage/plugin-sonarqube@0.6.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-sonarqube-react@0.1.5 + +## @backstage/plugin-sonarqube-backend@0.1.11-next.0 + +### Patch Changes + +- 0bb0b19b0da2: Provide full schema definition for sonarqube plugin, especially to protect api keys. +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## @backstage/plugin-splunk-on-call@0.4.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## @backstage/plugin-stack-overflow@0.1.16-next.0 + +### Patch Changes + +- 41e8037a8a6d: Extract new plugin-home-react package and deprecate createCardExtension in plugin-home +- Updated dependencies + - @backstage/plugin-home-react@0.1.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-search-react@1.6.1-next.0 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-stack-overflow-backend@0.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-stackstorm@0.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## @backstage/plugin-tech-insights@0.3.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10 + +## @backstage/plugin-tech-insights-backend@0.5.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10 + - @backstage/plugin-tech-insights-node@0.4.4-next.0 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.30-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-tech-insights-common@0.2.10 + - @backstage/plugin-tech-insights-node@0.4.4-next.0 + +## @backstage/plugin-tech-insights-node@0.4.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10 + +## @backstage/plugin-tech-radar@0.6.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## @backstage/plugin-techdocs@1.6.3-next.0 + +### Patch Changes + +- 956d09e8ea68: Change deprecated local references to import from shared `plugin-techdocs-react` plugin +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/plugin-techdocs-react@1.1.7-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/plugin-search-react@1.6.1-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.14-next.0 + +### Patch Changes + +- 1fd38bc4141a: Avoiding re-running tests on cleanup. +- Updated dependencies + - @backstage/plugin-techdocs@1.6.3-next.0 + - @backstage/test-utils@1.4.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/plugin-techdocs-react@1.1.7-next.0 + - @backstage/plugin-catalog@1.11.1-next.0 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/plugin-search-react@1.6.1-next.0 + +## @backstage/plugin-techdocs-backend@1.6.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-common@1.2.3 + - @backstage/plugin-techdocs-node@1.7.2-next.0 + +## @backstage/plugin-techdocs-module-addons-contrib@1.0.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/plugin-techdocs-react@1.1.7-next.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + +## @backstage/plugin-techdocs-node@1.7.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/integration-aws-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-search-common@1.2.3 + +## @backstage/plugin-techdocs-react@1.1.7-next.0 + +### Patch Changes + +- 3d11596a72b5: Update plugin installation docs to be more consistent across documentations +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/version-bridge@1.0.4 + +## @backstage/plugin-todo@0.2.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-todo-backend@0.1.43-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-user-settings@0.7.4-next.0 + +### Patch Changes + +- 7a8441b9a323: Reflect the updated sign on status for a provider after signing out. +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## @backstage/plugin-user-settings-backend@0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.15-next.0 + +## @backstage/plugin-vault@0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-vault-backend@0.3.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/errors@1.1.5 + +## @backstage/plugin-xcmetrics@0.2.39-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## example-app@0.2.84-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-kubernetes@0.9.2-next.0 + - @backstage/plugin-user-settings@0.7.4-next.0 + - @backstage/plugin-catalog-import@0.9.9-next.0 + - @backstage/plugin-scaffolder-react@1.4.1-next.0 + - @backstage/plugin-octopus-deploy@0.2.1-next.0 + - @backstage/plugin-scaffolder@1.13.2-next.0 + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/plugin-techdocs@1.6.3-next.0 + - @backstage/plugin-github-actions@0.6.0-next.0 + - @backstage/plugin-stack-overflow@0.1.16-next.0 + - @backstage/plugin-home@0.5.3-next.0 + - @backstage/app-defaults@1.4.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/cli@0.22.8-next.0 + - @backstage/plugin-techdocs-react@1.1.7-next.0 + - @backstage/plugin-dynatrace@6.0.0-next.0 + - @backstage/plugin-pagerduty@0.5.12-next.0 + - @backstage/plugin-catalog-graph@0.2.31-next.0 + - @backstage/plugin-org@0.6.9-next.0 + - @backstage/plugin-airbrake@0.3.19-next.0 + - @backstage/plugin-api-docs@0.9.4-next.0 + - @backstage/plugin-azure-devops@0.3.1-next.0 + - @backstage/plugin-azure-sites@0.1.8-next.0 + - @backstage/plugin-badges@0.2.43-next.0 + - @internal/plugin-catalog-customized@0.0.11-next.0 + - @backstage/plugin-circleci@0.3.19-next.0 + - @backstage/plugin-cloudbuild@0.3.19-next.0 + - @backstage/plugin-code-coverage@0.2.12-next.0 + - @backstage/plugin-cost-insights@0.12.8-next.0 + - @backstage/plugin-entity-feedback@0.2.2-next.0 + - @backstage/plugin-explore@0.4.4-next.0 + - @backstage/plugin-gocd@0.1.25-next.0 + - @backstage/plugin-jenkins@0.8.1-next.0 + - @backstage/plugin-kafka@0.3.19-next.0 + - @backstage/plugin-lighthouse@0.4.4-next.0 + - @backstage/plugin-linguist@0.1.4-next.0 + - @backstage/plugin-newrelic-dashboard@0.2.12-next.0 + - @backstage/plugin-playlist@0.1.10-next.0 + - @backstage/plugin-puppetdb@0.1.2-next.0 + - @backstage/plugin-rollbar@0.4.19-next.0 + - @backstage/plugin-search@1.3.1-next.0 + - @backstage/plugin-sentry@0.5.4-next.0 + - @backstage/plugin-tech-insights@0.3.11-next.0 + - @backstage/plugin-todo@0.2.21-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.14-next.0 + - @backstage/config@1.0.7 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/plugin-apache-airflow@0.2.12-next.0 + - @backstage/plugin-devtools@0.1.1-next.0 + - @backstage/plugin-gcalendar@0.3.15-next.0 + - @backstage/plugin-gcp-projects@0.3.38-next.0 + - @backstage/plugin-graphiql@0.2.51-next.0 + - @backstage/plugin-microsoft-calendar@0.1.4-next.0 + - @backstage/plugin-newrelic@0.3.37-next.0 + - @backstage/plugin-permission-react@0.4.12 + - @backstage/plugin-search-react@1.6.1-next.0 + - @backstage/plugin-shortcuts@0.3.11-next.0 + - @backstage/plugin-stackstorm@0.1.3-next.0 + - @backstage/plugin-tech-radar@0.6.5-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-linguist-common@0.1.0 + - @backstage/plugin-search-common@1.2.3 + +## example-backend@0.2.84-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-scaffolder-backend@1.14.1-next.0 + - @backstage/plugin-jenkins-backend@0.2.1-next.0 + - @backstage/plugin-linguist-backend@0.3.0-next.0 + - @backstage/plugin-devtools-backend@0.1.1-next.0 + - @backstage/plugin-adr-backend@0.3.4-next.0 + - @backstage/plugin-auth-backend@0.18.4-next.0 + - @backstage/plugin-badges-backend@0.2.1-next.0 + - @backstage/plugin-catalog-backend@1.9.2-next.0 + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/plugin-code-coverage-backend@0.2.12-next.0 + - @backstage/plugin-entity-feedback-backend@0.1.4-next.0 + - @backstage/plugin-kubernetes-backend@0.11.1-next.0 + - @backstage/plugin-lighthouse-backend@0.2.2-next.0 + - @backstage/plugin-playlist-backend@0.3.2-next.0 + - @backstage/plugin-tech-insights-backend@0.5.12-next.0 + - @backstage/plugin-techdocs-backend@1.6.3-next.0 + - @backstage/plugin-todo-backend@0.1.43-next.0 + - example-app@0.2.84-next.0 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.15-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/plugin-app-backend@0.3.46-next.0 + - @backstage/plugin-explore-backend@0.0.8-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-azure-devops-backend@0.3.25-next.0 + - @backstage/plugin-azure-sites-backend@0.1.8-next.0 + - @backstage/plugin-events-backend@0.2.7-next.0 + - @backstage/plugin-events-node@0.2.7-next.0 + - @backstage/plugin-graphql-backend@0.1.36-next.0 + - @backstage/plugin-kafka-backend@0.2.39-next.0 + - @backstage/plugin-permission-backend@0.5.21-next.0 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-node@0.7.9-next.0 + - @backstage/plugin-proxy-backend@0.2.40-next.0 + - @backstage/plugin-rollbar-backend@0.1.43-next.0 + - @backstage/plugin-search-backend@1.3.2-next.0 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.1-next.0 + - @backstage/plugin-search-backend-module-pg@0.5.7-next.0 + - @backstage/plugin-search-backend-node@1.2.2-next.0 + - @backstage/plugin-search-common@1.2.3 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.30-next.0 + - @backstage/plugin-tech-insights-node@0.4.4-next.0 + +## example-backend-next@0.0.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.14.1-next.0 + - @backstage/plugin-search-backend-module-explore@0.1.2-next.0 + - @backstage/plugin-catalog-backend@1.9.2-next.0 + - @backstage/plugin-kubernetes-backend@0.11.1-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.2-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.2-next.0 + - @backstage/plugin-techdocs-backend@1.6.3-next.0 + - @backstage/plugin-todo-backend@0.1.43-next.0 + - @backstage/plugin-app-backend@0.3.46-next.0 + - @backstage/backend-defaults@0.1.11-next.0 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-permission-backend@0.5.21-next.0 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-node@0.7.9-next.0 + - @backstage/plugin-search-backend@1.3.2-next.0 + - @backstage/plugin-search-backend-node@1.2.2-next.0 + +## e2e-test@0.2.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.2-next.0 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.1.5 + +## techdocs-cli-embedded-app@0.2.83-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs@1.6.3-next.0 + - @backstage/test-utils@1.4.0-next.0 + - @backstage/app-defaults@1.4.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/cli@0.22.8-next.0 + - @backstage/plugin-techdocs-react@1.1.7-next.0 + - @backstage/plugin-catalog@1.11.1-next.0 + - @backstage/config@1.0.7 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/catalog-model@1.3.0 + +## @internal/plugin-catalog-customized@0.0.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/plugin-catalog@1.11.1-next.0 + +## @internal/plugin-todo-list@1.0.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## @internal/plugin-todo-list-backend@1.0.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-auth-node@0.2.15-next.0 diff --git a/docs/tutorials/switching-sqlite-postgres.md b/docs/tutorials/switching-sqlite-postgres.md index b87a77f4ed..87afabda60 100644 --- a/docs/tutorials/switching-sqlite-postgres.md +++ b/docs/tutorials/switching-sqlite-postgres.md @@ -37,7 +37,7 @@ backend: connection: ':memory:' # highlight-remove-end # highlight-add-start - # config options: https://node-postgres.com/api/client + # config options: https://node-postgres.com/apis/client client: pg connection: host: ${POSTGRES_HOST} @@ -72,7 +72,7 @@ backend: connection: ':memory:' # highlight-remove-end # highlight-add-start - # config options: https://node-postgres.com/api/client + # config options: https://node-postgres.com/apis/client client: pg connection: host: ${POSTGRES_HOST} diff --git a/microsite/data/plugins/3scale.yaml b/microsite/data/plugins/3scale.yaml new file mode 100644 index 0000000000..c190ed7e9e --- /dev/null +++ b/microsite/data/plugins/3scale.yaml @@ -0,0 +1,10 @@ +--- +title: APIs with 3scale +author: Red Hat +authorUrl: https://redhat.com +category: Discovery +description: Synchronize 3scale content into the Backstage catalog. +documentation: https://janus-idp.io/plugins/3scale +iconUrl: http://janus-idp.io/images/plugins/3scale.svg +npmPackageName: '@janus-idp/backstage-plugin-3scale-backend' +addedDate: '2023-05-15' diff --git a/microsite/data/plugins/aws-app-development.yaml b/microsite/data/plugins/aws-app-development.yaml new file mode 100644 index 0000000000..3944bbb4e0 --- /dev/null +++ b/microsite/data/plugins/aws-app-development.yaml @@ -0,0 +1,10 @@ +--- +title: AWS App Developer Tools +author: Amazon Web Services +authorUrl: https://aws.amazon.com/ +category: Infrastructure +description: Create and manage AWS Apps within Backstage +documentation: https://github.com/awslabs/app-development-for-backstage-io-on-aws#readme +iconUrl: https://github.com/awslabs/app-development-for-backstage-io-on-aws/blob/main/docs/images/AWS_logo.png?raw=true +npmPackageName: '@aws/plugin-aws-apps-for-backstage' +addedDate: '2023-05-10' diff --git a/microsite/data/plugins/catalog-backend-module-puppetdb.yaml b/microsite/data/plugins/catalog-backend-module-puppetdb.yaml index 3eac117e19..e7a15ecd4a 100644 --- a/microsite/data/plugins/catalog-backend-module-puppetdb.yaml +++ b/microsite/data/plugins/catalog-backend-module-puppetdb.yaml @@ -5,7 +5,7 @@ authorUrl: https://github.com/tdabasinskas category: Configuration Management description: Import nodes from PuppetDB into Backstage as Resource Entities documentation: https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-puppetdb/README.md -iconUrl: https://avatars.githubusercontent.com/u/234268?s=200&v=4 +iconUrl: /img/puppet.png npmPackageName: '@backstage/plugin-catalog-backend-module-puppetdb' tags: - puppet diff --git a/microsite/data/plugins/dependencytrack b/microsite/data/plugins/dependencytrack.yaml similarity index 100% rename from microsite/data/plugins/dependencytrack rename to microsite/data/plugins/dependencytrack.yaml diff --git a/microsite/data/plugins/jfrog-artifactory.yaml b/microsite/data/plugins/jfrog-artifactory.yaml new file mode 100644 index 0000000000..279cbc161e --- /dev/null +++ b/microsite/data/plugins/jfrog-artifactory.yaml @@ -0,0 +1,10 @@ +--- +title: Container Image Registry for JFrog Artifactory +author: Red Hat +authorUrl: https://redhat.com +category: Image +description: View container image details from JFrog Artifactory in Backstage. +documentation: https://janus-idp.io/plugins/jfrog-artifactory +iconUrl: http://janus-idp.io/images/plugins/jfrog-artifactory.svg +npmPackageName: '@janus-idp/backstage-plugin-jfrog-artifactory' +addedDate: '2023-05-15' diff --git a/microsite/data/plugins/keycloak.yaml b/microsite/data/plugins/keycloak.yaml new file mode 100644 index 0000000000..882d43f515 --- /dev/null +++ b/microsite/data/plugins/keycloak.yaml @@ -0,0 +1,10 @@ +--- +title: Authentication and Authorization with Keycloak +author: Red Hat +authorUrl: https://redhat.com +category: Authentication +description: Load users and groups from Keycloak, enabling use of multiple authentication providers to be applied to Backstage entities. +documentation: https://janus-idp.io/plugins/keycloak +iconUrl: http://janus-idp.io/images/plugins/keycloak.svg +npmPackageName: '@janus-idp/backstage-plugin-keycloak-backend' +addedDate: '2023-05-15' diff --git a/microsite/data/plugins/kubernetes-provider.yaml b/microsite/data/plugins/kubernetes-provider.yaml new file mode 100644 index 0000000000..e0971d55be --- /dev/null +++ b/microsite/data/plugins/kubernetes-provider.yaml @@ -0,0 +1,10 @@ +--- +title: Kubernetes Entity Provider +author: Antoine Dao +authorUrl: https://github.com/antoinedao +category: Kubernetes +description: Import Kubernetes resources into Backstage Components +documentation: https://github.com/AntoineDao/backstage-provider-kubernetes#readme +iconUrl: https://avatars.githubusercontent.com/u/13629408 +npmPackageName: https://www.npmjs.com/package/@antoinedao/backstage-provider-kubernetes +addedDate: '2023-04-10' diff --git a/microsite/data/plugins/ocm.yaml b/microsite/data/plugins/ocm.yaml new file mode 100644 index 0000000000..15c23a0fb7 --- /dev/null +++ b/microsite/data/plugins/ocm.yaml @@ -0,0 +1,10 @@ +--- +title: Multi Cluster View with OCM +author: Red Hat +authorUrl: https://redhat.com +category: OCM +description: View clusters from OCM's MultiClusterHub and MultiCluster Engine in Backstage. +documentation: https://janus-idp.io/plugins/ocm +iconUrl: http://janus-idp.io/images/plugins/ocm.svg +npmPackageName: '@janus-idp/backstage-plugin-ocm' +addedDate: '2023-05-15' diff --git a/microsite/data/plugins/quay.yaml b/microsite/data/plugins/quay.yaml new file mode 100644 index 0000000000..e4aeb1ec1a --- /dev/null +++ b/microsite/data/plugins/quay.yaml @@ -0,0 +1,10 @@ +--- +title: Container Image Registry for Quay +author: Red Hat +authorUrl: https://redhat.com +category: Image +description: View container image details from Quay in Backstage. +documentation: https://janus-idp.io/plugins/quay +iconUrl: http://janus-idp.io/images/plugins/quay.svg +npmPackageName: '@janus-idp/backstage-plugin-quay' +addedDate: '2023-05-15' diff --git a/microsite/data/plugins/tekton.yaml b/microsite/data/plugins/tekton.yaml new file mode 100644 index 0000000000..b1ebfb1349 --- /dev/null +++ b/microsite/data/plugins/tekton.yaml @@ -0,0 +1,10 @@ +--- +title: Pipelines with Tekton +author: Red Hat +authorUrl: https://redhat.com +category: CI +description: Easily view Tekton PipelineRun status for your services in Backstage. +documentation: https://janus-idp.io/plugins/tekton +iconUrl: http://janus-idp.io/images/plugins/tekton.svg +npmPackageName: '@janus-idp/backstage-plugin-tekton' +addedDate: '2023-05-15' diff --git a/microsite/data/plugins/topology.yaml b/microsite/data/plugins/topology.yaml new file mode 100644 index 0000000000..2f26f7c755 --- /dev/null +++ b/microsite/data/plugins/topology.yaml @@ -0,0 +1,10 @@ +--- +title: Application Topology for Kubernetes +author: Red Hat +authorUrl: https://redhat.com +category: Kubernetes +description: Visualize the deployment status and related resources of your applications deployed on any Kubernetes cluster. +documentation: https://janus-idp.io/plugins/topology +iconUrl: http://janus-idp.io/images/plugins/topology.svg +npmPackageName: '@janus-idp/backstage-plugin-topology' +addedDate: '2023-05-15' diff --git a/microsite/data/plugins/xkcd.yaml b/microsite/data/plugins/xkcd.yaml new file mode 100644 index 0000000000..370718a08f --- /dev/null +++ b/microsite/data/plugins/xkcd.yaml @@ -0,0 +1,10 @@ +--- +title: xkcd comic +author: Vity +authorUrl: https://github.com/Vity01 +category: Humor +description: xkcd comic within Backstage +documentation: https://github.com/Vity01/backstage-xkcd/ +iconUrl: https://raw.githubusercontent.com/Vity01/backstage-xkcd/main/docs/xkcd.svg +npmPackageName: 'backstage-plugin-xkcd' +addedDate: '2023-05-05' diff --git a/microsite/docusaurus.config.js b/microsite/docusaurus.config.js index e6137b572b..9985796e3f 100644 --- a/microsite/docusaurus.config.js +++ b/microsite/docusaurus.config.js @@ -173,7 +173,7 @@ module.exports = { position: 'left', }, { - to: 'docs/releases/v1.12.0', + to: 'docs/releases/v1.14.0', label: 'Releases', position: 'left', }, @@ -241,7 +241,7 @@ module.exports = { }, { label: 'Subscribe to our newsletter', - to: 'https://mailchi.mp/spotify/backstage-community', + to: 'https://info.backstage.spotify.com/newsletter_subscribe', }, { label: 'CNCF Incubation', diff --git a/microsite/package.json b/microsite/package.json index 6e20cad4fa..98301ce2d0 100644 --- a/microsite/package.json +++ b/microsite/package.json @@ -17,7 +17,7 @@ "docusaurus": "docusaurus" }, "devDependencies": { - "@docusaurus/module-type-aliases": "0.0.0-5566", + "@docusaurus/module-type-aliases": "0.0.0-5580", "@spotify/prettier-config": "^14.0.0", "@tsconfig/docusaurus": "^1.0.6", "@types/webpack-env": "^1.18.0", @@ -28,9 +28,9 @@ }, "prettier": "@spotify/prettier-config", "dependencies": { - "@docusaurus/core": "0.0.0-5566", - "@docusaurus/plugin-client-redirects": "0.0.0-5566", - "@docusaurus/preset-classic": "0.0.0-5566", + "@docusaurus/core": "0.0.0-5580", + "@docusaurus/plugin-client-redirects": "0.0.0-5580", + "@docusaurus/preset-classic": "0.0.0-5580", "@swc/core": "^1.3.46", "clsx": "^1.1.1", "docusaurus-plugin-sass": "^0.2.3", diff --git a/microsite/sidebars.json b/microsite/sidebars.json index cf2f9b7b56..972a67f424 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -1,6 +1,7 @@ { "releases": { "Release Notes": [ + "releases/v1.14.0", "releases/v1.13.0", "releases/v1.12.0", "releases/v1.11.0", @@ -80,7 +81,8 @@ "features/software-catalog/extending-the-model", "features/software-catalog/external-integrations", "features/software-catalog/catalog-customization", - "features/software-catalog/software-catalog-api" + "features/software-catalog/software-catalog-api", + "features/software-catalog/creating-the-catalog-graph" ] }, { @@ -408,6 +410,7 @@ "label": "Core Services", "items": ["backend-system/core-services/index"] } - ] + ], + "Accessibility": ["accessibility/index"] } } diff --git a/microsite/src/components/pluginsFilter/pluginsFilter.tsx b/microsite/src/components/pluginsFilter/pluginsFilter.tsx new file mode 100644 index 0000000000..4023415fa6 --- /dev/null +++ b/microsite/src/components/pluginsFilter/pluginsFilter.tsx @@ -0,0 +1,39 @@ +import { ChipCategory } from '@site/src/util/types'; +import React from 'react'; + +type Props = { + categories: ChipCategory[]; + handleChipClick: (name: string) => void; +}; + +const PluginsFilter = ({ categories, handleChipClick }: Props) => { + const alphaCategories = categories.sort((a, b) => + a.name.localeCompare(b.name), + ); + return ( +
+ +
    + {alphaCategories.map(chip => { + return ( +
  • handleChipClick(chip.name)}> +
    + handleChipClick(chip.name)} + /> + {chip.name} +
    +
  • + ); + })} +
+
+ ); +}; + +export default PluginsFilter; diff --git a/microsite/src/pages/plugins/index.tsx b/microsite/src/pages/plugins/index.tsx index 280a165daa..b1c9601110 100644 --- a/microsite/src/pages/plugins/index.tsx +++ b/microsite/src/pages/plugins/index.tsx @@ -1,13 +1,13 @@ import Link from '@docusaurus/Link'; import Layout from '@theme/Layout'; import clsx from 'clsx'; -import React from 'react'; - +import React, { useState } from 'react'; import { IPluginData, PluginCard } from './_pluginCard'; import pluginsStyles from './plugins.module.scss'; +import { ChipCategory } from '@site/src/util/types'; import { truncateDescription } from '@site/src/util/truncateDescription'; +import PluginsFilter from '@site/src/components/pluginsFilter/pluginsFilter'; -//#region Plugin data import const pluginsContext = require.context( '../../../data/plugins', false, @@ -29,50 +29,137 @@ const plugins = pluginsContext.keys().reduce( plugins.corePlugins.sort((a, b) => a.order - b.order); plugins.otherPlugins.sort((a, b) => a.order - b.order); -//#endregion -const Plugins = () => ( - -
-
-
-

Plugin Marketplace

+const Plugins = () => { + const allCategoriesSet = new Set( + [...plugins.corePlugins, ...plugins.otherPlugins].map( + ({ category }) => category, + ), + ); + const allCategoriesArray = Array.from(allCategoriesSet).map(category => ({ + name: category, + isSelected: false, + })); + const [categories, setCategories] = + useState(allCategoriesArray); + const [selectedCategories, setSelectedCategories] = useState([]); + const [showCoreFeatures, setShowCoreFeatures] = useState(true); + const [showOtherPlugins, setShowOtherPlugins] = useState(true); -

- Open source plugins that you can add to your Backstage deployment. - Learn how to build a plugin. -

+ const handleChipClick = (categoryName: string) => { + const isSelected = + categories.find(category => category.name === categoryName)?.isSelected || + false; + + const newSelectedCategories = isSelected + ? selectedCategories.filter(c => c !== categoryName) + : [...selectedCategories, categoryName]; + + setSelectedCategories(newSelectedCategories); + + const newCategories = categories.map(category => { + if (category.name === categoryName) { + return { ...category, isSelected: !isSelected }; + } + return category; + }); + + setCategories(newCategories); + + if (!newSelectedCategories.includes('Core Feature')) { + setShowCoreFeatures(false); + } else { + setShowCoreFeatures(true); + } + + if ( + newSelectedCategories.length === 1 && + newSelectedCategories[0] === 'Core Feature' + ) { + setShowOtherPlugins(false); + } else { + setShowOtherPlugins(true); + } + + if (newSelectedCategories.length === 0) { + setShowOtherPlugins(true); + setShowCoreFeatures(true); + } + }; + + return ( + +
+
+
+

Plugin Marketplace

+ +

+ Open source plugins that you can add to your Backstage deployment. + Learn how to build a plugin. +

+
+ + + Add to Marketplace +
- - Add to Marketplace - +
+
+ +
+ + {showCoreFeatures && ( +
+

Core Features

+
+ {plugins.corePlugins + .filter( + pluginData => + !selectedCategories.length || + selectedCategories.includes(pluginData.category), + ) + .map(pluginData => ( + + ))} +
+
+ )} + + {showOtherPlugins && ( +
+

All Plugins

+
+ {plugins.otherPlugins + .filter( + pluginData => + !selectedCategories.length || + selectedCategories.includes(pluginData.category), + ) + .map(pluginData => ( + + ))} +
+
+ )}
- -
- -

Core Features

- -
- {plugins.corePlugins.map(pluginData => ( - - ))} -
- -

All Plugins

- -
- {plugins.otherPlugins.map(pluginData => ( - - ))} -
-
- -); + + ); +}; export default Plugins; diff --git a/microsite/src/pages/plugins/plugins.module.scss b/microsite/src/pages/plugins/plugins.module.scss index bb08c2fd33..d5ea5de6e7 100644 --- a/microsite/src/pages/plugins/plugins.module.scss +++ b/microsite/src/pages/plugins/plugins.module.scss @@ -28,10 +28,60 @@ :global(.pluginsContainer) { gap: 1rem; display: grid; - grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(250px, 300px)); + } + + @media (max-width: 768px) { + :global(.pluginsContainer) { + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + } + } + + :global(.hidePluginsHeader) { + display: none; } :global(.fit-content) { width: fit-content; } + + :global(.pluginsFilterBox) { + width: 100%; + margin-bottom: 1rem; + height: 1rem; + } + + :global(.dropdown) { + float: right; + margin-bottom: 1rem; + } + + :global(.button--info) { + background-color: transparent; + border-color: var(--ifm-color-primary); + color: var(--ifm-color-primary); + min-width: 250px; + } + + :global(label.dropdown__item) { + display: flex; + align-items: center; + cursor: pointer; + margin-top: 5px; + + &:hover { + background-color: var(--ifm-color-primary); + color: black; + } + } + + :global(.dropdown__label) { + font-size: 15px; + cursor: pointer; + } + + :global(.dropdown__checkbox) { + margin-right: 10px; + cursor: pointer; + } } diff --git a/microsite/src/util/types.ts b/microsite/src/util/types.ts new file mode 100644 index 0000000000..fba7c0ba46 --- /dev/null +++ b/microsite/src/util/types.ts @@ -0,0 +1,4 @@ +export type ChipCategory = { + name: string; + isSelected: boolean; +}; diff --git a/microsite/yarn.lock b/microsite/yarn.lock index 10028fc4b4..7097fb337e 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -1620,9 +1620,9 @@ __metadata: languageName: node linkType: hard -"@docusaurus/core@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/core@npm:0.0.0-5566" +"@docusaurus/core@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/core@npm:0.0.0-5580" dependencies: "@babel/core": ^7.20.12 "@babel/generator": ^7.21.1 @@ -1634,13 +1634,13 @@ __metadata: "@babel/runtime": ^7.21.0 "@babel/runtime-corejs3": ^7.21.0 "@babel/traverse": ^7.21.2 - "@docusaurus/cssnano-preset": 0.0.0-5566 - "@docusaurus/logger": 0.0.0-5566 - "@docusaurus/mdx-loader": 0.0.0-5566 + "@docusaurus/cssnano-preset": 0.0.0-5580 + "@docusaurus/logger": 0.0.0-5580 + "@docusaurus/mdx-loader": 0.0.0-5580 "@docusaurus/react-loadable": 5.5.2 - "@docusaurus/utils": 0.0.0-5566 - "@docusaurus/utils-common": 0.0.0-5566 - "@docusaurus/utils-validation": 0.0.0-5566 + "@docusaurus/utils": 0.0.0-5580 + "@docusaurus/utils-common": 0.0.0-5580 + "@docusaurus/utils-validation": 0.0.0-5580 "@slorber/static-site-generator-webpack-plugin": ^4.0.7 "@svgr/webpack": ^6.5.1 autoprefixer: ^10.4.13 @@ -1700,41 +1700,41 @@ __metadata: react-dom: ^16.8.4 || ^17.0.0 bin: docusaurus: bin/docusaurus.mjs - checksum: c85ea103cd3a14dc340533d1cad0627736d87e4336b5919adabd23627958eed108fddb2dd45066944185ebe52a8648a4463a9587804f3a537f0a8deaea3e835e + checksum: 1160559109aa834bcd3dc0210ca824ad6cbdea363951c5cba690c1882c78a7da6e1e52b8a5c35fef3bfc23f9f66e84880c354727b7987d371cac8ec6fb77d1bb languageName: node linkType: hard -"@docusaurus/cssnano-preset@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/cssnano-preset@npm:0.0.0-5566" +"@docusaurus/cssnano-preset@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/cssnano-preset@npm:0.0.0-5580" dependencies: cssnano-preset-advanced: ^5.3.10 postcss: ^8.4.21 postcss-sort-media-queries: ^4.3.0 tslib: ^2.5.0 - checksum: 9aece7f723e7bdeecaa0cc9ce956ef590dfd1c11200f9799236ce80ad94f4653c717a0f16d8694a9f635fb21e0e5bbf3093ba59f8996c012b71062560d9e0fd3 + checksum: 4a46af1e9327d6ebbed3f0f6e60cc1ca59d5c07d39be35c42c13b0a64795b0b1565585adfca063798be79100aca425ee0c12f28a816b56686fb97726bec00f40 languageName: node linkType: hard -"@docusaurus/logger@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/logger@npm:0.0.0-5566" +"@docusaurus/logger@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/logger@npm:0.0.0-5580" dependencies: chalk: ^4.1.2 tslib: ^2.5.0 - checksum: aab288cf6f7c062bb54de296723bbd8deea3029267c49e3f2fb6ab86b462256c4cff805debfd93bd3b35daaefdb9f5bb1a07876434e0b4887e0ec6cf159594d0 + checksum: 5792b6672623b70d38871713c47ba88cc0df6c8d224c28ac58d0512b8bf1b672786cc2fa0b1a79cc045c473e1e14b5a9cce4b01e623dd252893294d6aff9d1c2 languageName: node linkType: hard -"@docusaurus/mdx-loader@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/mdx-loader@npm:0.0.0-5566" +"@docusaurus/mdx-loader@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/mdx-loader@npm:0.0.0-5580" dependencies: "@babel/parser": ^7.21.2 "@babel/traverse": ^7.21.2 - "@docusaurus/logger": 0.0.0-5566 - "@docusaurus/utils": 0.0.0-5566 - "@docusaurus/utils-validation": 0.0.0-5566 + "@docusaurus/logger": 0.0.0-5580 + "@docusaurus/utils": 0.0.0-5580 + "@docusaurus/utils-validation": 0.0.0-5580 "@mdx-js/mdx": ^2.1.5 escape-html: ^1.0.3 estree-util-value-to-estree: ^2.1.0 @@ -1744,6 +1744,7 @@ __metadata: image-size: ^1.0.2 mdast-util-mdx: ^2.0.0 mdast-util-to-string: ^3.0.0 + rehype-raw: ^6.1.1 remark-comment: ^1.0.0 remark-directive: ^2.0.1 remark-emoji: ^2.2.0 @@ -1757,16 +1758,16 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: d4e82a3bdf8eefe7c3996c9ac3860a60f6bb028ab60dce31cef199d22da606631e7eacfeacd4e51c0181d3649026e081c353dea5f01317ec05b48c20b4e8cc39 + checksum: b32812e0bca91a29761fda742a790f67077bb7e8860e20e83f009e297ca49017192fa14051ab82f1a3e66800de9e5a0b561b32ce2dffb4eecc0aee48116d3490 languageName: node linkType: hard -"@docusaurus/module-type-aliases@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/module-type-aliases@npm:0.0.0-5566" +"@docusaurus/module-type-aliases@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/module-type-aliases@npm:0.0.0-5580" dependencies: "@docusaurus/react-loadable": 5.5.2 - "@docusaurus/types": 0.0.0-5566 + "@docusaurus/types": 0.0.0-5580 "@types/history": ^4.7.11 "@types/react": "*" "@types/react-router-config": "*" @@ -1776,19 +1777,19 @@ __metadata: peerDependencies: react: "*" react-dom: "*" - checksum: 6f8a86386c54829f41e28d01a7ffe96b2a3211aaa9fd217f614154726620ce118a0a9bba5563b512bdbc4d3e4a03e1d73848caadbd7fe2b55e59e4ff1ae3633a + checksum: b5b3544f2f2d395c1d406a1b3f03f719aee3aa3fd7603c54af3b09c4fb8bb153cf2ee6697bc9cfc9fb2550a11a3e474a52c9f2c132924e2be60662ffc6379ace languageName: node linkType: hard -"@docusaurus/plugin-client-redirects@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/plugin-client-redirects@npm:0.0.0-5566" +"@docusaurus/plugin-client-redirects@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/plugin-client-redirects@npm:0.0.0-5580" dependencies: - "@docusaurus/core": 0.0.0-5566 - "@docusaurus/logger": 0.0.0-5566 - "@docusaurus/utils": 0.0.0-5566 - "@docusaurus/utils-common": 0.0.0-5566 - "@docusaurus/utils-validation": 0.0.0-5566 + "@docusaurus/core": 0.0.0-5580 + "@docusaurus/logger": 0.0.0-5580 + "@docusaurus/utils": 0.0.0-5580 + "@docusaurus/utils-common": 0.0.0-5580 + "@docusaurus/utils-validation": 0.0.0-5580 eta: ^2.0.1 fs-extra: ^11.1.0 lodash: ^4.17.21 @@ -1796,21 +1797,21 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 01976bc176541b7506680f56f74f2f5cf8d128f33eb6151bdd3bf09795a5ec5161356f4d7711c1fb63e7617fbdd2c6d08a4243870144b04fc1c02b67a98bdcb6 + checksum: 7414d2026446862505d0c679ad3757107f28100ea76309d2a024ebe78865f2fcf3e3b85c3117361142e319362b5a5b22e6bce968763fdfd0741b6a60d2eb3f4b languageName: node linkType: hard -"@docusaurus/plugin-content-blog@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/plugin-content-blog@npm:0.0.0-5566" +"@docusaurus/plugin-content-blog@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/plugin-content-blog@npm:0.0.0-5580" dependencies: - "@docusaurus/core": 0.0.0-5566 - "@docusaurus/logger": 0.0.0-5566 - "@docusaurus/mdx-loader": 0.0.0-5566 - "@docusaurus/types": 0.0.0-5566 - "@docusaurus/utils": 0.0.0-5566 - "@docusaurus/utils-common": 0.0.0-5566 - "@docusaurus/utils-validation": 0.0.0-5566 + "@docusaurus/core": 0.0.0-5580 + "@docusaurus/logger": 0.0.0-5580 + "@docusaurus/mdx-loader": 0.0.0-5580 + "@docusaurus/types": 0.0.0-5580 + "@docusaurus/utils": 0.0.0-5580 + "@docusaurus/utils-common": 0.0.0-5580 + "@docusaurus/utils-validation": 0.0.0-5580 cheerio: ^1.0.0-rc.12 feed: ^4.2.2 fs-extra: ^11.1.0 @@ -1823,21 +1824,21 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 1d1dfaf61c98de3e5722d1ea726dae29b75eb8747600583347aaca1dfe1ba0cb3b023d1af02ab8aac6e8750288ecd7f5b90bde5e5a693a822c874f0c053a24ea + checksum: 0c5d37fa84298ce12b2a0f5c1dea1ee7d72d4b28c545fd081f3c3e5f93f15a980d877dcf88718aa1f4b8a03abf3d0c8c0df10d0a2ef22aac7a8a96d2786f91c2 languageName: node linkType: hard -"@docusaurus/plugin-content-docs@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/plugin-content-docs@npm:0.0.0-5566" +"@docusaurus/plugin-content-docs@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/plugin-content-docs@npm:0.0.0-5580" dependencies: - "@docusaurus/core": 0.0.0-5566 - "@docusaurus/logger": 0.0.0-5566 - "@docusaurus/mdx-loader": 0.0.0-5566 - "@docusaurus/module-type-aliases": 0.0.0-5566 - "@docusaurus/types": 0.0.0-5566 - "@docusaurus/utils": 0.0.0-5566 - "@docusaurus/utils-validation": 0.0.0-5566 + "@docusaurus/core": 0.0.0-5580 + "@docusaurus/logger": 0.0.0-5580 + "@docusaurus/mdx-loader": 0.0.0-5580 + "@docusaurus/module-type-aliases": 0.0.0-5580 + "@docusaurus/types": 0.0.0-5580 + "@docusaurus/utils": 0.0.0-5580 + "@docusaurus/utils-validation": 0.0.0-5580 "@types/react-router-config": ^5.0.6 combine-promises: ^1.1.0 fs-extra: ^11.1.0 @@ -1850,133 +1851,133 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 32bb9c8c82ff4dfb9639b8fabda4d7b3c69c7a4a551719dba7495be8c7baf2ad96cb79b241904def5bab33f38c4e84a01d870f7200fe5c4eae74d380abaa6c60 + checksum: fa58801bf0cebf055ed11adbadc3f27f7ed0ddb95174ab60bab76a21f759dc7abdfdd15f32141f7e259090c456634ee2556ac9a7daaaf7f5f6e3666d9f247d00 languageName: node linkType: hard -"@docusaurus/plugin-content-pages@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/plugin-content-pages@npm:0.0.0-5566" +"@docusaurus/plugin-content-pages@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/plugin-content-pages@npm:0.0.0-5580" dependencies: - "@docusaurus/core": 0.0.0-5566 - "@docusaurus/mdx-loader": 0.0.0-5566 - "@docusaurus/types": 0.0.0-5566 - "@docusaurus/utils": 0.0.0-5566 - "@docusaurus/utils-validation": 0.0.0-5566 + "@docusaurus/core": 0.0.0-5580 + "@docusaurus/mdx-loader": 0.0.0-5580 + "@docusaurus/types": 0.0.0-5580 + "@docusaurus/utils": 0.0.0-5580 + "@docusaurus/utils-validation": 0.0.0-5580 fs-extra: ^11.1.0 tslib: ^2.5.0 webpack: ^5.76.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 6764c2d922d308305b0f71866f951b05a9cf885ff758e8982f865d8a52d77295802ae0d35cad20518b45a6a4daf7fbfbe2728fd5e078fdcc5104a4f21de0134f + checksum: 42bf814d9bf5540b8b2f8045f1577c49d3fca4a85069865695ff5dd9fa3f935283f9d46f920c4dd0a28190cf3b342d432b0985636bae9f05280835f73aec8c87 languageName: node linkType: hard -"@docusaurus/plugin-debug@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/plugin-debug@npm:0.0.0-5566" +"@docusaurus/plugin-debug@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/plugin-debug@npm:0.0.0-5580" dependencies: - "@docusaurus/core": 0.0.0-5566 - "@docusaurus/types": 0.0.0-5566 - "@docusaurus/utils": 0.0.0-5566 + "@docusaurus/core": 0.0.0-5580 + "@docusaurus/types": 0.0.0-5580 + "@docusaurus/utils": 0.0.0-5580 fs-extra: ^11.1.0 react-json-view: ^1.21.3 tslib: ^2.5.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 32a996e40cc58ebc2fd3cbfb9f6d33b7303952788d9c9b2f41f36b54a327939807e990784191f6f3a6169a4c56c7dabec2f7b369828d86f86414e32c3ac39dfe + checksum: dc58659adab3c859daa2e0dfc0b5b588d490a4d2bb313dcfdc9e92d559d0c4145c686b001805ad44a1f2a0f55f87524637a34844a4438cfeec479a2c24ec1c4d languageName: node linkType: hard -"@docusaurus/plugin-google-analytics@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/plugin-google-analytics@npm:0.0.0-5566" +"@docusaurus/plugin-google-analytics@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/plugin-google-analytics@npm:0.0.0-5580" dependencies: - "@docusaurus/core": 0.0.0-5566 - "@docusaurus/types": 0.0.0-5566 - "@docusaurus/utils-validation": 0.0.0-5566 + "@docusaurus/core": 0.0.0-5580 + "@docusaurus/types": 0.0.0-5580 + "@docusaurus/utils-validation": 0.0.0-5580 tslib: ^2.5.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: a1549324beb15024b3cfc6ebc0fb1ef7017f28d4a7419c14d469cc24025a53e460bceeed7401e01900b530e06ec84c302de891aea165ed5c3885261eb8eccb12 + checksum: f66a737a2b8b08648f28a279784e527fff34e2dba6f3022ec83b01a7f1781bfa0f208fac1db1fc919c1a01d405755c0816304cf4912e7b434b3924d5a968e6b0 languageName: node linkType: hard -"@docusaurus/plugin-google-gtag@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/plugin-google-gtag@npm:0.0.0-5566" +"@docusaurus/plugin-google-gtag@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/plugin-google-gtag@npm:0.0.0-5580" dependencies: - "@docusaurus/core": 0.0.0-5566 - "@docusaurus/types": 0.0.0-5566 - "@docusaurus/utils-validation": 0.0.0-5566 + "@docusaurus/core": 0.0.0-5580 + "@docusaurus/types": 0.0.0-5580 + "@docusaurus/utils-validation": 0.0.0-5580 "@types/gtag.js": ^0.0.12 tslib: ^2.5.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 3e98f82b2e2767205fc3d40673e6db5b188d2cd4c3ff83d7f6ff7588b0e2486a6d48c1a6ef37bae6a1fafb77309bbc4000eb2784bd4f01df21deb23235f13884 + checksum: 6b05e7c2a8e4d757660acca1131a0e3abfd21c5544a31e93bd08ff9c75deb5f3b131ed0e47283bbc2f102e00947ab7a64ee4d5a53f300e98fc82ec13c4a6eda1 languageName: node linkType: hard -"@docusaurus/plugin-google-tag-manager@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/plugin-google-tag-manager@npm:0.0.0-5566" +"@docusaurus/plugin-google-tag-manager@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/plugin-google-tag-manager@npm:0.0.0-5580" dependencies: - "@docusaurus/core": 0.0.0-5566 - "@docusaurus/types": 0.0.0-5566 - "@docusaurus/utils-validation": 0.0.0-5566 + "@docusaurus/core": 0.0.0-5580 + "@docusaurus/types": 0.0.0-5580 + "@docusaurus/utils-validation": 0.0.0-5580 tslib: ^2.5.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 6ea3e845ad5bab9cec34947e851e3adbf27c609227ad4dec8c4bad6ff05ab2190028dea78a4c0d844b6c377357189d9b739ca83c330d8f46dfe25e48ee61037a + checksum: 8904b150b2faa05dc49fd957ca8c392605e53073d031dfedb098be2abae924c3faf4f5e26ecfea91fe452695699801de9882a85a4371a1a35ca05fd57de232ae languageName: node linkType: hard -"@docusaurus/plugin-sitemap@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/plugin-sitemap@npm:0.0.0-5566" +"@docusaurus/plugin-sitemap@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/plugin-sitemap@npm:0.0.0-5580" dependencies: - "@docusaurus/core": 0.0.0-5566 - "@docusaurus/logger": 0.0.0-5566 - "@docusaurus/types": 0.0.0-5566 - "@docusaurus/utils": 0.0.0-5566 - "@docusaurus/utils-common": 0.0.0-5566 - "@docusaurus/utils-validation": 0.0.0-5566 + "@docusaurus/core": 0.0.0-5580 + "@docusaurus/logger": 0.0.0-5580 + "@docusaurus/types": 0.0.0-5580 + "@docusaurus/utils": 0.0.0-5580 + "@docusaurus/utils-common": 0.0.0-5580 + "@docusaurus/utils-validation": 0.0.0-5580 fs-extra: ^11.1.0 sitemap: ^7.1.1 tslib: ^2.5.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 1ceb243d048aaadfd05aaa4bb02455d3e87281ba49c08ecaa2ceb58f2cfa94a52af55756e20c562a2fa0c01524396d754d116e6ecb0d7591c2718baeaa334688 + checksum: 4243cf4ed649d8e9a29b122ce23f1a6194cc5d7fc244e33326320315d8ff2756b18b9d85a0f0d49df33b2e68224c1b747e87ad5fa9944e7572bc761f641c5b77 languageName: node linkType: hard -"@docusaurus/preset-classic@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/preset-classic@npm:0.0.0-5566" +"@docusaurus/preset-classic@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/preset-classic@npm:0.0.0-5580" dependencies: - "@docusaurus/core": 0.0.0-5566 - "@docusaurus/plugin-content-blog": 0.0.0-5566 - "@docusaurus/plugin-content-docs": 0.0.0-5566 - "@docusaurus/plugin-content-pages": 0.0.0-5566 - "@docusaurus/plugin-debug": 0.0.0-5566 - "@docusaurus/plugin-google-analytics": 0.0.0-5566 - "@docusaurus/plugin-google-gtag": 0.0.0-5566 - "@docusaurus/plugin-google-tag-manager": 0.0.0-5566 - "@docusaurus/plugin-sitemap": 0.0.0-5566 - "@docusaurus/theme-classic": 0.0.0-5566 - "@docusaurus/theme-common": 0.0.0-5566 - "@docusaurus/theme-search-algolia": 0.0.0-5566 - "@docusaurus/types": 0.0.0-5566 + "@docusaurus/core": 0.0.0-5580 + "@docusaurus/plugin-content-blog": 0.0.0-5580 + "@docusaurus/plugin-content-docs": 0.0.0-5580 + "@docusaurus/plugin-content-pages": 0.0.0-5580 + "@docusaurus/plugin-debug": 0.0.0-5580 + "@docusaurus/plugin-google-analytics": 0.0.0-5580 + "@docusaurus/plugin-google-gtag": 0.0.0-5580 + "@docusaurus/plugin-google-tag-manager": 0.0.0-5580 + "@docusaurus/plugin-sitemap": 0.0.0-5580 + "@docusaurus/theme-classic": 0.0.0-5580 + "@docusaurus/theme-common": 0.0.0-5580 + "@docusaurus/theme-search-algolia": 0.0.0-5580 + "@docusaurus/types": 0.0.0-5580 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: e7b1181b414f7795c540a4c9fed282ce350eaeee5006a9eb228cb42990d67ec933231f0af2f0329571ea135d87012a6ad606e9adaee61ae105573bbe6433a698 + checksum: 3aa48aea40e33c2c7adcad54918e117b1f1d917eba110889d85a273e82b4bbf0d73d9e5bb8c5aaadd846ec341981bbe701014cbd93ddf55c83245ce1bc4a56a6 languageName: node linkType: hard @@ -1992,22 +1993,22 @@ __metadata: languageName: node linkType: hard -"@docusaurus/theme-classic@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/theme-classic@npm:0.0.0-5566" +"@docusaurus/theme-classic@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/theme-classic@npm:0.0.0-5580" dependencies: - "@docusaurus/core": 0.0.0-5566 - "@docusaurus/mdx-loader": 0.0.0-5566 - "@docusaurus/module-type-aliases": 0.0.0-5566 - "@docusaurus/plugin-content-blog": 0.0.0-5566 - "@docusaurus/plugin-content-docs": 0.0.0-5566 - "@docusaurus/plugin-content-pages": 0.0.0-5566 - "@docusaurus/theme-common": 0.0.0-5566 - "@docusaurus/theme-translations": 0.0.0-5566 - "@docusaurus/types": 0.0.0-5566 - "@docusaurus/utils": 0.0.0-5566 - "@docusaurus/utils-common": 0.0.0-5566 - "@docusaurus/utils-validation": 0.0.0-5566 + "@docusaurus/core": 0.0.0-5580 + "@docusaurus/mdx-loader": 0.0.0-5580 + "@docusaurus/module-type-aliases": 0.0.0-5580 + "@docusaurus/plugin-content-blog": 0.0.0-5580 + "@docusaurus/plugin-content-docs": 0.0.0-5580 + "@docusaurus/plugin-content-pages": 0.0.0-5580 + "@docusaurus/theme-common": 0.0.0-5580 + "@docusaurus/theme-translations": 0.0.0-5580 + "@docusaurus/types": 0.0.0-5580 + "@docusaurus/utils": 0.0.0-5580 + "@docusaurus/utils-common": 0.0.0-5580 + "@docusaurus/utils-validation": 0.0.0-5580 "@mdx-js/react": ^2.1.5 clsx: ^1.2.1 copy-text-to-clipboard: ^3.0.1 @@ -2024,21 +2025,21 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 17ba0e0d5f27b0dfd700dd1c9536eae416268abc8d4b308cdf4015b2aff246153b4906e5aa292be58987ccc10b9fe0d0d3182bbba52e370c3116076787009206 + checksum: 6a8f99d5143017d4754601fbf6487b697dc77945f730763917578abe0a1ef694607f888d824146aef86fdc2a620f0ddbd4925a23dcfc15b57d8338c1de73d526 languageName: node linkType: hard -"@docusaurus/theme-common@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/theme-common@npm:0.0.0-5566" +"@docusaurus/theme-common@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/theme-common@npm:0.0.0-5580" dependencies: - "@docusaurus/mdx-loader": 0.0.0-5566 - "@docusaurus/module-type-aliases": 0.0.0-5566 - "@docusaurus/plugin-content-blog": 0.0.0-5566 - "@docusaurus/plugin-content-docs": 0.0.0-5566 - "@docusaurus/plugin-content-pages": 0.0.0-5566 - "@docusaurus/utils": 0.0.0-5566 - "@docusaurus/utils-common": 0.0.0-5566 + "@docusaurus/mdx-loader": 0.0.0-5580 + "@docusaurus/module-type-aliases": 0.0.0-5580 + "@docusaurus/plugin-content-blog": 0.0.0-5580 + "@docusaurus/plugin-content-docs": 0.0.0-5580 + "@docusaurus/plugin-content-pages": 0.0.0-5580 + "@docusaurus/utils": 0.0.0-5580 + "@docusaurus/utils-common": 0.0.0-5580 "@types/history": ^4.7.11 "@types/react": "*" "@types/react-router-config": "*" @@ -2051,22 +2052,22 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 5f2978300b9a01c93d12e6fcd768259cab224207da15f6fd6889cc3e441fda61354e165f084f0353257e9c6d6af5184adb0f03ce7cf009845751657c3d52a00f + checksum: 99524cb36a520568f63140734daaea8d56b35c0c8de3c36cb0102a93a0714f31a68aa5302607b9113a68e1b9fb7d73fd53ac80aa82ce48bf6f2d9e304ce21da2 languageName: node linkType: hard -"@docusaurus/theme-search-algolia@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/theme-search-algolia@npm:0.0.0-5566" +"@docusaurus/theme-search-algolia@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/theme-search-algolia@npm:0.0.0-5580" dependencies: "@docsearch/react": ^3.3.3 - "@docusaurus/core": 0.0.0-5566 - "@docusaurus/logger": 0.0.0-5566 - "@docusaurus/plugin-content-docs": 0.0.0-5566 - "@docusaurus/theme-common": 0.0.0-5566 - "@docusaurus/theme-translations": 0.0.0-5566 - "@docusaurus/utils": 0.0.0-5566 - "@docusaurus/utils-validation": 0.0.0-5566 + "@docusaurus/core": 0.0.0-5580 + "@docusaurus/logger": 0.0.0-5580 + "@docusaurus/plugin-content-docs": 0.0.0-5580 + "@docusaurus/theme-common": 0.0.0-5580 + "@docusaurus/theme-translations": 0.0.0-5580 + "@docusaurus/utils": 0.0.0-5580 + "@docusaurus/utils-validation": 0.0.0-5580 algoliasearch: ^4.15.0 algoliasearch-helper: ^3.12.0 clsx: ^1.2.1 @@ -2078,23 +2079,23 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 89256f242ccc5d0e1aca92e817413a1e40d18de58fb069e283741b2e5dbc29b267b345fc6d602ad88ac0faf0a003c3a99d549e9bc9027aa79b0e767ad4d7b79c + checksum: efc6054ad979b9fde43bec8befeb41c0f9ca609832b51e4da42fdcdfd7e4ee599fd3e6949c576d9ff348c0ffd044a4dbb07638a1990f57586f493ba394369c96 languageName: node linkType: hard -"@docusaurus/theme-translations@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/theme-translations@npm:0.0.0-5566" +"@docusaurus/theme-translations@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/theme-translations@npm:0.0.0-5580" dependencies: fs-extra: ^11.1.0 tslib: ^2.5.0 - checksum: e6595e675617669267b48e8cf79cbde8e65f279b8cdf0a3a45cb75f32ec0d2ddd59d0d02ac3f0aaa5328f0a13cd63a41aaff49a2251ce6665bba4abdfba71361 + checksum: 1555956d2a7cf3122ded374937559ab19e6a6620fd0910d6bdbf48be78a10e595cfd9a0b9157c129f36f0bfae4297f07991f071a394c87cb9d2facee04597dd2 languageName: node linkType: hard -"@docusaurus/types@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/types@npm:0.0.0-5566" +"@docusaurus/types@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/types@npm:0.0.0-5580" dependencies: "@types/history": ^4.7.11 "@types/react": "*" @@ -2107,13 +2108,13 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: aec430471a0019e650e168320c168f942ce8097022c45fb70e1ec86ba793b146f95a9d3cf434e3d9c985a45cea363f870cc51395dddaf0d0f600496ca6dbf810 + checksum: 5df67f562c5d516eb020ecf63e6343e1d6d18e2716b1b530a24c5d63b48229623222861c1a69f0e4715c34a768f7c05599340f1af18ca1259709467fb1149af9 languageName: node linkType: hard -"@docusaurus/utils-common@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/utils-common@npm:0.0.0-5566" +"@docusaurus/utils-common@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/utils-common@npm:0.0.0-5580" dependencies: tslib: ^2.5.0 peerDependencies: @@ -2121,28 +2122,28 @@ __metadata: peerDependenciesMeta: "@docusaurus/types": optional: true - checksum: 14cc02aac8a59350244ab733f8c662b838aac9ed3bc156a75113cbf1e2bf50d3db2e722313f9b6fe2616dcfafef3abc858f064289a8a0539b97745c571ec3fca + checksum: 238b2f12607834164fa82f9a3154703b75609719888cf96f06c9f70c17ab76a46babcfd66dce4f2722ecaaf47742a40a606101f0578f2345845fa23b6f262b5d languageName: node linkType: hard -"@docusaurus/utils-validation@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/utils-validation@npm:0.0.0-5566" +"@docusaurus/utils-validation@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/utils-validation@npm:0.0.0-5580" dependencies: - "@docusaurus/logger": 0.0.0-5566 - "@docusaurus/utils": 0.0.0-5566 + "@docusaurus/logger": 0.0.0-5580 + "@docusaurus/utils": 0.0.0-5580 joi: ^17.8.3 js-yaml: ^4.1.0 tslib: ^2.5.0 - checksum: 85a3570134ee26c88571ccb409c08f8ed182257cd72eb564e2a553e0d32a9a0c8bf4daaf1c33c5805e77e47a9fb97d29dfa0a758d8a7224d70ece80e82b583cc + checksum: cf0602b2411738adc47f5596fd4a3076137aa754aca24a4630700dc6355fed07e9a66ec093e438fa1199d9076bebae036317d073a604e4f0666f8390ceb73b5d languageName: node linkType: hard -"@docusaurus/utils@npm:0.0.0-5566": - version: 0.0.0-5566 - resolution: "@docusaurus/utils@npm:0.0.0-5566" +"@docusaurus/utils@npm:0.0.0-5580": + version: 0.0.0-5580 + resolution: "@docusaurus/utils@npm:0.0.0-5580" dependencies: - "@docusaurus/logger": 0.0.0-5566 + "@docusaurus/logger": 0.0.0-5580 "@svgr/webpack": ^6.5.1 escape-string-regexp: ^4.0.0 file-loader: ^6.2.0 @@ -2163,7 +2164,7 @@ __metadata: peerDependenciesMeta: "@docusaurus/types": optional: true - checksum: 82f682fdec2711d4608bb84f4a400e4f93bfbd4fde2da4cce37691b91e3e501bd409e7e86bae19bcc3b5dce576edcd33e078b25c28236ed1f15628d814cfe04e + checksum: c9b085d3724cba748b3db763f056742aace45cc58a636e23513ee6a7db781558377de5507b651b3566562fa71eebb42ac835034cdcbcc2c77edf9b4009c6a215 languageName: node linkType: hard @@ -2603,90 +2604,90 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-darwin-arm64@npm:1.3.51" +"@swc/core-darwin-arm64@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-darwin-arm64@npm:1.3.59" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-darwin-x64@npm:1.3.51" +"@swc/core-darwin-x64@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-darwin-x64@npm:1.3.59" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.51" +"@swc/core-linux-arm-gnueabihf@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.59" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.51" +"@swc/core-linux-arm64-gnu@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.59" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.51" +"@swc/core-linux-arm64-musl@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.59" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.51" +"@swc/core-linux-x64-gnu@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.59" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-linux-x64-musl@npm:1.3.51" +"@swc/core-linux-x64-musl@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-linux-x64-musl@npm:1.3.59" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.51" +"@swc/core-win32-arm64-msvc@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.59" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.51" +"@swc/core-win32-ia32-msvc@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.59" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.51" +"@swc/core-win32-x64-msvc@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.59" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.46": - version: 1.3.51 - resolution: "@swc/core@npm:1.3.51" + version: 1.3.59 + resolution: "@swc/core@npm:1.3.59" dependencies: - "@swc/core-darwin-arm64": 1.3.51 - "@swc/core-darwin-x64": 1.3.51 - "@swc/core-linux-arm-gnueabihf": 1.3.51 - "@swc/core-linux-arm64-gnu": 1.3.51 - "@swc/core-linux-arm64-musl": 1.3.51 - "@swc/core-linux-x64-gnu": 1.3.51 - "@swc/core-linux-x64-musl": 1.3.51 - "@swc/core-win32-arm64-msvc": 1.3.51 - "@swc/core-win32-ia32-msvc": 1.3.51 - "@swc/core-win32-x64-msvc": 1.3.51 + "@swc/core-darwin-arm64": 1.3.59 + "@swc/core-darwin-x64": 1.3.59 + "@swc/core-linux-arm-gnueabihf": 1.3.59 + "@swc/core-linux-arm64-gnu": 1.3.59 + "@swc/core-linux-arm64-musl": 1.3.59 + "@swc/core-linux-x64-gnu": 1.3.59 + "@swc/core-linux-x64-musl": 1.3.59 + "@swc/core-win32-arm64-msvc": 1.3.59 + "@swc/core-win32-ia32-msvc": 1.3.59 + "@swc/core-win32-x64-msvc": 1.3.59 peerDependencies: "@swc/helpers": ^0.5.0 dependenciesMeta: @@ -2713,7 +2714,7 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: f4e72d347b26353fbb48eae110a63c939922a38b20730ea010f5ae3dd15434f212dce582df05556ec35e677c089dfb6d00f5dd6fc655f8c9a7829458e4301469 + checksum: 0283f39cf49cd12a6dc7062ef9ea4fa93e1a4f622ce46903a09605219f4f47ed5ad03925c6146d09ffe6ee02a89bb14e3c82eb86b4c60ecce4985ea6e078ffcf languageName: node linkType: hard @@ -2991,6 +2992,13 @@ __metadata: languageName: node linkType: hard +"@types/parse5@npm:^6.0.0": + version: 6.0.3 + resolution: "@types/parse5@npm:6.0.3" + checksum: ddb59ee4144af5dfcc508a8dcf32f37879d11e12559561e65788756b95b33e6f03ea027d88e1f5408f9b7bfb656bf630ace31a2169edf44151daaf8dd58df1b7 + languageName: node + linkType: hard + "@types/prop-types@npm:*": version: 15.7.5 resolution: "@types/prop-types@npm:15.7.5" @@ -3737,10 +3745,10 @@ __metadata: version: 0.0.0-use.local resolution: "backstage-microsite@workspace:." dependencies: - "@docusaurus/core": 0.0.0-5566 - "@docusaurus/module-type-aliases": 0.0.0-5566 - "@docusaurus/plugin-client-redirects": 0.0.0-5566 - "@docusaurus/preset-classic": 0.0.0-5566 + "@docusaurus/core": 0.0.0-5580 + "@docusaurus/module-type-aliases": 0.0.0-5580 + "@docusaurus/plugin-client-redirects": 0.0.0-5580 + "@docusaurus/preset-classic": 0.0.0-5580 "@spotify/prettier-config": ^14.0.0 "@swc/core": ^1.3.46 "@tsconfig/docusaurus": ^1.0.6 @@ -6132,6 +6140,21 @@ __metadata: languageName: node linkType: hard +"hast-util-from-parse5@npm:^7.0.0": + version: 7.1.2 + resolution: "hast-util-from-parse5@npm:7.1.2" + dependencies: + "@types/hast": ^2.0.0 + "@types/unist": ^2.0.0 + hastscript: ^7.0.0 + property-information: ^6.0.0 + vfile: ^5.0.0 + vfile-location: ^4.0.0 + web-namespaces: ^2.0.0 + checksum: 7b4ed5b508b1352127c6719f7b0c0880190cf9859fe54ccaf7c9228ecf623d36cef3097910b3874d2fe1aac6bf4cf45d3cc2303daac3135a05e9ade6534ddddb + languageName: node + linkType: hard + "hast-util-parse-selector@npm:^3.0.0": version: 3.1.1 resolution: "hast-util-parse-selector@npm:3.1.1" @@ -6141,6 +6164,25 @@ __metadata: languageName: node linkType: hard +"hast-util-raw@npm:^7.2.0": + version: 7.2.3 + resolution: "hast-util-raw@npm:7.2.3" + dependencies: + "@types/hast": ^2.0.0 + "@types/parse5": ^6.0.0 + hast-util-from-parse5: ^7.0.0 + hast-util-to-parse5: ^7.0.0 + html-void-elements: ^2.0.0 + parse5: ^6.0.0 + unist-util-position: ^4.0.0 + unist-util-visit: ^4.0.0 + vfile: ^5.0.0 + web-namespaces: ^2.0.0 + zwitch: ^2.0.0 + checksum: 21857eea3ffb8fd92d2d9be7793b56d0b2c40db03c4cfa14828855ae41d7c584917aa83efb7157220b2e41e25e95f81f24679ac342c35145e5f1c1d39015f81f + languageName: node + linkType: hard + "hast-util-to-estree@npm:^2.0.0": version: 2.3.2 resolution: "hast-util-to-estree@npm:2.3.2" @@ -6164,6 +6206,20 @@ __metadata: languageName: node linkType: hard +"hast-util-to-parse5@npm:^7.0.0": + version: 7.1.0 + resolution: "hast-util-to-parse5@npm:7.1.0" + dependencies: + "@types/hast": ^2.0.0 + comma-separated-tokens: ^2.0.0 + property-information: ^6.0.0 + space-separated-tokens: ^2.0.0 + web-namespaces: ^2.0.0 + zwitch: ^2.0.0 + checksum: 3a7f2175a3db599bbae7e49ba73d3e5e688e5efca7590ff50130ba108ad649f728402815d47db49146f6b94c14c934bf119915da9f6964e38802c122bcc8af6b + languageName: node + linkType: hard + "hast-util-whitespace@npm:^2.0.0": version: 2.0.1 resolution: "hast-util-whitespace@npm:2.0.1" @@ -6171,7 +6227,7 @@ __metadata: languageName: node linkType: hard -"hastscript@npm:^7.1.0": +"hastscript@npm:^7.0.0, hastscript@npm:^7.1.0": version: 7.2.0 resolution: "hastscript@npm:7.2.0" dependencies: @@ -6276,6 +6332,13 @@ __metadata: languageName: node linkType: hard +"html-void-elements@npm:^2.0.0": + version: 2.0.1 + resolution: "html-void-elements@npm:2.0.1" + checksum: 06d41f13b9d5d6e0f39861c4bec9a9196fa4906d56cd5cf6cf54ad2e52a85bf960cca2bf9600026bde16c8331db171bedba5e5a35e2e43630c8f1d497b2fb658 + languageName: node + linkType: hard + "html-webpack-plugin@npm:^5.5.0": version: 5.5.0 resolution: "html-webpack-plugin@npm:5.5.0" @@ -8735,6 +8798,13 @@ __metadata: languageName: node linkType: hard +"parse5@npm:^6.0.0": + version: 6.0.1 + resolution: "parse5@npm:6.0.1" + checksum: 7d569a176c5460897f7c8f3377eff640d54132b9be51ae8a8fa4979af940830b2b0c296ce75e5bd8f4041520aadde13170dbdec44889975f906098ea0002f4bd + languageName: node + linkType: hard + "parse5@npm:^7.0.0": version: 7.1.2 resolution: "parse5@npm:7.1.2" @@ -9901,6 +9971,17 @@ __metadata: languageName: node linkType: hard +"rehype-raw@npm:^6.1.1": + version: 6.1.1 + resolution: "rehype-raw@npm:6.1.1" + dependencies: + "@types/hast": ^2.0.0 + hast-util-raw: ^7.2.0 + unified: ^10.0.0 + checksum: a1f9d309e609f49fb1f1e06e722705f4dd2e569653a89f756eaccb33b612cf1bb511216a81d10a619d11d047afc161e4b3cb99b957df05a8ba8fdbd5843f949a + languageName: node + linkType: hard + "relateurl@npm:^0.2.7": version: 0.2.7 resolution: "relateurl@npm:0.2.7" @@ -11526,6 +11607,13 @@ __metadata: languageName: node linkType: hard +"web-namespaces@npm:^2.0.0": + version: 2.0.1 + resolution: "web-namespaces@npm:2.0.1" + checksum: b6d9f02f1a43d0ef0848a812d89c83801d5bbad57d8bb61f02eb6d7eb794c3736f6cc2e1191664bb26136594c8218ac609f4069722c6f56d9fc2d808fa9271c6 + languageName: node + linkType: hard + "webidl-conversions@npm:^3.0.0": version: 3.0.1 resolution: "webidl-conversions@npm:3.0.1" diff --git a/package.json b/package.json index 44778ae926..003d4e704e 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@types/react": "^17", "@types/react-dom": "^17" }, - "version": "1.14.0-next.1", + "version": "1.15.0-next.0", "dependencies": { "@backstage/errors": "workspace:^", "@manypkg/get-packages": "^1.1.3" diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index 5d781b58ca..d18d5e0006 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,60 @@ # @backstage/app-defaults +## 1.4.0-next.0 + +### Minor Changes + +- 1fd38bc4141a: **MUI v5 Support:** Adding platform-wide support for MUI v5 allowing a transition phase for migrating central plugins & components over. We still support v4 instances & plugins by adding a + + To allow the future support of plugins & components using MUI v5 you want to upgrade your `AppTheme`'s to using the `UnifiedThemeProvider` + + ```diff + Provider: ({ children }) => ( + - + - {children} + - + + + ), + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + +## 1.3.1 + +### Patch Changes + +- 575d9178eff: Added a System Icon for resource entities. + This can be obtained using: + + ```ts + useApp().getSystemIcon('kind:resource'); + ``` + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + +## 1.3.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-app-api@1.8.0-next.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + ## 1.3.1-next.1 ### Patch Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index 0a8f2e5dc1..2d1e2b3746 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/app-defaults", "description": "Provides the default wiring of a Backstage App", - "version": "1.3.1-next.1", + "version": "1.4.0-next.0", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/app-defaults/src/defaults/themes.tsx b/packages/app-defaults/src/defaults/themes.tsx index 397c160168..10368bd3bc 100644 --- a/packages/app-defaults/src/defaults/themes.tsx +++ b/packages/app-defaults/src/defaults/themes.tsx @@ -15,11 +15,12 @@ */ import React from 'react'; -import { darkTheme, lightTheme } from '@backstage/theme'; +import { + UnifiedThemeProvider, + themes as builtinThemes, +} from '@backstage/theme'; import DarkIcon from '@material-ui/icons/Brightness2'; import LightIcon from '@material-ui/icons/WbSunny'; -import { ThemeProvider } from '@material-ui/core/styles'; -import CssBaseline from '@material-ui/core/CssBaseline'; import { AppTheme } from '@backstage/core-plugin-api'; export const themes: AppTheme[] = [ @@ -29,9 +30,7 @@ export const themes: AppTheme[] = [ variant: 'light', icon: , Provider: ({ children }) => ( - - {children} - + ), }, { @@ -40,9 +39,7 @@ export const themes: AppTheme[] = [ variant: 'dark', icon: , Provider: ({ children }) => ( - - {children} - + ), }, ]; diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index b20fafb995..f087ae6da0 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,217 @@ # example-app +## 0.2.84-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-kubernetes@0.9.2-next.0 + - @backstage/plugin-user-settings@0.7.4-next.0 + - @backstage/plugin-catalog-import@0.9.9-next.0 + - @backstage/plugin-scaffolder-react@1.4.1-next.0 + - @backstage/plugin-octopus-deploy@0.2.1-next.0 + - @backstage/plugin-scaffolder@1.13.2-next.0 + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/plugin-techdocs@1.6.3-next.0 + - @backstage/plugin-github-actions@0.6.0-next.0 + - @backstage/plugin-stack-overflow@0.1.16-next.0 + - @backstage/plugin-home@0.5.3-next.0 + - @backstage/app-defaults@1.4.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/cli@0.22.8-next.0 + - @backstage/plugin-techdocs-react@1.1.7-next.0 + - @backstage/plugin-dynatrace@6.0.0-next.0 + - @backstage/plugin-pagerduty@0.5.12-next.0 + - @backstage/plugin-catalog-graph@0.2.31-next.0 + - @backstage/plugin-org@0.6.9-next.0 + - @backstage/plugin-airbrake@0.3.19-next.0 + - @backstage/plugin-api-docs@0.9.4-next.0 + - @backstage/plugin-azure-devops@0.3.1-next.0 + - @backstage/plugin-azure-sites@0.1.8-next.0 + - @backstage/plugin-badges@0.2.43-next.0 + - @internal/plugin-catalog-customized@0.0.11-next.0 + - @backstage/plugin-circleci@0.3.19-next.0 + - @backstage/plugin-cloudbuild@0.3.19-next.0 + - @backstage/plugin-code-coverage@0.2.12-next.0 + - @backstage/plugin-cost-insights@0.12.8-next.0 + - @backstage/plugin-entity-feedback@0.2.2-next.0 + - @backstage/plugin-explore@0.4.4-next.0 + - @backstage/plugin-gocd@0.1.25-next.0 + - @backstage/plugin-jenkins@0.8.1-next.0 + - @backstage/plugin-kafka@0.3.19-next.0 + - @backstage/plugin-lighthouse@0.4.4-next.0 + - @backstage/plugin-linguist@0.1.4-next.0 + - @backstage/plugin-newrelic-dashboard@0.2.12-next.0 + - @backstage/plugin-playlist@0.1.10-next.0 + - @backstage/plugin-puppetdb@0.1.2-next.0 + - @backstage/plugin-rollbar@0.4.19-next.0 + - @backstage/plugin-search@1.3.1-next.0 + - @backstage/plugin-sentry@0.5.4-next.0 + - @backstage/plugin-tech-insights@0.3.11-next.0 + - @backstage/plugin-todo@0.2.21-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.14-next.0 + - @backstage/config@1.0.7 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/plugin-apache-airflow@0.2.12-next.0 + - @backstage/plugin-devtools@0.1.1-next.0 + - @backstage/plugin-gcalendar@0.3.15-next.0 + - @backstage/plugin-gcp-projects@0.3.38-next.0 + - @backstage/plugin-graphiql@0.2.51-next.0 + - @backstage/plugin-microsoft-calendar@0.1.4-next.0 + - @backstage/plugin-newrelic@0.3.37-next.0 + - @backstage/plugin-permission-react@0.4.12 + - @backstage/plugin-search-react@1.6.1-next.0 + - @backstage/plugin-shortcuts@0.3.11-next.0 + - @backstage/plugin-stackstorm@0.1.3-next.0 + - @backstage/plugin-tech-radar@0.6.5-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-linguist-common@0.1.0 + - @backstage/plugin-search-common@1.2.3 + +## 0.2.83 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-tech-insights@0.3.10 + - @backstage/plugin-scaffolder@1.13.1 + - @backstage/plugin-devtools@0.1.0 + - @backstage/plugin-kubernetes@0.9.0 + - @backstage/plugin-search@1.3.0 + - @backstage/plugin-home@0.5.2 + - @backstage/plugin-explore@0.4.3 + - @backstage/theme@0.3.0 + - @backstage/plugin-techdocs@1.6.2 + - @backstage/app-defaults@1.3.1 + - @backstage/plugin-badges@0.2.42 + - @backstage/plugin-tech-radar@0.6.4 + - @backstage/cli@0.22.7 + - @backstage/plugin-stack-overflow@0.1.15 + - @backstage/plugin-gcalendar@0.3.14 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-app-api@1.8.0 + - @backstage/plugin-scaffolder-react@1.4.0 + - @backstage/plugin-catalog-graph@0.2.30 + - @backstage/plugin-circleci@0.3.18 + - @backstage/plugin-search-react@1.6.0 + - @backstage/plugin-org@0.6.8 + - @backstage/core-components@0.13.1 + - @backstage/plugin-azure-devops@0.3.0 + - @backstage/plugin-jenkins@0.8.0 + - @backstage/plugin-octopus-deploy@0.2.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.13 + - @backstage/plugin-user-settings@0.7.3 + - @backstage/plugin-shortcuts@0.3.10 + - @backstage/integration-react@1.1.13 + - @backstage/plugin-airbrake@0.3.18 + - @backstage/plugin-api-docs@0.9.3 + - @backstage/plugin-azure-sites@0.1.7 + - @backstage/plugin-cloudbuild@0.3.18 + - @backstage/plugin-code-coverage@0.2.11 + - @backstage/plugin-cost-insights@0.12.7 + - @backstage/plugin-dynatrace@5.0.0 + - @backstage/plugin-entity-feedback@0.2.1 + - @backstage/plugin-gcp-projects@0.3.37 + - @backstage/plugin-github-actions@0.5.18 + - @backstage/plugin-gocd@0.1.24 + - @backstage/plugin-graphiql@0.2.50 + - @backstage/plugin-kafka@0.3.18 + - @backstage/plugin-lighthouse@0.4.3 + - @backstage/plugin-linguist@0.1.3 + - @backstage/plugin-microsoft-calendar@0.1.3 + - @backstage/plugin-newrelic@0.3.36 + - @backstage/plugin-pagerduty@0.5.11 + - @backstage/plugin-playlist@0.1.9 + - @backstage/plugin-puppetdb@0.1.1 + - @backstage/plugin-rollbar@0.4.18 + - @backstage/plugin-sentry@0.5.3 + - @backstage/plugin-stackstorm@0.1.2 + - @backstage/plugin-techdocs-react@1.1.6 + - @backstage/plugin-todo@0.2.20 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-apache-airflow@0.2.11 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-catalog-import@0.9.8 + - @backstage/plugin-linguist-common@0.1.0 + - @backstage/plugin-newrelic-dashboard@0.2.11 + - @backstage/plugin-permission-react@0.4.12 + - @backstage/plugin-search-common@1.2.3 + - @internal/plugin-catalog-customized@0.0.10 + +## 0.2.83-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-devtools@0.1.0-next.0 + - @backstage/plugin-kubernetes@0.9.0-next.2 + - @backstage/plugin-home@0.5.2-next.2 + - @backstage/theme@0.3.0-next.0 + - @backstage/plugin-badges@0.2.42-next.2 + - @backstage/plugin-tech-radar@0.6.4-next.2 + - @backstage/plugin-scaffolder-react@1.4.0-next.2 + - @backstage/plugin-explore@0.4.3-next.2 + - @backstage/plugin-org@0.6.8-next.2 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-search-react@1.6.0-next.2 + - @backstage/plugin-azure-devops@0.3.0-next.2 + - @backstage/plugin-stack-overflow@0.1.15-next.2 + - @backstage/app-defaults@1.3.1-next.2 + - @backstage/cli@0.22.7-next.0 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/plugin-airbrake@0.3.18-next.2 + - @backstage/plugin-api-docs@0.9.3-next.2 + - @backstage/plugin-azure-sites@0.1.7-next.2 + - @backstage/plugin-catalog-graph@0.2.30-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/plugin-circleci@0.3.18-next.2 + - @backstage/plugin-cloudbuild@0.3.18-next.2 + - @backstage/plugin-code-coverage@0.2.11-next.2 + - @backstage/plugin-cost-insights@0.12.7-next.2 + - @backstage/plugin-dynatrace@5.0.0-next.2 + - @backstage/plugin-entity-feedback@0.2.1-next.2 + - @backstage/plugin-gcalendar@0.3.14-next.1 + - @backstage/plugin-gcp-projects@0.3.37-next.1 + - @backstage/plugin-github-actions@0.5.18-next.2 + - @backstage/plugin-gocd@0.1.24-next.2 + - @backstage/plugin-graphiql@0.2.50-next.1 + - @backstage/plugin-jenkins@0.7.17-next.2 + - @backstage/plugin-kafka@0.3.18-next.2 + - @backstage/plugin-lighthouse@0.4.3-next.2 + - @backstage/plugin-linguist@0.1.3-next.2 + - @backstage/plugin-microsoft-calendar@0.1.3-next.1 + - @backstage/plugin-newrelic@0.3.36-next.1 + - @backstage/plugin-octopus-deploy@0.2.0-next.2 + - @backstage/plugin-pagerduty@0.5.11-next.2 + - @backstage/plugin-playlist@0.1.9-next.2 + - @backstage/plugin-puppetdb@0.1.1-next.2 + - @backstage/plugin-rollbar@0.4.18-next.2 + - @backstage/plugin-scaffolder@1.13.1-next.2 + - @backstage/plugin-search@1.3.0-next.2 + - @backstage/plugin-sentry@0.5.3-next.2 + - @backstage/plugin-shortcuts@0.3.10-next.2 + - @backstage/plugin-stackstorm@0.1.2-next.1 + - @backstage/plugin-tech-insights@0.3.10-next.2 + - @backstage/plugin-techdocs@1.6.2-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.13-next.2 + - @backstage/plugin-techdocs-react@1.1.6-next.1 + - @backstage/plugin-todo@0.2.20-next.2 + - @backstage/plugin-user-settings@0.7.3-next.2 + - @backstage/plugin-apache-airflow@0.2.11-next.1 + - @backstage/plugin-catalog-import@0.9.8-next.2 + - @backstage/plugin-newrelic-dashboard@0.2.11-next.2 + - @backstage/config@1.0.7 + - @backstage/core-app-api@1.8.0-next.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + - @internal/plugin-catalog-customized@0.0.10-next.2 + ## 0.2.83-next.1 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index d4941ecd48..010b2dd648 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.83-next.1", + "version": "0.2.84-next.0", "private": true, "backstage": { "role": "frontend" @@ -29,6 +29,7 @@ "@backstage/plugin-cloudbuild": "workspace:^", "@backstage/plugin-code-coverage": "workspace:^", "@backstage/plugin-cost-insights": "workspace:^", + "@backstage/plugin-devtools": "workspace:^", "@backstage/plugin-dynatrace": "workspace:^", "@backstage/plugin-entity-feedback": "workspace:^", "@backstage/plugin-explore": "workspace:^", diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 19edd9640d..bc9eac8c64 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -109,6 +109,8 @@ import { TwoColumnLayout } from './components/scaffolder/customScaffolderLayouts import { ScoreBoardPage } from '@oriflame/backstage-plugin-score-card'; import { StackstormPage } from '@backstage/plugin-stackstorm'; import { PuppetDbPage } from '@backstage/plugin-puppetdb'; +import { DevToolsPage } from '@backstage/plugin-devtools'; +import { customDevToolsPage } from './components/devtools/CustomDevToolsPage'; const app = createApp({ apis, @@ -291,6 +293,9 @@ const routes = ( } /> } /> } /> + }> + {customDevToolsPage} + ); diff --git a/packages/app/src/components/Root/Root.tsx b/packages/app/src/components/Root/Root.tsx index 904fa4a7d4..ffaf72296a 100644 --- a/packages/app/src/components/Root/Root.tsx +++ b/packages/app/src/components/Root/Root.tsx @@ -52,6 +52,7 @@ import { MyGroupsSidebarItem } from '@backstage/plugin-org'; import { SearchModal } from '../search/SearchModal'; import Score from '@material-ui/icons/Score'; import { useApp } from '@backstage/core-plugin-api'; +import BuildIcon from '@material-ui/icons/Build'; const useSidebarLogoStyles = makeStyles({ root: { @@ -176,6 +177,7 @@ export const Root = ({ children }: PropsWithChildren<{}>) => ( to="/settings" > + {children} diff --git a/packages/app/src/components/devtools/CustomDevToolsPage.tsx b/packages/app/src/components/devtools/CustomDevToolsPage.tsx new file mode 100644 index 0000000000..dfe70426aa --- /dev/null +++ b/packages/app/src/components/devtools/CustomDevToolsPage.tsx @@ -0,0 +1,44 @@ +/* + * Copyright 2022 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 { + ConfigContent, + ExternalDependenciesContent, + InfoContent, +} from '@backstage/plugin-devtools'; +import { DevToolsLayout } from '@backstage/plugin-devtools'; +import React from 'react'; + +const DevToolsPage = () => { + return ( + + + + + + + + + + + + ); +}; + +export const customDevToolsPage = ; diff --git a/packages/app/src/components/home/HomePage.tsx b/packages/app/src/components/home/HomePage.tsx index 26a7ab60f3..da1d0d425c 100644 --- a/packages/app/src/components/home/HomePage.tsx +++ b/packages/app/src/components/home/HomePage.tsx @@ -21,12 +21,15 @@ import { ClockConfig, HomePageStarredEntities, CustomHomepageGrid, + HomePageToolkit, + HomePageCompanyLogo, } from '@backstage/plugin-home'; import { Content, Header, Page } from '@backstage/core-components'; import { HomePageSearchBar } from '@backstage/plugin-search'; import { HomePageCalendar } from '@backstage/plugin-gcalendar'; import { MicrosoftCalendarCard } from '@backstage/plugin-microsoft-calendar'; import React from 'react'; +import HomeIcon from '@material-ui/icons/Home'; const clockConfigs: ClockConfig[] = [ { @@ -55,12 +58,26 @@ const timeFormat: Intl.DateTimeFormatOptions = { const defaultConfig = [ { - component: 'HomePageSearchBar', + component: 'CompanyLogo', x: 0, y: 0, width: 12, height: 1, }, + { + component: 'WelcomeTitle', + x: 0, + y: 1, + width: 12, + height: 1, + }, + { + component: 'HomePageSearchBar', + x: 0, + y: 2, + width: 12, + height: 1, + }, ]; export const homePage = ( @@ -78,6 +95,17 @@ export const homePage = ( + + + , + }, + ]} + /> diff --git a/packages/app/src/components/home/templates/CustomizableTemplate.stories.tsx b/packages/app/src/components/home/templates/CustomizableTemplate.stories.tsx new file mode 100644 index 0000000000..e587e52da4 --- /dev/null +++ b/packages/app/src/components/home/templates/CustomizableTemplate.stories.tsx @@ -0,0 +1,153 @@ +/* + * Copyright 2023 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 { + HomePageStarredEntities, + HomePageRandomJoke, + CustomHomepageGrid, +} from '@backstage/plugin-home'; +import { + starredEntitiesApiRef, + MockStarredEntitiesApi, + entityRouteRef, + catalogApiRef, +} from '@backstage/plugin-catalog-react'; +import { wrapInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { configApiRef } from '@backstage/core-plugin-api'; +import { ConfigReader } from '@backstage/config'; +import { searchApiRef } from '@backstage/plugin-search-react'; +import { HomePageSearchBar, searchPlugin } from '@backstage/plugin-search'; +import { HomePageCalendar } from '@backstage/plugin-gcalendar'; +import { MicrosoftCalendarCard } from '@backstage/plugin-microsoft-calendar'; +import React, { ComponentType } from 'react'; + +const entities = [ + { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'mock-starred-entity', + title: 'Mock Starred Entity!', + }, + }, + { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'mock-starred-entity-2', + title: 'Mock Starred Entity 2!', + }, + }, + { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'mock-starred-entity-3', + title: 'Mock Starred Entity 3!', + }, + }, + { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'mock-starred-entity-4', + title: 'Mock Starred Entity 4!', + }, + }, +]; + +const mockCatalogApi = { + getEntities: async () => ({ items: entities }), +}; + +const starredEntitiesApi = new MockStarredEntitiesApi(); +starredEntitiesApi.toggleStarred('component:default/example-starred-entity'); +starredEntitiesApi.toggleStarred('component:default/example-starred-entity-2'); +starredEntitiesApi.toggleStarred('component:default/example-starred-entity-3'); +starredEntitiesApi.toggleStarred('component:default/example-starred-entity-4'); + +export default { + title: 'Plugins/Home/Templates', + decorators: [ + (Story: ComponentType<{}>) => + wrapInTestApp( + <> + Promise.resolve({ results: [] }) }], + [ + configApiRef, + new ConfigReader({ + backend: { + baseUrl: 'https://localhost:7007', + }, + }), + ], + ]} + > + + + , + { + mountedRoutes: { + '/hello-company': searchPlugin.routes.root, + '/catalog/:namespace/:kind/:name': entityRouteRef, + }, + }, + ), + ], +}; +export const CustomizableTemplate = () => { + // This is the default configuration that is shown to the user + // when first arriving to the homepage. + const defaultConfig = [ + { + component: 'HomePageSearchBar', + x: 0, + y: 0, + width: 12, + height: 5, + }, + { + component: 'HomePageRandomJoke', + x: 0, + y: 2, + width: 6, + height: 16, + }, + { + component: 'HomePageStarredEntities', + x: 6, + y: 2, + width: 6, + height: 12, + }, + ]; + + return ( + + // Insert the allowed widgets inside the grid. User can add, organize and + // remove the widgets as they want. + + + + + + + ); +}; diff --git a/packages/app/src/components/home/templates/DefaultTemplate.stories.tsx b/packages/app/src/components/home/templates/DefaultTemplate.stories.tsx index 9cf2e8ab35..52fab3c55f 100644 --- a/packages/app/src/components/home/templates/DefaultTemplate.stories.tsx +++ b/packages/app/src/components/home/templates/DefaultTemplate.stories.tsx @@ -140,15 +140,16 @@ export default { }; const useStyles = makeStyles(theme => ({ - searchBar: { - display: 'flex', + searchBarInput: { maxWidth: '60vw', - backgroundColor: theme.palette.background.paper, - boxShadow: theme.shadows[1], - padding: '8px 0', - borderRadius: '50px', margin: 'auto', + backgroundColor: theme.palette.background.paper, + borderRadius: '50px', + boxShadow: theme.shadows[1], }, + searchBarOutline: { + borderStyle: 'none' + } })); const useLogoStyles = makeStyles(theme => ({ @@ -177,9 +178,9 @@ export const DefaultTemplate = () => { className={container} logo={} /> - + diff --git a/packages/backend-app-api/CHANGELOG.md b/packages/backend-app-api/CHANGELOG.md index 00e7582ad3..3a6eadf23b 100644 --- a/packages/backend-app-api/CHANGELOG.md +++ b/packages/backend-app-api/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/backend-app-api +## 0.4.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.3.1-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-permission-node@0.7.9-next.0 + +## 0.4.3 + +### Patch Changes + +- cf13b482f9e: Switch `configServiceFactory` to use `ConfigSources` from `@backstage/config-loader` to load config. +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config-loader@1.3.0 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + ## 0.4.3-next.1 ### Patch Changes diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index a21484ff2e..679c9fa9ca 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-app-api", "description": "Core API used by Backstage backend apps", - "version": "0.4.3-next.1", + "version": "0.4.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index fc6d99cf93..a354795e21 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/backend-common +## 0.18.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.3.1-next.0 + - @backstage/backend-app-api@0.4.4-next.0 + - @backstage/integration@1.4.5 + - @backstage/integration-aws-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/backend-dev-utils@0.1.1 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## 0.18.5 + +### Patch Changes + +- 0297f7a54af: Remove the direct dependency on deprecated "request" library +- 284db225083: Updated the `DatabaseManager` to include the plugin id in the Postgres application name of the database connections created for each plugin. +- 3659c71c5d9: Standardize `@aws-sdk` v3 versions +- 42d817e76ab: Added `HostDiscovery` to supersede deprecated `SingleHostDiscovery` (deprecated due to name) +- Updated dependencies + - @backstage/config-loader@1.3.0 + - @backstage/integration@1.4.5 + - @backstage/integration-aws-node@0.1.3 + - @backstage/backend-app-api@0.4.3 + - @backstage/backend-dev-utils@0.1.1 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + ## 0.18.5-next.1 ### Patch Changes diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 045a385218..79d955be88 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-common", "description": "Common functionality library for Backstage backends", - "version": "0.18.5-next.1", + "version": "0.18.6-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -46,10 +46,10 @@ "test:kubernetes": "backstage-cli package test -t KubernetesContainerRunner --no-watch" }, "dependencies": { - "@aws-sdk/abort-controller": "^3.208.0", - "@aws-sdk/client-s3": "^3.208.0", - "@aws-sdk/credential-providers": "^3.208.0", - "@aws-sdk/types": "^3.208.0", + "@aws-sdk/abort-controller": "^3.310.0", + "@aws-sdk/client-s3": "^3.310.0", + "@aws-sdk/credential-providers": "^3.310.0", + "@aws-sdk/types": "^3.310.0", "@backstage/backend-app-api": "workspace:^", "@backstage/backend-dev-utils": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", @@ -114,7 +114,7 @@ } }, "devDependencies": { - "@aws-sdk/util-stream-node": "^3.208.0", + "@aws-sdk/util-stream-node": "^3.310.0", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/archiver": "^5.1.0", diff --git a/packages/backend-defaults/CHANGELOG.md b/packages/backend-defaults/CHANGELOG.md index 52043b4ecf..5f1ceea06c 100644 --- a/packages/backend-defaults/CHANGELOG.md +++ b/packages/backend-defaults/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/backend-defaults +## 0.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-app-api@0.4.4-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/backend-plugin-api@0.5.3-next.0 + +## 0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-app-api@0.4.3 + - @backstage/backend-plugin-api@0.5.2 + ## 0.1.10-next.1 ### Patch Changes diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index d99e462efa..4677d9af89 100644 --- a/packages/backend-defaults/package.json +++ b/packages/backend-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-defaults", "description": "Backend defaults used by Backstage backend apps", - "version": "0.1.10-next.1", + "version": "0.1.11-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-next/CHANGELOG.md b/packages/backend-next/CHANGELOG.md index 2eea18b4af..d26412f02d 100644 --- a/packages/backend-next/CHANGELOG.md +++ b/packages/backend-next/CHANGELOG.md @@ -1,5 +1,59 @@ # example-backend-next +## 0.0.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.14.1-next.0 + - @backstage/plugin-search-backend-module-explore@0.1.2-next.0 + - @backstage/plugin-catalog-backend@1.9.2-next.0 + - @backstage/plugin-kubernetes-backend@0.11.1-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.2-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.2-next.0 + - @backstage/plugin-techdocs-backend@1.6.3-next.0 + - @backstage/plugin-todo-backend@0.1.43-next.0 + - @backstage/plugin-app-backend@0.3.46-next.0 + - @backstage/backend-defaults@0.1.11-next.0 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-permission-backend@0.5.21-next.0 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-node@0.7.9-next.0 + - @backstage/plugin-search-backend@1.3.2-next.0 + - @backstage/plugin-search-backend-node@1.2.2-next.0 + +## 0.0.11 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.14.0 + - @backstage/plugin-catalog-backend@1.9.1 + - @backstage/plugin-kubernetes-backend@0.11.0 + - @backstage/plugin-todo-backend@0.1.42 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/plugin-search-backend@1.3.1 + - @backstage/backend-defaults@0.1.10 + - @backstage/plugin-app-backend@0.3.45 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/plugin-search-backend-module-catalog@0.1.1 + - @backstage/plugin-search-backend-module-explore@0.1.1 + - @backstage/plugin-search-backend-module-techdocs@0.1.1 + - @backstage/plugin-techdocs-backend@1.6.2 + - @backstage/plugin-permission-backend@0.5.20 + - @backstage/plugin-search-backend-node@1.2.1 + - @backstage/plugin-permission-common@0.7.5 + +## 0.0.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.1-next.2 + - @backstage/plugin-kubernetes-backend@0.11.0-next.2 + - @backstage/plugin-search-backend@1.3.1-next.2 + - @backstage/plugin-scaffolder-backend@1.13.2-next.2 + ## 0.0.11-next.1 ### Patch Changes diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index bf913492ac..664360eaa0 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -1,6 +1,6 @@ { "name": "example-backend-next", - "version": "0.0.11-next.1", + "version": "0.0.12-next.0", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/backend-openapi-utils/CHANGELOG.md b/packages/backend-openapi-utils/CHANGELOG.md index 015a54cf45..0255bbbf73 100644 --- a/packages/backend-openapi-utils/CHANGELOG.md +++ b/packages/backend-openapi-utils/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/backend-openapi-utils +## 0.0.2 + +### Patch Changes + +- fe16bd39e83: Use permalinks for links including a line number reference +- 27956d78671: Adjusted README accordingly after the generated output now has a `.generated.ts` extension +- 021cfbb5152: Corrected resolution of parameter nested schema to use central schemas. +- 799c33047ed: Updated README to reflect changes in `@backstage/repo-tools`. + +## 0.0.2-next.1 + +### Patch Changes + +- fe16bd39e83: Use permalinks for links including a line number reference +- 021cfbb5152: Corrected resolution of parameter nested schema to use central schemas. + ## 0.0.2-next.0 ### Patch Changes diff --git a/packages/backend-openapi-utils/README.md b/packages/backend-openapi-utils/README.md index fe22ac2cf2..ba286f94e8 100644 --- a/packages/backend-openapi-utils/README.md +++ b/packages/backend-openapi-utils/README.md @@ -8,7 +8,7 @@ This package is meant to provide a typed Express router for an OpenAPI spec. Bas ### Configuration -1. Run `yarn --cwd backstage-cli package schema:openapi:generate` to translate your `src/schema/openapi.yaml` to a new Typescript file in `src/schema/openapi.generated.ts`. The command will try to execute both a lint and prettier step on the generated file, where applicable. +1. Run `yarn --cwd backstage-cli package schema openapi generate` to translate your `src/schema/openapi.yaml` to a new Typescript file in `src/schema/openapi.generated.ts`. The command will try to execute both a lint and prettier step on the generated file, where applicable. 2. In your plugin's `src/service/createRouter.ts`, @@ -42,4 +42,4 @@ Router() as ApiRouter> ### Runtime validation -Using a package like [`express-openapi-validator`](https://www.npmjs.com/package/express-openapi-validator), would allow us to remove [validation of request bodies with `AJV`](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/src/service/util.ts#L58). However, `AJV` currently doesn't have support for OpenAPI 3.1 and `express-openapi-validator` enforces full URL matching for paths, meaning it cannot be mounted at the router level. +Using a package like [`express-openapi-validator`](https://www.npmjs.com/package/express-openapi-validator), would allow us to remove [validation of request bodies with `AJV`](https://github.com/backstage/backstage/blob/e0506af8fc54074a160fb91c83d6cae8172d3bb3/plugins/catalog-backend/src/service/util.ts#L58). However, `AJV` currently doesn't have support for OpenAPI 3.1 and `express-openapi-validator` enforces full URL matching for paths, meaning it cannot be mounted at the router level. diff --git a/packages/backend-openapi-utils/package.json b/packages/backend-openapi-utils/package.json index e59da29840..89a4621a49 100644 --- a/packages/backend-openapi-utils/package.json +++ b/packages/backend-openapi-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-openapi-utils", "description": "OpenAPI typescript support.", - "version": "0.0.2-next.0", + "version": "0.0.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/backend-plugin-api/CHANGELOG.md b/packages/backend-plugin-api/CHANGELOG.md index 9a28b1dd3a..97b1bb4664 100644 --- a/packages/backend-plugin-api/CHANGELOG.md +++ b/packages/backend-plugin-api/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/backend-plugin-api +## 0.5.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-permission-common@0.7.5 + +## 0.5.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/config@1.0.7 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.5 + ## 0.5.2-next.1 ### Patch Changes diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index 58e103e647..117fd931d9 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-plugin-api", "description": "Core API used by Backstage backend plugins", - "version": "0.5.2-next.1", + "version": "0.5.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md index 1ef0203eb1..70532f865e 100644 --- a/packages/backend-tasks/CHANGELOG.md +++ b/packages/backend-tasks/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/backend-tasks +## 0.5.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## 0.5.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + ## 0.5.2-next.1 ### Patch Changes diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index b0f5c3afb3..7a76b1a004 100644 --- a/packages/backend-tasks/package.json +++ b/packages/backend-tasks/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-tasks", "description": "Common distributed task management library for Backstage backends", - "version": "0.5.2-next.1", + "version": "0.5.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index 3ce5006003..8b3c5de2c7 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/backend-test-utils +## 0.1.38-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-app-api@0.4.4-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.15-next.0 + +## 0.1.37 + +### Patch Changes + +- 63af7f6d53f: Allow specifying custom Docker registry for database tests +- b1eb268bf9d: Added `POSTGRES_11` and `POSTGRES_12` as supported test database IDs. +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-app-api@0.4.3 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/types@1.0.2 + ## 0.1.37-next.1 ### Patch Changes diff --git a/packages/backend-test-utils/README.md b/packages/backend-test-utils/README.md index d0f52388bb..f22cb1bd3c 100644 --- a/packages/backend-test-utils/README.md +++ b/packages/backend-test-utils/README.md @@ -12,6 +12,26 @@ cd plugins/my-plugin-backend yarn add --dev @backstage/backend-test-utils ``` +## Environment variables + +- `BACKSTAGE_TEST_DISABLE_DOCKER` + - Setting the value to `1` disables Docker for tests +- `CI` + - Setting the value to `1` enables long-running tests, including the ones utilizing Docker +- `BACKSTAGE_TEST_DOCKER_REGISTRY` + - Docker registry mirror address where to pull images for tests, for example `mycompany.docker.io/mirror` + - See [documentation](https://node.testcontainers.org/configuration/) for information + about authentication (`DOCKER_AUTH_CONFIG`) + +Connection strings for different databases that are used for testing. The value of the +string should point to the running instance of the database. + +- `BACKSTAGE_TEST_DATABASE_POSTGRES13_CONNECTION_STRING` +- `BACKSTAGE_TEST_DATABASE_POSTGRES12_CONNECTION_STRING` +- `BACKSTAGE_TEST_DATABASE_POSTGRES11_CONNECTION_STRING` +- `BACKSTAGE_TEST_DATABASE_POSTGRES9_CONNECTION_STRING` +- `BACKSTAGE_TEST_DATABASE_MYSQL8_CONNECTION_STRING` + ## Documentation - [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index b23d3b411e..b8a747a871 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-test-utils", "description": "Test helpers library for Backstage backends", - "version": "0.1.37-next.1", + "version": "0.1.38-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-test-utils/src/database/types.ts b/packages/backend-test-utils/src/database/types.ts index 89ec21e7cc..8c1d6f5193 100644 --- a/packages/backend-test-utils/src/database/types.ts +++ b/packages/backend-test-utils/src/database/types.ts @@ -16,6 +16,7 @@ import { DatabaseManager } from '@backstage/backend-common'; import { Knex } from 'knex'; +import { getDockerImageForName } from '../util/getDockerImageForName'; /** * The possible databases to test against. @@ -48,35 +49,35 @@ export const allDatabases: Record = POSTGRES_13: { name: 'Postgres 13.x', driver: 'pg', - dockerImageName: 'postgres:13', + dockerImageName: getDockerImageForName('postgres:13'), connectionStringEnvironmentVariableName: 'BACKSTAGE_TEST_DATABASE_POSTGRES13_CONNECTION_STRING', }, POSTGRES_12: { name: 'Postgres 12.x', driver: 'pg', - dockerImageName: 'postgres:12', + dockerImageName: getDockerImageForName('postgres:12'), connectionStringEnvironmentVariableName: 'BACKSTAGE_TEST_DATABASE_POSTGRES12_CONNECTION_STRING', }, POSTGRES_11: { name: 'Postgres 11.x', driver: 'pg', - dockerImageName: 'postgres:11', + dockerImageName: getDockerImageForName('postgres:11'), connectionStringEnvironmentVariableName: 'BACKSTAGE_TEST_DATABASE_POSTGRES11_CONNECTION_STRING', }, POSTGRES_9: { name: 'Postgres 9.x', driver: 'pg', - dockerImageName: 'postgres:9', + dockerImageName: getDockerImageForName('postgres:9'), connectionStringEnvironmentVariableName: 'BACKSTAGE_TEST_DATABASE_POSTGRES9_CONNECTION_STRING', }, MYSQL_8: { name: 'MySQL 8.x', driver: 'mysql2', - dockerImageName: 'mysql:8', + dockerImageName: getDockerImageForName('mysql:8'), connectionStringEnvironmentVariableName: 'BACKSTAGE_TEST_DATABASE_MYSQL8_CONNECTION_STRING', }, diff --git a/packages/backend-test-utils/src/util/getDockerImageForName.ts b/packages/backend-test-utils/src/util/getDockerImageForName.ts new file mode 100644 index 0000000000..7869e7b418 --- /dev/null +++ b/packages/backend-test-utils/src/util/getDockerImageForName.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2021 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. + */ + +export const getDockerImageForName = (name: string) => { + return process.env.BACKSTAGE_TEST_DOCKER_REGISTRY + ? `${process.env.BACKSTAGE_TEST_DOCKER_REGISTRY}/${name}` + : name; +}; diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index e676df6839..8ba25739ed 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,126 @@ # example-backend +## 0.2.84-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-scaffolder-backend@1.14.1-next.0 + - @backstage/plugin-jenkins-backend@0.2.1-next.0 + - @backstage/plugin-linguist-backend@0.3.0-next.0 + - @backstage/plugin-devtools-backend@0.1.1-next.0 + - @backstage/plugin-adr-backend@0.3.4-next.0 + - @backstage/plugin-auth-backend@0.18.4-next.0 + - @backstage/plugin-badges-backend@0.2.1-next.0 + - @backstage/plugin-catalog-backend@1.9.2-next.0 + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/plugin-code-coverage-backend@0.2.12-next.0 + - @backstage/plugin-entity-feedback-backend@0.1.4-next.0 + - @backstage/plugin-kubernetes-backend@0.11.1-next.0 + - @backstage/plugin-lighthouse-backend@0.2.2-next.0 + - @backstage/plugin-playlist-backend@0.3.2-next.0 + - @backstage/plugin-tech-insights-backend@0.5.12-next.0 + - @backstage/plugin-techdocs-backend@1.6.3-next.0 + - @backstage/plugin-todo-backend@0.1.43-next.0 + - example-app@0.2.84-next.0 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.15-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/plugin-app-backend@0.3.46-next.0 + - @backstage/plugin-explore-backend@0.0.8-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-azure-devops-backend@0.3.25-next.0 + - @backstage/plugin-azure-sites-backend@0.1.8-next.0 + - @backstage/plugin-events-backend@0.2.7-next.0 + - @backstage/plugin-events-node@0.2.7-next.0 + - @backstage/plugin-graphql-backend@0.1.36-next.0 + - @backstage/plugin-kafka-backend@0.2.39-next.0 + - @backstage/plugin-permission-backend@0.5.21-next.0 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-node@0.7.9-next.0 + - @backstage/plugin-proxy-backend@0.2.40-next.0 + - @backstage/plugin-rollbar-backend@0.1.43-next.0 + - @backstage/plugin-search-backend@1.3.2-next.0 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.1-next.0 + - @backstage/plugin-search-backend-module-pg@0.5.7-next.0 + - @backstage/plugin-search-backend-node@1.2.2-next.0 + - @backstage/plugin-search-common@1.2.3 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.30-next.0 + - @backstage/plugin-tech-insights-node@0.4.4-next.0 + +## 0.2.83 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.14.0 + - @backstage/plugin-devtools-backend@0.1.0 + - @backstage/plugin-catalog-backend@1.9.1 + - @backstage/backend-common@0.18.5 + - @backstage/plugin-kubernetes-backend@0.11.0 + - @backstage/plugin-auth-backend@0.18.3 + - @backstage/plugin-badges-backend@0.2.0 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.0 + - @backstage/integration@1.4.5 + - @backstage/plugin-todo-backend@0.1.42 + - @backstage/plugin-jenkins-backend@0.2.0 + - @backstage/plugin-azure-sites-backend@0.1.7 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/plugin-search-backend@1.3.1 + - example-app@0.2.83 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-app-backend@0.3.45 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/plugin-entity-feedback-backend@0.1.3 + - @backstage/plugin-events-backend@0.2.6 + - @backstage/plugin-playlist-backend@0.3.1 + - @backstage/plugin-rollbar-backend@0.1.42 + - @backstage/plugin-search-backend-module-pg@0.5.6 + - @backstage/plugin-tech-insights-backend@0.5.11 + - @backstage/plugin-techdocs-backend@1.6.2 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.14 + - @backstage/plugin-adr-backend@0.3.3 + - @backstage/plugin-azure-devops-backend@0.3.24 + - @backstage/plugin-code-coverage-backend@0.2.11 + - @backstage/plugin-explore-backend@0.0.7 + - @backstage/plugin-graphql-backend@0.1.35 + - @backstage/plugin-kafka-backend@0.2.38 + - @backstage/plugin-lighthouse-backend@0.2.1 + - @backstage/plugin-linguist-backend@0.2.2 + - @backstage/plugin-permission-backend@0.5.20 + - @backstage/plugin-proxy-backend@0.2.39 + - @backstage/plugin-search-backend-node@1.2.1 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.29 + - @backstage/plugin-tech-insights-node@0.4.3 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/plugin-events-node@0.2.6 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-common@1.2.3 + +## 0.2.83-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-devtools-backend@0.1.0-next.0 + - @backstage/plugin-catalog-backend@1.9.1-next.2 + - @backstage/plugin-badges-backend@0.2.0-next.2 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.0-next.2 + - @backstage/plugin-kubernetes-backend@0.11.0-next.2 + - @backstage/plugin-auth-backend@0.18.3-next.2 + - @backstage/plugin-search-backend@1.3.1-next.2 + - example-app@0.2.83-next.2 + - @backstage/plugin-scaffolder-backend@1.13.2-next.2 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.14-next.2 + - @backstage/config@1.0.7 + ## 0.2.83-next.1 ### Patch Changes diff --git a/packages/backend/Dockerfile b/packages/backend/Dockerfile index eca6ce82c2..da25f9736c 100644 --- a/packages/backend/Dockerfile +++ b/packages/backend/Dockerfile @@ -13,11 +13,14 @@ FROM node:16-bullseye-slim # Install sqlite3 dependencies. You can skip this if you don't use sqlite3 in the image, # in which case you should also move better-sqlite3 to "devDependencies" in package.json. +# Additionally, we install dependencies for `techdocs.generator.runIn: local`. +# https://backstage.io/docs/features/techdocs/getting-started#disabling-docker-in-docker-situation-optional RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt,sharing=locked \ apt-get update && \ - apt-get install -y --no-install-recommends libsqlite3-dev python3 build-essential && \ - yarn config set python /usr/bin/python3 + apt-get install -y --no-install-recommends libsqlite3-dev python3 python3-pip build-essential && \ + yarn config set python /usr/bin/python3 && \ + pip3 install mkdocs-techdocs-core==1.1.7 # From here on we use the least-privileged `node` user to run the backend. WORKDIR /app diff --git a/packages/backend/package.json b/packages/backend/package.json index 900ee150fc..f225e35d98 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.83-next.1", + "version": "0.2.84-next.0", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", @@ -42,6 +42,7 @@ "@backstage/plugin-catalog-backend": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", "@backstage/plugin-code-coverage-backend": "workspace:^", + "@backstage/plugin-devtools-backend": "workspace:^", "@backstage/plugin-entity-feedback-backend": "workspace:^", "@backstage/plugin-events-backend": "workspace:^", "@backstage/plugin-events-node": "workspace:^", diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index 593d30bc3b..976ad9a577 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -64,6 +64,7 @@ import playlist from './plugins/playlist'; import adr from './plugins/adr'; import lighthouse from './plugins/lighthouse'; import linguist from './plugins/linguist'; +import devTools from './plugins/devtools'; import { PluginEnvironment } from './types'; import { ServerPermissionClient } from '@backstage/plugin-permission-node'; import { DefaultIdentityClient } from '@backstage/plugin-auth-node'; @@ -158,8 +159,8 @@ async function main() { const eventsEnv = useHotMemoize(module, () => createEnv('events')); const exploreEnv = useHotMemoize(module, () => createEnv('explore')); const lighthouseEnv = useHotMemoize(module, () => createEnv('lighthouse')); - const linguistEnv = useHotMemoize(module, () => createEnv('linguist')); + const devToolsEnv = useHotMemoize(module, () => createEnv('devtools')); const apiRouter = Router(); apiRouter.use('/catalog', await catalog(catalogEnv)); @@ -185,6 +186,7 @@ async function main() { apiRouter.use('/entity-feedback', await entityFeedback(entityFeedbackEnv)); apiRouter.use('/adr', await adr(adrEnv)); apiRouter.use('/linguist', await linguist(linguistEnv)); + apiRouter.use('/devtools', await devTools(devToolsEnv)); apiRouter.use(notFoundHandler()); await lighthouse(lighthouseEnv); diff --git a/packages/backend/src/plugins/badges.ts b/packages/backend/src/plugins/badges.ts index 37529689f3..fa50731809 100644 --- a/packages/backend/src/plugins/badges.ts +++ b/packages/backend/src/plugins/badges.ts @@ -28,5 +28,8 @@ export default async function createPlugin( config: env.config, discovery: env.discovery, badgeFactories: createDefaultBadgeFactories(), + tokenManager: env.tokenManager, + logger: env.logger, + identity: env.identity, }); } diff --git a/packages/backend/src/plugins/devtools.ts b/packages/backend/src/plugins/devtools.ts new file mode 100644 index 0000000000..8e1767ddb1 --- /dev/null +++ b/packages/backend/src/plugins/devtools.ts @@ -0,0 +1,29 @@ +/* + * Copyright 2022 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 { createRouter } from '@backstage/plugin-devtools-backend'; +import { Router } from 'express'; +import type { PluginEnvironment } from '../types'; + +export default async function createPlugin( + env: PluginEnvironment, +): Promise { + return createRouter({ + logger: env.logger, + config: env.config, + permissions: env.permissions, + }); +} diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index 12c6e1b9c9..5b7d668947 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/catalog-client +## 1.4.2-next.0 + +### Patch Changes + +- cc936b529676: Updated API docs +- Updated dependencies + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + ## 1.4.1 ### Patch Changes diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index 010269dee6..77d3b58735 100644 --- a/packages/catalog-client/package.json +++ b/packages/catalog-client/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-client", "description": "An isomorphic client for the catalog backend", - "version": "1.4.1", + "version": "1.4.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index ee6579efca..5285bda2f7 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -353,6 +353,10 @@ export type Location = { export type AddLocationRequest = { type?: string; target: string; + /** + * If set to true, the location will not be added, but the response will + * contain the entities that match the given location. + */ dryRun?: boolean; }; @@ -363,8 +367,13 @@ export type AddLocationRequest = { */ export type AddLocationResponse = { location: Location; + /** + * The entities matching this location. Will only be filled in dryRun mode + */ entities: Entity[]; - // Only set in dryRun mode. + /** + * True, if the location exists. Will only be filled in dryRun mode + */ exists?: boolean; }; diff --git a/packages/catalog-model/examples/domains/artists-domain.yaml b/packages/catalog-model/examples/domains/artists-domain.yaml index 2a74425791..0dc1b91cb5 100644 --- a/packages/catalog-model/examples/domains/artists-domain.yaml +++ b/packages/catalog-model/examples/domains/artists-domain.yaml @@ -3,6 +3,7 @@ kind: Domain metadata: name: artists description: Everything related to artists + title: Artists links: - url: http://example.com/domain/artists/ title: Domain Readme diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index a8c7207650..386effadda 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/cli +## 0.22.8-next.0 + +### Patch Changes + +- 20b7da6f1311: Enforcing MUI v5 specific linting to minimize bundle size. +- Updated dependencies + - @backstage/config-loader@1.3.1-next.0 + - @backstage/config@1.0.7 + - @backstage/release-manifests@0.0.9 + - @backstage/cli-common@0.1.12 + - @backstage/cli-node@0.1.0 + - @backstage/errors@1.1.5 + - @backstage/eslint-plugin@0.1.3 + - @backstage/types@1.0.2 + +## 0.22.7 + +### Patch Changes + +- 473db605a4f: Enable strict config checking during `backstage-cli config:check` with the new `--strict` option which will surface schema errors. +- d548886872d: Deprecated the use of React 16 +- Updated dependencies + - @backstage/config-loader@1.3.0 + - @backstage/cli-common@0.1.12 + - @backstage/cli-node@0.1.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/eslint-plugin@0.1.3 + - @backstage/release-manifests@0.0.9 + - @backstage/types@1.0.2 + ## 0.22.7-next.0 ### Patch Changes diff --git a/packages/cli/cli-report.md b/packages/cli/cli-report.md index bad849d283..39bee2ed05 100644 --- a/packages/cli/cli-report.md +++ b/packages/cli/cli-report.md @@ -58,6 +58,7 @@ Options: --lax --frontend --deprecated + --strict --config -h, --help ``` diff --git a/packages/cli/config/eslint-factory.js b/packages/cli/config/eslint-factory.js index dde853fdff..36b51324fc 100644 --- a/packages/cli/config/eslint-factory.js +++ b/packages/cli/config/eslint-factory.js @@ -24,6 +24,7 @@ const { join: joinPath } = require('path'); * - `tsRules`: Additional ESLint rules to apply to TypeScript * - `testRules`: Additional ESLint rules to apply to tests * - `restrictedImports`: Additional paths to add to no-restricted-imports + * - `restrictedImportsPattern`: Additional patterns to add to no-restricted-imports * - `restrictedSrcImports`: Additional paths to add to no-restricted-imports in src files * - `restrictedTestImports`: Additional paths to add to no-restricted-imports in test files * - `restrictedSyntax`: Additional patterns to add to no-restricted-syntax @@ -44,6 +45,7 @@ function createConfig(dir, extraConfig = {}) { testRules, restrictedImports, + restrictedImportPatterns, restrictedSrcImports, restrictedTestImports, restrictedSyntax, @@ -114,6 +116,7 @@ function createConfig(dir, extraConfig = {}) { '*.test*', '**/__testUtils__/**', '**/__mocks__/**', + ...(restrictedImportPatterns ?? []), ], }, ], @@ -208,9 +211,19 @@ function createConfigForRole(dir, role, extraConfig = {}) { name: '@material-ui/icons/', // because this is possible too ._. message: "Please import '@material-ui/icons/' instead.", }, + { + // https://mui.com/material-ui/guides/minimizing-bundle-size/ + name: '@mui/material', + message: "Please import '@mui/material/...' instead.", + }, ...require('module').builtinModules, ...(extraConfig.restrictedImports ?? []), ], + // https://mui.com/material-ui/guides/minimizing-bundle-size/ + restrictedImportPatterns: [ + '@mui/*/*/*', + ...(extraConfig.restrictedImportPatterns ?? []), + ], tsRules: { 'react/prop-types': 0, ...extraConfig.tsRules, diff --git a/packages/cli/package.json b/packages/cli/package.json index 9de7b3dbb2..82f0667d5e 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli", "description": "CLI for developing Backstage plugins and apps", - "version": "0.22.7-next.0", + "version": "0.22.8-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/cli/src/commands/config/validate.ts b/packages/cli/src/commands/config/validate.ts index c3d05291e0..c81d82832e 100644 --- a/packages/cli/src/commands/config/validate.ts +++ b/packages/cli/src/commands/config/validate.ts @@ -24,5 +24,6 @@ export default async (opts: OptionValues) => { mockEnv: opts.lax, fullVisibility: !opts.frontend, withDeprecatedKeys: opts.deprecated, + strict: opts.strict, }); }; diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index ba11a53cfd..3a40839e25 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -345,6 +345,10 @@ export function registerCommands(program: Command) { .option('--lax', 'Do not require environment variables to be set') .option('--frontend', 'Only validate the frontend configuration') .option('--deprecated', 'Output deprecated configuration settings') + .option( + '--strict', + 'Enable strict config validation, forbidding errors and unknown keys', + ) .option(...configOption) .description( 'Validate that the given configuration loads and matches schema', diff --git a/packages/cli/src/commands/start/startFrontend.ts b/packages/cli/src/commands/start/startFrontend.ts index e066a40e7a..00f7818b41 100644 --- a/packages/cli/src/commands/start/startFrontend.ts +++ b/packages/cli/src/commands/start/startFrontend.ts @@ -32,6 +32,30 @@ interface StartAppOptions { configPaths: string[]; } +function checkReactVersion() { + try { + // Make sure we're looking at the root of the target repo + const reactPkgPath = require.resolve('react/package.json', { + paths: [paths.targetRoot], + }); + const reactPkg = require(reactPkgPath); + if (reactPkg.version.startsWith('16.')) { + console.log( + chalk.yellow( + ` +⚠️ ⚠️ +⚠️ You are using React version 16, which is deprecated for use in Backstage. ⚠️ +⚠️ Please upgrade to React 17 by updating your packages/app dependencies. ⚠️ +⚠️ ⚠️ +`, + ), + ); + } + } catch { + /* ignored */ + } +} + export async function startFrontend(options: StartAppOptions) { if (options.verifyVersions) { const lockfile = await Lockfile.load(paths.resolveTargetRoot('yarn.lock')); @@ -65,6 +89,8 @@ export async function startFrontend(options: StartAppOptions) { } } + checkReactVersion(); + const { name } = await fs.readJson(paths.resolveTarget('package.json')); const config = await loadCliConfig({ args: options.configPaths, diff --git a/packages/cli/src/lib/config.ts b/packages/cli/src/lib/config.ts index b34e1280c0..aaf3fcfcb9 100644 --- a/packages/cli/src/lib/config.ts +++ b/packages/cli/src/lib/config.ts @@ -32,6 +32,7 @@ type Options = { withFilteredKeys?: boolean; withDeprecatedKeys?: boolean; fullVisibility?: boolean; + strict?: boolean; }; export async function loadCliConfig(options: Options) { @@ -70,6 +71,7 @@ export async function loadCliConfig(options: Options) { dependencies: localPackageNames, // Include the package.json in the project root if it exists packagePaths: [paths.resolveTargetRoot('package.json')], + noUndeclaredProperties: options.strict, }); const { appConfigs } = await loadConfig({ @@ -93,6 +95,7 @@ export async function loadCliConfig(options: Options) { : ['frontend'], withFilteredKeys: options.withFilteredKeys, withDeprecatedKeys: options.withDeprecatedKeys, + ignoreSchemaErrors: !options.strict, }); const frontendConfig = ConfigReader.fromConfigs(frontendAppConfigs); diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md index 9b2d34f957..ce613acbb5 100644 --- a/packages/config-loader/CHANGELOG.md +++ b/packages/config-loader/CHANGELOG.md @@ -1,5 +1,67 @@ # @backstage/config-loader +## 1.3.1-next.0 + +### Patch Changes + +- f25427f665f7: Fix a bug where config items with `/` in the key were incorrectly handled. +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## 1.3.0 + +### Minor Changes + +- 201206132da: Introduced a new config source system to replace `loadConfig`. There is a new `ConfigSource` interface along with utilities provided by `ConfigSources`, as well as a number of built-in configuration source implementations. The new system is more flexible and makes it easier to create new and reusable sources of configuration, such as loading configuration from secret providers. + + The following is an example of how to load configuration using the default behavior: + + ```ts + const source = ConfigSources.default({ + argv: options?.argv, + remote: options?.remote, + }); + const config = await ConfigSources.toConfig(source); + ``` + + The `ConfigSource` interface looks like this: + + ```ts + export interface ConfigSource { + readConfigData(options?: ReadConfigDataOptions): AsyncConfigSourceIterator; + } + ``` + + It is best implemented using an async iterator: + + ```ts + class MyConfigSource implements ConfigSource { + async *readConfigData() { + yield { + config: [ + { + context: 'example', + data: { backend: { baseUrl: 'http://localhost' } }, + }, + ], + }; + } + } + ``` + +### Patch Changes + +- 7c116bcac7f: Fixed the way that some request errors are thrown +- 473db605a4f: Added a new `noUndeclaredProperties` option to `SchemaLoader` to support enforcing that there are no extra keys when verifying config. +- Updated dependencies + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + ## 1.3.0-next.0 ### Minor Changes diff --git a/packages/config-loader/api-report.md b/packages/config-loader/api-report.md index 1cc353fd4c..8cd469d4d7 100644 --- a/packages/config-loader/api-report.md +++ b/packages/config-loader/api-report.md @@ -180,14 +180,17 @@ export function loadConfigSchema( ): Promise; // @public -export type LoadConfigSchemaOptions = +export type LoadConfigSchemaOptions = ( | { dependencies: string[]; packagePaths?: string[]; } | { serialized: JsonObject; - }; + } +) & { + noUndeclaredProperties?: boolean; +}; // @public export function mergeConfigSchemas(schemas: JSONSchema7[]): JSONSchema7; diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index 0aa071c206..741637e40b 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config-loader", "description": "Config loading functionality used by Backstage backend, and CLI", - "version": "1.3.0-next.0", + "version": "1.3.1-next.0", "publishConfig": { "access": "public", "main": "dist/index.cjs.js", diff --git a/packages/config-loader/src/schema/compile.test.ts b/packages/config-loader/src/schema/compile.test.ts index c2541751e7..df81923684 100644 --- a/packages/config-loader/src/schema/compile.test.ts +++ b/packages/config-loader/src/schema/compile.test.ts @@ -170,4 +170,64 @@ describe('compileConfigSchemas', () => { visibilityBySchemaPath: new Map(), }); }); + + it('should handle slashes correctly', () => { + const validate = compileConfigSchemas([ + { + path: 'a1', + value: { + type: 'object', + properties: { + '/circleci/api': { + type: 'object', + properties: { + target: { + type: 'string', + }, + headers: { + type: 'object', + properties: { + 'Circle-Token': { + type: 'string', + visibility: 'secret', + }, + }, + }, + }, + }, + '/gocd': { type: 'string', visibility: 'backend' }, + }, + }, + }, + ]); + expect( + validate([ + { + data: { + '/circleci/api': { + target: 'test', + headers: { + 'Circle-Token': 'my-token', + }, + }, + '/gocd': 'test', + }, + context: 'test', + }, + ]), + ).toEqual({ + visibilityByDataPath: new Map( + Object.entries({ + '//circleci/api/headers/Circle-Token': 'secret', + }), + ), + visibilityBySchemaPath: new Map( + Object.entries({ + '/properties//circleci/api/properties/headers/properties/Circle-Token': + 'secret', + }), + ), + deprecationByDataPath: new Map(), + }); + }); }); diff --git a/packages/config-loader/src/schema/compile.ts b/packages/config-loader/src/schema/compile.ts index d193e7fbf2..63a8e4b8a6 100644 --- a/packages/config-loader/src/schema/compile.ts +++ b/packages/config-loader/src/schema/compile.ts @@ -25,6 +25,8 @@ import { CONFIG_VISIBILITIES, ConfigVisibility, } from './types'; +import { SchemaObject } from 'json-schema-traverse'; +import { normalizeAjvPath } from './utils'; /** * This takes a collection of Backstage configuration schemas from various @@ -35,6 +37,9 @@ import { */ export function compileConfigSchemas( schemas: ConfigSchemaPackageEntry[], + options?: { + noUndeclaredProperties?: boolean; + }, ): ValidationFunc { // The ajv instance below is stateful and doesn't really allow for additional // output during validation. We work around this by having this extra piece @@ -62,10 +67,7 @@ export function compileConfigSchemas( return false; } if (visibility && visibility !== 'backend') { - const normalizedPath = context.instancePath.replace( - /\['?(.*?)'?\]/g, - (_, segment) => `/${segment}`, - ); + const normalizedPath = normalizeAjvPath(context.instancePath); visibilityByDataPath.set(normalizedPath, visibility); } return true; @@ -81,10 +83,7 @@ export function compileConfigSchemas( if (context?.instancePath === undefined) { return false; } - const normalizedPath = context.instancePath.replace( - /\['?(.*?)'?\]/g, - (_, segment) => `/${segment}`, - ); + const normalizedPath = normalizeAjvPath(context.instancePath); // create mapping of deprecation description and data path of property deprecationByDataPath.set(normalizedPath, deprecationDescription); return true; @@ -102,12 +101,24 @@ export function compileConfigSchemas( const merged = mergeConfigSchemas(schemas.map(_ => _.value)); + if (options?.noUndeclaredProperties) { + traverse(merged, (schema: SchemaObject) => { + /** + * The `additionalProperties` key can only be applied to `type: object` in the JSON + * schema. + */ + if (schema?.type === 'object') { + schema.additionalProperties ||= false; + } + }); + } + const validate = ajv.compile(merged); const visibilityBySchemaPath = new Map(); traverse(merged, (schema, path) => { if (schema.visibility && schema.visibility !== 'backend') { - visibilityBySchemaPath.set(path, schema.visibility); + visibilityBySchemaPath.set(normalizeAjvPath(path), schema.visibility); } }); diff --git a/packages/config-loader/src/schema/filtering.ts b/packages/config-loader/src/schema/filtering.ts index e9a0327e06..1c2d0c122a 100644 --- a/packages/config-loader/src/schema/filtering.ts +++ b/packages/config-loader/src/schema/filtering.ts @@ -21,6 +21,7 @@ import { TransformFunc, ValidationError, } from './types'; +import { normalizeAjvPath } from './utils'; /** * This filters data by visibility by discovering the visibility of each @@ -163,7 +164,10 @@ export function filterErrorsByVisibility( // We don't use this method for all the errors as the data path is more robust // and doesn't require us to properly trim the schema path. if (error.keyword === 'required') { - const trimmedPath = error.schemaPath.slice(1, -'/required'.length); + const trimmedPath = normalizeAjvPath(error.schemaPath).slice( + 1, + -'/required'.length, + ); const fullPath = `${trimmedPath}/properties/${error.params.missingProperty}`; if ( visibleSchemaPaths.some(visiblePath => visiblePath.startsWith(fullPath)) @@ -173,7 +177,8 @@ export function filterErrorsByVisibility( } const vis = - visibilityByDataPath.get(error.instancePath) ?? DEFAULT_CONFIG_VISIBILITY; + visibilityByDataPath.get(normalizeAjvPath(error.instancePath)) ?? + DEFAULT_CONFIG_VISIBILITY; return vis && includeVisibilities.includes(vis); }); } diff --git a/packages/config-loader/src/schema/load.ts b/packages/config-loader/src/schema/load.ts index 0309f64ea0..8ef971184f 100644 --- a/packages/config-loader/src/schema/load.ts +++ b/packages/config-loader/src/schema/load.ts @@ -25,6 +25,7 @@ import { ConfigSchemaPackageEntry, CONFIG_VISIBILITIES, } from './types'; +import { normalizeAjvPath } from './utils'; /** * Options that control the loading of configuration schema files in the backend. @@ -32,12 +33,16 @@ import { * @public */ export type LoadConfigSchemaOptions = - | { - dependencies: string[]; - packagePaths?: string[]; - } - | { - serialized: JsonObject; + | ( + | { + dependencies: string[]; + packagePaths?: string[]; + } + | { + serialized: JsonObject; + } + ) & { + noUndeclaredProperties?: boolean; }; function errorsToError(errors: ValidationError[]): Error { @@ -45,7 +50,9 @@ function errorsToError(errors: ValidationError[]): Error { const paramStr = Object.entries(params) .map(([name, value]) => `${name}=${value}`) .join(' '); - return `Config ${message || ''} { ${paramStr} } at ${instancePath}`; + return `Config ${message || ''} { ${paramStr} } at ${normalizeAjvPath( + instancePath, + )}`; }); const error = new Error(`Config validation failed, ${messages.join('; ')}`); (error as any).messages = messages; @@ -77,7 +84,9 @@ export async function loadConfigSchema( schemas = serialized.schemas as ConfigSchemaPackageEntry[]; } - const validate = compileConfigSchemas(schemas); + const validate = compileConfigSchemas(schemas, { + noUndeclaredProperties: options.noUndeclaredProperties, + }); return { process( diff --git a/packages/config-loader/src/schema/utils.ts b/packages/config-loader/src/schema/utils.ts new file mode 100644 index 0000000000..25525a8c50 --- /dev/null +++ b/packages/config-loader/src/schema/utils.ts @@ -0,0 +1,29 @@ +/* + * Copyright 2023 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. + */ + +/** + * AJV does some encoding to schema and instance paths. Revert those encodings to + * easier to read and parse values. + * See https://github.com/ajv-validator/ajv/blob/master/lib/compile/util.ts#L69. + * + * @param path Path from AJV. + * @returns Updated path with correct characters. + */ +export function normalizeAjvPath(path: string) { + return path + .replace(/~1/g, '/') + .replace(/\['?(.*?)'?\]/g, (_, segment) => `/${segment}`); +} diff --git a/packages/config-loader/src/sources/FileConfigSource.test.ts b/packages/config-loader/src/sources/FileConfigSource.test.ts index c6980006c0..61cdeed272 100644 --- a/packages/config-loader/src/sources/FileConfigSource.test.ts +++ b/packages/config-loader/src/sources/FileConfigSource.test.ts @@ -66,7 +66,7 @@ describe('FileConfigSource', () => { setTimeout(() => { tmp.write('a.yaml', 'a: 2'); - }, 10); + }, 100); await expect(readN(source, 2)).resolves.toEqual([ [{ data: { a: 1 }, context: 'a.yaml', path: tmp.resolve('a.yaml') }], @@ -132,7 +132,7 @@ describe('FileConfigSource', () => { setTimeout(() => { tmp.write('x.yaml', '${MY_OTHER_VALUE}'); - }, 10); + }, 100); await expect(readN(source, 2)).resolves.toEqual([ [{ data: { a: '6' }, context: 'a.yaml', path: tmp.resolve('a.yaml') }], @@ -152,7 +152,7 @@ describe('FileConfigSource', () => { setTimeout(() => { tmp.write('x.txt', '9'); - }, 10); + }, 100); await expect(readN(source, 2)).resolves.toEqual([ [{ data: { a: '8' }, context: 'a.yaml', path: tmp.resolve('a.yaml') }], diff --git a/packages/config-loader/src/sources/RemoteConfigSource.ts b/packages/config-loader/src/sources/RemoteConfigSource.ts index ff75060f56..3a8f6bf812 100644 --- a/packages/config-loader/src/sources/RemoteConfigSource.ts +++ b/packages/config-loader/src/sources/RemoteConfigSource.ts @@ -149,7 +149,7 @@ export class RemoteConfigSource implements ConfigSource { signal: signal as import('node-fetch').RequestInit['signal'], }); if (!res.ok) { - throw ResponseError.fromResponse(res); + throw await ResponseError.fromResponse(res); } const content = await res.text(); diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index f4179e6fb6..f6df0da032 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/core-app-api +## 1.8.0 + +### Minor Changes + +- c89437db899: The analytics' `navigate` event will now include the route parameters as attributes of the navigate event + +### Patch Changes + +- b645d70034a: Fixed a bug in the Azure auth provider which prevented getting access tokens with multiple scopes for one resource +- 42d817e76ab: Added `FrontendHostDiscovery` for config driven discovery implementation +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.4 + ## 1.8.0-next.1 ### Minor Changes diff --git a/packages/core-app-api/config.d.ts b/packages/core-app-api/config.d.ts index 2de1d96114..e8cc879c90 100644 --- a/packages/core-app-api/config.d.ts +++ b/packages/core-app-api/config.d.ts @@ -117,8 +117,8 @@ export interface Config { }; /** - $ Enable redirect authentication flow type, instead of a popup for authentication - * default value: 'false' + * Enable redirect authentication flow type, instead of a popup for authentication. + * @defaultValue false * @visibility frontend */ enableExperimentalRedirectFlow?: boolean; diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index 5d99754068..4416fa99e1 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-app-api", "description": "Core app API used by Backstage apps", - "version": "1.8.0-next.1", + "version": "1.8.0", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/core-app-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.test.ts b/packages/core-app-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.test.ts index c71799ed98..1c51dd0698 100644 --- a/packages/core-app-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.test.ts +++ b/packages/core-app-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.test.ts @@ -79,6 +79,16 @@ describe('MicrosoftAuth', () => { 'Requested access token with scopes from multiple Azure resources: one-resource, other-resource. Access tokens can only have a single audience.', ); }); + + it('succeeds when requesting multiple scopes for the same resource', async () => { + const accessTokenPromise = microsoftAuth.getAccessToken( + 'same-resource/one-scope same-resource/other-scope', + ); + + await expect(accessTokenPromise).resolves.toEqual( + 'tokenForOtherResource', + ); + }); }); describe('without a refresh token', () => { diff --git a/packages/core-app-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.ts b/packages/core-app-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.ts index fdffb3fc45..c57c65d830 100644 --- a/packages/core-app-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.ts +++ b/packages/core-app-api/src/apis/implementations/auth/microsoft/MicrosoftAuth.ts @@ -91,10 +91,15 @@ export default class MicrosoftAuth { } private static resourceForScopes(scope: string): Promise { - const audiences = scope - .split(' ') - .map(MicrosoftAuth.resourceForScope) - .filter(aud => aud !== 'openid'); + const audiences = [ + ...new Set( + scope + .split(' ') + .map(MicrosoftAuth.resourceForScope) + .filter(aud => aud !== 'openid'), + ), + ]; + if (audiences.length > 1) { return Promise.reject( new Error( diff --git a/packages/core-app-api/src/app/types.ts b/packages/core-app-api/src/app/types.ts index 3d9005b0c0..c34407ca3a 100644 --- a/packages/core-app-api/src/app/types.ts +++ b/packages/core-app-api/src/app/types.ts @@ -236,21 +236,13 @@ export type AppOptions = { * title: 'Light Theme', * variant: 'light', * icon: , - * Provider: ({ children }) => ( - * - * {children} - * - * ), + * Provider: ({ children }) => , * }, { * id: 'dark', * title: 'Dark Theme', * variant: 'dark', * icon: , - * Provider: ({ children }) => ( - * - * {children} - * - * ), + * Provider: ({ children }) => , * }] * ``` */ diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index 825b793d2c..8f3b626157 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/core-components +## 0.13.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/version-bridge@1.0.4 + +## 0.13.1 + +### Patch Changes + +- 83b45f9df50: Fix accessibility issue with Backstage Table's header style +- e97769f7c0b: Fix accessibility issue on controlled select input on tab navigation + keyboard enter/space action. +- b1f13cb38aa: Fix accessibility issue with Edit Metadata Link on screen readers missing notice about opening in a new tab. +- 26cff1a5dfb: Start capturing sidebar click events in analytics by default. +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/version-bridge@1.0.4 + +## 0.13.1-next.1 + +### Patch Changes + +- 83b45f9df50: Fix accessibility issue with Backstage Table's header style +- e97769f7c0b: Fix accessibility issue on controlled select input on tab navigation + keyboard enter/space action. +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + ## 0.13.1-next.0 ### Patch Changes diff --git a/packages/core-components/package.json b/packages/core-components/package.json index cdb5a6e4a8..e3e27e492b 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-components", "description": "Core components used by Backstage plugins and apps", - "version": "0.13.1-next.0", + "version": "0.13.2-next.0", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/core-components/src/components/Link/Link.tsx b/packages/core-components/src/components/Link/Link.tsx index be91753ea3..4d58fdfa77 100644 --- a/packages/core-components/src/components/Link/Link.tsx +++ b/packages/core-components/src/components/Link/Link.tsx @@ -188,6 +188,9 @@ export const Link = React.forwardRef( - + Login Required {authRedirect ? ( diff --git a/packages/core-components/src/components/Select/Select.test.tsx b/packages/core-components/src/components/Select/Select.test.tsx index e9828e70fd..71159150e4 100644 --- a/packages/core-components/src/components/Select/Select.test.tsx +++ b/packages/core-components/src/components/Select/Select.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { fireEvent, render } from '@testing-library/react'; +import { fireEvent, render, within } from '@testing-library/react'; import React from 'react'; import { SelectComponent as Select } from './Select'; @@ -45,7 +45,7 @@ describe('} - label={label} - tabIndex={0} - renderValue={s => - multiple && (value as any[]).length !== 0 ? ( - - {(s as string[]).map(selectedValue => ( - el.value === selectedValue)?.value} - label={ - items.find(el => el.value === selectedValue)?.label - } - clickable - onDelete={handleDelete(selectedValue)} - className={classes.chip} - /> - ))} - - ) : ( - - {(value as any[]).length === 0 - ? placeholder || '' - : items.find(el => el.value === s)?.label} - - ) - } - IconComponent={() => - !isOpen ? : - } - MenuProps={{ - anchorOrigin: { - vertical: 'bottom', - horizontal: 'left', - }, - transformOrigin: { - vertical: 'top', - horizontal: 'left', - }, - getContentAnchorEl: null, - }} - > - {placeholder && !multiple && ( - {placeholder} - )} - {native - ? items && - items.map(item => ( - - )) - : items && - items.map(item => ( - - {multiple && ( - - )} - {item.label} - + + {label} + - - + + ) : ( + + {(value as any[]).length === 0 + ? placeholder || '' + : items.find(el => el.value === s)?.label} + + ) + } + IconComponent={() => + !isOpen ? : + } + MenuProps={{ + anchorOrigin: { + vertical: 'bottom', + horizontal: 'left', + }, + transformOrigin: { + vertical: 'top', + horizontal: 'left', + }, + getContentAnchorEl: null, + }} + > + {placeholder && !multiple && ( + {placeholder} + )} + {native + ? items && + items.map(item => ( + + )) + : items && + items.map(item => ( + + {multiple && ( + + )} + {item.label} + + ))} + + ); } diff --git a/packages/core-components/src/components/Table/Table.tsx b/packages/core-components/src/components/Table/Table.tsx index 848c85eb60..5cea3dd6b6 100644 --- a/packages/core-components/src/components/Table/Table.tsx +++ b/packages/core-components/src/components/Table/Table.tsx @@ -105,7 +105,6 @@ const StyledMTableHeader = withStyles( borderTop: `1px solid ${theme.palette.grey.A100}`, borderBottom: `1px solid ${theme.palette.grey.A100}`, // withStyles hasn't a generic overload for theme - color: (theme as BackstageTheme).palette.textSubtle, fontWeight: theme.typography.fontWeightBold, position: 'static', wordBreak: 'normal', diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 948c4017a3..52639751e7 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/create-app +## 0.5.2-next.0 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.12 + +## 0.5.1 + +### Patch Changes + +- 1d5e42655cd: Correct command to create new plugins +- e04bb20bdc4: Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.12 + +## 0.5.1-next.2 + +### Patch Changes + +- 1d5e42655cd: Correct command to create new plugins + ## 0.5.1-next.1 ### Patch Changes @@ -2595,7 +2618,7 @@ fields that clarify a previous grey area such that the intent of the alteration is made explicit. This is caught by `tsc` and your editor if you are using the `@ts-check` and `@param` syntax in your migration files - ([example](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/migrations/20220116144621_remove_legacy.js#L17)), + ([example](https://github.com/backstage/backstage/blob/e0506af8fc54074a160fb91c83d6cae8172d3bb3/plugins/catalog-backend/migrations/20220116144621_remove_legacy.js#L17)), which we strongly recommend. See the [`knex` documentation](https://knexjs.org/#Schema-alter) for more @@ -2665,7 +2688,7 @@ fields that clarify a previous grey area such that the intent of the alteration is made explicit. This is caught by `tsc` and your editor if you are using the `@ts-check` and `@param` syntax in your migration files - ([example](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/migrations/20220116144621_remove_legacy.js#L17)), + ([example](https://github.com/backstage/backstage/blob/e0506af8fc54074a160fb91c83d6cae8172d3bb3/plugins/catalog-backend/migrations/20220116144621_remove_legacy.js#L17)), which we strongly recommend. See the [`knex` documentation](https://knexjs.org/#Schema-alter) for more diff --git a/packages/create-app/package.json b/packages/create-app/package.json index ef61e1c5b8..08b67c7ea1 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/create-app", "description": "A CLI that helps you create your own Backstage app", - "version": "0.5.1-next.1", + "version": "0.5.2-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/create-app/templates/default-app/package.json.hbs b/packages/create-app/templates/default-app/package.json.hbs index f00500af68..0682114a35 100644 --- a/packages/create-app/templates/default-app/package.json.hbs +++ b/packages/create-app/templates/default-app/package.json.hbs @@ -39,10 +39,7 @@ }, "resolutions": { "@types/react": "^17", - "@types/react-dom": "^17", - "@octokit/rest": "18.5.6", - "@octokit/plugin-rest-endpoint-methods": "5.16.2", - "@octokit/plugin-paginate-rest": "2.7.0" + "@types/react-dom": "^17" }, "prettier": "@spotify/prettier-config", "lint-staged": { diff --git a/packages/create-app/templates/default-app/plugins/README.md b/packages/create-app/templates/default-app/plugins/README.md index 58dc32cb08..d7865fdba3 100644 --- a/packages/create-app/templates/default-app/plugins/README.md +++ b/packages/create-app/templates/default-app/plugins/README.md @@ -4,6 +4,6 @@ This is where your own plugins and their associated modules live, each in a separate folder of its own. If you want to create a new plugin here, go to your project root directory, run -the command `yarn backstage-cli create`, and follow the on-screen instructions. +the command `yarn new`, and follow the on-screen instructions. You can also check out existing plugins on [the plugin marketplace](https://backstage.io/plugins)! diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index a6aeda0901..75a72c7f1d 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,49 @@ # @backstage/dev-utils +## 1.0.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/test-utils@1.4.0-next.0 + - @backstage/app-defaults@1.4.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/catalog-model@1.3.0 + +## 1.0.15 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/app-defaults@1.3.1 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/test-utils@1.3.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 1.0.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/app-defaults@1.3.1-next.2 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/test-utils@1.3.1-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-app-api@1.8.0-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 1.0.15-next.1 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index ca5057c928..e3b057395e 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/dev-utils", "description": "Utilities for developing Backstage plugins.", - "version": "1.0.15-next.1", + "version": "1.0.16-next.0", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/e2e-test/CHANGELOG.md b/packages/e2e-test/CHANGELOG.md index 2486a83f5c..363337002e 100644 --- a/packages/e2e-test/CHANGELOG.md +++ b/packages/e2e-test/CHANGELOG.md @@ -1,5 +1,30 @@ # e2e-test +## 0.2.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.2-next.0 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.1.5 + +## 0.2.3 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.1 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.1.5 + +## 0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.1-next.2 + ## 0.2.3-next.1 ### Patch Changes diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index 513a9c6a96..e17f320c31 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -1,7 +1,7 @@ { "name": "e2e-test", "description": "E2E test for verifying Backstage packages", - "version": "0.2.3-next.1", + "version": "0.2.4-next.0", "private": true, "backstage": { "role": "cli" diff --git a/packages/integration-aws-node/CHANGELOG.md b/packages/integration-aws-node/CHANGELOG.md index 40192bdfaf..181b08c4ee 100644 --- a/packages/integration-aws-node/CHANGELOG.md +++ b/packages/integration-aws-node/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/integration-aws-node +## 0.1.3 + +### Patch Changes + +- 3659c71c5d9: Standardize `@aws-sdk` v3 versions +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + ## 0.1.2 ### Patch Changes diff --git a/packages/integration-aws-node/package.json b/packages/integration-aws-node/package.json index 7afc31cc47..8eec21a143 100644 --- a/packages/integration-aws-node/package.json +++ b/packages/integration-aws-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration-aws-node", "description": "Helpers for fetching AWS account credentials", - "version": "0.1.2", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -32,11 +32,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@aws-sdk/client-sts": "^3.208.0", - "@aws-sdk/credential-provider-node": "^3.208.0", - "@aws-sdk/credential-providers": "^3.208.0", - "@aws-sdk/types": "^3.208.0", - "@aws-sdk/util-arn-parser": "^3.208.0", + "@aws-sdk/client-sts": "^3.310.0", + "@aws-sdk/credential-provider-node": "^3.310.0", + "@aws-sdk/credential-providers": "^3.310.0", + "@aws-sdk/types": "^3.310.0", + "@aws-sdk/util-arn-parser": "^3.310.0", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^" }, diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index ac62e9aab7..7a893b10b7 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/integration-react +## 1.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## 1.1.13 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## 1.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + ## 1.1.13-next.1 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index e59c8f48c4..086d616510 100644 --- a/packages/integration-react/package.json +++ b/packages/integration-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration-react", "description": "Frontend package for managing integrations towards external systems", - "version": "1.1.13-next.1", + "version": "1.1.14-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md index 92eff86bb5..7dcef4fbc9 100644 --- a/packages/integration/CHANGELOG.md +++ b/packages/integration/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/integration +## 1.4.5 + +### Patch Changes + +- b026275bcc8: Fixed a bug where the wrong credentials would be selected when using multiple GitHub app integrations. +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + ## 1.4.5-next.0 ### Patch Changes diff --git a/packages/integration/package.json b/packages/integration/package.json index fbe8ac1fc3..14b64b3089 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration", "description": "Helpers for managing integrations towards external systems", - "version": "1.4.5-next.0", + "version": "1.4.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/repo-tools/CHANGELOG.md b/packages/repo-tools/CHANGELOG.md index e31c05532c..7f1ece48d4 100644 --- a/packages/repo-tools/CHANGELOG.md +++ b/packages/repo-tools/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/repo-tools +## 0.3.0 + +### Minor Changes + +- 799c33047ed: **BREAKING**: The OpenAPI commands are now found within the `schema openapi` sub-command. For example `yarn backstage-repo-tools schema:openapi:verify` is now `yarn backstage-repo-tools schema openapi verify`. +- 27956d78671: Generated OpenAPI files now have a `.generated.ts` file name and a warning header at the top, to highlight that they should not be edited by hand. + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.12 + - @backstage/cli-node@0.1.0 + - @backstage/errors@1.1.5 + ## 0.3.0-next.0 ### Minor Changes diff --git a/packages/repo-tools/cli-report.md b/packages/repo-tools/cli-report.md index b361bac02f..789b4bc407 100644 --- a/packages/repo-tools/cli-report.md +++ b/packages/repo-tools/cli-report.md @@ -14,8 +14,7 @@ Options: Commands: api-reports [options] [paths...] type-deps - schema:openapi:verify [paths...] - schema:openapi:generate [paths...] + schema [command] help [command] ``` @@ -37,19 +36,46 @@ Options: -h, --help ``` -### `backstage-repo-tools schema:openapi:generate` +### `backstage-repo-tools schema` ``` -Usage: backstage-repo-tools schema:openapi:generate [options] [paths...] +Usage: backstage-repo-tools schema [options] [command] [command] + +Options: + -h, --help + +Commands: + openapi [command] + help [command] +``` + +### `backstage-repo-tools schema openapi` + +``` +Usage: backstage-repo-tools schema openapi [options] [command] [command] + +Options: + -h, --help + +Commands: + verify [paths...] + generate [paths...] + help [command] +``` + +### `backstage-repo-tools schema openapi generate` + +``` +Usage: backstage-repo-tools schema openapi generate [options] [paths...] Options: -h, --help ``` -### `backstage-repo-tools schema:openapi:verify` +### `backstage-repo-tools schema openapi verify` ``` -Usage: backstage-repo-tools schema:openapi:verify [options] [paths...] +Usage: backstage-repo-tools schema openapi verify [options] [paths...] Options: -h, --help diff --git a/packages/repo-tools/package.json b/packages/repo-tools/package.json index 74c39fc9a8..85f683a999 100644 --- a/packages/repo-tools/package.json +++ b/packages/repo-tools/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/repo-tools", "description": "CLI for Backstage repo tooling ", - "version": "0.3.0-next.0", + "version": "0.3.0", "publishConfig": { "access": "public" }, diff --git a/packages/repo-tools/src/commands/index.ts b/packages/repo-tools/src/commands/index.ts index f4d02df3bc..a8324c7d33 100644 --- a/packages/repo-tools/src/commands/index.ts +++ b/packages/repo-tools/src/commands/index.ts @@ -18,6 +18,30 @@ import { assertError } from '@backstage/errors'; import { Command } from 'commander'; import { exitWithError } from '../lib/errors'; +function registerSchemaCommand(program: Command) { + const command = program + .command('schema [command]') + .description('Various tools for working with API schema'); + + const openApiCommand = command + .command('openapi [command]') + .description('Tooling for OpenApi schema'); + + openApiCommand + .command('verify [paths...]') + .description( + 'Verify that all OpenAPI schemas are valid and have a matching `schemas/openapi.generated.ts` file.', + ) + .action(lazy(() => import('./openapi/verify').then(m => m.bulkCommand))); + + openApiCommand + .command('generate [paths...]') + .description( + 'Generates a Typescript file from an OpenAPI yaml spec. For use with the `@backstage/backend-openapi-utils` ApiRouter type.', + ) + .action(lazy(() => import('./openapi/generate').then(m => m.bulkCommand))); +} + export function registerCommands(program: Command) { program .command('api-reports [paths...]') @@ -63,19 +87,7 @@ export function registerCommands(program: Command) { .description('Find inconsistencies in types of all packages and plugins') .action(lazy(() => import('./type-deps/type-deps').then(m => m.default))); - program - .command('schema:openapi:verify [paths...]') - .description( - 'Verify that all OpenAPI schemas are valid and have a matching `schemas/openapi.generated.ts` file.', - ) - .action(lazy(() => import('./openapi/verify').then(m => m.bulkCommand))); - - program - .command('schema:openapi:generate [paths...]') - .description( - 'Generates a Typescript file from an OpenAPI yaml spec. For use with the `@backstage/backend-openapi-utils` ApiRouter type.', - ) - .action(lazy(() => import('./openapi/generate').then(m => m.bulkCommand))); + registerSchemaCommand(program); } // Wraps an action function so that it always exits and handles errors diff --git a/packages/repo-tools/src/commands/openapi/verify.ts b/packages/repo-tools/src/commands/openapi/verify.ts index f6dda66738..4c4f310f73 100644 --- a/packages/repo-tools/src/commands/openapi/verify.ts +++ b/packages/repo-tools/src/commands/openapi/verify.ts @@ -47,7 +47,7 @@ async function verify(directoryPath: string) { if (!isEqual(schema.default, yaml)) { const path = relativePath(cliPaths.targetRoot, directoryPath); throw new Error( - `\`${YAML_SCHEMA_PATH}\` and \`${TS_SCHEMA_PATH}\` do not match. Please run \`yarn backstage-repo-tools schema:openapi:generate ${path}\` to regenerate \`${TS_SCHEMA_PATH}\`.`, + `\`${YAML_SCHEMA_PATH}\` and \`${TS_SCHEMA_PATH}\` do not match. Please run \`yarn backstage-repo-tools schema openapi generate ${path}\` to regenerate \`${TS_SCHEMA_PATH}\`.`, ); } } diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md index 98bf3668d6..798ceb5317 100644 --- a/packages/techdocs-cli-embedded-app/CHANGELOG.md +++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md @@ -1,5 +1,61 @@ # techdocs-cli-embedded-app +## 0.2.83-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs@1.6.3-next.0 + - @backstage/test-utils@1.4.0-next.0 + - @backstage/app-defaults@1.4.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/cli@0.22.8-next.0 + - @backstage/plugin-techdocs-react@1.1.7-next.0 + - @backstage/plugin-catalog@1.11.1-next.0 + - @backstage/config@1.0.7 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/catalog-model@1.3.0 + +## 0.2.82 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-techdocs@1.6.2 + - @backstage/app-defaults@1.3.1 + - @backstage/cli@0.22.7 + - @backstage/plugin-catalog@1.11.0 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/test-utils@1.3.1 + - @backstage/plugin-techdocs-react@1.1.6 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## 0.2.82-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/app-defaults@1.3.1-next.2 + - @backstage/cli@0.22.7-next.0 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/test-utils@1.3.1-next.2 + - @backstage/plugin-catalog@1.11.0-next.2 + - @backstage/plugin-techdocs@1.6.2-next.2 + - @backstage/plugin-techdocs-react@1.1.6-next.1 + - @backstage/config@1.0.7 + - @backstage/core-app-api@1.8.0-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 0.2.82-next.1 ### Patch Changes diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index 01f5f8128c..27da72de5f 100644 --- a/packages/techdocs-cli-embedded-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -1,6 +1,6 @@ { "name": "techdocs-cli-embedded-app", - "version": "0.2.82-next.1", + "version": "0.2.83-next.0", "private": true, "backstage": { "role": "frontend" diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index 35f3b4bc28..49cf10e01a 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,5 +1,27 @@ # @techdocs/cli +## 1.4.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/cli-common@0.1.12 + - @backstage/plugin-techdocs-node@1.7.2-next.0 + +## 1.4.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-techdocs-node@1.7.1 + - @backstage/catalog-model@1.3.0 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.7 + ## 1.4.2-next.1 ### Patch Changes diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index 8b533b4453..5d25f057f6 100644 --- a/packages/techdocs-cli/package.json +++ b/packages/techdocs-cli/package.json @@ -1,7 +1,7 @@ { "name": "@techdocs/cli", "description": "Utility CLI for managing TechDocs sites in Backstage.", - "version": "1.4.2-next.1", + "version": "1.4.3-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index 9fd73a6840..4463f5646c 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,46 @@ # @backstage/test-utils +## 1.4.0-next.0 + +### Minor Changes + +- 1fd38bc4141a: Test App Wrapper is now using `UnifiedThemeProvider` for supporting MUI v5 next to MUI v4 in tests. + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-app-api@1.8.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.5 + +## 1.3.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-app-api@1.8.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-react@0.4.12 + +## 1.3.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-app-api@1.8.0-next.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + ## 1.3.1-next.1 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 80d5a2e620..992075922e 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/test-utils", "description": "Utilities to test Backstage plugins and apps.", - "version": "1.3.1-next.1", + "version": "1.4.0-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/test-utils/src/testUtils/appWrappers.tsx b/packages/test-utils/src/testUtils/appWrappers.tsx index 8b644ad2d1..6545cc312a 100644 --- a/packages/test-utils/src/testUtils/appWrappers.tsx +++ b/packages/test-utils/src/testUtils/appWrappers.tsx @@ -17,9 +17,7 @@ import React, { ComponentType, ReactNode, ReactElement } from 'react'; import { MemoryRouter } from 'react-router-dom'; import { Route } from 'react-router-dom'; -import { lightTheme } from '@backstage/theme'; -import { ThemeProvider } from '@material-ui/core/styles'; -import { CssBaseline } from '@material-ui/core'; +import { UnifiedThemeProvider, themes } from '@backstage/theme'; import MockIcon from '@material-ui/icons/AcUnit'; import { createSpecializedApp } from '@backstage/core-app-api'; import { @@ -142,9 +140,9 @@ export function createTestAppWrapper( title: 'Test App Theme', variant: 'light', Provider: ({ children }) => ( - - {children} - + + {children} + ), }, ], diff --git a/packages/theme/CHANGELOG.md b/packages/theme/CHANGELOG.md index e2490f346e..bb1e52b792 100644 --- a/packages/theme/CHANGELOG.md +++ b/packages/theme/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/theme +## 0.4.0-next.0 + +### Minor Changes + +- 1fd38bc4141a: **MUI v5 Support:** Adding platform-wide support for MUI v5 allowing a transition phase for migrating central plugins & components over. We still support v4 instances & plugins by adding a + + To allow the future support of plugins & components using MUI v5 you want to upgrade your `AppTheme`'s to using the `UnifiedThemeProvider` + + ```diff + Provider: ({ children }) => ( + - + - {children} + - + + + ), + ``` + +## 0.3.0 + +### Minor Changes + +- 98c0c199b15: Updates light theme's primary foreground and `running` status indicator colours to meet WCAG. Previously #2E77D0 changed to #1F5493. + +### Patch Changes + +- 83b45f9df50: Fix accessibility issue with Backstage Table's header style + +## 0.3.0-next.0 + +### Minor Changes + +- 98c0c199b15: Updates light theme's primary foreground and `running` status indicator colours to meet WCAG. Previously #2E77D0 changed to #1F5493. + +### Patch Changes + +- 83b45f9df50: Fix accessibility issue with Backstage Table's header style + ## 0.2.19 ### Patch Changes diff --git a/packages/theme/api-report.md b/packages/theme/api-report.md index 863ab81b68..fe05ca6b4e 100644 --- a/packages/theme/api-report.md +++ b/packages/theme/api-report.md @@ -3,13 +3,19 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import type { ComponentsProps } from '@material-ui/core/styles/props'; import { Overrides } from '@material-ui/core/styles/overrides'; -import { Palette } from '@material-ui/core/styles/createPalette'; -import { PaletteOptions } from '@material-ui/core/styles/createPalette'; -import { Theme } from '@material-ui/core'; -import { ThemeOptions } from '@material-ui/core'; +import type { Palette } from '@material-ui/core/styles/createPalette'; +import type { PaletteOptions } from '@material-ui/core/styles/createPalette'; +import { PaletteOptions as PaletteOptions_2 } from '@mui/material/styles'; +import { ReactNode } from 'react'; +import { Theme } from '@mui/material/styles'; +import { Theme as Theme_2 } from '@material-ui/core'; +import { ThemeOptions } from '@mui/material/styles'; +import { ThemeOptions as ThemeOptions_2 } from '@material-ui/core/styles'; +import type { ThemeOptions as ThemeOptions_3 } from '@material-ui/core'; -// @public +// @public @deprecated export type BackstagePalette = Palette & BackstagePaletteAdditions; // @public @@ -75,12 +81,12 @@ export type BackstagePaletteAdditions = { }; }; -// @public +// @public @deprecated export type BackstagePaletteOptions = PaletteOptions & BackstagePaletteAdditions; -// @public -export interface BackstageTheme extends Theme { +// @public @deprecated +export interface BackstageTheme extends Theme_2 { // (undocumented) getPageTheme: (selector: PageThemeSelector) => PageTheme; // (undocumented) @@ -90,7 +96,13 @@ export interface BackstageTheme extends Theme { } // @public -export interface BackstageThemeOptions extends ThemeOptions { +export type BackstageThemeAdditions = { + page: PageTheme; + getPageTheme: (selector: PageThemeSelector) => PageTheme; +}; + +// @public @deprecated +export interface BackstageThemeOptions extends ThemeOptions_3 { // (undocumented) getPageTheme: (selector: PageThemeSelector) => PageTheme; // (undocumented) @@ -99,22 +111,86 @@ export interface BackstageThemeOptions extends ThemeOptions { palette: BackstagePaletteOptions; } +// @public +export interface BaseThemeOptionsInput { + // (undocumented) + defaultPageTheme?: string; + // (undocumented) + fontFamily?: string; + // (undocumented) + htmlFontSize?: number; + // (undocumented) + pageTheme?: Record; + // (undocumented) + palette: PaletteOptions; +} + // @public export const colorVariants: Record; // @public -export function createTheme(options: SimpleThemeOptions): BackstageTheme; +export function createBaseThemeOptions( + options: BaseThemeOptionsInput, +): { + palette: PaletteOptions; + typography: { + htmlFontSize: number; + fontFamily: string; + h1: { + fontSize: number; + fontWeight: number; + marginBottom: number; + }; + h2: { + fontSize: number; + fontWeight: number; + marginBottom: number; + }; + h3: { + fontSize: number; + fontWeight: number; + marginBottom: number; + }; + h4: { + fontWeight: number; + fontSize: number; + marginBottom: number; + }; + h5: { + fontWeight: number; + fontSize: number; + marginBottom: number; + }; + h6: { + fontWeight: number; + fontSize: number; + marginBottom: number; + }; + }; + page: PageTheme; + getPageTheme: ({ themeId }: PageThemeSelector) => PageTheme; +}; + +// @public @deprecated +export function createTheme(options: SimpleThemeOptions): Theme_2; + +// @public @deprecated +export function createThemeOptions(options: SimpleThemeOptions): ThemeOptions_3; + +// @public @deprecated +export function createThemeOverrides(theme: Theme_2): Overrides; // @public -export function createThemeOptions( - options: SimpleThemeOptions, -): BackstageThemeOptions; +export function createUnifiedTheme(options: UnifiedThemeOptions): UnifiedTheme; // @public -export function createThemeOverrides(theme: BackstageTheme): Overrides; +export function createUnifiedThemeFromV4(options: ThemeOptions_2): UnifiedTheme; + +// @public @deprecated +export const darkTheme: Theme_2; // @public -export const darkTheme: BackstageTheme; +export const defaultComponentThemes: ThemeOptions['components']; // @public export function genPageTheme(props: { @@ -125,8 +201,8 @@ export function genPageTheme(props: { }; }): PageTheme; -// @public -export const lightTheme: BackstageTheme; +// @public @deprecated +export const lightTheme: Theme_2; // @public export type PageTheme = { @@ -145,14 +221,214 @@ export type PageThemeSelector = { }; // @public -export const shapes: Record; +export const palettes: { + light: { + type: 'light'; + mode: 'light'; + background: { + default: string; + paper: string; + }; + status: { + ok: string; + warning: string; + error: string; + running: string; + pending: string; + aborted: string; + }; + bursts: { + fontColor: string; + slackChannelText: string; + backgroundColor: { + default: string; + }; + gradient: { + linear: string; + }; + }; + primary: { + main: string; + }; + banner: { + info: string; + error: string; + text: string; + link: string; + closeButtonColor: string; + warning: string; + }; + border: string; + textContrast: string; + textVerySubtle: string; + textSubtle: string; + highlight: string; + errorBackground: string; + warningBackground: string; + infoBackground: string; + errorText: string; + infoText: string; + warningText: string; + linkHover: string; + link: string; + gold: string; + navigation: { + background: string; + indicator: string; + color: string; + selectedColor: string; + navItem: { + hoverBackground: string; + }; + submenu: { + background: string; + }; + }; + pinSidebarButton: { + icon: string; + background: string; + }; + tabbar: { + indicator: string; + }; + }; + dark: { + type: 'dark'; + mode: 'dark'; + background: { + default: string; + paper: string; + }; + status: { + ok: string; + warning: string; + error: string; + running: string; + pending: string; + aborted: string; + }; + bursts: { + fontColor: string; + slackChannelText: string; + backgroundColor: { + default: string; + }; + gradient: { + linear: string; + }; + }; + primary: { + main: string; + dark: string; + }; + secondary: { + main: string; + }; + banner: { + info: string; + error: string; + text: string; + link: string; + closeButtonColor: string; + warning: string; + }; + border: string; + textContrast: string; + textVerySubtle: string; + textSubtle: string; + highlight: string; + errorBackground: string; + warningBackground: string; + infoBackground: string; + errorText: string; + infoText: string; + warningText: string; + linkHover: string; + link: string; + gold: string; + navigation: { + background: string; + indicator: string; + color: string; + selectedColor: string; + navItem: { + hoverBackground: string; + }; + submenu: { + background: string; + }; + }; + pinSidebarButton: { + icon: string; + background: string; + }; + tabbar: { + indicator: string; + }; + }; +}; // @public +export const shapes: Record; + +// @public @deprecated export type SimpleThemeOptions = { - palette: BackstagePaletteOptions; - defaultPageTheme: string; + palette: PaletteOptions; + defaultPageTheme?: string; pageTheme?: Record; fontFamily?: string; htmlFontSize?: number; }; + +// @public +export const themes: { + light: UnifiedTheme; + dark: UnifiedTheme; +}; + +// @public +export function transformV5ComponentThemesToV4( + theme: Theme, + components?: ThemeOptions['components'], +): { + overrides: Overrides; + props: ComponentsProps; +}; + +// @public +export interface UnifiedTheme { + // (undocumented) + getTheme(version: string): unknown | undefined; +} + +// @public +export interface UnifiedThemeOptions { + // (undocumented) + components?: ThemeOptions['components']; + // (undocumented) + defaultPageTheme?: string; + // (undocumented) + fontFamily?: string; + // (undocumented) + htmlFontSize?: number; + // (undocumented) + pageTheme?: Record; + // (undocumented) + palette: PaletteOptions & PaletteOptions_2; +} + +// @public +export function UnifiedThemeProvider( + props: UnifiedThemeProviderProps, +): JSX.Element; + +// @public +export interface UnifiedThemeProviderProps { + // (undocumented) + children: ReactNode; + // (undocumented) + noCssBaseline?: boolean; + // (undocumented) + theme: UnifiedTheme; +} ``` diff --git a/packages/theme/package.json b/packages/theme/package.json index e102c067d7..dd90f5c834 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/theme", "description": "material-ui theme for use with Backstage.", - "version": "0.2.19", + "version": "0.4.0-next.0", "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -32,9 +32,13 @@ "test": "backstage-cli package test" }, "dependencies": { - "@material-ui/core": "^4.12.2" + "@emotion/react": "^11.10.5", + "@emotion/styled": "^11.10.5", + "@mui/material": "^5.12.2" }, "peerDependencies": { + "@material-ui/core": "^4.12.2", + "@types/react": "^16.13.1 || ^17.0.0", "react": "^16.13.1 || ^17.0.0", "react-dom": "^16.13.1 || ^17.0.0" }, diff --git a/packages/theme/src/base/createBaseThemeOptions.ts b/packages/theme/src/base/createBaseThemeOptions.ts new file mode 100644 index 0000000000..e54e920deb --- /dev/null +++ b/packages/theme/src/base/createBaseThemeOptions.ts @@ -0,0 +1,98 @@ +/* + * Copyright 2022 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 { PageTheme, PageThemeSelector } from './types'; +import { pageTheme as defaultPageThemes } from './pageTheme'; + +const DEFAULT_HTML_FONT_SIZE = 16; +const DEFAULT_FONT_FAMILY = + '"Helvetica Neue", Helvetica, Roboto, Arial, sans-serif'; +const DEFAULT_PAGE_THEME = 'home'; + +/** + * Options for {@link createBaseThemeOptions}. + * + * @public + */ +export interface BaseThemeOptionsInput { + palette: PaletteOptions; + defaultPageTheme?: string; + pageTheme?: Record; + fontFamily?: string; + htmlFontSize?: number; +} + +/** + * A helper for creating theme options. + * + * @public + */ +export function createBaseThemeOptions( + options: BaseThemeOptionsInput, +) { + const { + palette, + htmlFontSize = DEFAULT_HTML_FONT_SIZE, + fontFamily = DEFAULT_FONT_FAMILY, + defaultPageTheme = DEFAULT_PAGE_THEME, + pageTheme = defaultPageThemes, + } = options; + + if (!pageTheme[defaultPageTheme]) { + throw new Error(`${defaultPageTheme} is not defined in pageTheme.`); + } + + return { + palette, + typography: { + htmlFontSize, + fontFamily, + h1: { + fontSize: 54, + fontWeight: 700, + marginBottom: 10, + }, + h2: { + fontSize: 40, + fontWeight: 700, + marginBottom: 8, + }, + h3: { + fontSize: 32, + fontWeight: 700, + marginBottom: 6, + }, + h4: { + fontWeight: 700, + fontSize: 28, + marginBottom: 6, + }, + h5: { + fontWeight: 700, + fontSize: 24, + marginBottom: 4, + }, + h6: { + fontWeight: 700, + fontSize: 20, + marginBottom: 2, + }, + }, + page: pageTheme[defaultPageTheme], + getPageTheme: ({ themeId }: PageThemeSelector) => + pageTheme[themeId] ?? pageTheme[defaultPageTheme], + }; +} diff --git a/packages/theme/src/base/index.ts b/packages/theme/src/base/index.ts new file mode 100644 index 0000000000..4bb80aa42b --- /dev/null +++ b/packages/theme/src/base/index.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2022 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. + */ + +export { createBaseThemeOptions } from './createBaseThemeOptions'; +export type { BaseThemeOptionsInput } from './createBaseThemeOptions'; +export { colorVariants, genPageTheme, pageTheme, shapes } from './pageTheme'; +export { palettes } from './palettes'; +export type { + BackstageThemeAdditions, + BackstagePaletteAdditions, + PageTheme, + PageThemeSelector, +} from './types'; diff --git a/packages/theme/src/pageTheme.ts b/packages/theme/src/base/pageTheme.ts similarity index 99% rename from packages/theme/src/pageTheme.ts rename to packages/theme/src/base/pageTheme.ts index dd36d7641b..12a73b6089 100644 --- a/packages/theme/src/pageTheme.ts +++ b/packages/theme/src/base/pageTheme.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { PageTheme } from './types'; /** diff --git a/packages/theme/src/themes.ts b/packages/theme/src/base/palettes.ts similarity index 86% rename from packages/theme/src/themes.ts rename to packages/theme/src/base/palettes.ts index eb2ef7ce41..5e70afd7b8 100644 --- a/packages/theme/src/themes.ts +++ b/packages/theme/src/base/palettes.ts @@ -14,26 +14,24 @@ * limitations under the License. */ -import { createTheme } from './baseTheme'; -import { pageTheme } from './pageTheme'; -import { yellow } from '@material-ui/core/colors'; - /** - * The default Backstage light theme. + * Built-in Backstage color palettes. * * @public */ -export const lightTheme = createTheme({ - palette: { - type: 'light', +export const palettes = { + light: { + type: 'light' as const, + mode: 'light' as const, background: { default: '#F8F8F8', + paper: '#FFFFFF', }, status: { ok: '#1DB954', warning: '#FF9800', error: '#E22134', - running: '#2E77D0', + running: '#1F5493', pending: '#FFED51', aborted: '#757575', }, @@ -48,7 +46,7 @@ export const lightTheme = createTheme({ }, }, primary: { - main: '#2E77D0', + main: '#1F5493', }, banner: { info: '#2E77D0', @@ -71,7 +69,7 @@ export const lightTheme = createTheme({ warningText: '#000000', linkHover: '#2196F3', link: '#0A6EBE', - gold: yellow.A700, + gold: '#FFD600', navigation: { background: '#171717', indicator: '#9BF0E1', @@ -92,20 +90,12 @@ export const lightTheme = createTheme({ indicator: '#9BF0E1', }, }, - defaultPageTheme: 'home', - pageTheme, -}); - -/** - * The default Backstage dark theme. - * - * @public - */ -export const darkTheme = createTheme({ - palette: { - type: 'dark', + dark: { + type: 'dark' as const, + mode: 'dark' as const, background: { default: '#333333', + paper: '#424242', }, status: { ok: '#71CF88', @@ -153,7 +143,7 @@ export const darkTheme = createTheme({ warningText: '#000000', linkHover: '#82BAFD', link: '#9CC9FF', - gold: yellow.A700, + gold: '#FFD600', navigation: { background: '#424242', indicator: '#9BF0E1', @@ -174,6 +164,4 @@ export const darkTheme = createTheme({ indicator: '#9BF0E1', }, }, - defaultPageTheme: 'home', - pageTheme, -}); +}; diff --git a/packages/theme/src/types.ts b/packages/theme/src/base/types.ts similarity index 63% rename from packages/theme/src/types.ts rename to packages/theme/src/base/types.ts index 0295e491f1..8f71ce4292 100644 --- a/packages/theme/src/types.ts +++ b/packages/theme/src/base/types.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * Copyright 2022 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. @@ -14,12 +14,6 @@ * limitations under the License. */ -import { Theme, ThemeOptions } from '@material-ui/core'; -import { - PaletteOptions, - Palette, -} from '@material-ui/core/styles/createPalette'; - /** * Backstage specific additions to the material-ui palette. * @@ -90,21 +84,6 @@ export type BackstagePaletteAdditions = { }; }; -/** - * The full Backstage palette. - * - * @public - */ -export type BackstagePalette = Palette & BackstagePaletteAdditions; - -/** - * The full Backstage palette options. - * - * @public - */ -export type BackstagePaletteOptions = PaletteOptions & - BackstagePaletteAdditions; - /** * Selector for what page theme to use. * @@ -114,48 +93,6 @@ export type PageThemeSelector = { themeId: string; }; -/** - * A Backstage theme. - * - * @public - */ -export interface BackstageTheme extends Theme { - palette: BackstagePalette; - page: PageTheme; - getPageTheme: (selector: PageThemeSelector) => PageTheme; -} - -/** - * Backstage theme options. - * - * @public - * @remarks - * - * This is essentially a partial theme definition made by the user, that then - * gets merged together with defaults and other values to form the final - * {@link BackstageTheme}. - * - */ -export interface BackstageThemeOptions extends ThemeOptions { - palette: BackstagePaletteOptions; - page: PageTheme; - getPageTheme: (selector: PageThemeSelector) => PageTheme; -} - -/** - * A simpler configuration for creating a new theme that just tweaks some parts - * of the backstage one. - * - * @public - */ -export type SimpleThemeOptions = { - palette: BackstagePaletteOptions; - defaultPageTheme: string; - pageTheme?: Record; - fontFamily?: string; - htmlFontSize?: number; -}; - /** * The theme definitions for a given layout page. * @@ -167,3 +104,13 @@ export type PageTheme = { backgroundImage: string; fontColor: string; }; + +/** + * Backstage specific additions to the material-ui theme. + * + * @public + */ +export type BackstageThemeAdditions = { + page: PageTheme; + getPageTheme: (selector: PageThemeSelector) => PageTheme; +}; diff --git a/packages/theme/src/index.ts b/packages/theme/src/index.ts index 41f827bf43..b0e3590273 100644 --- a/packages/theme/src/index.ts +++ b/packages/theme/src/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * Copyright 2022 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. @@ -20,7 +20,7 @@ * @packageDocumentation */ -export * from './themes'; -export * from './baseTheme'; -export * from './types'; -export * from './pageTheme'; +export * from './unified'; +export * from './base'; +export * from './v4'; +export * from './v5'; diff --git a/packages/theme/src/unified/MuiClassNameSetup.ts b/packages/theme/src/unified/MuiClassNameSetup.ts new file mode 100644 index 0000000000..42b948af32 --- /dev/null +++ b/packages/theme/src/unified/MuiClassNameSetup.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2022 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 { unstable_ClassNameGenerator as ClassNameGenerator } from '@mui/material/className'; + +/** + * This API is introduced in @mui/material (v5.0.5) as a replacement of deprecated createGenerateClassName & only affects v5 MUI components from `@mui/*` + */ +ClassNameGenerator.configure(componentName => { + return `v5-${componentName}`; +}); diff --git a/packages/theme/src/unified/UnifiedTheme.tsx b/packages/theme/src/unified/UnifiedTheme.tsx new file mode 100644 index 0000000000..0c5f80357a --- /dev/null +++ b/packages/theme/src/unified/UnifiedTheme.tsx @@ -0,0 +1,101 @@ +/* + * Copyright 2022 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 { + Theme as Mui4Theme, + ThemeOptions as ThemeOptionsV4, + createTheme, +} from '@material-ui/core/styles'; +import type { PaletteOptions as PaletteOptionsV4 } from '@material-ui/core/styles/createPalette'; +import { PaletteOptions as PaletteOptionsV5 } from '@mui/material/styles'; +import { + adaptV4Theme, + Theme as Mui5Theme, + createTheme as createV5Theme, + ThemeOptions as ThemeOptionsV5, +} from '@mui/material/styles'; +import { transformV5ComponentThemesToV4 } from './overrides'; +import { PageTheme } from '../base/types'; +import { defaultComponentThemes } from '../v5'; +import { createBaseThemeOptions } from '../base/createBaseThemeOptions'; +import { UnifiedTheme } from './types'; + +export class UnifiedThemeHolder implements UnifiedTheme { + #themes = new Map(); + + constructor(v4?: Mui4Theme, v5?: Mui5Theme) { + this.#themes = new Map(); + if (v4) { + this.#themes.set('v4', v4); + } + if (v5) { + this.#themes.set('v5', v5); + } + } + + getTheme(version: string): unknown | undefined { + return this.#themes.get(version); + } +} + +/** + * Options for creating a new {@link UnifiedTheme}. + * + * @public + */ +export interface UnifiedThemeOptions { + palette: PaletteOptionsV4 & PaletteOptionsV5; + defaultPageTheme?: string; + pageTheme?: Record; + fontFamily?: string; + htmlFontSize?: number; + components?: ThemeOptionsV5['components']; +} + +/** + * Creates a new {@link UnifiedTheme} using the provided options. + * + * @public + */ +export function createUnifiedTheme(options: UnifiedThemeOptions): UnifiedTheme { + const themeOptions = createBaseThemeOptions(options); + const components = { ...defaultComponentThemes, ...options.components }; + const v5Theme = createV5Theme({ ...themeOptions, components }); + + // TODO: Not super relevant in the beginning + /* const mui4Styles = maybeLoadMui4Styles(); + if (!mui4Styles) { + return new UnifiedThemeHolder(undefined, v5Theme); + } */ + + const v4Overrides = transformV5ComponentThemesToV4(v5Theme, components); + const v4Theme = { ...createTheme(themeOptions), ...v4Overrides }; + return new UnifiedThemeHolder(v4Theme, v5Theme); +} + +/** + * Creates a new {@link UnifiedTheme} using MUI v4 theme options. + * Note that this uses `adaptV4Theme` from MUI v5, which is deprecated. + * + * @public + */ +export function createUnifiedThemeFromV4( + options: ThemeOptionsV4, +): UnifiedTheme { + const v5Theme = adaptV4Theme(options as any); + const v4Theme = createTheme(options); + return new UnifiedThemeHolder(v4Theme, v5Theme); +} diff --git a/packages/theme/src/unified/UnifiedThemeProvider.tsx b/packages/theme/src/unified/UnifiedThemeProvider.tsx new file mode 100644 index 0000000000..c7054e0e55 --- /dev/null +++ b/packages/theme/src/unified/UnifiedThemeProvider.tsx @@ -0,0 +1,76 @@ +/* + * Copyright 2022 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, { ReactNode } from 'react'; +import './MuiClassNameSetup'; +import { ThemeProvider } from '@material-ui/core/styles'; +import { + StyledEngineProvider, + ThemeProvider as Mui5Provider, +} from '@mui/material/styles'; +import CSSBaseline from '@mui/material/CssBaseline'; +import { UnifiedTheme } from './types'; + +/** + * Props for {@link UnifiedThemeProvider}. + * + * @public + */ +export interface UnifiedThemeProviderProps { + children: ReactNode; + theme: UnifiedTheme; + noCssBaseline?: boolean; +} + +/** + * Provides themes for all MUI versions supported by the provided unified theme. + * + * @public + */ +export function UnifiedThemeProvider( + props: UnifiedThemeProviderProps, +): JSX.Element { + const { children, theme, noCssBaseline = false } = props; + + const v4Theme = theme.getTheme('v4'); + const v5Theme = theme.getTheme('v5'); + + let cssBaseline: JSX.Element | undefined = undefined; + if (!noCssBaseline) { + cssBaseline = ; + } + + let result = ( + <> + {cssBaseline} + {children} + + ); + + if (v4Theme) { + result = {result}; + } + + if (v5Theme) { + result = ( + + {result} + + ); + } + + return result; +} diff --git a/packages/theme/src/unified/index.ts b/packages/theme/src/unified/index.ts new file mode 100644 index 0000000000..f5c805d3ed --- /dev/null +++ b/packages/theme/src/unified/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2022 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. + */ + +export { transformV5ComponentThemesToV4 } from './overrides'; +export { createUnifiedTheme, createUnifiedThemeFromV4 } from './UnifiedTheme'; +export type { UnifiedThemeOptions } from './UnifiedTheme'; +export { themes } from './themes'; +export { UnifiedThemeProvider } from './UnifiedThemeProvider'; +export type { UnifiedThemeProviderProps } from './UnifiedThemeProvider'; +export type { UnifiedTheme } from './types'; diff --git a/packages/theme/src/unified/overrides.test.ts b/packages/theme/src/unified/overrides.test.ts new file mode 100644 index 0000000000..e84cedade6 --- /dev/null +++ b/packages/theme/src/unified/overrides.test.ts @@ -0,0 +1,165 @@ +/* + * Copyright 2022 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 { Theme } from '@mui/material/styles'; +import { transformV5ComponentThemesToV4 } from './overrides'; + +describe('transformV5ComponentThemesToV4', () => { + const mockTheme = { + palette: { + primary: { + main: 'red', + }, + }, + } as unknown as Theme; + it('transforms empty component themes', () => { + expect(transformV5ComponentThemesToV4(mockTheme)).toEqual({ + overrides: {}, + props: {}, + }); + expect(transformV5ComponentThemesToV4(mockTheme, {})).toEqual({ + overrides: {}, + props: {}, + }); + expect( + transformV5ComponentThemesToV4(mockTheme, { + MuiButton: { + styleOverrides: undefined, + defaultProps: undefined, + }, + }), + ).toEqual({ overrides: {}, props: {} }); + expect( + transformV5ComponentThemesToV4(mockTheme, { + MuiButton: { + styleOverrides: {}, + defaultProps: {}, + }, + }), + ).toEqual({ overrides: { MuiButton: {} }, props: { MuiButton: {} } }); + }); + + it('transforms component themes', () => { + expect( + transformV5ComponentThemesToV4(mockTheme, { + MuiButton: { + styleOverrides: { + root: { + color: 'green', + }, + }, + defaultProps: { + disableRipple: true, + }, + }, + }), + ).toEqual({ + overrides: { + MuiButton: { + root: { + color: 'green', + }, + }, + }, + props: { + MuiButton: { + disableRipple: true, + }, + }, + }); + expect( + transformV5ComponentThemesToV4(mockTheme, { + MuiButton: { + styleOverrides: { + root: ({ theme }) => ({ + color: theme.palette.primary.main, + }), + }, + }, + }), + ).toEqual({ + overrides: { + MuiButton: { + root: { + color: 'red', + }, + }, + }, + props: {}, + }); + }); + + it('transforms CSSBaseline theme', () => { + expect( + transformV5ComponentThemesToV4(mockTheme, { + MuiCssBaseline: { + styleOverrides: theme => ({ + html: { + color: theme.palette.primary.main, + }, + }), + defaultProps: { + enableColorScheme: true, + }, + }, + }), + ).toEqual({ + overrides: { + MuiCssBaseline: { + '@global': { + html: { + color: 'red', + }, + }, + }, + }, + props: { + MuiCssBaseline: { + enableColorScheme: true, + }, + }, + }); + }); + + it('transform state styles', () => { + expect( + transformV5ComponentThemesToV4(mockTheme, { + MuiButton: { + styleOverrides: { + root: { + color: 'green', + '&.Mui-disabled': { + color: 'red', + }, + }, + }, + }, + }), + ).toEqual({ + overrides: { + MuiButton: { + root: { + color: 'green', + }, + disabled: { + color: 'red', + }, + }, + }, + props: {}, + }); + }); +}); diff --git a/packages/theme/src/unified/overrides.ts b/packages/theme/src/unified/overrides.ts new file mode 100644 index 0000000000..7417fccedc --- /dev/null +++ b/packages/theme/src/unified/overrides.ts @@ -0,0 +1,142 @@ +/* + * Copyright 2022 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 type { Overrides } from '@material-ui/core/styles/overrides'; +import type { ComponentsProps } from '@material-ui/core/styles/props'; +import { ComponentsOverrides, Theme, ThemeOptions } from '@mui/material/styles'; +import { CSSProperties } from 'react'; + +type V5Override = ComponentsOverrides[Exclude< + keyof ComponentsOverrides, + 'MuiCssBaseline' +>]; +type V4Override = Overrides[keyof Overrides]; +type StaticStyleRules = Record< + string, + CSSProperties | Record +>; + +// Converts callback-based overrides to static styles, e.g. +// { root: theme => ({ color: theme.color }) } -> { root: { color: 'red' } } +function adaptV5CssBaselineOverride( + theme: Theme, + overrides: ComponentsOverrides['MuiCssBaseline'], +): StaticStyleRules | undefined { + if (!overrides || typeof overrides === 'string') { + return undefined; + } + + const styles = typeof overrides === 'function' ? overrides(theme) : overrides; + if (styles) { + return { '@global': styles } as StaticStyleRules; + } + + return undefined; +} + +// Converts callback-based overrides to static styles, e.g. +// { root: theme => ({ color: theme.color }) } -> { root: { color: 'red' } } +function adaptV5Override( + theme: Theme, + overrides: V5Override, +): StaticStyleRules | undefined { + if (!overrides || typeof overrides === 'string') { + return undefined; + } + if (typeof overrides === 'object') { + return Object.fromEntries( + Object.entries(overrides).map(([className, style]) => { + if (typeof style === 'function') { + return [className, style({ theme })]; + } + return [className, style]; + }), + ); + } + return overrides as StaticStyleRules; +} + +const stateStyleKeyPattern = /^&.Mui-([\w-]+)$/; + +// Move state style overrides to the top level, e.g. +// { root: { '&.Mui-active': { color: 'red' } } } -> { active: { color: 'red' } } +function extractV5StateOverrides( + overrides: StaticStyleRules | undefined, +): StaticStyleRules | undefined { + let output = overrides; + if (!overrides || typeof overrides !== 'object') { + return output; + } + for (const className of Object.keys(overrides)) { + const styles = overrides[className]; + if (!styles || typeof styles !== 'object') { + continue; + } + for (const _styleKey of Object.keys(styles)) { + const styleKey = _styleKey as keyof typeof styles; + const match = styleKey.match(stateStyleKeyPattern); + if (match) { + const [, state] = match; + const { [styleKey]: stateStyles, ...restStyles } = styles; + if (stateStyles) { + output = { + ...output, + [className]: restStyles, + [state]: stateStyles, + }; + } + } + } + } + return output; +} + +/** + * Transform MUI v5 component themes into a v4 theme props and overrides. + * + * @public + */ +export function transformV5ComponentThemesToV4( + theme: Theme, + components: ThemeOptions['components'] = {}, +): { overrides: Overrides; props: ComponentsProps } { + const overrides: Record = {}; + const props: Record = {}; + + for (const name of Object.keys(components)) { + const component = components[name as keyof typeof components]; + if (!component) { + continue; + } + if ('styleOverrides' in component) { + if (name === 'MuiCssBaseline') { + overrides[name] = adaptV5CssBaselineOverride( + theme, + component.styleOverrides as ComponentsOverrides['MuiCssBaseline'], + ); + } else { + overrides[name] = extractV5StateOverrides( + adaptV5Override(theme, component.styleOverrides as V5Override), + ); + } + } + if ('defaultProps' in component) { + props[name] = component.defaultProps; + } + } + + return { overrides, props }; +} diff --git a/packages/theme/src/unified/themes.ts b/packages/theme/src/unified/themes.ts new file mode 100644 index 0000000000..24e1b1026b --- /dev/null +++ b/packages/theme/src/unified/themes.ts @@ -0,0 +1,28 @@ +/* + * Copyright 2022 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 { palettes } from '../base'; +import { createUnifiedTheme } from './UnifiedTheme'; + +/** + * Built-in Backstage MUI themes. + * + * @public + */ +export const themes = { + light: createUnifiedTheme({ palette: palettes.light }), + dark: createUnifiedTheme({ palette: palettes.dark }), +}; diff --git a/packages/theme/src/unified/types.ts b/packages/theme/src/unified/types.ts new file mode 100644 index 0000000000..f090a99b83 --- /dev/null +++ b/packages/theme/src/unified/types.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2022 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. + */ + +/** + * A container of one theme for multiple different MUI versions. + * + * Currently known keys are 'v4' and 'v5'. + * + * @public + */ +export interface UnifiedTheme { + getTheme(version: string): unknown | undefined; +} diff --git a/packages/theme/src/v4/baseTheme.ts b/packages/theme/src/v4/baseTheme.ts new file mode 100644 index 0000000000..8143183ec0 --- /dev/null +++ b/packages/theme/src/v4/baseTheme.ts @@ -0,0 +1,76 @@ +/* + * Copyright 2020 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 { Theme as Mui5Theme } from '@mui/material/styles'; +import { createTheme as createMuiTheme } from '@material-ui/core/styles'; +import type { + GridProps, + SwitchProps, + Theme, + ThemeOptions, +} from '@material-ui/core'; +import { Overrides } from '@material-ui/core/styles/overrides'; +import { SimpleThemeOptions } from './types'; +import { createBaseThemeOptions } from '../base'; +import { defaultComponentThemes } from '../v5'; +import { transformV5ComponentThemesToV4 } from '../unified/overrides'; + +/** + * An old helper for creating MUI v4 theme options. + * + * @public + * @deprecated Use {@link createBaseThemeOptions} instead. + */ +export function createThemeOptions(options: SimpleThemeOptions): ThemeOptions { + return { + props: { + MuiGrid: defaultComponentThemes?.MuiGrid + ?.defaultProps as Partial, + MuiSwitch: defaultComponentThemes?.MuiSwitch + ?.defaultProps as Partial, + }, + ...createBaseThemeOptions(options), + }; +} + +/** + * * An old helper for creating MUI v4 theme overrides. + * + * @public + * @deprecated Use {@link defaultComponentThemes} with {@link transformV5ComponentThemesToV4} instead. + */ +export function createThemeOverrides(theme: Theme): Overrides { + return transformV5ComponentThemesToV4( + // Safe but we have to make sure we don't use mui5 specific stuff in the default component themes + theme as unknown as Mui5Theme, + defaultComponentThemes, + ).overrides; +} + +/** + * The old method to create a Backstage MUI v4 theme using a palette. + * The theme is created with the common Backstage options and component styles. + * + * @public + * @deprecated Use {@link createUnifiedTheme} instead. + */ +export function createTheme(options: SimpleThemeOptions): Theme { + const themeOptions = createThemeOptions(options); + const baseTheme = createMuiTheme(themeOptions); + const overrides = createThemeOverrides(baseTheme); + const theme = { ...baseTheme, overrides }; + return theme; +} diff --git a/packages/theme/src/v4/index.ts b/packages/theme/src/v4/index.ts new file mode 100644 index 0000000000..fad349b849 --- /dev/null +++ b/packages/theme/src/v4/index.ts @@ -0,0 +1,29 @@ +/* + * Copyright 2020 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. + */ + +export { darkTheme, lightTheme } from './themes'; +export { + createTheme, + createThemeOptions, + createThemeOverrides, +} from './baseTheme'; +export type { + BackstagePalette, + BackstagePaletteOptions, + BackstageTheme, + BackstageThemeOptions, + SimpleThemeOptions, +} from './types'; diff --git a/packages/theme/src/v4/themes.ts b/packages/theme/src/v4/themes.ts new file mode 100644 index 0000000000..488ee58831 --- /dev/null +++ b/packages/theme/src/v4/themes.ts @@ -0,0 +1,38 @@ +/* + * Copyright 2020 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 { createTheme } from './baseTheme'; +import { palettes } from '../base'; + +/** + * The old MUI v4 Backstage light theme. + * + * @public + * @deprecated Use {@link themes.light} instead. + */ +export const lightTheme = createTheme({ + palette: palettes.light, +}); + +/** + * The old MUI v4 Backstage dark theme. + * + * @public + * @deprecated Use {@link themes.dark} instead. + */ +export const darkTheme = createTheme({ + palette: palettes.dark, +}); diff --git a/packages/theme/src/v4/types.ts b/packages/theme/src/v4/types.ts new file mode 100644 index 0000000000..8bca5b8c3b --- /dev/null +++ b/packages/theme/src/v4/types.ts @@ -0,0 +1,104 @@ +/* + * Copyright 2020 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 type { + Theme as MuiTheme, + ThemeOptions as MuiThemeOptions, +} from '@material-ui/core'; +import type { + PaletteOptions as MuiPaletteOptions, + Palette as MuiPalette, +} from '@material-ui/core/styles/createPalette'; +import { + BackstagePaletteAdditions, + BackstageThemeAdditions, + PageTheme, + PageThemeSelector, +} from '../base/types'; + +/** + * The full Backstage palette. + * + * @public + * @deprecated This type is deprecated, the MUI Palette type is now always extended instead. + */ +export type BackstagePalette = MuiPalette & BackstagePaletteAdditions; + +/** + * The full Backstage palette options. + * + * @public + * @deprecated This type is deprecated, the MUI PaletteOptions type is now always extended instead. + */ +export type BackstagePaletteOptions = MuiPaletteOptions & + BackstagePaletteAdditions; + +/** + * Backstage theme options. + * + * @public + * @deprecated This type is deprecated, the MUI ThemeOptions type is now always extended instead. + * @remarks + * + * This is essentially a partial theme definition made by the user, that then + * gets merged together with defaults and other values to form the final + * {@link BackstageTheme}. + * + */ +export interface BackstageThemeOptions extends MuiThemeOptions { + palette: BackstagePaletteOptions; + page: PageTheme; + getPageTheme: (selector: PageThemeSelector) => PageTheme; +} + +/** + * A Backstage theme. + * + * @public + * @deprecated This type is deprecated, the MUI Theme type is now always extended instead. + */ +export interface BackstageTheme extends MuiTheme { + palette: BackstagePalette; + page: PageTheme; + getPageTheme: (selector: PageThemeSelector) => PageTheme; +} + +/** + * A simpler configuration for creating a new theme that just tweaks some parts + * of the backstage one. + * + * @public + * @deprecated Use {@link BaseThemeOptionsInput} instead. + */ +export type SimpleThemeOptions = { + palette: MuiPaletteOptions; + defaultPageTheme?: string; + pageTheme?: Record; + fontFamily?: string; + htmlFontSize?: number; +}; + +declare module '@material-ui/core/styles/createPalette' { + interface Palette extends BackstagePaletteAdditions {} + + interface PaletteOptions extends BackstagePaletteAdditions {} +} + +declare module '@material-ui/core/styles/createTheme' { + interface Theme extends BackstageThemeAdditions {} + + interface ThemeOptions extends BackstageThemeAdditions {} +} diff --git a/packages/theme/src/baseTheme.ts b/packages/theme/src/v5/defaultComponentThemes.ts similarity index 51% rename from packages/theme/src/baseTheme.ts rename to packages/theme/src/v5/defaultComponentThemes.ts index 53f3a3ef2b..14656b007d 100644 --- a/packages/theme/src/baseTheme.ts +++ b/packages/theme/src/v5/defaultComponentThemes.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * Copyright 2022 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. @@ -14,121 +14,51 @@ * limitations under the License. */ -import { createTheme as createMuiTheme } from '@material-ui/core/styles'; -import { darken, lighten } from '@material-ui/core/styles/colorManipulator'; -import { Overrides } from '@material-ui/core/styles/overrides'; -import { - BackstageTheme, - BackstageThemeOptions, - SimpleThemeOptions, -} from './types'; -import { pageTheme as defaultPageThemes } from './pageTheme'; - -const DEFAULT_HTML_FONT_SIZE = 16; -const DEFAULT_FONT_FAMILY = - '"Helvetica Neue", Helvetica, Roboto, Arial, sans-serif'; - -/** - * A helper for creating theme options. - * - * @public - */ -export function createThemeOptions( - options: SimpleThemeOptions, -): BackstageThemeOptions { - const { - palette, - htmlFontSize = DEFAULT_HTML_FONT_SIZE, - fontFamily = DEFAULT_FONT_FAMILY, - defaultPageTheme, - pageTheme = defaultPageThemes, - } = options; - - if (!pageTheme[defaultPageTheme]) { - throw new Error(`${defaultPageTheme} is not defined in pageTheme.`); - } - - return { - palette, - props: { - MuiGrid: { - spacing: 2, - }, - MuiSwitch: { - color: 'primary', - }, - }, - typography: { - htmlFontSize, - fontFamily, - h6: { - fontWeight: 700, - fontSize: 20, - marginBottom: 2, - }, - h5: { - fontWeight: 700, - fontSize: 24, - marginBottom: 4, - }, - h4: { - fontWeight: 700, - fontSize: 28, - marginBottom: 6, - }, - h3: { - fontSize: 32, - fontWeight: 700, - marginBottom: 6, - }, - h2: { - fontSize: 40, - fontWeight: 700, - marginBottom: 8, - }, - h1: { - fontSize: 54, - fontWeight: 700, - marginBottom: 10, - }, - }, - page: pageTheme[defaultPageTheme], - getPageTheme: ({ themeId }) => - pageTheme[themeId] ?? pageTheme[defaultPageTheme], - }; -} +import { darken, lighten, ThemeOptions } from '@mui/material/styles'; /** * A helper for creating theme overrides. * * @public */ -export function createThemeOverrides(theme: BackstageTheme): Overrides { - return { - MuiCssBaseline: { - '@global': { - html: { - height: '100%', - fontFamily: theme.typography.fontFamily, - }, - body: { - height: '100%', - fontFamily: theme.typography.fontFamily, - 'overscroll-behavior-y': 'none', - }, - a: { - color: 'inherit', - textDecoration: 'none', - }, +export const defaultComponentThemes: ThemeOptions['components'] = { + MuiCssBaseline: { + styleOverrides: theme => ({ + html: { + height: '100%', + fontFamily: theme.typography.fontFamily, }, + body: { + height: '100%', + fontFamily: theme.typography.fontFamily, + overscrollBehaviorY: 'none', + fontSize: '0.875rem', + lineHeight: 1.43, + }, + a: { + color: 'inherit', + textDecoration: 'none', + }, + }), + }, + MuiGrid: { + defaultProps: { + spacing: 2, }, - MuiTableRow: { + }, + MuiSwitch: { + defaultProps: { + color: 'primary', + }, + }, + MuiTableRow: { + styleOverrides: { // Alternating row backgrounds - root: { + root: ({ theme }) => ({ '&:nth-of-type(odd)': { backgroundColor: theme.palette.background.default, }, - }, + }), // Use pointer for hoverable rows hover: { '&:hover': { @@ -136,15 +66,17 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides { }, }, // Alternating head backgrounds - head: { + head: ({ theme }) => ({ '&:nth-of-type(odd)': { backgroundColor: theme.palette.background.paper, }, - }, + }), }, - // Tables are more dense than default mui tables - MuiTableCell: { - root: { + }, + // Tables are more dense than default mui tables + MuiTableCell: { + styleOverrides: { + root: ({ theme }) => ({ wordBreak: 'break-word', overflow: 'hidden', verticalAlign: 'middle', @@ -152,27 +84,31 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides { margin: 0, padding: theme.spacing(3, 2, 3, 2.5), borderBottom: 0, - }, - sizeSmall: { + }), + sizeSmall: ({ theme }) => ({ padding: theme.spacing(1.5, 2, 1.5, 2.5), - }, - head: { + }), + head: ({ theme }) => ({ wordBreak: 'break-word', overflow: 'hidden', color: theme.palette.textSubtle, fontWeight: 'normal', lineHeight: '1', - }, + }), }, - MuiTabs: { + }, + MuiTabs: { + styleOverrides: { // Tabs are smaller than default mui tab rows root: { minHeight: 24, }, }, - MuiTab: { + }, + MuiTab: { + styleOverrides: { // Tabs are smaller and have a hover background - root: { + root: ({ theme }) => ({ color: theme.palette.link, minHeight: 24, textTransform: 'initial', @@ -186,12 +122,14 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides { fontSize: theme.typography.pxToRem(14), fontWeight: 500, }, - }, - textColorPrimary: { + }), + textColorPrimary: ({ theme }) => ({ color: theme.palette.link, - }, + }), }, - MuiTableSortLabel: { + }, + MuiTableSortLabel: { + styleOverrides: { // No color change on hover, just rely on the arrow showing up instead. root: { color: 'inherit', @@ -201,14 +139,16 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides { '&:focus': { color: 'inherit', }, - }, - // Bold font for highlighting selected column - active: { - fontWeight: 'bold', - color: 'inherit', + // Bold font for highlighting selected column + '&.Mui-active': { + fontWeight: 'bold', + color: 'inherit', + }, }, }, - MuiListItemText: { + }, + MuiListItemText: { + styleOverrides: { dense: { // Default dense list items to adding ellipsis for really long str... whiteSpace: 'nowrap', @@ -216,44 +156,50 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides { textOverflow: 'ellipsis', }, }, - MuiButton: { + }, + MuiButton: { + styleOverrides: { text: { // Text buttons have less padding by default, but we want to keep the original padding padding: undefined, }, }, - MuiChip: { - root: { + }, + MuiChip: { + styleOverrides: { + root: ({ theme }) => ({ backgroundColor: '#D9D9D9', // By default there's no margin, but it's usually wanted, so we add some trailing margin marginRight: theme.spacing(1), marginBottom: theme.spacing(1), color: theme.palette.grey[900], - }, - outlined: { + }), + outlined: ({ theme }) => ({ color: theme.palette.text.primary, - }, - label: { - lineHeight: `${theme.spacing(2.5)}px`, + }), + label: ({ theme }) => ({ + lineHeight: theme.spacing(2.5), fontWeight: theme.typography.fontWeightMedium, - fontSize: `${theme.spacing(1.75)}px`, - }, - labelSmall: { - fontSize: `${theme.spacing(1.5)}px`, - }, - deleteIcon: { + fontSize: theme.spacing(1.75), + }), + labelSmall: ({ theme }) => ({ + fontSize: theme.spacing(1.5), + }), + deleteIcon: ({ theme }) => ({ color: theme.palette.grey[500], - width: `${theme.spacing(3)}px`, - height: `${theme.spacing(3)}px`, - margin: `0 ${theme.spacing(0.75)}px 0 -${theme.spacing(0.75)}px`, - }, - deleteIconSmall: { - width: `${theme.spacing(2)}px`, - height: `${theme.spacing(2)}px`, - margin: `0 ${theme.spacing(0.5)}px 0 -${theme.spacing(0.5)}px`, - }, + width: theme.spacing(3), + height: theme.spacing(3), + margin: `0 ${theme.spacing(0.75)} 0 -${theme.spacing(0.75)}`, + }), + deleteIconSmall: ({ theme }) => ({ + width: theme.spacing(2), + height: theme.spacing(2), + margin: `0 ${theme.spacing(0.5)} 0 -${theme.spacing(0.5)}`, + }), }, - MuiCard: { + }, + MuiCard: { + styleOverrides: { root: { // When cards have a forced size, such as when they are arranged in a // CSS grid, the content needs to flex such that the actions (buttons @@ -263,13 +209,17 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides { flexDirection: 'column', }, }, - MuiCardHeader: { + }, + MuiCardHeader: { + styleOverrides: { root: { // Reduce padding between header and content paddingBottom: 0, }, }, - MuiCardContent: { + }, + MuiCardContent: { + styleOverrides: { root: { // When cards have a forced size, such as when they are arranged in a // CSS grid, the content needs to flex such that the actions (buttons @@ -281,25 +231,13 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides { }, }, }, - MuiCardActions: { + }, + MuiCardActions: { + styleOverrides: { root: { // We default to putting the card actions at the end justifyContent: 'flex-end', }, }, - }; -} - -/** - * Creates a Backstage MUI theme using a palette. The theme is created with the - * common Backstage options and component styles. - * - * @public - */ -export function createTheme(options: SimpleThemeOptions): BackstageTheme { - const themeOptions = createThemeOptions(options); - const baseTheme = createMuiTheme(themeOptions) as BackstageTheme; - const overrides = createThemeOverrides(baseTheme); - const theme = { ...baseTheme, overrides }; - return theme; -} + }, +}; diff --git a/packages/theme/src/v5/index.ts b/packages/theme/src/v5/index.ts new file mode 100644 index 0000000000..eee5d852b1 --- /dev/null +++ b/packages/theme/src/v5/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2022 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. + */ + +export * from './types'; +export { defaultComponentThemes } from './defaultComponentThemes'; diff --git a/packages/theme/src/v5/types.ts b/packages/theme/src/v5/types.ts new file mode 100644 index 0000000000..31fe72b5b9 --- /dev/null +++ b/packages/theme/src/v5/types.ts @@ -0,0 +1,37 @@ +/* + * Copyright 2022 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 { Theme } from '@mui/material/styles'; +import { + BackstagePaletteAdditions, + BackstageThemeAdditions, +} from '../base/types'; + +declare module '@mui/material/styles' { + interface Palette extends BackstagePaletteAdditions {} + + interface PaletteOptions extends BackstagePaletteAdditions {} +} + +declare module '@mui/material/styles' { + interface Theme extends BackstageThemeAdditions {} + + interface ThemeOptions extends BackstageThemeAdditions {} +} + +declare module '@mui/private-theming/defaultTheme' { + interface DefaultTheme extends Theme {} +} diff --git a/plugins/adr-backend/CHANGELOG.md b/plugins/adr-backend/CHANGELOG.md index 39e8bf7e4c..e4e23e4b66 100644 --- a/plugins/adr-backend/CHANGELOG.md +++ b/plugins/adr-backend/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-adr-backend +## 0.3.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-adr-common@0.2.9 + - @backstage/plugin-search-common@1.2.3 + +## 0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-adr-common@0.2.9 + - @backstage/plugin-search-common@1.2.3 + ## 0.3.3-next.1 ### Patch Changes diff --git a/plugins/adr-backend/package.json b/plugins/adr-backend/package.json index a1f6a859a0..b693d3e8c2 100644 --- a/plugins/adr-backend/package.json +++ b/plugins/adr-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr-backend", - "version": "0.3.3-next.1", + "version": "0.3.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr-common/CHANGELOG.md b/plugins/adr-common/CHANGELOG.md index c3b8806c80..9fddae2588 100644 --- a/plugins/adr-common/CHANGELOG.md +++ b/plugins/adr-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-adr-common +## 0.2.9 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.4.5 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-search-common@1.2.3 + ## 0.2.9-next.0 ### Patch Changes diff --git a/plugins/adr-common/package.json b/plugins/adr-common/package.json index 0fdf94003a..adbb6bea58 100644 --- a/plugins/adr-common/package.json +++ b/plugins/adr-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-adr-common", "description": "Common functionalities for the adr plugin", - "version": "0.2.9-next.0", + "version": "0.2.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr/CHANGELOG.md b/plugins/adr/CHANGELOG.md index b0ce02fa19..5a16413811 100644 --- a/plugins/adr/CHANGELOG.md +++ b/plugins/adr/CHANGELOG.md @@ -1,5 +1,51 @@ # @backstage/plugin-adr +## 0.6.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/plugin-search-react@1.6.1-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-adr-common@0.2.9 + - @backstage/plugin-search-common@1.2.3 + +## 0.6.0 + +### Minor Changes + +- b12cd5dc221: render SupportButton only if config is set + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/plugin-search-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-adr-common@0.2.9 + - @backstage/plugin-search-common@1.2.3 + +## 0.5.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-search-react@1.6.0-next.2 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.5.1-next.1 ### Patch Changes diff --git a/plugins/adr/package.json b/plugins/adr/package.json index 3202a8c14e..41653dc1dc 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr", - "version": "0.5.1-next.1", + "version": "0.6.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx b/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx index d136de4717..da575d884f 100644 --- a/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx +++ b/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx @@ -29,7 +29,7 @@ import { SupportButton, WarningPanel, } from '@backstage/core-components'; -import { useApi, useRouteRef } from '@backstage/core-plugin-api'; +import { configApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api'; import { scmIntegrationsApiRef } from '@backstage/integration-react'; import { AdrFilePathFilterFn, @@ -170,6 +170,9 @@ export const EntityAdrContent = (props: { const adrApi = useApi(adrApiRef); const entityHasAdrs = isAdrAvailable(entity); + const config = useApi(configApiRef); + const appSupportConfigured = config?.getOptionalConfig('app.support'); + const { value, loading, error } = useAsync(async () => { const url = getAdrLocationUrl(entity, scmIntegrations); return adrApi.listAdrs(url); @@ -212,7 +215,7 @@ export const EntityAdrContent = (props: { return ( - + {appSupportConfigured && } {!entityHasAdrs && ( diff --git a/plugins/airbrake-backend/CHANGELOG.md b/plugins/airbrake-backend/CHANGELOG.md index 8407f5822e..99bc787d74 100644 --- a/plugins/airbrake-backend/CHANGELOG.md +++ b/plugins/airbrake-backend/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-airbrake-backend +## 0.2.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + +## 0.2.18 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config@1.0.7 + ## 0.2.18-next.1 ### Patch Changes diff --git a/plugins/airbrake-backend/package.json b/plugins/airbrake-backend/package.json index c57ffa8be9..6754446993 100644 --- a/plugins/airbrake-backend/package.json +++ b/plugins/airbrake-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake-backend", - "version": "0.2.18-next.1", + "version": "0.2.19-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/airbrake/CHANGELOG.md b/plugins/airbrake/CHANGELOG.md index 191207e591..dbc923f75c 100644 --- a/plugins/airbrake/CHANGELOG.md +++ b/plugins/airbrake/CHANGELOG.md @@ -1,5 +1,43 @@ # @backstage/plugin-airbrake +## 0.3.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/test-utils@1.4.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/dev-utils@1.0.16-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.3.18 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/dev-utils@1.0.15 + - @backstage/test-utils@1.3.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.3.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/dev-utils@1.0.15-next.2 + - @backstage/test-utils@1.3.1-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.3.18-next.1 ### Patch Changes diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index 6f7f404742..f7034ced40 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake", - "version": "0.3.18-next.1", + "version": "0.3.19-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/allure/CHANGELOG.md b/plugins/allure/CHANGELOG.md index a20bd80961..f7462e5bc3 100644 --- a/plugins/allure/CHANGELOG.md +++ b/plugins/allure/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-allure +## 0.1.35-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.1.34 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.1.34-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.34-next.1 ### Patch Changes diff --git a/plugins/allure/package.json b/plugins/allure/package.json index 2a98ae1faf..af095a2901 100644 --- a/plugins/allure/package.json +++ b/plugins/allure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-allure", "description": "A Backstage plugin that integrates with Allure", - "version": "0.1.34-next.1", + "version": "0.1.35-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/analytics-module-ga/CHANGELOG.md b/plugins/analytics-module-ga/CHANGELOG.md index 4195e02248..7ead93c55e 100644 --- a/plugins/analytics-module-ga/CHANGELOG.md +++ b/plugins/analytics-module-ga/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-analytics-module-ga +## 0.1.30-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.1.29 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## 0.1.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.29-next.0 ### Patch Changes diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index 31215bd84f..5851edf627 100644 --- a/plugins/analytics-module-ga/package.json +++ b/plugins/analytics-module-ga/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-ga", - "version": "0.1.29-next.0", + "version": "0.1.30-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/analytics-module-ga4/CHANGELOG.md b/plugins/analytics-module-ga4/CHANGELOG.md index 59c03fec0f..dd9d87b2c4 100644 --- a/plugins/analytics-module-ga4/CHANGELOG.md +++ b/plugins/analytics-module-ga4/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-analytics-module-ga4 +## 0.1.1-next.0 + +### Patch Changes + +- 3d11596a72b5: Update plugin installation docs to be more consistent across documentations +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.1.0 + +### Minor Changes + +- 22b46f7f562: Plugin provides Backstage Analytics API for Google Analytics 4. Once installed and configured, analytics events will be sent to GA4 as your users navigate and use your Backstage instance + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## 0.1.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.0-next.1 ### Patch Changes diff --git a/plugins/analytics-module-ga4/README.md b/plugins/analytics-module-ga4/README.md index d060c9d9b1..97bb751ca8 100644 --- a/plugins/analytics-module-ga4/README.md +++ b/plugins/analytics-module-ga4/README.md @@ -9,7 +9,12 @@ This plugin contains no other functionality. ## Installation 1. Install the plugin package in your Backstage app: - `cd packages/app && yarn add @backstage/plugin-analytics-module-ga4` + +```sh +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-analytics-module-ga4 +``` + 2. Wire up the API implementation to your App: ```tsx diff --git a/plugins/analytics-module-ga4/package.json b/plugins/analytics-module-ga4/package.json index 5e27228534..80dd77e11b 100644 --- a/plugins/analytics-module-ga4/package.json +++ b/plugins/analytics-module-ga4/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-ga4", - "version": "0.1.0-next.1", + "version": "0.1.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/apache-airflow/CHANGELOG.md b/plugins/apache-airflow/CHANGELOG.md index 368995a369..410286ecf1 100644 --- a/plugins/apache-airflow/CHANGELOG.md +++ b/plugins/apache-airflow/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-apache-airflow +## 0.2.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.2.11 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + +## 0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 0.2.11-next.0 ### Patch Changes diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index 6d503e972a..569f256318 100644 --- a/plugins/apache-airflow/package.json +++ b/plugins/apache-airflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apache-airflow", - "version": "0.2.11-next.0", + "version": "0.2.12-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index 635b1e2dca..afad944485 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-api-docs +## 0.9.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/plugin-catalog@1.11.1-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.9.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/plugin-catalog@1.11.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.9.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog@1.11.0-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.9.3-next.1 ### Patch Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 89e65dfcc3..be31cea662 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-api-docs", "description": "A Backstage plugin that helps represent API entities in the frontend", - "version": "0.9.3-next.1", + "version": "0.9.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/apollo-explorer/CHANGELOG.md b/plugins/apollo-explorer/CHANGELOG.md index 174a862d61..15e38c890f 100644 --- a/plugins/apollo-explorer/CHANGELOG.md +++ b/plugins/apollo-explorer/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-apollo-explorer +## 0.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.1.11 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + +## 0.1.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.11-next.0 ### Patch Changes diff --git a/plugins/apollo-explorer/README.md b/plugins/apollo-explorer/README.md index 98f3116966..23ea71e934 100644 --- a/plugins/apollo-explorer/README.md +++ b/plugins/apollo-explorer/README.md @@ -38,17 +38,22 @@ yarn --cwd packages/app add @backstage/plugin-apollo-explorer Then, in `packages/app/src/App.tsx` add the plugin as a `Route` ```typescript - + {/* other routes... */} + + } /> - } -/> ``` Then, in `packages/app/src/components/Root/Root.tsx` add a sidebar item so users can find your beautiful plugin! diff --git a/plugins/apollo-explorer/package.json b/plugins/apollo-explorer/package.json index c1164cf1d6..59325f4dc4 100644 --- a/plugins/apollo-explorer/package.json +++ b/plugins/apollo-explorer/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apollo-explorer", - "version": "0.1.11-next.0", + "version": "0.1.12-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index 1e98f25c64..ef2230a370 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-app-backend +## 0.3.46-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.3.1-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/types@1.0.2 + +## 0.3.45 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config-loader@1.3.0 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/types@1.0.2 + ## 0.3.45-next.1 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index 85602a06e4..3f983e66e0 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-app-backend", "description": "A Backstage backend plugin that serves the Backstage frontend app", - "version": "0.3.45-next.1", + "version": "0.3.46-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index c6ff454a7d..93b2d31e56 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-auth-backend +## 0.18.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.15-next.0 + +## 0.18.3 + +### Patch Changes + +- 7c116bcac7f: Fixed the way that some request errors are thrown +- 473db605a4f: Fix config schema definition. +- 3ffcdac7d07: Added a persistent session store through the database +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## 0.18.3-next.2 + +### Patch Changes + +- 3ffcdac7d07: Added a persistent session store through the database +- Updated dependencies + - @backstage/config@1.0.7 + ## 0.18.3-next.1 ### Patch Changes diff --git a/plugins/auth-backend/config.d.ts b/plugins/auth-backend/config.d.ts index 8d76ca8bf5..c6579e08f8 100644 --- a/plugins/auth-backend/config.d.ts +++ b/plugins/auth-backend/config.d.ts @@ -59,6 +59,7 @@ export interface Config { /** * The available auth-provider options and attributes + * @additionalProperties true */ providers?: { google?: { diff --git a/plugins/auth-backend/migrations/20230428155633_sessions.js b/plugins/auth-backend/migrations/20230428155633_sessions.js new file mode 100644 index 0000000000..49462ac503 --- /dev/null +++ b/plugins/auth-backend/migrations/20230428155633_sessions.js @@ -0,0 +1,52 @@ +/* + * Copyright 2023 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + // See https://github.com/gx0r/connect-session-knex + // Modeled loosely after https://github.com/gx0r/connect-session-knex/blob/4e0e36a9afbb13c3000a89f5e341f2d2d4339a02/lib/index.js#L114 + // For simplicity we always make the session a string + // Do NOT change around this table or column names; the connect-session-knex library makes assumptions about them + await knex.schema.createTable('sessions', table => { + table.comment('Session data'); + table.string('sid').primary().notNullable().comment('ID of the session'); + table + .text('sess', 'longtext') + .notNullable() + .comment('Session data, JSON serialized'); + table + .timestamp('expired') + .notNullable() + .comment('The point in time when the session expires'); + table.index('sid', 'sessions_sid_idx'); + table.index('expired', 'sessions_expired_idx'); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.alterTable('sessions', table => { + table.dropIndex([], 'sessions_sid_idx'); + table.dropIndex([], 'sessions_expired_idx'); + }); + await knex.schema.dropTable('sessions'); +}; diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 61c3fe9a8d..3425a17831 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend", "description": "A Backstage backend plugin that handles authentication", - "version": "0.18.3-next.1", + "version": "0.18.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -44,6 +44,7 @@ "@types/express": "^4.17.6", "@types/passport": "^1.0.3", "compression": "^1.7.4", + "connect-session-knex": "^3.0.1", "cookie-parser": "^1.4.5", "cors": "^2.8.5", "express": "^4.17.1", diff --git a/plugins/auth-backend/src/database/AuthDatabase.ts b/plugins/auth-backend/src/database/AuthDatabase.ts new file mode 100644 index 0000000000..97e4236754 --- /dev/null +++ b/plugins/auth-backend/src/database/AuthDatabase.ts @@ -0,0 +1,77 @@ +/* + * Copyright 2023 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 { + DatabaseManager, + PluginDatabaseManager, + resolvePackagePath, +} from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { Knex } from 'knex'; + +const migrationsDir = resolvePackagePath( + '@backstage/plugin-auth-backend', + 'migrations', +); + +/** + * Ensures that a database connection is established exactly once and only when + * asked for, and runs migrations. + */ +export class AuthDatabase { + readonly #database: PluginDatabaseManager; + #promise: Promise | undefined; + + static create(database: PluginDatabaseManager): AuthDatabase { + return new AuthDatabase(database); + } + + /** @internal */ + static forTesting(): AuthDatabase { + const config = new ConfigReader({ + backend: { + database: { + client: 'better-sqlite3', + connection: ':memory:', + useNullAsDefault: true, + }, + }, + }); + const database = DatabaseManager.fromConfig(config).forPlugin('auth'); + return new AuthDatabase(database); + } + + static async runMigrations(knex: Knex): Promise { + await knex.migrate.latest({ + directory: migrationsDir, + }); + } + + private constructor(database: PluginDatabaseManager) { + this.#database = database; + } + + get(): Promise { + this.#promise ??= this.#database.getClient().then(async client => { + if (!this.#database.migrations?.skip) { + await AuthDatabase.runMigrations(client); + } + return client; + }); + + return this.#promise; + } +} diff --git a/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts b/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts index da67a2f88f..cf415c7e13 100644 --- a/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts +++ b/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts @@ -14,33 +14,10 @@ * limitations under the License. */ -import Knex, { Knex as KnexType } from 'knex'; -import { DatabaseKeyStore } from './DatabaseKeyStore'; import { DateTime } from 'luxon'; - -function createDatabaseManager( - client: KnexType, - skipMigrations: boolean = false, -) { - return { - getClient: async () => client, - migrations: { - skip: skipMigrations, - }, - }; -} - -function createDB() { - const knex = Knex({ - client: 'better-sqlite3', - connection: ':memory:', - useNullAsDefault: true, - }); - knex.client.pool.on('createSuccess', (_eventId: any, resource: any) => { - resource.run('PRAGMA foreign_keys = ON', () => {}); - }); - return knex; -} +import { AuthDatabase } from '../database/AuthDatabase'; +import { DatabaseKeyStore } from './DatabaseKeyStore'; +import { TestDatabases } from '@backstage/backend-test-utils'; const keyBase = { use: 'sig', @@ -48,95 +25,107 @@ const keyBase = { alg: 'Base64', } as const; +jest.setTimeout(60_000); + describe('DatabaseKeyStore', () => { - it('should store a key', async () => { - const client = createDB(); - const store = await DatabaseKeyStore.create({ - database: createDatabaseManager(client), - }); - - const key = { - kid: '123', - ...keyBase, - }; - - await expect(store.listKeys()).resolves.toEqual({ items: [] }); - await store.addKey(key); - - const { items } = await store.listKeys(); - expect(items).toEqual([{ createdAt: expect.anything(), key }]); - expect( - Math.abs( - DateTime.fromJSDate(items[0].createdAt).diffNow('seconds').seconds, - ), - ).toBeLessThan(10); + const databases = TestDatabases.create({ + ids: ['MYSQL_8', 'POSTGRES_13', 'POSTGRES_9', 'SQLITE_3'], }); - it('should remove stored keys', async () => { - const client = createDB(); - const store = await DatabaseKeyStore.create({ - database: createDatabaseManager(client), - }); + it.each(databases.eachSupportedId())( + 'should store a key, %p', + async databaseId => { + const knex = await databases.init(databaseId); + await AuthDatabase.runMigrations(knex); - const key1 = { kid: '1', ...keyBase }; - const key2 = { kid: '2', ...keyBase }; - const key3 = { kid: '3', ...keyBase }; + const store = new DatabaseKeyStore(knex); - await store.addKey(key1); - await store.addKey(key2); - await store.addKey(key3); + const key = { + kid: '123', + ...keyBase, + }; - await expect(store.listKeys()).resolves.toEqual({ - items: [ - { key: key1, createdAt: expect.anything() }, - { key: key2, createdAt: expect.anything() }, - { key: key3, createdAt: expect.anything() }, - ], - }); + await expect(store.listKeys()).resolves.toEqual({ items: [] }); + await store.addKey(key); - store.removeKeys(['1']); + const { items } = await store.listKeys(); + expect(items).toEqual([{ createdAt: expect.anything(), key }]); + expect( + Math.abs( + DateTime.fromJSDate(items[0].createdAt).diffNow('seconds').seconds, + ), + ).toBeLessThan(10); + }, + ); - await expect(store.listKeys()).resolves.toEqual({ - items: [ - { key: key2, createdAt: expect.anything() }, - { key: key3, createdAt: expect.anything() }, - ], - }); + it.each(databases.eachSupportedId())( + 'should remove stored keys, %p', + async databaseId => { + const knex = await databases.init(databaseId); + await AuthDatabase.runMigrations(knex); - store.removeKeys(['1', '2']); + const store = new DatabaseKeyStore(knex); - await expect(store.listKeys()).resolves.toEqual({ - items: [{ key: key3, createdAt: expect.anything() }], - }); + const key1 = { kid: '1', ...keyBase }; + const key2 = { kid: '2', ...keyBase }; + const key3 = { kid: '3', ...keyBase }; - store.removeKeys([]); + await store.addKey(key1); + await store.addKey(key2); + await store.addKey(key3); - await expect(store.listKeys()).resolves.toEqual({ - items: [{ key: key3, createdAt: expect.anything() }], - }); + await expect(store.listKeys()).resolves.toEqual({ + items: [ + { key: key1, createdAt: expect.anything() }, + { key: key2, createdAt: expect.anything() }, + { key: key3, createdAt: expect.anything() }, + ], + }); - store.removeKeys(['3', '4']); + await store.removeKeys(['1']); - await expect(store.listKeys()).resolves.toEqual({ - items: [], - }); + await expect(store.listKeys()).resolves.toEqual({ + items: [ + { key: key2, createdAt: expect.anything() }, + { key: key3, createdAt: expect.anything() }, + ], + }); - await store.addKey(key1); - await store.addKey(key2); - await store.addKey(key3); + await store.removeKeys(['1', '2']); - await expect(store.listKeys()).resolves.toEqual({ - items: [ - { key: key1, createdAt: expect.anything() }, - { key: key2, createdAt: expect.anything() }, - { key: key3, createdAt: expect.anything() }, - ], - }); + await expect(store.listKeys()).resolves.toEqual({ + items: [{ key: key3, createdAt: expect.anything() }], + }); - store.removeKeys(['1', '2', '3']); + await store.removeKeys([]); - await expect(store.listKeys()).resolves.toEqual({ - items: [], - }); - }); + await expect(store.listKeys()).resolves.toEqual({ + items: [{ key: key3, createdAt: expect.anything() }], + }); + + await store.removeKeys(['3', '4']); + + await expect(store.listKeys()).resolves.toEqual({ + items: [], + }); + + await store.addKey(key1); + await store.addKey(key2); + await store.addKey(key3); + + await expect(store.listKeys()).resolves.toEqual({ + items: [ + { key: key1, createdAt: expect.anything() }, + { key: key2, createdAt: expect.anything() }, + { key: key3, createdAt: expect.anything() }, + ], + }); + + await store.removeKeys(['1', '2', '3']); + + await expect(store.listKeys()).resolves.toEqual({ + items: [], + }); + }, + ); }); diff --git a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts index 8039837469..0559b698e9 100644 --- a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts +++ b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts @@ -14,19 +14,10 @@ * limitations under the License. */ -import { - PluginDatabaseManager, - resolvePackagePath, -} from '@backstage/backend-common'; import { Knex } from 'knex'; import { DateTime } from 'luxon'; import { AnyJWK, KeyStore, StoredKey } from './types'; -const migrationsDir = resolvePackagePath( - '@backstage/plugin-auth-backend', - 'migrations', -); - const TABLE = 'signing_keys'; type Row = { @@ -35,10 +26,6 @@ type Row = { key: string; }; -type Options = { - database: PluginDatabaseManager; -}; - const parseDate = (date: string | Date) => { const parsedDate = typeof date === 'string' @@ -55,24 +42,7 @@ const parseDate = (date: string | Date) => { }; export class DatabaseKeyStore implements KeyStore { - static async create(options: Options): Promise { - const { database } = options; - const client = await database.getClient(); - - if (!database.migrations?.skip) { - await client.migrate.latest({ - directory: migrationsDir, - }); - } - - return new DatabaseKeyStore(client); - } - - private readonly client: Knex; - - private constructor(client: Knex) { - this.client = client; - } + constructor(private readonly client: Knex) {} async addKey(key: AnyJWK): Promise { await this.client(TABLE).insert({ diff --git a/plugins/auth-backend/src/identity/KeyStores.test.ts b/plugins/auth-backend/src/identity/KeyStores.test.ts index 375db4698b..6c034eb64b 100644 --- a/plugins/auth-backend/src/identity/KeyStores.test.ts +++ b/plugins/auth-backend/src/identity/KeyStores.test.ts @@ -14,13 +14,13 @@ * limitations under the License. */ -import { DatabaseManager } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; - -import { MemoryKeyStore } from './MemoryKeyStore'; +import { AuthDatabase } from '../database/AuthDatabase'; import { DatabaseKeyStore } from './DatabaseKeyStore'; import { FirestoreKeyStore } from './FirestoreKeyStore'; import { KeyStores } from './KeyStores'; +import { MemoryKeyStore } from './MemoryKeyStore'; +import { getVoidLogger } from '@backstage/backend-common'; describe('KeyStores', () => { const defaultConfigOptions = { @@ -34,7 +34,10 @@ describe('KeyStores', () => { it('reads auth section from config', async () => { const configSpy = jest.spyOn(defaultConfig, 'getOptionalConfig'); - const keyStore = await KeyStores.fromConfig(defaultConfig); + const keyStore = await KeyStores.fromConfig(defaultConfig, { + logger: getVoidLogger(), + database: AuthDatabase.forTesting(), + }); expect(keyStore).toBeInstanceOf(MemoryKeyStore); expect(configSpy).toHaveBeenCalledWith('auth.keyStore'); @@ -46,18 +49,10 @@ describe('KeyStores', () => { }); it('can handle without auth config', async () => { - const config = new ConfigReader({ - backend: { - database: { - client: 'better-sqlite3', - connection: ':memory:', - }, - }, + const keyStore = await KeyStores.fromConfig(new ConfigReader({}), { + logger: getVoidLogger(), + database: AuthDatabase.forTesting(), }); - const database = - DatabaseManager.fromConfig(config).forPlugin('auth-backend'); - const keyStore = await KeyStores.fromConfig(config, { database }); - expect(keyStore).toBeInstanceOf(DatabaseKeyStore); }); @@ -82,7 +77,10 @@ describe('KeyStores', () => { }, }; const config = new ConfigReader(configOptions); - const keyStore = await KeyStores.fromConfig(config); + const keyStore = await KeyStores.fromConfig(config, { + logger: getVoidLogger(), + database: AuthDatabase.forTesting(), + }); expect(keyStore).toBeInstanceOf(FirestoreKeyStore); expect(createSpy).toHaveBeenCalledWith( diff --git a/plugins/auth-backend/src/identity/KeyStores.ts b/plugins/auth-backend/src/identity/KeyStores.ts index e29b4b6fc4..4cd8f91842 100644 --- a/plugins/auth-backend/src/identity/KeyStores.ts +++ b/plugins/auth-backend/src/identity/KeyStores.ts @@ -14,20 +14,20 @@ * limitations under the License. */ -import { Logger } from 'winston'; import { pickBy } from 'lodash'; +import { Logger } from 'winston'; -import { PluginDatabaseManager } from '@backstage/backend-common'; import { Config } from '@backstage/config'; +import { AuthDatabase } from '../database/AuthDatabase'; import { DatabaseKeyStore } from './DatabaseKeyStore'; -import { MemoryKeyStore } from './MemoryKeyStore'; import { FirestoreKeyStore } from './FirestoreKeyStore'; +import { MemoryKeyStore } from './MemoryKeyStore'; import { KeyStore } from './types'; type Options = { - logger?: Logger; - database?: PluginDatabaseManager; + logger: Logger; + database: AuthDatabase; }; export class KeyStores { @@ -37,23 +37,16 @@ export class KeyStores { * * @returns a KeyStore store */ - static async fromConfig( - config: Config, - options?: Options, - ): Promise { - const { logger, database } = options ?? {}; + static async fromConfig(config: Config, options: Options): Promise { + const { logger, database } = options; const ks = config.getOptionalConfig('auth.keyStore'); const provider = ks?.getOptionalString('provider') ?? 'database'; - logger?.info(`Configuring "${provider}" as KeyStore provider`); + logger.info(`Configuring "${provider}" as KeyStore provider`); if (provider === 'database') { - if (!database) { - throw new Error('This KeyStore provider requires a database'); - } - - return await DatabaseKeyStore.create({ database }); + return new DatabaseKeyStore(await database.get()); } if (provider === 'memory') { diff --git a/plugins/auth-backend/src/migrations.test.ts b/plugins/auth-backend/src/migrations.test.ts new file mode 100644 index 0000000000..194bbbf44c --- /dev/null +++ b/plugins/auth-backend/src/migrations.test.ts @@ -0,0 +1,76 @@ +/* + * Copyright 2022 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 { Knex } from 'knex'; +import { TestDatabases } from '@backstage/backend-test-utils'; +import fs from 'fs'; + +const migrationsDir = `${__dirname}/../migrations`; +const migrationsFiles = fs.readdirSync(migrationsDir).sort(); + +async function migrateUpOnce(knex: Knex): Promise { + await knex.migrate.up({ directory: migrationsDir }); +} + +async function migrateDownOnce(knex: Knex): Promise { + await knex.migrate.down({ directory: migrationsDir }); +} + +async function migrateUntilBefore(knex: Knex, target: string): Promise { + const index = migrationsFiles.indexOf(target); + if (index === -1) { + throw new Error(`Migration ${target} not found`); + } + for (let i = 0; i < index; i++) { + await migrateUpOnce(knex); + } +} + +jest.setTimeout(60_000); + +describe('migrations', () => { + const databases = TestDatabases.create({ + ids: ['MYSQL_8', 'POSTGRES_13', 'POSTGRES_9', 'SQLITE_3'], + }); + + it.each(databases.eachSupportedId())( + '20230428155633_sessions.js, %p', + async databaseId => { + const knex = await databases.init(databaseId); + + await migrateUntilBefore(knex, '20230428155633_sessions.js'); + await migrateUpOnce(knex); + + // Ensure that large cookies are supported + const data = `{"cookie":"${'a'.repeat(100_000)}"}`; + await knex + .insert({ sid: 'abc', expired: knex.fn.now(), sess: data }) + .into('sessions'); + await knex + .insert({ sid: 'def', expired: knex.fn.now(), sess: data }) + .into('sessions'); + + await expect(knex('sessions').orderBy('sid', 'asc')).resolves.toEqual([ + { sid: 'abc', expired: expect.anything(), sess: data }, + { sid: 'def', expired: expect.anything(), sess: data }, + ]); + + await migrateDownOnce(knex); + + await knex.destroy(); + }, + ); +}); diff --git a/plugins/auth-backend/src/providers/cloudflare-access/provider.ts b/plugins/auth-backend/src/providers/cloudflare-access/provider.ts index 0d8f736550..6313276508 100644 --- a/plugins/auth-backend/src/providers/cloudflare-access/provider.ts +++ b/plugins/auth-backend/src/providers/cloudflare-access/provider.ts @@ -227,7 +227,7 @@ export class CloudflareAccessAuthProvider implements AuthProviderRouteHandlers { { headers }, ); if (!res.ok) { - throw ResponseError.fromResponse(res); + throw await ResponseError.fromResponse(res); } const cfIdentity = await res.json(); return cfIdentity as unknown as CloudflareAccessIdentityProfile; diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts index 8013777415..2996ff68be 100644 --- a/plugins/auth-backend/src/service/router.ts +++ b/plugins/auth-backend/src/service/router.ts @@ -32,9 +32,11 @@ import { CatalogApi, CatalogClient } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; import { createOidcRouter, TokenFactory, KeyStores } from '../identity'; import session from 'express-session'; +import connectSessionKnex from 'connect-session-knex'; import passport from 'passport'; import { Minimatch } from 'minimatch'; import { CatalogAuthResolverContext } from '../lib/resolvers'; +import { AuthDatabase } from '../database/AuthDatabase'; /** @public */ export type ProviderFactories = { [s: string]: AuthProviderFactory }; @@ -70,7 +72,11 @@ export async function createRouter( const appUrl = config.getString('app.baseUrl'); const authUrl = await discovery.getExternalBaseUrl('auth'); - const keyStore = await KeyStores.fromConfig(config, { logger, database }); + const authDb = AuthDatabase.create(database); + const keyStore = await KeyStores.fromConfig(config, { + logger, + database: authDb, + }); const keyDurationSeconds = 3600; const tokenIssuer = new TokenFactory({ @@ -84,14 +90,18 @@ export async function createRouter( const secret = config.getOptionalString('auth.session.secret'); if (secret) { router.use(cookieParser(secret)); - // TODO: Configure the server-side session storage. The default MemoryStore is not designed for production const enforceCookieSSL = authUrl.startsWith('https'); + const KnexSessionStore = connectSessionKnex(session); router.use( session({ secret, saveUninitialized: false, resave: false, cookie: { secure: enforceCookieSSL ? 'auto' : false }, + store: new KnexSessionStore({ + createtable: false, + knex: await authDb.get(), + }), }), ); router.use(passport.initialize()); diff --git a/plugins/auth-node/CHANGELOG.md b/plugins/auth-node/CHANGELOG.md index 7cb9f4cc64..3dacefa8d0 100644 --- a/plugins/auth-node/CHANGELOG.md +++ b/plugins/auth-node/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-auth-node +## 0.2.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## 0.2.14 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + ## 0.2.14-next.1 ### Patch Changes diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index 1d8e71a4c0..155c107525 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-node", - "version": "0.2.14-next.1", + "version": "0.2.15-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops-backend/CHANGELOG.md b/plugins/azure-devops-backend/CHANGELOG.md index 3dd206ae66..cf6e17985c 100644 --- a/plugins/azure-devops-backend/CHANGELOG.md +++ b/plugins/azure-devops-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-azure-devops-backend +## 0.3.25-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/plugin-azure-devops-common@0.3.0 + +## 0.3.24 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config@1.0.7 + - @backstage/plugin-azure-devops-common@0.3.0 + ## 0.3.24-next.1 ### Patch Changes diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index f28bfa5cb4..af4e285bc7 100644 --- a/plugins/azure-devops-backend/package.json +++ b/plugins/azure-devops-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops-backend", - "version": "0.3.24-next.1", + "version": "0.3.25-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops/CHANGELOG.md b/plugins/azure-devops/CHANGELOG.md index a0328bcb22..7bbf34f381 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,49 @@ # @backstage/plugin-azure-devops +## 0.3.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-azure-devops-common@0.3.0 + +## 0.3.0 + +### Minor Changes + +- 877df261085: The getBuildRuns function now checks contains multiple comma-separated builds and splits them to send multiple requests for each and concatenates the results. + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/plugin-azure-devops-common@0.3.0 + +## 0.3.0-next.2 + +### Minor Changes + +- 877df261085: The getBuildRuns function now checks contains multiple comma-separated builds and splits them to send multiple requests for each and concatenates the results. + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.2.9-next.1 ### Patch Changes diff --git a/plugins/azure-devops/README.md b/plugins/azure-devops/README.md index 5079fa4f16..7eeae09813 100644 --- a/plugins/azure-devops/README.md +++ b/plugins/azure-devops/README.md @@ -70,7 +70,7 @@ dev.azure.com/project: dev.azure.com/build-definition: ``` -In this case `` will be the name of your Team Project and `` will be the name of the Build Definition you would like to see Builds for. If the Build Definition name has spaces in it make sure to put quotes around it +In this case `` will be the name of your Team Project and `` will be the name of the Build Definition you would like to see Builds for, and it's possible to add more Builds separated by a comma. If the Build Definition name has spaces in it make sure to put quotes around it. ### Azure Pipelines Component diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index 914cc9a4ba..0e9b38dfe7 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops", - "version": "0.2.9-next.1", + "version": "0.3.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops/src/api/AzureDevOpsClient.ts b/plugins/azure-devops/src/api/AzureDevOpsClient.ts index 68d8896538..a202008798 100644 --- a/plugins/azure-devops/src/api/AzureDevOpsClient.ts +++ b/plugins/azure-devops/src/api/AzureDevOpsClient.ts @@ -120,7 +120,23 @@ export class AzureDevOpsClient implements AzureDevOpsApi { queryString.append('repoName', repoName); } if (definitionName) { - queryString.append('definitionName', definitionName); + const definitionNames = definitionName.split(','); + if (definitionNames.length > 1) { + const buildRuns: BuildRun[] = []; + for (const name of definitionNames) { + queryString.set('definitionName', name.trim()); + if (options?.top) { + queryString.set('top', options.top.toString()); + } + const urlSegment = `builds/${encodeURIComponent( + projectName, + )}?${queryString}`; + const items = await this.get(urlSegment); + buildRuns.push(...items); + } + return { items: buildRuns }; + } + queryString.append('definitionName', definitionName.trim()); } if (options?.top) { queryString.append('top', options.top.toString()); diff --git a/plugins/azure-sites-backend/CHANGELOG.md b/plugins/azure-sites-backend/CHANGELOG.md index 9c25a70214..bb29d92f51 100644 --- a/plugins/azure-sites-backend/CHANGELOG.md +++ b/plugins/azure-sites-backend/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-azure-sites-backend +## 0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/plugin-azure-sites-common@0.1.0 + +## 0.1.7 + +### Patch Changes + +- d66d4f916aa: Updated URL to `/health` and corrected typos in the `README.md` +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config@1.0.7 + - @backstage/plugin-azure-sites-common@0.1.0 + ## 0.1.7-next.1 ### Patch Changes diff --git a/plugins/azure-sites-backend/README.md b/plugins/azure-sites-backend/README.md index 0d44b9a4e4..23152f9760 100644 --- a/plugins/azure-sites-backend/README.md +++ b/plugins/azure-sites-backend/README.md @@ -2,7 +2,7 @@ Simple plugin that proxies requests to the Azure Portal API through Azure SDK JavaScript libraries. -_Inspired by [roadie.io AWS Lamda plugin](https://roadie.io/backstage/plugins/aws-lambda/)_ +_Inspired by [roadie.io AWS Lambda plugin](https://roadie.io/backstage/plugins/aws-lambda/)_ ## Setup @@ -65,7 +65,7 @@ Here's how to get the backend plugin up and running: ```ts import azure from './plugins/azure'; - // Removed for clairty... + // Removed for clarity... async function main() { // ... @@ -82,4 +82,4 @@ Here's how to get the backend plugin up and running: 4. Now run `yarn start-backend` from the repo root. -5. Finally, open `http://localhost:7007/api/azure/health` in a browser, it should return `{"status":"ok"}`. +5. Finally, open `http://localhost:7007/api/azure-sites/health` in a browser, it should return `{"status":"ok"}`. diff --git a/plugins/azure-sites-backend/package.json b/plugins/azure-sites-backend/package.json index a58459d2aa..84f5fcb6a1 100644 --- a/plugins/azure-sites-backend/package.json +++ b/plugins/azure-sites-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-sites-backend", - "version": "0.1.7-next.1", + "version": "0.1.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites/CHANGELOG.md b/plugins/azure-sites/CHANGELOG.md index 1eea015834..3412e100c1 100644 --- a/plugins/azure-sites/CHANGELOG.md +++ b/plugins/azure-sites/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-azure-sites +## 0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-azure-sites-common@0.1.0 + +## 0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-azure-sites-common@0.1.0 + +## 0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.7-next.1 ### Patch Changes diff --git a/plugins/azure-sites/package.json b/plugins/azure-sites/package.json index 8863e76dae..59bfaf839a 100644 --- a/plugins/azure-sites/package.json +++ b/plugins/azure-sites/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-sites", - "version": "0.1.7-next.1", + "version": "0.1.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/badges-backend/CHANGELOG.md b/plugins/badges-backend/CHANGELOG.md index 50bf55c918..57e5d63270 100644 --- a/plugins/badges-backend/CHANGELOG.md +++ b/plugins/badges-backend/CHANGELOG.md @@ -1,5 +1,53 @@ # @backstage/plugin-badges-backend +## 0.2.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-auth-node@0.2.15-next.0 + +## 0.2.0 + +### Minor Changes + +- a0108c49774: Fixing badges-backend plugin to get a token from the TokenManager instead of parsing the request header. Hence, it's now possible to disable the authMiddleware for the badges-backend plugin to expose publicly the badges. + + Implementing an obfuscation feature to protect an open badges endpoint from being enumerated. The feature is disabled by default and the change is compatible with the previous version. + + **BREAKING**: `createRouter` now require that `tokenManager`, `logger`, and `identityApi`, are passed in as options. + +### Patch Changes + +- 0cd552c28d8: Removed some unused dependencies +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## 0.2.0-next.2 + +### Minor Changes + +- a0108c49774: Fixing badges-backend plugin to get a token from the TokenManager instead of parsing the request header. Hence, it's now possible to disable the authMiddleware for the badges-backend plugin to expose publicly the badges. + + Implementing an obfuscation feature to protect an open badges endpoint from being enumerated. The feature is disabled by default and the change is compatible with the previous version. + + **BREAKING**: `createRouter` now require that `tokenManager`, `logger`, and `identityApi`, are passed in as options. + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.7 + ## 0.1.39-next.1 ### Patch Changes diff --git a/plugins/badges-backend/README.md b/plugins/badges-backend/README.md index 63e43c6692..ddbb30bc4e 100644 --- a/plugins/badges-backend/README.md +++ b/plugins/badges-backend/README.md @@ -36,6 +36,9 @@ export default async function createPlugin( config: env.config, discovery: env.discovery, badgeFactories: createDefaultBadgeFactories(), + tokenManager: env.tokenManager, + logger: env.logger, + identity: env.identity, }); } ``` @@ -112,11 +115,29 @@ export const createMyCustomBadgeFactories = (): BadgeFactories => ({ }); ``` +### Badge obfuscation + +When you enable the obfuscation feature, the badges backend will obfuscate the entity names in the badge link. It's useful when you want your badges to be visible to the public, but you don't want to expose the entity names and also to protect your entity names from being enumerated. + +To enable the obfuscation you need to activate the `obfuscation` feature in the `app-config.yaml`: + +```yaml +app: + badges: + obfuscate: true +``` + +:warning: **Warning**: The only endpoint to be publicly available is the `/entity/:entityUuid/:badgeId` endpoint. The other endpoints are meant for trusted internal users and should not be publicly exposed. + +> Note that you cannot use env vars to set the `obfuscate` value. It must be a boolean value and env vars are always strings. + ## API The badges backend api exposes two main endpoints for entity badges. The `/badges` prefix is arbitrary, and the default for the example backend. +### If obfuscation is disabled (default or apps.badges.obfuscate: false) + - `/badges/entity/:namespace/:kind/:name/badge-specs` List all defined badges for a particular entity, in json format. See [BadgeSpec](https://github.com/backstage/backstage/tree/master/plugins/badges/src/api/types.ts) @@ -126,6 +147,21 @@ The badges backend api exposes two main endpoints for entity badges. The an SVG image. If the `accept` request header prefers `application/json` the badge spec as JSON will be returned instead of the image. +### If obfuscation is enabled (apps.badges.obfuscate: true) + +- `/badges/entity/:namespace/:kind/:name/obfuscated` Get the obfuscated `entity url`. + +> Note that endpoint have a embedded authMiddleware to authenticate the user requesting this endpoint. _It meant to be called from the frontend plugin._ + +- `/badges/entity/:entityUuid/:badgeId` Get the entity badge as an SVG image. If + the `accept` request header prefers `application/json` the badge spec as JSON + will be returned instead of the image. + +- `/badge/entity/:entityUuid/badge-specs` List all defined badges for a + particular entity, in json format. See + [BadgeSpec](https://github.com/backstage/backstage/tree/master/plugins/badges/src/api/types.ts) + from the frontend plugin for a type declaration. + ## Links - [Frontend part of the plugin](https://github.com/backstage/backstage/tree/master/plugins/badges) diff --git a/plugins/badges-backend/api-report.md b/plugins/badges-backend/api-report.md index 8ca4b561a2..09a02ba44d 100644 --- a/plugins/badges-backend/api-report.md +++ b/plugins/badges-backend/api-report.md @@ -7,7 +7,10 @@ import { CatalogApi } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; import { Entity } from '@backstage/catalog-model'; import express from 'express'; +import { IdentityApi } from '@backstage/plugin-auth-node'; +import { Logger } from 'winston'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; +import { TokenManager } from '@backstage/backend-common'; // @public (undocumented) export interface Badge { @@ -78,6 +81,27 @@ export type BadgeSpec = { markdown: string; }; +// @public +export interface BadgesStore { + // (undocumented) + getBadgeFromUuid(uuid: string): Promise< + | { + name: string; + namespace: string; + kind: string; + } + | undefined + >; + // (undocumented) + getBadgeUuid( + name: string, + namespace: string, + kind: string, + ): Promise<{ + uuid: string; + }>; +} + // @public (undocumented) export type BadgeStyle = (typeof BADGE_STYLES)[number]; @@ -107,10 +131,18 @@ export interface RouterOptions { // (undocumented) badgeFactories?: BadgeFactories; // (undocumented) + badgeStore?: BadgesStore; + // (undocumented) catalog?: CatalogApi; // (undocumented) config: Config; // (undocumented) discovery: PluginEndpointDiscovery; + // (undocumented) + identity: IdentityApi; + // (undocumented) + logger: Logger; + // (undocumented) + tokenManager: TokenManager; } ``` diff --git a/plugins/badges-backend/migrations/20230404_init.js b/plugins/badges-backend/migrations/20230404_init.js new file mode 100644 index 0000000000..3de6bfc248 --- /dev/null +++ b/plugins/badges-backend/migrations/20230404_init.js @@ -0,0 +1,33 @@ +/* + * Copyright 2021 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. + */ + +exports.up = async function up(knex) { + await knex.schema.createTable('badges', table => { + table.string('kind').notNullable(); + table.string('namespace').notNullable(); + table.string('name').notNullable(); + table.string('uuid').unique().notNullable(); + table.index(['uuid'], 'badges_uuid_index'); + table.primary(['kind', 'namespace', 'name']); + }); +}; + +exports.down = async function down(knex) { + await knex.schema.alterTable('badges', table => { + table.dropIndex('', 'badges_uuid_index'); + }); + await knex.schema.dropTable('badges'); +}; diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index 5f9b5b51a3..e29d3f9e8f 100644 --- a/plugins/badges-backend/package.json +++ b/plugins/badges-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges-backend", "description": "A Backstage backend plugin that generates README badges for your entities", - "version": "0.1.39-next.1", + "version": "0.2.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -38,18 +38,25 @@ "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", + "@backstage/plugin-auth-node": "workspace:^", "@types/express": "^4.17.6", "badge-maker": "^3.3.0", "cors": "^2.8.5", "express": "^4.17.1", "express-promise-router": "^4.1.0", + "knex": "^2.4.2", + "lodash": "^4.17.21", + "supertest": "^6.3.3", + "uuid": "^9.0.0", "winston": "^3.2.1", "yn": "^4.0.0" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", + "@backstage/catalog-client": "workspace:^", "@backstage/cli": "workspace:^", - "@types/supertest": "^2.0.8", - "supertest": "^6.1.3" + "@types/node": "*", + "cross-fetch": "^3.1.5" }, "files": [ "dist" diff --git a/plugins/badges-backend/src/database/badgeStore.test.ts b/plugins/badges-backend/src/database/badgeStore.test.ts new file mode 100644 index 0000000000..5a7a82d4b7 --- /dev/null +++ b/plugins/badges-backend/src/database/badgeStore.test.ts @@ -0,0 +1,110 @@ +/* + * Copyright 2021 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 { DatabaseBadgesStore } from './badgesStore'; +import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; +import { Knex } from 'knex'; +import { Entity } from '@backstage/catalog-model'; + +describe('DatabaseBadgesStore', () => { + const entity: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'test', + }, + }; + + const databases = TestDatabases.create(); + + async function createDatabaseBadgesStore(databaseId: TestDatabaseId) { + const knex = await databases.init(databaseId); + return { + knex, + badgeStore: await DatabaseBadgesStore.create({ + database: { getClient: async () => knex }, + }), + }; + } + + describe.each(databases.eachSupportedId())('%p', databaseId => { + let knex: Knex; + let badgeStore: DatabaseBadgesStore; + + beforeEach(async () => { + ({ knex, badgeStore } = await createDatabaseBadgesStore(databaseId)); + }); + + it('createABadge if not existing in DB', async () => { + const uuid = await badgeStore.getBadgeUuid( + entity.metadata.name, + entity.metadata.namespace || 'default', + entity.kind, + ); + + expect(uuid.uuid).toMatch( + /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/, + ); + + const storedBadge = await badgeStore.getBadgeFromUuid(uuid.uuid); + expect(storedBadge?.kind).toEqual(entity.kind); + expect(storedBadge?.name).toEqual(entity.metadata.name); + expect(storedBadge?.namespace).toEqual( + entity.metadata.namespace || 'default', + ); + }); + + it('getBadge if badge already exist in DB', async () => { + await knex('badges').truncate(); + await knex('badges').insert([ + { + uuid: 'uuid1', + name: 'test', + namespace: 'default', + kind: 'component', + }, + ]); + + const storedEntity = await badgeStore.getBadgeFromUuid('uuid1'); + + expect(storedEntity).toEqual({ + name: 'test', + namespace: 'default', + kind: 'component', + }); + }); + + it('getBadgeUuid if badge exist in DB', async () => { + await knex('badges').truncate(); + await knex('badges').insert([ + { + uuid: 'uuid1', + name: 'test', + namespace: 'default', + kind: 'component', + }, + ]); + + const storedUuid = await badgeStore.getBadgeUuid( + 'test', + 'default', + 'component', + ); + + expect(storedUuid).toEqual({ uuid: 'uuid1' }); + }); + }); +}); diff --git a/plugins/badges-backend/src/database/badgesStore.ts b/plugins/badges-backend/src/database/badgesStore.ts new file mode 100644 index 0000000000..e6c6a9e2ad --- /dev/null +++ b/plugins/badges-backend/src/database/badgesStore.ts @@ -0,0 +1,110 @@ +/* + * Copyright 2021 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 { + PluginDatabaseManager, + resolvePackagePath, +} from '@backstage/backend-common'; +import { Knex } from 'knex'; +import { isNil } from 'lodash'; +import { v4 as uuidv4 } from 'uuid'; + +/** + * internal + * @public + */ +export interface BadgesStore { + getBadgeUuid( + name: string, + namespace: string, + kind: string, + ): Promise<{ uuid: string }>; + + getBadgeFromUuid( + uuid: string, + ): Promise<{ name: string; namespace: string; kind: string } | undefined>; +} + +const migrationsDir = resolvePackagePath( + '@backstage/plugin-badges-backend', // Package name + 'migrations', // Migrations directory +); + +/** + * DatabaseBadgesStore + * @internal + */ +export class DatabaseBadgesStore implements BadgesStore { + private constructor(private readonly db: Knex) {} + + static async create({ + database, + skipMigrations, + }: { + database: PluginDatabaseManager; + skipMigrations?: boolean; + }): Promise { + const client = await database.getClient(); + + if (!database.migrations?.skip && !skipMigrations) { + await client.migrate.latest({ + directory: migrationsDir, + }); + } + + return new DatabaseBadgesStore(client); + } + + async getBadgeFromUuid( + uuid: string, + ): Promise<{ name: string; namespace: string; kind: string } | undefined> { + const result = await this.db('badges') + .select('namespace', 'name', 'kind') + .where({ uuid: uuid }) + .first(); + + return result; + } + + async getBadgeUuid( + name: string, + namespace: string, + kind: string, + ): Promise<{ uuid: string }> { + const result = await this.db('badges') + .select('uuid') + .where({ name: name, namespace: namespace, kind: kind }) + .first(); + + let uuid = result?.uuid; + + if (isNil(uuid)) { + uuid = uuidv4(); + + await this.db('badges') + .insert({ + uuid: uuid, + name: name, + namespace: namespace, + kind: kind, + }) + .onConflict(['name', 'namespace', 'kind']) + .ignore(); + } + + return { uuid }; + } +} diff --git a/plugins/badges-backend/src/index.ts b/plugins/badges-backend/src/index.ts index a45714cb81..35a061c516 100644 --- a/plugins/badges-backend/src/index.ts +++ b/plugins/badges-backend/src/index.ts @@ -24,3 +24,4 @@ export * from './badges'; export * from './lib'; export * from './service/router'; export * from './types'; +export * from './database/badgesStore'; diff --git a/plugins/badges-backend/src/service/router-obfuscated.test.ts b/plugins/badges-backend/src/service/router-obfuscated.test.ts new file mode 100644 index 0000000000..3c9ec0d2b6 --- /dev/null +++ b/plugins/badges-backend/src/service/router-obfuscated.test.ts @@ -0,0 +1,302 @@ +/* + * Copyright 2021 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 express from 'express'; +import request from 'supertest'; +import { + getVoidLogger, + PluginEndpointDiscovery, + ServerTokenManager, + SingleHostDiscovery, +} from '@backstage/backend-common'; +import { CatalogApi } from '@backstage/catalog-client'; +import type { Entity } from '@backstage/catalog-model'; +import { Config, ConfigReader } from '@backstage/config'; +import { createRouter } from './router'; +import { BadgeBuilder } from '../lib'; +import { + BackstageIdentityResponse, + IdentityApiGetIdentityRequest, +} from '@backstage/plugin-auth-node'; +import { BadgesStore } from '../database/badgesStore'; + +describe('createRouter', () => { + let app: express.Express; + const badgeBuilder: jest.Mocked = { + getBadges: jest.fn(), + createBadgeJson: jest.fn(), + createBadgeSvg: jest.fn(), + }; + + const catalog = { + addLocation: jest.fn(), + getEntities: jest.fn(), + getEntityByRef: jest.fn(), + getLocationByRef: jest.fn(), + getLocationById: jest.fn(), + removeLocationById: jest.fn(), + removeEntityByUid: jest.fn(), + refreshEntity: jest.fn(), + getEntityAncestors: jest.fn(), + getEntityFacets: jest.fn(), + validateEntity: jest.fn(), + }; + const getIdentity = jest + .fn() + .mockImplementation( + async ({ + request: _request, + }: IdentityApiGetIdentityRequest): Promise< + BackstageIdentityResponse | undefined + > => { + return { + identity: { + userEntityRef: 'user:default/guest', + ownershipEntityRefs: [], + type: 'user', + }, + token: 'token', + }; + }, + ); + + const config: Config = new ConfigReader({ + backend: { + baseUrl: 'http://127.0.0.1', + listen: { + port: 7007, + }, + database: { + client: 'better-sqlite3', + connection: ':memory:', + }, + }, + app: { + badges: { + obfuscate: true, + }, + }, + }); + + let discovery: PluginEndpointDiscovery; + + const entity: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'test', + }, + }; + + const entities: Entity[] = [ + entity, + { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'test-2', + }, + }, + ]; + + const badge = { + id: 'test-badge', + badge: { + label: 'test', + message: 'badge', + }, + url: '/...', + markdown: '[![...](...)]', + }; + + const badgeEntity = { + name: 'test', + namespace: 'default', + kind: 'component', + }; + + const badgeStore: jest.Mocked = { + getBadgeUuid: jest.fn().mockImplementation(async () => { + return { uuid: 'uuid1' }; + }), + getBadgeFromUuid: jest.fn().mockImplementation(async () => { + return badgeEntity; + }), + }; + + beforeAll(async () => { + discovery = SingleHostDiscovery.fromConfig(config); + const tokenManager = ServerTokenManager.noop(); + const router = await createRouter({ + badgeBuilder, + catalog: catalog as Partial as CatalogApi, + config, + discovery, + tokenManager, + logger: getVoidLogger(), + identity: { getIdentity }, + }); + app = express().use(router); + }); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('works with provided badgeStore', async () => { + const tokenManager = ServerTokenManager.noop(); + const router = await createRouter({ + badgeBuilder, + catalog: catalog as Partial as CatalogApi, + config, + discovery, + tokenManager, + logger: getVoidLogger(), + identity: { getIdentity }, + badgeStore: badgeStore, + }); + expect(router).toBeDefined(); + }); + + describe('GET /entity/:namespace/:kind/:name/badge-specs', () => { + it('does not returns all badge specs for entity', async () => { + catalog.getEntityByRef.mockResolvedValueOnce(entity); + + badgeBuilder.getBadges.mockResolvedValueOnce([{ id: badge.id }]); + badgeBuilder.createBadgeJson.mockResolvedValueOnce(badge); + + const response = await request(app).get( + '/entity/default/component/test/badge-specs', + ); + + expect(response.status).toEqual(404); + }); + }); + + describe('GET /entity/:namespace/:kind/:name/badge/test-badge', () => { + it('does not returns badge for entity', async () => { + catalog.getEntityByRef.mockResolvedValueOnce(entity); + + const image = '...'; + badgeBuilder.createBadgeSvg.mockResolvedValueOnce(image); + + const response = await request(app).get( + '/entity/default/component/test/badge/test-badge', + ); + + expect(response.status).toEqual(404); + }); + + it('does not returns badge spec for entity', async () => { + catalog.getEntityByRef.mockResolvedValueOnce(entity); + badgeBuilder.createBadgeJson.mockResolvedValueOnce(badge); + + const url = '/entity/default/component/test/badge/test-badge?format=json'; + const response = await request(app).get(url); + + expect(response.status).toEqual(404); + }); + }); + + describe('GET /entity/:namespace/:kind/:name/obfuscated', () => { + catalog.getEntityByRef.mockResolvedValueOnce(entity); + catalog.getEntities.mockResolvedValueOnce({ items: entities }); + + it('returns obfuscated 401 if no auth', async () => { + const obfuscatedEntity = await request(app).get( + '/entity/default/component/test/obfuscated', + ); + expect(obfuscatedEntity.status).toEqual(401); + }); + + it('returns obfuscated entity and badges', async () => { + const obfuscatedEntity = await request(app) + .get('/entity/default/component/test/obfuscated') + .set('Authorization', 'Bearer fakeToken'); + expect(obfuscatedEntity.status).toEqual(200); + expect(obfuscatedEntity.body.uuid).toMatch( + new RegExp( + '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$', + ), + ); + + const uuid = obfuscatedEntity.body.uuid; + const url = `/entity/${uuid}/test-badge?format=json`; + let response = await request(app).get(url); + + expect(response.status).toEqual(200); + expect(response.body).toEqual(badge); + + catalog.getEntityByRef.mockResolvedValueOnce(entity); + catalog.getEntities.mockResolvedValueOnce({ items: entities }); + + const image = '...'; + badgeBuilder.createBadgeSvg.mockResolvedValueOnce(image); + + response = await request(app).get(`/entity/${uuid}/test-badge`); + + expect(response.status).toEqual(200); + expect(response.body).toEqual(Buffer.from(image)); + + catalog.getEntities.mockResolvedValueOnce({ items: entities }); + catalog.getEntityByRef.mockResolvedValueOnce(entity); + + badgeBuilder.getBadges.mockResolvedValueOnce([{ id: badge.id }]); + badgeBuilder.createBadgeJson.mockResolvedValueOnce(badge); + + response = await request(app).get(`/entity/${uuid}/badge-specs`); + expect(response.status).toEqual(200); + expect(response.body).toEqual([badge]); + + expect(badgeBuilder.getBadges).toHaveBeenCalledTimes(1); + expect(badgeBuilder.createBadgeJson).toHaveBeenCalledTimes(2); + }); + + describe('Errors', () => { + it('returns 404 for unknown entity uuid', async () => { + badgeStore.getBadgeFromUuid.mockResolvedValue(undefined); + catalog.getEntityByRef.mockResolvedValueOnce(entity); + catalog.getEntities.mockResolvedValueOnce({ items: entities }); + badgeBuilder.getBadges.mockResolvedValueOnce([{ id: badge.id }]); + badgeBuilder.createBadgeJson.mockResolvedValueOnce(badge); + + async function testUrl(url: string) { + const response = await request(app).get(url); + expect(response.status).toEqual(404); + expect(response.body).toEqual({ + error: { + message: expect.any(String), + name: 'NotFoundError', + }, + request: { + method: 'GET', + url, + }, + response: { + statusCode: 404, + }, + }); + } + await testUrl( + '/entity/3a5f91c1e66519be5394c37a8ba69cfsf3087b7c322c600e7497dc9d517353e5bed/badge-specs', + ); + await testUrl( + '/entity/3a5f91c1e66519be5394c37a8ba69c3087b7csfsf322c600e7497dc9d517353e5bed/test-badge', + ); + }); + }); + }); +}); diff --git a/plugins/badges-backend/src/service/router.test.ts b/plugins/badges-backend/src/service/router.test.ts index 109b64231d..2ecae6b452 100644 --- a/plugins/badges-backend/src/service/router.test.ts +++ b/plugins/badges-backend/src/service/router.test.ts @@ -17,7 +17,9 @@ import express from 'express'; import request from 'supertest'; import { + getVoidLogger, PluginEndpointDiscovery, + ServerTokenManager, SingleHostDiscovery, } from '@backstage/backend-common'; import { CatalogApi } from '@backstage/catalog-client'; @@ -25,10 +27,16 @@ import type { Entity } from '@backstage/catalog-model'; import { Config, ConfigReader } from '@backstage/config'; import { createRouter } from './router'; import { BadgeBuilder } from '../lib'; +import { + BackstageIdentityResponse, + IdentityApiGetIdentityRequest, +} from '@backstage/plugin-auth-node'; +import { BadgesStore } from '../database/badgesStore'; describe('createRouter', () => { let app: express.Express; let badgeBuilder: jest.Mocked; + const catalog = { addLocation: jest.fn(), getEntities: jest.fn(), @@ -42,12 +50,15 @@ describe('createRouter', () => { getEntityFacets: jest.fn(), validateEntity: jest.fn(), }; + + const getIdentity = jest.fn(); + let config: Config; let discovery: PluginEndpointDiscovery; const entity: Entity = { apiVersion: 'v1', - kind: 'service', + kind: 'component', metadata: { name: 'test', }, @@ -63,6 +74,11 @@ describe('createRouter', () => { markdown: '[![...](...)]', }; + const badgeStore: jest.Mocked = { + getBadgeFromUuid: jest.fn(), + getBadgeUuid: jest.fn(), + }; + beforeAll(async () => { badgeBuilder = { getBadges: jest.fn(), @@ -73,15 +89,40 @@ describe('createRouter', () => { backend: { baseUrl: 'http://127.0.0.1', listen: { port: 7007 }, + database: { + client: 'better-sqlite3', + connection: ':memory:', + }, }, }); - discovery = SingleHostDiscovery.fromConfig(config); + getIdentity.mockImplementation( + async ({ + request: _request, + }: IdentityApiGetIdentityRequest): Promise< + BackstageIdentityResponse | undefined + > => { + return { + identity: { + userEntityRef: 'user:default/guest', + ownershipEntityRefs: [], + type: 'user', + }, + token: 'token', + }; + }, + ); + + discovery = SingleHostDiscovery.fromConfig(config); + const tokenManager = ServerTokenManager.noop(); const router = await createRouter({ badgeBuilder, catalog: catalog as Partial as CatalogApi, config, discovery, + tokenManager, + logger: getVoidLogger(), + identity: { getIdentity }, }); app = express().use(router); }); @@ -90,12 +131,17 @@ describe('createRouter', () => { jest.resetAllMocks(); }); - it('works', async () => { + it('works with badgeStore', async () => { + const tokenManager = ServerTokenManager.noop(); const router = await createRouter({ badgeBuilder, catalog: catalog as Partial as CatalogApi, config, discovery, + tokenManager, + logger: getVoidLogger(), + identity: { getIdentity }, + badgeStore: badgeStore, }); expect(router).toBeDefined(); }); @@ -108,7 +154,7 @@ describe('createRouter', () => { badgeBuilder.createBadgeJson.mockResolvedValueOnce(badge); const response = await request(app).get( - '/entity/default/service/test/badge-specs', + '/entity/default/component/test/badge-specs', ); expect(response.status).toEqual(200); @@ -118,10 +164,10 @@ describe('createRouter', () => { expect(catalog.getEntityByRef).toHaveBeenCalledWith( { namespace: 'default', - kind: 'service', + kind: 'component', name: 'test', }, - { token: undefined }, + { token: '' }, ); expect(badgeBuilder.getBadges).toHaveBeenCalledTimes(1); @@ -130,46 +176,7 @@ describe('createRouter', () => { badgeInfo: { id: badge.id }, context: { badgeUrl: expect.stringMatching( - /http:\/\/127.0.0.1\/api\/badges\/entity\/default\/service\/test\/badge\/test-badge/, - ), - config, - entity, - }, - }); - }); - }); - - describe('GET /entity/:namespace/:kind/:name/badge/test-badge', () => { - it('returns badge for entity', async () => { - catalog.getEntityByRef.mockResolvedValueOnce(entity); - - const image = '...'; - badgeBuilder.createBadgeSvg.mockResolvedValueOnce(image); - - const response = await request(app).get( - '/entity/default/service/test/badge/test-badge', - ); - - expect(response.status).toEqual(200); - expect(response.body).toEqual(Buffer.from(image)); - - expect(catalog.getEntityByRef).toHaveBeenCalledTimes(1); - expect(catalog.getEntityByRef).toHaveBeenCalledWith( - { - namespace: 'default', - kind: 'service', - name: 'test', - }, - { token: undefined }, - ); - - expect(badgeBuilder.getBadges).toHaveBeenCalledTimes(0); - expect(badgeBuilder.createBadgeSvg).toHaveBeenCalledTimes(1); - expect(badgeBuilder.createBadgeSvg).toHaveBeenCalledWith({ - badgeInfo: { id: badge.id }, - context: { - badgeUrl: expect.stringMatching( - /http:\/\/127.0.0.1\/api\/badges\/entity\/default\/service\/test\/badge\/test-badge/, + /http:\/\/127.0.0.1\/api\/badges\/entity\/default\/component\/test\/badge\/test-badge/, ), config, entity, @@ -177,27 +184,90 @@ describe('createRouter', () => { }); }); - it('returns badge spec for entity', async () => { - catalog.getEntityByRef.mockResolvedValueOnce(entity); - badgeBuilder.createBadgeJson.mockResolvedValueOnce(badge); + describe('GET /entity/:namespace/:kind/:name/badge/test-badge', () => { + it('returns badge for entity', async () => { + catalog.getEntityByRef.mockResolvedValueOnce(entity); - const url = '/entity/default/service/test/badge/test-badge?format=json'; - const response = await request(app).get(url); + const image = '...'; + badgeBuilder.createBadgeSvg.mockResolvedValueOnce(image); - expect(response.status).toEqual(200); - expect(response.body).toEqual(badge); + const response = await request(app).get( + '/entity/default/component/test/badge/test-badge', + ); + + expect(response.status).toEqual(200); + expect(response.body).toEqual(Buffer.from(image)); + + expect(catalog.getEntityByRef).toHaveBeenCalledTimes(1); + expect(catalog.getEntityByRef).toHaveBeenCalledWith( + { + namespace: 'default', + kind: 'component', + name: 'test', + }, + { token: '' }, + ); + + expect(badgeBuilder.getBadges).toHaveBeenCalledTimes(0); + expect(badgeBuilder.createBadgeSvg).toHaveBeenCalledTimes(1); + expect(badgeBuilder.createBadgeSvg).toHaveBeenCalledWith({ + badgeInfo: { id: badge.id }, + context: { + badgeUrl: expect.stringMatching( + /http:\/\/127.0.0.1\/api\/badges\/entity\/default\/component\/test\/badge\/test-badge/, + ), + config, + entity, + }, + }); + }); + + it('returns badge spec for entity', async () => { + catalog.getEntityByRef.mockResolvedValueOnce(entity); + badgeBuilder.createBadgeJson.mockResolvedValueOnce(badge); + + const url = + '/entity/default/component/test/badge/test-badge?format=json'; + const response = await request(app).get(url); + + expect(response.status).toEqual(200); + expect(response.body).toEqual(badge); + }); }); - }); - describe('Errors', () => { - it('returns 404 for unknown entities', async () => { + describe('Errors', () => { + it('returns 404 for unknown entities', async () => { + catalog.getEntityByRef.mockResolvedValue(undefined); + async function testUrl(url: string) { + const response = await request(app).get(url); + expect(response.status).toEqual(404); + expect(response.body).toEqual({ + error: { + message: 'No component entity in default named "missing"', + name: 'NotFoundError', + }, + request: { + method: 'GET', + url, + }, + response: { + statusCode: 404, + }, + }); + } + await testUrl('/entity/default/component/missing/badge-specs'); + await testUrl('/entity/default/component/missing/badge/test-badge'); + }); + }); + + it('returns 404 for uuid entities', async () => { catalog.getEntityByRef.mockResolvedValue(undefined); async function testUrl(url: string) { const response = await request(app).get(url); expect(response.status).toEqual(404); expect(response.body).toEqual({ error: { - message: 'No service entity in default named "missing"', + message: 'No component entity in default named "missing"', name: 'NotFoundError', }, request: { @@ -209,8 +279,8 @@ describe('createRouter', () => { }, }); } - await testUrl('/entity/default/service/missing/badge-specs'); - await testUrl('/entity/default/service/missing/badge/test-badge'); + await testUrl('/entity/default/component/missing/badge-specs'); + await testUrl('/entity/default/component/missing/badge/test-badge'); }); }); }); diff --git a/plugins/badges-backend/src/service/router.ts b/plugins/badges-backend/src/service/router.ts index e5caa5cd2a..308865b73a 100644 --- a/plugins/badges-backend/src/service/router.ts +++ b/plugins/badges-backend/src/service/router.ts @@ -17,14 +17,21 @@ import express from 'express'; import Router from 'express-promise-router'; import { + DatabaseManager, errorHandler, PluginEndpointDiscovery, + TokenManager, } from '@backstage/backend-common'; import { CatalogApi, CatalogClient } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; -import { NotFoundError } from '@backstage/errors'; +import { AuthenticationError, NotFoundError } from '@backstage/errors'; import { BadgeBuilder, DefaultBadgeBuilder } from '../lib/BadgeBuilder'; import { BadgeContext, BadgeFactories } from '../types'; +import { isNil } from 'lodash'; +import { Logger } from 'winston'; +import { IdentityApi } from '@backstage/plugin-auth-node'; +import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node'; +import { BadgesStore, DatabaseBadgesStore } from '../database/badgesStore'; /** @public */ export interface RouterOptions { @@ -33,6 +40,10 @@ export interface RouterOptions { catalog?: CatalogApi; config: Config; discovery: PluginEndpointDiscovery; + tokenManager: TokenManager; + logger: Logger; + identity: IdentityApi; + badgeStore?: BadgesStore; } /** @public */ @@ -46,13 +57,214 @@ export async function createRouter( new DefaultBadgeBuilder(options.badgeFactories || {}); const router = Router(); + const { config, logger, tokenManager, discovery, identity } = options; + const baseUrl = await discovery.getExternalBaseUrl('badges'); + + if (config.getOptionalBoolean('app.badges.obfuscate')) { + return obfuscatedRoute( + router, + catalog, + badgeBuilder, + tokenManager, + logger, + options, + config, + identity, + baseUrl, + ); + } + return nonObfuscatedRoute( + router, + catalog, + badgeBuilder, + tokenManager, + config, + baseUrl, + ); +} + +async function obfuscatedRoute( + router: express.Router, + catalog: CatalogApi, + badgeBuilder: BadgeBuilder, + tokenManager: TokenManager, + logger: Logger, + options: RouterOptions, + config: Config, + identity: IdentityApi, + baseUrl: string, +) { + logger.info('Badges obfuscation is enabled'); + + const store = options.badgeStore + ? options.badgeStore + : await DatabaseBadgesStore.create({ + database: await DatabaseManager.fromConfig(config).forPlugin('badges'), + }); + + router.get('/entity/:entityUuid/badge-specs', async (req, res) => { + const { entityUuid } = req.params; + + // Retrieve the badge info from the database + const badgeInfos = await store.getBadgeFromUuid(entityUuid); + + if (isNil(badgeInfos)) { + throw new NotFoundError(`No badge found for entity uuid "${entityUuid}"`); + } + + // If a mapping is found, map name, namespace and kind + const name = badgeInfos.name; + const namespace = badgeInfos.namespace; + const kind = badgeInfos.kind; + const token = await tokenManager.getToken(); + + // Query the catalog with the name, namespace, kind to get the entity informations + const entity = await catalog.getEntityByRef( + { + namespace, + kind, + name, + }, + token, + ); + if (isNil(entity)) { + throw new NotFoundError( + `No ${kind} entity in ${namespace} named "${name}"`, + ); + } + + // Create the badge specs + const specs = []; + for (const badgeInfo of await badgeBuilder.getBadges()) { + const context: BadgeContext = { + badgeUrl: `${baseUrl}/entity/${entityUuid}/${badgeInfo.id}`, + config: config, + entity, + }; + + const badge = await badgeBuilder.createBadgeJson({ + badgeInfo, + context, + }); + specs.push(badge); + } + + res.status(200).json(specs); + }); + + router.get('/entity/:entityUuid/:badgeId', async (req, res) => { + const { entityUuid, badgeId } = req.params; + + // Retrieve the badge info from the database + const badgeInfo = await store.getBadgeFromUuid(entityUuid); + + if (isNil(badgeInfo)) { + throw new NotFoundError(`No badge found for entity uuid "${entityUuid}"`); + } + + // If a mapping is found, map name, namespace and kind + const name = badgeInfo.name; + const namespace = badgeInfo.namespace; + const kind = badgeInfo.kind; + const token = await tokenManager.getToken(); + const entity = await catalog.getEntityByRef( + { + namespace, + kind, + name, + }, + token, + ); + if (isNil(entity)) { + throw new NotFoundError( + `No ${kind} entity in ${namespace} named "${name}"`, + res.sendStatus(404), + ); + } + + let format = + req.accepts(['image/svg+xml', 'application/json']) || 'image/svg+xml'; + if (req.query.format === 'json') { + format = 'application/json'; + } + + const badgeOptions = { + badgeInfo: { id: badgeId }, + context: { + badgeUrl: `${baseUrl}/entity/${entityUuid}/${badgeId}`, + config: config, + entity, + }, + }; + + let data: string; + if (format === 'application/json') { + data = JSON.stringify( + await badgeBuilder.createBadgeJson(badgeOptions), + null, + 2, + ); + } else { + data = await badgeBuilder.createBadgeSvg(badgeOptions); + } + + res.setHeader('Content-Type', format); + res.status(200).send(data); + }); + + router.get( + '/entity/:namespace/:kind/:name/obfuscated', + function authenticate(req, _res, next) { + const token = + getBearerTokenFromAuthorizationHeader(req.headers.authorization) || + (req.cookies?.token as string | undefined); + + if (!token) { + throw new AuthenticationError('Unauthorized'); + } + + try { + req.user = identity.getIdentity({ request: req }); + next(); + } catch (error) { + tokenManager.authenticate(token.toString()); + next(error); + } + }, + async (req, res) => { + const { namespace, kind, name } = req.params; + const storedEntityUuid: { uuid: string } | undefined = + await store.getBadgeUuid(name, namespace, kind); + + if (isNil(storedEntityUuid)) { + throw new NotFoundError( + `No uuid found for entity "${namespace}/${kind}/${name}"`, + ); + } + + return res.status(200).json(storedEntityUuid); + }, + ); + + router.use(errorHandler()); + + return router; +} + +async function nonObfuscatedRoute( + router: express.Router, + catalog: CatalogApi, + badgeBuilder: BadgeBuilder, + tokenManager: TokenManager, + config: Config, + baseUrl: string, +) { router.get('/entity/:namespace/:kind/:name/badge-specs', async (req, res) => { + const token = await tokenManager.getToken(); const { namespace, kind, name } = req.params; const entity = await catalog.getEntityByRef( { namespace, kind, name }, - { - token: getBearerToken(req.headers.authorization), - }, + token, ); if (!entity) { throw new NotFoundError( @@ -62,19 +274,17 @@ export async function createRouter( const specs = []; for (const badgeInfo of await badgeBuilder.getBadges()) { + const badgeId = badgeInfo.id; const context: BadgeContext = { - badgeUrl: await getBadgeUrl( - namespace, - kind, - name, - badgeInfo.id, - options, - ), - config: options.config, + badgeUrl: `${baseUrl}/entity/${namespace}/${kind}/${name}/badge/${badgeId}`, + config: config, entity, }; - const badge = await badgeBuilder.createBadgeJson({ badgeInfo, context }); + const badge = await badgeBuilder.createBadgeJson({ + badgeInfo, + context, + }); specs.push(badge); } @@ -85,11 +295,10 @@ export async function createRouter( '/entity/:namespace/:kind/:name/badge/:badgeId', async (req, res) => { const { namespace, kind, name, badgeId } = req.params; + const token = await tokenManager.getToken(); const entity = await catalog.getEntityByRef( { namespace, kind, name }, - { - token: getBearerToken(req.headers.authorization), - }, + token, ); if (!entity) { throw new NotFoundError( @@ -106,8 +315,8 @@ export async function createRouter( const badgeOptions = { badgeInfo: { id: badgeId }, context: { - badgeUrl: await getBadgeUrl(namespace, kind, name, badgeId, options), - config: options.config, + badgeUrl: `${baseUrl}/entity/${namespace}/${kind}/${name}/badge/${badgeId}`, + config: config, entity, }, }; @@ -132,18 +341,3 @@ export async function createRouter( return router; } - -async function getBadgeUrl( - namespace: string, - kind: string, - name: string, - badgeId: string, - options: RouterOptions, -): Promise { - const baseUrl = await options.discovery.getExternalBaseUrl('badges'); - return `${baseUrl}/entity/${namespace}/${kind}/${name}/badge/${badgeId}`; -} - -function getBearerToken(header?: string): string | undefined { - return header?.match(/Bearer\s+(\S+)/i)?.[1]; -} diff --git a/plugins/badges-backend/src/service/standaloneServer.ts b/plugins/badges-backend/src/service/standaloneServer.ts index 0800585634..b07e1fa3b1 100644 --- a/plugins/badges-backend/src/service/standaloneServer.ts +++ b/plugins/badges-backend/src/service/standaloneServer.ts @@ -19,9 +19,14 @@ import { Logger } from 'winston'; import { createServiceBuilder, loadBackendConfig, + ServerTokenManager, SingleHostDiscovery, + useHotMemoize, } from '@backstage/backend-common'; import { createRouter } from './router'; +import { IdentityApi } from '@backstage/plugin-auth-node'; +import { DatabaseBadgesStore } from '../database/badgesStore'; +import Knex from 'knex'; export interface ServerOptions { port: number; @@ -35,10 +40,40 @@ export async function startStandaloneServer( const logger = options.logger.child({ service: 'badges-backend' }); const config = await loadBackendConfig({ logger, argv: process.argv }); const discovery = SingleHostDiscovery.fromConfig(config); + const database = useHotMemoize(module, () => { + return Knex({ + client: 'better-sqlite3', + connection: ':memory:', + useNullAsDefault: true, + }); + }); logger.debug('Creating application...'); - const router = await createRouter({ config, discovery }); + const tokenManager = ServerTokenManager.noop(); + const identity: IdentityApi = { + async getIdentity({ request }) { + const token = request.headers.authorization?.split(' ')[1]; + return { + identity: { + type: 'user', + ownershipEntityRefs: [], + userEntityRef: token || 'user:default/john_doe', + }, + token: token || 'no-token', + }; + }, + }; + const router = await createRouter({ + config, + discovery, + tokenManager, + logger, + identity, + badgeStore: await DatabaseBadgesStore.create({ + database: { getClient: async () => database }, + }), + }); let service = createServiceBuilder(module) .setPort(options.port) diff --git a/plugins/badges/CHANGELOG.md b/plugins/badges/CHANGELOG.md index b4a0e6aec6..656745c506 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,51 @@ # @backstage/plugin-badges +## 0.2.43-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## 0.2.42 + +### Patch Changes + +- a0108c49774: Fixing badges-backend plugin to get a token from the TokenManager instead of parsing the request header. Hence, it's now possible to disable the authMiddleware for the badges-backend plugin to expose publicly the badges. + + Implementing an obfuscation feature to protect an open badges endpoint from being enumerated. The feature is disabled by default and the change is compatible with the previous version. + + **BREAKING**: `createRouter` now require that `tokenManager`, `logger`, and `identityApi`, are passed in as options. + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.2.42-next.2 + +### Patch Changes + +- a0108c49774: Fixing badges-backend plugin to get a token from the TokenManager instead of parsing the request header. Hence, it's now possible to disable the authMiddleware for the badges-backend plugin to expose publicly the badges. + + Implementing an obfuscation feature to protect an open badges endpoint from being enumerated. The feature is disabled by default and the change is compatible with the previous version. + + **BREAKING**: `createRouter` now require that `tokenManager`, `logger`, and `identityApi`, are passed in as options. + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.2.42-next.1 ### Patch Changes diff --git a/plugins/badges/README.md b/plugins/badges/README.md index 65ace6226e..4b8ff38d47 100644 --- a/plugins/badges/README.md +++ b/plugins/badges/README.md @@ -18,6 +18,51 @@ This will popup a badges dialog showing all available badges for that entity lik ![Badges Dialog](./doc/badges-dialog.png) +##  Badge obfuscation + +The badges plugin supports obfuscating the badge URL to prevent it from being enumerated if the badges are used in a public context (like in Github repositories). + +To enable obfuscation, set the `obfuscate` option to `true` in the `app.badges` section of your `app-config.yaml`: + +```yaml +app: + badges: + obfuscate: true +``` + +Please note that if you have already set badges in your repositories and you activate the obfuscation you will need to update the badges in your repositories to use the new obfuscated URLs. + +Please note that the backend part needs to be configured to support obfuscation. See the [backend plugin documentation](../badges-backend/README.md) for more details. + +Also, you need to allow your frontend to access the configuration see : + +Example implementation would be in : `packages/app/src/config.d.ts` + +```typescript +export interface Config { + app: { + ... some code + badges: { + /** + * badges obfuscate + * @visibility frontend + */ + obfuscate?: string; + }; + }; +} +``` + +then include in the `packages/app/package.json` : + +```json +"files": [ + "dist", + "config.d.ts" + ], +"configSchema": "config.d.ts", +``` + ## Sample Badges Here are some samples of badges for the `artists-lookup` service in the Demo Backstage site: diff --git a/plugins/badges/package.json b/plugins/badges/package.json index 0e736d1cbc..2c3d72f234 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges", "description": "A Backstage plugin that generates README badges for your entities", - "version": "0.2.42-next.1", + "version": "0.2.43-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -50,14 +50,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/user-event": "^14.0.0", + "@testing-library/jest-dom": "^5.16.5", "@types/node": "^16.11.26", - "@types/react": "^16.13.1 || ^17.0.0", - "cross-fetch": "^3.1.5", - "msw": "^1.0.0" + "cross-fetch": "^3.1.5" }, "files": [ "dist" diff --git a/plugins/badges/src/api/BadgesClient.ts b/plugins/badges/src/api/BadgesClient.ts index 9a89806d56..9a08db882a 100644 --- a/plugins/badges/src/api/BadgesClient.ts +++ b/plugins/badges/src/api/BadgesClient.ts @@ -18,31 +18,55 @@ import { generatePath } from 'react-router-dom'; import { ResponseError } from '@backstage/errors'; import { Entity, DEFAULT_NAMESPACE } from '@backstage/catalog-model'; import { BadgesApi, BadgeSpec } from './types'; -import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api'; +import { ConfigApi, DiscoveryApi, FetchApi } from '@backstage/core-plugin-api'; export class BadgesClient implements BadgesApi { private readonly discoveryApi: DiscoveryApi; - private readonly identityApi: IdentityApi; + private readonly fetchApi: FetchApi; + private readonly configApi: ConfigApi; constructor(options: { discoveryApi: DiscoveryApi; - identityApi: IdentityApi; + fetchApi: FetchApi; + configApi: ConfigApi; }) { this.discoveryApi = options.discoveryApi; - this.identityApi = options.identityApi; + this.fetchApi = options.fetchApi; + this.configApi = options.configApi; + } + + static fromConfig(options: { + fetchApi: FetchApi; + discoveryApi: DiscoveryApi; + configApi: ConfigApi; + }) { + return new BadgesClient(options); } public async getEntityBadgeSpecs(entity: Entity): Promise { - const entityBadgeSpecsUrl = await this.getEntityBadgeSpecsUrl(entity); - const { token } = await this.identityApi.getCredentials(); - const response = await fetch(entityBadgeSpecsUrl, { - headers: token - ? { - Authorization: `Bearer ${token}`, - } - : undefined, - }); + // Check if obfuscation is enabled in the configuration + const obfuscate = this.configApi.getOptionalBoolean('app.badges.obfuscate'); + if (obfuscate) { + const entityUuidUrl = await this.getEntityUuidUrl(entity); + const entityUuid = await this.getEntityUuid(entityUuidUrl).then(data => { + return data.uuid; + }); + const entityUuidBadgeSpecsUrl = await this.getEntityUuidBadgeSpecsUrl( + entityUuid, + ); + + const response = await this.fetchApi.fetch(entityUuidBadgeSpecsUrl); + if (!response.ok) { + throw await ResponseError.fromResponse(response); + } + + return await response.json(); + } + + // If obfuscation is disabled, get the badge specs directly as the previous implementation + const entityBadgeSpecsUrl = await this.getEntityBadgeSpecsUrl(entity); + const response = await this.fetchApi.fetch(entityBadgeSpecsUrl); if (!response.ok) { throw await ResponseError.fromResponse(response); } @@ -50,14 +74,39 @@ export class BadgesClient implements BadgesApi { return await response.json(); } + private async getEntityUuidUrl(entity: Entity): Promise { + const routeParams = this.getEntityRouteParams(entity); + const path = generatePath(`:namespace/:kind/:name`, routeParams); + const baseUrl = await this.discoveryApi.getBaseUrl('badges'); + const obfuscatedEntityUrl = `${baseUrl}/entity/${path}/obfuscated`; + + return obfuscatedEntityUrl; + } + + private async getEntityUuid(entityUuidUrl: string): Promise { + const responseEntityUuid = await this.fetchApi.fetch(entityUuidUrl); + + if (!responseEntityUuid.ok) { + throw await ResponseError.fromResponse(responseEntityUuid); + } + return await responseEntityUuid.json(); + } + + private async getEntityUuidBadgeSpecsUrl(entityUuid: { + uuid: string; + }): Promise { + const baseUrl = await this.discoveryApi.getBaseUrl('badges'); + return `${baseUrl}/entity/${entityUuid}/badge-specs`; + } + private async getEntityBadgeSpecsUrl(entity: Entity): Promise { const routeParams = this.getEntityRouteParams(entity); const path = generatePath(`:namespace/:kind/:name`, routeParams); - return `${await this.discoveryApi.getBaseUrl( - 'badges', - )}/entity/${path}/badge-specs`; + const baseUrl = await this.discoveryApi.getBaseUrl('badges'); + return `${baseUrl}/entity/${path}/badge-specs`; } + // This function is used to generate the route parameters using the entity kind, namespace and name private getEntityRouteParams(entity: Entity) { return { kind: entity.kind.toLocaleLowerCase('en-US'), diff --git a/plugins/badges/src/plugin.ts b/plugins/badges/src/plugin.ts index 7ef3025458..771e3ed893 100644 --- a/plugins/badges/src/plugin.ts +++ b/plugins/badges/src/plugin.ts @@ -15,11 +15,12 @@ */ import { badgesApiRef, BadgesClient } from './api'; import { + configApiRef, createApiFactory, createComponentExtension, createPlugin, + fetchApiRef, discoveryApiRef, - identityApiRef, } from '@backstage/core-plugin-api'; /** @public */ @@ -28,9 +29,17 @@ export const badgesPlugin = createPlugin({ apis: [ createApiFactory({ api: badgesApiRef, - deps: { discoveryApi: discoveryApiRef, identityApi: identityApiRef }, - factory: ({ discoveryApi, identityApi }) => - new BadgesClient({ discoveryApi, identityApi }), + deps: { + fetchApi: fetchApiRef, + discoveryApi: discoveryApiRef, + configApi: configApiRef, + }, + factory: ({ fetchApi, discoveryApi, configApi }) => + new BadgesClient({ + fetchApi, + discoveryApi, + configApi, + }), }), ], }); diff --git a/plugins/bazaar-backend/CHANGELOG.md b/plugins/bazaar-backend/CHANGELOG.md index 11d820a334..0861db530f 100644 --- a/plugins/bazaar-backend/CHANGELOG.md +++ b/plugins/bazaar-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-bazaar-backend +## 0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-auth-node@0.2.15-next.0 + +## 0.2.8 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + ## 0.2.8-next.1 ### Patch Changes diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index 60e549655e..be621f5d5f 100644 --- a/plugins/bazaar-backend/package.json +++ b/plugins/bazaar-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar-backend", - "version": "0.2.8-next.1", + "version": "0.2.9-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bazaar/CHANGELOG.md b/plugins/bazaar/CHANGELOG.md index 298c684d3e..97fc659f03 100644 --- a/plugins/bazaar/CHANGELOG.md +++ b/plugins/bazaar/CHANGELOG.md @@ -1,5 +1,49 @@ # @backstage/plugin-bazaar +## 0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/cli@0.22.8-next.0 + - @backstage/plugin-catalog@1.11.1-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## 0.2.8 + +### Patch Changes + +- 900880ab7c3: Fixed `validateDOMNesting` warnings +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/cli@0.22.7 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/plugin-catalog@1.11.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.2.8-next.2 + +### Patch Changes + +- 900880ab7c3: Fixed `validateDOMNesting` warnings +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/cli@0.22.7-next.0 + - @backstage/plugin-catalog@1.11.0-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.2.8-next.1 ### Patch Changes diff --git a/plugins/bazaar/dev/__fixtures__/get-projects-response.json b/plugins/bazaar/dev/__fixtures__/get-projects-response.json new file mode 100644 index 0000000000..7aee019a6e --- /dev/null +++ b/plugins/bazaar/dev/__fixtures__/get-projects-response.json @@ -0,0 +1,35 @@ +{ + "status": "ok", + "data": [ + { + "id": 10, + "entity_ref": null, + "title": "Lorem ipsum 1", + "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", + "status": "proposed", + "updated_at": "2023-03-10T12:41:41.941Z", + "community": "", + "size": "medium", + "start_date": null, + "end_date": null, + "responsible": "Responsible Adult 1", + "docs": null, + "members_count": "3" + }, + { + "id": 11, + "entity_ref": null, + "title": "Lorem ipsum 2", + "description": "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud", + "status": "proposed", + "updated_at": "2023-03-09T12:41:41.941Z", + "community": "", + "size": "medium", + "start_date": null, + "end_date": null, + "responsible": "Responsible Adult 2", + "docs": null, + "members_count": "5" + } + ] +} diff --git a/plugins/bazaar/dev/index.tsx b/plugins/bazaar/dev/index.tsx index a4509bc1fc..f2c40df8e1 100644 --- a/plugins/bazaar/dev/index.tsx +++ b/plugins/bazaar/dev/index.tsx @@ -16,10 +16,30 @@ import React from 'react'; import { createDevApp } from '@backstage/dev-utils'; +import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; import { bazaarPlugin, BazaarPage } from '../src/plugin'; +import { bazaarApiRef } from '../src/api'; + +import getProjectsData from './__fixtures__/get-projects-response.json'; createDevApp() .registerPlugin(bazaarPlugin) + .registerApi({ + api: bazaarApiRef, + deps: {}, + factory: () => + ({ + getProjects: async () => getProjectsData, + } as any), + }) + .registerApi({ + api: catalogApiRef, + deps: {}, + factory: () => + ({ + getEntities: () => ({}), + } as CatalogApi), + }) .addPage({ element: , title: 'Root Page', diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index c61db47231..11f8dce0dc 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar", - "version": "0.2.8-next.1", + "version": "0.2.9-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bazaar/src/components/ProjectCard/ProjectCard.tsx b/plugins/bazaar/src/components/ProjectCard/ProjectCard.tsx index 97b247e289..61d1dfebb9 100644 --- a/plugins/bazaar/src/components/ProjectCard/ProjectCard.tsx +++ b/plugins/bazaar/src/components/ProjectCard/ProjectCard.tsx @@ -94,11 +94,7 @@ export const ProjectCard = ({ setOpenCard(true)}> - {title} - - } + title={title} subtitle={`updated ${DateTime.fromISO( new Date(updatedAt!).toISOString(), ).toRelative({ diff --git a/plugins/bazaar/src/components/ProjectPreview/ProjectPreview.tsx b/plugins/bazaar/src/components/ProjectPreview/ProjectPreview.tsx index 8f7160600a..39319b6353 100644 --- a/plugins/bazaar/src/components/ProjectPreview/ProjectPreview.tsx +++ b/plugins/bazaar/src/components/ProjectPreview/ProjectPreview.tsx @@ -15,9 +15,14 @@ */ import React, { ChangeEvent, useState } from 'react'; -import { Content } from '@backstage/core-components'; import { ProjectCard } from '../ProjectCard/ProjectCard'; -import { makeStyles, Grid, TablePagination, GridSize } from '@material-ui/core'; +import { + Box, + makeStyles, + Grid, + TablePagination, + GridSize, +} from '@material-ui/core'; import { BazaarProject } from '../../types'; import { Entity } from '@backstage/catalog-model'; @@ -80,7 +85,7 @@ export const ProjectPreview = ({ } return ( - + {bazaarProjects .slice((page - 1) * rows, rows * page) @@ -101,6 +106,7 @@ export const ProjectPreview = ({ {useTablePagination && ( )} - + ); }; diff --git a/plugins/bitbucket-cloud-common/CHANGELOG.md b/plugins/bitbucket-cloud-common/CHANGELOG.md index c3c31ed392..04b2cc787b 100644 --- a/plugins/bitbucket-cloud-common/CHANGELOG.md +++ b/plugins/bitbucket-cloud-common/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-bitbucket-cloud-common +## 0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.4.5 + ## 0.2.6-next.0 ### Patch Changes diff --git a/plugins/bitbucket-cloud-common/package.json b/plugins/bitbucket-cloud-common/package.json index 7bf2c5791e..a63b9588fb 100644 --- a/plugins/bitbucket-cloud-common/package.json +++ b/plugins/bitbucket-cloud-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-bitbucket-cloud-common", "description": "Common functionalities for bitbucket-cloud plugins", - "version": "0.2.6-next.0", + "version": "0.2.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bitrise/CHANGELOG.md b/plugins/bitrise/CHANGELOG.md index 1ef42a6bbe..cb9f5b1a5e 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-bitrise +## 0.1.46-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.1.45 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.1.45-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.45-next.1 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index 1b3740a058..db4769d6f1 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-bitrise", "description": "A Backstage plugin that integrates towards Bitrise", - "version": "0.1.45-next.1", + "version": "0.1.46-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-aws/CHANGELOG.md b/plugins/catalog-backend-module-aws/CHANGELOG.md index f7ffc5e63c..e4b6e3d63a 100644 --- a/plugins/catalog-backend-module-aws/CHANGELOG.md +++ b/plugins/catalog-backend-module-aws/CHANGELOG.md @@ -1,5 +1,53 @@ # @backstage/plugin-catalog-backend-module-aws +## 0.2.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/integration-aws-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-kubernetes-common@0.6.3 + +## 0.2.0 + +### Minor Changes + +- 1a3b5f1e390: **BREAKING**: AwsOrganizationCloudAccountProcessor.fromConfig now returns a promise instead of the instance directly. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/integration-aws-node@0.1.3 + - @backstage/plugin-kubernetes-common@0.6.3 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + +## 0.1.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-kubernetes-common@0.6.3-next.0 + - @backstage/config@1.0.7 + ## 0.1.19-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-aws/api-report.md b/plugins/catalog-backend-module-aws/api-report.md index 491dbf497e..83b072061b 100644 --- a/plugins/catalog-backend-module-aws/api-report.md +++ b/plugins/catalog-backend-module-aws/api-report.md @@ -3,11 +3,12 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { AwsCredentialIdentity } from '@aws-sdk/types'; +import { AwsCredentialsManager } from '@backstage/integration-aws-node'; import { CatalogProcessor } from '@backstage/plugin-catalog-node'; import { CatalogProcessorEmit } from '@backstage/plugin-catalog-node'; import { CatalogProcessorParser } from '@backstage/plugin-catalog-node'; import { Config } from '@backstage/config'; -import { Credentials } from 'aws-sdk'; import { EntityProvider } from '@backstage/plugin-catalog-node'; import { EntityProviderConnection } from '@backstage/plugin-catalog-node'; import { LocationSpec } from '@backstage/plugin-catalog-common'; @@ -19,11 +20,16 @@ import { UrlReader } from '@backstage/backend-common'; // @public export type AWSCredentialFactory = ( awsAccountId: string, -) => Promise; +) => Promise; // @public export class AwsEKSClusterProcessor implements CatalogProcessor { - constructor(options: { credentialsFactory?: AWSCredentialFactory }); + constructor(options: { + credentialsFactory?: AWSCredentialFactory; + credentialsManager?: AwsCredentialsManager; + }); + // (undocumented) + static fromConfig(configRoot: Config): AwsEKSClusterProcessor; // (undocumented) getProcessorName(): string; // (undocumented) @@ -44,7 +50,7 @@ export class AwsOrganizationCloudAccountProcessor implements CatalogProcessor { options: { logger: Logger; }, - ): AwsOrganizationCloudAccountProcessor; + ): Promise; // (undocumented) getProcessorName(): string; // (undocumented) diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 73bd5123d2..07309f81cc 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-aws", "description": "A Backstage catalog backend module that helps integrate towards AWS", - "version": "0.1.19-next.1", + "version": "0.2.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -45,7 +45,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@aws-sdk/client-s3": "^3.208.0", + "@aws-sdk/client-eks": "^3.310.0", + "@aws-sdk/client-organizations": "^3.310.0", + "@aws-sdk/client-s3": "^3.310.0", + "@aws-sdk/credential-providers": "^3.310.0", + "@aws-sdk/middleware-endpoint": "^3.310.0", + "@aws-sdk/types": "^3.310.0", "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/backend-tasks": "workspace:^", @@ -53,23 +58,23 @@ "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/integration": "workspace:^", + "@backstage/integration-aws-node": "workspace:^", "@backstage/plugin-catalog-common": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", "@backstage/plugin-kubernetes-common": "workspace:^", "@backstage/types": "workspace:^", - "aws-sdk": "^2.840.0", "lodash": "^4.17.21", "p-limit": "^3.0.2", "uuid": "^8.0.0", "winston": "^3.2.1" }, "devDependencies": { - "@aws-sdk/util-stream-node": "^3.208.0", + "@aws-sdk/util-stream-node": "^3.310.0", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/lodash": "^4.14.151", "aws-sdk-client-mock": "^2.0.0", - "aws-sdk-mock": "^5.2.1", + "aws-sdk-client-mock-jest": "^2.0.0", "luxon": "^3.0.0", "yaml": "^2.0.0" }, diff --git a/plugins/catalog-backend-module-aws/src/credentials/AwsCredentials.ts b/plugins/catalog-backend-module-aws/src/credentials/AwsCredentials.ts deleted file mode 100644 index fded78aed4..0000000000 --- a/plugins/catalog-backend-module-aws/src/credentials/AwsCredentials.ts +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2022 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 aws, { Credentials } from 'aws-sdk'; -import { CredentialsOptions } from 'aws-sdk/lib/credentials'; - -export class AwsCredentials { - /** - * If accessKeyId and secretAccessKey are missing, the DefaultAWSCredentialsProviderChain will be used: - * https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html - */ - static create( - config: { - accessKeyId?: string; - secretAccessKey?: string; - roleArn?: string; - externalId?: string; - }, - roleSessionName: string, - ): Credentials | CredentialsOptions | undefined { - if (!config) { - return undefined; - } - - const accessKeyId = config.accessKeyId; - const secretAccessKey = config.secretAccessKey; - let explicitCredentials: Credentials | undefined; - - if (accessKeyId && secretAccessKey) { - explicitCredentials = new Credentials({ - accessKeyId, - secretAccessKey, - }); - } - - const roleArn = config.roleArn; - if (roleArn) { - return new aws.ChainableTemporaryCredentials({ - masterCredentials: explicitCredentials, - params: { - RoleArn: roleArn, - RoleSessionName: roleSessionName, - ExternalId: config.externalId, - }, - }); - } - - return explicitCredentials; - } -} diff --git a/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.test.ts b/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.test.ts index ecf3b1a961..6cec6ed66d 100644 --- a/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.test.ts +++ b/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.test.ts @@ -15,24 +15,28 @@ */ import { AwsEKSClusterProcessor } from './AwsEKSClusterProcessor'; -import AWSMock from 'aws-sdk-mock'; -import aws from 'aws-sdk'; +import { mockClient } from 'aws-sdk-client-mock'; +import { + ListClustersResponse, + DescribeClusterResponse, + ListClustersCommand, + DescribeClusterCommand, + EKSClient, +} from '@aws-sdk/client-eks'; describe('AwsEKSClusterProcessor', () => { - AWSMock.setSDKInstance(aws); - describe('readLocation', () => { const processor = new (AwsEKSClusterProcessor as any)({}); const location = { type: 'aws-eks', target: '957140518395/us-west-2' }; const emit = jest.fn(); it('generates cluster correctly', async () => { - const clusters: aws.EKS.Types.ListClustersResponse = { + const clusters: ListClustersResponse = { clusters: ['backstage-test'], nextToken: undefined, }; - const cluster: aws.EKS.Types.DescribeClusterResponse = { + const cluster: DescribeClusterResponse = { cluster: { name: 'backstage-test', arn: 'arn:aws:1', @@ -42,9 +46,10 @@ describe('AwsEKSClusterProcessor', () => { }, }, }; + const mock = mockClient(EKSClient); - AWSMock.mock('EKS', 'listClusters', clusters); - AWSMock.mock('EKS', 'describeCluster', cluster); + mock.on(ListClustersCommand).resolves(clusters); + mock.on(DescribeClusterCommand).resolves(cluster); await processor.readLocation(location, false, emit); diff --git a/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.ts b/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.ts index 05c85c7426..4a19b9eb7f 100644 --- a/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.ts +++ b/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.ts @@ -24,8 +24,14 @@ import { ANNOTATION_KUBERNETES_API_SERVER_CA, ANNOTATION_KUBERNETES_AUTH_PROVIDER, } from '@backstage/plugin-kubernetes-common'; -import { Credentials, EKS } from 'aws-sdk'; +import { EKS } from '@aws-sdk/client-eks'; import { AWSCredentialFactory } from '../types'; +import { AwsCredentialIdentity, Provider } from '@aws-sdk/types'; +import { + AwsCredentialsManager, + DefaultAwsCredentialsManager, +} from '@backstage/integration-aws-node'; +import { Config } from '@backstage/config'; const ACCOUNTID_ANNOTATION: string = 'amazonaws.com/account-id'; const ARN_ANNOTATION: string = 'amazonaws.com/arn'; @@ -39,9 +45,22 @@ const ARN_ANNOTATION: string = 'amazonaws.com/arn'; */ export class AwsEKSClusterProcessor implements CatalogProcessor { private credentialsFactory?: AWSCredentialFactory; + private credentialsManager?: AwsCredentialsManager; - constructor(options: { credentialsFactory?: AWSCredentialFactory }) { + static fromConfig(configRoot: Config): AwsEKSClusterProcessor { + const awsCredentaislManager = + DefaultAwsCredentialsManager.fromConfig(configRoot); + return new AwsEKSClusterProcessor({ + credentialsManager: awsCredentaislManager, + }); + } + + constructor(options: { + credentialsFactory?: AWSCredentialFactory; + credentialsManager?: AwsCredentialsManager; + }) { this.credentialsFactory = options.credentialsFactory; + this.credentialsManager = options.credentialsManager; } getProcessorName(): string { @@ -73,20 +92,30 @@ export class AwsEKSClusterProcessor implements CatalogProcessor { ); } - let credentials: Credentials | undefined; + let credentials: AwsCredentialIdentity | undefined; if (this.credentialsFactory) { credentials = await this.credentialsFactory(accountId); } - const eksClient = new EKS({ credentials, region }); - const clusters = await eksClient.listClusters({}).promise(); + let providerFunction: (() => Provider) | undefined; + if (this.credentialsManager) { + const credentialsProvider = + await this.credentialsManager.getCredentialProvider({ accountId }); + providerFunction = () => credentialsProvider.sdkCredentialProvider; + } + + const eksClient = new EKS({ + credentials, + credentialDefaultProvider: providerFunction, + }); + const clusters = await eksClient.listClusters({}); if (clusters.clusters === undefined) { return true; } const results = clusters.clusters - .map(cluster => eksClient.describeCluster({ name: cluster }).promise()) + .map(cluster => eksClient.describeCluster({ name: cluster })) .map(async describedClusterPromise => { const describedCluster = await describedClusterPromise; if (describedCluster.cluster) { diff --git a/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.test.ts b/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.test.ts index b9b8ba7741..458a1f3531 100644 --- a/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.test.ts +++ b/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.test.ts @@ -14,7 +14,13 @@ * limitations under the License. */ +import { mockClient } from 'aws-sdk-client-mock'; +import 'aws-sdk-client-mock-jest'; import { AwsOrganizationCloudAccountProcessor } from './AwsOrganizationCloudAccountProcessor'; +import { + ListAccountsCommand, + OrganizationsClient, +} from '@aws-sdk/client-organizations'; describe('AwsOrganizationCloudAccountProcessor', () => { describe('readLocation', () => { @@ -23,26 +29,21 @@ describe('AwsOrganizationCloudAccountProcessor', () => { }); const location = { type: 'aws-cloud-accounts', target: '' }; const emit = jest.fn(); - const listAccounts = jest.fn(); + const mock = mockClient(OrganizationsClient); - processor.organizations.listAccounts = listAccounts; - afterEach(() => jest.resetAllMocks()); + afterEach(() => { + jest.resetAllMocks(); + }); it('generates component entities for accounts', async () => { - listAccounts.mockImplementation(() => { - return { - async promise() { - return { - Accounts: [ - { - Arn: 'arn:aws:organizations::192594491037:account/o-1vl18kc5a3/957140518395', - Name: 'testaccount', - }, - ], - NextToken: undefined, - }; + mock.on(ListAccountsCommand).resolves({ + Accounts: [ + { + Arn: 'arn:aws:organizations::192594491037:account/o-1vl18kc5a3/957140518395', + Name: 'testaccount', }, - }; + ], + NextToken: undefined, }); await processor.readLocation(location, false, emit); expect(emit).toHaveBeenCalledWith({ @@ -74,24 +75,18 @@ describe('AwsOrganizationCloudAccountProcessor', () => { type: 'aws-cloud-accounts', target: 'o-1vl18kc5a3', }; - listAccounts.mockImplementation(() => { - return { - async promise() { - return { - Accounts: [ - { - Arn: 'arn:aws:organizations::192594491037:account/o-1vl18kc5a3/957140518395', - Name: 'testaccount', - }, - { - Arn: 'arn:aws:organizations::192594491037:account/o-zzzzzzzzz/957140518395', - Name: 'testaccount2', - }, - ], - NextToken: undefined, - }; + mock.on(ListAccountsCommand).resolves({ + Accounts: [ + { + Arn: 'arn:aws:organizations::192594491037:account/o-1vl18kc5a3/957140518395', + Name: 'testaccount', }, - }; + { + Arn: 'arn:aws:organizations::192594491037:account/o-zzzzzzzzz/957140518395', + Name: 'testaccount2', + }, + ], + NextToken: undefined, }); await processor.readLocation(locationTest, false, emit); expect(emit).toHaveBeenCalledTimes(1); diff --git a/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.ts b/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.ts index c0ba1e3e98..264fa7a50d 100644 --- a/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.ts +++ b/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.ts @@ -22,13 +22,17 @@ import { processingResult, } from '@backstage/plugin-catalog-node'; import { LocationSpec } from '@backstage/plugin-catalog-common'; -import AWS, { Credentials, Organizations } from 'aws-sdk'; -import { Account, ListAccountsResponse } from 'aws-sdk/clients/organizations'; -import { Logger } from 'winston'; import { - AwsOrganizationProviderConfig, - readAwsOrganizationConfig, -} from '../awsOrganization/config'; + Account, + ListAccountsResponse, + Organizations, +} from '@aws-sdk/client-organizations'; +import { Logger } from 'winston'; +import { readAwsOrganizationConfig } from '../awsOrganization/config'; +import { + AwsCredentialProvider, + DefaultAwsCredentialsManager, +} from '@backstage/integration-aws-node'; const AWS_ORGANIZATION_REGION = 'us-east-1'; const LOCATION_TYPE = 'aws-cloud-accounts'; @@ -47,39 +51,31 @@ const ORGANIZATION_ANNOTATION = 'amazonaws.com/organization-id'; */ export class AwsOrganizationCloudAccountProcessor implements CatalogProcessor { private readonly organizations: Organizations; - private readonly provider: AwsOrganizationProviderConfig; + private readonly logger: Logger; - static fromConfig(config: Config, options: { logger: Logger }) { + static async fromConfig(config: Config, options: { logger: Logger }) { const c = config.getOptionalConfig('catalog.processors.awsOrganization'); - return new AwsOrganizationCloudAccountProcessor({ - ...options, - provider: c ? readAwsOrganizationConfig(c) : {}, + const orgConfig = c ? readAwsOrganizationConfig(c) : undefined; + const awsCredentialsManager = + DefaultAwsCredentialsManager.fromConfig(config); + const credProvider = await awsCredentialsManager.getCredentialProvider({ + arn: orgConfig?.roleArn, }); - } - - private static buildCredentials( - config: AwsOrganizationProviderConfig, - ): Credentials | undefined { - const roleArn = config.roleArn; - if (!roleArn) { - return undefined; - } - - return new AWS.ChainableTemporaryCredentials({ - params: { - RoleSessionName: 'backstage-aws-organization-processor', - RoleArn: roleArn, - }, - }); - } - - private constructor(options: { provider: AwsOrganizationProviderConfig }) { - this.provider = options.provider; - const credentials = AwsOrganizationCloudAccountProcessor.buildCredentials( - this.provider, + return new AwsOrganizationCloudAccountProcessor( + credProvider, + options.logger, ); - this.organizations = new AWS.Organizations({ - credentials, + } + + private constructor( + private readonly credProvider: AwsCredentialProvider, + logger: Logger, + ) { + this.logger = logger?.child({ + target: this.getProcessorName(), + }); + this.organizations = new Organizations({ + credentialDefaultProvider: () => this.credProvider.sdkCredentialProvider, region: AWS_ORGANIZATION_REGION, }); // Only available in us-east-1 } @@ -97,6 +93,8 @@ export class AwsOrganizationCloudAccountProcessor implements CatalogProcessor { return false; } + this.logger?.info('Discovering AWS Organization Account objects'); + (await this.getAwsAccounts()) .map(account => this.mapAccountToComponent(account)) .filter(entity => { @@ -143,9 +141,8 @@ export class AwsOrganizationCloudAccountProcessor implements CatalogProcessor { let nextToken = undefined; while (isInitialAttempt || nextToken) { isInitialAttempt = false; - const orgAccounts: ListAccountsResponse = await this.organizations - .listAccounts({ NextToken: nextToken }) - .promise(); + const orgAccounts: ListAccountsResponse = + await this.organizations.listAccounts({ NextToken: nextToken }); if (orgAccounts.Accounts) { awsAccounts = awsAccounts.concat(orgAccounts.Accounts); } diff --git a/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.test.ts b/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.test.ts index 821fb6d4f4..e9e17ad76a 100644 --- a/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.test.ts +++ b/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.test.ts @@ -23,8 +23,9 @@ import { import { ConfigReader } from '@backstage/config'; import { EntityProviderConnection } from '@backstage/plugin-catalog-node'; import { AwsS3EntityProvider } from './AwsS3EntityProvider'; -import aws from 'aws-sdk'; -import AWSMock from 'aws-sdk-mock'; +import { mockClient } from 'aws-sdk-client-mock'; +import 'aws-sdk-client-mock-jest'; +import { ListObjectsV2Command, S3Client } from '@aws-sdk/client-s3'; class PersistingTaskRunner implements TaskRunner { private tasks: TaskInvocationDefinition[] = []; @@ -42,38 +43,39 @@ class PersistingTaskRunner implements TaskRunner { const logger = getVoidLogger(); describe('AwsS3EntityProvider', () => { - AWSMock.setSDKInstance(aws); - const createObjectList = (keys: string[]): aws.S3.ObjectList => { + const createObjectList = (keys: string[]) => { const objects = keys.map(key => { return { Key: key, - } as aws.S3.Types.Object; + }; }); - - return objects as aws.S3.ObjectList; + return objects; }; const keys = ['key1.yaml', 'key2.yaml', 'key3.yaml', 'key 4.yaml']; + const mock = mockClient(S3Client); - AWSMock.mock('S3', 'listObjectsV2', async req => { - const prefix = req.Prefix ?? ''; + beforeEach(() => { + mock.on(ListObjectsV2Command).callsFake(async req => { + const prefix = req.Prefix ?? ''; + + if (!req.ContinuationToken) { + return { + Contents: createObjectList( + keys + .slice(0, Math.ceil(keys.length / 2)) + .map(key => `${prefix}${key}`), + ), + NextContinuationToken: 'next-token', + }; + } - if (!req.ContinuationToken) { return { Contents: createObjectList( - keys - .slice(0, Math.ceil(keys.length / 2)) - .map(key => `${prefix}${key}`), + keys.slice(Math.ceil(keys.length / 2)).map(key => `${prefix}${key}`), ), - NextContinuationToken: 'next-token', - } as aws.S3.Types.ListObjectsV2Output; - } - - return { - Contents: createObjectList( - keys.slice(Math.ceil(keys.length / 2)).map(key => `${prefix}${key}`), - ), - } as aws.S3.Types.ListObjectsV2Output; + }; + }); }); afterEach(() => { @@ -103,7 +105,9 @@ describe('AwsS3EntityProvider', () => { }); const schedulingConfig: Record = {}; - + const normalizedExpectedBaseUrl = expectedBaseUrl.endsWith('/') + ? expectedBaseUrl + : `${expectedBaseUrl}/`; const schedule = new PersistingTaskRunner(); const entityProviderConnection: EntityProviderConnection = { applyMutation: jest.fn(), @@ -131,7 +135,7 @@ describe('AwsS3EntityProvider', () => { await (taskDef.fn as () => Promise)(); const expectedEntities = keys.map(key => { - const url = encodeURI(`${expectedBaseUrl}${key}`); + const url = encodeURI(`${normalizedExpectedBaseUrl}${key}`); return { entity: { apiVersion: 'backstage.io/v1alpha1', @@ -161,6 +165,25 @@ describe('AwsS3EntityProvider', () => { // eslint-disable-next-line jest/expect-expect it('apply full update on scheduled execution', async () => { + return expectMutation( + 'regionalStatic', + { + bucketName: 'bucket-1', + prefix: 'sub/dir/', + region: 'eu-west-1', + }, + 'https://bucket-1.s3.eu-west-1.amazonaws.com/sub/dir/', + { + 'key1.yaml': 'generated-8ece85ad90200c6577b99f553dcbedde05fa34bb', + 'key2.yaml': 'generated-6b54c6aaa44696f5e91ce0f54fb27bf837549d11', + 'key3.yaml': 'generated-88c703cf1aa66913db4033b029adc0b174574646', + 'key 4.yaml': 'generated-2b7e068bb4ec818c14f179a1e721843fc2dbc5f9', + }, + ); + }); + + // eslint-disable-next-line jest/expect-expect + it('apply full update on scheduled execution force path style', async () => { return expectMutation( 'regionalStatic', { @@ -175,11 +198,72 @@ describe('AwsS3EntityProvider', () => { 'key3.yaml': 'generated-8d75f78ed9fa618ce433b226dc24eeab441f3a2d', 'key 4.yaml': 'generated-1e0249dcb5805fc2ce6ac2d3c4d2a3ef4f1270c0', }, + { + s3ForcePathStyle: true, + }, ); }); // eslint-disable-next-line jest/expect-expect - it('us-east-1 has region-less URLs', async () => { + it('apply full update on scheduled execution no prefix', async () => { + return expectMutation( + 'regionalStatic', + { + bucketName: 'bucket-1', + region: 'eu-west-1', + }, + 'https://bucket-1.s3.eu-west-1.amazonaws.com/', + { + 'key1.yaml': 'generated-ac6d99e56e0fbd6bf3719a5182f37bfa84b1cddc', + 'key2.yaml': 'generated-cc3e1145496cd95bf3898687bb5b7d2991a7b7fd', + 'key3.yaml': 'generated-a197557b0cb89d14ac1297231ed930bd4c40b664', + 'key 4.yaml': 'generated-a774e6c1d1c7ee511b7d79ebb99b08a39cf439c4', + }, + ); + }); + + // eslint-disable-next-line jest/expect-expect + it('apply full update on scheduled execution force path style no prefix', async () => { + return expectMutation( + 'regionalStatic', + { + bucketName: 'bucket-1', + region: 'eu-west-1', + }, + 'https://s3.eu-west-1.amazonaws.com/bucket-1', + { + 'key1.yaml': 'generated-b390cd4de7ff00f6d51426870fc0e685029fbf09', + 'key2.yaml': 'generated-15ebeb1e53ffe71ea93f037076aefcdc5cc5e617', + 'key3.yaml': 'generated-fd0a33e70bafd707a60139decbd0383361ab3b4e', + 'key 4.yaml': 'generated-ac574fb266d9c8bd983b25a208c538e4ad2c1d06', + }, + { + s3ForcePathStyle: true, + }, + ); + }); + + // eslint-disable-next-line jest/expect-expect + it('apply full update on scheduled execution bucket with dot in it', async () => { + return expectMutation( + 'regionalStatic', + { + bucketName: 'bucket.1', + prefix: 'sub/dir/', + region: 'eu-west-1', + }, + 'https://s3.eu-west-1.amazonaws.com/bucket.1/sub/dir/', + { + 'key1.yaml': 'generated-651b5851d4670b7d5bb9a319d8f6eb295092e4ad', + 'key2.yaml': 'generated-ccddcdc3ad814aea072883118f3a9d0ac39a161e', + 'key3.yaml': 'generated-b2b8548903aa764544ab79dc81ab5093e6e4ba83', + 'key 4.yaml': 'generated-aafa9cc0422f5e8ccce1616dc0c74fa94f692af3', + }, + ); + }); + + // eslint-disable-next-line jest/expect-expect + it('us-east-1 does not have region-less URLs', async () => { return expectMutation( 'usEast1', { @@ -187,12 +271,12 @@ describe('AwsS3EntityProvider', () => { prefix: 'sub/dir/', region: 'us-east-1', }, - 'https://s3.amazonaws.com/bucket-1/sub/dir/', + 'https://bucket-1.s3.us-east-1.amazonaws.com/sub/dir/', { - 'key1.yaml': 'generated-f7e3f1c89f62cbf0d82db16452faaa7c040fc331', - 'key2.yaml': 'generated-925173f7dba1acaa73cac5ef4d10c3ed7660aa25', - 'key3.yaml': 'generated-d94cf017911ed7fb3be4a62a3dae1f5202879de3', - 'key 4.yaml': 'generated-f917fca0cfacc2be478ca2a3cff94d00917a1cde', + 'key1.yaml': 'generated-980e6ad47fbfbfeead708a9c7c87331b7540296a', + 'key2.yaml': 'generated-266794d8e789089dddba2b42cd79e70b149aa61c', + 'key3.yaml': 'generated-96f0cdcd7e33aa687c19d160ec7d5b1975cb9ea1', + 'key 4.yaml': 'generated-4f6d3ffb232e4a5b82c3a52549e4c36dab1c2f8d', }, ); }); @@ -209,18 +293,60 @@ describe('AwsS3EntityProvider', () => { bucketName: 'bucket-1', prefix: 'sub/dir/', }, - 'https://s3.eu-central-1.amazonaws.com/bucket-1/sub/dir/', + 'https://bucket-1.s3.eu-central-1.amazonaws.com/sub/dir/', { - 'key1.yaml': 'generated-285d144b5c1e24e801b97f61f794d566dabc7236', - 'key2.yaml': 'generated-36b78d7fa69690059797d4cc4f40c2a5eaed1d6d', - 'key3.yaml': 'generated-a39ad804bf65993cbc0f3810ff128a3c91daf768', - 'key 4.yaml': 'generated-bd7622ac86c313cb812d90e335b2f5f6bff14670', + 'key1.yaml': 'generated-bb17a9f9b420edd93137692f000b2d443a29239c', + 'key2.yaml': 'generated-b4559ecc8b615407e421dbaa3fcb9338e977b8ac', + 'key3.yaml': 'generated-bb3d500a6f8b351b0eed1aec77ebce65c1ab41fb', + 'key 4.yaml': 'generated-686de87f5882f6558b43280c5b6047e485199e88', }, ); }); // eslint-disable-next-line jest/expect-expect it('custom endpoint', async () => { + return expectMutation( + 'customEndpoint', + { + bucketName: 'bucket-1', + prefix: 'sub/dir/', + }, + 'http://bucket-1.localhost:1234/sub/dir/', + { + 'key1.yaml': 'generated-79625971ead9c39c91b0bfef4d7c748325e31234', + 'key2.yaml': 'generated-eeae95f16605d3afdc615436c18c9fbd35781299', + 'key3.yaml': 'generated-692976561563c3fa55889ad090363716c7b7e915', + 'key 4.yaml': 'generated-c8f92ea0eb96c355b7e56cbc461cef29f830747e', + }, + { + endpoint: 'http://localhost:1234/', + }, + ); + }); + + // eslint-disable-next-line jest/expect-expect + it('custom endpoint bucket dot', async () => { + return expectMutation( + 'customEndpoint', + { + bucketName: 'bucket.1', + prefix: 'sub/dir/', + }, + 'http://localhost:1234/bucket.1/sub/dir/', + { + 'key1.yaml': 'generated-07be77ac8626ac76a924414e0edf5ce66d3e0b27', + 'key2.yaml': 'generated-47295ada3c894cf9bac0d570a34d909244ea2f74', + 'key3.yaml': 'generated-30e98f3ebd350f3b618acd024199b5f31545495d', + 'key 4.yaml': 'generated-b71bc7661b92cef0db62c9652912fd5e4b245aa7', + }, + { + endpoint: 'http://localhost:1234/', + }, + ); + }); + + // eslint-disable-next-line jest/expect-expect + it('custom endpoint force path style', async () => { return expectMutation( 'customEndpoint', { @@ -235,7 +361,8 @@ describe('AwsS3EntityProvider', () => { 'key 4.yaml': 'generated-659f17a2429f107db04850f9081e3e9c56084aeb', }, { - endpoint: 'http://localhost:1234', + endpoint: 'http://localhost:1234/', + s3ForcePathStyle: true, }, ); }); @@ -305,12 +432,12 @@ describe('AwsS3EntityProvider', () => { }, }, }, - 'https://s3.eu-west-1.amazonaws.com/bucket-1/sub/dir/', + 'https://bucket-1.s3.eu-west-1.amazonaws.com/sub/dir/', { - 'key1.yaml': 'generated-7f6d5861b0b3401a38b5fe62e6c7ca11da5fd6d8', - 'key2.yaml': 'generated-a290be145586042af7d80715626399c9d661718d', - 'key3.yaml': 'generated-8d75f78ed9fa618ce433b226dc24eeab441f3a2d', - 'key 4.yaml': 'generated-1e0249dcb5805fc2ce6ac2d3c4d2a3ef4f1270c0', + 'key1.yaml': 'generated-8ece85ad90200c6577b99f553dcbedde05fa34bb', + 'key2.yaml': 'generated-6b54c6aaa44696f5e91ce0f54fb27bf837549d11', + 'key3.yaml': 'generated-88c703cf1aa66913db4033b029adc0b174574646', + 'key 4.yaml': 'generated-2b7e068bb4ec818c14f179a1e721843fc2dbc5f9', }, undefined, true, diff --git a/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.ts b/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.ts index 8212f9279a..4a87a42e75 100644 --- a/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.ts +++ b/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.ts @@ -23,13 +23,20 @@ import { locationSpecToLocationEntity, } from '@backstage/plugin-catalog-node'; import { LocationSpec } from '@backstage/plugin-catalog-common'; -import { AwsCredentials } from '../credentials/AwsCredentials'; import { readAwsS3Configs } from './config'; import { AwsS3Config } from './types'; -import { S3 } from 'aws-sdk'; -import { ListObjectsV2Output } from 'aws-sdk/clients/s3'; +import { + ListObjectsV2Command, + ListObjectsV2Output, + S3, +} from '@aws-sdk/client-s3'; import * as uuid from 'uuid'; import { Logger } from 'winston'; +import { getEndpointFromInstructions } from '@aws-sdk/middleware-endpoint'; +import { + AwsCredentialsManager, + DefaultAwsCredentialsManager, +} from '@backstage/integration-aws-node'; // TODO: event-based updates using S3 events (+ queue like SQS)? /** @@ -41,9 +48,10 @@ import { Logger } from 'winston'; */ export class AwsS3EntityProvider implements EntityProvider { private readonly logger: Logger; - private readonly s3: S3; + private s3?: S3; private readonly scheduleFn: () => Promise; private connection?: EntityProviderConnection; + private endpoint?: string; static fromConfig( configRoot: Config, @@ -78,7 +86,8 @@ export class AwsS3EntityProvider implements EntityProvider { `No schedule provided neither via code nor config for awsS3-provider:${providerConfig.id}.`, ); } - + const awsCredentialsManager = + DefaultAwsCredentialsManager.fromConfig(configRoot); const taskRunner = options.schedule ?? options.scheduler!.createScheduledTaskRunner(providerConfig.schedule!); @@ -86,6 +95,7 @@ export class AwsS3EntityProvider implements EntityProvider { return new AwsS3EntityProvider( providerConfig, integration, + awsCredentialsManager, options.logger, taskRunner, ); @@ -94,7 +104,8 @@ export class AwsS3EntityProvider implements EntityProvider { private constructor( private readonly config: AwsS3Config, - integration: AwsS3Integration, + private readonly integration: AwsS3Integration, + private readonly awsCredentialsManager: AwsCredentialsManager, logger: Logger, taskRunner: TaskRunner, ) { @@ -102,17 +113,6 @@ export class AwsS3EntityProvider implements EntityProvider { target: this.getProviderName(), }); - this.s3 = new S3({ - apiVersion: '2006-03-01', - credentials: AwsCredentials.create( - integration.config, - 'backstage-aws-s3-provider', - ), - endpoint: integration.config.endpoint, - region: this.config.region, - s3ForcePathStyle: integration.config.s3ForcePathStyle, - }); - this.scheduleFn = this.createScheduleFn(taskRunner); } @@ -146,6 +146,28 @@ export class AwsS3EntityProvider implements EntityProvider { /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.connect} */ async connect(connection: EntityProviderConnection): Promise { this.connection = connection; + const credProvider = + await this.awsCredentialsManager.getCredentialProvider(); + this.s3 = new S3({ + apiVersion: '2006-03-01', + credentialDefaultProvider: () => credProvider.sdkCredentialProvider, + endpoint: this.integration.config.endpoint, + region: this.config.region, + forcePathStyle: this.integration.config.s3ForcePathStyle, + }); + + // https://github.com/aws/aws-sdk-js-v3/issues/4122#issuecomment-1298968804 + const endpoint = await getEndpointFromInstructions( + { + Bucket: this.config.bucketName, + }, + ListObjectsV2Command, + this.s3.config as unknown as Record, + ); + if (endpoint?.url) + this.endpoint = endpoint.url.href.endsWith('/') + ? endpoint.url.href + : `${endpoint.url.href}/`; await this.scheduleFn(); } @@ -175,18 +197,21 @@ export class AwsS3EntityProvider implements EntityProvider { } private async listAllObjectKeys(): Promise { + if (!this.s3) { + throw new Error('Not initialized'); + } + const keys: string[] = []; let continuationToken: string | undefined = undefined; let output: ListObjectsV2Output; do { - const request = this.s3.listObjectsV2({ + output = await this.s3.listObjectsV2({ Bucket: this.config.bucketName, ContinuationToken: continuationToken, Prefix: this.config.prefix, }); - output = await request.promise(); if (output.Contents) { output.Contents.forEach(item => { if (item.Key && !item.Key.endsWith('/')) { @@ -209,9 +234,6 @@ export class AwsS3EntityProvider implements EntityProvider { } private createObjectUrl(key: string): string { - const bucketName = this.config.bucketName; - const endpoint = this.s3.endpoint.href; - - return encodeURI(`${endpoint}${bucketName}/${key}`); + return new URL(key, this.endpoint).href; } } diff --git a/plugins/catalog-backend-module-aws/src/types.ts b/plugins/catalog-backend-module-aws/src/types.ts index 3d9df38181..23460c104e 100644 --- a/plugins/catalog-backend-module-aws/src/types.ts +++ b/plugins/catalog-backend-module-aws/src/types.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Credentials } from 'aws-sdk'; +import { AwsCredentialIdentity } from '@aws-sdk/types'; /** * A factory for providing user-specified AWS credentials for a given AWS account. @@ -22,4 +22,4 @@ import { Credentials } from 'aws-sdk'; */ export type AWSCredentialFactory = ( awsAccountId: string, -) => Promise; +) => Promise; diff --git a/plugins/catalog-backend-module-azure/CHANGELOG.md b/plugins/catalog-backend-module-azure/CHANGELOG.md index e8458d82e7..1783335c0f 100644 --- a/plugins/catalog-backend-module-azure/CHANGELOG.md +++ b/plugins/catalog-backend-module-azure/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-catalog-backend-module-azure +## 0.1.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + ## 0.1.16-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index 2e2ff96e7e..eb94c176f3 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-azure", "description": "A Backstage catalog backend module that helps integrate towards Azure", - "version": "0.1.16-next.1", + "version": "0.1.17-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md index af6e6c3a7f..c11afef754 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-catalog-backend-module-bitbucket-cloud +## 0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-bitbucket-cloud-common@0.2.6 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-events-node@0.2.7-next.0 + +## 0.1.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/plugin-bitbucket-cloud-common@0.2.6 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-events-node@0.2.6 + ## 0.1.12-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 77df5b12b4..946a50d6a5 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-cloud", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket Cloud", - "version": "0.1.12-next.1", + "version": "0.1.13-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md index 3c9e51b08e..5609b696c4 100644 --- a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-catalog-backend-module-bitbucket-server +## 0.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## 0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + ## 0.1.10-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index 68960fbf81..cbb4c89e04 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-server", - "version": "0.1.10-next.1", + "version": "0.1.11-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md index 0193d551a5..c4bf6ca2e2 100644 --- a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-catalog-backend-module-bitbucket +## 0.2.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.6 + +## 0.2.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.6 + ## 0.2.12-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket/package.json b/plugins/catalog-backend-module-bitbucket/package.json index 64269a9102..2efd5558ae 100644 --- a/plugins/catalog-backend-module-bitbucket/package.json +++ b/plugins/catalog-backend-module-bitbucket/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket", - "version": "0.2.12-next.1", + "version": "0.2.13-next.0", "deprecated": true, "main": "src/index.ts", "types": "src/index.ts", diff --git a/plugins/catalog-backend-module-gerrit/CHANGELOG.md b/plugins/catalog-backend-module-gerrit/CHANGELOG.md index ea3d4af960..9f22598c98 100644 --- a/plugins/catalog-backend-module-gerrit/CHANGELOG.md +++ b/plugins/catalog-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-catalog-backend-module-gerrit +## 0.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## 0.1.13 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + ## 0.1.13-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index 22bc3a95e5..f104b894f2 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gerrit", - "version": "0.1.13-next.1", + "version": "0.1.14-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-github/CHANGELOG.md b/plugins/catalog-backend-module-github/CHANGELOG.md index f54a55f9e9..42ec45f0d1 100644 --- a/plugins/catalog-backend-module-github/CHANGELOG.md +++ b/plugins/catalog-backend-module-github/CHANGELOG.md @@ -1,5 +1,66 @@ # @backstage/plugin-catalog-backend-module-github +## 0.3.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-backend@1.9.2-next.0 + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-events-node@0.2.7-next.0 + +## 0.3.0 + +### Minor Changes + +- 970678adbe2: Implement events support for `GithubMultiOrgEntityProvider` + + **BREAKING:** Passing in a custom `teamTransformer` will now correctly completely override the default transformer behavior + +### Patch Changes + +- 78bb674a713: Fixed bug in queryWithPaging that caused secondary rate limit errors in GitHub with organizations having more than 1000 repositories. This change makes one request per second to avoid concurrency issues. +- bd101cefd37: Updated the `team.edited` event emitted from `GithubOrgEntityProvider` to also include teams description. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.1 + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-events-node@0.2.6 + +## 0.3.0-next.2 + +### Minor Changes + +- 970678adbe2: Implement events support for `GithubMultiOrgEntityProvider` + + **BREAKING:** Passing in a custom `teamTransformer` will now correctly completely override the default transformer behavior + +### Patch Changes + +- bd101cefd37: Updated the `team.edited` event emitted from `GithubOrgEntityProvider` to also include teams description. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.1-next.2 + - @backstage/config@1.0.7 + ## 0.2.8-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-github/api-report.md b/plugins/catalog-backend-module-github/api-report.md index 0698fae8a0..7b944b33a9 100644 --- a/plugins/catalog-backend-module-github/api-report.md +++ b/plugins/catalog-backend-module-github/api-report.md @@ -10,6 +10,7 @@ import { Config } from '@backstage/config'; import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-node'; import { EntityProviderConnection } from '@backstage/plugin-catalog-node'; +import { EventBroker } from '@backstage/plugin-events-node'; import { EventParams } from '@backstage/plugin-events-node'; import { EventSubscriber } from '@backstage/plugin-events-node'; import { GithubCredentialsProvider } from '@backstage/integration'; @@ -158,6 +159,7 @@ export class GithubMultiOrgEntityProvider implements EntityProvider { // @public export interface GithubMultiOrgEntityProviderOptions { + eventBroker?: EventBroker; githubCredentialsProvider?: GithubCredentialsProvider; githubUrl: string; id: string; diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index 5b29baa05c..f4cd2d1e0b 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-github", "description": "A Backstage catalog backend module that helps integrate towards GitHub", - "version": "0.2.8-next.1", + "version": "0.3.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-github/src/lib/github.test.ts b/plugins/catalog-backend-module-github/src/lib/github.test.ts index df4565a174..7a0a29e098 100644 --- a/plugins/catalog-backend-module-github/src/lib/github.test.ts +++ b/plugins/catalog-backend-module-github/src/lib/github.test.ts @@ -21,6 +21,7 @@ import { graphql as graphqlMsw } from 'msw'; import { setupServer } from 'msw/node'; import { TeamTransformer, UserTransformer } from './defaultTransformers'; import { + getOrganizationsFromUser, getOrganizationTeams, getOrganizationUsers, getTeamMembers, @@ -448,6 +449,37 @@ describe('github', () => { }); }); + describe('getOrganizationsFromUser', () => { + it('reads orgs from user', async () => { + const input: QueryResponse = { + user: { + organizations: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + login: 'a', + }, + { + login: 'b', + }, + { + login: 'c', + }, + ], + }, + }, + }; + + server.use( + graphqlMsw.query('orgs', (_req, res, ctx) => res(ctx.data(input))), + ); + + await expect(getOrganizationsFromUser(graphql, 'foo')).resolves.toEqual({ + orgs: ['a', 'b', 'c'], + }); + }); + }); + describe('getTeamMembers', () => { it('reads team members', async () => { const input: QueryResponse = { diff --git a/plugins/catalog-backend-module-github/src/lib/github.ts b/plugins/catalog-backend-module-github/src/lib/github.ts index d0b629092a..412b751c38 100644 --- a/plugins/catalog-backend-module-github/src/lib/github.ts +++ b/plugins/catalog-backend-module-github/src/lib/github.ts @@ -33,6 +33,7 @@ import { DeferredEntity } from '@backstage/plugin-catalog-node'; export type QueryResponse = { organization?: OrganizationResponse; repositoryOwner?: RepositoryOwnerResponse; + user?: UserResponse; }; type RepositoryOwnerResponse = { @@ -46,11 +47,19 @@ export type OrganizationResponse = { repositories?: Connection; }; +export type UserResponse = { + organizations?: Connection; +}; + export type PageInfo = { hasNextPage: boolean; endCursor?: string; }; +export type GithubOrg = { + login: string; +}; + /** * Github User * @@ -334,6 +343,34 @@ export async function getOrganizationTeamsFromUsers( return { groups }; } +export async function getOrganizationsFromUser( + client: typeof graphql, + user: string, +): Promise<{ + orgs: string[]; +}> { + const query = ` + query orgs($user: String!) { + user(login: $user) { + organizations(first: 100) { + nodes { login } + pageInfo { hasNextPage, endCursor } + } + } + }`; + + const orgs = await queryWithPaging( + client, + query, + '', + r => r.user?.organizations, + async o => o.login, + { user }, + ); + + return { orgs }; +} + export async function getOrganizationTeam( client: typeof graphql, org: string, diff --git a/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.test.ts b/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.test.ts index 76ab55552d..99bef6e074 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.test.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.test.ts @@ -16,11 +16,13 @@ import { getVoidLogger } from '@backstage/backend-common'; import { GroupEntity, UserEntity } from '@backstage/catalog-model'; +import { ConfigReader } from '@backstage/config'; import { GithubCredentialsProvider, GithubIntegrationConfig, } from '@backstage/integration'; import { EntityProviderConnection } from '@backstage/plugin-catalog-node'; +import { EventSubscriber } from '@backstage/plugin-events-node'; import { graphql } from '@octokit/graphql'; import { GithubMultiOrgEntityProvider, @@ -160,7 +162,7 @@ describe('GithubMultiOrgEntityProvider', () => { const logger = getVoidLogger(); const gitHubConfig: GithubIntegrationConfig = { - host: 'https://github.com', + host: 'github.com', }; const mockGetCredentials = jest.fn().mockReturnValue({ @@ -201,9 +203,9 @@ describe('GithubMultiOrgEntityProvider', () => { metadata: { annotations: { 'backstage.io/managed-by-location': - 'url:https://https://github.com/a', + 'url:https://github.com/a', 'backstage.io/managed-by-origin-location': - 'url:https://https://github.com/a', + 'url:https://github.com/a', 'github.com/user-login': 'a', }, description: 'c', @@ -227,9 +229,9 @@ describe('GithubMultiOrgEntityProvider', () => { metadata: { annotations: { 'backstage.io/managed-by-location': - 'url:https://https://github.com/x', + 'url:https://github.com/x', 'backstage.io/managed-by-origin-location': - 'url:https://https://github.com/x', + 'url:https://github.com/x', 'github.com/user-login': 'x', }, description: 'z', @@ -253,9 +255,9 @@ describe('GithubMultiOrgEntityProvider', () => { metadata: { annotations: { 'backstage.io/managed-by-location': - 'url:https://https://github.com/q', + 'url:https://github.com/q', 'backstage.io/managed-by-origin-location': - 'url:https://https://github.com/q', + 'url:https://github.com/q', 'github.com/user-login': 'q', }, description: 's', @@ -279,9 +281,9 @@ describe('GithubMultiOrgEntityProvider', () => { metadata: { annotations: { 'backstage.io/managed-by-location': - 'url:https://https://github.com/orgs/orgA/teams/team', + 'url:https://github.com/orgs/orgA/teams/team', 'backstage.io/managed-by-origin-location': - 'url:https://https://github.com/orgs/orgA/teams/team', + 'url:https://github.com/orgs/orgA/teams/team', 'github.com/team-slug': 'orgA/team', }, namespace: 'orga', @@ -308,9 +310,9 @@ describe('GithubMultiOrgEntityProvider', () => { metadata: { annotations: { 'backstage.io/managed-by-location': - 'url:https://https://github.com/orgs/orgB/teams/team', + 'url:https://github.com/orgs/orgB/teams/team', 'backstage.io/managed-by-origin-location': - 'url:https://https://github.com/orgs/orgB/teams/team', + 'url:https://github.com/orgs/orgB/teams/team', 'github.com/team-slug': 'orgB/team', }, namespace: 'orgb', @@ -467,7 +469,7 @@ describe('GithubMultiOrgEntityProvider', () => { const logger = getVoidLogger(); const gitHubConfig: GithubIntegrationConfig = { - host: 'https://github.com', + host: 'github.com', }; const mockGetCredentials = jest.fn().mockReturnValue({ @@ -507,9 +509,9 @@ describe('GithubMultiOrgEntityProvider', () => { metadata: { annotations: { 'backstage.io/managed-by-location': - 'url:https://https://github.com/a', + 'url:https://github.com/a', 'backstage.io/managed-by-origin-location': - 'url:https://https://github.com/a', + 'url:https://github.com/a', 'github.com/user-login': 'a', }, description: 'c', @@ -533,9 +535,9 @@ describe('GithubMultiOrgEntityProvider', () => { metadata: { annotations: { 'backstage.io/managed-by-location': - 'url:https://https://github.com/x', + 'url:https://github.com/x', 'backstage.io/managed-by-origin-location': - 'url:https://https://github.com/x', + 'url:https://github.com/x', 'github.com/user-login': 'x', }, description: 'z', @@ -559,9 +561,9 @@ describe('GithubMultiOrgEntityProvider', () => { metadata: { annotations: { 'backstage.io/managed-by-location': - 'url:https://https://github.com/q', + 'url:https://github.com/q', 'backstage.io/managed-by-origin-location': - 'url:https://https://github.com/q', + 'url:https://github.com/q', 'github.com/user-login': 'q', }, description: 's', @@ -585,9 +587,9 @@ describe('GithubMultiOrgEntityProvider', () => { metadata: { annotations: { 'backstage.io/managed-by-location': - 'url:https://https://github.com/orgs/orgC/teams/team', + 'url:https://github.com/orgs/orgC/teams/team', 'backstage.io/managed-by-origin-location': - 'url:https://https://github.com/orgs/orgC/teams/team', + 'url:https://github.com/orgs/orgC/teams/team', 'github.com/team-slug': 'orgC/team', }, namespace: 'orgc', @@ -614,9 +616,9 @@ describe('GithubMultiOrgEntityProvider', () => { metadata: { annotations: { 'backstage.io/managed-by-location': - 'url:https://https://github.com/orgs/orgD/teams/team', + 'url:https://github.com/orgs/orgD/teams/team', 'backstage.io/managed-by-origin-location': - 'url:https://https://github.com/orgs/orgD/teams/team', + 'url:https://github.com/orgs/orgD/teams/team', 'github.com/team-slug': 'orgD/team', }, namespace: 'orgd', @@ -713,4 +715,1223 @@ describe('GithubMultiOrgEntityProvider', () => { }); }); }); + + describe('events', () => { + let onEvent: Function; + + const entityProviderConnection: EntityProviderConnection = { + applyMutation: jest.fn(), + refresh: jest.fn(), + }; + + beforeEach(() => { + const logger = getVoidLogger(); + const config = new ConfigReader({ + integrations: { + github: [ + { + host: 'github.com', + }, + ], + }, + }); + + const mockGetCredentials = jest.fn().mockReturnValue({ + headers: { token: 'blah' }, + type: 'app', + }); + + const githubCredentialsProvider: GithubCredentialsProvider = { + getCredentials: mockGetCredentials, + }; + + const mockEventBroker = { + publish: async () => {}, + subscribe: (subscriber: EventSubscriber) => { + onEvent = subscriber.onEvent; + }, + }; + + const entityProvider = GithubMultiOrgEntityProvider.fromConfig(config, { + id: 'my-id', + githubCredentialsProvider, + githubUrl: 'https://github.com', + logger, + orgs: ['orgA', 'orgB'], + eventBroker: mockEventBroker, + }); + + entityProvider.connect(entityProviderConnection); + }); + + afterEach(() => jest.resetAllMocks()); + + it('should ignore events from non-applicable orgs', async () => { + await onEvent({ + topic: 'github.organization', + eventPayload: { + action: 'member_added', + membership: { + user: { + name: 'githubuser', + login: 'githubuser', + avatar_url: 'https://avatars.githubusercontent.com/u/83820368', + email: 'user1@test.com', + }, + }, + organization: { + login: 'test-org', + }, + }, + }); + + expect(entityProviderConnection.applyMutation).not.toHaveBeenCalled(); + + await onEvent({ + topic: 'github.installation', + eventPayload: { + action: 'created', + installation: { + account: { + login: 'test-org', + }, + }, + }, + }); + + expect(entityProviderConnection.applyMutation).not.toHaveBeenCalled(); + }); + + describe('installation', () => { + it('adds users and groups from new org', async () => { + const mockClient = jest.fn(); + + mockClient + .mockResolvedValueOnce({ + organization: { + membersWithRole: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + login: 'a', + name: 'b', + bio: 'c', + email: 'd', + avatarUrl: 'e', + }, + ], + }, + }, + }) + .mockResolvedValueOnce({ + organization: { + teams: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + slug: 'team', + combinedSlug: 'orgB/team', + name: 'TeamB', + description: 'The one and only team', + avatarUrl: 'http://example.com/team.jpeg', + parentTeam: { + slug: 'parent', + combinedSlug: '', + members: { pageInfo: { hasNextPage: false }, nodes: [] }, + }, + members: { + pageInfo: { hasNextPage: false }, + nodes: [{ login: 'a' }], + }, + }, + ], + }, + }, + }) + .mockResolvedValueOnce({ + organization: { + teams: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + slug: 'team', + combinedSlug: 'orgA/team', + name: 'TeamA', + description: 'The one and only team', + avatarUrl: 'http://example.com/team.jpeg', + parentTeam: { + slug: 'parent', + combinedSlug: '', + members: { pageInfo: { hasNextPage: false }, nodes: [] }, + }, + members: { + pageInfo: { hasNextPage: false }, + nodes: [{ login: 'a' }], + }, + }, + ], + }, + }, + }) + .mockResolvedValueOnce({ + organization: { + teams: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + slug: 'team', + combinedSlug: 'orgB/team', + name: 'TeamB', + description: 'The one and only team', + avatarUrl: 'http://example.com/team.jpeg', + parentTeam: { + slug: 'parent', + combinedSlug: '', + members: { pageInfo: { hasNextPage: false }, nodes: [] }, + }, + members: { + pageInfo: { hasNextPage: false }, + nodes: [{ login: 'a' }], + }, + }, + ], + }, + }, + }); + + (graphql.defaults as jest.Mock).mockReturnValue(mockClient); + + await onEvent({ + topic: 'github.installation', + eventPayload: { + action: 'created', + installation: { + account: { + login: 'orgB', + }, + }, + }, + }); + + expect(entityProviderConnection.applyMutation).toHaveBeenCalledTimes(1); + expect(entityProviderConnection.applyMutation).toHaveBeenCalledWith({ + type: 'delta', + added: [ + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + annotations: { + 'backstage.io/managed-by-location': + 'url:https://github.com/a', + 'backstage.io/managed-by-origin-location': + 'url:https://github.com/a', + 'github.com/user-login': 'a', + }, + description: 'c', + name: 'a', + }, + spec: { + memberOf: ['orga/team', 'orgb/team'], + profile: { + displayName: 'b', + email: 'd', + picture: 'e', + }, + }, + }, + locationKey: 'github-multi-org-provider:my-id', + }, + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + annotations: { + 'backstage.io/managed-by-location': + 'url:https://github.com/orgs/orgB/teams/team', + 'backstage.io/managed-by-origin-location': + 'url:https://github.com/orgs/orgB/teams/team', + 'github.com/team-slug': 'orgB/team', + }, + namespace: 'orgb', + name: 'team', + description: 'The one and only team', + }, + spec: { + children: [], + parent: 'parent', + profile: { + displayName: 'TeamB', + picture: 'http://example.com/team.jpeg', + }, + type: 'team', + members: ['default/a'], + }, + }, + locationKey: 'github-multi-org-provider:my-id', + }, + ], + removed: [], + }); + }); + }); + + describe('organization', () => { + it('should add a new user', async () => { + const mockClient = jest.fn(); + + mockClient + .mockResolvedValueOnce({ + user: { + organizations: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + login: 'orgA', + }, + { + login: 'orgB', + }, + ], + }, + }, + }) + .mockResolvedValueOnce({ + organization: { + teams: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + slug: 'team', + combinedSlug: 'orgA/team', + name: 'TeamB', + description: 'The one and only team', + avatarUrl: 'http://example.com/team.jpeg', + editTeamUrl: 'https://example.com', + parentTeam: { + slug: 'parent', + }, + members: { + pageInfo: { hasNextPage: false }, + nodes: [{ login: 'a', name: 'a' }], + }, + }, + ], + }, + }, + }) + .mockResolvedValueOnce({ + organization: { + teams: { + pageInfo: { hasNextPage: false }, + nodes: [], + }, + }, + }); + + (graphql.defaults as jest.Mock).mockReturnValue(mockClient); + + await onEvent({ + topic: 'github.organization', + eventPayload: { + action: 'member_added', + organization: { + login: 'orgB', + }, + membership: { + user: { + name: 'a', + avatar_url: 'https://avatars.githubusercontent.com/u/83820368', + email: 'user1@test.com', + login: 'a', + }, + }, + }, + }); + + expect(entityProviderConnection.applyMutation).toHaveBeenCalledTimes(1); + expect(entityProviderConnection.applyMutation).toHaveBeenCalledWith({ + type: 'delta', + added: [ + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + annotations: { + 'backstage.io/managed-by-location': + 'url:https://github.com/a', + 'backstage.io/managed-by-origin-location': + 'url:https://github.com/a', + 'github.com/user-login': 'a', + }, + name: 'a', + }, + spec: { + memberOf: ['orga/team'], + profile: { + displayName: 'a', + email: 'user1@test.com', + picture: 'https://avatars.githubusercontent.com/u/83820368', + }, + }, + }, + locationKey: 'github-multi-org-provider:my-id', + }, + ], + removed: [], + }); + }); + + it('should remove a user', async () => { + const mockClient = jest.fn(); + + mockClient.mockResolvedValueOnce({ + user: { + organizations: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + login: 'orgC', + }, + ], + }, + }, + }); + + (graphql.defaults as jest.Mock).mockReturnValue(mockClient); + + await onEvent({ + topic: 'github.organization', + eventPayload: { + action: 'member_removed', + organization: { + login: 'orgB', + }, + membership: { + user: { + name: 'a', + avatar_url: 'https://avatars.githubusercontent.com/u/83820368', + email: 'user1@test.com', + login: 'a', + }, + }, + }, + }); + + expect(entityProviderConnection.applyMutation).toHaveBeenCalledTimes(1); + expect(entityProviderConnection.applyMutation).toHaveBeenCalledWith({ + type: 'delta', + added: [], + removed: [ + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + annotations: { + 'backstage.io/managed-by-location': + 'url:https://github.com/a', + 'backstage.io/managed-by-origin-location': + 'url:https://github.com/a', + 'github.com/user-login': 'a', + }, + name: 'a', + }, + spec: { + memberOf: [], + profile: { + displayName: 'a', + email: 'user1@test.com', + picture: 'https://avatars.githubusercontent.com/u/83820368', + }, + }, + }, + locationKey: 'github-multi-org-provider:my-id', + }, + ], + }); + }); + + it('should only update group memberships of a user that still belongs to an applicable org', async () => { + const mockClient = jest.fn(); + + mockClient + .mockResolvedValueOnce({ + user: { + organizations: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + login: 'orgA', + }, + ], + }, + }, + }) + .mockResolvedValueOnce({ + organization: { + teams: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + slug: 'team', + combinedSlug: 'orgA/team', + name: 'TeamB', + description: 'The one and only team', + avatarUrl: 'http://example.com/team.jpeg', + editTeamUrl: 'https://example.com', + parentTeam: { + slug: 'parent', + }, + members: { + pageInfo: { hasNextPage: false }, + nodes: [{ login: 'a', name: 'a' }], + }, + }, + ], + }, + }, + }); + + (graphql.defaults as jest.Mock).mockReturnValue(mockClient); + + await onEvent({ + topic: 'github.organization', + eventPayload: { + action: 'member_removed', + organization: { + login: 'orgB', + }, + membership: { + user: { + name: 'a', + avatar_url: 'https://avatars.githubusercontent.com/u/83820368', + email: 'user1@test.com', + login: 'a', + }, + }, + }, + }); + + expect(entityProviderConnection.applyMutation).toHaveBeenCalledTimes(1); + expect(entityProviderConnection.applyMutation).toHaveBeenCalledWith({ + type: 'delta', + added: [ + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + annotations: { + 'backstage.io/managed-by-location': + 'url:https://github.com/a', + 'backstage.io/managed-by-origin-location': + 'url:https://github.com/a', + 'github.com/user-login': 'a', + }, + name: 'a', + }, + spec: { + memberOf: ['orga/team'], + profile: { + displayName: 'a', + email: 'user1@test.com', + picture: 'https://avatars.githubusercontent.com/u/83820368', + }, + }, + }, + locationKey: 'github-multi-org-provider:my-id', + }, + ], + removed: [], + }); + }); + }); + + describe('team', () => { + it('should create a new group from a new team', async () => { + await onEvent({ + topic: 'github.team', + eventPayload: { + action: 'created', + organization: { + login: 'orgB', + }, + team: { + name: 'New Team', + slug: 'new-team', + description: 'description from the new team', + html_url: 'https://github.com/orgs/orgB/teams/new-team', + parent: { + slug: 'father-team', + }, + }, + }, + }); + + expect(entityProviderConnection.applyMutation).toHaveBeenCalledTimes(1); + expect(entityProviderConnection.applyMutation).toHaveBeenCalledWith({ + type: 'delta', + added: [ + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + name: 'new-team', + namespace: 'orgb', + description: 'description from the new team', + annotations: { + 'backstage.io/edit-url': + 'https://github.com/orgs/orgB/teams/new-team/edit', + 'backstage.io/managed-by-location': + 'url:https://github.com/orgs/orgB/teams/new-team', + 'backstage.io/managed-by-origin-location': + 'url:https://github.com/orgs/orgB/teams/new-team', + 'github.com/team-slug': 'orgB/new-team', + }, + }, + spec: { + type: 'team', + children: [], + members: [], + parent: 'father-team', + profile: { + displayName: 'New Team', + }, + }, + }, + locationKey: 'github-multi-org-provider:my-id', + }, + ], + removed: [], + }); + }); + + it('should remove a group from a deleted team', async () => { + await onEvent({ + topic: 'github.team', + eventPayload: { + action: 'deleted', + organization: { + login: 'orgB', + }, + team: { + name: 'New Team', + slug: 'new-team', + description: 'description from the new team', + html_url: 'https://github.com/orgs/orgB/teams/new-team', + parent: { + slug: 'father-team', + }, + }, + }, + }); + + expect(entityProviderConnection.applyMutation).toHaveBeenCalledTimes(1); + expect(entityProviderConnection.applyMutation).toHaveBeenCalledWith({ + type: 'delta', + added: [], + removed: [ + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + name: 'new-team', + namespace: 'orgb', + description: 'description from the new team', + annotations: { + 'backstage.io/edit-url': + 'https://github.com/orgs/orgB/teams/new-team/edit', + 'backstage.io/managed-by-location': + 'url:https://github.com/orgs/orgB/teams/new-team', + 'backstage.io/managed-by-origin-location': + 'url:https://github.com/orgs/orgB/teams/new-team', + 'github.com/team-slug': 'orgB/new-team', + }, + }, + spec: { + type: 'team', + children: [], + members: [], + parent: 'father-team', + profile: { + displayName: 'New Team', + }, + }, + }, + locationKey: 'github-multi-org-provider:my-id', + }, + ], + }); + }); + + it('should update group and user entities when a team is edited', async () => { + const mockClient = jest.fn(); + + mockClient + .mockResolvedValueOnce({ + organization: { + team: { + slug: 'team', + combinedSlug: 'orgA/team', + name: 'TeamA', + description: 'The one and only team', + avatarUrl: 'http://example.com/team.jpeg', + editTeamUrl: 'https://example.com', + parentTeam: { + slug: 'parent', + }, + members: { + pageInfo: { hasNextPage: false }, + nodes: [{ login: 'a', name: 'a' }], + }, + }, + }, + }) + .mockResolvedValueOnce({ + organization: { + membersWithRole: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + login: 'a', + name: 'b', + bio: 'c', + email: 'd', + avatarUrl: 'e', + }, + { + login: 'w', + name: 'x', + bio: 'y', + email: 'z', + avatarUrl: 'q', + }, + ], + }, + }, + }) + .mockResolvedValueOnce({ + organization: { + teams: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + slug: 'team', + combinedSlug: 'orgA/team', + name: 'TeamA', + description: 'The one and only team', + avatarUrl: 'http://example.com/team.jpeg', + editTeamUrl: 'https://example.com', + parentTeam: { + slug: 'parent', + }, + members: { + pageInfo: { hasNextPage: false }, + nodes: [{ login: 'a', name: 'a' }], + }, + }, + ], + }, + }, + }) + .mockResolvedValueOnce({ + organization: { + teams: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + slug: 'team', + combinedSlug: 'orgB/team', + name: 'TeamB', + description: 'The one and only team', + avatarUrl: 'http://example.com/team.jpeg', + editTeamUrl: 'https://example.com', + parentTeam: { + slug: 'parent', + }, + members: { + pageInfo: { hasNextPage: false }, + nodes: [{ login: 'a', name: 'a' }], + }, + }, + ], + }, + }, + }); + + (graphql.defaults as jest.Mock).mockReturnValue(mockClient); + + await onEvent({ + topic: 'github.team', + eventPayload: { + action: 'edited', + changes: { + name: { + from: 'oldName', + }, + description: { + from: 'oldDescription', + }, + }, + team: { + slug: 'team', + parent: { + slug: 'parent', + }, + }, + organization: { + login: 'orgA', + }, + }, + }); + + expect(entityProviderConnection.applyMutation).toHaveBeenCalledTimes(1); + expect(entityProviderConnection.applyMutation).toHaveBeenCalledWith({ + type: 'delta', + added: [ + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + annotations: { + 'backstage.io/managed-by-location': + 'url:https://github.com/a', + 'backstage.io/managed-by-origin-location': + 'url:https://github.com/a', + 'github.com/user-login': 'a', + }, + name: 'a', + description: 'c', + }, + spec: { + memberOf: ['orga/team', 'orgb/team'], + profile: { + displayName: 'b', + email: 'd', + picture: 'e', + }, + }, + }, + locationKey: 'github-multi-org-provider:my-id', + }, + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + annotations: { + 'backstage.io/edit-url': 'https://example.com', + 'backstage.io/managed-by-location': + 'url:https://github.com/orgs/orgA/teams/team', + 'backstage.io/managed-by-origin-location': + 'url:https://github.com/orgs/orgA/teams/team', + 'github.com/team-slug': 'orgA/team', + }, + namespace: 'orga', + name: 'team', + description: 'The one and only team', + }, + spec: { + children: [], + parent: 'parent', + profile: { + displayName: 'TeamA', + picture: 'http://example.com/team.jpeg', + }, + type: 'team', + members: ['default/a'], + }, + }, + locationKey: 'github-multi-org-provider:my-id', + }, + ], + removed: [ + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + annotations: { + 'backstage.io/managed-by-location': + 'url:https://github.com/orgs/orgA/teams/oldname', + 'backstage.io/managed-by-origin-location': + 'url:https://github.com/orgs/orgA/teams/oldname', + 'github.com/team-slug': 'orgA/oldname', + }, + namespace: 'orga', + name: 'oldname', + description: 'oldDescription', + }, + spec: { + children: [], + parent: 'parent', + profile: { + displayName: 'oldName', + }, + type: 'team', + members: [], + }, + }, + locationKey: 'github-multi-org-provider:my-id', + }, + ], + }); + }); + }); + + describe('membership', () => { + it('should update group and user entities when a member is added', async () => { + const mockClient = jest.fn(); + + mockClient + .mockResolvedValueOnce({ + organization: { + team: { + slug: 'team', + combinedSlug: 'orgA/team', + name: 'TeamA', + description: 'The one and only team', + avatarUrl: 'http://example.com/team.jpeg', + editTeamUrl: 'https://example.com', + parentTeam: { + slug: 'parent', + }, + members: { + pageInfo: { hasNextPage: false }, + nodes: [{ login: 'a', name: 'a' }], + }, + }, + }, + }) + .mockResolvedValueOnce({ + user: { + organizations: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + login: 'orgA', + }, + { + login: 'orgB', + }, + ], + }, + }, + }) + .mockResolvedValueOnce({ + organization: { + teams: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + slug: 'team', + combinedSlug: 'orgA/team', + name: 'TeamA', + description: 'The one and only team', + avatarUrl: 'http://example.com/team.jpeg', + editTeamUrl: 'https://example.com', + parentTeam: { + slug: 'parent', + }, + members: { + pageInfo: { hasNextPage: false }, + nodes: [{ login: 'a', name: 'a' }], + }, + }, + ], + }, + }, + }) + .mockResolvedValueOnce({ + organization: { + teams: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + slug: 'team', + combinedSlug: 'orgB/team', + name: 'TeamB', + description: 'The one and only team', + avatarUrl: 'http://example.com/team.jpeg', + editTeamUrl: 'https://example.com', + parentTeam: { + slug: 'parent', + }, + members: { + pageInfo: { hasNextPage: false }, + nodes: [{ login: 'a', name: 'a' }], + }, + }, + ], + }, + }, + }); + + (graphql.defaults as jest.Mock).mockReturnValue(mockClient); + + await onEvent({ + topic: 'github.membership', + eventPayload: { + action: 'added', + organization: { + login: 'orgA', + }, + team: { + slug: 'teama', + }, + member: { + name: 'a', + login: 'a', + avatar_url: 'https://avatars.githubusercontent.com/u/83820368', + email: 'user1@test.com', + }, + }, + }); + await new Promise(process.nextTick); + + expect(entityProviderConnection.applyMutation).toHaveBeenCalledTimes(1); + expect(entityProviderConnection.applyMutation).toHaveBeenCalledWith({ + type: 'delta', + added: [ + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + annotations: { + 'backstage.io/managed-by-location': + 'url:https://github.com/a', + 'backstage.io/managed-by-origin-location': + 'url:https://github.com/a', + 'github.com/user-login': 'a', + }, + name: 'a', + }, + spec: { + memberOf: ['orga/team', 'orgb/team'], + profile: { + displayName: 'a', + email: 'user1@test.com', + picture: 'https://avatars.githubusercontent.com/u/83820368', + }, + }, + }, + locationKey: 'github-multi-org-provider:my-id', + }, + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + annotations: { + 'backstage.io/edit-url': 'https://example.com', + 'backstage.io/managed-by-location': + 'url:https://github.com/orgs/orgA/teams/team', + 'backstage.io/managed-by-origin-location': + 'url:https://github.com/orgs/orgA/teams/team', + 'github.com/team-slug': 'orgA/team', + }, + namespace: 'orga', + name: 'team', + description: 'The one and only team', + }, + spec: { + children: [], + parent: 'parent', + profile: { + displayName: 'TeamA', + picture: 'http://example.com/team.jpeg', + }, + type: 'team', + members: ['default/a'], + }, + }, + locationKey: 'github-multi-org-provider:my-id', + }, + ], + removed: [], + }); + }); + + it('should update group and user entities when a member is removed', async () => { + const mockClient = jest.fn(); + + mockClient + .mockResolvedValueOnce({ + organization: { + team: { + slug: 'team', + combinedSlug: 'orgA/team', + name: 'TeamA', + description: 'The one and only team', + avatarUrl: 'http://example.com/team.jpeg', + editTeamUrl: 'https://example.com', + parentTeam: { + slug: 'parent', + }, + members: { + pageInfo: { hasNextPage: false }, + nodes: [], + }, + }, + }, + }) + .mockResolvedValueOnce({ + user: { + organizations: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + login: 'orgA', + }, + { + login: 'orgB', + }, + ], + }, + }, + }) + .mockResolvedValueOnce({ + organization: { + teams: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + slug: 'team', + combinedSlug: 'orgA/team', + name: 'TeamA', + description: 'The one and only team', + avatarUrl: 'http://example.com/team.jpeg', + editTeamUrl: 'https://example.com', + parentTeam: { + slug: 'parent', + }, + members: { + pageInfo: { hasNextPage: false }, + nodes: [], + }, + }, + ], + }, + }, + }) + .mockResolvedValueOnce({ + organization: { + teams: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + slug: 'team', + combinedSlug: 'orgB/team', + name: 'TeamB', + description: 'The one and only team', + avatarUrl: 'http://example.com/team.jpeg', + editTeamUrl: 'https://example.com', + parentTeam: { + slug: 'parent', + }, + members: { + pageInfo: { hasNextPage: false }, + nodes: [{ login: 'a', name: 'a' }], + }, + }, + ], + }, + }, + }); + + (graphql.defaults as jest.Mock).mockReturnValue(mockClient); + + await onEvent({ + topic: 'github.membership', + eventPayload: { + action: 'removed', + organization: { + login: 'orgA', + }, + team: { + slug: 'teama', + }, + member: { + name: 'a', + login: 'a', + avatar_url: 'https://avatars.githubusercontent.com/u/83820368', + email: 'user1@test.com', + }, + }, + }); + await new Promise(process.nextTick); + + expect(entityProviderConnection.applyMutation).toHaveBeenCalledTimes(1); + expect(entityProviderConnection.applyMutation).toHaveBeenCalledWith({ + type: 'delta', + added: [ + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + annotations: { + 'backstage.io/managed-by-location': + 'url:https://github.com/a', + 'backstage.io/managed-by-origin-location': + 'url:https://github.com/a', + 'github.com/user-login': 'a', + }, + name: 'a', + }, + spec: { + memberOf: ['orgb/team'], + profile: { + displayName: 'a', + email: 'user1@test.com', + picture: 'https://avatars.githubusercontent.com/u/83820368', + }, + }, + }, + locationKey: 'github-multi-org-provider:my-id', + }, + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + annotations: { + 'backstage.io/edit-url': 'https://example.com', + 'backstage.io/managed-by-location': + 'url:https://github.com/orgs/orgA/teams/team', + 'backstage.io/managed-by-origin-location': + 'url:https://github.com/orgs/orgA/teams/team', + 'github.com/team-slug': 'orgA/team', + }, + namespace: 'orga', + name: 'team', + description: 'The one and only team', + }, + spec: { + children: [], + parent: 'parent', + profile: { + displayName: 'TeamA', + picture: 'http://example.com/team.jpeg', + }, + type: 'team', + members: [], + }, + }, + locationKey: 'github-multi-org-provider:my-id', + }, + ], + removed: [], + }); + }); + }); + }); }); diff --git a/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.ts b/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.ts index ce45f30d96..51796c2116 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.ts @@ -21,7 +21,9 @@ import { DEFAULT_NAMESPACE, Entity, GroupEntity, + parseEntityRef, stringifyEntityRef, + UserEntity, } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import { @@ -32,10 +34,24 @@ import { ScmIntegrations, } from '@backstage/integration'; import { + DeferredEntity, EntityProvider, EntityProviderConnection, } from '@backstage/plugin-catalog-node'; +import { EventBroker, EventParams } from '@backstage/plugin-events-node'; import { graphql } from '@octokit/graphql'; +import { + InstallationCreatedEvent, + InstallationEvent, + OrganizationEvent, + OrganizationMemberAddedEvent, + OrganizationMemberRemovedEvent, + MembershipEvent, + TeamCreatedEvent, + TeamDeletedEvent, + TeamEditedEvent, + TeamEvent, +} from '@octokit/webhooks-types'; import { merge } from 'lodash'; import * as uuid from 'uuid'; import { Logger } from 'winston'; @@ -44,6 +60,7 @@ import { assignGroupsToUsers, buildOrgHierarchy, defaultOrganizationTeamTransformer, + defaultUserTransformer, getOrganizationTeams, getOrganizationUsers, GithubTeam, @@ -55,6 +72,11 @@ import { ANNOTATION_GITHUB_TEAM_SLUG, ANNOTATION_GITHUB_USER_LOGIN, } from '../lib/annotation'; +import { + getOrganizationsFromUser, + getOrganizationTeam, + getOrganizationTeamsFromUsers, +} from '../lib/github'; import { splitTeamSlug } from '../lib/util'; /** @@ -118,8 +140,18 @@ export interface GithubMultiOrgEntityProviderOptions { * By default groups will be namespaced according to their GitHub org. */ teamTransformer?: TeamTransformer; + + /** + * An EventBroker to subscribe this provider to GitHub events to trigger delta mutations + */ + eventBroker?: EventBroker; } +type CreateDeltaOperation = (entities: Entity[]) => { + added: DeferredEntity[]; + removed: DeferredEntity[]; +}; + /** * Ingests org data (users and groups) from GitHub. * @@ -161,6 +193,13 @@ export class GithubMultiOrgEntityProvider implements EntityProvider { provider.schedule(options.schedule); + if (options.eventBroker) { + options.eventBroker.subscribe({ + supportsEventTopics: provider.supportsEventTopics.bind(provider), + onEvent: provider.onEvent.bind(provider), + }); + } + return provider; } @@ -271,6 +310,476 @@ export class GithubMultiOrgEntityProvider implements EntityProvider { markCommitComplete(); } + private supportsEventTopics(): string[] { + return [ + 'github.installation', + 'github.organization', + 'github.team', + 'github.membership', + ]; + } + + private async onEvent(params: EventParams): Promise { + const { logger } = this.options; + logger.debug(`Received event from ${params.topic}`); + + const orgs = this.options.orgs?.length + ? this.options.orgs + : await this.getAllOrgs(this.options.gitHubConfig); + + const eventPayload = params.eventPayload as + | InstallationEvent + | OrganizationEvent + | MembershipEvent + | TeamEvent; + + if ( + !orgs.includes( + (eventPayload as InstallationEvent).installation?.account?.login, + ) && + !orgs.includes( + (eventPayload as OrganizationEvent | MembershipEvent | TeamEvent) + .organization?.login, + ) + ) { + return; + } + + // https://docs.github.com/webhooks-and-events/webhooks/webhook-events-and-payloads#installation + if ( + params.topic.includes('installation') && + eventPayload.action === 'created' + ) { + // We can only respond to installation.created events to add new users/groups since a + // installation.deleted event won't provide us info on what user/groups we should remove and + // we can't query the uninstalled org since we will no longer have access. This will need to be + // eventually resolved via occasional full mutation runs by calling read() + await this.onInstallationChange( + eventPayload as InstallationCreatedEvent, + orgs, + ); + } + + // https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#organization + if ( + params.topic.includes('organization') && + (eventPayload.action === 'member_added' || + eventPayload.action === 'member_removed') + ) { + await this.onMemberChangeInOrganization(eventPayload, orgs); + } + + // https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#team + if (params.topic.includes('team')) { + if ( + eventPayload.action === 'created' || + eventPayload.action === 'deleted' + ) { + await this.onTeamChangeInOrganization( + eventPayload as TeamCreatedEvent | TeamDeletedEvent, + ); + } else if (eventPayload.action === 'edited') { + await this.onTeamEditedInOrganization( + eventPayload as TeamEditedEvent, + orgs, + ); + } + } + + // https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#membership + if (params.topic.includes('membership')) { + this.onMembershipChangedInTeam(eventPayload as MembershipEvent, orgs); + } + + return; + } + + private async onInstallationChange( + event: InstallationCreatedEvent, + applicableOrgs: string[], + ) { + if (!this.connection) { + throw new Error('Not initialized'); + } + + const org = event.installation.account.login; + const { headers, type: tokenType } = + await this.options.githubCredentialsProvider.getCredentials({ + url: `${this.options.githubUrl}/${org}`, + }); + const client = graphql.defaults({ + baseUrl: this.options.gitHubConfig.apiBaseUrl, + headers, + }); + + const { users } = await getOrganizationUsers( + client, + org, + tokenType, + this.options.userTransformer, + ); + + const { groups } = await getOrganizationTeams( + client, + org, + this.defaultMultiOrgTeamTransformer.bind(this), + ); + + // Fetch group memberships of users in case they already exist and + // have memberships in groups from other applicable orgs + for (const userOrg of applicableOrgs) { + const { headers: orgHeaders } = + await this.options.githubCredentialsProvider.getCredentials({ + url: `${this.options.githubUrl}/${userOrg}`, + }); + const orgClient = graphql.defaults({ + baseUrl: this.options.gitHubConfig.apiBaseUrl, + headers: orgHeaders, + }); + + const { groups: userGroups } = await getOrganizationTeamsFromUsers( + orgClient, + userOrg, + users.map( + u => + u.metadata.annotations?.[ANNOTATION_GITHUB_USER_LOGIN] || + u.metadata.name, + ), + this.defaultMultiOrgTeamTransformer.bind(this), + ); + + assignGroupsToUsers(users, userGroups); + } + + const { added, removed } = this.createAddEntitiesOperation([ + ...users, + ...groups, + ]); + await this.connection.applyMutation({ + type: 'delta', + removed, + added, + }); + } + + private async onMemberChangeInOrganization( + event: OrganizationMemberAddedEvent | OrganizationMemberRemovedEvent, + applicableOrgs: string[], + ) { + if (!this.connection) { + throw new Error('Not initialized'); + } + + const userTransformer = + this.options.userTransformer || defaultUserTransformer; + const { name, avatar_url: avatarUrl, email, login } = event.membership.user; + const org = event.organization.login; + const { headers } = + await this.options.githubCredentialsProvider.getCredentials({ + url: `${this.options.githubUrl}/${org}`, + }); + const client = graphql.defaults({ + baseUrl: this.options.gitHubConfig.apiBaseUrl, + headers, + }); + + const { orgs } = await getOrganizationsFromUser(client, login); + const userApplicableOrgs = orgs.filter(o => applicableOrgs.includes(o)); + + let updateMemberships: boolean; + let createDeltaOperation: CreateDeltaOperation; + if (event.action === 'member_removed') { + if (userApplicableOrgs.length) { + // If the user is still associated with another applicable org then we don't want to remove + // them, just update the entity to remove any potential group memberships from the old org + createDeltaOperation = this.createAddEntitiesOperation.bind(this); + updateMemberships = true; + } else { + // User is no longer part of any applicable orgs so we can remove it, + // no need to take memberships into account + createDeltaOperation = this.createRemoveEntitiesOperation.bind(this); + updateMemberships = false; + } + } else { + // We're not sure if this user was already added as part of another applicable org + // so grab the latest memberships (potentially from teams of other orgs) to ensure + // we're not accidentally omitting them + createDeltaOperation = this.createAddEntitiesOperation.bind(this); + updateMemberships = true; + } + + const user = (await userTransformer( + { + name, + avatarUrl, + login, + email: email ?? undefined, + }, + { + org, + client, + query: '', + }, + )) as UserEntity; + + if (updateMemberships) { + for (const userOrg of userApplicableOrgs) { + const { headers: orgHeaders } = + await this.options.githubCredentialsProvider.getCredentials({ + url: `${this.options.githubUrl}/${userOrg}`, + }); + const orgClient = graphql.defaults({ + baseUrl: this.options.gitHubConfig.apiBaseUrl, + headers: orgHeaders, + }); + + const { groups } = await getOrganizationTeamsFromUsers( + orgClient, + userOrg, + [login], + this.defaultMultiOrgTeamTransformer.bind(this), + ); + + assignGroupsToUsers([user], groups); + } + } + + const { added, removed } = createDeltaOperation([user]); + await this.connection.applyMutation({ + type: 'delta', + removed, + added, + }); + } + + private async onTeamChangeInOrganization( + event: TeamCreatedEvent | TeamDeletedEvent, + ) { + if (!this.connection) { + throw new Error('Not initialized'); + } + + const org = event.organization.login; + const { headers } = + await this.options.githubCredentialsProvider.getCredentials({ + url: `${this.options.githubUrl}/${org}`, + }); + const client = graphql.defaults({ + baseUrl: this.options.gitHubConfig.apiBaseUrl, + headers, + }); + + const { name, html_url: url, description, slug } = event.team; + const group = (await this.defaultMultiOrgTeamTransformer( + { + name, + slug, + editTeamUrl: `${url}/edit`, + combinedSlug: `${org}/${slug}`, + description: description ?? undefined, + parentTeam: { slug: event.team?.parent?.slug || '' } as GithubTeam, + // entity will be removed or is new + members: [], + }, + { + org, + client, + query: '', + }, + )) as Entity; + + const createDeltaOperation = + event.action === 'created' + ? this.createAddEntitiesOperation.bind(this) + : this.createRemoveEntitiesOperation.bind(this); + const { added, removed } = createDeltaOperation([group]); + + await this.connection.applyMutation({ + type: 'delta', + removed, + added, + }); + } + + private async onTeamEditedInOrganization( + event: TeamEditedEvent, + applicableOrgs: string[], + ) { + if (!this.connection) { + throw new Error('Not initialized'); + } + + const org = event.organization.login; + const { headers, type: tokenType } = + await this.options.githubCredentialsProvider.getCredentials({ + url: `${this.options.githubUrl}/${org}`, + }); + const client = graphql.defaults({ + baseUrl: this.options.gitHubConfig.apiBaseUrl, + headers, + }); + + const teamSlug = event.team.slug; + const { group } = await getOrganizationTeam( + client, + org, + teamSlug, + this.defaultMultiOrgTeamTransformer.bind(this), + ); + + const { users } = await getOrganizationUsers( + client, + org, + tokenType, + this.options.userTransformer, + ); + + const usersFromChangedGroup = + group.spec.members?.map(m => + stringifyEntityRef(parseEntityRef(m, { defaultKind: 'user' })), + ) || []; + const usersToRebuild = users.filter(u => + usersFromChangedGroup.includes(stringifyEntityRef(u)), + ); + + // Update memberships of associated members of this group in case the group entity ref changed + for (const userOrg of applicableOrgs) { + const { headers: orgHeaders } = + await this.options.githubCredentialsProvider.getCredentials({ + url: `${this.options.githubUrl}/${userOrg}`, + }); + const orgClient = graphql.defaults({ + baseUrl: this.options.gitHubConfig.apiBaseUrl, + headers: orgHeaders, + }); + + const { groups } = await getOrganizationTeamsFromUsers( + orgClient, + userOrg, + usersToRebuild.map( + u => + u.metadata.annotations?.[ANNOTATION_GITHUB_USER_LOGIN] || + u.metadata.name, + ), + this.defaultMultiOrgTeamTransformer.bind(this), + ); + + assignGroupsToUsers(usersToRebuild, groups); + } + + const oldName = event.changes.name?.from || ''; + const oldSlug = oldName.toLowerCase().replaceAll(/\s/gi, '-'); + const oldGroup = (await this.defaultMultiOrgTeamTransformer( + { + name: event.changes.name?.from, + slug: oldSlug, + combinedSlug: `${org}/${oldSlug}`, + description: event.changes.description?.from, + parentTeam: { slug: event.team?.parent?.slug || '' } as GithubTeam, + // entity will be removed + members: [], + }, + { + org, + client, + query: '', + }, + )) as Entity; + + // Remove the old group entity in case the entity ref is now different + const { removed } = this.createRemoveEntitiesOperation([oldGroup]); + const { added } = this.createAddEntitiesOperation([ + ...usersToRebuild, + group, + ]); + await this.connection.applyMutation({ + type: 'delta', + removed, + added, + }); + } + + private async onMembershipChangedInTeam( + event: MembershipEvent, + applicableOrgs: string[], + ) { + if (!this.connection) { + throw new Error('Not initialized'); + } + + // The docs are saying I will receive the slug for the removed event, + // but the types don't reflect that, + // so I will just check to be sure the slug is there + // https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#membership + if (!('slug' in event.team)) { + return; + } + + const org = event.organization.login; + const { headers } = + await this.options.githubCredentialsProvider.getCredentials({ + url: `${this.options.githubUrl}/${org}`, + }); + const client = graphql.defaults({ + baseUrl: this.options.gitHubConfig.apiBaseUrl, + headers, + }); + + const teamSlug = event.team.slug; + const { group } = await getOrganizationTeam( + client, + org, + teamSlug, + this.defaultMultiOrgTeamTransformer.bind(this), + ); + + const userTransformer = + this.options.userTransformer || defaultUserTransformer; + const { name, avatar_url: avatarUrl, email, login } = event.member; + const user = (await userTransformer( + { + name, + avatarUrl, + login, + email: email ?? undefined, + }, + { + org, + client, + query: '', + }, + )) as UserEntity; + + const { orgs } = await getOrganizationsFromUser(client, login); + const userApplicableOrgs = orgs.filter(o => applicableOrgs.includes(o)); + for (const userOrg of userApplicableOrgs) { + const { headers: orgHeaders } = + await this.options.githubCredentialsProvider.getCredentials({ + url: `${this.options.githubUrl}/${userOrg}`, + }); + const orgClient = graphql.defaults({ + baseUrl: this.options.gitHubConfig.apiBaseUrl, + headers: orgHeaders, + }); + + const { groups } = await getOrganizationTeamsFromUsers( + orgClient, + userOrg, + [login], + this.defaultMultiOrgTeamTransformer.bind(this), + ); + + assignGroupsToUsers([user], groups); + } + + const { added, removed } = this.createAddEntitiesOperation([user, group]); + await this.connection.applyMutation({ + type: 'delta', + removed, + added, + }); + } + private schedule(schedule: GithubMultiOrgEntityProviderOptions['schedule']) { if (!schedule || schedule === 'manual') { return; @@ -301,9 +810,11 @@ export class GithubMultiOrgEntityProvider implements EntityProvider { team: GithubTeam, ctx: TransformerContext, ): Promise { - const result = this.options.teamTransformer - ? await this.options.teamTransformer(team, ctx) - : await defaultOrganizationTeamTransformer(team, ctx); + if (this.options.teamTransformer) { + return await this.options.teamTransformer(team, ctx); + } + + const result = await defaultOrganizationTeamTransformer(team, ctx); if (result) { result.metadata.namespace = ctx.org.toLocaleLowerCase('en-US'); @@ -333,6 +844,32 @@ export class GithubMultiOrgEntityProvider implements EntityProvider { ) .filter(Boolean) as string[]; } + + private createAddEntitiesOperation(entities: Entity[]) { + return { + removed: [], + added: entities.map(entity => ({ + locationKey: `github-multi-org-provider:${this.options.id}`, + entity: withLocations( + `https://${this.options.gitHubConfig.host}`, + entity, + ), + })), + }; + } + + private createRemoveEntitiesOperation(entities: Entity[]) { + return { + added: [], + removed: entities.map(entity => ({ + locationKey: `github-multi-org-provider:${this.options.id}`, + entity: withLocations( + `https://${this.options.gitHubConfig.host}`, + entity, + ), + })), + }; + } } // Helps wrap the timing and logging behaviors diff --git a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.test.ts b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.test.ts index ff42e42718..3e58c1473f 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.test.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.test.ts @@ -833,6 +833,7 @@ describe('GithubOrgEntityProvider', () => { 'url:https://github.com/orgs/backstage/teams/mygroup-with-spaces', }, name: 'mygroup-with-spaces', + description: 'description-from-the-new-team', }, apiVersion: 'backstage.io/v1alpha1', kind: 'Group', diff --git a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts index 02e225c938..c181510a67 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts @@ -371,14 +371,21 @@ export class GithubOrgEntityProvider assignGroupsToUsers(usersToRebuild, groups); buildOrgHierarchy(groups); - const oldName = event.changes.name?.from || ''; + const oldName = event.changes.name?.from || event.team.name; const oldSlug = oldName.toLowerCase().replaceAll(/\s/gi, '-'); + const oldDescription = + event.changes.description?.from || event.team.description; + const oldDescriptionSlug = oldDescription + ?.toLowerCase() + .replaceAll(/\s/gi, '-'); + const { removed } = createDeltaOperation(org, [ { ...group, metadata: { name: oldSlug, + description: oldDescriptionSlug, }, }, ]); diff --git a/plugins/catalog-backend-module-gitlab/CHANGELOG.md b/plugins/catalog-backend-module-gitlab/CHANGELOG.md index 9882178a2b..c7fdb3e600 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## 0.2.1 + +### Patch Changes + +- b12c41fafc4: Fix a corner case where returned users are null for bots +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + ## 0.2.1-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index 22237862aa..31f67c8b28 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab", "description": "A Backstage catalog backend module that helps integrate towards GitLab", - "version": "0.2.1-next.1", + "version": "0.2.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-gitlab/src/lib/client.ts b/plugins/catalog-backend-module-gitlab/src/lib/client.ts index 8f8c67895c..46932c95c6 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/client.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/client.ts @@ -128,10 +128,11 @@ export class GitLabClient { throw new Error(`GraphQL errors: ${JSON.stringify(response.errors)}`); } memberIds.push( - ...response.data.group.groupMembers.nodes.map( - (node: { user: { id: string } }) => + ...response.data.group.groupMembers.nodes + .filter(n => n.user) + .map(node => Number(node.user.id.replace(/^gid:\/\/gitlab\/User\//, '')), - ), + ), ); ({ hasNextPage, endCursor } = response.data.group.groupMembers.pageInfo); } while (hasNextPage); diff --git a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md index 9921b0dabc..887a38f1fc 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md +++ b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-catalog-backend-module-incremental-ingestion +## 0.3.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.2-next.0 + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-events-node@0.2.7-next.0 + - @backstage/plugin-permission-common@0.7.5 + +## 0.3.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.1 + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-events-node@0.2.6 + - @backstage/plugin-permission-common@0.7.5 + +## 0.3.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.1-next.2 + - @backstage/config@1.0.7 + ## 0.3.2-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index 686c89cd25..d34042afd4 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-incremental-ingestion", "description": "An entity provider for streaming large asset sources into the catalog", - "version": "0.3.2-next.1", + "version": "0.3.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index 104e3f1c0f..540143a4d6 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.5.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + +## 0.5.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + ## 0.5.12-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index 120131d95a..b931f9b752 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-ldap", "description": "A Backstage catalog backend module that helps integrate towards LDAP", - "version": "0.5.12-next.1", + "version": "0.5.13-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-msgraph/CHANGELOG.md b/plugins/catalog-backend-module-msgraph/CHANGELOG.md index c0c0888f38..dfd79f3023 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.5.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-catalog-common@1.0.13 + +## 0.5.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/plugin-catalog-common@1.0.13 + ## 0.5.4-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index 026386457a..120c4a46b8 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-msgraph", "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph", - "version": "0.5.4-next.1", + "version": "0.5.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-openapi/CHANGELOG.md b/plugins/catalog-backend-module-openapi/CHANGELOG.md index 5fc587a4f9..f35874880d 100644 --- a/plugins/catalog-backend-module-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-openapi/CHANGELOG.md @@ -1,5 +1,43 @@ # @backstage/plugin-catalog-backend-module-openapi +## 0.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.2-next.0 + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + +## 0.1.11 + +### Patch Changes + +- accaceadffa: Fixed bug in `jsonSchemaRefPlaceholderResolver` where relative $ref files were resolved through file system instead of base URL of file +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.1 + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + +## 0.1.11-next.2 + +### Patch Changes + +- accaceadffa: Fixed bug in `jsonSchemaRefPlaceholderResolver` where relative $ref files were resolved through file system instead of base URL of file +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.1-next.2 + - @backstage/config@1.0.7 + ## 0.1.11-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index e02490ef59..66ac0df179 100644 --- a/plugins/catalog-backend-module-openapi/package.json +++ b/plugins/catalog-backend-module-openapi/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-openapi", "description": "A Backstage catalog backend module that helps with OpenAPI specifications", - "version": "0.1.11-next.1", + "version": "0.1.12-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-openapi/src/lib/bundle.ts b/plugins/catalog-backend-module-openapi/src/lib/bundle.ts index 64c772b91e..59f7e5791f 100644 --- a/plugins/catalog-backend-module-openapi/src/lib/bundle.ts +++ b/plugins/catalog-backend-module-openapi/src/lib/bundle.ts @@ -65,6 +65,6 @@ export async function bundleFileWithRefs( }, }; const fileObject = parse(fileWithRefs); - const bundledObject = await $RefParser.bundle(fileObject, options); + const bundledObject = await $RefParser.bundle(baseUrl, fileObject, options); return stringify(bundledObject); } diff --git a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md index 39bd1e3cdc..0ae5333d51 100644 --- a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md +++ b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-catalog-backend-module-puppetdb +## 0.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## 0.1.2 + +### Patch Changes + +- 95b2168d71b: Fixes import paths and updates documentation +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## 0.1.2-next.2 + +### Patch Changes + +- 95b2168d71b: Fixes import paths and updates documentation +- Updated dependencies + - @backstage/config@1.0.7 + ## 0.1.2-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-puppetdb/README.md b/plugins/catalog-backend-module-puppetdb/README.md index d4782c6d18..9319299a06 100644 --- a/plugins/catalog-backend-module-puppetdb/README.md +++ b/plugins/catalog-backend-module-puppetdb/README.md @@ -31,9 +31,9 @@ Update the catalog plugin initialization in your backend to add the provider and + schedule: env.scheduler.createScheduledTaskRunner({ + frequency: { minutes: 10 }, + timeout: { minutes: 50 }, -+ initialDelay: { seconds: 15} ++ initialDelay: { seconds: 15 } + }), -+ }); ++ }) + ); ``` @@ -67,7 +67,7 @@ of overriding the default transformer. export const customResourceTransformer: ResourceTransformer = async ( node, config, -): Promise => { +): Promise => { // Transformations may change namespace, owner, change entity naming pattern, add labels, annotations, etc. // Create the Resource Entity on your own, or wrap the default transformer @@ -77,14 +77,16 @@ export const customResourceTransformer: ResourceTransformer = async ( 2. Configure the provider with the transformer: -```ts -const puppetDbEntityProvider = PuppetDbEntityProvider.fromConfig(env.config, { - logger: env.logger, - schedule: env.scheduler.createScheduledTaskRunner({ - frequency: { minutes: 10 }, - timeout: { minutes: 50 }, - initialDelay: { seconds: 15 }, - }), - transformer: customResourceTransformer, -}); +```diff + builder.addEntityProvider( + PuppetDbEntityProvider.fromConfig(env.config, { + logger: env.logger, ++ transformer: customResourceTransformer, + schedule: env.scheduler.createScheduledTaskRunner({ + frequency: { minutes: 10 }, + timeout: { minutes: 50 }, + initialDelay: { seconds: 15 } + }), + }) + ); ``` diff --git a/plugins/catalog-backend-module-puppetdb/package.json b/plugins/catalog-backend-module-puppetdb/package.json index 65bda327dd..2a16f0c46d 100644 --- a/plugins/catalog-backend-module-puppetdb/package.json +++ b/plugins/catalog-backend-module-puppetdb/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-puppetdb", "description": "A Backstage catalog backend module that helps integrate towards PuppetDB", - "version": "0.1.2-next.1", + "version": "0.1.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -65,7 +65,7 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/lodash": "^4.14.151", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/catalog-backend-module-puppetdb/src/providers/PuppetDbEntityProvider.test.ts b/plugins/catalog-backend-module-puppetdb/src/providers/PuppetDbEntityProvider.test.ts index ad89e1fd9a..42091fd6d6 100644 --- a/plugins/catalog-backend-module-puppetdb/src/providers/PuppetDbEntityProvider.test.ts +++ b/plugins/catalog-backend-module-puppetdb/src/providers/PuppetDbEntityProvider.test.ts @@ -28,7 +28,7 @@ import { ANNOTATION_LOCATION, ANNOTATION_ORIGIN_LOCATION, ResourceEntity, -} from '@backstage/catalog-model/'; +} from '@backstage/catalog-model'; import { DEFAULT_ENTITY_OWNER, ENDPOINT_NODES } from '../puppet/constants'; jest.mock('../puppet/read', () => { diff --git a/plugins/catalog-backend-module-puppetdb/src/providers/PuppetDbEntityProvider.ts b/plugins/catalog-backend-module-puppetdb/src/providers/PuppetDbEntityProvider.ts index 8c63baf467..a5286a9d70 100644 --- a/plugins/catalog-backend-module-puppetdb/src/providers/PuppetDbEntityProvider.ts +++ b/plugins/catalog-backend-module-puppetdb/src/providers/PuppetDbEntityProvider.ts @@ -31,7 +31,7 @@ import { ANNOTATION_LOCATION, ANNOTATION_ORIGIN_LOCATION, Entity, -} from '@backstage/catalog-model/'; +} from '@backstage/catalog-model'; import { merge } from 'lodash'; import { readPuppetNodes } from '../puppet/read'; import { ENDPOINT_NODES } from '../puppet/constants'; diff --git a/plugins/catalog-backend-module-puppetdb/src/puppet/read.ts b/plugins/catalog-backend-module-puppetdb/src/puppet/read.ts index 568ea7224e..ab3e85370a 100644 --- a/plugins/catalog-backend-module-puppetdb/src/puppet/read.ts +++ b/plugins/catalog-backend-module-puppetdb/src/puppet/read.ts @@ -16,7 +16,7 @@ import { PuppetDbEntityProviderConfig } from '../providers'; import { PuppetNode, ResourceTransformer } from './types'; -import { ResourceEntity } from '@backstage/catalog-model/'; +import { ResourceEntity } from '@backstage/catalog-model'; import { defaultResourceTransformer } from './transformers'; import fetch from 'node-fetch'; import { ResponseError } from '@backstage/errors'; diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 1a715e26bc..d97663c66f 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,68 @@ # @backstage/plugin-catalog-backend +## 1.9.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-node@0.7.9-next.0 + - @backstage/plugin-scaffolder-common@1.3.0 + - @backstage/plugin-search-common@1.2.3 + +## 1.9.1 + +### Patch Changes + +- ce8d203235b: Ensure that entity cache state is only written to the database when actually changed +- 485a6c5f7b5: Internal refactoring for performance in the service handlers +- 3587a968dcd: Fixed a bug in the `queryEntities` endpoint that was causing filtered entities to be included in cursor requests. +- ce335df9d1c: Improve the query for orphan pruning +- 27956d78671: Adjusted the OpenAPI schema file name according to the new structure +- 51064e6e5ee: Change orphan cleanup task to only log a message if it deleted entities. +- 12a345317ab: Remove unnecessary join in the entity facets endpoint, exclude nulls +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/plugin-scaffolder-common@1.3.0 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/plugin-search-backend-module-catalog@0.1.1 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-common@1.2.3 + +## 1.9.1-next.2 + +### Patch Changes + +- ce8d203235b: Ensure that entity cache state is only written to the database when actually changed +- 485a6c5f7b5: Internal refactoring for performance in the service handlers +- 3587a968dcd: Fixed a bug in the `queryEntities` endpoint that was causing filtered entities to be included in cursor requests. +- 12a345317ab: Remove unnecessary join in the entity facets endpoint, exclude nulls +- Updated dependencies + - @backstage/plugin-scaffolder-common@1.3.0-next.0 + - @backstage/config@1.0.7 + ## 1.9.1-next.1 ### Patch Changes diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 289a9a801d..b22541bda1 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend", "description": "The Backstage backend plugin that provides the Backstage catalog", - "version": "1.9.1-next.1", + "version": "1.9.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend/src/database/operations/util/deleteOrphanedEntities.ts b/plugins/catalog-backend/src/database/operations/util/deleteOrphanedEntities.ts index 920acae7bd..eeab85f59e 100644 --- a/plugins/catalog-backend/src/database/operations/util/deleteOrphanedEntities.ts +++ b/plugins/catalog-backend/src/database/operations/util/deleteOrphanedEntities.ts @@ -33,13 +33,16 @@ export async function deleteOrphanedEntities(options: { // Limit iterations for sanity for (let i = 0; i < 100; ++i) { const candidates = await tx - .with('orphans', orphans => + .with('orphans', ['entity_id', 'entity_ref'], orphans => orphans - .from('refresh_state') - .select('entity_id', 'entity_ref') - .whereNotIn('entity_ref', keep => - keep.distinct('target_entity_ref').from('refresh_state_references'), - ), + .from('refresh_state') + .select('refresh_state.entity_id', 'refresh_state.entity_ref') + .leftOuterJoin( + 'refresh_state_references', + 'refresh_state_references.target_entity_ref', + 'refresh_state.entity_ref', + ) + .whereNull('refresh_state_references.target_entity_ref'), ) .select({ entityId: 'orphans.entity_id', diff --git a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts index e89d53f79f..8e2f8b2f6f 100644 --- a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts @@ -317,7 +317,9 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { try { await this.processingDatabase.transaction(async tx => { const n = await this.processingDatabase.deleteOrphanedEntities(tx); - this.logger.info(`Deleted ${n} orphaned entities`); + if (n > 0) { + this.logger.info(`Deleted ${n} orphaned entities`); + } }); } catch (error) { this.logger.warn(`Failed to delete orphaned entities`, error); diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index 93a37fb04a..4f011813e6 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -1729,6 +1729,17 @@ describe('DefaultEntitiesCatalog', () => { ], }, }); + + await expect( + catalog.facets({ + facets: ['kind'], + filter: { not: { key: 'metadata.name', values: ['two'] } }, + }), + ).resolves.toEqual({ + facets: { + kind: [{ value: 'k', count: 1 }], + }, + }); }, ); diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index 5fca950cac..c328c83823 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -64,43 +64,47 @@ const defaultSortField: EntityOrder = { const DEFAULT_LIMIT = 20; -function parsePagination(input?: EntityPagination): { - limit?: number; - offset?: number; -} { +function parsePagination(input?: EntityPagination): EntityPagination { if (!input) { return {}; } let { limit, offset } = input; - if (input.after !== undefined) { - let cursor; - try { - const json = Buffer.from(input.after, 'base64').toString('utf8'); - cursor = JSON.parse(json); - } catch { - throw new InputError('Malformed after cursor, could not be parsed'); + if (input.after === undefined) { + return { limit, offset }; + } + + let cursor; + try { + const json = Buffer.from(input.after, 'base64').toString('utf8'); + cursor = JSON.parse(json); + } catch { + throw new InputError('Malformed after cursor, could not be parsed'); + } + + if (cursor.limit !== undefined) { + if (!Number.isInteger(cursor.limit)) { + throw new InputError('Malformed after cursor, limit was not an number'); } - if (cursor.limit !== undefined) { - if (!Number.isInteger(cursor.limit)) { - throw new InputError('Malformed after cursor, limit was not an number'); - } - limit = cursor.limit; - } - if (cursor.offset !== undefined) { - if (!Number.isInteger(cursor.offset)) { - throw new InputError('Malformed after cursor, offset was not a number'); - } - offset = cursor.offset; + limit = cursor.limit; + } + + if (cursor.offset !== undefined) { + if (!Number.isInteger(cursor.offset)) { + throw new InputError('Malformed after cursor, offset was not a number'); } + offset = cursor.offset; } return { limit, offset }; } -function stringifyPagination(input: { limit: number; offset: number }) { - const json = JSON.stringify({ limit: input.limit, offset: input.offset }); +function stringifyPagination( + input: Required>, +): string { + const { limit, offset } = input; + const json = JSON.stringify({ limit, offset }); const base64 = Buffer.from(json, 'utf8').toString('base64'); return base64; } @@ -111,24 +115,21 @@ function addCondition( filter: EntitiesSearchFilter, negate: boolean = false, entityIdField = 'entity_id', -) { +): void { + const key = filter.key.toLowerCase(); + const values = filter.values?.map(v => v.toLowerCase()); + // NOTE(freben): This used to be a set of OUTER JOIN, which may seem to // make a lot of sense. However, it had abysmal performance on sqlite // when datasets grew large, so we're using IN instead. const matchQuery = db('search') .select('search.entity_id') - .where({ key: filter.key.toLowerCase() }) + .where({ key }) .andWhere(function keyFilter() { - if (filter.values) { - if (filter.values.length === 1) { - this.where({ value: filter.values[0].toLowerCase() }); - } else { - this.andWhere( - 'value', - 'in', - filter.values.map(v => v.toLowerCase()), - ); - } + if (values?.length === 1) { + this.where({ value: values.at(0) }); + } else if (values) { + this.andWhere('value', 'in', values); } }); queryBuilder.andWhere(entityIdField, negate ? 'not in' : 'in', matchQuery); @@ -159,16 +160,16 @@ function parseFilter( negate: boolean = false, entityIdField = 'entity_id', ): Knex.QueryBuilder { + if (isNegationEntityFilter(filter)) { + return parseFilter(filter.not, query, db, !negate, entityIdField); + } + if (isEntitiesSearchFilter(filter)) { return query.andWhere(function filterFunction() { addCondition(this, db, filter, negate, entityIdField); }); } - if (isNegationEntityFilter(filter)) { - return parseFilter(filter.not, query, db, !negate, entityIdField); - } - return query[negate ? 'andWhereNot' : 'andWhere'](function filterFunction() { if (isOrEntityFilter(filter)) { for (const subFilter of filter.anyOf ?? []) { @@ -678,10 +679,9 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { for (const facet of request.facets) { const dbQuery = db('search') - .join('final_entities', 'search.entity_id', 'final_entities.entity_id') .where('search.key', facet.toLocaleLowerCase('en-US')) - .count('search.entity_id as count') - .select({ value: 'search.original_value' }) + .whereNotNull('search.original_value') + .select({ value: 'search.original_value', count: db.raw('count(*)') }) .groupBy('search.original_value'); if (request?.filter) { diff --git a/plugins/catalog-customized/CHANGELOG.md b/plugins/catalog-customized/CHANGELOG.md index 138edaee90..7b6a839605 100644 --- a/plugins/catalog-customized/CHANGELOG.md +++ b/plugins/catalog-customized/CHANGELOG.md @@ -1,5 +1,29 @@ # @internal/plugin-catalog-customized +## 0.0.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/plugin-catalog@1.11.1-next.0 + +## 0.0.10 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/plugin-catalog@1.11.0 + +## 0.0.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.11.0-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + ## 0.0.10-next.1 ### Patch Changes diff --git a/plugins/catalog-customized/package.json b/plugins/catalog-customized/package.json index 808f7a40e4..eb5e1ded05 100644 --- a/plugins/catalog-customized/package.json +++ b/plugins/catalog-customized/package.json @@ -1,7 +1,7 @@ { "name": "@internal/plugin-catalog-customized", "description": "The internal Backstage Customizable plugin for browsing the Backstage catalog", - "version": "0.0.10-next.1", + "version": "0.0.11-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index eabfdaff12..36398fd099 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-catalog-graph +## 0.2.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.2.30 + +### Patch Changes + +- d446f8fb0a8: Expose all `EntityRelationsGraphProps` to Catalog Graph Page +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.2.30-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.2.30-next.1 ### Patch Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index b9ac5ea1c1..510bc13b9c 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graph", - "version": "0.2.30-next.1", + "version": "0.2.31-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/CurveFilter.test.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/CurveFilter.test.tsx index 85d9d97c7f..242bed6311 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/CurveFilter.test.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/CurveFilter.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { render, waitFor, screen } from '@testing-library/react'; +import { render, waitFor, screen, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { CurveFilter } from './CurveFilter'; @@ -33,7 +33,9 @@ describe('', () => { expect(screen.getByText('Step Before')).toBeInTheDocument(); - await userEvent.click(screen.getByTestId('select')); + await userEvent.click( + within(screen.getByTestId('select')).getByRole('button'), + ); await userEvent.click(screen.getByText('Monotone X')); await waitFor(() => { diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/DirectionFilter.test.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/DirectionFilter.test.tsx index cb660b5a25..dc74218316 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/DirectionFilter.test.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/DirectionFilter.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { render, waitFor, screen } from '@testing-library/react'; +import { render, waitFor, screen, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { Direction } from '../EntityRelationsGraph'; @@ -37,7 +37,9 @@ describe('', () => { expect(screen.getByText('Right to left')).toBeInTheDocument(); - await userEvent.click(screen.getByTestId('select')); + await userEvent.click( + within(screen.getByTestId('select')).getByRole('button'), + ); await userEvent.click(screen.getByText('Top to bottom')); await waitFor(() => { diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityKindIcon.test.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityKindIcon.test.tsx index 6592c6195e..cc47c8850b 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityKindIcon.test.tsx +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityKindIcon.test.tsx @@ -24,7 +24,7 @@ describe('', () => { , ); - expect(baseElement.querySelector('.MuiSvgIcon-root')).toBeInTheDocument(); + expect(baseElement.querySelector('svg')).toBeInTheDocument(); }); it('renders without exploding for unknown kind', async () => { @@ -32,6 +32,6 @@ describe('', () => { , ); - expect(baseElement.querySelector('.MuiSvgIcon-root')).toBeInTheDocument(); + expect(baseElement.querySelector('svg')).toBeInTheDocument(); }); }); diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 738a28f3af..7c9646a22e 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,49 @@ # @backstage/plugin-catalog-import +## 0.9.9-next.0 + +### Patch Changes + +- 2ef84c05aee7: Added analytics event for import entity button +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-catalog-common@1.0.13 + +## 0.9.8 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/plugin-catalog-common@1.0.13 + +## 0.9.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.1-next.1 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + ## 0.9.8-next.1 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 7e7113a16c..8fc04f95f4 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-import", "description": "A Backstage plugin the helps you import entities into your catalog", - "version": "0.9.8-next.1", + "version": "0.9.9-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-import/src/components/StepReviewLocation/StepReviewLocation.tsx b/plugins/catalog-import/src/components/StepReviewLocation/StepReviewLocation.tsx index 7943b6e3b8..74ebd973d0 100644 --- a/plugins/catalog-import/src/components/StepReviewLocation/StepReviewLocation.tsx +++ b/plugins/catalog-import/src/components/StepReviewLocation/StepReviewLocation.tsx @@ -22,7 +22,7 @@ import { BackButton, NextButton } from '../Buttons'; import { EntityListComponent } from '../EntityListComponent'; import { PrepareResult, ReviewResult } from '../useImportState'; -import { configApiRef, useApi } from '@backstage/core-plugin-api'; +import { configApiRef, useAnalytics, useApi } from '@backstage/core-plugin-api'; import { Link } from '@backstage/core-components'; import { stringifyEntityRef } from '@backstage/catalog-model'; import { assertError } from '@backstage/errors'; @@ -40,6 +40,7 @@ export const StepReviewLocation = ({ }: Props) => { const catalogApi = useApi(catalogApiRef); const configApi = useApi(configApiRef); + const analytics = useAnalytics(); const appTitle = configApi.getOptional('app.title') || 'Backstage'; @@ -52,6 +53,7 @@ export const StepReviewLocation = ({ : false; const handleClick = useCallback(async () => { setSubmitted(true); + analytics.captureEvent('click', 'import entity'); try { let refreshed = new Array<{ target: string }>(); if (prepareResult.type === 'locations') { @@ -108,7 +110,7 @@ export const StepReviewLocation = ({ setSubmitted(false); } } - }, [prepareResult, onReview, catalogApi]); + }, [prepareResult, onReview, catalogApi, analytics]); return ( <> diff --git a/plugins/catalog-node/CHANGELOG.md b/plugins/catalog-node/CHANGELOG.md index a1ca2c37c6..903088747e 100644 --- a/plugins/catalog-node/CHANGELOG.md +++ b/plugins/catalog-node/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-catalog-node +## 1.3.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + +## 1.3.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + ## 1.3.6-next.1 ### Patch Changes diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index 95136c2da1..ec47249a1c 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-node", "description": "The plugin-catalog-node module for @backstage/plugin-catalog-backend", - "version": "1.3.6-next.1", + "version": "1.3.7-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index bd9d13ace5..2a267bfd1d 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,81 @@ # @backstage/plugin-catalog-react +## 1.7.0-next.0 + +### Minor Changes + +- cb4c15989b6b: The `EntityOwnerPicker` component has undergone improvements to enhance its performance. + + The component now loads entities asynchronously, resulting in improved performance and responsiveness. Instead of loading all entities upfront, they are now loaded in batches as the user scrolls. + The previous implementation inferred users and groups displayed by the `EntityOwnerPicker` component based on the entities available in the `EntityListContext`. The updated version no longer relies on the `EntityListContext` for inference, allowing for better decoupling and improved performance. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.4 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + +## 1.6.0 + +### Minor Changes + +- 2258dcae970: Added an entity namespace filter and column on the default catalog page. + + If you have a custom version of the catalog page, you can add this filter in your CatalogPage code: + + ```ts + + + + + + /* if you want namespace picker */ + + + + + + + ``` + + The namespace column can be added using `createNamespaceColumn();`. This is only needed if you customized the columns for CatalogTable. + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.1 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.4 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-react@0.4.12 + +## 1.6.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + ## 1.6.0-next.1 ### Patch Changes diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md index f9725e41e8..90bddecd71 100644 --- a/plugins/catalog-react/api-report.md +++ b/plugins/catalog-react/api-report.md @@ -195,7 +195,7 @@ export class EntityLifecycleFilter implements EntityFilter { // @public (undocumented) export const EntityLifecyclePicker: (props: { initialFilter?: string[]; -}) => JSX.Element | null; +}) => JSX.Element; // @public export const EntityListContext: React_2.Context< diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 37190aa4c8..7d925d825b 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-react", "description": "A frontend library that helps other Backstage plugins interact with the catalog", - "version": "1.6.0-next.1", + "version": "1.7.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -60,6 +60,7 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", + "@react-hookz/web": "^23.0.0", "@types/react": "^16.13.1 || ^17.0.0", "classnames": "^2.2.6", "jwt-decode": "^3.1.0", diff --git a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx index 3a9a100357..b6de85937d 100644 --- a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx +++ b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx @@ -54,6 +54,7 @@ export type EntityAutocompletePickerProps< showCounts?: boolean; Filter: ConstructableFilter>; InputProps?: TextFieldProps; + initialSelectedOptions?: string[]; }; /** @public */ @@ -61,7 +62,15 @@ export function EntityAutocompletePicker< T extends DefaultEntityFilters = DefaultEntityFilters, Name extends AllowedEntityFilters = AllowedEntityFilters, >(props: EntityAutocompletePickerProps) { - const { label, name, path, showCounts, Filter, InputProps } = props; + const { + label, + name, + path, + showCounts, + Filter, + InputProps, + initialSelectedOptions = [], + } = props; const { updateFilters, @@ -90,7 +99,8 @@ export function EntityAutocompletePicker< const [selectedOptions, setSelectedOptions] = useState( queryParameters.length ? queryParameters - : (filters[name] as unknown as { values: string[] })?.values ?? [], + : (filters[name] as unknown as { values: string[] })?.values ?? + initialSelectedOptions, ); // Set selected options on query parameter updates; this happens at initial page load and from diff --git a/plugins/catalog-react/src/components/EntityKindPicker/EntityKindPicker.test.tsx b/plugins/catalog-react/src/components/EntityKindPicker/EntityKindPicker.test.tsx index 04d8df3d16..2513f8dca9 100644 --- a/plugins/catalog-react/src/components/EntityKindPicker/EntityKindPicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityKindPicker/EntityKindPicker.test.tsx @@ -19,7 +19,7 @@ import { Entity } from '@backstage/catalog-model'; import { ApiProvider } from '@backstage/core-app-api'; import { alertApiRef } from '@backstage/core-plugin-api'; import { renderWithEffects, TestApiRegistry } from '@backstage/test-utils'; -import { fireEvent, waitFor, screen } from '@testing-library/react'; +import { fireEvent, waitFor, screen, within } from '@testing-library/react'; import { capitalize } from 'lodash'; import { default as React } from 'react'; import { catalogApiRef } from '../../api'; @@ -87,7 +87,7 @@ describe('', () => { expect(screen.getByText('Kind')).toBeInTheDocument(); const input = screen.getByTestId('select'); - fireEvent.click(input); + fireEvent.mouseDown(within(input).getByRole('button')); await waitFor(() => screen.getByText('Domain')); @@ -115,7 +115,7 @@ describe('', () => { , ); const input = screen.getByTestId('select'); - fireEvent.click(input); + fireEvent.mouseDown(within(input).getByRole('button')); await waitFor(() => screen.getByText('Domain')); fireEvent.click(screen.getByText('Domain')); @@ -171,7 +171,7 @@ describe('', () => { ); const input = screen.getByTestId('select'); - fireEvent.click(input); + fireEvent.mouseDown(within(input).getByRole('button')); expect( screen.getByRole('option', { name: 'Component' }), @@ -196,7 +196,7 @@ describe('', () => { expect(screen.getByText('Frob')).toBeInTheDocument(); const input = screen.getByTestId('select'); - fireEvent.click(input); + fireEvent.mouseDown(within(input).getByRole('button')); expect(screen.getByRole('option', { name: 'Domain' })).toBeInTheDocument(); }); }); diff --git a/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.test.tsx b/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.test.tsx index 3ee610ddaf..19554f18b7 100644 --- a/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.test.tsx @@ -14,146 +14,116 @@ * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; -import { fireEvent, render, screen } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import React from 'react'; import { MockEntityListContextProvider } from '../../testUtils/providers'; import { EntityLifecycleFilter } from '../../filters'; import { EntityLifecyclePicker } from './EntityLifecyclePicker'; - -const sampleEntities: Entity[] = [ - { - apiVersion: '1', - kind: 'Component', - metadata: { - name: 'component-1', - }, - spec: { - lifecycle: 'production', - }, - }, - { - apiVersion: '1', - kind: 'Component', - metadata: { - name: 'component-2', - }, - spec: { - lifecycle: 'experimental', - }, - }, - { - apiVersion: '1', - kind: 'Component', - metadata: { - name: 'component-3', - }, - spec: { - lifecycle: 'experimental', - }, - }, -]; +import { TestApiProvider } from '@backstage/test-utils'; +import { catalogApiRef } from '../../api'; +import { CatalogApi } from '@backstage/catalog-client'; describe('', () => { - it('renders all lifecycles', () => { - render( - - - , - ); - expect(screen.getByText('Lifecycle')).toBeInTheDocument(); + const catalogApi = { + getEntityFacets: jest.fn(), + } as unknown as jest.Mocked; - fireEvent.click(screen.getByTestId('lifecycle-picker-expand')); - sampleEntities - .map(e => e.spec?.lifecycle!) - .forEach(lifecycle => { - expect(screen.getByText(lifecycle as string)).toBeInTheDocument(); - }); + beforeEach(() => { + catalogApi.getEntityFacets.mockResolvedValue({ + facets: { + 'spec.lifecycle': [ + { count: 1, value: 'experimental' }, + { count: 1, value: 'production' }, + ], + }, + }); }); - it('renders unique lifecycles in alphabetical order', () => { - render( - - - , - ); - expect(screen.getByText('Lifecycle')).toBeInTheDocument(); - - fireEvent.click(screen.getByTestId('lifecycle-picker-expand')); - - expect(screen.getAllByRole('option').map(o => o.textContent)).toEqual([ - 'experimental', - 'production', - ]); + afterEach(() => { + jest.resetAllMocks(); }); - it('respects the query parameter filter value', () => { + it('renders all lifecycles', async () => { + render( + + + + + , + ); + expect(await screen.findByText('Lifecycle')).toBeInTheDocument(); + + fireEvent.click(await screen.findByTestId('lifecycles-picker-expand')); + expect(screen.getByText('experimental')).toBeInTheDocument(); + expect(screen.getByText('production')).toBeInTheDocument(); + }); + + it('respects the query parameter filter value', async () => { const updateFilters = jest.fn(); const queryParameters = { lifecycles: ['experimental'] }; render( - - - , + + + + + , ); + await waitFor(() => expect(catalogApi.getEntityFacets).toHaveBeenCalled()); expect(updateFilters).toHaveBeenLastCalledWith({ lifecycles: new EntityLifecycleFilter(['experimental']), }); }); - it('adds lifecycles to filters', () => { + it('adds lifecycles to filters', async () => { const updateFilters = jest.fn(); render( - - - , + + + + + , ); expect(updateFilters).toHaveBeenLastCalledWith({ lifecycles: undefined, }); - fireEvent.click(screen.getByTestId('lifecycle-picker-expand')); + fireEvent.click(await screen.findByTestId('lifecycles-picker-expand')); fireEvent.click(screen.getByText('production')); expect(updateFilters).toHaveBeenLastCalledWith({ lifecycles: new EntityLifecycleFilter(['production']), }); }); - it('removes lifecycles from filters', () => { + it('removes lifecycles from filters', async () => { const updateFilters = jest.fn(); render( - - - , + + + + + , ); + + await waitFor(() => expect(catalogApi.getEntityFacets).toHaveBeenCalled()); expect(updateFilters).toHaveBeenLastCalledWith({ lifecycles: new EntityLifecycleFilter(['production']), }); - fireEvent.click(screen.getByTestId('lifecycle-picker-expand')); + fireEvent.click(screen.getByTestId('lifecycles-picker-expand')); expect(screen.getByLabelText('production')).toBeChecked(); fireEvent.click(screen.getByLabelText('production')); @@ -162,67 +132,85 @@ describe('', () => { }); }); - it('responds to external queryParameters changes', () => { + it('responds to external queryParameters changes', async () => { const updateFilters = jest.fn(); const rendered = render( - - - , + + + + + , ); + + await waitFor(() => expect(catalogApi.getEntityFacets).toHaveBeenCalled()); expect(updateFilters).toHaveBeenLastCalledWith({ lifecycles: new EntityLifecycleFilter(['experimental']), }); + rendered.rerender( - - - , + + + + + , ); expect(updateFilters).toHaveBeenLastCalledWith({ lifecycles: new EntityLifecycleFilter(['production']), }); }); - it('removes lifecycles from filters if there are no available lifecycles', () => { + + it('removes lifecycles from filters if there are no available lifecycles', async () => { + catalogApi.getEntityFacets.mockResolvedValue({ + facets: { + 'spec.lifecycle': [], + }, + }); + const updateFilters = jest.fn(); render( - - - , + + + + + , ); + + await waitFor(() => expect(catalogApi.getEntityFacets).toHaveBeenCalled()); expect(updateFilters).toHaveBeenLastCalledWith({ lifecycles: undefined, }); }); - it('responds to initialFilter prop', () => { + + it('responds to initialFilter prop', async () => { const updateFilters = jest.fn(); render( - - - , + + + + + , ); + + await waitFor(() => expect(catalogApi.getEntityFacets).toHaveBeenCalled()); expect(updateFilters).toHaveBeenLastCalledWith({ lifecycles: new EntityLifecycleFilter(['production']), }); diff --git a/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.tsx b/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.tsx index dd107b2673..a1bd6ef86b 100644 --- a/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.tsx +++ b/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.tsx @@ -14,22 +14,10 @@ * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; -import { - Box, - Checkbox, - FormControlLabel, - makeStyles, - TextField, - Typography, -} from '@material-ui/core'; -import CheckBoxIcon from '@material-ui/icons/CheckBox'; -import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank'; -import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; -import { Autocomplete } from '@material-ui/lab'; -import React, { useEffect, useMemo, useState } from 'react'; -import { useEntityList } from '../../hooks/useEntityListProvider'; +import { makeStyles } from '@material-ui/core'; +import React from 'react'; import { EntityLifecycleFilter } from '../../filters'; +import { EntityAutocompletePicker } from '../EntityAutocompletePicker'; /** @public */ export type CatalogReactEntityLifecyclePickerClassKey = 'input'; @@ -43,98 +31,19 @@ const useStyles = makeStyles( }, ); -const icon = ; -const checkedIcon = ; - /** @public */ export const EntityLifecyclePicker = (props: { initialFilter?: string[] }) => { const { initialFilter = [] } = props; const classes = useStyles(); - const { - updateFilters, - backendEntities, - filters, - queryParameters: { lifecycles: lifecyclesParameter }, - } = useEntityList(); - - const queryParamLifecycles = useMemo( - () => [lifecyclesParameter].flat().filter(Boolean) as string[], - [lifecyclesParameter], - ); - - const [selectedLifecycles, setSelectedLifecycles] = useState( - queryParamLifecycles.length - ? queryParamLifecycles - : filters.lifecycles?.values ?? initialFilter, - ); - - // Set selected lifecycles on query parameter updates; this happens at initial page load and from - // external updates to the page location. - useEffect(() => { - if (queryParamLifecycles.length) { - setSelectedLifecycles(queryParamLifecycles); - } - }, [queryParamLifecycles]); - - const availableLifecycles = useMemo( - () => - [ - ...new Set( - backendEntities - .map((e: Entity) => e.spec?.lifecycle) - .filter(Boolean) as string[], - ), - ].sort(), - [backendEntities], - ); - - useEffect(() => { - updateFilters({ - lifecycles: - selectedLifecycles.length && availableLifecycles.length - ? new EntityLifecycleFilter(selectedLifecycles) - : undefined, - }); - }, [selectedLifecycles, updateFilters, availableLifecycles]); - - if (!availableLifecycles.length) return null; return ( - - - Lifecycle - - setSelectedLifecycles(value) - } - renderOption={(option, { selected }) => ( - - } - onClick={event => event.preventDefault()} - label={option} - /> - )} - size="small" - popupIcon={} - renderInput={params => ( - - )} - /> - - + ); }; diff --git a/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.test.tsx b/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.test.tsx index e4dc322c7c..e5497d022a 100644 --- a/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.test.tsx @@ -14,8 +14,8 @@ * limitations under the License. */ -import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; -import { fireEvent, screen } from '@testing-library/react'; +import { Entity } from '@backstage/catalog-model'; +import { fireEvent, screen, waitFor } from '@testing-library/react'; import React from 'react'; import { MockEntityListContextProvider } from '../../testUtils/providers'; import { EntityOwnerFilter } from '../../filters'; @@ -28,8 +28,9 @@ import { } from '@backstage/test-utils'; import { catalogApiRef, CatalogApi } from '../..'; import { errorApiRef } from '@backstage/core-plugin-api'; +import { QueryEntitiesCursorRequest } from '@backstage/catalog-client'; -const ownerEntities: Entity[] = [ +const ownerEntitiesBatch1: Entity[] = [ { apiVersion: '1', kind: 'Group', @@ -68,64 +69,56 @@ const ownerEntities: Entity[] = [ }, ]; -const sampleEntities: Entity[] = [ +const ownerEntitiesBatch2: Entity[] = [ { apiVersion: '1', - kind: 'Component', + kind: 'Group', metadata: { - name: 'component-1', + name: 'some-owner-batch-2', }, - relations: [ - { - type: 'ownedBy', - targetRef: 'group:default/some-owner', - }, - { - type: 'ownedBy', - targetRef: 'group:default/some-owner-2', - }, - ], }, { apiVersion: '1', - kind: 'Component', + kind: 'Group', metadata: { - name: 'component-2', + name: 'some-owner-2-batch-2', }, - relations: [ - { - type: 'ownedBy', - targetRef: 'group:default/another-owner', + spec: { + profile: { + displayName: 'Some Owner Batch 2', }, - { - type: 'ownedBy', - targetRef: 'group:test-namespace/another-owner-2', - }, - ], + }, }, { apiVersion: '1', - kind: 'Component', + kind: 'Group', metadata: { - name: 'component-3', + name: 'another-owner-batch-2', + title: 'Another Owner Batch 2', + }, + }, + { + apiVersion: '1', + kind: 'Group', + metadata: { + namespace: 'test-namespace', + name: 'another-owner-2-batch-2', + title: 'Another Owner in Another Namespace Batch 2', }, - relations: [ - { - type: 'ownedBy', - targetRef: 'group:default/some-owner', - }, - ], }, ]; -const getEntitiesByRefs = jest.fn(async ({ entityRefs }) => ({ - items: entityRefs.map((e: string) => - ownerEntities.find(f => stringifyEntityRef(f) === e), - ), -})); +const mockedQueryEntities: jest.MockedFn = + jest.fn(); + +const mockedGetEntitiesByRef: jest.MockedFn = + jest.fn(); + const mockCatalogApi: Partial = { - getEntitiesByRefs, + queryEntities: mockedQueryEntities, + getEntitiesByRefs: mockedGetEntitiesByRef, }; + const mockErrorApi = new MockErrorApi(); describe('', () => { @@ -134,12 +127,33 @@ describe('', () => { [errorApiRef, mockErrorApi], ); - it('renders all owners', async () => { + beforeEach(() => { + jest.resetAllMocks(); + + mockedQueryEntities.mockImplementation(async request => { + const totalItems = + ownerEntitiesBatch1.length + ownerEntitiesBatch2.length; + if ((request as QueryEntitiesCursorRequest).cursor) { + return { + items: ownerEntitiesBatch2, + pageInfo: {}, + totalItems, + }; + } + return { + items: ownerEntitiesBatch1, + pageInfo: { + nextCursor: 'nextCursor', + }, + totalItems, + }; + }); + }); + + it('renders all users and groups', async () => { await renderWithEffects( - + , @@ -147,36 +161,37 @@ describe('', () => { expect(screen.getByText('Owner')).toBeInTheDocument(); fireEvent.click(screen.getByTestId('owner-picker-expand')); + + await waitFor(() => + expect(screen.getByText('Another Owner')).toBeInTheDocument(), + ); + [ - 'Another Owner', 'some-owner', 'Some Owner 2', 'Another Owner in Another Namespace', ].forEach(owner => { expect(screen.getByText(owner)).toBeInTheDocument(); }); - }); - it('renders unique owners in alphabetical order', async () => { - await renderWithEffects( - - - - - , + expect(mockedQueryEntities).toHaveBeenCalledTimes(1); + expect(mockedGetEntitiesByRef).not.toHaveBeenCalled(); + + fireEvent.scroll(screen.getByTestId('owner-picker-listbox')); + + await waitFor(() => + expect(screen.getByText('some-owner-batch-2')).toBeInTheDocument(), ); - expect(screen.getByText('Owner')).toBeInTheDocument(); - fireEvent.click(screen.getByTestId('owner-picker-expand')); + [ + 'some-owner-batch-2', + 'Some Owner Batch 2', + 'Another Owner in Another Namespace Batch 2', + ].forEach(owner => { + expect(screen.getByText(owner)).toBeInTheDocument(); + }); - expect(screen.getAllByRole('option').map(o => o.textContent)).toEqual([ - 'Another Owner', - 'Another Owner in Another Namespace', - 'some-owner', - 'Some Owner 2', - ]); + expect(mockedQueryEntities).toHaveBeenCalledTimes(2); }); it('respects the query parameter filter value', async () => { @@ -186,8 +201,6 @@ describe('', () => { ', () => { , ); + expect(mockedGetEntitiesByRef).toHaveBeenCalledWith({ + entityRefs: ['another-owner'], + }); expect(updateFilters).toHaveBeenLastCalledWith({ owners: new EntityOwnerFilter(['group:default/another-owner']), }); }); + it('should display the selected owners as humanized entities', async () => { + const updateFilters = jest.fn(); + const queryParameters = { owners: ['another-owner'] }; + + mockedGetEntitiesByRef.mockResolvedValue({ + items: [ + { + metadata: { + name: 'another-owner', + title: 'Beautiful display name', + namespace: 'default', + }, + apiVersion: '1', + kind: 'group', + }, + ], + }); + await renderWithEffects( + + + + + , + ); + + await waitFor(() => + expect( + screen.getByRole('button', { + name: 'Beautiful display name', + }), + ).toBeInTheDocument(), + ); + + expect(mockedGetEntitiesByRef).toHaveBeenCalledWith({ + entityRefs: ['another-owner'], + }); + + fireEvent.click(screen.getByTestId('owner-picker-expand')); + await waitFor(() => screen.getByText('Some Owner 2')); + fireEvent.click(screen.getByText('Some Owner 2')); + + expect(mockedGetEntitiesByRef).toHaveBeenCalledTimes(1); + + await waitFor(() => + expect( + screen.getByRole('button', { + name: 'Some Owner 2', + }), + ).toBeInTheDocument(), + ); + }); + it('adds owners to filters', async () => { const updateFilters = jest.fn(); await renderWithEffects( @@ -217,11 +288,14 @@ describe('', () => { , ); + expect(mockedGetEntitiesByRef).not.toHaveBeenCalled(); expect(updateFilters).toHaveBeenLastCalledWith({ owners: undefined, }); fireEvent.click(screen.getByTestId('owner-picker-expand')); + await waitFor(() => screen.getByText('some-owner')); + fireEvent.click(screen.getByText('some-owner')); expect(updateFilters).toHaveBeenLastCalledWith({ owners: new EntityOwnerFilter(['group:default/some-owner']), @@ -234,8 +308,6 @@ describe('', () => { ', () => { , ); + expect(mockedGetEntitiesByRef).toHaveBeenCalledWith({ + entityRefs: ['group:default/some-owner'], + }); expect(updateFilters).toHaveBeenLastCalledWith({ owners: new EntityOwnerFilter(['group:default/some-owner']), }); fireEvent.click(screen.getByTestId('owner-picker-expand')); - expect(screen.getByLabelText('some-owner')).toBeChecked(); + await waitFor(() => + expect(screen.getByLabelText('some-owner')).toBeChecked(), + ); fireEvent.click(screen.getByLabelText('some-owner')); expect(updateFilters).toHaveBeenLastCalledWith({ @@ -265,13 +342,15 @@ describe('', () => { value={{ updateFilters, queryParameters: { owners: ['team-a'] }, - backendEntities: sampleEntities, }} > , ); + expect(mockedGetEntitiesByRef).toHaveBeenCalledWith({ + entityRefs: ['team-a'], + }); expect(updateFilters).toHaveBeenLastCalledWith({ owners: new EntityOwnerFilter(['group:default/team-a']), }); @@ -281,7 +360,6 @@ describe('', () => { value={{ updateFilters, queryParameters: { owners: ['team-b'] }, - backendEntities: sampleEntities, }} > @@ -292,23 +370,4 @@ describe('', () => { owners: new EntityOwnerFilter(['group:default/team-b']), }); }); - it('removes owners from filters if there are none available', async () => { - const updateFilters = jest.fn(); - await renderWithEffects( - - - - - , - ); - expect(updateFilters).toHaveBeenLastCalledWith({ - owners: undefined, - }); - }); }); diff --git a/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx b/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx index 8c4f2bfea0..8b223c50b1 100644 --- a/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx +++ b/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx @@ -14,32 +14,30 @@ * limitations under the License. */ -import { - Entity, - parseEntityRef, - RELATION_OWNED_BY, - stringifyEntityRef, -} from '@backstage/catalog-model'; +import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { Box, Checkbox, FormControlLabel, - makeStyles, TextField, Typography, + makeStyles, } from '@material-ui/core'; import CheckBoxIcon from '@material-ui/icons/CheckBox'; import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import { Autocomplete } from '@material-ui/lab'; -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; import { useEntityList } from '../../hooks/useEntityListProvider'; import { EntityOwnerFilter } from '../../filters'; -import { getEntityRelations } from '../../utils'; -import useAsync from 'react-use/lib/useAsync'; -import { errorApiRef, useApi } from '@backstage/core-plugin-api'; +import { useApi } from '@backstage/core-plugin-api'; import { catalogApiRef } from '../../api'; -import { humanizeEntity, humanizeEntityRef } from '../EntityRefLink/humanize'; +import useAsync from 'react-use/lib/useAsync'; +import useAsyncFn from 'react-use/lib/useAsyncFn'; +import { useDebouncedEffect } from '@react-hookz/web'; +import PersonIcon from '@material-ui/icons/Person'; +import GroupIcon from '@material-ui/icons/Group'; +import { humanizeEntity } from '../EntityRefLink/humanize'; /** @public */ export type CatalogReactEntityOwnerPickerClassKey = 'input'; @@ -61,12 +59,51 @@ export const EntityOwnerPicker = () => { const classes = useStyles(); const { updateFilters, - backendEntities, filters, queryParameters: { owners: ownersParameter }, } = useEntityList(); + const catalogApi = useApi(catalogApiRef); - const errorApi = useApi(errorApiRef); + const [text, setText] = useState(''); + + const [{ value, loading }, handleFetch] = useAsyncFn( + async (request: { text: string } | { cursor: string; prev: Entity[] }) => { + const initialRequest = request as { text: string }; + const cursorRequest = request as { cursor: string; prev: Entity[] }; + const limit = 20; + + if (cursorRequest.cursor) { + const response = await catalogApi.queryEntities({ + cursor: cursorRequest.cursor, + limit, + }); + return { + ...response, + items: [...cursorRequest.prev, ...response.items], + }; + } + + return catalogApi.queryEntities({ + fullTextFilter: { + term: initialRequest.text || '', + fields: [ + 'metadata.name', + 'kind', + 'spec.profile.displayname', + 'metadata.title', + ], + }, + filter: { kind: ['User', 'Group'] }, + orderFields: [{ field: 'metadata.name', order: 'asc' }], + limit, + }); + }, + [text], + ); + + useDebouncedEffect(() => handleFetch({ text }), [text], 250); + + const availableOwners = value?.items || []; const queryParamOwners = useMemo( () => [ownersParameter].flat().filter(Boolean) as string[], @@ -74,71 +111,10 @@ export const EntityOwnerPicker = () => { ); const [selectedOwners, setSelectedOwners] = useState( - queryParamOwners.length - ? new EntityOwnerFilter(queryParamOwners).values - : filters.owners?.values ?? [], + queryParamOwners.length ? queryParamOwners : filters.owners?.values ?? [], ); - const { - loading, - error, - value: ownerEntities, - } = useAsync(async () => { - const ownerEntityRefs = [ - ...new Set( - backendEntities - .flatMap((e: Entity) => - getEntityRelations(e, RELATION_OWNED_BY).map(o => - stringifyEntityRef(o), - ), - ) - .filter(Boolean) as string[], - ), - ]; - const { items: ownerEntitiesOrNull } = await catalogApi.getEntitiesByRefs({ - entityRefs: ownerEntityRefs, - fields: [ - 'kind', - 'metadata.name', - 'metadata.title', - 'metadata.namespace', - 'spec.profile.displayName', - ], - }); - const owners = ownerEntitiesOrNull.map((entity, index) => { - if (entity) { - return { - label: humanizeEntity(entity, { defaultKind: 'Group' }), - entityRef: stringifyEntityRef(entity), - }; - } - return { - label: humanizeEntityRef(parseEntityRef(ownerEntityRefs[index]), { - defaultKind: 'group', - }), - entityRef: ownerEntityRefs[index], - }; - }); - - return owners.sort((a, b) => - a.label.localeCompare(b.label, 'en-US', { - ignorePunctuation: true, - caseFirst: 'upper', - }), - ); - }, [backendEntities]); - - useEffect(() => { - if (error) { - errorApi.post( - { - ...error, - message: `EntityOwnerPicker failed to initialize: ${error.message}`, - }, - {}, - ); - } - }, [error, errorApi]); + const { getEntity, setEntity } = useSelectedOwners(selectedOwners); // Set selected owners on query parameter updates; this happens at initial page load and from // external updates to the page location. @@ -150,17 +126,20 @@ export const EntityOwnerPicker = () => { }, [queryParamOwners]); useEffect(() => { - if (!loading && ownerEntities) { - updateFilters({ - owners: - selectedOwners.length && ownerEntities.length - ? new EntityOwnerFilter(selectedOwners) - : undefined, - }); - } - }, [selectedOwners, updateFilters, ownerEntities, loading]); + updateFilters({ + owners: selectedOwners.length + ? new EntityOwnerFilter(selectedOwners) + : undefined, + }); + }, [selectedOwners, updateFilters]); - if (!loading && !ownerEntities?.length) return null; + if ( + ['user', 'group'].includes( + filters.kind?.value.toLocaleLowerCase('en-US') || '', + ) + ) { + return null; + } return ( @@ -170,40 +149,130 @@ export const EntityOwnerPicker = () => { multiple disableCloseOnSelect loading={loading} - options={ownerEntities || []} - value={ - ownerEntities?.filter(e => - selectedOwners.some((f: string) => f === e.entityRef), - ) ?? [] - } - onChange={(_: object, value: { entityRef: string }[]) => - setSelectedOwners(value.map(e => e.entityRef)) - } - getOptionLabel={option => option.label} - renderOption={(option, { selected }) => ( - - } - onClick={event => event.preventDefault()} - label={option.label} - /> - )} + options={availableOwners} + value={selectedOwners as unknown as Entity[]} + getOptionSelected={(o, v) => { + if (typeof v === 'string') { + return stringifyEntityRef(o) === v; + } + return o === v; + }} + getOptionLabel={o => { + const entity = typeof o === 'string' ? getEntity(o) || o : o; + + return typeof entity === 'string' + ? entity + : humanizeEntity(entity, entity.metadata.name); + }} + onChange={(_: object, owners) => { + setText(''); + setSelectedOwners( + owners.map(e => { + const entityRef = + typeof e === 'string' ? e : stringifyEntityRef(e); + + if (typeof e !== 'string') { + setEntity(e); + } + + return entityRef; + }), + ); + }} + filterOptions={x => x} + renderOption={(entity, { selected }) => { + const isGroup = entity.kind === 'Group'; + + return ( + + } + onClick={event => event.preventDefault()} + label={ + + {isGroup ? ( + + ) : ( + + )} +   + {humanizeEntity(entity, entity.metadata.name)} + + } + /> + ); + }} size="small" popupIcon={} renderInput={params => ( { + setText(e.currentTarget.value); + }} variant="outlined" /> )} + ListboxProps={{ + onScroll: (e: React.MouseEvent) => { + const element = e.currentTarget; + const hasReachedEnd = + Math.abs( + element.scrollHeight - + element.clientHeight - + element.scrollTop, + ) < 1; + + if (hasReachedEnd && value?.pageInfo.nextCursor) { + handleFetch({ + cursor: value.pageInfo.nextCursor, + prev: value.items, + }); + } + }, + 'data-testid': 'owner-picker-listbox', + }} /> ); }; + +/** + * Hook used for storing the full entity of the specified owners + * in order to display users and group using the information contained on each entity. + * When a component is rendered for the first time, it loads the content of the entities + * specified by `initialSelectedOwnersRefs` and export the `getEntity` and `setEntity` + * utilities, used to retrieve and modify the owners. + */ +function useSelectedOwners(initialSelectedOwnersRefs: string[]) { + const allEntities = useRef>({}); + const catalogApi = useApi(catalogApiRef); + + useAsync(async () => { + if (initialSelectedOwnersRefs.length === 0) { + return; + } + const initialSelectedEntities = await catalogApi.getEntitiesByRefs({ + entityRefs: initialSelectedOwnersRefs, + }); + initialSelectedEntities.items.forEach(e => { + if (e) { + allEntities.current[stringifyEntityRef(e)] = e; + } + }); + }, []); + + return { + getEntity: (entityRef: string) => allEntities.current[entityRef], + setEntity: (entity: Entity) => { + allEntities.current[stringifyEntityRef(entity)] = entity; + }, + }; +} diff --git a/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.test.tsx b/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.test.tsx index 00d36e5e13..3321db6d96 100644 --- a/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.test.tsx @@ -14,48 +14,16 @@ * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; import { fireEvent, render, screen } from '@testing-library/react'; import React from 'react'; import { EntityErrorFilter, EntityOrphanFilter } from '../../filters'; import { MockEntityListContextProvider } from '../../testUtils/providers'; import { EntityProcessingStatusPicker } from './EntityProcessingStatusPicker'; -const orphanAnnotation: Record = {}; -orphanAnnotation['backstage.io/orphan'] = 'true'; - -const sampleEntities: Entity[] = [ - { - apiVersion: '1', - kind: 'Component', - metadata: { - name: 'valid-component', - }, - }, - { - apiVersion: '1', - kind: 'Component', - metadata: { - name: 'orphan-component', - annotations: orphanAnnotation, - }, - }, - { - apiVersion: '1', - kind: 'Component', - metadata: { - name: 'error-component', - tags: ['Invalid Tag'], - }, - }, -]; - describe('', () => { it('renders all processing status options', () => { render( - + , ); @@ -71,8 +39,6 @@ describe('', () => { render( @@ -92,8 +58,6 @@ describe('', () => { render( @@ -113,8 +77,6 @@ describe('', () => { render( @@ -134,8 +96,6 @@ describe('', () => { render( diff --git a/plugins/catalog-react/src/components/EntityRefLink/humanize.test.ts b/plugins/catalog-react/src/components/EntityRefLink/humanize.test.ts index e7d1649a29..1182a7778d 100644 --- a/plugins/catalog-react/src/components/EntityRefLink/humanize.test.ts +++ b/plugins/catalog-react/src/components/EntityRefLink/humanize.test.ts @@ -215,9 +215,12 @@ describe('humanizeEntityRef', () => { describe('humanizeEntity', () => { it('gives a readable name when one is provided at metadata.title', () => { expect( - humanizeEntity({ - metadata: { name: 'my-entity', title: 'My Title' }, - } as Entity), + humanizeEntity( + { + metadata: { name: 'my-entity', title: 'My Title' }, + } as Entity, + 'default', + ), ).toBe('My Title'); }); @@ -257,13 +260,16 @@ describe('humanizeEntity', () => { ])( 'gives a readable name for kind %s when one is provided at spec.profile.displayName', (_, entity: Entity, expected) => { - expect(humanizeEntity(entity)).toBe(expected); + expect(humanizeEntity(entity, 'default')).toBe(expected); }, ); it('should pass through to humanizeEntityRef when nothing matches', () => { expect( - humanizeEntity({ kind: 'Group', metadata: { name: 'test' } } as Entity), - ).toBe('group:test'); + humanizeEntity( + { kind: 'Group', metadata: { name: 'test' } } as Entity, + 'default', + ), + ).toBe('default'); }); }); diff --git a/plugins/catalog-react/src/components/EntityRefLink/humanize.ts b/plugins/catalog-react/src/components/EntityRefLink/humanize.ts index 7f1501280a..478f0dce9d 100644 --- a/plugins/catalog-react/src/components/EntityRefLink/humanize.ts +++ b/plugins/catalog-react/src/components/EntityRefLink/humanize.ts @@ -25,7 +25,8 @@ import get from 'lodash/get'; * @param defaultNamespace - if set to false then namespace is never omitted, * if set to string which matches namespace of entity then omitted * - * @public */ + * @public + **/ export function humanizeEntityRef( entityRef: Entity | CompoundEntityRef, opts?: { @@ -73,27 +74,19 @@ export function humanizeEntityRef( * If an entity is either User or Group, this will be its `spec.profile.displayName`. * Otherwise, this is `metadata.title`. * - * If neither of those are found or populated, fallback to `humanizeEntityRef`. + * If neither of those are found or populated, fallback to `defaultName`. * * @param entity - Entity to convert. - * @param opts - If entity readable name is not available, opts will be used to specify humanizeEntityRef options. - * @returns Readable name, defaults to unique identifier. + * @param defaultName - If entity readable name is not available, `defaultName` will be returned. + * @returns Readable name, defaults to `defaultName`. * - * @public */ -export function humanizeEntity( - entity: Entity, - opts?: { - defaultKind?: string; - defaultNamespace?: string | false; - }, -) { +export function humanizeEntity(entity: Entity, defaultName: string) { for (const path of ['spec.profile.displayName', 'metadata.title']) { const value = get(entity, path); if (value && typeof value === 'string') { return value; } } - - return humanizeEntityRef(entity, opts); + return defaultName; } diff --git a/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx b/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx index d61a6c480f..3e69c35180 100644 --- a/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { fireEvent, waitFor, screen } from '@testing-library/react'; +import { fireEvent, waitFor, screen, within } from '@testing-library/react'; import { Entity } from '@backstage/catalog-model'; import { EntityTypePicker } from './EntityTypePicker'; import { MockEntityListContextProvider } from '../../testUtils/providers'; @@ -95,7 +95,7 @@ describe('', () => { expect(screen.getByText('Type')).toBeInTheDocument(); const input = screen.getByTestId('select'); - fireEvent.click(input); + fireEvent.mouseDown(within(input).getByRole('button')); await waitFor(() => screen.getByText('service')); @@ -119,7 +119,7 @@ describe('', () => { , ); const input = screen.getByTestId('select'); - fireEvent.click(input); + fireEvent.mouseDown(within(input).getByRole('button')); await waitFor(() => screen.getByText('service')); fireEvent.click(screen.getByText('service')); @@ -128,7 +128,7 @@ describe('', () => { type: new EntityTypeFilter(['service']), }); - fireEvent.click(input); + fireEvent.mouseDown(within(input).getByRole('button')); fireEvent.click(screen.getByText('all')); expect(updateFilters).toHaveBeenLastCalledWith({ type: undefined }); diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index 1082396da1..07603b5a5b 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,76 @@ # @backstage/plugin-catalog +## 1.11.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/plugin-search-react@1.6.1-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-search-common@1.2.3 + +## 1.11.0 + +### Minor Changes + +- 2258dcae970: Added an entity namespace filter and column on the default catalog page. + + If you have a custom version of the catalog page, you can add this filter in your CatalogPage code: + + ```ts + + + + + + /* if you want namespace picker */ + + + + + + + ``` + + The namespace column can be added using `createNamespaceColumn();`. This is only needed if you customized the columns for CatalogTable. + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/plugin-search-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-search-common@1.2.3 + +## 1.11.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-search-react@1.6.0-next.2 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 1.11.0-next.1 ### Patch Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 0d5a9badcd..e76be49515 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog", "description": "The Backstage plugin for browsing the Backstage catalog", - "version": "1.11.0-next.1", + "version": "1.11.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md index d895633ad4..3466ea9586 100644 --- a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md +++ b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-cicd-statistics-module-gitlab +## 0.1.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-cicd-statistics@0.1.21-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.1.14 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-cicd-statistics@0.1.20 + +## 0.1.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-cicd-statistics@0.1.20-next.2 + ## 0.1.14-next.1 ### Patch Changes diff --git a/plugins/cicd-statistics-module-gitlab/package.json b/plugins/cicd-statistics-module-gitlab/package.json index 20d82e485f..4c33240415 100644 --- a/plugins/cicd-statistics-module-gitlab/package.json +++ b/plugins/cicd-statistics-module-gitlab/package.json @@ -1,14 +1,13 @@ { "name": "@backstage/plugin-cicd-statistics-module-gitlab", "description": "CI/CD Statistics plugin module; Gitlab CICD", - "version": "0.1.14-next.1", + "version": "0.1.15-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { "access": "public", - "main": "dist/index.cjs.js", - "module": "dist/index.esm.js", + "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, "backstage": { diff --git a/plugins/cicd-statistics/CHANGELOG.md b/plugins/cicd-statistics/CHANGELOG.md index 3a802df672..cd6ea6dba8 100644 --- a/plugins/cicd-statistics/CHANGELOG.md +++ b/plugins/cicd-statistics/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-cicd-statistics +## 0.1.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.1.20 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.1.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.20-next.1 ### Patch Changes diff --git a/plugins/cicd-statistics/package.json b/plugins/cicd-statistics/package.json index a6a01ae05c..31027c84e7 100644 --- a/plugins/cicd-statistics/package.json +++ b/plugins/cicd-statistics/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cicd-statistics", "description": "A frontend plugin visualizing CI/CD pipeline statistics (build time)", - "version": "0.1.20-next.1", + "version": "0.1.21-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md index 8afa59660d..f1ede4c911 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-circleci +## 0.3.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.3.18 + +### Patch Changes + +- 451b3cadb3d: Fixes row display for in progress jobs to not display trailing "took" +- 1c4958d905f: Hide empty time field data for queued builds which haven't started yet +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.3.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.3.18-next.1 ### Patch Changes diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 683b43795c..dda06965c1 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-circleci", "description": "A Backstage plugin that integrates towards Circle CI", - "version": "0.3.18-next.1", + "version": "0.3.19-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md index ba462e356c..9ce48f5525 100644 --- a/plugins/cloudbuild/CHANGELOG.md +++ b/plugins/cloudbuild/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-cloudbuild +## 0.3.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.3.18 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.3.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.3.18-next.1 ### Patch Changes diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 26a72a6c84..5a2877a9a5 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cloudbuild", "description": "A Backstage plugin that integrates towards Google Cloud Build", - "version": "0.3.18-next.1", + "version": "0.3.19-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-climate/CHANGELOG.md b/plugins/code-climate/CHANGELOG.md index 405e65e814..2f4b706935 100644 --- a/plugins/code-climate/CHANGELOG.md +++ b/plugins/code-climate/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-code-climate +## 0.1.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.1.18 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.1.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.18-next.1 ### Patch Changes diff --git a/plugins/code-climate/package.json b/plugins/code-climate/package.json index 2edda59078..c531a6bff4 100644 --- a/plugins/code-climate/package.json +++ b/plugins/code-climate/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-code-climate", - "version": "0.1.18-next.1", + "version": "0.1.19-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-coverage-backend/CHANGELOG.md b/plugins/code-coverage-backend/CHANGELOG.md index a63405bd75..d9dd489217 100644 --- a/plugins/code-coverage-backend/CHANGELOG.md +++ b/plugins/code-coverage-backend/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-code-coverage-backend +## 0.2.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## 0.2.11 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + ## 0.2.11-next.1 ### Patch Changes diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index 549e0a1b2c..24cdbc2f60 100644 --- a/plugins/code-coverage-backend/package.json +++ b/plugins/code-coverage-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-code-coverage-backend", "description": "A Backstage backend plugin that helps you keep track of your code coverage", - "version": "0.2.11-next.1", + "version": "0.2.12-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-coverage/CHANGELOG.md b/plugins/code-coverage/CHANGELOG.md index 7f5789d3a5..064f1bc791 100644 --- a/plugins/code-coverage/CHANGELOG.md +++ b/plugins/code-coverage/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-code-coverage +## 0.2.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## 0.2.11 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.2.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + ## 0.2.11-next.1 ### Patch Changes diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 412c7d3281..9f4b310d04 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-code-coverage", "description": "A Backstage plugin that helps you keep track of your code coverage", - "version": "0.2.11-next.1", + "version": "0.2.12-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/codescene/CHANGELOG.md b/plugins/codescene/CHANGELOG.md index 3c6338dfb0..0dc5111af3 100644 --- a/plugins/codescene/CHANGELOG.md +++ b/plugins/codescene/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-codescene +## 0.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.1.13 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.1.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.13-next.0 ### Patch Changes diff --git a/plugins/codescene/package.json b/plugins/codescene/package.json index 744634130c..9cd8baa955 100644 --- a/plugins/codescene/package.json +++ b/plugins/codescene/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-codescene", - "version": "0.1.13-next.0", + "version": "0.1.14-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/config-schema/CHANGELOG.md b/plugins/config-schema/CHANGELOG.md index e744ff73b1..4e1ed10101 100644 --- a/plugins/config-schema/CHANGELOG.md +++ b/plugins/config-schema/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-config-schema +## 0.1.42-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## 0.1.41 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## 0.1.41-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.41-next.0 ### Patch Changes diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 893048274e..4e1349974f 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-config-schema", "description": "A Backstage plugin that lets you browse the configuration schema of your app", - "version": "0.1.41-next.0", + "version": "0.1.42-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index 89ba2ebaa0..59670358ad 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-cost-insights +## 0.12.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-cost-insights-common@0.1.1 + +## 0.12.7 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-cost-insights-common@0.1.1 + +## 0.12.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + ## 0.12.7-next.1 ### Patch Changes diff --git a/plugins/cost-insights/contrib/aws-cost-explorer-api.md b/plugins/cost-insights/contrib/aws-cost-explorer-api.md index 1e3f4e9de6..4fbf8a0cbe 100644 --- a/plugins/cost-insights/contrib/aws-cost-explorer-api.md +++ b/plugins/cost-insights/contrib/aws-cost-explorer-api.md @@ -75,7 +75,7 @@ try { We can use the data provided by the Cost Explorer API to implement CostInsightsApi methods such as `getGroupDailyCost`, `getProjectDailyCost`, and `getProductInsights`. You'll still need to provide external data for methods such as `getUserGroups` and `getAlerts`. -### 1. [getGroupDailyCost](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/api/CostInsightsApi.ts#L93) +### 1. [getGroupDailyCost](https://github.com/backstage/backstage/blob/e0506af8fc54074a160fb91c83d6cae8172d3bb3/plugins/cost-insights/src/api/CostInsightsApi.ts#L119) The `getGroupDailyCost` method is expected to return daily cost aggregations for a given group and interval time frame as a [`Cost`](https://github.com/backstage/backstage/blob/master/plugins/cost-insights-common/src/types/Cost.ts). @@ -206,13 +206,13 @@ Sample `groupedCosts` based on the response: } ``` -### 2. [getProjectDailyCost](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/api/CostInsightsApi.ts#L111) +### 2. [getProjectDailyCost](https://github.com/backstage/backstage/blob/e0506af8fc54074a160fb91c83d6cae8172d3bb3/plugins/cost-insights/src/api/CostInsightsApi.ts#L137) The `getProjectDailyCost` method is expected to return daily cost aggregations for a given billing entity and interval time frame as a [`Cost`](https://github.com/backstage/backstage/blob/master/plugins/cost-insights-common/src/types/Cost.ts). This should be similar to the `getGroupDailyCost` method implementation, but with an updated `LINKED_ACCOUNT` filter to get narrower cost data for a lower-level linked account. -### 3. [getProductInsights](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/api/CostInsightsApi.ts#L111) +### 3. [getProductInsights](https://github.com/backstage/backstage/blob/e0506af8fc54074a160fb91c83d6cae8172d3bb3/plugins/cost-insights/src/api/CostInsightsApi.ts#L165) The `getProductInsights` method is expected to return cost aggregations for a particular cloud product and interval time frame as an [`Entity`](https://github.com/backstage/backstage/blob/master/plugins/cost-insights-common/src/types/Entity.ts). diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 4855aae01a..b1ab7f444c 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cost-insights", "description": "A Backstage plugin that helps you keep track of your cloud spend", - "version": "0.12.7-next.1", + "version": "0.12.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/devtools-backend/.eslintrc.js b/plugins/devtools-backend/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/devtools-backend/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/devtools-backend/CHANGELOG.md b/plugins/devtools-backend/CHANGELOG.md new file mode 100644 index 0000000000..d4b5c74d9c --- /dev/null +++ b/plugins/devtools-backend/CHANGELOG.md @@ -0,0 +1,50 @@ +# @backstage/plugin-devtools-backend + +## 0.1.1-next.0 + +### Patch Changes + +- 3d11596a72b5: Update plugin installation docs to be more consistent across documentations +- Updated dependencies + - @backstage/config-loader@1.3.1-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-devtools-common@0.1.0 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-node@0.7.9-next.0 + +## 0.1.0 + +### Minor Changes + +- 347aeca204c: Introduced the DevTools plugin, checkout the plugin's [`README.md`](https://github.com/backstage/backstage/tree/master/plugins/devtools) for more details! + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-devtools-common@0.1.0 + - @backstage/backend-common@0.18.5 + - @backstage/config-loader@1.3.0 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.5 + +## 0.1.0-next.0 + +### Minor Changes + +- 347aeca204c: Introduced the DevTools plugin, checkout the plugin's [`README.md`](https://github.com/backstage/backstage/tree/master/plugins/devtools) for more details! + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-devtools-common@0.1.0-next.0 + - @backstage/config@1.0.7 diff --git a/plugins/devtools-backend/README.md b/plugins/devtools-backend/README.md new file mode 100644 index 0000000000..7304ce33d7 --- /dev/null +++ b/plugins/devtools-backend/README.md @@ -0,0 +1,55 @@ +# DevTools Backend + +Welcome to the DevTools backend plugin! This plugin provides data for the [DevTools frontend](../devtools/) features. + +## Setup + +Here's how to get the DevTools Backend up and running: + +1. First we need to add the `@backstage/plugin-devtools-backend` package to your backend: + + ```sh + # From the Backstage root directory + yarn add --cwd packages/backend @backstage/plugin-devtools-backend + ``` + +2. Then we will create a new file named `packages/backend/src/plugins/devtools.ts`, and add the + following to it: + + ```ts + import { createRouter } from '@backstage/plugin-devtools-backend'; + import { Router } from 'express'; + import type { PluginEnvironment } from '../types'; + + export default function createPlugin( + env: PluginEnvironment, + ): Promise { + return createRouter({ + logger: env.logger, + config: env.config, + permissions: env.permissions, + }); + } + ``` + +3. Next we wire this into the overall backend router, edit `packages/backend/src/index.ts`: + + ```ts + import devTools from './plugins/devtools'; + // ... + async function main() { + // ... + // Add this line under the other lines that follow the useHotMemoize pattern + const devToolsEnv = useHotMemoize(module, () => createEnv('devtools')); + // ... + // Insert this line under the other lines that add their routers to apiRouter in the same way + apiRouter.use('/devtools', await devTools(devToolsEnv)); + ``` + +4. Now run `yarn start-backend` from the repo root +5. Finally open `http://localhost:7007/api/devtools/health` in a browser and it should return `{"status":"ok"}` + +## Links + +- [Frontend part of the plugin](../devtools/README.md) +- [The Backstage homepage](https://backstage.io) diff --git a/plugins/devtools-backend/api-report.md b/plugins/devtools-backend/api-report.md new file mode 100644 index 0000000000..e28f0697ab --- /dev/null +++ b/plugins/devtools-backend/api-report.md @@ -0,0 +1,39 @@ +## API Report File for "@backstage/plugin-devtools-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { Config } from '@backstage/config'; +import { ConfigInfo } from '@backstage/plugin-devtools-common'; +import { DevToolsInfo } from '@backstage/plugin-devtools-common'; +import express from 'express'; +import { ExternalDependency } from '@backstage/plugin-devtools-common'; +import { Logger } from 'winston'; +import { PermissionEvaluator } from '@backstage/plugin-permission-common'; + +// @public (undocumented) +export function createRouter(options: RouterOptions): Promise; + +// @public (undocumented) +export class DevToolsBackendApi { + constructor(logger: Logger, config: Config); + // (undocumented) + listConfig(): Promise; + // (undocumented) + listExternalDependencyDetails(): Promise; + // (undocumented) + listInfo(): Promise; +} + +// @public (undocumented) +export interface RouterOptions { + // (undocumented) + config: Config; + // (undocumented) + devToolsBackendApi?: DevToolsBackendApi; + // (undocumented) + logger: Logger; + // (undocumented) + permissions: PermissionEvaluator; +} +``` diff --git a/plugins/devtools-backend/config.d.ts b/plugins/devtools-backend/config.d.ts new file mode 100644 index 0000000000..15e70afcf8 --- /dev/null +++ b/plugins/devtools-backend/config.d.ts @@ -0,0 +1,44 @@ +/* + * Copyright 2022 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. + */ +export interface Config { + /** + * DevTools configuration. + */ + devTools?: { + /** + * External dependency configuration. + */ + externalDependencies?: { + /** + * The list of endpoints to check. + */ + endpoints?: Array<{ + /** + * The name of the endpoint. + */ + name: string; + /** + * Type of check to perform; currently fetch or ping + */ + type: string; + /** + * The target of the endpoint; currently either a URL for fetch or server name for ping. + */ + target: string; + }>; + }; + }; +} diff --git a/plugins/devtools-backend/package.json b/plugins/devtools-backend/package.json new file mode 100644 index 0000000000..d59cf963db --- /dev/null +++ b/plugins/devtools-backend/package.json @@ -0,0 +1,63 @@ +{ + "name": "@backstage/plugin-devtools-backend", + "version": "0.1.1-next.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "backend-plugin" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/backend-common": "workspace:^", + "@backstage/cli-common": "workspace:^", + "@backstage/config": "workspace:^", + "@backstage/config-loader": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/plugin-auth-node": "workspace:^", + "@backstage/plugin-devtools-common": "workspace:^", + "@backstage/plugin-permission-common": "workspace:^", + "@backstage/plugin-permission-node": "workspace:^", + "@backstage/types": "workspace:^", + "@manypkg/get-packages": "^1.1.3", + "@types/express": "*", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "^3.0.0-rc.4", + "express": "^4.18.1", + "express-promise-router": "^4.1.0", + "fs-extra": "^10.0.0", + "lodash": "^4.17.21", + "node-fetch": "^2.6.7", + "ping": "^0.4.1", + "semver": "^7.3.2", + "winston": "^3.2.1", + "yn": "^4.0.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@types/minimist": "^1.2.0", + "@types/ping": "^0.4.1", + "@types/supertest": "^2.0.8", + "@types/yarnpkg__lockfile": "^1.1.4", + "msw": "^1.0.0", + "supertest": "^6.2.4" + }, + "files": [ + "dist", + "config.d.ts" + ], + "configSchema": "config.d.ts" +} diff --git a/plugins/devtools-backend/src/api/DevToolsBackendApi.ts b/plugins/devtools-backend/src/api/DevToolsBackendApi.ts new file mode 100644 index 0000000000..efd0407b31 --- /dev/null +++ b/plugins/devtools-backend/src/api/DevToolsBackendApi.ts @@ -0,0 +1,254 @@ +/* + * Copyright 2022 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 { Config, ConfigReader } from '@backstage/config'; +import { loadConfigSchema } from '@backstage/config-loader'; +import { + PackageDependency, + DevToolsInfo, + ExternalDependency, + Endpoint, + ExternalDependencyStatus, + ConfigInfo, +} from '@backstage/plugin-devtools-common'; + +import { JsonObject } from '@backstage/types'; +import { Logger } from 'winston'; +import fetch from 'node-fetch'; +import { findPaths } from '@backstage/cli-common'; +import { getPackages } from '@manypkg/get-packages'; +import ping from 'ping'; +import os from 'os'; +import fs from 'fs-extra'; +import { Lockfile } from '../util/Lockfile'; +import { memoize } from 'lodash'; +import { assertError } from '@backstage/errors'; + +/** @public */ +export class DevToolsBackendApi { + public constructor( + private readonly logger: Logger, + private readonly config: Config, + ) {} + + public async listExternalDependencyDetails(): Promise { + const result: ExternalDependency[] = []; + + const endpoints = this.config.getOptional( + 'devTools.externalDependencies.endpoints', + ); + if (!endpoints) { + // No external dependency endpoints configured + return result; + } + for (const endpoint of endpoints) { + this.logger?.info( + `Checking external dependency "${endpoint.name}" at "${endpoint.target}"`, + ); + + switch (endpoint.type) { + case 'ping': { + const pingResult = await this.pingExternalDependency(endpoint); + result.push(pingResult); + break; + } + case 'fetch': { + const fetchResult = await this.fetchExternalDependency(endpoint); + result.push(fetchResult); + break; + } + default: + return result; + } + } + + return result; + } + + private async fetchExternalDependency( + endpoint: Endpoint, + ): Promise { + let status; + let error; + + await fetch(endpoint.target) + .then(res => { + status = + res.status === 200 + ? ExternalDependencyStatus.healthy + : ExternalDependencyStatus.unhealthy; + this.logger.debug( + `Fetch for ${endpoint.name} resulted in status code "${res.status}"`, + ); + }) + .catch((err: Error) => { + this.logger.error(`Fetch failed for ${endpoint.name} - ${err.message}`); + error = err.message; + }); + + const result: ExternalDependency = { + name: endpoint.name, + type: endpoint.type, + target: endpoint.target, + status: status ?? ExternalDependencyStatus.unhealthy, + error: error ?? undefined, + }; + + return result; + } + + private async pingExternalDependency( + endpoint: Endpoint, + ): Promise { + const pingResult = await ping.promise.probe(endpoint.target); + + let error; + if ( + pingResult.packetLoss === '100.000' || + pingResult.packetLoss === 'unknown' + ) { + this.logger.error( + `Ping failed for ${endpoint.name} - ${pingResult.output}`, + ); + error = + pingResult.output === '' + ? `${endpoint.target} - Unknown` + : pingResult.output; + } + + this.logger.debug( + `Ping results for ${endpoint.name}: ${pingResult.output}`, + ); + + const result: ExternalDependency = { + name: endpoint.name, + type: endpoint.type, + target: endpoint.target, + status: pingResult.alive + ? ExternalDependencyStatus.healthy + : ExternalDependencyStatus.unhealthy, + error: error ?? undefined, + }; + + return result; + } + + public async listConfig(): Promise { + /* eslint-disable-next-line no-restricted-syntax */ + const paths = findPaths(__dirname); + + const { packages } = await getPackages(paths.targetDir); + const schemaFunc = async () => { + return await loadConfigSchema({ + dependencies: packages.map(p => p.packageJson.name), + }); + }; + + const schemaMemo = memoize(schemaFunc); + const schema = await schemaMemo(); + + const configInfo: ConfigInfo = { + config: undefined, + error: undefined, + }; + try { + const config = { + data: this.config.get() as JsonObject, + context: 'inline', + }; + const sanitizedConfigs = schema.process([config], { + ignoreSchemaErrors: false, + valueTransform: (value, context) => + context.visibility === 'secret' ? '' : value, + }); + + const data = ConfigReader.fromConfigs(sanitizedConfigs).get(); + configInfo.config = data; + } catch (error) { + assertError(error); + // The config is not valid for some reason but we want to be able to see it still + const config = { + data: this.config.get() as JsonObject, + context: 'inline', + }; + const sanitizedConfigs = schema.process([config], { + ignoreSchemaErrors: true, + valueTransform: (value, context) => + context.visibility === 'secret' ? '' : value, + }); + + const data = ConfigReader.fromConfigs(sanitizedConfigs).get(); + configInfo.config = data; + configInfo.error = { + name: error.name, + message: error.message, + messages: error.messages as string[] | undefined, + stack: error.stack, + }; + } + + return configInfo; + } + + public async listInfo(): Promise { + const operatingSystem = `${os.type} ${os.release} - ${os.platform}/${os.arch}`; + const nodeJsVersion = process.version; + + /* eslint-disable-next-line no-restricted-syntax */ + const paths = findPaths(__dirname); + const backstageFile = paths.resolveTargetRoot('backstage.json'); + let backstageJson = undefined; + if (fs.existsSync(backstageFile)) { + const buffer = await fs.readFile(backstageFile); + backstageJson = JSON.parse(buffer.toString()); + } + + const lockfilePath = paths.resolveTargetRoot('yarn.lock'); + const lockfile = await Lockfile.load(lockfilePath); + + const deps = [...lockfile.keys()].filter(n => n.startsWith('@backstage/')); + + const infoDependencies: PackageDependency[] = []; + for (const dep of deps) { + const versions = new Set(lockfile.get(dep)!.map(i => i.version)); + const infoDependency: PackageDependency = { + name: dep, + versions: [...versions].join(', '), + }; + infoDependencies.push(infoDependency); + } + + const info: DevToolsInfo = { + operatingSystem: operatingSystem ?? 'N/A', + nodeJsVersion: nodeJsVersion ?? 'N/A', + backstageVersion: + backstageJson && backstageJson.version ? backstageJson.version : 'N/A', + dependencies: infoDependencies, + }; + + return info; + } +} + +export function isValidUrl(url: string): boolean { + try { + // eslint-disable-next-line no-new + new URL(url); + return true; + } catch { + return false; + } +} diff --git a/plugins/devtools-backend/src/api/index.ts b/plugins/devtools-backend/src/api/index.ts new file mode 100644 index 0000000000..ed3390b113 --- /dev/null +++ b/plugins/devtools-backend/src/api/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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. + */ + +export { DevToolsBackendApi } from './DevToolsBackendApi'; diff --git a/plugins/devtools-backend/src/index.ts b/plugins/devtools-backend/src/index.ts new file mode 100644 index 0000000000..e1545e0022 --- /dev/null +++ b/plugins/devtools-backend/src/index.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2022 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. + */ + +/** + * Backstage DevTools backend plugin that contains the API for retrieving package dependencies and current configuration which is used by the Backstage DevTools frontend plugin. + * + * @packageDocumentation + */ + +export { DevToolsBackendApi } from './api'; +export * from './service/router'; diff --git a/plugins/devtools-backend/src/run.ts b/plugins/devtools-backend/src/run.ts new file mode 100644 index 0000000000..d945aa13f0 --- /dev/null +++ b/plugins/devtools-backend/src/run.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2022 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 { getRootLogger } from '@backstage/backend-common'; +import yn from 'yn'; +import { startStandaloneServer } from './service/standaloneServer'; + +const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007; +const enableCors = yn(process.env.PLUGIN_CORS, { default: false }); +const logger = getRootLogger(); + +startStandaloneServer({ port, enableCors, logger }).catch(err => { + logger.error(err); + process.exit(1); +}); + +process.on('SIGINT', () => { + logger.info('CTRL+C pressed; exiting.'); + process.exit(0); +}); diff --git a/plugins/devtools-backend/src/service/router.test.ts b/plugins/devtools-backend/src/service/router.test.ts new file mode 100644 index 0000000000..f3c78242cf --- /dev/null +++ b/plugins/devtools-backend/src/service/router.test.ts @@ -0,0 +1,69 @@ +/* + * Copyright 2022 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 { getVoidLogger } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import express from 'express'; +import request from 'supertest'; +import { PermissionEvaluator } from '@backstage/plugin-permission-common'; +import { createRouter } from './router'; + +const mockedAuthorize: jest.MockedFunction = + jest.fn(); +const mockedPermissionQuery: jest.MockedFunction< + PermissionEvaluator['authorizeConditional'] +> = jest.fn(); + +const permissionEvaluator: PermissionEvaluator = { + authorize: mockedAuthorize, + authorizeConditional: mockedPermissionQuery, +}; + +describe('createRouter', () => { + let app: express.Express; + + beforeAll(async () => { + const router = await createRouter({ + logger: getVoidLogger(), + config: new ConfigReader({ + healthCheck: { + endpoint: [ + { + name: '', + type: '', + target: '', + }, + ], + }, + }), + permissions: permissionEvaluator, + }); + app = express().use(router); + }); + + beforeEach(() => { + jest.resetAllMocks(); + }); + + describe('GET /health', () => { + it('returns ok', async () => { + const response = await request(app).get('/health'); + + expect(response.status).toEqual(200); + expect(response.body).toEqual({ status: 'ok' }); + }); + }); +}); diff --git a/plugins/devtools-backend/src/service/router.ts b/plugins/devtools-backend/src/service/router.ts new file mode 100644 index 0000000000..fbeeb5af84 --- /dev/null +++ b/plugins/devtools-backend/src/service/router.ts @@ -0,0 +1,137 @@ +/* + * Copyright 2022 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 { + AuthorizeResult, + PermissionEvaluator, +} from '@backstage/plugin-permission-common'; +import { + devToolsConfigReadPermission, + devToolsExternalDependenciesReadPermission, + devToolsInfoReadPermission, + devToolsPermissions, +} from '@backstage/plugin-devtools-common'; + +import { Config } from '@backstage/config'; +import { DevToolsBackendApi } from '../api'; +import { Logger } from 'winston'; +import { NotAllowedError } from '@backstage/errors'; +import Router from 'express-promise-router'; +import { errorHandler } from '@backstage/backend-common'; +import express from 'express'; +import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node'; +import { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node'; + +/** @public */ +export interface RouterOptions { + devToolsBackendApi?: DevToolsBackendApi; + logger: Logger; + config: Config; + permissions: PermissionEvaluator; +} + +/** @public */ +export async function createRouter( + options: RouterOptions, +): Promise { + const { logger, config, permissions } = options; + + const devToolsBackendApi = + options.devToolsBackendApi || new DevToolsBackendApi(logger, config); + + const router = Router(); + router.use(express.json()); + router.use( + createPermissionIntegrationRouter({ + permissions: devToolsPermissions, + }), + ); + + router.get('/health', (_req, res) => { + res.status(200).json({ status: 'ok' }); + }); + + router.get('/info', async (req, response) => { + const token = getBearerTokenFromAuthorizationHeader( + req.header('authorization'), + ); + + const decision = ( + await permissions.authorize( + [{ permission: devToolsInfoReadPermission }], + { + token, + }, + ) + )[0]; + + if (decision.result === AuthorizeResult.DENY) { + throw new NotAllowedError('Unauthorized'); + } + + const info = await devToolsBackendApi.listInfo(); + + response.status(200).json(info); + }); + + router.get('/config', async (req, response) => { + const token = getBearerTokenFromAuthorizationHeader( + req.header('authorization'), + ); + + const decision = ( + await permissions.authorize( + [{ permission: devToolsConfigReadPermission }], + { + token, + }, + ) + )[0]; + + if (decision.result === AuthorizeResult.DENY) { + throw new NotAllowedError('Unauthorized'); + } + + const configList = await devToolsBackendApi.listConfig(); + + response.status(200).json(configList); + }); + + router.get('/external-dependencies', async (req, response) => { + const token = getBearerTokenFromAuthorizationHeader( + req.header('authorization'), + ); + + const decision = ( + await permissions.authorize( + [{ permission: devToolsExternalDependenciesReadPermission }], + { + token, + }, + ) + )[0]; + + if (decision.result === AuthorizeResult.DENY) { + throw new NotAllowedError('Unauthorized'); + } + + const health = await devToolsBackendApi.listExternalDependencyDetails(); + + response.status(200).json(health); + }); + + router.use(errorHandler()); + return router; +} diff --git a/plugins/devtools-backend/src/service/standaloneServer.ts b/plugins/devtools-backend/src/service/standaloneServer.ts new file mode 100644 index 0000000000..d2fdce169d --- /dev/null +++ b/plugins/devtools-backend/src/service/standaloneServer.ts @@ -0,0 +1,68 @@ +/* + * Copyright 2022 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 { + ServerTokenManager, + SingleHostDiscovery, + createServiceBuilder, + loadBackendConfig, +} from '@backstage/backend-common'; + +import { Logger } from 'winston'; +import { Server } from 'http'; +import { ServerPermissionClient } from '@backstage/plugin-permission-node'; +import { createRouter } from './router'; + +export interface ServerOptions { + port: number; + enableCors: boolean; + logger: Logger; +} + +export async function startStandaloneServer( + options: ServerOptions, +): Promise { + const logger = options.logger.child({ service: 'devtools-backend-backend' }); + const config = await loadBackendConfig({ logger, argv: process.argv }); + const discovery = SingleHostDiscovery.fromConfig(config); + const tokenManager = ServerTokenManager.fromConfig(config, { + logger, + }); + const permissions = ServerPermissionClient.fromConfig(config, { + discovery, + tokenManager, + }); + logger.debug('Starting application server...'); + const router = await createRouter({ + logger, + config, + permissions, + }); + + let service = createServiceBuilder(module) + .setPort(options.port) + .addRouter('/devtools-backend', router); + if (options.enableCors) { + service = service.enableCors({ origin: 'http://localhost:3000' }); + } + + return await service.start().catch(err => { + logger.error(err); + process.exit(1); + }); +} + +module.hot?.accept(); diff --git a/plugins/devtools-backend/src/setupTests.ts b/plugins/devtools-backend/src/setupTests.ts new file mode 100644 index 0000000000..813cdeaae3 --- /dev/null +++ b/plugins/devtools-backend/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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. + */ + +export {}; diff --git a/plugins/devtools-backend/src/util/Lockfile.ts b/plugins/devtools-backend/src/util/Lockfile.ts new file mode 100644 index 0000000000..52dbb847bc --- /dev/null +++ b/plugins/devtools-backend/src/util/Lockfile.ts @@ -0,0 +1,317 @@ +/* + * Copyright 2022 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 fs from 'fs-extra'; +import semver from 'semver'; +import { parseSyml, stringifySyml } from '@yarnpkg/parsers'; +import { stringify as legacyStringifyLockfile } from '@yarnpkg/lockfile'; + +const ENTRY_PATTERN = /^((?:@[^/]+\/)?[^@/]+)@(.+)$/; + +type LockfileData = { + [entry: string]: { + version: string; + resolved?: string; + integrity?: string; + dependencies?: { [name: string]: string }; + }; +}; + +type LockfileQueryEntry = { + range: string; + version: string; +}; + +/** Entries that have an invalid version range, for example an npm tag */ +type AnalyzeResultInvalidRange = { + name: string; + range: string; +}; + +/** Entries that can be deduplicated by bumping to an existing higher version */ +type AnalyzeResultNewVersion = { + name: string; + range: string; + oldVersion: string; + newVersion: string; +}; + +/** Entries that would need a dependency update in package.json to be deduplicated */ +type AnalyzeResultNewRange = { + name: string; + oldRange: string; + newRange: string; + oldVersion: string; + newVersion: string; +}; + +type AnalyzeResult = { + invalidRanges: AnalyzeResultInvalidRange[]; + newVersions: AnalyzeResultNewVersion[]; + newRanges: AnalyzeResultNewRange[]; +}; + +function parseLockfile(lockfileContents: string) { + try { + return { + object: parseSyml(lockfileContents), + type: 'success', + }; + } catch (err) { + return { + object: null, + type: err, + }; + } +} + +// the new yarn header is handled out of band of the parsing +// https://github.com/yarnpkg/berry/blob/0c5974f193a9397630e9aee2b3876cca62611149/packages/yarnpkg-core/sources/Project.ts#L1741-L1746 +const NEW_HEADER = `${[ + `# This file is generated by running "yarn install" inside your project.\n`, + `# Manual changes might be lost - proceed with caution!\n`, +].join(``)}\n`; + +function stringifyLockfile(data: LockfileData, legacy: boolean) { + return legacy + ? legacyStringifyLockfile(data) + : NEW_HEADER + stringifySyml(data); +} +// taken from yarn parser package +// https://github.com/yarnpkg/berry/blob/0c5974f193a9397630e9aee2b3876cca62611149/packages/yarnpkg-parsers/sources/syml.ts#L136 +const LEGACY_REGEX = /^(#.*(\r?\n))*?#\s+yarn\s+lockfile\s+v1\r?\n/i; + +// these are special top level yarn keys. +// https://github.com/yarnpkg/berry/blob/9bd61fbffb83d0b8166a9cc26bec3a58743aa453/packages/yarnpkg-parsers/sources/syml.ts#L9 +const SPECIAL_OBJECT_KEYS = [ + `__metadata`, + `version`, + `resolution`, + `dependencies`, + `peerDependencies`, + `dependenciesMeta`, + `peerDependenciesMeta`, + `binaries`, +]; + +export class Lockfile { + static async load(path: string) { + const lockfileContents = await fs.readFile(path, 'utf8'); + const legacy = LEGACY_REGEX.test(lockfileContents); + const lockfile = parseLockfile(lockfileContents); + if (lockfile.type !== 'success') { + throw new Error(`Failed yarn.lock parse with ${lockfile.type}`); + } + + const data = lockfile.object as LockfileData; + const packages = new Map(); + + for (const [key, value] of Object.entries(data)) { + if (SPECIAL_OBJECT_KEYS.includes(key)) continue; + + const [, name, range] = ENTRY_PATTERN.exec(key) ?? []; + if (!name) { + throw new Error(`Failed to parse yarn.lock entry '${key}'`); + } + + let queries = packages.get(name); + if (!queries) { + queries = []; + packages.set(name, queries); + } + queries.push({ range, version: value.version }); + } + + return new Lockfile(path, packages, data, legacy); + } + + private constructor( + private readonly path: string, + private readonly packages: Map, + private readonly data: LockfileData, + private readonly legacy: boolean = false, + ) {} + + /** Get the entries for a single package in the lockfile */ + get(name: string): LockfileQueryEntry[] | undefined { + return this.packages.get(name); + } + + /** Returns the name of all packages available in the lockfile */ + keys(): IterableIterator { + return this.packages.keys(); + } + + /** Analyzes the lockfile to identify possible actions and warnings for the entries */ + analyze(options?: { filter?: (name: string) => boolean }): AnalyzeResult { + const { filter } = options ?? {}; + const result: AnalyzeResult = { + invalidRanges: [], + newVersions: [], + newRanges: [], + }; + + for (const [name, allEntries] of this.packages) { + if (filter && !filter(name)) { + continue; + } + + // Get rid of and signal any invalid ranges upfront + const invalid = allEntries.filter(e => !semver.validRange(e.range)); + result.invalidRanges.push( + ...invalid.map(({ range }) => ({ name, range })), + ); + + // Grab all valid entries, if there aren't at least 2 different valid ones we're done + const entries = allEntries.filter(e => semver.validRange(e.range)); + if (entries.length < 2) { + continue; + } + + // Find all versions currently in use + const versions = Array.from(new Set(entries.map(e => e.version))).sort( + (v1, v2) => semver.rcompare(v1, v2), + ); + + // If we're not using at least 2 different versions we're done + if (versions.length < 2) { + continue; + } + + const acceptedVersions = new Set(); + for (const { version, range } of entries) { + // Finds the highest matching version from the the known versions + // TODO(Rugvip): We may want to select the version that satisfies the most ranges rather than the highest one + const acceptedVersion = versions.find(v => semver.satisfies(v, range)); + if (!acceptedVersion) { + throw new Error( + `No existing version was accepted for range ${range}, searching through ${versions}, for package ${name}`, + ); + } + + if (acceptedVersion !== version) { + result.newVersions.push({ + name, + range, + newVersion: acceptedVersion, + oldVersion: version, + }); + } + + acceptedVersions.add(acceptedVersion); + } + + // If all ranges were able to accept the same version, we're done + if (acceptedVersions.size === 1) { + continue; + } + + // Find the max version that we may want bump older packages to + const maxVersion = Array.from(acceptedVersions).sort(semver.rcompare)[0]; + // Find all existing ranges that satisfy the new max version, and pick the one that + // results in the highest minimum allowed version, usually being the more specific one + const maxEntry = entries + .filter(e => semver.satisfies(maxVersion, e.range)) + .map(e => ({ e, min: semver.minVersion(e.range) })) + .filter(p => p.min) + .sort((a, b) => semver.rcompare(a.min!, b.min!))[0]?.e; + if (!maxEntry) { + throw new Error( + `No entry found that satisfies max version '${maxVersion}'`, + ); + } + + // Find all entries that don't satisfy the max version + for (const { version, range } of entries) { + if (semver.satisfies(maxVersion, range)) { + continue; + } + + result.newRanges.push({ + name, + oldRange: range, + newRange: maxEntry.range, + oldVersion: version, + newVersion: maxVersion, + }); + } + } + + return result; + } + + remove(name: string, range: string): boolean { + const query = `${name}@${range}`; + const existed = Boolean(this.data[query]); + delete this.data[query]; + + const newEntries = this.packages.get(name)?.filter(e => e.range !== range); + if (newEntries) { + this.packages.set(name, newEntries); + } + + return existed; + } + + /** Modifies the lockfile by bumping packages to the suggested versions */ + replaceVersions(results: AnalyzeResultNewVersion[]) { + for (const { name, range, oldVersion, newVersion } of results) { + const query = `${name}@${range}`; + + // Update the backing data + const entryData = this.data[query]; + if (!entryData) { + throw new Error(`No entry data for ${query}`); + } + if (entryData.version !== oldVersion) { + throw new Error( + `Expected existing version data for ${query} to be ${oldVersion}, was ${entryData.version}`, + ); + } + + // Modifying the data in the entry is not enough, we need to reference an existing version object + const matchingEntry = Object.entries(this.data).find( + ([q, e]) => q.startsWith(`${name}@`) && e.version === newVersion, + ); + if (!matchingEntry) { + throw new Error( + `No matching entry found for ${name} at version ${newVersion}`, + ); + } + this.data[query] = matchingEntry[1]; + + // Update our internal data structure + const entry = this.packages.get(name)?.find(e => e.range === range); + if (!entry) { + throw new Error(`No entry data for ${query}`); + } + if (entry.version !== oldVersion) { + throw new Error( + `Expected existing version data for ${query} to be ${oldVersion}, was ${entryData.version}`, + ); + } + entry.version = newVersion; + } + } + + async save() { + await fs.writeFile(this.path, this.toString(), 'utf8'); + } + + toString() { + return stringifyLockfile(this.data, this.legacy); + } +} diff --git a/plugins/devtools-common/.eslintrc.js b/plugins/devtools-common/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/devtools-common/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/devtools-common/CHANGELOG.md b/plugins/devtools-common/CHANGELOG.md new file mode 100644 index 0000000000..6a566d0a67 --- /dev/null +++ b/plugins/devtools-common/CHANGELOG.md @@ -0,0 +1,19 @@ +# @backstage/plugin-devtools-common + +## 0.1.0 + +### Minor Changes + +- 347aeca204c: Introduced the DevTools plugin, checkout the plugin's [`README.md`](https://github.com/backstage/backstage/tree/master/plugins/devtools) for more details! + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.5 + +## 0.1.0-next.0 + +### Minor Changes + +- 347aeca204c: Introduced the DevTools plugin, checkout the plugin's [`README.md`](https://github.com/backstage/backstage/tree/master/plugins/devtools) for more details! diff --git a/plugins/devtools-common/README.md b/plugins/devtools-common/README.md new file mode 100644 index 0000000000..5be5e58773 --- /dev/null +++ b/plugins/devtools-common/README.md @@ -0,0 +1,3 @@ +# DevTools Common + +Common types and permissions for the DevTools plugin. diff --git a/plugins/devtools-common/api-report.md b/plugins/devtools-common/api-report.md new file mode 100644 index 0000000000..6594b0d8a4 --- /dev/null +++ b/plugins/devtools-common/api-report.md @@ -0,0 +1,75 @@ +## API Report File for "@backstage/plugin-devtools-common" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BasicPermission } from '@backstage/plugin-permission-common'; +import { JsonValue } from '@backstage/types'; + +// @public (undocumented) +export type ConfigError = { + name: string; + message: string; + messages?: string[]; + stack?: string; +}; + +// @public (undocumented) +export type ConfigInfo = { + config?: JsonValue; + error?: ConfigError; +}; + +// @public (undocumented) +export const devToolsAdministerPermission: BasicPermission; + +// @public (undocumented) +export const devToolsConfigReadPermission: BasicPermission; + +// @public (undocumented) +export const devToolsExternalDependenciesReadPermission: BasicPermission; + +// @public (undocumented) +export type DevToolsInfo = { + operatingSystem: string; + nodeJsVersion: string; + backstageVersion: string; + dependencies: PackageDependency[]; +}; + +// @public (undocumented) +export const devToolsInfoReadPermission: BasicPermission; + +// @public +export const devToolsPermissions: BasicPermission[]; + +// @public (undocumented) +export type Endpoint = { + name: string; + type: string; + target: string; +}; + +// @public (undocumented) +export type ExternalDependency = { + name: string; + type: string; + target: string; + status: string; + error?: string; +}; + +// @public (undocumented) +export enum ExternalDependencyStatus { + // (undocumented) + healthy = 'Healthy', + // (undocumented) + unhealthy = 'Unhealthy', +} + +// @public (undocumented) +export type PackageDependency = { + name: string; + versions: string; +}; +``` diff --git a/plugins/devtools-common/package.json b/plugins/devtools-common/package.json new file mode 100644 index 0000000000..0e114e39b9 --- /dev/null +++ b/plugins/devtools-common/package.json @@ -0,0 +1,35 @@ +{ + "name": "@backstage/plugin-devtools-common", + "description": "Common functionalities for the devtools plugin", + "version": "0.1.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "module": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "common-library" + }, + "scripts": { + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/plugin-permission-common": "workspace:^", + "@backstage/types": "workspace:^" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/devtools-common/src/index.ts b/plugins/devtools-common/src/index.ts new file mode 100644 index 0000000000..be7426394b --- /dev/null +++ b/plugins/devtools-common/src/index.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2022 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. + */ + +/** + * Common types and permissions for the DevTools frontend and backend plugins. + * + * @packageDocumentation + */ + +export * from './types'; +export * from './permissions'; diff --git a/plugins/devtools-common/src/permissions.ts b/plugins/devtools-common/src/permissions.ts new file mode 100644 index 0000000000..ba464f7d80 --- /dev/null +++ b/plugins/devtools-common/src/permissions.ts @@ -0,0 +1,61 @@ +/* + * Copyright 2022 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 { createPermission } from '@backstage/plugin-permission-common'; + +/** + * @public + */ +export const devToolsAdministerPermission = createPermission({ + name: 'devtools.administer', + attributes: { action: 'read' }, +}); + +/** + * @public + */ +export const devToolsInfoReadPermission = createPermission({ + name: 'devtools.info', + attributes: { action: 'read' }, +}); + +/** + * @public + */ +export const devToolsConfigReadPermission = createPermission({ + name: 'devtools.config', + attributes: { action: 'read' }, +}); + +/** + * @public + */ +export const devToolsExternalDependenciesReadPermission = createPermission({ + name: 'devtools.external-dependencies', + attributes: { action: 'read' }, +}); + +/** + * List of all Devtools permissions + * + * @public + */ +export const devToolsPermissions = [ + devToolsAdministerPermission, + devToolsInfoReadPermission, + devToolsConfigReadPermission, + devToolsExternalDependenciesReadPermission, +]; diff --git a/plugins/devtools-common/src/setupTests.ts b/plugins/devtools-common/src/setupTests.ts new file mode 100644 index 0000000000..813cdeaae3 --- /dev/null +++ b/plugins/devtools-common/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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. + */ + +export {}; diff --git a/plugins/devtools-common/src/types.ts b/plugins/devtools-common/src/types.ts new file mode 100644 index 0000000000..d08232b155 --- /dev/null +++ b/plugins/devtools-common/src/types.ts @@ -0,0 +1,67 @@ +/* + * Copyright 2022 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 { JsonValue } from '@backstage/types'; + +/** @public */ +export type Endpoint = { + name: string; + type: string; + target: string; +}; + +/** @public */ +export type ExternalDependency = { + name: string; + type: string; + target: string; + status: string; + error?: string; +}; + +/** @public */ +export type DevToolsInfo = { + operatingSystem: string; + nodeJsVersion: string; + backstageVersion: string; + dependencies: PackageDependency[]; +}; + +/** @public */ +export type PackageDependency = { + name: string; + versions: string; +}; + +/** @public */ +export enum ExternalDependencyStatus { + healthy = 'Healthy', + unhealthy = 'Unhealthy', +} + +/** @public */ +export type ConfigInfo = { + config?: JsonValue; + error?: ConfigError; +}; + +/** @public */ +export type ConfigError = { + name: string; + message: string; + messages?: string[]; + stack?: string; +}; diff --git a/plugins/devtools/.eslintrc.js b/plugins/devtools/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/devtools/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/devtools/CHANGELOG.md b/plugins/devtools/CHANGELOG.md new file mode 100644 index 0000000000..c9db73ff44 --- /dev/null +++ b/plugins/devtools/CHANGELOG.md @@ -0,0 +1,46 @@ +# @backstage/plugin-devtools + +## 0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-devtools-common@0.1.0 + +## 0.1.0 + +### Minor Changes + +- 347aeca204c: Introduced the DevTools plugin, checkout the plugin's [`README.md`](https://github.com/backstage/backstage/tree/master/plugins/devtools) for more details! + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-devtools-common@0.1.0 + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-react@0.4.12 + +## 0.1.0-next.0 + +### Minor Changes + +- 347aeca204c: Introduced the DevTools plugin, checkout the plugin's [`README.md`](https://github.com/backstage/backstage/tree/master/plugins/devtools) for more details! + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-devtools-common@0.1.0-next.0 + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 diff --git a/plugins/devtools/README.md b/plugins/devtools/README.md new file mode 100644 index 0000000000..26226d2976 --- /dev/null +++ b/plugins/devtools/README.md @@ -0,0 +1,375 @@ +# DevTools + +Welcome to the DevTools plugin! This plugin helps elevate useful information about a Backstage instance through the frontend, which can be helpful for an integrator for troubleshooting, reviewing, and understanding their installation. + +## Features + +The DevTools plugin comes with two tabs out of the box. + +### Info + +Lists helpful information about your current running Backstage instance such as: OS, NodeJS version, Backstage version, and package versions. + +![Example of Info tab](./docs/devtools-info-tab.png) + +### Config + +Lists the configuration being used by your current running Backstage instance. + +![Example of Config tab](./docs/devtools-config-tab.png) + +## Optional Features + +The DevTools plugin can be setup with other tabs with additional helpful features. + +### External Dependencies + +Lists the status of configured External Dependencies based on your current running Backstage instance's ability to reach them. + +![Example of external dependencies tab](./docs/devtools-external-dependencies.png) + +## Setup + +The following sections will help you get the DevTools plugin setup and running. + +### Backend + +You need to setup the [DevTools backend plugin](../devtools-backend/README.md) before you move forward with any of the following steps if you haven't already. + +### Frontend + +To setup the DevTools frontend you'll need to do the following steps: + +1. First we need to add the `@backstage/plugin-devtools` package to your frontend app: + + ```sh + # From your Backstage root directory + yarn add --cwd packages/app @backstage/plugin-devtools + ``` + +2. Now open the `packages/app/src/App.tsx` file +3. Then after all the import statements add the following line: + + ```ts + import { DevToolsPage } from '@backstage/plugin-devtools'; + ``` + +4. In this same file just before the closing ``, this will be near the bottom of the file, add this line: + + ```ts + } /> + ``` + +5. Next open the `packages/app/src/components/Root/Root.tsx` file +6. We want to add this icon import after all the existing import statements: + + ```ts + import BuildIcon from '@material-ui/icons/Build'; + ``` + +7. Then add this line just after the `` line: + + ```ts + + ``` + +8. Now run `yarn dev` from the root of your project and you should see the DevTools option show up just below Settings in your sidebar and clicking on it will get you to the [Info tab](#info) + +## Customizing + +The DevTools plugin has been designed so that you can customize the tabs to suite your needs. You may only want some or none of the out of the box tabs or you may want to add your own. The following sections explains how to do that (assuming you've already done the [setup steps](#setup)). As part of this example we'll also be showing how you can add the optional [External Dependencies](#external-dependencies) tab. + +1. In the `packages/app/src/components` folder create a new sub-folder called `devtools` +2. Then in this new `devtools` folder add a file called `CustomDevToolsPage.tsx` +3. In the `CustomDevToolsPage.tsx` file add the following content: + + ```tsx + import { + ConfigContent, + ExternalDependenciesContent, + InfoContent, + } from '@backstage/plugin-devtools'; + import { DevToolsLayout } from '@backstage/plugin-devtools'; + import React from 'react'; + + export const DevToolsPage = () => { + return ( + + + + + + + + + + + + ); + }; + + export const customDevToolsPage = ; + ``` + +4. Now open the `packages/app/src/App.tsx` file and add the following import after all the existing import statements: + + ```ts + import { customDevToolsPage } from './components/devtools/CustomDevToolsPage'; + ``` + +5. Then we need to adjust our route as follows + + ```diff + - } /> + + } > + + {customDevToolsPage} + + + ``` + +6. Now run `yarn dev` from the root of your project. When you go to the DevTools you'll now see you have a third tab for [External Dependencies](#external-dependencies) + +With this setup you can add or remove the tabs as you'd like or add your own simply by editing your `CustomDevToolsPage.tsx` file + +## Permissions + +The DevTools plugin supports the [permissions framework](https://backstage.io/docs/permissions/overview), the following sections outline how you can use them with the assumption that you have the permissions framework setup and working. + +**Note:** These sections are intended as guidance and are completely optional. The DevTools plugin will work with the permission framework off or on without any specific policy setup. + +### Secure Sidebar Option + +To use the permission framework to secure the DevTools sidebar option you'll want to do the following: + +1. First we need to add the `@backstage/plugin-devtools-common` package to your frontend app: + + ```sh + # From your Backstage root directory + yarn add --cwd packages/app @backstage/plugin-devtools-common + ``` + +2. Then open the `packages/app/src/components/Root/Root.tsx` file +3. The add these imports after all the existing import statements: + + ```ts + import { devToolsAdministerPermission } from '@backstage/plugin-devtools-common'; + import { RequirePermission } from '@backstage/plugin-permission-react'; + ``` + +4. Then make the following change: + + ```diff + - + + }> + + + + + ``` + +### Secure the DevTools Route + +To use the permission framework to secure the DevTools route you'll want to do the following: + +1. First we need to add the `@backstage/plugin-devtools-common` package to your frontend app (skip this step if you've already done this): + + ```sh + # From your Backstage root directory + yarn add --cwd packages/app @backstage/plugin-devtools-common + ``` + +2. Then open the `packages/app/src/App.tsx` file +3. The add this import after all the existing import statements: + + ```ts + import { devToolsAdministerPermission } from '@backstage/plugin-devtools-common'; + ``` + +4. Then make the following change: + + ```diff + - } /> + + + + + + + + } + + /> + ``` + +Note: if you are using a `customDevToolsPage` as per the [Customizing](#customizing) documentation the changes for Step 4 will be: + +```diff +- } /> ++ ++ ++ ++ } ++ > ++ {customDevToolsPage} ++ +``` + +### Permission Policy + +Here is an example permission policy that you might use to secure the DevTools plugin: + +```ts +// packages/backend/src/plugins/permission.ts + +class TestPermissionPolicy implements PermissionPolicy { + async handle(request: PolicyQuery): Promise { + if (isPermission(request.permission, devToolsAdministerPermission)) { + if ( + user?.identity.ownershipEntityRefs.includes( + 'group:default/backstage-admins', + ) + ) { + return { result: AuthorizeResult.ALLOW }; + } + return { result: AuthorizeResult.DENY }; + } + + if (isPermission(request.permission, devToolsInfoReadPermission)) { + if ( + user?.identity.ownershipEntityRefs.includes( + 'group:default/backstage-admins', + ) + ) { + return { result: AuthorizeResult.ALLOW }; + } + return { result: AuthorizeResult.DENY }; + } + + if (isPermission(request.permission, devToolsConfigReadPermission)) { + if ( + user?.identity.ownershipEntityRefs.includes( + 'group:default/backstage-admins', + ) + ) { + return { result: AuthorizeResult.ALLOW }; + } + return { result: AuthorizeResult.DENY }; + } + + if ( + isPermission( + request.permission, + devToolsExternalDependenciesReadPermission, + ) + ) { + if ( + user?.identity.ownershipEntityRefs.includes( + 'group:default/backstage-admins', + ) + ) { + return { result: AuthorizeResult.ALLOW }; + } + return { result: AuthorizeResult.DENY }; + } + + return { result: AuthorizeResult.ALLOW }; + } +} +``` + +To use this policy you'll need to make sure to add the `@backstage/plugin-devtools-common` package to your backend you can do that by running this command: + +```sh +# From your Backstage root directory +yarn add --cwd packages/backend @backstage/plugin-devtools-common +``` + +You'll also need to add these imports: + +```ts +import { + devToolsAdministerPermission, + devToolsConfigReadPermission, + devToolsExternalDependenciesReadPermission, + devToolsInfoReadPermission, +} from '@backstage/plugin-devtools-common'; +``` + +**Note:** The group "group:default/backstage-admins" is simply an example and does not exist. You can point this to any group you have in your catalog instead. + +### Customizing with Permissions + +If you followed the [Customizing](#customizing) documentation and want to use permission there this is what your `CustomDevToolsPage.tsx` would look like: + +```tsx +import { + ConfigContent, + ExternalDependenciesContent, + InfoContent, +} from '@backstage/plugin-devtools'; +import { DevToolsLayout } from '@backstage/plugin-devtools'; +import { + devToolsConfigReadPermission, + devToolsExternalDependenciesReadPermission, + devToolsInfoReadPermission, +} from '@backstage/plugin-devtools-common'; +import { RequirePermission } from '@backstage/plugin-permission-react'; +import React from 'react'; + +const DevToolsPage = () => { + return ( + + + + + + + + + + + + + + + + + + ); +}; + +export const customDevToolsPage = ; +``` + +## Configuration + +The following sections outline the configuration for the DevTools plugin + +### External Dependencies Configuration + +If you decide to use the External Dependencies tab then you'll need to setup the configuration for it in your `app-config.yaml`, if there is no config setup then the tab will be empty. Here's an example: + +```yaml +devTools: + externalDependencies: + endpoints: + - name: 'Google' + type: 'fetch' + target: 'https://google.ca' + - name: 'Google Public DNS' + type: 'ping' + target: '8.8.8.8' +``` + +Configuration details: + +- `endpoints` is an array +- `name` is the friendly name for your endpoint +- `type` can be either `ping` or `fetch` and will perform the respective action on the `target` +- `target` is either a URL or server that you want to trigger a `type` action on diff --git a/plugins/devtools/api-report.md b/plugins/devtools/api-report.md new file mode 100644 index 0000000000..c9cfbf77e5 --- /dev/null +++ b/plugins/devtools/api-report.md @@ -0,0 +1,57 @@ +## API Report File for "@backstage/plugin-devtools" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { BackstagePlugin } from '@backstage/core-plugin-api'; +import { default as default_2 } from 'react'; +import { RouteRef } from '@backstage/core-plugin-api'; +import { TabProps } from '@material-ui/core'; + +// @public (undocumented) +export const ConfigContent: () => JSX.Element; + +// @public +export const DevToolsLayout: { + ({ children }: DevToolsLayoutProps): JSX.Element; + Route: (props: SubRoute) => null; +}; + +// @public (undocumented) +export type DevToolsLayoutProps = { + children?: default_2.ReactNode; +}; + +// @public (undocumented) +export const DevToolsPage: () => JSX.Element; + +// @public (undocumented) +export const devToolsPlugin: BackstagePlugin< + { + root: RouteRef; + }, + {}, + {} +>; + +// @public (undocumented) +export const ExternalDependenciesContent: () => JSX.Element; + +// @public (undocumented) +export const InfoContent: () => JSX.Element; + +// @public (undocumented) +export type SubRoute = { + path: string; + title: string; + children: JSX.Element; + tabProps?: TabProps< + default_2.ElementType, + { + component?: default_2.ElementType; + } + >; +}; +``` diff --git a/plugins/devtools/dev/index.tsx b/plugins/devtools/dev/index.tsx new file mode 100644 index 0000000000..00c966a801 --- /dev/null +++ b/plugins/devtools/dev/index.tsx @@ -0,0 +1,27 @@ +/* + * Copyright 2022 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 { createDevApp } from '@backstage/dev-utils'; +import { devToolsPlugin, DevToolsPage } from '../src/plugin'; + +createDevApp() + .registerPlugin(devToolsPlugin) + .addPage({ + element: , + title: 'Root Page', + path: '/devtools', + }) + .render(); diff --git a/plugins/devtools/docs/devtools-config-tab.png b/plugins/devtools/docs/devtools-config-tab.png new file mode 100644 index 0000000000..b5c22f691b Binary files /dev/null and b/plugins/devtools/docs/devtools-config-tab.png differ diff --git a/plugins/devtools/docs/devtools-external-dependencies.png b/plugins/devtools/docs/devtools-external-dependencies.png new file mode 100644 index 0000000000..9356d83ef5 Binary files /dev/null and b/plugins/devtools/docs/devtools-external-dependencies.png differ diff --git a/plugins/devtools/docs/devtools-info-tab.png b/plugins/devtools/docs/devtools-info-tab.png new file mode 100644 index 0000000000..739045a77f Binary files /dev/null and b/plugins/devtools/docs/devtools-info-tab.png differ diff --git a/plugins/devtools/package.json b/plugins/devtools/package.json new file mode 100644 index 0000000000..3023c83d71 --- /dev/null +++ b/plugins/devtools/package.json @@ -0,0 +1,64 @@ +{ + "name": "@backstage/plugin-devtools", + "version": "0.1.1-next.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "frontend-plugin" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/devtools" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/core-components": "workspace:^", + "@backstage/core-plugin-api": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/plugin-devtools-common": "workspace:^", + "@backstage/plugin-permission-react": "workspace:^", + "@backstage/theme": "workspace:^", + "@backstage/types": "workspace:^", + "@material-ui/core": "^4.9.13", + "@material-ui/icons": "^4.9.1", + "@material-ui/lab": "^4.0.0-alpha.57", + "react-json-view": "^1.21.3", + "react-use": "^17.2.4" + }, + "peerDependencies": { + "@types/react": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17.0.0", + "react-router-dom": "6.0.0-beta.0 || ^6.3.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@backstage/core-app-api": "workspace:^", + "@backstage/dev-utils": "workspace:^", + "@backstage/test-utils": "workspace:^", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^12.1.3", + "@testing-library/user-event": "^14.0.0", + "@types/node": "*", + "cross-fetch": "^3.1.5", + "msw": "^1.0.0" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/devtools/src/api/DevToolsApi.ts b/plugins/devtools/src/api/DevToolsApi.ts new file mode 100644 index 0000000000..ff58a4ea16 --- /dev/null +++ b/plugins/devtools/src/api/DevToolsApi.ts @@ -0,0 +1,32 @@ +/* + * Copyright 2022 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 { createApiRef } from '@backstage/core-plugin-api'; +import { + ConfigInfo, + DevToolsInfo, + ExternalDependency, +} from '@backstage/plugin-devtools-common'; + +export const devToolsApiRef = createApiRef({ + id: 'plugin.devtools.service', +}); + +export interface DevToolsApi { + getConfig(): Promise; + getExternalDependencies(): Promise; + getInfo(): Promise; +} diff --git a/plugins/devtools/src/api/DevToolsClient.ts b/plugins/devtools/src/api/DevToolsClient.ts new file mode 100644 index 0000000000..0be8294b3f --- /dev/null +++ b/plugins/devtools/src/api/DevToolsClient.ts @@ -0,0 +1,78 @@ +/* + * Copyright 2022 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 { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api'; +import { + ConfigInfo, + DevToolsInfo, + ExternalDependency, +} from '@backstage/plugin-devtools-common'; +import { ResponseError } from '@backstage/errors'; +import { DevToolsApi } from './DevToolsApi'; + +export class DevToolsClient implements DevToolsApi { + private readonly discoveryApi: DiscoveryApi; + private readonly identityApi: IdentityApi; + + public constructor(options: { + discoveryApi: DiscoveryApi; + identityApi: IdentityApi; + }) { + this.discoveryApi = options.discoveryApi; + this.identityApi = options.identityApi; + } + + public async getConfig(): Promise { + const urlSegment = 'config'; + + const configInfo = await this.get(urlSegment); + return configInfo; + } + + public async getExternalDependencies(): Promise< + ExternalDependency[] | undefined + > { + const urlSegment = 'external-dependencies'; + + const externalDependencies = await this.get< + ExternalDependency[] | undefined + >(urlSegment); + return externalDependencies; + } + + public async getInfo(): Promise { + const urlSegment = 'info'; + + const info = await this.get(urlSegment); + return info; + } + + private async get(path: string): Promise { + const baseUrl = `${await this.discoveryApi.getBaseUrl('devtools')}/`; + const url = new URL(path, baseUrl); + + const { token } = await this.identityApi.getCredentials(); + const response = await fetch(url.toString(), { + headers: token ? { Authorization: `Bearer ${token}` } : {}, + }); + + if (!response.ok) { + throw await ResponseError.fromResponse(response); + } + + return response.json() as Promise; + } +} diff --git a/plugins/devtools/src/api/index.ts b/plugins/devtools/src/api/index.ts new file mode 100644 index 0000000000..6bea0a07aa --- /dev/null +++ b/plugins/devtools/src/api/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2022 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. + */ + +export * from './DevToolsApi'; +export * from './DevToolsClient'; diff --git a/plugins/devtools/src/components/Content/ConfigContent/ConfigContent.tsx b/plugins/devtools/src/components/Content/ConfigContent/ConfigContent.tsx new file mode 100644 index 0000000000..66129b5dae --- /dev/null +++ b/plugins/devtools/src/components/Content/ConfigContent/ConfigContent.tsx @@ -0,0 +1,95 @@ +/* + * Copyright 2022 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 { Progress, WarningPanel } from '@backstage/core-components'; +import { + Box, + createStyles, + makeStyles, + Paper, + Theme, + Typography, + useTheme, +} from '@material-ui/core'; +import { Alert } from '@material-ui/lab'; +import React from 'react'; +import ReactJson from 'react-json-view'; +import { useConfig } from '../../../hooks'; +import { ConfigError } from '@backstage/plugin-devtools-common'; + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + warningStyle: { + paddingBottom: theme.spacing(2), + }, + paperStyle: { + padding: theme.spacing(2), + }, + }), +); + +export const WarningContent = ({ error }: { error: ConfigError }) => { + if (!error.messages) { + return {error.message}; + } + + const messages = error.messages as string[]; + + return ( + + {messages.map(message => ( + {message} + ))} + + ); +}; + +/** @public */ +export const ConfigContent = () => { + const classes = useStyles(); + const theme = useTheme(); + const { configInfo, loading, error } = useConfig(); + + if (loading) { + return ; + } else if (error) { + return {error.message}; + } + + if (!configInfo) { + return Unable to load config data; + } + + return ( + + {configInfo && configInfo.error && ( + + + + + + )} + + + + + ); +}; diff --git a/plugins/devtools/src/components/Content/ConfigContent/index.ts b/plugins/devtools/src/components/Content/ConfigContent/index.ts new file mode 100644 index 0000000000..b1cc671de8 --- /dev/null +++ b/plugins/devtools/src/components/Content/ConfigContent/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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. + */ + +export { ConfigContent } from './ConfigContent'; diff --git a/plugins/devtools/src/components/Content/ExternalDependenciesContent/ExternalDependenciesContent.tsx b/plugins/devtools/src/components/Content/ExternalDependenciesContent/ExternalDependenciesContent.tsx new file mode 100644 index 0000000000..a5dd825fe5 --- /dev/null +++ b/plugins/devtools/src/components/Content/ExternalDependenciesContent/ExternalDependenciesContent.tsx @@ -0,0 +1,140 @@ +/* + * Copyright 2022 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 { + Progress, + StatusError, + StatusOK, + StatusWarning, + Table, + TableColumn, +} from '@backstage/core-components'; +import { ExternalDependency } from '@backstage/plugin-devtools-common'; +import { + Box, + createStyles, + Grid, + makeStyles, + Paper, + Theme, + Typography, +} from '@material-ui/core'; +import { Alert } from '@material-ui/lab'; +import React from 'react'; +import { useExternalDependencies } from '../../../hooks'; + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + paperStyle: { + padding: theme.spacing(2), + }, + }), +); + +export const getExternalDependencyStatus = ( + result: Partial | undefined, +) => { + switch (result?.status) { + case 'Healthy': + return ( + + {result.status} + + ); + case 'Unhealthy': + return ( + + {`${result.status}`} + + ); + case undefined: + default: + return ( + + Unknown + + ); + } +}; + +const columns: TableColumn[] = [ + { + title: 'Name', + width: 'auto', + field: 'name', + }, + { + title: 'Target', + width: 'auto', + field: 'target', + }, + { + title: 'Type', + width: 'auto', + field: 'type', + }, + { + title: 'Status', + width: 'auto', + render: (row: Partial) => ( + + + + {getExternalDependencyStatus(row)} + + + {row.error && {row.error}} + + ), + }, +]; + +/** @public */ +export const ExternalDependenciesContent = () => { + const classes = useStyles(); + const { externalDependencies, loading, error } = useExternalDependencies(); + + if (loading) { + return ; + } else if (error) { + return {error.message}; + } + + if (!externalDependencies || externalDependencies.length === 0) { + return ( + + + No external dependencies found + + + ); + } + + return ( + + ); +}; diff --git a/plugins/devtools/src/components/Content/ExternalDependenciesContent/index.ts b/plugins/devtools/src/components/Content/ExternalDependenciesContent/index.ts new file mode 100644 index 0000000000..bf747f3065 --- /dev/null +++ b/plugins/devtools/src/components/Content/ExternalDependenciesContent/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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. + */ + +export { ExternalDependenciesContent } from './ExternalDependenciesContent'; diff --git a/plugins/devtools/src/components/Content/InfoContent/BackstageLogoIcon.tsx b/plugins/devtools/src/components/Content/InfoContent/BackstageLogoIcon.tsx new file mode 100644 index 0000000000..32f35600f2 --- /dev/null +++ b/plugins/devtools/src/components/Content/InfoContent/BackstageLogoIcon.tsx @@ -0,0 +1,25 @@ +/* + * Copyright 2022 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 { SvgIcon, SvgIconProps } from '@material-ui/core'; + +import React from 'react'; + +export const BackstageLogoIcon = (props: SvgIconProps) => ( + + + +); diff --git a/plugins/devtools/src/components/Content/InfoContent/InfoContent.tsx b/plugins/devtools/src/components/Content/InfoContent/InfoContent.tsx new file mode 100644 index 0000000000..7a0ebb3e06 --- /dev/null +++ b/plugins/devtools/src/components/Content/InfoContent/InfoContent.tsx @@ -0,0 +1,138 @@ +/* + * Copyright 2022 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 { Progress } from '@backstage/core-components'; +import { + Avatar, + Box, + createStyles, + Divider, + List, + ListItem, + ListItemAvatar, + ListItemText, + makeStyles, + Paper, + Theme, +} from '@material-ui/core'; +import { Alert } from '@material-ui/lab'; +import React from 'react'; +import { useInfo } from '../../../hooks'; +import { InfoDependenciesTable } from './InfoDependenciesTable'; +import DescriptionIcon from '@material-ui/icons/Description'; +import DeveloperBoardIcon from '@material-ui/icons/DeveloperBoard'; +import { BackstageLogoIcon } from './BackstageLogoIcon'; +import FileCopyIcon from '@material-ui/icons/FileCopy'; +import { DevToolsInfo } from '@backstage/plugin-devtools-common'; + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + paperStyle: { + marginBottom: theme.spacing(2), + }, + flexContainer: { + display: 'flex', + flexDirection: 'row', + padding: 0, + }, + copyButton: { + float: 'left', + margin: theme.spacing(2), + }, + }), +); + +const copyToClipboard = ({ about }: { about: DevToolsInfo | undefined }) => { + if (about) { + let formatted = `OS: ${about.operatingSystem}\nnode: ${about.nodeJsVersion}\nbackstage: ${about.backstageVersion}\nDependencies:\n`; + const deps = about.dependencies; + for (const key in deps) { + if (Object.prototype.hasOwnProperty.call(deps, key)) { + formatted = `${formatted} ${deps[key].name}: ${deps[key].versions}\n`; + } + } + window.navigator.clipboard.writeText(formatted); + } +}; + +/** @public */ +export const InfoContent = () => { + const classes = useStyles(); + const { about, loading, error } = useInfo(); + + if (loading) { + return ; + } else if (error) { + return {error.message}; + } + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { + copyToClipboard({ about }); + }} + className={classes.copyButton} + > + + + + + + + + + + + + ); +}; diff --git a/plugins/devtools/src/components/Content/InfoContent/InfoDependenciesTable.tsx b/plugins/devtools/src/components/Content/InfoContent/InfoDependenciesTable.tsx new file mode 100644 index 0000000000..e1ab59f279 --- /dev/null +++ b/plugins/devtools/src/components/Content/InfoContent/InfoDependenciesTable.tsx @@ -0,0 +1,55 @@ +/* + * Copyright 2022 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 { Table, TableColumn } from '@backstage/core-components'; +import { PackageDependency } from '@backstage/plugin-devtools-common'; + +import React from 'react'; + +const columns: TableColumn[] = [ + { + title: 'Name', + width: 'auto', + field: 'name', + defaultSort: 'asc', + }, + { + title: 'Versions', + width: 'auto', + field: 'versions', + }, +]; + +export const InfoDependenciesTable = ({ + infoDependencies, +}: { + infoDependencies: PackageDependency[] | undefined; +}) => { + return ( +
+ ); +}; diff --git a/plugins/devtools/src/components/Content/InfoContent/index.ts b/plugins/devtools/src/components/Content/InfoContent/index.ts new file mode 100644 index 0000000000..6d5bad53f8 --- /dev/null +++ b/plugins/devtools/src/components/Content/InfoContent/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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. + */ + +export { InfoContent } from './InfoContent'; diff --git a/plugins/devtools/src/components/Content/index.ts b/plugins/devtools/src/components/Content/index.ts new file mode 100644 index 0000000000..f5bd64f7c0 --- /dev/null +++ b/plugins/devtools/src/components/Content/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright 2022 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. + */ + +export * from './ConfigContent'; +export * from './InfoContent'; +export * from './ExternalDependenciesContent'; diff --git a/plugins/devtools/src/components/DefaultDevToolsPage/DefaultDevToolsPage.tsx b/plugins/devtools/src/components/DefaultDevToolsPage/DefaultDevToolsPage.tsx new file mode 100644 index 0000000000..a5e4f2439b --- /dev/null +++ b/plugins/devtools/src/components/DefaultDevToolsPage/DefaultDevToolsPage.tsx @@ -0,0 +1,42 @@ +/* + * Copyright 2022 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 { + devToolsConfigReadPermission, + devToolsInfoReadPermission, +} from '@backstage/plugin-devtools-common'; + +import { ConfigContent } from '../Content/ConfigContent'; +import { DevToolsLayout } from '../DevToolsLayout'; +import { InfoContent } from '../Content/InfoContent'; +import React from 'react'; +import { RequirePermission } from '@backstage/plugin-permission-react'; + +/** @public */ +export const DefaultDevToolsPage = () => ( + + + + + + + + + + + + +); diff --git a/plugins/devtools/src/components/DefaultDevToolsPage/index.ts b/plugins/devtools/src/components/DefaultDevToolsPage/index.ts new file mode 100644 index 0000000000..133dcf6e3a --- /dev/null +++ b/plugins/devtools/src/components/DefaultDevToolsPage/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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. + */ + +export { DefaultDevToolsPage } from './DefaultDevToolsPage'; diff --git a/plugins/devtools/src/components/DevToolsLayout/DevToolsLayout.tsx b/plugins/devtools/src/components/DevToolsLayout/DevToolsLayout.tsx new file mode 100644 index 0000000000..12cd3f7666 --- /dev/null +++ b/plugins/devtools/src/components/DevToolsLayout/DevToolsLayout.tsx @@ -0,0 +1,79 @@ +/* + * Copyright 2022 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 { Header, Page, RoutedTabs } from '@backstage/core-components'; +import { + attachComponentData, + useElementFilter, +} from '@backstage/core-plugin-api'; +import { TabProps } from '@material-ui/core'; +import { default as React } from 'react'; + +/** @public */ +export type SubRoute = { + path: string; + title: string; + children: JSX.Element; + tabProps?: TabProps; +}; + +const dataKey = 'plugin.devtools.devtoolsLayoutRoute'; + +const Route: (props: SubRoute) => null = () => null; +attachComponentData(Route, dataKey, true); + +// This causes all mount points that are discovered within this route to use the path of the route itself +attachComponentData(Route, 'core.gatherMountPoints', true); + +/** @public */ +export type DevToolsLayoutProps = { + children?: React.ReactNode; +}; + +/** + * DevTools is a compound component, which allows you to define a custom layout + * + * @example + * ```jsx + * + * + *
This is rendered under /example/anything-here route
+ *
+ *
+ * ``` + * @public + */ +export const DevToolsLayout = ({ children }: DevToolsLayoutProps) => { + const routes = useElementFilter(children, elements => + elements + .selectByComponentData({ + key: dataKey, + withStrictError: + 'Child of DevToolsLayout must be an DevToolsLayout.Route', + }) + .getElements() + .map(child => child.props), + ); + + return ( + +
+ + + ); +}; + +DevToolsLayout.Route = Route; diff --git a/plugins/devtools/src/components/DevToolsLayout/index.tsx b/plugins/devtools/src/components/DevToolsLayout/index.tsx new file mode 100644 index 0000000000..0bef371b05 --- /dev/null +++ b/plugins/devtools/src/components/DevToolsLayout/index.tsx @@ -0,0 +1,18 @@ +/* + * Copyright 2022 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. + */ + +export type { DevToolsLayoutProps, SubRoute } from './DevToolsLayout'; +export { DevToolsLayout } from './DevToolsLayout'; diff --git a/plugins/devtools/src/components/DevToolsPage/DevToolsPage.tsx b/plugins/devtools/src/components/DevToolsPage/DevToolsPage.tsx new file mode 100644 index 0000000000..880efed68c --- /dev/null +++ b/plugins/devtools/src/components/DevToolsPage/DevToolsPage.tsx @@ -0,0 +1,25 @@ +/* + * Copyright 2022 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 { useOutlet } from 'react-router-dom'; +import { DefaultDevToolsPage } from '../DefaultDevToolsPage'; + +export const DevToolsPage = () => { + const outlet = useOutlet(); + + return <>{outlet || }; +}; diff --git a/plugins/devtools/src/components/DevToolsPage/index.ts b/plugins/devtools/src/components/DevToolsPage/index.ts new file mode 100644 index 0000000000..88d8bc06fa --- /dev/null +++ b/plugins/devtools/src/components/DevToolsPage/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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. + */ + +export { DevToolsPage } from './DevToolsPage'; diff --git a/plugins/devtools/src/components/index.ts b/plugins/devtools/src/components/index.ts new file mode 100644 index 0000000000..9938866bcc --- /dev/null +++ b/plugins/devtools/src/components/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2022 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. + */ + +export * from './Content'; +export * from './DevToolsLayout'; diff --git a/plugins/devtools/src/hooks/index.ts b/plugins/devtools/src/hooks/index.ts new file mode 100644 index 0000000000..bb2e83d06f --- /dev/null +++ b/plugins/devtools/src/hooks/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright 2022 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. + */ + +export { useConfig } from './useConfig'; +export { useExternalDependencies } from './useExternalDependencies'; +export { useInfo } from './useInfo'; diff --git a/plugins/devtools/src/hooks/useConfig.ts b/plugins/devtools/src/hooks/useConfig.ts new file mode 100644 index 0000000000..6703e7ea59 --- /dev/null +++ b/plugins/devtools/src/hooks/useConfig.ts @@ -0,0 +1,37 @@ +/* + * Copyright 2022 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 { devToolsApiRef } from '../api'; +import { useApi } from '@backstage/core-plugin-api'; +import useAsync from 'react-use/lib/useAsync'; +import { ConfigInfo } from '@backstage/plugin-devtools-common'; + +export function useConfig(): { + configInfo?: ConfigInfo; + loading: boolean; + error?: Error; +} { + const api = useApi(devToolsApiRef); + const { value, loading, error } = useAsync(() => { + return api.getConfig(); + }, [api]); + + return { + configInfo: value, + loading, + error, + }; +} diff --git a/plugins/devtools/src/hooks/useExternalDependencies.ts b/plugins/devtools/src/hooks/useExternalDependencies.ts new file mode 100644 index 0000000000..df2f3e193b --- /dev/null +++ b/plugins/devtools/src/hooks/useExternalDependencies.ts @@ -0,0 +1,37 @@ +/* + * Copyright 2022 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 { devToolsApiRef } from '../api'; +import { useApi } from '@backstage/core-plugin-api'; +import useAsync from 'react-use/lib/useAsync'; +import { ExternalDependency } from '@backstage/plugin-devtools-common'; + +export function useExternalDependencies(): { + externalDependencies?: ExternalDependency[]; + loading: boolean; + error?: Error; +} { + const api = useApi(devToolsApiRef); + const { value, loading, error } = useAsync(() => { + return api.getExternalDependencies(); + }, [api]); + + return { + externalDependencies: value, + loading, + error, + }; +} diff --git a/plugins/devtools/src/hooks/useInfo.ts b/plugins/devtools/src/hooks/useInfo.ts new file mode 100644 index 0000000000..ad700cb3fe --- /dev/null +++ b/plugins/devtools/src/hooks/useInfo.ts @@ -0,0 +1,37 @@ +/* + * Copyright 2022 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 { devToolsApiRef } from '../api'; +import { useApi } from '@backstage/core-plugin-api'; +import useAsync from 'react-use/lib/useAsync'; +import { DevToolsInfo } from '@backstage/plugin-devtools-common'; + +export function useInfo(): { + about?: DevToolsInfo; + loading: boolean; + error?: Error; +} { + const api = useApi(devToolsApiRef); + const { value, loading, error } = useAsync(() => { + return api.getInfo(); + }, [api]); + + return { + about: value, + loading, + error, + }; +} diff --git a/plugins/devtools/src/index.ts b/plugins/devtools/src/index.ts new file mode 100644 index 0000000000..1077a2518c --- /dev/null +++ b/plugins/devtools/src/index.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2022 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. + */ + +/** + * Backstage DevTools frontend plugin with a tab that shows package dependencies and another tab that shows your current configuration. + * + * @packageDocumentation + */ + +export { devToolsPlugin, DevToolsPage } from './plugin'; +export * from './components'; diff --git a/plugins/devtools/src/plugin.test.ts b/plugins/devtools/src/plugin.test.ts new file mode 100644 index 0000000000..62f4ae5a61 --- /dev/null +++ b/plugins/devtools/src/plugin.test.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2022 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 { devToolsPlugin } from './plugin'; + +describe('devtools', () => { + it('should export plugin', () => { + expect(devToolsPlugin).toBeDefined(); + }); +}); diff --git a/plugins/devtools/src/plugin.ts b/plugins/devtools/src/plugin.ts new file mode 100644 index 0000000000..df2aca3447 --- /dev/null +++ b/plugins/devtools/src/plugin.ts @@ -0,0 +1,52 @@ +/* + * Copyright 2022 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 { + createApiFactory, + createPlugin, + createRoutableExtension, + discoveryApiRef, + identityApiRef, +} from '@backstage/core-plugin-api'; +import { devToolsApiRef, DevToolsClient } from './api'; + +import { rootRouteRef } from './routes'; + +/** @public */ +export const devToolsPlugin = createPlugin({ + id: 'devtools', + apis: [ + createApiFactory({ + api: devToolsApiRef, + deps: { discoveryApi: discoveryApiRef, identityApi: identityApiRef }, + factory: ({ discoveryApi, identityApi }) => + new DevToolsClient({ discoveryApi, identityApi }), + }), + ], + routes: { + root: rootRouteRef, + }, +}); + +/** @public */ +export const DevToolsPage = devToolsPlugin.provide( + createRoutableExtension({ + name: 'DevToolsPage', + component: () => + import('./components/DevToolsPage').then(m => m.DevToolsPage), + mountPoint: rootRouteRef, + }), +); diff --git a/plugins/devtools/src/routes.ts b/plugins/devtools/src/routes.ts new file mode 100644 index 0000000000..7825f928be --- /dev/null +++ b/plugins/devtools/src/routes.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2022 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 { createRouteRef } from '@backstage/core-plugin-api'; + +export const rootRouteRef = createRouteRef({ + id: 'devtools', +}); diff --git a/plugins/devtools/src/setupTests.ts b/plugins/devtools/src/setupTests.ts new file mode 100644 index 0000000000..7a459ed24e --- /dev/null +++ b/plugins/devtools/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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 '@testing-library/jest-dom'; diff --git a/plugins/dynatrace/CHANGELOG.md b/plugins/dynatrace/CHANGELOG.md index 5ede228812..ab21d254ac 100644 --- a/plugins/dynatrace/CHANGELOG.md +++ b/plugins/dynatrace/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-dynatrace +## 6.0.0-next.0 + +### Patch Changes + +- 3d11596a72b5: Update plugin installation docs to be more consistent across documentations +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 5.0.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 5.0.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 5.0.0-next.1 ### Patch Changes diff --git a/plugins/dynatrace/README.md b/plugins/dynatrace/README.md index b07fe985fe..3d14be9145 100644 --- a/plugins/dynatrace/README.md +++ b/plugins/dynatrace/README.md @@ -26,6 +26,7 @@ The Dynatrace plugin will require the following information, to be used in the c 1. Install the plugin on your frontend: ``` +# From your Backstage root directory yarn add --cwd packages/app @backstage/plugin-dynatrace ``` diff --git a/plugins/dynatrace/package.json b/plugins/dynatrace/package.json index b7c8244753..551830fd31 100644 --- a/plugins/dynatrace/package.json +++ b/plugins/dynatrace/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-dynatrace", - "version": "5.0.0-next.1", + "version": "6.0.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-feedback-backend/CHANGELOG.md b/plugins/entity-feedback-backend/CHANGELOG.md index 2ee2ffb799..70ea3b224e 100644 --- a/plugins/entity-feedback-backend/CHANGELOG.md +++ b/plugins/entity-feedback-backend/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-entity-feedback-backend +## 0.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-entity-feedback-common@0.1.1 + +## 0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/plugin-entity-feedback-common@0.1.1 + ## 0.1.3-next.1 ### Patch Changes diff --git a/plugins/entity-feedback-backend/package.json b/plugins/entity-feedback-backend/package.json index bfda97de8f..c47d574acf 100644 --- a/plugins/entity-feedback-backend/package.json +++ b/plugins/entity-feedback-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-feedback-backend", - "version": "0.1.3-next.1", + "version": "0.1.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-feedback/CHANGELOG.md b/plugins/entity-feedback/CHANGELOG.md index 3f4575ca8a..1d562e4c47 100644 --- a/plugins/entity-feedback/CHANGELOG.md +++ b/plugins/entity-feedback/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-entity-feedback +## 0.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-entity-feedback-common@0.1.1 + +## 0.2.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/plugin-entity-feedback-common@0.1.1 + +## 0.2.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.2.1-next.1 ### Patch Changes diff --git a/plugins/entity-feedback/package.json b/plugins/entity-feedback/package.json index 0c15a0f3c8..fd9afe389b 100644 --- a/plugins/entity-feedback/package.json +++ b/plugins/entity-feedback/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-feedback", - "version": "0.2.1-next.1", + "version": "0.2.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-validation/CHANGELOG.md b/plugins/entity-validation/CHANGELOG.md index 9b63d46c5b..2e0da12a3c 100644 --- a/plugins/entity-validation/CHANGELOG.md +++ b/plugins/entity-validation/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-entity-validation +## 0.1.4-next.0 + +### Patch Changes + +- 3d11596a72b5: Update plugin installation docs to be more consistent across documentations +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-catalog-common@1.0.13 + +## 0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/plugin-catalog-common@1.0.13 + +## 0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.3-next.1 ### Patch Changes diff --git a/plugins/entity-validation/README.md b/plugins/entity-validation/README.md index 1f864d0857..7816262836 100644 --- a/plugins/entity-validation/README.md +++ b/plugins/entity-validation/README.md @@ -9,6 +9,7 @@ This plugin creates a new page in Backstage where the user can validate the enti First of all, install the package in the `app` package by running the following command: ```bash +# From your Backstage root directory yarn add --cwd packages/app @backstage/plugin-entity-validation ``` diff --git a/plugins/entity-validation/package.json b/plugins/entity-validation/package.json index 674c5c6a56..2e366e6534 100644 --- a/plugins/entity-validation/package.json +++ b/plugins/entity-validation/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-validation", - "version": "0.1.3-next.1", + "version": "0.1.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-aws-sqs/CHANGELOG.md b/plugins/events-backend-module-aws-sqs/CHANGELOG.md index 9b076afbd3..6ed5764e5a 100644 --- a/plugins/events-backend-module-aws-sqs/CHANGELOG.md +++ b/plugins/events-backend-module-aws-sqs/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-events-backend-module-aws-sqs +## 0.2.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/types@1.0.2 + - @backstage/plugin-events-node@0.2.7-next.0 + +## 0.2.0 + +### Minor Changes + +- 2c5661f3899: Allow endpoint configuration for sqs, enabling use of localstack for testing. + +### Patch Changes + +- 3659c71c5d9: Standardize `@aws-sdk` v3 versions +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/types@1.0.2 + - @backstage/plugin-events-node@0.2.6 + +## 0.2.0-next.2 + +### Minor Changes + +- 2c5661f3899: Allow endpoint configuration for sqs, enabling use of localstack for testing. + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.7 + ## 0.1.7-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-aws-sqs/package.json b/plugins/events-backend-module-aws-sqs/package.json index 0125d5e5b4..efe222baeb 100644 --- a/plugins/events-backend-module-aws-sqs/package.json +++ b/plugins/events-backend-module-aws-sqs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-aws-sqs", - "version": "0.1.7-next.1", + "version": "0.2.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,7 +35,7 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@aws-sdk/client-sqs": "^3.208.0", + "@aws-sdk/client-sqs": "^3.310.0", "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/backend-tasks": "workspace:^", @@ -46,7 +46,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@aws-sdk/types": "^3.208.0", + "@aws-sdk/types": "^3.310.0", "@backstage/backend-common": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", diff --git a/plugins/events-backend-module-aws-sqs/src/publisher/AwsSqsConsumingEventPublisher.ts b/plugins/events-backend-module-aws-sqs/src/publisher/AwsSqsConsumingEventPublisher.ts index e649e2ee83..4f4e6ea55d 100644 --- a/plugins/events-backend-module-aws-sqs/src/publisher/AwsSqsConsumingEventPublisher.ts +++ b/plugins/events-backend-module-aws-sqs/src/publisher/AwsSqsConsumingEventPublisher.ts @@ -68,7 +68,11 @@ export class AwsSqsConsumingEventPublisher implements EventPublisher { VisibilityTimeout: config.visibilityTimeout?.as('seconds'), WaitTimeSeconds: config.pollingWaitTime.as('seconds'), }; - this.sqs = new SQSClient({ region: config.region }); + + this.sqs = new SQSClient({ + region: config.region, + endpoint: config.endpoint, + }); this.queueUrl = config.queueUrl; this.taskTimeoutSeconds = config.timeout.as('seconds'); diff --git a/plugins/events-backend-module-aws-sqs/src/publisher/config.test.ts b/plugins/events-backend-module-aws-sqs/src/publisher/config.test.ts index 1fa9df4ce3..6d7a08d7a7 100644 --- a/plugins/events-backend-module-aws-sqs/src/publisher/config.test.ts +++ b/plugins/events-backend-module-aws-sqs/src/publisher/config.test.ts @@ -79,6 +79,7 @@ describe('readConfig', () => { url: 'https://fake1.queue.url', visibilityTimeout: { minutes: 5 }, waitTime: { seconds: 10 }, + endpoint: 'https://fake.endpoint.url', }, timeout: { minutes: 5 }, waitTimeAfterEmptyReceive: { seconds: 30 }, @@ -97,6 +98,7 @@ describe('readConfig', () => { expect(publisherConfigs[0].topic).toEqual('fake1'); expect(publisherConfigs[0].region).toEqual('eu-west-1'); expect(publisherConfigs[0].queueUrl).toEqual('https://fake1.queue.url'); + expect(publisherConfigs[0].endpoint).toEqual('https://fake.endpoint.url'); expect(publisherConfigs[0].pollingWaitTime.as('seconds')).toBe(10); expect(publisherConfigs[0].timeout.as('seconds')).toBe(300); expect(publisherConfigs[0].waitTimeAfterEmptyReceive.as('seconds')).toBe( diff --git a/plugins/events-backend-module-aws-sqs/src/publisher/config.ts b/plugins/events-backend-module-aws-sqs/src/publisher/config.ts index c6b74ea8d3..eeb650ff6c 100644 --- a/plugins/events-backend-module-aws-sqs/src/publisher/config.ts +++ b/plugins/events-backend-module-aws-sqs/src/publisher/config.ts @@ -31,6 +31,7 @@ export interface AwsSqsEventSourceConfig { topic: string; visibilityTimeout?: Duration; waitTimeAfterEmptyReceive: Duration; + endpoint?: string; } // TODO(pjungermann): validation could be improved similar to `convertToHumanDuration` at @backstage/backend-tasks @@ -74,6 +75,7 @@ export function readConfig(config: Config): AwsSqsEventSourceConfig[] { } const queueUrl = topicConfig.getString('queue.url'); const region = topicConfig.getString('queue.region'); + const endpoint = topicConfig.getOptionalString('queue.endpoint'); const visibilityTimeout = readOptionalDuration( topicConfig, 'queue.visibilityTimeout', @@ -106,6 +108,7 @@ export function readConfig(config: Config): AwsSqsEventSourceConfig[] { return { pollingWaitTime, queueUrl, + endpoint, region, timeout, topic, diff --git a/plugins/events-backend-module-azure/CHANGELOG.md b/plugins/events-backend-module-azure/CHANGELOG.md index b89363b7c3..4e65353911 100644 --- a/plugins/events-backend-module-azure/CHANGELOG.md +++ b/plugins/events-backend-module-azure/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-events-backend-module-azure +## 0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/plugin-events-node@0.2.7-next.0 + +## 0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.2 + - @backstage/plugin-events-node@0.2.6 + ## 0.1.7-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-azure/package.json b/plugins/events-backend-module-azure/package.json index 3667e73ebd..3c9aa9a1ed 100644 --- a/plugins/events-backend-module-azure/package.json +++ b/plugins/events-backend-module-azure/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-azure", - "version": "0.1.7-next.1", + "version": "0.1.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md index ea70f7686e..ebf3e3a3f6 100644 --- a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-events-backend-module-bitbucket-cloud +## 0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/plugin-events-node@0.2.7-next.0 + +## 0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.2 + - @backstage/plugin-events-node@0.2.6 + ## 0.1.7-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-bitbucket-cloud/package.json b/plugins/events-backend-module-bitbucket-cloud/package.json index ea04a4faaa..47dc1d4428 100644 --- a/plugins/events-backend-module-bitbucket-cloud/package.json +++ b/plugins/events-backend-module-bitbucket-cloud/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-bitbucket-cloud", - "version": "0.1.7-next.1", + "version": "0.1.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-gerrit/CHANGELOG.md b/plugins/events-backend-module-gerrit/CHANGELOG.md index 411d9ffff8..b9f27bdaf2 100644 --- a/plugins/events-backend-module-gerrit/CHANGELOG.md +++ b/plugins/events-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-events-backend-module-gerrit +## 0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/plugin-events-node@0.2.7-next.0 + +## 0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.2 + - @backstage/plugin-events-node@0.2.6 + ## 0.1.7-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-gerrit/package.json b/plugins/events-backend-module-gerrit/package.json index 64fe31d31f..d9bf28fa7b 100644 --- a/plugins/events-backend-module-gerrit/package.json +++ b/plugins/events-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-gerrit", - "version": "0.1.7-next.1", + "version": "0.1.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-github/CHANGELOG.md b/plugins/events-backend-module-github/CHANGELOG.md index 0e2b2ae8de..ccca2e505a 100644 --- a/plugins/events-backend-module-github/CHANGELOG.md +++ b/plugins/events-backend-module-github/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-events-backend-module-github +## 0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/plugin-events-node@0.2.7-next.0 + +## 0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/plugin-events-node@0.2.6 + ## 0.1.7-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-github/package.json b/plugins/events-backend-module-github/package.json index 74b74469ca..625af1abf2 100644 --- a/plugins/events-backend-module-github/package.json +++ b/plugins/events-backend-module-github/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-github", - "version": "0.1.7-next.1", + "version": "0.1.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-gitlab/CHANGELOG.md b/plugins/events-backend-module-gitlab/CHANGELOG.md index d8d48674c8..5ea11ebf9f 100644 --- a/plugins/events-backend-module-gitlab/CHANGELOG.md +++ b/plugins/events-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-events-backend-module-gitlab +## 0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/plugin-events-node@0.2.7-next.0 + +## 0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/plugin-events-node@0.2.6 + ## 0.1.7-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-gitlab/package.json b/plugins/events-backend-module-gitlab/package.json index 07102c0b6f..04422bf7cf 100644 --- a/plugins/events-backend-module-gitlab/package.json +++ b/plugins/events-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-gitlab", - "version": "0.1.7-next.1", + "version": "0.1.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-test-utils/CHANGELOG.md b/plugins/events-backend-test-utils/CHANGELOG.md index 3d665a44ce..b3e92112a8 100644 --- a/plugins/events-backend-test-utils/CHANGELOG.md +++ b/plugins/events-backend-test-utils/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-events-backend-test-utils +## 0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.7-next.0 + +## 0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.6 + ## 0.1.7-next.1 ### Patch Changes diff --git a/plugins/events-backend-test-utils/package.json b/plugins/events-backend-test-utils/package.json index 3d46ea9210..3e37dc5cde 100644 --- a/plugins/events-backend-test-utils/package.json +++ b/plugins/events-backend-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-events-backend-test-utils", "description": "The plugin-events-backend-test-utils for @backstage/plugin-events-node", - "version": "0.1.7-next.1", + "version": "0.1.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend/CHANGELOG.md b/plugins/events-backend/CHANGELOG.md index 929a003cf9..0b3793bd0f 100644 --- a/plugins/events-backend/CHANGELOG.md +++ b/plugins/events-backend/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-events-backend +## 0.2.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/plugin-events-node@0.2.7-next.0 + +## 0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/plugin-events-node@0.2.6 + ## 0.2.6-next.1 ### Patch Changes diff --git a/plugins/events-backend/package.json b/plugins/events-backend/package.json index fdaee7d4a8..1cb8201b1b 100644 --- a/plugins/events-backend/package.json +++ b/plugins/events-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend", - "version": "0.2.6-next.1", + "version": "0.2.7-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-node/CHANGELOG.md b/plugins/events-node/CHANGELOG.md index c44e1e3999..17182dc4f5 100644 --- a/plugins/events-node/CHANGELOG.md +++ b/plugins/events-node/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-events-node +## 0.2.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.3-next.0 + +## 0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.2 + ## 0.2.6-next.1 ### Patch Changes diff --git a/plugins/events-node/package.json b/plugins/events-node/package.json index 7a368206bf..6652b40f10 100644 --- a/plugins/events-node/package.json +++ b/plugins/events-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-events-node", "description": "The plugin-events-node module for @backstage/plugin-events-backend", - "version": "0.2.6-next.1", + "version": "0.2.7-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/example-todo-list-backend/CHANGELOG.md b/plugins/example-todo-list-backend/CHANGELOG.md index 3fb578f05a..21205240e3 100644 --- a/plugins/example-todo-list-backend/CHANGELOG.md +++ b/plugins/example-todo-list-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @internal/plugin-todo-list-backend +## 1.0.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-auth-node@0.2.15-next.0 + +## 1.0.13 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + ## 1.0.13-next.1 ### Patch Changes diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index 0b635586b7..c00d019fec 100644 --- a/plugins/example-todo-list-backend/package.json +++ b/plugins/example-todo-list-backend/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list-backend", - "version": "1.0.13-next.1", + "version": "1.0.14-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/example-todo-list/CHANGELOG.md b/plugins/example-todo-list/CHANGELOG.md index 87cc779cde..2d722069fa 100644 --- a/plugins/example-todo-list/CHANGELOG.md +++ b/plugins/example-todo-list/CHANGELOG.md @@ -1,5 +1,32 @@ # @internal/plugin-todo-list +## 1.0.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## 1.0.13 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + +## 1.0.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 1.0.13-next.0 ### Patch Changes diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index fcd193bd5f..efb84fbe3b 100644 --- a/plugins/example-todo-list/package.json +++ b/plugins/example-todo-list/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list", - "version": "1.0.13-next.0", + "version": "1.0.14-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore-backend/CHANGELOG.md b/plugins/explore-backend/CHANGELOG.md index d178b091b1..24b7553ff5 100644 --- a/plugins/explore-backend/CHANGELOG.md +++ b/plugins/explore-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-explore-backend +## 0.0.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-module-explore@0.1.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.3 + +## 0.0.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-search-backend-module-explore@0.1.1 + - @backstage/config@1.0.7 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.3 + ## 0.0.7-next.1 ### Patch Changes diff --git a/plugins/explore-backend/package.json b/plugins/explore-backend/package.json index 7b21e885c1..ef1deae7f9 100644 --- a/plugins/explore-backend/package.json +++ b/plugins/explore-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-explore-backend", - "version": "0.0.7-next.1", + "version": "0.0.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore/CHANGELOG.md b/plugins/explore/CHANGELOG.md index 3ad9bdb917..a7b5b1a3a0 100644 --- a/plugins/explore/CHANGELOG.md +++ b/plugins/explore/CHANGELOG.md @@ -1,5 +1,54 @@ # @backstage/plugin-explore +## 0.4.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-explore-react@0.0.28 + - @backstage/plugin-search-react@1.6.1-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.3 + +## 0.4.3 + +### Patch Changes + +- 1996920782b: Make sure that the first support button row does not break across lines +- 4851581deb6: Display the title of the entity on the explore card if present, otherwise stick to the name +- a6025e25d99: Updated the example code in the "Customization" section of the README to make the imports match the components used. +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/plugin-search-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-explore-react@0.0.28 + - @backstage/plugin-search-common@1.2.3 + +## 0.4.3-next.2 + +### Patch Changes + +- 4851581deb6: Display the title of the entity on the explore card if present, otherwise stick to the name +- a6025e25d99: Updated the example code in the "Customization" section of the README to make the imports match the components used. +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-search-react@1.6.0-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/plugin-explore-react@0.0.28 + - @backstage/core-plugin-api@1.5.1 + ## 0.4.3-next.1 ### Patch Changes diff --git a/plugins/explore/README.md b/plugins/explore/README.md index a1cb273aab..24e6496cc3 100644 --- a/plugins/explore/README.md +++ b/plugins/explore/README.md @@ -104,11 +104,11 @@ Create a custom explore page in ```tsx import { - DomainExplorerContent, + CatalogKindExploreContent, ExploreLayout, } from '@backstage/plugin-explore'; import React from 'react'; -import { InnserSourceExplorerContent } from './InnserSourceExplorerContent'; +import { InnerSourceExploreContent } from './InnerSourceExploreContent'; export const ExplorePage = () => { return ( @@ -123,7 +123,7 @@ export const ExplorePage = () => { - + ); diff --git a/plugins/explore/package.json b/plugins/explore/package.json index bbe114c1f0..ec7c928de6 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-explore", "description": "A Backstage plugin for building an exploration page of your software ecosystem", - "version": "0.4.3-next.1", + "version": "0.4.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore/src/components/DomainCard/DomainCard.test.tsx b/plugins/explore/src/components/DomainCard/DomainCard.test.tsx index df9b84820a..b66e30c652 100644 --- a/plugins/explore/src/components/DomainCard/DomainCard.test.tsx +++ b/plugins/explore/src/components/DomainCard/DomainCard.test.tsx @@ -17,6 +17,7 @@ import { DomainEntity } from '@backstage/catalog-model'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; import { renderInTestApp } from '@backstage/test-utils'; +import { screen } from '@testing-library/react'; import React from 'react'; import { DomainCard } from './DomainCard'; @@ -51,4 +52,33 @@ describe('', () => { '/catalog/default/domain/artists', ); }); + + it('renders a domain card with custom title', async () => { + const entity: DomainEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Domain', + metadata: { + name: 'artists', + title: 'my Custom Title', + }, + spec: { + owner: 'guest', + }, + }; + const { getByText } = await renderInTestApp( + , + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name': entityRouteRef, + }, + }, + ); + + expect(getByText('Explore').parentElement).toHaveAttribute( + 'href', + '/catalog/default/domain/artists', + ); + expect(getByText('my Custom Title')).toBeInTheDocument(); + expect(screen.queryByText('artists')).not.toBeInTheDocument(); + }); }); diff --git a/plugins/explore/src/components/DomainCard/DomainCard.tsx b/plugins/explore/src/components/DomainCard/DomainCard.tsx index 0d37e3e273..c70df46b1a 100644 --- a/plugins/explore/src/components/DomainCard/DomainCard.tsx +++ b/plugins/explore/src/components/DomainCard/DomainCard.tsx @@ -53,7 +53,10 @@ export const DomainCard = (props: { entity: DomainEntity }) => { return ( - + {entity.metadata.tags?.length ? ( diff --git a/plugins/explore/src/components/EntityCard/EntityCard.test.tsx b/plugins/explore/src/components/EntityCard/EntityCard.test.tsx index 4b006e347f..cebd5af3d6 100644 --- a/plugins/explore/src/components/EntityCard/EntityCard.test.tsx +++ b/plugins/explore/src/components/EntityCard/EntityCard.test.tsx @@ -18,6 +18,7 @@ import { Entity } from '@backstage/catalog-model'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; import { renderInTestApp } from '@backstage/test-utils'; import React from 'react'; +import { screen } from '@testing-library/react'; import { EntityCard } from './EntityCard'; describe('', () => { @@ -51,4 +52,29 @@ describe('', () => { '/catalog/default/domain/artists', ); }); + + it('renders an entity card with display title', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Domain', + metadata: { + name: 'artists', + title: 'New Title', + }, + spec: { + owner: 'guest', + }, + }; + const { getByText } = await renderInTestApp( + , + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name': entityRouteRef, + }, + }, + ); + + expect(getByText('New Title')).toBeInTheDocument(); + expect(screen.queryByText('artists')).not.toBeInTheDocument(); + }); }); diff --git a/plugins/explore/src/components/EntityCard/EntityCard.tsx b/plugins/explore/src/components/EntityCard/EntityCard.tsx index 0a5908df38..9589d4721e 100644 --- a/plugins/explore/src/components/EntityCard/EntityCard.tsx +++ b/plugins/explore/src/components/EntityCard/EntityCard.tsx @@ -53,7 +53,10 @@ export const EntityCard = (props: { entity: Entity }) => { return ( - + {entity.metadata.tags?.length ? ( diff --git a/plugins/firehydrant/CHANGELOG.md b/plugins/firehydrant/CHANGELOG.md index 27c6a1b62e..734ef1742f 100644 --- a/plugins/firehydrant/CHANGELOG.md +++ b/plugins/firehydrant/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-firehydrant +## 0.2.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.2.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.2.2-next.1 ### Patch Changes diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index d5e136229c..5c011fdd4b 100644 --- a/plugins/firehydrant/package.json +++ b/plugins/firehydrant/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-firehydrant", "description": "A Backstage plugin that integrates towards FireHydrant", - "version": "0.2.2-next.1", + "version": "0.2.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md index 0399ad0ce2..4d370b8116 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-fossa +## 0.2.51-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## 0.2.50 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.2.50-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.2.50-next.1 ### Patch Changes diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 985202a403..d49ff6f36c 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-fossa", "description": "A Backstage plugin that integrates towards FOSSA", - "version": "0.2.50-next.1", + "version": "0.2.51-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gcalendar/CHANGELOG.md b/plugins/gcalendar/CHANGELOG.md index 1c23885154..d6062af499 100644 --- a/plugins/gcalendar/CHANGELOG.md +++ b/plugins/gcalendar/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-gcalendar +## 0.3.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.3.14 + +### Patch Changes + +- f493ccb9589: Pass user info email scope on auth refresh to resolve invalid credentials error +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.3.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 0.3.14-next.0 ### Patch Changes diff --git a/plugins/gcalendar/package.json b/plugins/gcalendar/package.json index 0cc77cabad..381f7d2ff8 100644 --- a/plugins/gcalendar/package.json +++ b/plugins/gcalendar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gcalendar", - "version": "0.3.14-next.0", + "version": "0.3.15-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gcalendar/src/hooks/useSignIn.ts b/plugins/gcalendar/src/hooks/useSignIn.ts index 351707b54e..3dbc778cf1 100644 --- a/plugins/gcalendar/src/hooks/useSignIn.ts +++ b/plugins/gcalendar/src/hooks/useSignIn.ts @@ -25,7 +25,10 @@ export const useSignIn = () => { const signIn = useCallback( async (optional = false) => { const token = await authApi.getAccessToken( - 'https://www.googleapis.com/auth/calendar.readonly', + [ + 'https://www.googleapis.com/auth/calendar.readonly', + 'https://www.googleapis.com/auth/userinfo.email', + ], { optional, instantPopup: !optional, diff --git a/plugins/gcp-projects/CHANGELOG.md b/plugins/gcp-projects/CHANGELOG.md index 7a5ea25c0d..24890793d3 100644 --- a/plugins/gcp-projects/CHANGELOG.md +++ b/plugins/gcp-projects/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-gcp-projects +## 0.3.38-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.3.37 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + +## 0.3.37-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 0.3.37-next.0 ### Patch Changes diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 039bcd094c..b70f0015a7 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gcp-projects", "description": "A Backstage plugin that helps you manage projects in GCP", - "version": "0.3.37-next.0", + "version": "0.3.38-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/git-release-manager/CHANGELOG.md b/plugins/git-release-manager/CHANGELOG.md index 976585c656..236e85cdf0 100644 --- a/plugins/git-release-manager/CHANGELOG.md +++ b/plugins/git-release-manager/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-git-release-manager +## 0.3.32-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.3.31 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + +## 0.3.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 0.3.31-next.1 ### Patch Changes diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 7bc4df059e..fb733dc46b 100644 --- a/plugins/git-release-manager/package.json +++ b/plugins/git-release-manager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-git-release-manager", "description": "A Backstage plugin that helps you manage releases in git", - "version": "0.3.31-next.1", + "version": "0.3.32-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index 09b205c9f1..0290b62cc0 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,46 @@ # @backstage/plugin-github-actions +## 0.6.0-next.0 + +### Minor Changes + +- 96e1004e2a02: Added support GitHub Enterprise hosted repositories. + + **BREAKING**: The `GithubActionsClient` is updated to take an `scmAuthApi` instead of the previous `githubAuthApi`. This does not require any code changes unless you construct your own `GithubActionsClient` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/catalog-model@1.3.0 + +## 0.5.18 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.5.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.5.18-next.1 ### Patch Changes diff --git a/plugins/github-actions/README.md b/plugins/github-actions/README.md index cb6867193c..b94862db2b 100644 --- a/plugins/github-actions/README.md +++ b/plugins/github-actions/README.md @@ -64,6 +64,22 @@ const serviceEntityPage = ( 3. Run the app with `yarn start` and the backend with `yarn start-backend`. Then navigate to `/github-actions/` under any entity. +### Self-hosted / Enterprise GitHub + +The plugin will try to use `backstage.io/source-location` or `backstage.io/managed-by-location` +annotations to figure out the location of the source code. + +1. Add the `host` and `apiBaseUrl` to your `app-config.yaml` + +```yaml +# app-config.yaml + +integrations: + github: + - host: 'your-github-host.com' + apiBaseUrl: 'https://api.your-github-host.com' +``` + ## Features - List workflow runs for a project diff --git a/plugins/github-actions/api-report.md b/plugins/github-actions/api-report.md index b1628996e0..0c9d06d90e 100644 --- a/plugins/github-actions/api-report.md +++ b/plugins/github-actions/api-report.md @@ -10,9 +10,9 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; import { ConfigApi } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; import { InfoCardVariants } from '@backstage/core-components'; -import { OAuthApi } from '@backstage/core-plugin-api'; import { RestEndpointMethodTypes } from '@octokit/rest'; import { RouteRef } from '@backstage/core-plugin-api'; +import { ScmAuthApi } from '@backstage/integration-react'; // @public (undocumented) export enum BuildStatus { @@ -111,7 +111,7 @@ export const githubActionsApiRef: ApiRef; // @public export class GithubActionsClient implements GithubActionsApi { - constructor(options: { configApi: ConfigApi; githubAuthApi: OAuthApi }); + constructor(options: { configApi: ConfigApi; scmAuthApi: ScmAuthApi }); // (undocumented) downloadJobLogsForWorkflowRun(options: { hostname?: string; diff --git a/plugins/github-actions/dev/index.tsx b/plugins/github-actions/dev/index.tsx index 93e6ee4f74..153478ddbc 100644 --- a/plugins/github-actions/dev/index.tsx +++ b/plugins/github-actions/dev/index.tsx @@ -33,6 +33,8 @@ const mockEntity: Entity = { description: 'backstage.io', annotations: { 'github.com/project-slug': 'backstage/backstage', + 'backstage.io/source-location': + 'url:https://ghes.acme.co/backstage/backstage/tree/master/', }, }, spec: { diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 25fac2b774..8e41f7ff3e 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-actions", "description": "A Backstage plugin that integrates towards GitHub Actions", - "version": "0.5.18-next.1", + "version": "0.6.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -38,12 +38,14 @@ "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/integration": "workspace:^", + "@backstage/integration-react": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", "@backstage/theme": "workspace:^", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", "@octokit/rest": "^19.0.3", + "git-url-parse": "^13.0.0", "luxon": "^3.0.0", "react-use": "^17.2.4" }, diff --git a/plugins/github-actions/src/api/GithubActionsClient.ts b/plugins/github-actions/src/api/GithubActionsClient.ts index 724081320f..e427c343e2 100644 --- a/plugins/github-actions/src/api/GithubActionsClient.ts +++ b/plugins/github-actions/src/api/GithubActionsClient.ts @@ -15,9 +15,10 @@ */ import { readGithubIntegrationConfigs } from '@backstage/integration'; +import { ScmAuthApi } from '@backstage/integration-react'; import { GithubActionsApi } from './GithubActionsApi'; import { Octokit, RestEndpointMethodTypes } from '@octokit/rest'; -import { ConfigApi, OAuthApi } from '@backstage/core-plugin-api'; +import { ConfigApi } from '@backstage/core-plugin-api'; /** * A client for fetching information about GitHub actions. @@ -26,22 +27,26 @@ import { ConfigApi, OAuthApi } from '@backstage/core-plugin-api'; */ export class GithubActionsClient implements GithubActionsApi { private readonly configApi: ConfigApi; - private readonly githubAuthApi: OAuthApi; + private readonly scmAuthApi: ScmAuthApi; - constructor(options: { configApi: ConfigApi; githubAuthApi: OAuthApi }) { + constructor(options: { configApi: ConfigApi; scmAuthApi: ScmAuthApi }) { this.configApi = options.configApi; - this.githubAuthApi = options.githubAuthApi; + this.scmAuthApi = options.scmAuthApi; } - private async getOctokit(hostname?: string): Promise { - // TODO: Get access token for the specified hostname - const token = await this.githubAuthApi.getAccessToken(['repo']); + private async getOctokit(hostname: string = 'github.com'): Promise { + const { token } = await this.scmAuthApi.getCredentials({ + url: `https://${hostname}/`, + additionalScope: { + customScopes: { + github: ['repo'], + }, + }, + }); const configs = readGithubIntegrationConfigs( this.configApi.getOptionalConfigArray('integrations.github') ?? [], ); - const githubIntegrationConfig = configs.find( - v => v.host === hostname ?? 'github.com', - ); + const githubIntegrationConfig = configs.find(v => v.host === hostname); const baseUrl = githubIntegrationConfig?.apiBaseUrl; return new Octokit({ auth: token, baseUrl }); } diff --git a/plugins/github-actions/src/components/Cards/Cards.tsx b/plugins/github-actions/src/components/Cards/Cards.tsx index e23f7f7d59..205288cba7 100644 --- a/plugins/github-actions/src/components/Cards/Cards.tsx +++ b/plugins/github-actions/src/components/Cards/Cards.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ -import { readGithubIntegrationConfigs } from '@backstage/integration'; import { useEntity } from '@backstage/plugin-catalog-react'; import { LinearProgress, @@ -28,13 +27,14 @@ import { GITHUB_ACTIONS_ANNOTATION } from '../getProjectNameFromEntity'; import { useWorkflowRuns, WorkflowRun } from '../useWorkflowRuns'; import { WorkflowRunsTable } from '../WorkflowRunsTable'; import { WorkflowRunStatus } from '../WorkflowRunStatus'; -import { configApiRef, errorApiRef, useApi } from '@backstage/core-plugin-api'; +import { errorApiRef, useApi } from '@backstage/core-plugin-api'; import { InfoCard, InfoCardVariants, Link, StructuredMetadataTable, } from '@backstage/core-components'; +import { getHostnameFromEntity } from '../getHostnameFromEntity'; const useStyles = makeStyles({ externalLinkIcon: { @@ -85,12 +85,8 @@ export const LatestWorkflowRunCard = (props: { }) => { const { branch = 'master', variant } = props; const { entity } = useEntity(); - const config = useApi(configApiRef); const errorApi = useApi(errorApiRef); - // TODO: Get github hostname from metadata annotation - const hostname = readGithubIntegrationConfigs( - config.getOptionalConfigArray('integrations.github') ?? [], - )[0].host; + const hostname = getHostnameFromEntity(entity); const [owner, repo] = ( entity?.metadata.annotations?.[GITHUB_ACTIONS_ANNOTATION] ?? '/' ).split('/'); diff --git a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx index f55cad8424..dcafc3b6f2 100644 --- a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx +++ b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx @@ -48,6 +48,8 @@ describe('', () => { name: 'software', annotations: { 'github.com/project-slug': 'theorg/the-service', + 'backstage.io/source-location': + 'url:https://ghes.acme.co/theorg/the-service/tree/main/', }, }, spec: { @@ -119,10 +121,14 @@ describe('', () => { ); }); - it('uses the github repo and owner from the entity annotation', async () => { + it('uses the github hostname, repo and owner from the entity annotations', async () => { renderSubject(); expect(useWorkflowRuns).toHaveBeenCalledWith( - expect.objectContaining({ owner: 'theorg', repo: 'the-service' }), + expect.objectContaining({ + hostname: 'ghes.acme.co', + owner: 'theorg', + repo: 'the-service', + }), ); }); diff --git a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx index 59d64af9c9..d48e4a6604 100644 --- a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx +++ b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { readGithubIntegrationConfigs } from '@backstage/integration'; import { useEntity } from '@backstage/plugin-catalog-react'; import React, { useEffect } from 'react'; import { Link as RouterLink } from 'react-router-dom'; @@ -22,12 +21,7 @@ import { useWorkflowRuns, WorkflowRun } from '../useWorkflowRuns'; import { WorkflowRunStatus } from '../WorkflowRunStatus'; import { Typography } from '@material-ui/core'; -import { - configApiRef, - errorApiRef, - useApi, - useRouteRef, -} from '@backstage/core-plugin-api'; +import { errorApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api'; import { ErrorPanel, InfoCard, @@ -36,6 +30,7 @@ import { Table, } from '@backstage/core-components'; import { buildRouteRef } from '../../routes'; +import { getHostnameFromEntity } from '../getHostnameFromEntity'; const firstLine = (message: string): string => message.split('\n')[0]; @@ -49,13 +44,9 @@ export const RecentWorkflowRunsCard = (props: { const { branch, dense = false, limit = 5, variant } = props; const { entity } = useEntity(); - const config = useApi(configApiRef); const errorApi = useApi(errorApiRef); - // TODO: Get github hostname from metadata annotation - const hostname = readGithubIntegrationConfigs( - config.getOptionalConfigArray('integrations.github') ?? [], - )[0].host; + const hostname = getHostnameFromEntity(entity); const [owner, repo] = ( entity?.metadata.annotations?.[GITHUB_ACTIONS_ANNOTATION] ?? '/' diff --git a/plugins/github-actions/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx b/plugins/github-actions/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx index a2c87772d5..76ce8451e2 100644 --- a/plugins/github-actions/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx +++ b/plugins/github-actions/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx @@ -15,7 +15,6 @@ */ import { Entity } from '@backstage/catalog-model'; -import { readGithubIntegrationConfigs } from '@backstage/integration'; import { Accordion, AccordionDetails, @@ -44,8 +43,8 @@ import { WorkflowRunStatus } from '../WorkflowRunStatus'; import { useWorkflowRunJobs } from './useWorkflowRunJobs'; import { useWorkflowRunsDetails } from './useWorkflowRunsDetails'; import { WorkflowRunLogs } from '../WorkflowRunLogs'; -import { configApiRef, useApi } from '@backstage/core-plugin-api'; import { Breadcrumbs, Link } from '@backstage/core-components'; +import { getHostnameFromEntity } from '../getHostnameFromEntity'; const useStyles = makeStyles(theme => ({ root: { @@ -163,13 +162,9 @@ const JobsList = ({ jobs, entity }: { jobs?: Jobs; entity: Entity }) => { }; export const WorkflowRunDetails = ({ entity }: { entity: Entity }) => { - const config = useApi(configApiRef); const projectName = getProjectNameFromEntity(entity); - // TODO: Get github hostname from metadata annotation - const hostname = readGithubIntegrationConfigs( - config.getOptionalConfigArray('integrations.github') ?? [], - )[0].host; + const hostname = getHostnameFromEntity(entity); const [owner, repo] = (projectName && projectName.split('/')) || []; const details = useWorkflowRunsDetails({ hostname, owner, repo }); const jobs = useWorkflowRunJobs({ hostname, owner, repo }); diff --git a/plugins/github-actions/src/components/WorkflowRunLogs/WorkflowRunLogs.tsx b/plugins/github-actions/src/components/WorkflowRunLogs/WorkflowRunLogs.tsx index 2c9d41398a..2bf8d3356b 100644 --- a/plugins/github-actions/src/components/WorkflowRunLogs/WorkflowRunLogs.tsx +++ b/plugins/github-actions/src/components/WorkflowRunLogs/WorkflowRunLogs.tsx @@ -16,8 +16,6 @@ import { Entity } from '@backstage/catalog-model'; import { LogViewer } from '@backstage/core-components'; -import { configApiRef, useApi } from '@backstage/core-plugin-api'; -import { readGithubIntegrationConfigs } from '@backstage/integration'; import { Accordion, AccordionSummary, @@ -35,6 +33,7 @@ import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import React from 'react'; import { getProjectNameFromEntity } from '../getProjectNameFromEntity'; import { useDownloadWorkflowRunLogs } from './useDownloadWorkflowRunLogs'; +import { getHostnameFromEntity } from '../getHostnameFromEntity'; const useStyles = makeStyles(theme => ({ button: { @@ -75,14 +74,10 @@ export const WorkflowRunLogs = ({ runId: number; inProgress: boolean; }) => { - const config = useApi(configApiRef); const classes = useStyles(); const projectName = getProjectNameFromEntity(entity); - // TODO: Get github hostname from metadata annotation - const hostname = readGithubIntegrationConfigs( - config.getOptionalConfigArray('integrations.github') ?? [], - )[0].host; + const hostname = getHostnameFromEntity(entity); const [owner, repo] = (projectName && projectName.split('/')) || []; const jobLogs = useDownloadWorkflowRunLogs({ hostname, diff --git a/plugins/github-actions/src/components/WorkflowRunsTable/WorkflowRunsTable.tsx b/plugins/github-actions/src/components/WorkflowRunsTable/WorkflowRunsTable.tsx index f05a41e71b..8471a5d7d6 100644 --- a/plugins/github-actions/src/components/WorkflowRunsTable/WorkflowRunsTable.tsx +++ b/plugins/github-actions/src/components/WorkflowRunsTable/WorkflowRunsTable.tsx @@ -30,7 +30,6 @@ import SyncIcon from '@material-ui/icons/Sync'; import { buildRouteRef } from '../../routes'; import { getProjectNameFromEntity } from '../getProjectNameFromEntity'; import { Entity } from '@backstage/catalog-model'; -import { readGithubIntegrationConfigs } from '@backstage/integration'; import { EmptyState, @@ -38,7 +37,8 @@ import { TableColumn, Link, } from '@backstage/core-components'; -import { configApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api'; +import { useRouteRef } from '@backstage/core-plugin-api'; +import { getHostnameFromEntity } from '../getHostnameFromEntity'; const generatedColumns: TableColumn[] = [ { @@ -164,12 +164,8 @@ export const WorkflowRunsTable = ({ entity: Entity; branch?: string; }) => { - const config = useApi(configApiRef); const projectName = getProjectNameFromEntity(entity); - // TODO: Get github hostname from metadata annotation - const hostname = readGithubIntegrationConfigs( - config.getOptionalConfigArray('integrations.github') ?? [], - )[0].host; + const hostname = getHostnameFromEntity(entity); const [owner, repo] = (projectName ?? '/').split('/'); const [{ runs, ...tableProps }, { retry, setPage, setPageSize }] = useWorkflowRuns({ diff --git a/plugins/github-actions/src/components/getHostnameFromEntity.ts b/plugins/github-actions/src/components/getHostnameFromEntity.ts new file mode 100644 index 0000000000..836fd22860 --- /dev/null +++ b/plugins/github-actions/src/components/getHostnameFromEntity.ts @@ -0,0 +1,32 @@ +/* + * Copyright 2020 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 { + ANNOTATION_LOCATION, + ANNOTATION_SOURCE_LOCATION, + Entity, +} from '@backstage/catalog-model'; +import gitUrlParse from 'git-url-parse'; + +export const getHostnameFromEntity = (entity: Entity) => { + const location = + entity?.metadata.annotations?.[ANNOTATION_SOURCE_LOCATION] ?? + entity?.metadata.annotations?.[ANNOTATION_LOCATION]; + + return location?.startsWith('url:') + ? gitUrlParse(location.slice(4)).resource + : undefined; +}; diff --git a/plugins/github-actions/src/plugin.ts b/plugins/github-actions/src/plugin.ts index 26cf246fb9..906ab7c91c 100644 --- a/plugins/github-actions/src/plugin.ts +++ b/plugins/github-actions/src/plugin.ts @@ -20,10 +20,10 @@ import { configApiRef, createPlugin, createApiFactory, - githubAuthApiRef, createRoutableExtension, createComponentExtension, } from '@backstage/core-plugin-api'; +import { scmAuthApiRef } from '@backstage/integration-react'; /** @public */ export const githubActionsPlugin = createPlugin({ @@ -31,9 +31,9 @@ export const githubActionsPlugin = createPlugin({ apis: [ createApiFactory({ api: githubActionsApiRef, - deps: { configApi: configApiRef, githubAuthApi: githubAuthApiRef }, - factory: ({ configApi, githubAuthApi }) => - new GithubActionsClient({ configApi, githubAuthApi }), + deps: { configApi: configApiRef, scmAuthApi: scmAuthApiRef }, + factory: ({ configApi, scmAuthApi }) => + new GithubActionsClient({ configApi, scmAuthApi }), }), ], routes: { diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md index 41475febd3..bfa7655804 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-github-deployments +## 0.1.50-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## 0.1.49 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.1.49-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.49-next.1 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index dcb4156f9d..29de2e5115 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-deployments", "description": "A Backstage plugin that integrates towards GitHub Deployments", - "version": "0.1.49-next.1", + "version": "0.1.50-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-issues/CHANGELOG.md b/plugins/github-issues/CHANGELOG.md index d1e2103800..0e5534e28b 100644 --- a/plugins/github-issues/CHANGELOG.md +++ b/plugins/github-issues/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-github-issues +## 0.2.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## 0.2.7 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.2.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.2.7-next.1 ### Patch Changes diff --git a/plugins/github-issues/package.json b/plugins/github-issues/package.json index ed982410e9..4c1c099160 100644 --- a/plugins/github-issues/package.json +++ b/plugins/github-issues/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-issues", - "version": "0.2.7-next.1", + "version": "0.2.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-pull-requests-board/CHANGELOG.md b/plugins/github-pull-requests-board/CHANGELOG.md index 7421c6e015..ba1d162916 100644 --- a/plugins/github-pull-requests-board/CHANGELOG.md +++ b/plugins/github-pull-requests-board/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-github-pull-requests-board +## 0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.1.12 + +### Patch Changes + +- cf125c36569: The `EntityTeamPullRequestsContent` and `EntityTeamPullRequestsCard` support the ability to view the labels/tags added to each PR +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.1.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.12-next.1 ### Patch Changes diff --git a/plugins/github-pull-requests-board/package.json b/plugins/github-pull-requests-board/package.json index e805cd99ce..ce0332cc51 100644 --- a/plugins/github-pull-requests-board/package.json +++ b/plugins/github-pull-requests-board/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-pull-requests-board", "description": "A Backstage plugin that allows you to see all open Pull Requests for all the repositories owned by your team", - "version": "0.1.12-next.1", + "version": "0.1.13-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gitops-profiles/CHANGELOG.md b/plugins/gitops-profiles/CHANGELOG.md index 99122116fb..0b130eed42 100644 --- a/plugins/gitops-profiles/CHANGELOG.md +++ b/plugins/gitops-profiles/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-gitops-profiles +## 0.3.37-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.3.36 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## 0.3.36-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + ## 0.3.36-next.0 ### Patch Changes diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index 2bb6f145a4..e64eb4f3db 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gitops-profiles", "description": "A Backstage plugin that helps you manage GitOps profiles", - "version": "0.3.36-next.0", + "version": "0.3.37-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gocd/CHANGELOG.md b/plugins/gocd/CHANGELOG.md index 14a0149ca5..61efa3401d 100644 --- a/plugins/gocd/CHANGELOG.md +++ b/plugins/gocd/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-gocd +## 0.1.25-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## 0.1.24 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.1.24-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.24-next.1 ### Patch Changes diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index 2e41e2c217..a2114d66dc 100644 --- a/plugins/gocd/package.json +++ b/plugins/gocd/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gocd", "description": "A Backstage plugin that integrates towards GoCD", - "version": "0.1.24-next.1", + "version": "0.1.25-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/graphiql/CHANGELOG.md b/plugins/graphiql/CHANGELOG.md index e831845d49..7e12506960 100644 --- a/plugins/graphiql/CHANGELOG.md +++ b/plugins/graphiql/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-graphiql +## 0.2.51-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.2.50 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + +## 0.2.50-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 0.2.50-next.0 ### Patch Changes diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 08fc2a6ec0..e0b7b94b82 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphiql", "description": "Backstage plugin for browsing GraphQL APIs", - "version": "0.2.50-next.0", + "version": "0.2.51-next.0", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/plugins/graphql-backend/CHANGELOG.md b/plugins/graphql-backend/CHANGELOG.md index 898e185d5d..3b915f994d 100644 --- a/plugins/graphql-backend/CHANGELOG.md +++ b/plugins/graphql-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-graphql-backend +## 0.1.36-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/plugin-catalog-graphql@0.3.20 + +## 0.1.35 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config@1.0.7 + - @backstage/plugin-catalog-graphql@0.3.20 + ## 0.1.35-next.1 ### Patch Changes diff --git a/plugins/graphql-backend/package.json b/plugins/graphql-backend/package.json index 388b587040..ccda2805de 100644 --- a/plugins/graphql-backend/package.json +++ b/plugins/graphql-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphql-backend", "description": "An experimental Backstage backend plugin for GraphQL", - "version": "0.1.35-next.1", + "version": "0.1.36-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/graphql-voyager/CHANGELOG.md b/plugins/graphql-voyager/CHANGELOG.md index 77586073af..e8d42388ef 100644 --- a/plugins/graphql-voyager/CHANGELOG.md +++ b/plugins/graphql-voyager/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-graphql-voyager +## 0.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + +## 0.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.3-next.0 ### Patch Changes diff --git a/plugins/graphql-voyager/package.json b/plugins/graphql-voyager/package.json index d356dee1c5..8b632ad94f 100644 --- a/plugins/graphql-voyager/package.json +++ b/plugins/graphql-voyager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphql-voyager", "description": "Backstage plugin for GraphQL Voyager", - "version": "0.1.3-next.0", + "version": "0.1.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/home-react/.eslintrc.js b/plugins/home-react/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/home-react/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/home-react/CHANGELOG.md b/plugins/home-react/CHANGELOG.md new file mode 100644 index 0000000000..32213cb62f --- /dev/null +++ b/plugins/home-react/CHANGELOG.md @@ -0,0 +1,13 @@ +# @backstage/plugin-home-react + +## 0.1.0-next.0 + +### Minor Changes + +- 41e8037a8a6d: Extract new plugin-home-react package and deprecate createCardExtension in plugin-home + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 diff --git a/plugins/home-react/README.md b/plugins/home-react/README.md new file mode 100644 index 0000000000..c10ad8d323 --- /dev/null +++ b/plugins/home-react/README.md @@ -0,0 +1,3 @@ +# Home React + +A new Library that contains React Components for [home plugin](/plugins/home/README.md) depend on. diff --git a/plugins/home-react/api-report.md b/plugins/home-react/api-report.md new file mode 100644 index 0000000000..42e8fd0b0f --- /dev/null +++ b/plugins/home-react/api-report.md @@ -0,0 +1,76 @@ +## API Report File for "@backstage/plugin-home-react" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { Extension } from '@backstage/core-plugin-api'; +import { RJSFSchema } from '@rjsf/utils'; + +// @public (undocumented) +export type CardConfig = { + layout?: CardLayout; + settings?: CardSettings; +}; + +// @public (undocumented) +export type CardExtensionProps = ComponentRenderer & { + title?: string; +} & T; + +// @public (undocumented) +export type CardLayout = { + width?: { + minColumns?: number; + maxColumns?: number; + defaultColumns?: number; + }; + height?: { + minRows?: number; + maxRows?: number; + defaultRows?: number; + }; +}; + +// @public (undocumented) +export type CardSettings = { + schema?: RJSFSchema; +}; + +// @public (undocumented) +export type ComponentParts = { + Content: (props?: any) => JSX.Element; + Actions?: () => JSX.Element; + Settings?: () => JSX.Element; + ContextProvider?: (props: any) => JSX.Element; +}; + +// @public (undocumented) +export type ComponentRenderer = { + Renderer?: (props: RendererProps) => JSX.Element; +}; + +// @public +export function createCardExtension(options: { + title: string; + components: () => Promise; + name?: string; + description?: string; + layout?: CardLayout; + settings?: CardSettings; +}): Extension<(props: CardExtensionProps) => JSX.Element>; + +// @public (undocumented) +export type RendererProps = { + title: string; +} & ComponentParts; + +// @public (undocumented) +export const SettingsModal: (props: { + open: boolean; + close: Function; + componentName: string; + children: JSX.Element; +}) => JSX.Element; +``` diff --git a/plugins/home-react/package.json b/plugins/home-react/package.json new file mode 100644 index 0000000000..f38e07617b --- /dev/null +++ b/plugins/home-react/package.json @@ -0,0 +1,65 @@ +{ + "name": "@backstage/plugin-home-react", + "description": "A Backstage plugin that contains react components helps you build a home page", + "version": "0.1.0-next.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "web-library" + }, + "homepage": "https://github.com/backstage/backstage/tree/master/plugins/home-react#readme", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/home-react" + }, + "keywords": [ + "backstage", + "homepage" + ], + "scripts": { + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" + }, + "dependencies": { + "@backstage/core-components": "workspace:^", + "@backstage/core-plugin-api": "workspace:^", + "@material-ui/core": "^4.12.2", + "@material-ui/icons": "^4.9.1", + "@rjsf/utils": "5.6.0" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0", + "react-dom": "^16.13.1 || ^17.0.0", + "react-router-dom": "6.0.0-beta.0 || ^6.3.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@backstage/core-app-api": "workspace:^", + "@backstage/dev-utils": "workspace:^", + "@backstage/test-utils": "workspace:^", + "@testing-library/dom": "^8.0.0", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^12.1.3", + "@testing-library/user-event": "^14.0.0", + "@types/node": "^16.11.26", + "@types/react": "^16.13.1 || ^17.0.0", + "@types/react-grid-layout": "^1.3.2", + "cross-fetch": "^3.1.5", + "msw": "^1.0.0" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/home/src/components/SettingsModal.tsx b/plugins/home-react/src/components/SettingsModal.tsx similarity index 100% rename from plugins/home/src/components/SettingsModal.tsx rename to plugins/home-react/src/components/SettingsModal.tsx diff --git a/plugins/home-react/src/components/index.ts b/plugins/home-react/src/components/index.ts new file mode 100644 index 0000000000..dce6968b36 --- /dev/null +++ b/plugins/home-react/src/components/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2020 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. + */ + +export { SettingsModal } from './SettingsModal'; diff --git a/plugins/home/src/extensions.tsx b/plugins/home-react/src/extensions.tsx similarity index 100% rename from plugins/home/src/extensions.tsx rename to plugins/home-react/src/extensions.tsx diff --git a/plugins/home-react/src/index.ts b/plugins/home-react/src/index.ts new file mode 100644 index 0000000000..1f02ded1c6 --- /dev/null +++ b/plugins/home-react/src/index.ts @@ -0,0 +1,32 @@ +/* + * Copyright 2021 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. + */ + +/** + * A Backstage plugin that helps you build a home page + * + * @packageDocumentation + */ +export * from './components'; +export { createCardExtension } from './extensions'; +export type { + CardExtensionProps, + ComponentParts, + ComponentRenderer, + RendererProps, + CardLayout, + CardSettings, + CardConfig, +} from './extensions'; diff --git a/plugins/home/CHANGELOG.md b/plugins/home/CHANGELOG.md index 868b1a6c3b..3b589b2c5a 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,47 @@ # @backstage/plugin-home +## 0.5.3-next.0 + +### Patch Changes + +- 41e8037a8a6d: Extract new plugin-home-react package and deprecate createCardExtension in plugin-home +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/plugin-home-react@0.1.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.5.2 + +### Patch Changes + +- acca8966465: Remove object-hash dependency +- 957cd9b8958: Use the semantic time tag for rendering world clocks on homepage headers. +- 0e19e7b0f3a: Bump to using the later v5 versions of `@rjsf/*` +- 5272cfabc3b: Add missing @rjsf/core dependency +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + +## 0.5.2-next.2 + +### Patch Changes + +- acca8966465: Remove object-hash dependency +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + ## 0.5.2-next.1 ### Patch Changes diff --git a/plugins/home/README.md b/plugins/home/README.md index 7da0034662..42fbf73d18 100644 --- a/plugins/home/README.md +++ b/plugins/home/README.md @@ -51,6 +51,8 @@ The Home Page can be composed with regular React components, so there's no magic Finally, the `createCardExtension` also accepts a generic, such that Component Developers can indicate to App Integrators what custom props their component will accept, such as the example below where the default category of the random jokes can be set. ```tsx +import { createCardExtension } from '@backstage/plugin-home-react'; + export const RandomJokeHomePageComponent = homePlugin.provide( createCardExtension<{ defaultCategory?: 'programming' | 'any' }>({ title: 'Random Joke', @@ -121,6 +123,8 @@ want to add additional configuration like component size or settings, you can de property: ```tsx +import { createCardExtension } from '@backstage/plugin-home-react'; + export const RandomJokeHomePageComponent = homePlugin.provide( createCardExtension<{ defaultCategory?: 'any' | 'programming' }>({ name: 'HomePageRandomJoke', @@ -178,6 +182,8 @@ properties. The `settings.schema` object should follow must be `object`. ```tsx +import { createCardExtension } from '@backstage/plugin-home-react'; + export const HomePageRandomJoke = homePlugin.provide( createCardExtension<{ defaultCategory?: 'any' | 'programming' }>({ name: 'HomePageRandomJoke', @@ -241,4 +247,5 @@ Additionally, the API is at a very early state, so contributing with additional ### Homepage Templates -We are hoping that we together can build up a collection of Homepage templates. We therefore put together a place where we can collect all the templates for the Home Plugin in the [storybook](https://backstage.io/storybook/?path=/story/plugins-home-templates). If you would like to contribute with a template, start by taking a look at the [DefaultTemplate storybook example to create your own](/packages/app/src/components/home/templates/DefaultTemplate.stories.tsx), and then open a PR with your suggestion. +We are hoping that we together can build up a collection of Homepage templates. We therefore put together a place where we can collect all the templates for the Home Plugin in the [storybook](https://backstage.io/storybook/?path=/story/plugins-home-templates). +If you would like to contribute with a template, start by taking a look at the [DefaultTemplate storybook example](/packages/app/src/components/home/templates/DefaultTemplate.stories.tsx) or [CustomizableTemplate storybook example](/packages/app/src/components/home/templates/CustomizableTemplate.stories.tsx) to create your own, and then open a PR with your suggestion. diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index 43fdbf403c..e4ff522062 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -6,36 +6,33 @@ /// import { BackstagePlugin } from '@backstage/core-plugin-api'; -import { Extension } from '@backstage/core-plugin-api'; +import { CardConfig as CardConfig_2 } from '@backstage/plugin-home-react'; +import { CardExtensionProps as CardExtensionProps_2 } from '@backstage/plugin-home-react'; +import { CardLayout as CardLayout_2 } from '@backstage/plugin-home-react'; +import { CardSettings as CardSettings_2 } from '@backstage/plugin-home-react'; +import { ComponentParts as ComponentParts_2 } from '@backstage/plugin-home-react'; +import { ComponentRenderer as ComponentRenderer_2 } from '@backstage/plugin-home-react'; +import { createCardExtension as createCardExtension_2 } from '@backstage/plugin-home-react'; import { default as React_2 } from 'react'; import { ReactElement } from 'react'; import { ReactNode } from 'react'; -import { RJSFSchema } from '@rjsf/utils'; +import { RendererProps as RendererProps_2 } from '@backstage/plugin-home-react'; import { RouteRef } from '@backstage/core-plugin-api'; -// @public (undocumented) -export type CardExtensionProps = ComponentRenderer & { - title?: string; -} & T; +// @public +export type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl'; -// @public (undocumented) -export type CardLayout = { - width?: { - minColumns?: number; - maxColumns?: number; - defaultColumns?: number; - }; - height?: { - minRows?: number; - maxRows?: number; - defaultRows?: number; - }; -}; +// @public @deprecated (undocumented) +export type CardConfig = CardConfig_2; -// @public (undocumented) -export type CardSettings = { - schema?: RJSFSchema; -}; +// @public @deprecated (undocumented) +export type CardExtensionProps = CardExtensionProps_2; + +// @public @deprecated (undocumented) +export type CardLayout = CardLayout_2; + +// @public @deprecated (undocumented) +export type CardSettings = CardSettings_2; // @public (undocumented) export type ClockConfig = { @@ -53,18 +50,11 @@ export const ComponentAccordion: (props: { ContextProvider?: ((props: any) => JSX.Element) | undefined; }) => JSX.Element; -// @public (undocumented) -export type ComponentParts = { - Content: (props?: any) => JSX.Element; - Actions?: () => JSX.Element; - Settings?: () => JSX.Element; - ContextProvider?: (props: any) => JSX.Element; -}; +// @public @deprecated (undocumented) +export type ComponentParts = ComponentParts_2; -// @public (undocumented) -export type ComponentRenderer = { - Renderer?: (props: RendererProps) => JSX.Element; -}; +// @public @deprecated (undocumented) +export type ComponentRenderer = ComponentRenderer_2; // @public (undocumented) export const ComponentTab: (props: { @@ -82,26 +72,28 @@ export const ComponentTabs: (props: { }[]; }) => JSX.Element; -// @public -export function createCardExtension(options: { - title: string; - components: () => Promise; - name?: string; - description?: string; - layout?: CardLayout; - settings?: CardSettings; -}): Extension<(props: CardExtensionProps) => JSX.Element>; +// @public @deprecated (undocumented) +export const createCardExtension: typeof createCardExtension_2; // @public export const CustomHomepageGrid: ( props: CustomHomepageGridProps, ) => JSX.Element; -// @public (undocumented) +// @public export type CustomHomepageGridProps = { children?: ReactNode; config?: LayoutConfiguration[]; rowHeight?: number; + breakpoints?: Record; + cols?: Record; + containerPadding?: [number, number] | Record; + containerMargin?: [number, number] | Record; + maxRows?: number; + style?: React_2.CSSProperties; + compactType?: 'vertical' | 'horizontal' | null; + allowOverlap?: boolean; + preventCollision?: boolean; }; // @public @@ -124,19 +116,19 @@ export const HomepageCompositionRoot: (props: { // @public (undocumented) export const HomePageRandomJoke: ( - props: CardExtensionProps<{ + props: CardExtensionProps_2<{ defaultCategory?: 'any' | 'programming' | undefined; }>, ) => JSX.Element; // @public export const HomePageStarredEntities: ( - props: CardExtensionProps, + props: CardExtensionProps_2, ) => JSX.Element; // @public export const HomePageToolkit: ( - props: CardExtensionProps, + props: CardExtensionProps_2, ) => JSX.Element; // @public (undocumented) @@ -157,12 +149,10 @@ export type LayoutConfiguration = { height: number; }; -// @public (undocumented) -export type RendererProps = { - title: string; -} & ComponentParts; +// @public @deprecated (undocumented) +export type RendererProps = RendererProps_2; -// @public (undocumented) +// @public @deprecated (undocumented) export const SettingsModal: (props: { open: boolean; close: Function; diff --git a/plugins/home/package.json b/plugins/home/package.json index ef9267234b..5c5bbb26d2 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-home", "description": "A Backstage plugin that helps you build a home page", - "version": "0.5.2-next.1", + "version": "0.5.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -38,6 +38,7 @@ "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", + "@backstage/plugin-home-react": "workspace:^", "@backstage/theme": "workspace:^", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -48,7 +49,6 @@ "@rjsf/validator-ajv8": "5.6.0", "@types/react": "^16.13.1 || ^17.0.0", "lodash": "^4.17.21", - "object-hash": "^3.0.0", "react-grid-layout": "^1.3.4", "react-resizable": "^3.0.4", "react-use": "^17.2.4", diff --git a/plugins/home/src/componentRenderers/ComponentAccordion.tsx b/plugins/home/src/componentRenderers/ComponentAccordion.tsx index 8b9795c9c3..77e7561e55 100644 --- a/plugins/home/src/componentRenderers/ComponentAccordion.tsx +++ b/plugins/home/src/componentRenderers/ComponentAccordion.tsx @@ -15,6 +15,7 @@ */ import React from 'react'; +import { SettingsModal } from '@backstage/plugin-home-react'; import { Accordion, AccordionDetails, @@ -27,8 +28,6 @@ import { makeStyles } from '@material-ui/core/styles'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import SettingsIcon from '@material-ui/icons/Settings'; -import { SettingsModal } from '../components'; - const useStyles = makeStyles((theme: Theme) => ({ settingsIconButton: { padding: theme.spacing(0, 1, 0, 0), diff --git a/plugins/home/src/components/CustomHomepage/CustomHomepageButtons.tsx b/plugins/home/src/components/CustomHomepage/CustomHomepageButtons.tsx index c2fdf5b979..22c88a30c7 100644 --- a/plugins/home/src/components/CustomHomepage/CustomHomepageButtons.tsx +++ b/plugins/home/src/components/CustomHomepage/CustomHomepageButtons.tsx @@ -20,6 +20,7 @@ import SaveIcon from '@material-ui/icons/Save'; import DeleteIcon from '@material-ui/icons/Delete'; import AddIcon from '@material-ui/icons/Add'; import EditIcon from '@material-ui/icons/Edit'; +import CancelIcon from '@material-ui/icons/Cancel'; const useStyles = makeStyles((theme: Theme) => createStyles({ @@ -41,6 +42,8 @@ interface CustomHomepageButtonsProps { clearLayout: () => void; setAddWidgetDialogOpen: (open: boolean) => void; changeEditMode: (mode: boolean) => void; + defaultConfigAvailable: boolean; + restoreDefault: () => void; } export const CustomHomepageButtons = (props: CustomHomepageButtonsProps) => { const { @@ -49,6 +52,8 @@ export const CustomHomepageButtons = (props: CustomHomepageButtonsProps) => { clearLayout, setAddWidgetDialogOpen, changeEditMode, + defaultConfigAvailable, + restoreDefault, } = props; const styles = useStyles(); @@ -59,27 +64,41 @@ export const CustomHomepageButtons = (props: CustomHomepageButtonsProps) => { variant="contained" color="primary" onClick={() => changeEditMode(true)} + size="small" startIcon={} > Edit ) : ( <> + {defaultConfigAvailable && ( + + )} {numWidgets > 0 && ( )}
diff --git a/plugins/kubernetes/src/components/Pods/types.ts b/plugins/kubernetes/src/components/Pods/types.ts index 195f0b9135..ac707c2a57 100644 --- a/plugins/kubernetes/src/components/Pods/types.ts +++ b/plugins/kubernetes/src/components/Pods/types.ts @@ -14,9 +14,10 @@ * limitations under the License. */ import { Pod } from 'kubernetes-models/v1'; +import { DetectedError } from '../../error-detection'; export interface PodAndErrors { clusterName: string; pod: Pod; - errors: any[]; + errors: DetectedError[]; } diff --git a/plugins/kubernetes/src/hooks/useMatchingErrors.test.tsx b/plugins/kubernetes/src/hooks/useMatchingErrors.test.tsx new file mode 100644 index 0000000000..b5fe588e86 --- /dev/null +++ b/plugins/kubernetes/src/hooks/useMatchingErrors.test.tsx @@ -0,0 +1,85 @@ +/* + * Copyright 2023 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 { renderHook } from '@testing-library/react-hooks'; +import { DetectedErrorsContext, useMatchingErrors } from './useMatchingErrors'; +import { DetectedError } from '../error-detection'; +import { ResourceRef } from '../error-detection/types'; + +const genericErrorWithRef = (resourceRef: ResourceRef): DetectedError => { + return { + type: 'some-error', + severity: 10, + message: 'some error message', + occuranceCount: 1, + sourceRef: resourceRef, + proposedFix: [ + { + type: 'logs', + container: 'some-container', + errorType: 'some error type', + rootCauseExplanation: 'some root cause', + possibleFixes: ['fix1', 'fix2'], + }, + ], + }; +}; + +describe('useMatchingErrors', () => { + it('should filter non-matching resources', () => { + const wrapper = ({ children }: { children: React.ReactNode }) => ( + + {children} + + ); + + const { result } = renderHook( + () => + useMatchingErrors({ + metadata: { + name: 'some-name', + namespace: 'some-namespace', + }, + kind: 'some-kind', + apiVersion: 'some-apiGroup', + }), + { wrapper }, + ); + expect(result.current).toStrictEqual([ + genericErrorWithRef({ + name: 'some-name', + namespace: 'some-namespace', + kind: 'some-kind', + apiGroup: 'some-apiGroup', + }), + ]); + }); +}); diff --git a/plugins/kubernetes/src/hooks/useMatchingErrors.ts b/plugins/kubernetes/src/hooks/useMatchingErrors.ts new file mode 100644 index 0000000000..623a32bdf8 --- /dev/null +++ b/plugins/kubernetes/src/hooks/useMatchingErrors.ts @@ -0,0 +1,46 @@ +/* + * Copyright 2023 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, { useContext } from 'react'; +import { DetectedError, ResourceRef } from '../error-detection/types'; +import { TypeMeta } from '@kubernetes-models/base'; +import { IIoK8sApimachineryPkgApisMetaV1ObjectMeta as V1ObjectMeta } from '@kubernetes-models/apimachinery/apis/meta/v1/ObjectMeta'; + +export const DetectedErrorsContext = React.createContext([]); + +type Matcher = { + metadata?: V1ObjectMeta; +} & TypeMeta; + +export const useMatchingErrors = (matcher: Matcher): DetectedError[] => { + const targetRef: ResourceRef = { + name: matcher.metadata?.name ?? '', + namespace: matcher.metadata?.namespace ?? '', + kind: matcher.kind, + apiGroup: matcher.apiVersion, + }; + + const errors = useContext(DetectedErrorsContext); + + return errors.filter(e => { + const r = e.sourceRef; + return ( + targetRef.apiGroup === r.apiGroup && + targetRef.kind === r.kind && + targetRef.name === r.name && + targetRef.namespace === r.namespace + ); + }); +}; diff --git a/plugins/kubernetes/src/kubernetes-auth-provider/AksKubernetesAuthProvider.ts b/plugins/kubernetes/src/kubernetes-auth-provider/AksKubernetesAuthProvider.ts new file mode 100644 index 0000000000..401fc1e127 --- /dev/null +++ b/plugins/kubernetes/src/kubernetes-auth-provider/AksKubernetesAuthProvider.ts @@ -0,0 +1,39 @@ +/* + * Copyright 2023 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 { OAuthApi } from '@backstage/core-plugin-api'; +import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; +import { KubernetesAuthProvider } from './types'; + +export class AksKubernetesAuthProvider implements KubernetesAuthProvider { + constructor(private readonly microsoftAuthApi: OAuthApi) {} + + async decorateRequestBodyForAuth( + requestBody: KubernetesRequestBody, + ): Promise { + return { + ...requestBody, + auth: { ...requestBody.auth, aks: (await this.getCredentials()).token }, + }; + } + + async getCredentials(): Promise<{ token?: string }> { + return { + token: await this.microsoftAuthApi.getAccessToken( + '6dae42f8-4368-4678-94ff-3960e28e3630/user.read', + ), + }; + } +} diff --git a/plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.test.ts b/plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.test.ts index a83cbcfaa4..14e574022a 100644 --- a/plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.test.ts +++ b/plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.test.ts @@ -39,11 +39,18 @@ const requestBody: KubernetesRequestBody = { }; describe('KubernetesAuthProviders tests', () => { - const kap = new KubernetesAuthProviders({ - googleAuthApi: new MockAuthApi('googleToken'), - oidcProviders: { - okta: new MockAuthApi('oktaToken'), - }, + let microsoftAuthApi: MockAuthApi; + let kap: KubernetesAuthProviders; + + beforeEach(() => { + microsoftAuthApi = new MockAuthApi('aksToken'); + kap = new KubernetesAuthProviders({ + microsoftAuthApi, + googleAuthApi: new MockAuthApi('googleToken'), + oidcProviders: { + okta: new MockAuthApi('oktaToken'), + }, + }); }); it('adds token to request body for google authProvider', async () => { @@ -52,6 +59,15 @@ describe('KubernetesAuthProviders tests', () => { expect(details.auth?.google).toBe('googleToken'); }); + it('adds token to request body for aks authProvider', async () => { + const details = await kap.decorateRequestBodyForAuth('aks', requestBody); + + expect(details.auth?.aks).toBe('aksToken'); + expect(microsoftAuthApi.getAccessToken).toHaveBeenCalledWith( + '6dae42f8-4368-4678-94ff-3960e28e3630/user.read', + ); + }); + it('adds token to request body for oidc authProvider', async () => { const details = await kap.decorateRequestBodyForAuth( 'oidc.okta', diff --git a/plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.ts b/plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.ts index 836641f1ed..84154d5e96 100644 --- a/plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.ts +++ b/plugins/kubernetes/src/kubernetes-auth-provider/KubernetesAuthProviders.ts @@ -20,6 +20,7 @@ import { GoogleKubernetesAuthProvider } from './GoogleKubernetesAuthProvider'; import { ServerSideKubernetesAuthProvider } from './ServerSideAuthProvider'; import { OAuthApi, OpenIdConnectApi } from '@backstage/core-plugin-api'; import { OidcKubernetesAuthProvider } from './OidcKubernetesAuthProvider'; +import { AksKubernetesAuthProvider } from './AksKubernetesAuthProvider'; export class KubernetesAuthProviders implements KubernetesAuthProvidersApi { private readonly kubernetesAuthProviderMap: Map< @@ -28,6 +29,7 @@ export class KubernetesAuthProviders implements KubernetesAuthProvidersApi { >; constructor(options: { + microsoftAuthApi: OAuthApi; googleAuthApi: OAuthApi; oidcProviders?: { [key: string]: OpenIdConnectApi }; }) { @@ -56,6 +58,10 @@ export class KubernetesAuthProviders implements KubernetesAuthProvidersApi { 'localKubectlProxy', new ServerSideKubernetesAuthProvider(), ); + this.kubernetesAuthProviderMap.set( + 'aks', + new AksKubernetesAuthProvider(options.microsoftAuthApi), + ); if (options.oidcProviders) { Object.keys(options.oidcProviders).forEach(provider => { diff --git a/plugins/kubernetes/src/plugin.ts b/plugins/kubernetes/src/plugin.ts index e10b4856b7..02c7bfd2d6 100644 --- a/plugins/kubernetes/src/plugin.ts +++ b/plugins/kubernetes/src/plugin.ts @@ -87,7 +87,11 @@ export const kubernetesPlugin = createPlugin({ onelogin: oneloginAuthApi, }; - return new KubernetesAuthProviders({ googleAuthApi, oidcProviders }); + return new KubernetesAuthProviders({ + microsoftAuthApi, + googleAuthApi, + oidcProviders, + }); }, }), ], diff --git a/plugins/kubernetes/src/utils/pod.tsx b/plugins/kubernetes/src/utils/pod.tsx index 2f657e7658..ce556fbc8d 100644 --- a/plugins/kubernetes/src/utils/pod.tsx +++ b/plugins/kubernetes/src/utils/pod.tsx @@ -28,6 +28,7 @@ import { SubvalueCell, } from '@backstage/core-components'; import { ClientPodStatus } from '@backstage/plugin-kubernetes-common'; +import { Pod } from 'kubernetes-models/v1/Pod'; export const imageChips = (pod: V1Pod): ReactNode => { const containerStatuses = pod.status?.containerStatuses ?? []; @@ -38,19 +39,19 @@ export const imageChips = (pod: V1Pod): ReactNode => { return
{images}
; }; -export const containersReady = (pod: V1Pod): string => { +export const containersReady = (pod: Pod): string => { const containerStatuses = pod.status?.containerStatuses ?? []; const containersReadyItem = containerStatuses.filter(cs => cs.ready).length; return `${containersReadyItem}/${containerStatuses.length}`; }; -export const totalRestarts = (pod: V1Pod): number => { +export const totalRestarts = (pod: Pod): number => { const containerStatuses = pod.status?.containerStatuses ?? []; return containerStatuses?.reduce((a, b) => a + b.restartCount, 0); }; -export const containerStatuses = (pod: V1Pod): ReactNode => { +export const containerStatuses = (pod: Pod): ReactNode => { const containerStatusesItem = pod.status?.containerStatuses ?? []; const errors = containerStatusesItem.reduce((accum, next) => { if (next.state === undefined) { diff --git a/plugins/lighthouse-backend/CHANGELOG.md b/plugins/lighthouse-backend/CHANGELOG.md index 81da2807af..c1790fdb39 100644 --- a/plugins/lighthouse-backend/CHANGELOG.md +++ b/plugins/lighthouse-backend/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-lighthouse-backend +## 0.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/types@1.0.2 + - @backstage/plugin-lighthouse-common@0.1.1 + +## 0.2.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/types@1.0.2 + - @backstage/plugin-lighthouse-common@0.1.1 + ## 0.2.1-next.1 ### Patch Changes diff --git a/plugins/lighthouse-backend/package.json b/plugins/lighthouse-backend/package.json index 351ee3fb7e..c1b19ccf90 100644 --- a/plugins/lighthouse-backend/package.json +++ b/plugins/lighthouse-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse-backend", "description": "Backend functionalities for lighthouse", - "version": "0.2.1-next.1", + "version": "0.2.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md index 67aa76b0f9..26ca5177bb 100644 --- a/plugins/lighthouse/CHANGELOG.md +++ b/plugins/lighthouse/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-lighthouse +## 0.4.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-lighthouse-common@0.1.1 + +## 0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-lighthouse-common@0.1.1 + +## 0.4.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + ## 0.4.3-next.1 ### Patch Changes diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index 7afa358f76..d6cab95ff6 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse", "description": "A Backstage plugin that integrates towards Lighthouse", - "version": "0.4.3-next.1", + "version": "0.4.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/linguist-backend/CHANGELOG.md b/plugins/linguist-backend/CHANGELOG.md index 5096043450..d90e0017ac 100644 --- a/plugins/linguist-backend/CHANGELOG.md +++ b/plugins/linguist-backend/CHANGELOG.md @@ -1,5 +1,51 @@ # @backstage/plugin-linguist-backend +## 0.3.0-next.0 + +### Minor Changes + +- bbf91840a52a: **BREAKING**: Removed public constructor from `LinguistBackendApi`. Removed export of `LinguistBackendDatabase` and `LinguistBackendStore` + + Several improvements to the Linguist backend have been made: + + - Added tests for the `LinguistBackendDatabase` and `LinguistBackendApi` + - Added support for using SQLite as a database, helpful for local development + - Removed the default from the `processes_date` column + - Converted the `LinguistBackendApi` into an Interface + - Added the `LinguistBackendClient` which implements the `LinguistBackendApi` Interface + - Unprocessed entities will get processed before stale entities + - Entities in the Linguist database but not in the Catalog anymore will be deleted + - Improved the README's headings + +### Patch Changes + +- 3d11596a72b5: Update plugin installation docs to be more consistent across documentations +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-linguist-common@0.1.0 + +## 0.2.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-linguist-common@0.1.0 + ## 0.2.2-next.1 ### Patch Changes diff --git a/plugins/linguist-backend/README.md b/plugins/linguist-backend/README.md index 46c067fb5a..6cfd3800b6 100644 --- a/plugins/linguist-backend/README.md +++ b/plugins/linguist-backend/README.md @@ -14,8 +14,7 @@ Here's how to get the backend up and running: ```sh # From the Backstage root directory - cd packages/backend - yarn add @backstage/plugin-linguist-backend + yarn add --cwd packages/backend @backstage/plugin-linguist-backend ``` 2. Then we will create a new file named `packages/backend/src/plugins/linguist.ts`, and add the @@ -57,7 +56,11 @@ Here's how to get the backend up and running: 4. Now run `yarn start-backend` from the repo root 5. Finally open `http://localhost:7007/api/linguist/health` in a browser and it should return `{"status":"ok"}` -## Batch Size +## Plugin Option + +The Linguist backend has various plugin options that you can provide to the `createRouter` function in your `packages/backend/src/plugins/linguist.ts` file that will allow you to configure various aspects of how it works. The following sections go into the details of these options + +### Batch Size The Linguist backend is setup to process entities by acting as a queue where it will pull down all the applicable entities from the Catalog and add them to it's database (saving just the `entityRef`). Then it will grab the `n` oldest entities that have not been processed to determine their languages and process them. To control the batch size simply provide that to the `createRouter` function in your `packages/backend/src/plugins/linguist.ts` like this: @@ -67,7 +70,7 @@ return createRouter({ schedule: schedule, batchSize: 40 }, { ...env }); **Note:** The default batch size is 20 -## Kind +### Kind The default setup only processes entities of kind `['API', 'Component', 'Template']`. To control the `kind` that are processed provide that to the `createRouter` function in your `packages/backend/src/plugins/linguist.ts` like this: @@ -75,7 +78,7 @@ The default setup only processes entities of kind `['API', 'Component', 'Templat return createRouter({ schedule: schedule, kind: ['Component'] }, { ...env }); ``` -## Refresh +### Refresh The default setup will only generate the language breakdown for entities with the linguist annotation that have not been generated yet. If you want this process to also refresh the data you can do so by adding the `age` (as a `HumanDuration`) in your `packages/backend/src/plugins/linguist.ts` when you call `createRouter`: @@ -85,7 +88,7 @@ return createRouter({ schedule: schedule, age: { days: 30 } }, { ...env }); With the `age` setup like this if the language breakdown is older than 15 days it will get regenerated. It's recommended that if you choose to use this configuration to set it to a large value - 30, 90, or 180 - as this data generally does not change drastically. -## Linguist JS options +### Linguist JS options The default setup will use the default [linguist-js](https://www.npmjs.com/package/linguist-js) options, a full list of the available options can be found [here](https://www.npmjs.com/package/linguist-js#API). @@ -96,7 +99,7 @@ return createRouter( ); ``` -## Use Source Location +### Use Source Location You may wish to use the `backstage.io/source-location` annotation over using the `backstage.io/linguist` as you may not be able to quickly add that annotation to your Entities. To do this you'll just need to set the `useSourceLocation` boolean to `true` in your `packages/backend/src/plugins/linguist.ts` when you call `createRouter`: diff --git a/plugins/linguist-backend/api-report.md b/plugins/linguist-backend/api-report.md index a47f123ac4..294d569ff7 100644 --- a/plugins/linguist-backend/api-report.md +++ b/plugins/linguist-backend/api-report.md @@ -3,16 +3,13 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { EntityResults } from '@backstage/plugin-linguist-common'; import express from 'express'; import { HumanDuration } from '@backstage/types'; -import { Knex } from 'knex'; import { Languages } from '@backstage/plugin-linguist-common'; import { Logger } from 'winston'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { PluginTaskScheduler } from '@backstage/backend-tasks'; -import { ProcessedEntity } from '@backstage/plugin-linguist-common'; import { TaskScheduleDefinition } from '@backstage/backend-tasks'; import { TokenManager } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; @@ -24,56 +21,13 @@ export function createRouter( ): Promise; // @public (undocumented) -export class LinguistBackendApi { - constructor( - logger: Logger, - store: LinguistBackendStore, - urlReader: UrlReader, - discovery: PluginEndpointDiscovery, - tokenManager: TokenManager, - age?: HumanDuration, - batchSize?: number, - useSourceLocation?: boolean, - kind?: string[], - linguistJsOptions?: Record, - ); +export interface LinguistBackendApi { // (undocumented) getEntityLanguages(entityRef: string): Promise; // (undocumented) processEntities(): Promise; } -// @public (undocumented) -export class LinguistBackendDatabase implements LinguistBackendStore { - constructor(db: Knex); - // (undocumented) - static create(knex: Knex): Promise; - // (undocumented) - getEntityResults(entityRef: string): Promise; - // (undocumented) - getProcessedEntities(): Promise; - // (undocumented) - getUnprocessedEntities(): Promise; - // (undocumented) - insertEntityResults(entityLanguages: EntityResults): Promise; - // (undocumented) - insertNewEntity(entityRef: string): Promise; -} - -// @public (undocumented) -export interface LinguistBackendStore { - // (undocumented) - getEntityResults(entityRef: string): Promise; - // (undocumented) - getProcessedEntities(): Promise; - // (undocumented) - getUnprocessedEntities(): Promise; - // (undocumented) - insertEntityResults(entityLanguages: EntityResults): Promise; - // (undocumented) - insertNewEntity(entityRef: string): Promise; -} - // @public (undocumented) export interface PluginOptions { // (undocumented) diff --git a/plugins/linguist-backend/migrations/20230216_remove_processed_date_default.js b/plugins/linguist-backend/migrations/20230216_remove_processed_date_default.js new file mode 100644 index 0000000000..5aaf02216e --- /dev/null +++ b/plugins/linguist-backend/migrations/20230216_remove_processed_date_default.js @@ -0,0 +1,39 @@ +/* + * Copyright 2023 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. + */ + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + // Sqlite does not support this raw SQL + if (!knex.client.config.client.includes('sqlite3')) { + await knex.raw( + 'ALTER TABLE entity_result ALTER COLUMN processed_date DROP DEFAULT;', + ); + } +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + // Sqlite does not support this raw SQL + if (!knex.client.config.client.includes('sqlite3')) { + await knex.raw( + 'ALTER TABLE entity_result ALTER COLUMN processed_date SET DEFAULT now();', + ); + } +}; diff --git a/plugins/linguist-backend/package.json b/plugins/linguist-backend/package.json index f3feacb740..2502a20736 100644 --- a/plugins/linguist-backend/package.json +++ b/plugins/linguist-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-linguist-backend", - "version": "0.2.2-next.1", + "version": "0.3.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -44,6 +44,7 @@ "yn": "^4.0.0" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/supertest": "^2.0.8", "msw": "^1.0.0", diff --git a/plugins/linguist-backend/src/api/LinguistBackendClient.test.ts b/plugins/linguist-backend/src/api/LinguistBackendClient.test.ts new file mode 100644 index 0000000000..1b0a4f4673 --- /dev/null +++ b/plugins/linguist-backend/src/api/LinguistBackendClient.test.ts @@ -0,0 +1,416 @@ +/* + * Copyright 2023 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 { + getVoidLogger, + ReadTreeResponse, + ServerTokenManager, + UrlReader, +} from '@backstage/backend-common'; +import { CatalogApi, GetEntitiesResponse } from '@backstage/catalog-client'; +import { Results } from 'linguist-js/dist/types'; +import { DateTime } from 'luxon'; +import { LinguistBackendStore } from '../db'; +import { kindOrDefault, LinguistBackendClient } from './LinguistBackendClient'; +import fs from 'fs-extra'; +import { LINGUIST_ANNOTATION } from '@backstage/plugin-linguist-common'; + +const linguistResultMock = Promise.resolve({ + files: { + count: 4, + bytes: 6010, + results: { + '/src/index.ts': 'TypeScript', + '/src/cli.js': 'JavaScript', + '/readme.md': 'Markdown', + '/no-lang': null, + }, + }, + languages: { + count: 3, + bytes: 6000, + results: { + JavaScript: { type: 'programming', bytes: 1000, color: '#f1e05a' }, + TypeScript: { type: 'programming', bytes: 2000, color: '#2b7489' }, + Markdown: { type: 'prose', bytes: 3000, color: '#083fa1' }, + }, + }, + unknown: { + count: 1, + bytes: 10, + filenames: { + 'no-lang': 10, + }, + extensions: {}, + }, +} as Results); + +describe('kindOrDefault', () => { + it('should return default kind when undefined', () => { + expect(kindOrDefault()).toEqual(['API', 'Component', 'Template']); + }); + it('should return the default kind when empty', () => { + expect(kindOrDefault([])).toEqual(['API', 'Component', 'Template']); + }); + it('should return provided kind when not empty', () => { + expect(kindOrDefault(['API'])).toEqual(['API']); + }); +}); + +describe('Linguist backend API', () => { + const logger = getVoidLogger(); + + const store: jest.Mocked = { + insertEntityResults: jest.fn(), + insertNewEntity: jest.fn(), + getEntityResults: jest.fn(), + getProcessedEntities: jest.fn(), + getUnprocessedEntities: jest.fn(), + getAllEntities: jest.fn(), + deleteEntity: jest.fn(), + }; + + const urlReader: jest.Mocked = { + readTree: jest.fn(), + search: jest.fn(), + readUrl: jest.fn(), + }; + + const catalogApi: jest.Mocked = { + getEntities: jest.fn(), + getEntityByRef: jest.fn(), + } as any; + + const tokenManager = ServerTokenManager.noop(); + + const api = new LinguistBackendClient( + logger, + store, + urlReader, + tokenManager, + catalogApi, + ); + + beforeEach(() => { + jest.resetAllMocks(); + }); + + it('should get languages for an entity', async () => { + store.getEntityResults.mockResolvedValue({ + languageCount: 1, + totalBytes: 2205, + processedDate: '2023-02-15T20:10:21.378Z', + breakdown: [ + { + name: 'YAML', + percentage: 100, + bytes: 2205, + type: 'data', + color: '#cb171e', + }, + ], + }); + + const entityRef = 'template:default/create-react-app-template'; + const languages = await api.getEntityLanguages(entityRef); + expect(languages).toEqual({ + languageCount: 1, + totalBytes: 2205, + processedDate: '2023-02-15T20:10:21.378Z', + breakdown: [ + { + name: 'YAML', + percentage: 100, + bytes: 2205, + type: 'data', + color: '#cb171e', + }, + ], + }); + }); + + it('should insert new entities', async () => { + const testEntityListResponse: GetEntitiesResponse = { + items: [ + { + apiVersion: 'backstage.io/v1beta1', + metadata: { + name: 'service-one', + }, + kind: 'Component', + }, + { + apiVersion: 'backstage.io/v1beta1', + metadata: { + name: 'service-two', + }, + kind: 'Component', + }, + { + apiVersion: 'backstage.io/v1beta1', + metadata: { + name: 'service-three', + }, + kind: 'Component', + }, + ], + }; + catalogApi.getEntities.mockResolvedValue(testEntityListResponse); + + await api.addNewEntities(); + expect(store.insertNewEntity).toHaveBeenCalledTimes(3); + }); + + it('should delete entities not in Catalog', async () => { + store.getAllEntities.mockResolvedValue([ + 'component:default/service-one', + 'component:default/stale-service-two', + ]); + + catalogApi.getEntityByRef.mockResolvedValueOnce({ + apiVersion: 'backstage.io/v1beta1', + metadata: { + name: 'service-one', + }, + kind: 'Component', + }); + + await api.cleanEntities(); + expect(store.deleteEntity).toHaveBeenCalledTimes(1); + }); + + it('should get default entity overview', async () => { + store.getProcessedEntities.mockResolvedValue([ + { + entityRef: 'component:default/service-one', + processedDate: DateTime.now().toJSDate(), + }, + { + entityRef: 'component:default/stale-service-two', + processedDate: DateTime.now().minus({ days: 45 }).toJSDate(), + }, + ]); + + store.getUnprocessedEntities.mockResolvedValue([ + 'component:default/service-three', + 'component:default/service-four', + 'component:default/service-five', + ]); + + const overview = await api.getEntitiesOverview(); + expect(overview.entityCount).toEqual(5); + expect(overview.processedCount).toEqual(2); + expect(overview.staleCount).toEqual(0); + expect(overview.pendingCount).toEqual(3); + expect(overview.filteredEntities).toEqual([ + 'component:default/service-three', + 'component:default/service-four', + 'component:default/service-five', + ]); + }); + + it('should get entity overview with stale items', async () => { + const apiWithAge = new LinguistBackendClient( + logger, + store, + urlReader, + tokenManager, + catalogApi, + { days: 5 }, + ); + store.getProcessedEntities.mockResolvedValue([ + { + entityRef: 'component:default/service-one', + processedDate: DateTime.now().toJSDate(), + }, + { + entityRef: 'component:default/stale-service-two', + processedDate: DateTime.now().minus({ days: 45 }).toJSDate(), + }, + ]); + + store.getUnprocessedEntities.mockResolvedValue([ + 'component:default/service-three', + 'component:default/service-four', + 'component:default/service-five', + ]); + + const overview = await apiWithAge.getEntitiesOverview(); + expect(overview.entityCount).toEqual(5); + expect(overview.processedCount).toEqual(2); + expect(overview.staleCount).toEqual(1); + expect(overview.pendingCount).toEqual(4); + expect(overview.filteredEntities).toEqual([ + 'component:default/service-three', + 'component:default/service-four', + 'component:default/service-five', + 'component:default/stale-service-two', + ]); + }); + + it('should generate and save languages for an entity', async () => { + const spy = jest + .spyOn(api, 'getLinguistResults') + .mockImplementation(() => linguistResultMock); + + urlReader.readTree.mockResolvedValueOnce({ + files: async () => [ + { + content: async () => Buffer.from('-- XXX: code-data', 'utf8'), + path: 'my-file.js', + }, + ], + dir: async () => '/temp/my-code', + } as ReadTreeResponse); + + const fsSpy = jest.spyOn(fs, 'remove'); + + await api.generateEntityLanguages( + 'component:default/fake-service', + 'https://some.fake/service/', + ); + expect(api.getLinguistResults).toHaveBeenCalled(); + expect(store.insertEntityResults).toHaveBeenCalled(); + expect(fs.remove).toHaveBeenCalled(); + spy.mockClear(); + fsSpy.mockClear(); + }); + + it('should generate languages for entities using default', async () => { + store.getProcessedEntities.mockResolvedValue([ + { + entityRef: 'component:default/service-one', + processedDate: DateTime.now().toJSDate(), + }, + { + entityRef: 'component:default/stale-service-two', + processedDate: DateTime.now().minus({ days: 45 }).toJSDate(), + }, + ]); + + store.getUnprocessedEntities.mockResolvedValue([ + 'component:default/service-three', + 'component:default/service-four', + 'component:default/service-five', + ]); + + const entity = { + apiVersion: 'backstage.io/v1beta1', + metadata: { + name: 'service-one', + annotations: { + [LINGUIST_ANNOTATION]: 'https://some.fake/service/', + }, + }, + kind: 'Component', + }; + + catalogApi.getEntityByRef.mockResolvedValue(entity); + + const resultsSpy = jest + .spyOn(api, 'getLinguistResults') + .mockImplementation(() => linguistResultMock); + + urlReader.readTree.mockResolvedValue({ + files: async () => [ + { + content: async () => Buffer.from('-- XXX: code-data', 'utf8'), + path: 'my-file.js', + }, + ], + dir: async () => '/temp/my-code', + } as ReadTreeResponse); + + const fsSpy = jest.spyOn(fs, 'remove'); + + const generateEntityLanguages = jest.spyOn(api, 'generateEntityLanguages'); + await api.generateEntitiesLanguages(); + expect(generateEntityLanguages).toHaveBeenCalledTimes(3); + + generateEntityLanguages.mockClear(); + resultsSpy.mockClear(); + fsSpy.mockClear(); + }); + + it('should generate languages for entities using defined batch size', async () => { + const apiWithBatchSize = new LinguistBackendClient( + logger, + store, + urlReader, + tokenManager, + catalogApi, + undefined, + 2, + ); + + store.getProcessedEntities.mockResolvedValue([ + { + entityRef: 'component:default/service-one', + processedDate: DateTime.now().toJSDate(), + }, + { + entityRef: 'component:default/stale-service-two', + processedDate: DateTime.now().minus({ days: 45 }).toJSDate(), + }, + ]); + + store.getUnprocessedEntities.mockResolvedValue([ + 'component:default/service-three', + 'component:default/service-four', + 'component:default/service-five', + ]); + + const entity = { + apiVersion: 'backstage.io/v1beta1', + metadata: { + name: 'service-one', + annotations: { + [LINGUIST_ANNOTATION]: 'https://some.fake/service/', + }, + }, + kind: 'Component', + }; + + catalogApi.getEntityByRef.mockResolvedValue(entity); + + const resultsSpy = jest + .spyOn(apiWithBatchSize, 'getLinguistResults') + .mockImplementation(() => linguistResultMock); + + urlReader.readTree.mockResolvedValue({ + files: async () => [ + { + content: async () => Buffer.from('-- XXX: code-data', 'utf8'), + path: 'my-file.js', + }, + ], + dir: async () => '/temp/my-code', + } as ReadTreeResponse); + + const fsSpy = jest.spyOn(fs, 'remove'); + + const generateEntityLanguages = jest.spyOn( + apiWithBatchSize, + 'generateEntityLanguages', + ); + await apiWithBatchSize.generateEntitiesLanguages(); + expect(generateEntityLanguages).toHaveBeenCalledTimes(2); + + generateEntityLanguages.mockClear(); + resultsSpy.mockClear(); + fsSpy.mockClear(); + }); +}); diff --git a/plugins/linguist-backend/src/api/LinguistBackendApi.ts b/plugins/linguist-backend/src/api/LinguistBackendClient.ts similarity index 76% rename from plugins/linguist-backend/src/api/LinguistBackendApi.ts rename to plugins/linguist-backend/src/api/LinguistBackendClient.ts index df7e30a7b0..5a84201bcb 100644 --- a/plugins/linguist-backend/src/api/LinguistBackendApi.ts +++ b/plugins/linguist-backend/src/api/LinguistBackendClient.ts @@ -22,14 +22,10 @@ import { } from '@backstage/plugin-linguist-common'; import { CATALOG_FILTER_EXISTS, - CatalogClient, GetEntitiesRequest, + CatalogApi, } from '@backstage/catalog-client'; -import { - PluginEndpointDiscovery, - TokenManager, - UrlReader, -} from '@backstage/backend-common'; +import { TokenManager, UrlReader } from '@backstage/backend-common'; import { DateTime } from 'luxon'; import { LINGUIST_ANNOTATION } from '@backstage/plugin-linguist-common'; @@ -43,16 +39,22 @@ import { } from '@backstage/catalog-model'; import { assertError } from '@backstage/errors'; import { HumanDuration } from '@backstage/types'; +import { Results } from 'linguist-js/dist/types'; /** @public */ -export class LinguistBackendApi { +export interface LinguistBackendApi { + getEntityLanguages(entityRef: string): Promise; + processEntities(): Promise; +} + +/** @public */ +export class LinguistBackendClient implements LinguistBackendApi { private readonly logger: Logger; private readonly store: LinguistBackendStore; private readonly urlReader: UrlReader; - private readonly discovery: PluginEndpointDiscovery; private readonly tokenManager: TokenManager; - private readonly catalogClient: CatalogClient; + private readonly catalogApi: CatalogApi; private readonly age?: HumanDuration; private readonly batchSize?: number; private readonly useSourceLocation?: boolean; @@ -62,8 +64,8 @@ export class LinguistBackendApi { logger: Logger, store: LinguistBackendStore, urlReader: UrlReader, - discovery: PluginEndpointDiscovery, tokenManager: TokenManager, + catalogApi: CatalogApi, age?: HumanDuration, batchSize?: number, useSourceLocation?: boolean, @@ -73,9 +75,8 @@ export class LinguistBackendApi { this.logger = logger; this.store = store; this.urlReader = urlReader; - this.discovery = discovery; this.tokenManager = tokenManager; - this.catalogClient = new CatalogClient({ discoveryApi: this.discovery }); + this.catalogApi = catalogApi; this.batchSize = batchSize; this.age = age; this.useSourceLocation = useSourceLocation; @@ -83,23 +84,25 @@ export class LinguistBackendApi { this.linguistJsOptions = linguistJsOptions; } - public async getEntityLanguages(entityRef: string): Promise { + async getEntityLanguages(entityRef: string): Promise { this.logger?.debug(`Getting languages for entity "${entityRef}"`); return this.store.getEntityResults(entityRef); } - public async processEntities() { + async processEntities(): Promise { this.logger?.info('Updating list of entities'); - await this.addNewEntities(); - this.logger?.info('Processing applicable entities through Linguist'); + this.logger?.info('Cleaning list of entities'); + await this.cleanEntities(); + this.logger?.info('Processing applicable entities through Linguist'); await this.generateEntitiesLanguages(); } - private async addNewEntities() { + /** @internal */ + async addNewEntities(): Promise { const annotationKey = this.useSourceLocation ? ANNOTATION_SOURCE_LOCATION : LINGUIST_ANNOTATION; @@ -112,7 +115,7 @@ export class LinguistBackendApi { }; const { token } = await this.tokenManager.getToken(); - const response = await this.catalogClient.getEntities(request, { token }); + const response = await this.catalogApi.getEntities(request, { token }); const entities = response.items; entities.forEach(entity => { @@ -121,7 +124,25 @@ export class LinguistBackendApi { }); } - private async generateEntitiesLanguages() { + /** @internal */ + async cleanEntities(): Promise { + this.logger?.info('Cleaning entities in Linguist queue'); + const allEntities = await this.store.getAllEntities(); + + for (const entityRef of allEntities) { + const result = await this.catalogApi.getEntityByRef(entityRef); + + if (!result) { + this.logger?.info( + `Entity ${entityRef} was not found in the Catalog, it will be deleted`, + ); + await this.store.deleteEntity(entityRef); + } + } + } + + /** @internal */ + async generateEntitiesLanguages(): Promise { const entitiesOverview = await this.getEntitiesOverview(); this.logger?.info( `Entities overview: Entity: ${entitiesOverview.entityCount}, Processed: ${entitiesOverview.processedCount}, Pending: ${entitiesOverview.pendingCount}, Stale ${entitiesOverview.staleCount}`, @@ -131,9 +152,10 @@ export class LinguistBackendApi { 0, this.batchSize ?? 20, ); - entities.forEach(async entityRef => { + + for (const entityRef of entities) { const { token } = await this.tokenManager.getToken(); - const entity = await this.catalogClient.getEntityByRef(entityRef, { + const entity = await this.catalogApi.getEntityByRef(entityRef, { token, }); const annotationKey = this.useSourceLocation @@ -153,10 +175,11 @@ export class LinguistBackendApi { `Unable to process "${entityRef}" using "${url}", message: ${error.message}, stack: ${error.stack}`, ); } - }); + } } - private async getEntitiesOverview(): Promise { + /** @internal */ + async getEntitiesOverview(): Promise { this.logger?.debug('Getting pending entities'); const processedEntities = await this.store.getProcessedEntities(); @@ -169,10 +192,10 @@ export class LinguistBackendApi { .map(pe => pe.entityRef); const unprocessedEntities = await this.store.getUnprocessedEntities(); - const filteredEntities = staleEntities.concat(unprocessedEntities); + const filteredEntities = unprocessedEntities.concat(staleEntities); const entitiesOverview: EntitiesOverview = { - entityCount: unprocessedEntities.length, + entityCount: unprocessedEntities.length + processedEntities.length, processedCount: processedEntities.length, staleCount: staleEntities.length, pendingCount: filteredEntities.length, @@ -182,7 +205,8 @@ export class LinguistBackendApi { return entitiesOverview; } - private async generateEntityLanguages( + /** @internal */ + async generateEntityLanguages( entityRef: string, url: string, ): Promise { @@ -193,7 +217,7 @@ export class LinguistBackendApi { const readTreeResponse = await this.urlReader.readTree(url); const dir = await readTreeResponse.dir(); - const results = await linguist(dir, this.linguistJsOptions); + const results = await this.getLinguistResults(dir); try { const totalBytes = results.languages.bytes; @@ -233,9 +257,15 @@ export class LinguistBackendApi { await fs.remove(dir); } } + + /** @internal */ + async getLinguistResults(dir: string): Promise { + const results = await linguist(dir, this.linguistJsOptions); + return results; + } } -export function kindOrDefault(kind?: string[]) { +export function kindOrDefault(kind?: string[]): string[] { if (!kind || kind.length === 0) { return ['API', 'Component', 'Template']; } diff --git a/plugins/linguist-backend/src/api/index.ts b/plugins/linguist-backend/src/api/index.ts index a88fa051d4..b3f73587e7 100644 --- a/plugins/linguist-backend/src/api/index.ts +++ b/plugins/linguist-backend/src/api/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { LinguistBackendApi } from './LinguistBackendApi'; +export type { LinguistBackendApi } from './LinguistBackendClient'; diff --git a/plugins/linguist-backend/src/db/LinguistBackendDatabase.test.ts b/plugins/linguist-backend/src/db/LinguistBackendDatabase.test.ts new file mode 100644 index 0000000000..5998ddfc1e --- /dev/null +++ b/plugins/linguist-backend/src/db/LinguistBackendDatabase.test.ts @@ -0,0 +1,200 @@ +/* + * Copyright 2021 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 { Knex as KnexType, Knex } from 'knex'; +import { TestDatabases } from '@backstage/backend-test-utils'; +import { + LinguistBackendDatabase, + LinguistBackendStore, +} from './LinguistBackendDatabase'; +import { Languages, ProcessedEntity } from '@backstage/plugin-linguist-common'; + +function createDatabaseManager( + client: KnexType, + skipMigrations: boolean = false, +) { + return { + getClient: async () => client, + migrations: { + skip: skipMigrations, + }, + }; +} + +const rawDbEntityResultRows = [ + { + id: '14b32439-848a-49b2-92a4-98753f932606', + entity_ref: 'template:default/create-react-app-template', + languages: undefined, + processed_date: undefined, + }, + { + id: '8c85d3ec-ccea-4b29-9de9-ccdd7e5ba452', + entity_ref: 'template:default/docs-template', + languages: undefined, + processed_date: undefined, + }, + { + id: 'b922c87b-37bc-4505-b4af-70a1438decda', + entity_ref: 'template:default/pull-request', + languages: + '{"languageCount":1,"totalBytes":2205,"processedDate":"2023-02-15T20:10:21.378Z","breakdown":[{"name":"YAML","percentage":100,"bytes":2205,"type":"data","color":"#cb171e"}]}', + processed_date: new Date('2023-02-15 20:10:21.378Z'), + }, + { + id: 'bd555e6d-a3d0-4b48-a930-194db8f80db7', + entity_ref: 'template:default/react-ssr-template', + languages: + '{"languageCount":8,"totalBytes":8988,"processedDate":"2023-02-15T20:10:21.388Z","breakdown":[{"name":"INI","percentage":2.26,"bytes":203,"type":"data","color":"#d1dbe0"},{"name":"JavaScript","percentage":5.94,"bytes":534,"type":"programming","color":"#f1e05a"},{"name":"YAML","percentage":31.09,"bytes":2794,"type":"data","color":"#cb171e"},{"name":"Markdown","percentage":11.79,"bytes":1060,"type":"prose","color":"#083fa1"},{"name":"JSON","percentage":21.09,"bytes":1896,"type":"data","color":"#292929"},{"name":"CSS","percentage":0,"bytes":0,"type":"markup","color":"#563d7c"},{"name":"TSX","percentage":26.01,"bytes":2338,"type":"programming","color":"#3178c6"},{"name":"TypeScript","percentage":1.81,"bytes":163,"type":"programming","color":"#3178c6"}]}', + processed_date: new Date('2023-02-15 20:10:21.388Z'), + }, + { + id: '4145c0cf-44e9-4e95-9d57-781af4685b28', + entity_ref: 'template:default/springboot-template', + languages: + '{"languageCount":9,"totalBytes":80986,"processedDate":"2023-02-15T20:10:21.419Z","breakdown":[{"name":"Shell","percentage":0.16,"bytes":130,"type":"programming","color":"#89e051"},{"name":"INI","percentage":0.35,"bytes":286,"type":"data","color":"#d1dbe0"},{"name":"Dockerfile","percentage":0.3,"bytes":246,"type":"programming","color":"#384d54"},{"name":"YAML","percentage":3.92,"bytes":3171,"type":"data","color":"#cb171e"},{"name":"Markdown","percentage":1.31,"bytes":1059,"type":"prose","color":"#083fa1"},{"name":"XML","percentage":10.48,"bytes":8491,"type":"data","color":"#0060ac"},{"name":"Java","percentage":1.8,"bytes":1455,"type":"programming","color":"#b07219"},{"name":"Text","percentage":81.22,"bytes":65780,"type":"prose"},{"name":"Protocol Buffer","percentage":0.45,"bytes":368,"type":"data"}]}', + processed_date: new Date('2023-02-15 20:10:21.419Z'), + }, +]; + +describe('Linguist database', () => { + const databases = TestDatabases.create(); + let store: LinguistBackendStore; + let testDbClient: Knex; + beforeAll(async () => { + testDbClient = await databases.init('SQLITE_3'); + const database = createDatabaseManager(testDbClient); + + store = await LinguistBackendDatabase.create(await database.getClient()); + }); + beforeEach(async () => { + await testDbClient.batchInsert('entity_result', rawDbEntityResultRows); + }); + afterEach(async () => { + await testDbClient('entity_result').delete(); + }); + + it('should be able to return entity results', async () => { + const validLanguagesResult: Languages = { + languageCount: 1, + totalBytes: 2205, + processedDate: '2023-02-15T20:10:21.378Z', + breakdown: [ + { + name: 'YAML', + percentage: 100, + bytes: 2205, + type: 'data', + color: '#cb171e', + }, + ], + }; + + const entityResult = await store.getEntityResults( + 'template:default/pull-request', + ); + expect(entityResult).toMatchObject(validLanguagesResult); + }); + + it('should return empty entity results when not found', async () => { + const validEmptyLanguagesResult: Languages = { + languageCount: 0, + totalBytes: 0, + processedDate: 'undefined', + breakdown: [], + }; + + const entityResult = await store.getEntityResults( + 'template:default/create-react-app-template', + ); + expect(entityResult).toMatchObject(validEmptyLanguagesResult); + }); + + it('should be able to return unprocessed entities', async () => { + const validUnprocessedEntities: string[] = [ + 'template:default/create-react-app-template', + 'template:default/docs-template', + ]; + + const unprocessedEntities = await store.getUnprocessedEntities(); + + expect(unprocessedEntities).toMatchObject(validUnprocessedEntities); + }); + + it('should return string[] when there is no unprocessed entities', async () => { + await testDbClient('entity_result').delete(); + const unprocessedEntities = await store.getUnprocessedEntities(); + + expect(unprocessedEntities).toMatchObject([]); + }); + + it('should be able to return processed entities', async () => { + const validProcessedEntities: ProcessedEntity[] = [ + { + entityRef: 'template:default/pull-request', + processedDate: new Date('2023-02-15 20:10:21.378Z'), + }, + { + entityRef: 'template:default/react-ssr-template', + processedDate: new Date('2023-02-15 20:10:21.388Z'), + }, + { + entityRef: 'template:default/springboot-template', + processedDate: new Date('2023-02-15 20:10:21.419Z'), + }, + ]; + + const processedEntities = await store.getProcessedEntities(); + + expect(processedEntities).toMatchObject(validProcessedEntities); + }); + + it('should return string[] when there is no processed entities', async () => { + await testDbClient('entity_result').delete(); + const unprocessedEntities = await store.getProcessedEntities(); + + expect(unprocessedEntities).toMatchObject([]); + }); + + it('should insert new entities and ignore duplicates', async () => { + const before = testDbClient.from('entity_result').count(); + + await store.insertNewEntity('component:/default/new-entity-one'); + await store.insertNewEntity('component:/default/new-entity-two'); + await store.insertNewEntity('template:default/pull-request'); + + const after = testDbClient.from('entity_result').count(); + + expect(before).toEqual(after); + }); + + it('should get all entities', async () => { + const allEntities = await store.getAllEntities(); + + expect(allEntities.length).toEqual(5); + }); + + it('should delete entity by its entityRef', async () => { + const before = await testDbClient.from('entity_result').count(); + + await store.deleteEntity('template:default/create-react-app-template'); + + const after = await testDbClient.from('entity_result').count(); + + expect(before).toEqual([{ 'count(*)': 5 }]); + expect(after).toEqual([{ 'count(*)': 4 }]); + }); +}); diff --git a/plugins/linguist-backend/src/db/LinguistBackendDatabase.ts b/plugins/linguist-backend/src/db/LinguistBackendDatabase.ts index cf93374800..5a59d18e90 100644 --- a/plugins/linguist-backend/src/db/LinguistBackendDatabase.ts +++ b/plugins/linguist-backend/src/db/LinguistBackendDatabase.ts @@ -26,8 +26,8 @@ import { export type RawDbEntityResultRow = { id: string; entity_ref: string; - languages: string; - processed_date: Date; + languages?: string; + processed_date?: Date; }; /** @public */ @@ -35,8 +35,10 @@ export interface LinguistBackendStore { insertEntityResults(entityLanguages: EntityResults): Promise; insertNewEntity(entityRef: string): Promise; getEntityResults(entityRef: string): Promise; - getProcessedEntities(): Promise; - getUnprocessedEntities(): Promise; + getProcessedEntities(): Promise; + getUnprocessedEntities(): Promise; + getAllEntities(): Promise; + deleteEntity(entityRef: string): Promise; } const migrationsDir = resolvePackagePath( @@ -91,7 +93,7 @@ export class LinguistBackendDatabase implements LinguistBackendStore { .where({ entity_ref: entityRef }) .first(); - if (!entityResults) { + if (!entityResults || !entityResults.languages) { const emptyResults: Languages = { languageCount: 0, totalBytes: 0, @@ -108,7 +110,7 @@ export class LinguistBackendDatabase implements LinguistBackendStore { } } - async getProcessedEntities(): Promise { + async getProcessedEntities(): Promise { const rawEntities = await this.db('entity_result') .whereNotNull('processed_date') .whereNotNull('languages'); @@ -118,9 +120,20 @@ export class LinguistBackendDatabase implements LinguistBackendStore { } const processedEntities = rawEntities.map(rawEntity => { + // Note: processed_date should never be null, this is handled by the DB query above + let processedDate = new Date(); + if (rawEntity.processed_date) { + // SQLite will return a Timestamp whereas Postgres will return a proper Date + // This tests to see if we are getting a timestamp and convert if needed + processedDate = new Date(+rawEntity.processed_date.toString()); + if (isNaN(+rawEntity.processed_date.toString())) { + processedDate = rawEntity.processed_date; + } + } + const processEntity = { entityRef: rawEntity.entity_ref, - processedDate: rawEntity.processed_date, + processedDate, }; return processEntity; @@ -129,8 +142,11 @@ export class LinguistBackendDatabase implements LinguistBackendStore { return processedEntities; } - async getUnprocessedEntities(): Promise { + async getUnprocessedEntities(): Promise { const rawEntities = await this.db('entity_result') + // TODO(ahhhndre) processed_date should always be null as well but it had a default to the current date + // once the default has been removed and released, we can then come back an enable this check + // .whereNull('processed_date') .whereNull('languages') .orderBy('created_at', 'asc'); @@ -144,4 +160,24 @@ export class LinguistBackendDatabase implements LinguistBackendStore { return unprocessedEntities; } + + async getAllEntities(): Promise { + const rawEntities = await this.db('entity_result'); + + if (!rawEntities) { + return []; + } + + const allEntities = rawEntities.map(rawEntity => { + return rawEntity.entity_ref; + }); + + return allEntities; + } + + async deleteEntity(entityRef: string): Promise { + await this.db('entity_result') + .where('entity_ref', entityRef) + .delete(); + } } diff --git a/plugins/linguist-backend/src/index.ts b/plugins/linguist-backend/src/index.ts index da1e0ffb00..37ecf2d47f 100644 --- a/plugins/linguist-backend/src/index.ts +++ b/plugins/linguist-backend/src/index.ts @@ -15,6 +15,4 @@ */ export * from './service/router'; -export { LinguistBackendApi } from './api'; -export { LinguistBackendDatabase } from './db'; -export type { LinguistBackendStore } from './db'; +export type { LinguistBackendApi } from './api'; diff --git a/plugins/linguist-backend/src/service/router.test.ts b/plugins/linguist-backend/src/service/router.test.ts index b8bde9d35d..7ab8f1c238 100644 --- a/plugins/linguist-backend/src/service/router.test.ts +++ b/plugins/linguist-backend/src/service/router.test.ts @@ -73,7 +73,7 @@ describe('createRouter', () => { const router = await createRouter( { schedule: schedule, age: { days: 30 }, useSourceLocation: false }, { - linguistBackendApi, + linguistBackendApi: linguistBackendApi, discovery: testDiscovery, database: createDatabase(), reader: mockUrlReader, diff --git a/plugins/linguist-backend/src/service/router.ts b/plugins/linguist-backend/src/service/router.ts index 8d52a2e01d..9e45438ec8 100644 --- a/plugins/linguist-backend/src/service/router.ts +++ b/plugins/linguist-backend/src/service/router.ts @@ -31,6 +31,8 @@ import { TaskScheduleDefinition, } from '@backstage/backend-tasks'; import { HumanDuration } from '@backstage/types'; +import { CatalogClient } from '@backstage/catalog-client'; +import { LinguistBackendClient } from '../api/LinguistBackendClient'; /** @public */ export interface PluginOptions { @@ -74,14 +76,16 @@ export async function createRouter( await database.getClient(), ); - const linguistBackendApi = + const catalogClient = new CatalogClient({ discoveryApi: discovery }); + + const linguistBackendClient = routerOptions.linguistBackendApi || - new LinguistBackendApi( + new LinguistBackendClient( logger, linguistBackendStore, reader, - discovery, tokenManager, + catalogClient, age, batchSize, useSourceLocation, @@ -100,7 +104,7 @@ export async function createRouter( initialDelay: schedule.initialDelay, scope: schedule.scope, fn: async () => { - await linguistBackendApi.processEntities(); + await linguistBackendClient.processEntities(); }, }); } @@ -122,7 +126,7 @@ export async function createRouter( throw new Error('No entityRef was provided'); } - const entityLanguages = await linguistBackendApi.getEntityLanguages( + const entityLanguages = await linguistBackendClient.getEntityLanguages( entityRef as string, ); res.status(200).json(entityLanguages); diff --git a/plugins/linguist/CHANGELOG.md b/plugins/linguist/CHANGELOG.md index 7c3a38f09d..a939d7469c 100644 --- a/plugins/linguist/CHANGELOG.md +++ b/plugins/linguist/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-linguist +## 0.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-linguist-common@0.1.0 + +## 0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/plugin-linguist-common@0.1.0 + +## 0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.3-next.1 ### Patch Changes diff --git a/plugins/linguist/package.json b/plugins/linguist/package.json index e71271c03f..045d03f153 100644 --- a/plugins/linguist/package.json +++ b/plugins/linguist/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-linguist", - "version": "0.1.3-next.1", + "version": "0.1.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/microsoft-calendar/CHANGELOG.md b/plugins/microsoft-calendar/CHANGELOG.md index 6e4ca92146..dde26c7c1f 100644 --- a/plugins/microsoft-calendar/CHANGELOG.md +++ b/plugins/microsoft-calendar/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-microsoft-calendar +## 0.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.3-next.0 ### Patch Changes diff --git a/plugins/microsoft-calendar/package.json b/plugins/microsoft-calendar/package.json index a28d9a5111..5007718c4e 100644 --- a/plugins/microsoft-calendar/package.json +++ b/plugins/microsoft-calendar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-microsoft-calendar", - "version": "0.1.3-next.0", + "version": "0.1.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/newrelic-dashboard/CHANGELOG.md b/plugins/newrelic-dashboard/CHANGELOG.md index 6e3142ef09..3a103baf44 100644 --- a/plugins/newrelic-dashboard/CHANGELOG.md +++ b/plugins/newrelic-dashboard/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/plugin-newrelic-dashboard +## 0.2.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## 0.2.11 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.2.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.2.11-next.1 ### Patch Changes diff --git a/plugins/newrelic-dashboard/package.json b/plugins/newrelic-dashboard/package.json index c7d6ee5733..b493efe792 100644 --- a/plugins/newrelic-dashboard/package.json +++ b/plugins/newrelic-dashboard/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-newrelic-dashboard", - "version": "0.2.11-next.1", + "version": "0.2.12-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/newrelic/CHANGELOG.md b/plugins/newrelic/CHANGELOG.md index b9beb277dc..dc235412e7 100644 --- a/plugins/newrelic/CHANGELOG.md +++ b/plugins/newrelic/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-newrelic +## 0.3.37-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.3.36 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + +## 0.3.36-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 0.3.36-next.0 ### Patch Changes diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 117d51f9e9..805ec7071c 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-newrelic", "description": "A Backstage plugin that integrates towards New Relic", - "version": "0.3.36-next.0", + "version": "0.3.37-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/octopus-deploy/CHANGELOG.md b/plugins/octopus-deploy/CHANGELOG.md index 98c05807bf..aa7d089eec 100644 --- a/plugins/octopus-deploy/CHANGELOG.md +++ b/plugins/octopus-deploy/CHANGELOG.md @@ -1,5 +1,43 @@ # @backstage/plugin-octopus-deploy +## 0.2.1-next.0 + +### Patch Changes + +- 944a8ac6fcc0: Improved getting started documentation +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.2.0 + +### Minor Changes + +- 87211bc2873: Added support for Octopus Deploy spaces. The octopus.com/project-id annotation can now (optionally) be prefixed by a space identifier, for example. Spaces-1/Projects-102. + Also note that some of this plugins exported API's have changed to accommodate this change, changing from separate arguments to a single object. + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.2.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.2.0-next.1 ### Minor Changes diff --git a/plugins/octopus-deploy/README.md b/plugins/octopus-deploy/README.md index 6039856998..e80bbf0fcd 100644 --- a/plugins/octopus-deploy/README.md +++ b/plugins/octopus-deploy/README.md @@ -18,7 +18,7 @@ To use it, you will need to generate an [API Key](https://octopus.com/docs/octop // app-config.yaml proxy: '/octopus-deploy': - target: '' + target: 'https:///api' headers: X-Octopus-ApiKey: ${OCTOPUS_API_KEY} ``` diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json index f8cfe04450..0fc597d979 100644 --- a/plugins/octopus-deploy/package.json +++ b/plugins/octopus-deploy/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-octopus-deploy", - "version": "0.2.0-next.1", + "version": "0.2.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/org-react/CHANGELOG.md b/plugins/org-react/CHANGELOG.md index 54b536cb79..7b48f043d1 100644 --- a/plugins/org-react/CHANGELOG.md +++ b/plugins/org-react/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-org-react +## 0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.7-next.1 ### Patch Changes diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index 7778af38db..0eefa8b66e 100644 --- a/plugins/org-react/package.json +++ b/plugins/org-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-org-react", - "version": "0.1.7-next.1", + "version": "0.1.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index 017d0c6db6..c3f6be183f 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,63 @@ # @backstage/plugin-org +## 0.6.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.6.8 + +### Patch Changes + +- 6e387c077a4: Changed the MembersListCard component to allow displaying aggregated members when viewing a group. Now, a toggle switch can be displayed that lets you switch between showing direct members and aggregated members. + + To enable this new feature, set the showAggregateMembersToggle prop on EntityMembersListCard: + + ```jsx + // In packages/app/src/components/catalog/EntityPage.tsx + const groupPage = ( + // ... + + // ... + ); + ``` + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.6.8-next.2 + +### Patch Changes + +- 6e387c077a4: Changed the MembersListCard component to allow displaying aggregated members when viewing a group. Now, a toggle switch can be displayed that lets you switch between showing direct members and aggregated members. + + To enable this new feature, set the showAggregateMembersToggle prop on EntityMembersListCard: + + ```jsx + // In packages/app/src/components/catalog/EntityPage.tsx + const groupPage = ( + // ... + + // ... + ); + ``` + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.6.8-next.1 ### Patch Changes diff --git a/plugins/org/api-report.md b/plugins/org/api-report.md index 1111253119..7f21bfbb6b 100644 --- a/plugins/org/api-report.md +++ b/plugins/org/api-report.md @@ -20,6 +20,7 @@ export const EntityGroupProfileCard: (props: { export const EntityMembersListCard: (props: { memberDisplayTitle?: string | undefined; pageSize?: number | undefined; + showAggregateMembersToggle?: boolean | undefined; }) => JSX.Element; // @public (undocumented) @@ -47,6 +48,7 @@ export const GroupProfileCard: (props: { export const MembersListCard: (props: { memberDisplayTitle?: string; pageSize?: number; + showAggregateMembersToggle?: boolean; }) => JSX.Element; // @public diff --git a/plugins/org/package.json b/plugins/org/package.json index 8d6490b2e2..1c19e92f78 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-org", "description": "A Backstage plugin that helps you create entity pages for your organization", - "version": "0.6.8-next.1", + "version": "0.6.9-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -51,7 +51,10 @@ "@backstage/cli": "workspace:^", "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", + "@backstage/plugin-catalog": "workspace:^", + "@backstage/plugin-permission-react": "workspace:^", "@backstage/test-utils": "workspace:^", + "@backstage/types": "workspace:^", "@testing-library/dom": "^8.0.0", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", diff --git a/plugins/org/src/__testUtils__/catalogMocks.ts b/plugins/org/src/__testUtils__/catalogMocks.ts new file mode 100644 index 0000000000..b14856e345 --- /dev/null +++ b/plugins/org/src/__testUtils__/catalogMocks.ts @@ -0,0 +1,340 @@ +/* + * Copyright 2023 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 { + CatalogApi, + GetEntitiesByRefsRequest, + GetEntitiesRequest, +} from '@backstage/catalog-client'; +import { + CompoundEntityRef, + Entity, + GroupEntity, + stringifyEntityRef, +} from '@backstage/catalog-model'; + +export const groupA: GroupEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + name: 'group-a', + title: 'Group A', + description: 'Testing Group A', + }, + spec: { + type: 'testing-group', + children: [], + }, + relations: [ + { + type: 'parentOf', + targetRef: 'group:default/group-b', + }, + { + type: 'parentOf', + targetRef: 'group:default/group-c', + }, + ], +}; + +export const groupAWithALeader: GroupEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + name: 'group-a', + title: 'Group A', + description: 'Testing Group A', + }, + spec: { + type: 'testing-group', + children: [], + }, + relations: [ + { + type: 'teamLeadBy', + targetRef: 'user:default/group-a-user-one', + }, + { + type: 'parentOf', + targetRef: 'group:default/group-b', + }, + { + type: 'parentOf', + targetRef: 'group:default/group-c', + }, + ], +}; + +export const groupARef: CompoundEntityRef = { + kind: 'group', + name: 'group-a', + namespace: 'default', +}; + +export const groupB: GroupEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + name: 'group-b', + title: 'Group B', + description: 'Testing Group B', + }, + spec: { + type: 'testing-group', + children: [], + }, + relations: [ + { + type: 'parentOf', + targetRef: 'group:default/group-a', + }, + { + type: 'parentOf', + targetRef: 'group:default/group-d', + }, + ], +}; + +export const groupBRef: CompoundEntityRef = { + kind: 'group', + name: 'group-b', + namespace: 'default', +}; + +export const groupC: GroupEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + name: 'group-c', + title: 'Group C', + description: 'Testing Group C', + }, + spec: { + type: 'testing-group', + children: [], + }, +}; + +export const groupCRef: CompoundEntityRef = { + kind: 'group', + name: 'group-c', + namespace: 'default', +}; + +export const groupD: GroupEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + name: 'group-d', + title: 'Group D', + description: 'Testing Group D', + }, + spec: { + type: 'testing-group', + children: [], + }, + relations: [ + { + type: 'parentOf', + targetRef: 'group:default/group-c', + }, + { + type: 'parentOf', + targetRef: 'group:default/group-e', + }, + ], +}; + +export const groupDRef: CompoundEntityRef = { + kind: 'group', + name: 'group-d', + namespace: 'default', +}; + +export const groupE: GroupEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + name: 'group-e', + title: 'Group E', + description: 'Testing Group E', + }, + spec: { + type: 'testing-group', + children: [], + }, +}; + +export const groupERef: CompoundEntityRef = { + kind: 'group', + name: 'group-e', + namespace: 'default', +}; + +export const groupF: GroupEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + name: 'group-f', + title: 'Group F', + description: 'Testing Group F', + }, + spec: { + type: 'testing-group', + children: [], + }, +}; + +export const groupAUserOne: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + name: 'group-a-user-one', + }, + spec: { + profile: { + displayName: 'Group A User One', + email: 'group-a-user-one@testing.email', + picture: + 'https://avatars.dicebear.com/api/avataaars/breanna-davison@example.com.svg', + }, + }, +}; + +export const groupBUserOne: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + name: 'group-b-user-one', + }, + spec: { + profile: { + displayName: 'Group B User One', + email: 'group-b-user-one@testing.email', + picture: + 'https://avatars.dicebear.com/api/avataaars/breanna-davison@example.com.svg', + }, + }, +}; + +export const groupDUserOne: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + name: 'group-d-user-one', + }, + spec: { + profile: { + displayName: 'Group D User One', + email: 'group-d-user-one@testing.email', + picture: + 'https://avatars.dicebear.com/api/avataaars/breanna-davison@example.com.svg', + }, + }, +}; + +export const groupEUserOne: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + name: 'group-e-user-one', + }, + spec: { + profile: { + displayName: 'Group E User One', + email: 'group-e-user-one@testing.email', + picture: + 'https://avatars.dicebear.com/api/avataaars/breanna-davison@example.com.svg', + }, + }, +}; + +export const groupFUserOne: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + name: 'group-f-user-one', + }, + spec: { + profile: { + displayName: 'Group F User One', + email: 'group-f-user-one@testing.email', + picture: + 'https://avatars.dicebear.com/api/avataaars/breanna-davison@example.com.svg', + }, + }, +}; + +export const duplicatedUser: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + name: 'duplicated-user', + }, + spec: { + profile: { + displayName: 'Duplicated User', + email: 'duplicated-user@testing.email', + picture: + 'https://avatars.dicebear.com/api/avataaars/breanna-davison@example.com.svg', + }, + }, +}; + +const mockedRefsToRelationsMap = new Map([ + ['group:default/group-a', groupA], + ['group:default/group-b', groupB], + ['group:default/group-c', groupC], + ['group:default/group-d', groupD], + ['group:default/group-e', groupE], + ['group:default/group-f', groupF], +]); + +const mockedMembersMapping = new Map([ + ['group:default/group-a', [groupAUserOne, duplicatedUser]], + ['group:default/group-b', [groupBUserOne]], + ['group:default/group-c', []], + ['group:default/group-d', [groupDUserOne, duplicatedUser]], + ['group:default/group-e', [groupEUserOne, duplicatedUser]], + ['group:default/group-f', [groupFUserOne]], +]); + +type Nullable = T | undefined; + +export const mockedCatalogApiSupportingGroups: Partial = { + getEntities: async (request?: GetEntitiesRequest) => { + const actualFilter = (request?.filter as Nullable<{ + 'relations.memberof': string[]; + }>) ?? { 'relations.memberof': [] }; + const items = + actualFilter['relations.memberof'].length > 0 + ? (actualFilter['relations.memberof'] + .map(group => mockedMembersMapping.get(group)) + .flat() + .filter(entity => !!entity) as Entity[]) + : [...mockedMembersMapping.values()].flat(); + + return { items }; + }, + getEntityByRef: async (entityRef: CompoundEntityRef) => + mockedRefsToRelationsMap.get(stringifyEntityRef(entityRef)), + getEntitiesByRefs: async (request: GetEntitiesByRefsRequest) => { + const items = request.entityRefs.map(entityRef => + mockedRefsToRelationsMap.get(entityRef), + ); + return { items }; + }, +}; diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.stories.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.stories.tsx index 073f892302..6b34d8b934 100644 --- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.stories.tsx +++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.stories.tsx @@ -20,6 +20,10 @@ import { TestApiProvider } from '@backstage/test-utils'; import { Grid } from '@material-ui/core'; import React from 'react'; import { MemoryRouter } from 'react-router-dom'; +import { + groupA, + mockedCatalogApiSupportingGroups, +} from '../../../../__testUtils__/catalogMocks'; import { MembersListCard } from './MembersListCard'; export default { @@ -132,3 +136,17 @@ export const Empty = () => ( ); + +export const AggregateMembersToggle = () => ( + + + + + + + + + + + +); diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx index cc524b60a2..47e954eb17 100644 --- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx +++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx @@ -19,14 +19,26 @@ import { CatalogApi, catalogApiRef, EntityProvider, + StarredEntitiesApi, + starredEntitiesApiRef, } from '@backstage/plugin-catalog-react'; import { + renderInTestApp, renderWithEffects, TestApiProvider, wrapInTestApp, } from '@backstage/test-utils'; import React from 'react'; import { MembersListCard } from './MembersListCard'; +import { + groupA, + mockedCatalogApiSupportingGroups, +} from '../../../../__testUtils__/catalogMocks'; +import { permissionApiRef } from '@backstage/plugin-permission-react'; +import { EntityLayout } from '@backstage/plugin-catalog'; +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { Observable } from '@backstage/types'; // Mock needed because jsdom doesn't correctly implement box-sizing // https://github.com/ShinyChang/React-Text-Truncate/issues/70 @@ -41,6 +53,20 @@ jest.mock('react-text-truncate', () => { }; }); +const mockedStarredEntitiesApi: Partial = { + starredEntitie$: () => { + return { + subscribe: () => { + return { + unsubscribe() { + // This is intentional + }, + }; + }, + } as Observable>; + }, +}; + describe('MemberTab Test', () => { const groupEntity: GroupEntity = { apiVersion: 'backstage.io/v1alpha1', @@ -131,4 +157,164 @@ describe('MemberTab Test', () => { expect(rendered.getByText('Testers (1)')).toBeInTheDocument(); }); + + describe('Aggregate members toggle', () => { + it('Does not show the aggregate members toggle if the showAggregateMembersToggle prop is undefined', async () => { + await renderInTestApp( + + + + + + + + + , + ); + + const toggleSwitch = screen.queryByRole('checkbox'); + expect(toggleSwitch).toBeNull(); + }); + + it('Shows the aggregate members toggle if the showAggregateMembersToggle prop is true', async () => { + await renderInTestApp( + + + + + + + + + , + ); + + expect(screen.queryByRole('checkbox')).toBeInTheDocument(); + }); + + it('Shows only direct members if the showAggregateMembersToggle prop is undefined', async () => { + await renderInTestApp( + + + + + + + + + , + ); + + const displayedMemberNames = screen.queryAllByTestId('user-link'); + const duplicatedUserText = screen.getByText('Duplicated User'); + const groupAUserOneText = screen.getByText('Group A User One'); + + expect(displayedMemberNames).toHaveLength(2); + expect(duplicatedUserText).toBeInTheDocument(); + expect(groupAUserOneText).toBeInTheDocument(); + expect( + duplicatedUserText.compareDocumentPosition(groupAUserOneText), + ).toBe(Node.DOCUMENT_POSITION_FOLLOWING); + }); + + it('Shows only direct members if the aggregate members switch is turned off', async () => { + await renderInTestApp( + + + + + + + + + , + ); + + const displayedMemberNames = screen.queryAllByTestId('user-link'); + const duplicatedUserText = screen.getByText('Duplicated User'); + const groupAUserOneText = screen.getByText('Group A User One'); + + expect(displayedMemberNames).toHaveLength(2); + expect(duplicatedUserText).toBeInTheDocument(); + expect(groupAUserOneText).toBeInTheDocument(); + expect( + duplicatedUserText.compareDocumentPosition(groupAUserOneText), + ).toBe(Node.DOCUMENT_POSITION_FOLLOWING); + }); + + it('Shows all descendant members of the group when the aggregate users switch is turned on, showing duplicated members only once', async () => { + await renderInTestApp( + + + + + + + + + , + ); + + // Click the toggle switch + await userEvent.click(screen.getByRole('checkbox')); + + const displayedMemberNames = screen.queryAllByTestId('user-link'); + const duplicatedUserText = screen.getByText('Duplicated User'); + const groupAUserOneText = screen.getByText('Group A User One'); + const groupBUserOneText = screen.getByText('Group B User One'); + const groupDUserOneText = screen.getByText('Group D User One'); + const groupEUserOneText = screen.getByText('Group E User One'); + + expect(displayedMemberNames).toHaveLength(5); + + expect(duplicatedUserText).toBeInTheDocument(); + expect(groupAUserOneText).toBeInTheDocument(); + expect(groupBUserOneText).toBeInTheDocument(); + expect(groupDUserOneText).toBeInTheDocument(); + expect(groupEUserOneText).toBeInTheDocument(); + + expect( + duplicatedUserText.compareDocumentPosition(groupAUserOneText), + ).toBe(Node.DOCUMENT_POSITION_FOLLOWING); + expect(groupAUserOneText.compareDocumentPosition(groupBUserOneText)).toBe( + Node.DOCUMENT_POSITION_FOLLOWING, + ); + expect(groupBUserOneText.compareDocumentPosition(groupDUserOneText)).toBe( + Node.DOCUMENT_POSITION_FOLLOWING, + ); + expect(groupDUserOneText.compareDocumentPosition(groupEUserOneText)).toBe( + Node.DOCUMENT_POSITION_FOLLOWING, + ); + }); + }); }); diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx index eb61989144..0a5386ea20 100644 --- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx +++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx @@ -30,11 +30,12 @@ import { createStyles, Grid, makeStyles, + Switch, Theme, Typography, } from '@material-ui/core'; import Pagination from '@material-ui/lab/Pagination'; -import React from 'react'; +import React, { useState } from 'react'; import { generatePath } from 'react-router-dom'; import useAsync from 'react-use/lib/useAsync'; @@ -47,6 +48,10 @@ import { OverflowTooltip, } from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; +import { + getAllDesendantMembersForGroupEntity, + removeDuplicateEntitiesFrom, +} from '../../../../helpers/helpers'; const useStyles = makeStyles((theme: Theme) => createStyles({ @@ -98,6 +103,7 @@ const MemberComponent = (props: { member: UserEntity }) => { > { export const MembersListCard = (props: { memberDisplayTitle?: string; pageSize?: number; + showAggregateMembersToggle?: boolean; }) => { - const { memberDisplayTitle = 'Members', pageSize = 50 } = props; + const { + memberDisplayTitle = 'Members', + pageSize = 50, + showAggregateMembersToggle, + } = props; const { entity: groupEntity } = useEntity(); const { @@ -144,10 +155,23 @@ export const MembersListCard = (props: { setPage(pageIndex); }; + const [showAggregateMembers, setShowAggregateMembers] = useState(false); + + const { loading: loadingDescendantMembers, value: descendantMembers } = + useAsync(async () => { + if (!showAggregateMembersToggle) { + return [] as UserEntity[]; + } + + return await getAllDesendantMembersForGroupEntity( + groupEntity, + catalogApi, + ); + }, [catalogApi, groupEntity, showAggregateMembersToggle]); const { loading, error, - value: members, + value: directMembers, } = useAsync(async () => { const membersList = await catalogApi.getEntities({ filter: { @@ -165,6 +189,15 @@ export const MembersListCard = (props: { return membersList.items as UserEntity[]; }, [catalogApi, groupEntity]); + const members = removeDuplicateEntitiesFrom( + [ + ...(directMembers ?? []), + ...(descendantMembers && showAggregateMembers ? descendantMembers : []), + ].sort((a, b) => + stringifyEntityRef(a).localeCompare(stringifyEntityRef(b)), + ), + ) as UserEntity[]; + if (loading) { return ; } else if (error) { @@ -193,21 +226,39 @@ export const MembersListCard = (props: { subheader={`of ${displayName}`} {...(nbPages <= 1 ? {} : { actions: pagination })} > - - {members && members.length > 0 ? ( - members - .slice(pageSize * (page - 1), pageSize * page) - .map(member => ( - - )) - ) : ( - - - This group has no {memberDisplayTitle.toLocaleLowerCase()}. - - - )} - + {showAggregateMembersToggle && ( + <> + Direct Members + { + setShowAggregateMembers(!showAggregateMembers); + }} + inputProps={{ 'aria-label': 'Users Type Switch' }} + /> + Aggregated Members + + )} + {showAggregateMembers && loadingDescendantMembers ? ( + + ) : ( + + {members && members.length > 0 ? ( + members + .slice(pageSize * (page - 1), pageSize * page) + .map(member => ( + + )) + ) : ( + + + This group has no {memberDisplayTitle.toLocaleLowerCase()}. + + + )} + + )} ); diff --git a/plugins/org/src/helpers/helpers.test.ts b/plugins/org/src/helpers/helpers.test.ts new file mode 100644 index 0000000000..4cee5422ce --- /dev/null +++ b/plugins/org/src/helpers/helpers.test.ts @@ -0,0 +1,135 @@ +/* + * Copyright 2023 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 { CatalogApi } from '@backstage/catalog-client'; +import { + getAllDesendantMembersForGroupEntity, + getMembersFromGroups, + getDescendantGroupsFromGroup, + removeDuplicateEntitiesFrom, +} from './helpers'; +import { + groupA, + groupARef, + groupB, + groupBRef, + groupC, + groupCRef, + groupD, + groupDRef, + groupE, + groupERef, + groupAUserOne, + groupBUserOne, + groupDUserOne, + groupEUserOne, + duplicatedUser, + mockedCatalogApiSupportingGroups, +} from '../__testUtils__/catalogMocks'; + +describe('Helper functions', () => { + it('getAllDesendantMembersForGroupEntity correctly recursively returns all descendant members', async () => { + const catalogApi = mockedCatalogApiSupportingGroups as CatalogApi; + + const actualGroupADescendantMembers = + await getAllDesendantMembersForGroupEntity(groupA, catalogApi); + const actualGroupCDescendantMembers = + await getAllDesendantMembersForGroupEntity(groupC, catalogApi); + + expect(actualGroupADescendantMembers).toStrictEqual([ + groupBUserOne, + groupDUserOne, + duplicatedUser, + groupEUserOne, + duplicatedUser, + ]); + expect(actualGroupCDescendantMembers).toStrictEqual([]); + }); + + it('getMembersFromGroups correctly returns all members of provided groups', async () => { + const catalogApi = mockedCatalogApiSupportingGroups as CatalogApi; + + const actualNoGroupsMembers = await getMembersFromGroups([], catalogApi); + const actualGroupAMembers = await getMembersFromGroups( + [groupARef], + catalogApi, + ); + const actualGroupCMembers = await getMembersFromGroups( + [groupCRef], + catalogApi, + ); + const actualMultipleGroupMembers = await getMembersFromGroups( + [groupARef, groupBRef, groupCRef], + catalogApi, + ); + + expect(actualNoGroupsMembers).toStrictEqual([]); + expect(actualGroupAMembers).toStrictEqual([groupAUserOne, duplicatedUser]); + expect(actualGroupCMembers).toStrictEqual([]); + expect(actualMultipleGroupMembers).toStrictEqual([ + groupAUserOne, + duplicatedUser, + groupBUserOne, + ]); + }); + + it('removeDuplicateEntitiesFrom correctly removes duplicate entities', () => { + const actualNoDuplicatedEntitiesResult = removeDuplicateEntitiesFrom([ + groupA, + groupB, + groupC, + groupD, + ]); + const actualDuplicatedEntitiesResult = removeDuplicateEntitiesFrom([ + groupA, + groupB, + groupB, + groupC, + groupC, + groupD, + groupE, + ]); + const actualNoEntitiesProvidedResult = removeDuplicateEntitiesFrom([]); + + expect(actualNoDuplicatedEntitiesResult).toStrictEqual([ + groupA, + groupB, + groupC, + groupD, + ]); + expect(actualDuplicatedEntitiesResult).toStrictEqual([ + groupA, + groupB, + groupC, + groupD, + groupE, + ]); + expect(actualNoEntitiesProvidedResult).toStrictEqual([]); + }); + + it('getDescendantGroupsFromGroup correctly recursively returns descendant groups, ignoring duplicates', async () => { + const actualDescendantGroups = await getDescendantGroupsFromGroup( + groupA, + mockedCatalogApiSupportingGroups as CatalogApi, + ); + expect(actualDescendantGroups).toStrictEqual([ + groupBRef, + groupCRef, + groupDRef, + groupERef, + ]); + }); +}); diff --git a/plugins/org/src/helpers/helpers.ts b/plugins/org/src/helpers/helpers.ts new file mode 100644 index 0000000000..7da4ee32d8 --- /dev/null +++ b/plugins/org/src/helpers/helpers.ts @@ -0,0 +1,118 @@ +/* + * Copyright 2023 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 { + CompoundEntityRef, + DEFAULT_NAMESPACE, + Entity, + GroupEntity, + RELATION_PARENT_OF, + stringifyEntityRef, + UserEntity, +} from '@backstage/catalog-model'; +import { + CatalogApi, + getEntityRelations, +} from '@backstage/plugin-catalog-react'; + +export const getMembersFromGroups = async ( + groups: CompoundEntityRef[], + catalogApi: CatalogApi, +) => { + const membersList = + groups.length === 0 + ? { items: [] } + : await catalogApi.getEntities({ + filter: { + kind: 'User', + 'relations.memberof': groups.map(group => + stringifyEntityRef({ + kind: 'group', + namespace: group.namespace.toLocaleLowerCase('en-US'), + name: group.name.toLocaleLowerCase('en-US'), + }), + ), + }, + }); + + return membersList.items as UserEntity[]; +}; + +export const getDescendantGroupsFromGroup = async ( + group: GroupEntity, + catalogApi: CatalogApi, +) => { + const alreadyQueuedOrExpandedGroupNames = new Map(); + const groupRef: CompoundEntityRef = { + kind: group.kind, + namespace: group.metadata.namespace ?? DEFAULT_NAMESPACE, + name: group.metadata.name, + }; + + const groupQueue = [groupRef]; + const resultantGroupRefs: CompoundEntityRef[] = []; + + // Continue expanding groups until there are no more + while (groupQueue.length > 0) { + const activeGroupRef = groupQueue.shift() as CompoundEntityRef; + const activeGroup = await catalogApi.getEntityByRef(activeGroupRef); + alreadyQueuedOrExpandedGroupNames.set( + stringifyEntityRef(activeGroupRef), + true, + ); + + const childGroups = getEntityRelations(activeGroup, RELATION_PARENT_OF, { + kind: 'Group', + }).filter( + currentGroup => + !alreadyQueuedOrExpandedGroupNames.has( + stringifyEntityRef(currentGroup), + ), + ); + childGroups.forEach(childGroup => + alreadyQueuedOrExpandedGroupNames.set( + stringifyEntityRef(childGroup), + true, + ), + ); + + groupQueue.push(...childGroups); + resultantGroupRefs.push(...childGroups); + } + + return resultantGroupRefs; +}; + +export const getAllDesendantMembersForGroupEntity = async ( + groupEntity: GroupEntity, + catalogApi: CatalogApi, +) => + getMembersFromGroups( + await getDescendantGroupsFromGroup(groupEntity, catalogApi), + catalogApi, + ); + +export const removeDuplicateEntitiesFrom = (entityArray: Entity[]) => { + const seenEntities = new Map(); + + return entityArray.filter(entity => { + const stringifiedEntity = stringifyEntityRef(entity); + const isDuplicate = seenEntities.has(stringifiedEntity); + + seenEntities.set(stringifiedEntity, true); + return !isDuplicate; + }); +}; diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index c1ce6836eb..4cfff390e6 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-pagerduty +## 0.5.12-next.0 + +### Patch Changes + +- 3d11596a72b5: Update plugin installation docs to be more consistent across documentations +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## 0.5.11 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.5.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.5.11-next.1 ### Patch Changes diff --git a/plugins/pagerduty/README.md b/plugins/pagerduty/README.md index ac3ba529dd..2affe1c423 100644 --- a/plugins/pagerduty/README.md +++ b/plugins/pagerduty/README.md @@ -42,7 +42,7 @@ The file paths mentioned in the following steps are relative to your app's root First, install the PagerDuty plugin via a CLI: ```bash -# From your Backstage app root directory +# From your Backstage root directory yarn add --cwd packages/app @backstage/plugin-pagerduty ``` diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 8e599ca240..5437764465 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-pagerduty", "description": "A Backstage plugin that integrates towards PagerDuty", - "version": "0.5.11-next.1", + "version": "0.5.12-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/periskop-backend/CHANGELOG.md b/plugins/periskop-backend/CHANGELOG.md index fde89edbe9..13b512abbc 100644 --- a/plugins/periskop-backend/CHANGELOG.md +++ b/plugins/periskop-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-periskop-backend +## 0.1.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + ## 0.1.16-next.1 ### Patch Changes diff --git a/plugins/periskop-backend/package.json b/plugins/periskop-backend/package.json index b453b2bc59..56a27feff3 100644 --- a/plugins/periskop-backend/package.json +++ b/plugins/periskop-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop-backend", - "version": "0.1.16-next.1", + "version": "0.1.17-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/periskop/CHANGELOG.md b/plugins/periskop/CHANGELOG.md index f205e47356..b9d21cf576 100644 --- a/plugins/periskop/CHANGELOG.md +++ b/plugins/periskop/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-periskop +## 0.1.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.16-next.1 ### Patch Changes diff --git a/plugins/periskop/package.json b/plugins/periskop/package.json index 97b7c26418..52701c8ebb 100644 --- a/plugins/periskop/package.json +++ b/plugins/periskop/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop", - "version": "0.1.16-next.1", + "version": "0.1.17-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-backend/CHANGELOG.md b/plugins/permission-backend/CHANGELOG.md index 02bb528853..3087c6eb19 100644 --- a/plugins/permission-backend/CHANGELOG.md +++ b/plugins/permission-backend/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-permission-backend +## 0.5.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-node@0.7.9-next.0 + +## 0.5.20 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-permission-common@0.7.5 + ## 0.5.20-next.1 ### Patch Changes diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index 0156c96626..196c9eac55 100644 --- a/plugins/permission-backend/package.json +++ b/plugins/permission-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-backend", - "version": "0.5.20-next.1", + "version": "0.5.21-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-node/CHANGELOG.md b/plugins/permission-node/CHANGELOG.md index b2014e3e62..b44f41c96a 100644 --- a/plugins/permission-node/CHANGELOG.md +++ b/plugins/permission-node/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/plugin-permission-node +## 0.7.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-permission-common@0.7.5 + +## 0.7.8 + +### Patch Changes + +- a788e715cfc: `createPermissionIntegrationRouter` now accepts rules and permissions for multiple resource types. Example: + + ```typescript + createPermissionIntegrationRouter({ + resources: [ + { + resourceType: 'resourceType-1', + permissions: permissionsResourceType1, + rules: rulesResourceType1, + }, + { + resourceType: 'resourceType-2', + permissions: permissionsResourceType2, + rules: rulesResourceType2, + }, + ], + }); + ``` + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-permission-common@0.7.5 + ## 0.7.8-next.1 ### Patch Changes diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index a0187f4576..4614afb60f 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-permission-node", "description": "Common permission and authorization utilities for backend plugins", - "version": "0.7.8-next.1", + "version": "0.7.9-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/playlist-backend/CHANGELOG.md b/plugins/playlist-backend/CHANGELOG.md index 2bf296d6b4..0b33f0c2d7 100644 --- a/plugins/playlist-backend/CHANGELOG.md +++ b/plugins/playlist-backend/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-playlist-backend +## 0.3.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-node@0.7.9-next.0 + - @backstage/plugin-playlist-common@0.1.6 + +## 0.3.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-playlist-common@0.1.6 + ## 0.3.1-next.1 ### Patch Changes diff --git a/plugins/playlist-backend/package.json b/plugins/playlist-backend/package.json index c0ac336383..316e74cb23 100644 --- a/plugins/playlist-backend/package.json +++ b/plugins/playlist-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist-backend", - "version": "0.3.1-next.1", + "version": "0.3.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/playlist/CHANGELOG.md b/plugins/playlist/CHANGELOG.md index 363c92681d..58e5d008f5 100644 --- a/plugins/playlist/CHANGELOG.md +++ b/plugins/playlist/CHANGELOG.md @@ -1,5 +1,51 @@ # @backstage/plugin-playlist +## 0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + - @backstage/plugin-search-react@1.6.1-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-playlist-common@0.1.6 + +## 0.1.9 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/plugin-search-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-react@0.4.12 + - @backstage/plugin-playlist-common@0.1.6 + +## 0.1.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-search-react@1.6.0-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + ## 0.1.9-next.1 ### Patch Changes diff --git a/plugins/playlist/package.json b/plugins/playlist/package.json index c542e6f05b..b84ad18e83 100644 --- a/plugins/playlist/package.json +++ b/plugins/playlist/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist", - "version": "0.1.9-next.1", + "version": "0.1.10-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/proxy-backend/CHANGELOG.md b/plugins/proxy-backend/CHANGELOG.md index e18a0f5a7f..bf1caa40d6 100644 --- a/plugins/proxy-backend/CHANGELOG.md +++ b/plugins/proxy-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-proxy-backend +## 0.2.40-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + +## 0.2.39 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + ## 0.2.39-next.1 ### Patch Changes diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index f16c87f3d7..4be05976a9 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-proxy-backend", "description": "A Backstage backend plugin that helps you set up proxy endpoints in the backend", - "version": "0.2.39-next.1", + "version": "0.2.40-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/puppetdb/CHANGELOG.md b/plugins/puppetdb/CHANGELOG.md index f5bad45030..28b605932d 100644 --- a/plugins/puppetdb/CHANGELOG.md +++ b/plugins/puppetdb/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-puppetdb +## 0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## 0.1.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.1-next.1 ### Patch Changes diff --git a/plugins/puppetdb/package.json b/plugins/puppetdb/package.json index 8e7cafac21..209a58f1e1 100644 --- a/plugins/puppetdb/package.json +++ b/plugins/puppetdb/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-puppetdb", "description": "Backstage plugin to visualize resource information and Puppet facts from PuppetDB.", - "version": "0.1.1-next.1", + "version": "0.1.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/rollbar-backend/CHANGELOG.md b/plugins/rollbar-backend/CHANGELOG.md index 337ba58f5f..77470eab1d 100644 --- a/plugins/rollbar-backend/CHANGELOG.md +++ b/plugins/rollbar-backend/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-rollbar-backend +## 0.1.43-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + +## 0.1.42 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config@1.0.7 + ## 0.1.42-next.1 ### Patch Changes diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index 170f06dcb0..a7e7a7ffb4 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-rollbar-backend", "description": "A Backstage backend plugin that integrates towards Rollbar", - "version": "0.1.42-next.1", + "version": "0.1.43-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md index 758244bd93..bdf0d9c76a 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-rollbar +## 0.4.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.4.18 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.4.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.4.18-next.1 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index b057062bb7..6caac9b670 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-rollbar", "description": "A Backstage plugin that integrates towards Rollbar", - "version": "0.4.18-next.1", + "version": "0.4.19-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md b/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md index f384a38e48..8c7aca74d9 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-scaffolder-backend-module-confluence-to-markdown +## 0.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.14.1-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.4-next.0 + +## 0.1.2 + +### Patch Changes + +- 7c116bcac7f: Fixed the way that some request errors are thrown +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.14.0 + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/plugin-scaffolder-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## 0.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.13.2-next.2 + - @backstage/plugin-scaffolder-node@0.1.3-next.2 + - @backstage/config@1.0.7 + ## 0.1.2-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/package.json b/plugins/scaffolder-backend-module-confluence-to-markdown/package.json index bdc9238d2e..aa8d0741c9 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/package.json +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown", "description": "The confluence-to-markdown module for @backstage/plugin-scaffolder-backend", - "version": "0.1.2-next.1", + "version": "0.1.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/helpers.ts b/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/helpers.ts index 58f84a8747..c741f6f6c0 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/helpers.ts +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/helpers.ts @@ -88,7 +88,7 @@ export const getAndWriteAttachments = async ( }, }); if (!res.ok) { - throw ResponseError.fromResponse(res); + throw await ResponseError.fromResponse(res); } else if (res.body !== null) { fs.openSync(`${workspace}/${mkdocsDir}docs/img/${downloadTitle}`, 'w'); const writeStream = fs.createWriteStream( diff --git a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md index 05d8456582..3fe37b59a8 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-scaffolder-backend-module-cookiecutter +## 0.2.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.14.1-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.4-next.0 + +## 0.2.21 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.14.0 + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/plugin-scaffolder-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## 0.2.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.13.2-next.2 + - @backstage/plugin-scaffolder-node@0.1.3-next.2 + - @backstage/config@1.0.7 + ## 0.2.21-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index f8e494ae8b..ead732125d 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/package.json +++ b/plugins/scaffolder-backend-module-cookiecutter/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-cookiecutter", "description": "A module for the scaffolder backend that lets you template projects using cookiecutter", - "version": "0.2.21-next.1", + "version": "0.2.22-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md b/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md index 4d0b7edcc4..1176ab9e98 100644 --- a/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,49 @@ # @backstage/plugin-scaffolder-backend-module-gitlab +## 0.2.1-next.0 + +### Patch Changes + +- f5a66052f04f: Tweak README +- Updated dependencies + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-scaffolder-node@0.1.4-next.0 + +## 0.2.0 + +### Minor Changes + +- 439e2986be1: Add a new scaffolder action for gitlab to ensure a group exists + +### Patch Changes + +- f1496d4ab6f: Fix input schema validation issue for gitlab actions: + + - gitlab:group:ensureExists + - gitlab:projectAccessToken:create + - gitlab:projectDeployToken:create + - gitlab:projectVariable:create + +- Updated dependencies + - @backstage/integration@1.4.5 + - @backstage/plugin-scaffolder-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## 0.2.0-next.2 + +### Minor Changes + +- 439e2986be1: Add a new scaffolder action for gitlab to ensure a group exists + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.3-next.2 + - @backstage/config@1.0.7 + ## 0.1.1-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-gitlab/README.md b/plugins/scaffolder-backend-module-gitlab/README.md index d071ca0cf6..340b57bbf8 100644 --- a/plugins/scaffolder-backend-module-gitlab/README.md +++ b/plugins/scaffolder-backend-module-gitlab/README.md @@ -20,9 +20,10 @@ Configure the action: // packages/backend/src/plugins/scaffolder.ts import { - createGitlabProjectAccessTokenAction, createGitlabProjectAccessTokenAction, createGitlabProjectDeployTokenAction, + createGitlabProjectVariableAction, + createGitlabGroupEnsureExistsAction, } from '@backstage/plugin-scaffolder-backend-module-gitlab'; // Create BuiltIn Actions @@ -36,18 +37,10 @@ const builtInActions = createBuiltinActions({ // Add Gitlab Actions const actions = [ ...builtInActions, - createGitlabProjectAccessTokenAction({ - integrations: integrations, - }), - createGitlabProjectAccessTokenAction({ - integrations: integrations, - }), - createGitlabProjectDeployTokenAction({ - integrations: integrations, - }), - createGitlabGroupEnsureExistsAction({ - integrations: integrations, - }), + createGitlabProjectAccessTokenAction({ integrations: integrations }), + createGitlabProjectDeployTokenAction({ integrations: integrations }), + createGitlabProjectVariableAction({ integrations: integrations }), + createGitlabGroupEnsureExistsAction({ integrations: integrations }), ]; // Create Scaffolder Router diff --git a/plugins/scaffolder-backend-module-gitlab/api-report.md b/plugins/scaffolder-backend-module-gitlab/api-report.md index 96ec3445dc..f7cf6024ec 100644 --- a/plugins/scaffolder-backend-module-gitlab/api-report.md +++ b/plugins/scaffolder-backend-module-gitlab/api-report.md @@ -12,10 +12,9 @@ export const createGitlabGroupEnsureExistsAction: (options: { integrations: ScmIntegrationRegistry; }) => TemplateAction< { + path: string[]; repoUrl: string; token?: string | undefined; - } & { - path: string[]; }, { groupId?: number | undefined; @@ -27,10 +26,9 @@ export const createGitlabProjectAccessTokenAction: (options: { integrations: ScmIntegrationRegistry; }) => TemplateAction< { + projectId: string | number; repoUrl: string; token?: string | undefined; - } & { - projectId: string | number; name?: string | undefined; accessLevel?: number | undefined; scopes?: string[] | undefined; @@ -45,11 +43,10 @@ export const createGitlabProjectDeployTokenAction: (options: { integrations: ScmIntegrationRegistry; }) => TemplateAction< { - repoUrl: string; - token?: string | undefined; - } & { name: string; projectId: string | number; + repoUrl: string; + token?: string | undefined; username?: string | undefined; scopes?: string[] | undefined; }, @@ -64,13 +61,12 @@ export const createGitlabProjectVariableAction: (options: { integrations: ScmIntegrationRegistry; }) => TemplateAction< { - repoUrl: string; - token?: string | undefined; - } & { key: string; value: string; projectId: string | number; + repoUrl: string; variableType: string; + token?: string | undefined; variableProtected?: boolean | undefined; masked?: boolean | undefined; raw?: boolean | undefined; diff --git a/plugins/scaffolder-backend-module-gitlab/package.json b/plugins/scaffolder-backend-module-gitlab/package.json index e338c21784..5c21695f90 100644 --- a/plugins/scaffolder-backend-module-gitlab/package.json +++ b/plugins/scaffolder-backend-module-gitlab/package.json @@ -1,12 +1,12 @@ { "name": "@backstage/plugin-scaffolder-backend-module-gitlab", - "version": "0.1.1-next.1", + "version": "0.2.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { "access": "public", - "main": "dist/index.esm.js", + "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, "backstage": { diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabGroupEnsureExistsAction.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabGroupEnsureExistsAction.ts index 698d402697..f96d57e356 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabGroupEnsureExistsAction.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabGroupEnsureExistsAction.ts @@ -36,7 +36,7 @@ export const createGitlabGroupEnsureExistsAction = (options: { id: 'gitlab:group:ensureExists', description: 'Ensures a Gitlab group exists', schema: { - input: commonGitlabConfig.and( + input: commonGitlabConfig.merge( z.object({ path: z .array(z.string(), { diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.ts index 832eb4cac7..614de0e221 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.ts @@ -33,7 +33,7 @@ export const createGitlabProjectAccessTokenAction = (options: { return createTemplateAction({ id: 'gitlab:projectAccessToken:create', schema: { - input: commonGitlabConfig.and( + input: commonGitlabConfig.merge( z.object({ projectId: z.union([z.number(), z.string()], { description: 'Project ID', diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectDeployTokenAction.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectDeployTokenAction.ts index 3010bd33d2..1665d23b39 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectDeployTokenAction.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectDeployTokenAction.ts @@ -36,7 +36,7 @@ export const createGitlabProjectDeployTokenAction = (options: { return createTemplateAction({ id: 'gitlab:projectDeployToken:create', schema: { - input: commonGitlabConfig.and( + input: commonGitlabConfig.merge( z.object({ projectId: z.union([z.number(), z.string()], { description: 'Project ID', diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectVariableAction.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectVariableAction.ts index a6043bea01..a154c16662 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectVariableAction.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectVariableAction.ts @@ -34,7 +34,7 @@ export const createGitlabProjectVariableAction = (options: { return createTemplateAction({ id: 'gitlab:projectVariable:create', schema: { - input: commonGitlabConfig.and( + input: commonGitlabConfig.merge( z.object({ projectId: z.union([z.number(), z.string()], { description: 'Project ID', diff --git a/plugins/scaffolder-backend-module-rails/CHANGELOG.md b/plugins/scaffolder-backend-module-rails/CHANGELOG.md index cd815f8d1e..bb5f44b8fa 100644 --- a/plugins/scaffolder-backend-module-rails/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-rails/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-scaffolder-backend-module-rails +## 0.4.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.14.1-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.4-next.0 + +## 0.4.14 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.14.0 + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/plugin-scaffolder-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## 0.4.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.13.2-next.2 + - @backstage/plugin-scaffolder-node@0.1.3-next.2 + - @backstage/config@1.0.7 + ## 0.4.14-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-rails/Rails.dockerfile b/plugins/scaffolder-backend-module-rails/Rails.dockerfile index 0774fdc975..921faa601d 100644 --- a/plugins/scaffolder-backend-module-rails/Rails.dockerfile +++ b/plugins/scaffolder-backend-module-rails/Rails.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.0 +FROM ruby:3.2 RUN apt-get update -qq && \ apt-get install -y nodejs postgresql-client git && \ diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index 035d698089..bb6df659cc 100644 --- a/plugins/scaffolder-backend-module-rails/package.json +++ b/plugins/scaffolder-backend-module-rails/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-rails", "description": "A module for the scaffolder backend that lets you template projects using Rails", - "version": "0.4.14-next.1", + "version": "0.4.15-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md index 128526ac64..65023baa20 100644 --- a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-scaffolder-backend-module-sentry +## 0.1.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-scaffolder-node@0.1.4-next.0 + +## 0.1.5 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## 0.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.3-next.2 + - @backstage/config@1.0.7 + ## 0.1.5-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-sentry/package.json b/plugins/scaffolder-backend-module-sentry/package.json index fa851fd80e..cd73436baf 100644 --- a/plugins/scaffolder-backend-module-sentry/package.json +++ b/plugins/scaffolder-backend-module-sentry/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-sentry", - "version": "0.1.5-next.1", + "version": "0.1.6-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md index b70c32aa52..ad01501993 100644 --- a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-scaffolder-backend-module-yeoman +## 0.2.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.4-next.0 + +## 0.2.18 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/types@1.0.2 + +## 0.2.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.3-next.2 + - @backstage/config@1.0.7 + ## 0.2.18-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index 77f50e3130..ddfc695dfc 100644 --- a/plugins/scaffolder-backend-module-yeoman/package.json +++ b/plugins/scaffolder-backend-module-yeoman/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-yeoman", - "version": "0.2.18-next.1", + "version": "0.2.19-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index 0b5b88b148..557a424976 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,74 @@ # @backstage/plugin-scaffolder-backend +## 1.14.1-next.0 + +### Patch Changes + +- cc936b529676: Fix handling of `optional` property in `catalog:register` scaffolder action +- b269da39ac2d: Clearer error messages for action `publish:gitlab:merge-request` +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-backend@1.9.2-next.0 + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-node@0.7.9-next.0 + - @backstage/plugin-scaffolder-common@1.3.0 + - @backstage/plugin-scaffolder-node@0.1.4-next.0 + +## 1.14.0 + +### Minor Changes + +- 67115f532b8: Expose both types of scaffolder permissions and rules through the metadata endpoint. + + The metadata endpoint now correctly exposes both types of scaffolder permissions and rules (for both the template and action resource types) through the metadata endpoint. + +- a73b3c0b097: Add ability to use `defaultNamespace` and `defaultKind` for scaffolder action `catalog:fetch` + +### Patch Changes + +- 1a48b84901c: Bump minimum required version of `vm2` to be 3.9.18 +- d20c87966a4: Bump minimum required version of `vm2` to be 3.9.17 +- 6d954de4b06: Update typing for `RouterOptions::actions` and `ScaffolderActionsExtensionPoint::addActions` to allow any kind of action being assigned to it. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.1 + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/plugin-scaffolder-common@1.3.0 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/plugin-scaffolder-node@0.1.3 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + +## 1.13.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.9.1-next.2 + - @backstage/plugin-scaffolder-common@1.3.0-next.0 + - @backstage/plugin-scaffolder-node@0.1.3-next.2 + - @backstage/config@1.0.7 + ## 1.13.2-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index a6fd41a29e..07dd5eaf1d 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -29,6 +29,7 @@ import { PermissionRule } from '@backstage/plugin-permission-node'; import { PermissionRuleParams } from '@backstage/plugin-permission-common'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginTaskScheduler } from '@backstage/backend-tasks'; +import { RESOURCE_TYPE_SCAFFOLDER_ACTION } from '@backstage/plugin-scaffolder-common/alpha'; import { RESOURCE_TYPE_SCAFFOLDER_TEMPLATE } from '@backstage/plugin-scaffolder-common/alpha'; import { Schema } from 'jsonschema'; import { ScmIntegrationRegistry } from '@backstage/integration'; @@ -49,6 +50,16 @@ import { ZodTypeDef } from 'zod'; // @public @deprecated (undocumented) export type ActionContext = ActionContext_2; +// @public (undocumented) +export type ActionPermissionRuleInput< + TParams extends PermissionRuleParams = PermissionRuleParams, +> = PermissionRule< + TemplateEntityStepV1beta3 | TemplateParametersV1beta3, + {}, + typeof RESOURCE_TYPE_SCAFFOLDER_ACTION, + TParams +>; + // @public export const createBuiltinActions: ( options: CreateBuiltInActionsOptions, @@ -108,6 +119,8 @@ export function createFetchCatalogEntityAction(options: { entityRef?: string | undefined; entityRefs?: string[] | undefined; optional?: boolean | undefined; + defaultKind?: string | undefined; + defaultNamespace?: string | undefined; }, { entity?: any; @@ -763,7 +776,9 @@ export interface RouterOptions { // (undocumented) logger: Logger; // (undocumented) - permissionRules?: TemplatePermissionRuleInput[]; + permissionRules?: Array< + TemplatePermissionRuleInput | ActionPermissionRuleInput + >; // (undocumented) permissions?: PermissionEvaluator; // (undocumented) diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 5b9e28322d..a5c3eaf937 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend", "description": "The Backstage backend plugin that helps you create new things", - "version": "1.13.2-next.1", + "version": "1.14.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -92,7 +92,7 @@ "p-queue": "^6.6.2", "prom-client": "^14.0.1", "uuid": "^8.2.0", - "vm2": "^3.9.17", + "vm2": "^3.9.18", "winston": "^3.2.1", "yaml": "^2.0.0", "zen-observable": "^0.10.0", diff --git a/plugins/scaffolder-backend/scripts/Cookiecutter.dockerfile b/plugins/scaffolder-backend/scripts/Cookiecutter.dockerfile index b33c7cbe64..a16248239c 100644 --- a/plugins/scaffolder-backend/scripts/Cookiecutter.dockerfile +++ b/plugins/scaffolder-backend/scripts/Cookiecutter.dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.7 +FROM alpine:3.18 RUN apk add --update \ git \ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.test.ts index 1cce7d66cb..bed15f2e39 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.test.ts @@ -46,179 +46,249 @@ describe('catalog:fetch', () => { jest.resetAllMocks(); }); - it('should return entity from catalog', async () => { - getEntityByRef.mockReturnValueOnce({ - metadata: { - namespace: 'default', - name: 'test', - }, - kind: 'Component', - } as Entity); - - await action.handler({ - ...mockContext, - input: { - entityRef: 'component:default/test', - }, - }); - - expect(getEntityByRef).toHaveBeenCalledWith('component:default/test', { - token: 'secret', - }); - expect(mockContext.output).toHaveBeenCalledWith('entity', { - metadata: { - namespace: 'default', - name: 'test', - }, - kind: 'Component', - }); - }); - - it('should throw error if entity fetch fails from catalog and optional is false', async () => { - getEntityByRef.mockImplementationOnce(() => { - throw new Error('Not found'); - }); - - await expect( - action.handler({ - ...mockContext, - input: { - entityRef: 'component:default/test', - }, - }), - ).rejects.toThrow('Not found'); - - expect(getEntityByRef).toHaveBeenCalledWith('component:default/test', { - token: 'secret', - }); - expect(mockContext.output).not.toHaveBeenCalled(); - }); - - it('should throw error if entity not in catalog and optional is false', async () => { - getEntityByRef.mockReturnValueOnce(null); - - await expect( - action.handler({ - ...mockContext, - input: { - entityRef: 'component:default/test', - }, - }), - ).rejects.toThrow('Entity component:default/test not found'); - - expect(getEntityByRef).toHaveBeenCalledWith('component:default/test', { - token: 'secret', - }); - expect(mockContext.output).not.toHaveBeenCalled(); - }); - - it('should return entities from catalog', async () => { - getEntitiesByRefs.mockReturnValueOnce({ - items: [ - { - metadata: { - namespace: 'default', - name: 'test', - }, - kind: 'Component', - } as Entity, - ], - }); - - await action.handler({ - ...mockContext, - input: { - entityRefs: ['component:default/test'], - }, - }); - - expect(getEntitiesByRefs).toHaveBeenCalledWith( - { entityRefs: ['component:default/test'] }, - { - token: 'secret', - }, - ); - expect(mockContext.output).toHaveBeenCalledWith('entities', [ - { + describe('fetch single entity', () => { + it('should return entity from catalog', async () => { + getEntityByRef.mockReturnValueOnce({ metadata: { namespace: 'default', name: 'test', }, kind: 'Component', - }, - ]); + } as Entity); + + await action.handler({ + ...mockContext, + input: { + entityRef: 'component:default/test', + }, + }); + + expect(getEntityByRef).toHaveBeenCalledWith('component:default/test', { + token: 'secret', + }); + expect(mockContext.output).toHaveBeenCalledWith('entity', { + metadata: { + namespace: 'default', + name: 'test', + }, + kind: 'Component', + }); + }); + + it('should throw error if entity fetch fails from catalog and optional is false', async () => { + getEntityByRef.mockImplementationOnce(() => { + throw new Error('Not found'); + }); + + await expect( + action.handler({ + ...mockContext, + input: { + entityRef: 'component:default/test', + }, + }), + ).rejects.toThrow('Not found'); + + expect(getEntityByRef).toHaveBeenCalledWith('component:default/test', { + token: 'secret', + }); + expect(mockContext.output).not.toHaveBeenCalled(); + }); + + it('should throw error if entity not in catalog and optional is false', async () => { + getEntityByRef.mockReturnValueOnce(null); + + await expect( + action.handler({ + ...mockContext, + input: { + entityRef: 'component:default/test', + }, + }), + ).rejects.toThrow('Entity component:default/test not found'); + + expect(getEntityByRef).toHaveBeenCalledWith('component:default/test', { + token: 'secret', + }); + expect(mockContext.output).not.toHaveBeenCalled(); + }); + + it('should use defaultKind and defaultNamespace if provided', async () => { + const entity: Entity = { + metadata: { + namespace: 'ns', + name: 'test', + }, + kind: 'Group', + } as Entity; + getEntityByRef.mockReturnValueOnce(entity); + + await action.handler({ + ...mockContext, + input: { + entityRef: 'test', + defaultKind: 'Group', + defaultNamespace: 'ns', + }, + }); + + expect(getEntityByRef).toHaveBeenCalledWith('group:ns/test', { + token: 'secret', + }); + expect(mockContext.output).toHaveBeenCalledWith('entity', entity); + }); }); - it('should throw error if undefined is returned for some entity', async () => { - getEntitiesByRefs.mockReturnValueOnce({ - items: [ + describe('fetch multiple entities', () => { + it('should return entities from catalog', async () => { + getEntitiesByRefs.mockReturnValueOnce({ + items: [ + { + metadata: { + namespace: 'default', + name: 'test', + }, + kind: 'Component', + } as Entity, + ], + }); + + await action.handler({ + ...mockContext, + input: { + entityRefs: ['component:default/test'], + }, + }); + + expect(getEntitiesByRefs).toHaveBeenCalledWith( + { entityRefs: ['component:default/test'] }, + { + token: 'secret', + }, + ); + expect(mockContext.output).toHaveBeenCalledWith('entities', [ { metadata: { namespace: 'default', name: 'test', }, kind: 'Component', - } as Entity, - undefined, - ], + }, + ]); }); - await expect( - action.handler({ + it('should throw error if undefined is returned for some entity', async () => { + getEntitiesByRefs.mockReturnValueOnce({ + items: [ + { + metadata: { + namespace: 'default', + name: 'test', + }, + kind: 'Component', + } as Entity, + undefined, + ], + }); + + await expect( + action.handler({ + ...mockContext, + input: { + entityRefs: ['component:default/test', 'component:default/test2'], + optional: false, + }, + }), + ).rejects.toThrow('Entity component:default/test2 not found'); + + expect(getEntitiesByRefs).toHaveBeenCalledWith( + { entityRefs: ['component:default/test', 'component:default/test2'] }, + { + token: 'secret', + }, + ); + expect(mockContext.output).not.toHaveBeenCalled(); + }); + + it('should return null in case some of the entities not found and optional is true', async () => { + getEntitiesByRefs.mockReturnValueOnce({ + items: [ + { + metadata: { + namespace: 'default', + name: 'test', + }, + kind: 'Component', + } as Entity, + undefined, + ], + }); + + await action.handler({ ...mockContext, input: { entityRefs: ['component:default/test', 'component:default/test2'], - optional: false, + optional: true, }, - }), - ).rejects.toThrow('Entity component:default/test2 not found'); + }); - expect(getEntitiesByRefs).toHaveBeenCalledWith( - { entityRefs: ['component:default/test', 'component:default/test2'] }, - { - token: 'secret', - }, - ); - expect(mockContext.output).not.toHaveBeenCalled(); - }); - - it('should return null in case some of the entities not found and optional is true', async () => { - getEntitiesByRefs.mockReturnValueOnce({ - items: [ + expect(getEntitiesByRefs).toHaveBeenCalledWith( + { entityRefs: ['component:default/test', 'component:default/test2'] }, + { + token: 'secret', + }, + ); + expect(mockContext.output).toHaveBeenCalledWith('entities', [ { metadata: { namespace: 'default', name: 'test', }, kind: 'Component', - } as Entity, - undefined, - ], + }, + null, + ]); }); - await action.handler({ - ...mockContext, - input: { - entityRefs: ['component:default/test', 'component:default/test2'], - optional: true, - }, - }); - - expect(getEntitiesByRefs).toHaveBeenCalledWith( - { entityRefs: ['component:default/test', 'component:default/test2'] }, - { - token: 'secret', - }, - ); - expect(mockContext.output).toHaveBeenCalledWith('entities', [ - { + it('should use defaultKind and defaultNamespace if provided', async () => { + const entity1: Entity = { + metadata: { + namespace: 'ns', + name: 'test', + }, + kind: 'Group', + } as Entity; + const entity2: Entity = { metadata: { namespace: 'default', name: 'test', }, - kind: 'Component', - }, - null, - ]); + kind: 'User', + } as Entity; + getEntitiesByRefs.mockReturnValueOnce({ + items: [entity1, entity2], + }); + + await action.handler({ + ...mockContext, + input: { + entityRefs: ['test', 'user:default/test'], + defaultKind: 'Group', + defaultNamespace: 'ns', + }, + }); + + expect(getEntitiesByRefs).toHaveBeenCalledWith( + { entityRefs: ['group:ns/test', 'user:default/test'] }, + { + token: 'secret', + }, + ); + + expect(mockContext.output).toHaveBeenCalledWith('entities', [ + entity1, + entity2, + ]); + }); }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.ts index d6abeee792..437da8ae73 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.ts @@ -18,6 +18,7 @@ import { CatalogApi } from '@backstage/catalog-client'; import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; import yaml from 'yaml'; import { z } from 'zod'; +import { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model'; const id = 'catalog:fetch'; @@ -69,6 +70,7 @@ export function createFetchCatalogEntityAction(options: { description: 'Returns entity or entities from the catalog by entity reference(s)', examples, + supportsDryRun: true, schema: { input: z.object({ entityRef: z @@ -87,6 +89,10 @@ export function createFetchCatalogEntityAction(options: { 'Allow the entity or entities to optionally exist. Default: false', }) .optional(), + defaultKind: z.string({ description: 'The default kind' }).optional(), + defaultNamespace: z + .string({ description: 'The default namespace' }) + .optional(), }), output: z.object({ entity: z @@ -106,7 +112,8 @@ export function createFetchCatalogEntityAction(options: { }), }, async handler(ctx) { - const { entityRef, entityRefs, optional } = ctx.input; + const { entityRef, entityRefs, optional, defaultKind, defaultNamespace } = + ctx.input; if (!entityRef && !entityRefs) { if (optional) { return; @@ -115,9 +122,14 @@ export function createFetchCatalogEntityAction(options: { } if (entityRef) { - const entity = await catalogClient.getEntityByRef(entityRef, { - token: ctx.secrets?.backstageToken, - }); + const entity = await catalogClient.getEntityByRef( + stringifyEntityRef( + parseEntityRef(entityRef, { defaultKind, defaultNamespace }), + ), + { + token: ctx.secrets?.backstageToken, + }, + ); if (!entity && !optional) { throw new Error(`Entity ${entityRef} not found`); @@ -127,7 +139,13 @@ export function createFetchCatalogEntityAction(options: { if (entityRefs) { const entities = await catalogClient.getEntitiesByRefs( - { entityRefs }, + { + entityRefs: entityRefs.map(ref => + stringifyEntityRef( + parseEntityRef(ref, { defaultKind, defaultNamespace }), + ), + ), + }, { token: ctx.secrets?.backstageToken, }, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.test.ts index c718f3906e..bae9f04575 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.test.ts @@ -265,9 +265,7 @@ describe('catalog:register', () => { it('should ignore failures when dry running the location in the catalog if `optional` is set', async () => { addLocation - .mockResolvedValueOnce({ - entities: [], - }) + .mockRejectedValueOnce(new Error('Not found')) .mockRejectedValueOnce(new Error('Not found')); await action.handler({ ...mockContext, @@ -300,4 +298,54 @@ describe('catalog:register', () => { 'http://foo/var', ); }); + + it('should fetch entities when adding location in the catalog fails and `optional` is set', async () => { + addLocation + .mockRejectedValueOnce(new Error('Already registered')) + .mockResolvedValueOnce({ + entities: [ + { + metadata: { + namespace: 'default', + name: 'test', + }, + kind: 'Component', + } as Entity, + ], + }); + await action.handler({ + ...mockContext, + input: { + catalogInfoUrl: 'http://foo/var', + optional: true, + }, + }); + + expect(addLocation).toHaveBeenNthCalledWith( + 1, + { + type: 'url', + target: 'http://foo/var', + }, + {}, + ); + expect(addLocation).toHaveBeenNthCalledWith( + 2, + { + dryRun: true, + type: 'url', + target: 'http://foo/var', + }, + {}, + ); + + expect(mockContext.output).toHaveBeenCalledWith( + 'catalogInfoUrl', + 'http://foo/var', + ); + expect(mockContext.output).toHaveBeenCalledWith( + 'entityRef', + 'component:default/test', + ); + }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts index e866eb12ba..3e35e16508 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts @@ -17,7 +17,7 @@ import { InputError } from '@backstage/errors'; import { ScmIntegrations } from '@backstage/integration'; import { CatalogApi } from '@backstage/catalog-client'; -import { stringifyEntityRef } from '@backstage/catalog-model'; +import { stringifyEntityRef, Entity } from '@backstage/catalog-model'; import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; import yaml from 'yaml'; @@ -144,17 +144,26 @@ export function createCatalogRegisterAction(options: { ctx.logger.info(`Registering ${catalogInfoUrl} in the catalog`); - await catalogClient.addLocation( - { - type: 'url', - target: catalogInfoUrl, - }, - ctx.secrets?.backstageToken - ? { token: ctx.secrets.backstageToken } - : {}, - ); + try { + // 1st try to register the location, this will throw an error if the location already exists (see catch) + await catalogClient.addLocation( + { + type: 'url', + target: catalogInfoUrl, + }, + ctx.secrets?.backstageToken + ? { token: ctx.secrets.backstageToken } + : {}, + ); + } catch (e) { + if (!input.optional) { + // if optional is false or unset, it is not allowed to register the same location twice, we rethrow the error + throw e; + } + } try { + // 2nd retry the registration as a dry run, this will not throw an error if the location already exists const result = await catalogClient.addLocation( { dryRun: true, @@ -166,18 +175,18 @@ export function createCatalogRegisterAction(options: { : {}, ); - if (result.entities.length > 0) { + if (result.entities.length) { const { entities } = result; - let entity: any; + let entity: Entity | undefined; // prioritise 'Component' type as it is the most central kind of entity entity = entities.find( - (e: any) => + e => !e.metadata.name.startsWith('generated-') && e.kind === 'Component', ); if (!entity) { entity = entities.find( - (e: any) => !e.metadata.name.startsWith('generated-'), + e => !e.metadata.name.startsWith('generated-'), ); } if (!entity) { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts index 06e056cda3..84a17024d1 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts @@ -218,14 +218,16 @@ export const createPublishGitlabMergeRequestAction = (options: { try { await api.Branches.create(repoID, branchName, String(defaultBranch)); } catch (e) { - throw new InputError(`The branch creation failed ${e}`); + throw new InputError( + `The branch creation failed. Please check that your repo does not already contain a branch named '${branchName}'. ${e}`, + ); } try { await api.Commits.create(repoID, branchName, ctx.input.title, actions); } catch (e) { throw new InputError( - `Committing the changes to ${branchName} failed ${e}`, + `Committing the changes to ${branchName} failed. Please check that none of the files created by the template already exists. ${e}`, ); } diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index deff4392d6..1771067367 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -36,8 +36,10 @@ import { TemplateEntityStepV1beta3, } from '@backstage/plugin-scaffolder-common'; import { + RESOURCE_TYPE_SCAFFOLDER_ACTION, RESOURCE_TYPE_SCAFFOLDER_TEMPLATE, - scaffolderPermissions, + scaffolderActionPermissions, + scaffolderTemplatePermissions, templateParameterReadPermission, templateStepReadPermission, } from '@backstage/plugin-scaffolder-common/alpha'; @@ -71,7 +73,7 @@ import { createPermissionIntegrationRouter, PermissionRule, } from '@backstage/plugin-permission-node'; -import { scaffolderTemplateRules } from './rules'; +import { scaffolderActionRules, scaffolderTemplateRules } from './rules'; /** * @@ -85,6 +87,29 @@ export type TemplatePermissionRuleInput< typeof RESOURCE_TYPE_SCAFFOLDER_TEMPLATE, TParams >; +function isTemplatePermissionRuleInput( + permissionRule: TemplatePermissionRuleInput | ActionPermissionRuleInput, +): permissionRule is TemplatePermissionRuleInput { + return permissionRule.resourceType === RESOURCE_TYPE_SCAFFOLDER_TEMPLATE; +} + +/** + * + * @public + */ +export type ActionPermissionRuleInput< + TParams extends PermissionRuleParams = PermissionRuleParams, +> = PermissionRule< + TemplateEntityStepV1beta3 | TemplateParametersV1beta3, + {}, + typeof RESOURCE_TYPE_SCAFFOLDER_ACTION, + TParams +>; +function isActionPermissionRuleInput( + permissionRule: TemplatePermissionRuleInput | ActionPermissionRuleInput, +): permissionRule is ActionPermissionRuleInput { + return permissionRule.resourceType === RESOURCE_TYPE_SCAFFOLDER_ACTION; +} /** * RouterOptions @@ -113,7 +138,9 @@ export interface RouterOptions { additionalTemplateFilters?: Record; additionalTemplateGlobals?: Record; permissions?: PermissionEvaluator; - permissionRules?: TemplatePermissionRuleInput[]; + permissionRules?: Array< + TemplatePermissionRuleInput | ActionPermissionRuleInput + >; identity?: IdentityApi; } @@ -290,17 +317,32 @@ export async function createRouter( const templateRules: TemplatePermissionRuleInput[] = Object.values( scaffolderTemplateRules, ); + const actionRules: ActionPermissionRuleInput[] = Object.values( + scaffolderActionRules, + ); if (permissionRules) { - templateRules.push(...permissionRules); + templateRules.push( + ...permissionRules.filter(isTemplatePermissionRuleInput), + ); + actionRules.push(...permissionRules.filter(isActionPermissionRuleInput)); } const isAuthorized = createConditionAuthorizer(Object.values(templateRules)); const permissionIntegrationRouter = createPermissionIntegrationRouter({ - resourceType: RESOURCE_TYPE_SCAFFOLDER_TEMPLATE, - permissions: scaffolderPermissions, - rules: templateRules, + resources: [ + { + resourceType: RESOURCE_TYPE_SCAFFOLDER_TEMPLATE, + permissions: scaffolderTemplatePermissions, + rules: templateRules, + }, + { + resourceType: RESOURCE_TYPE_SCAFFOLDER_ACTION, + permissions: scaffolderActionPermissions, + rules: actionRules, + }, + ], }); router.use(permissionIntegrationRouter); diff --git a/plugins/scaffolder-common/CHANGELOG.md b/plugins/scaffolder-common/CHANGELOG.md index c317230580..b5bcabb64f 100644 --- a/plugins/scaffolder-common/CHANGELOG.md +++ b/plugins/scaffolder-common/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-scaffolder-common +## 1.3.0 + +### Minor Changes + +- 82e10a6939c: Add support for Markdown text blob outputs from templates +- 67115f532b8: Expose scaffolder permissions in new sub-aggregations. + + In addition to exporting a list of all scaffolder permissions in `scaffolderPermissions`, scaffolder-common now exports `scaffolderTemplatePermissions` and `scaffolderActionPermissions`, which contain subsets of the scaffolder permissions separated by resource type. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.3.0 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.5 + +## 1.3.0-next.0 + +### Minor Changes + +- 82e10a6939c: Add support for Markdown text blob outputs from templates + ## 1.2.7 ### Patch Changes diff --git a/plugins/scaffolder-common/alpha-api-report.md b/plugins/scaffolder-common/alpha-api-report.md index d6e746026a..de9dffd1b9 100644 --- a/plugins/scaffolder-common/alpha-api-report.md +++ b/plugins/scaffolder-common/alpha-api-report.md @@ -14,12 +14,18 @@ export const RESOURCE_TYPE_SCAFFOLDER_ACTION = 'scaffolder-action'; // @alpha export const RESOURCE_TYPE_SCAFFOLDER_TEMPLATE = 'scaffolder-template'; +// @alpha +export const scaffolderActionPermissions: ResourcePermission<'scaffolder-action'>[]; + // @alpha export const scaffolderPermissions: ( | ResourcePermission<'scaffolder-action'> | ResourcePermission<'scaffolder-template'> )[]; +// @alpha +export const scaffolderTemplatePermissions: ResourcePermission<'scaffolder-template'>[]; + // @alpha export const templateParameterReadPermission: ResourcePermission<'scaffolder-template'>; diff --git a/plugins/scaffolder-common/package.json b/plugins/scaffolder-common/package.json index 6dfe10121e..45b4986155 100644 --- a/plugins/scaffolder-common/package.json +++ b/plugins/scaffolder-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-common", "description": "Common functionalities for the scaffolder, to be shared between scaffolder and scaffolder-backend plugin", - "version": "1.2.7", + "version": "1.3.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-common/src/Template.v1beta3.schema.json b/plugins/scaffolder-common/src/Template.v1beta3.schema.json index beb0ca5e31..1de68205b2 100644 --- a/plugins/scaffolder-common/src/Template.v1beta3.schema.json +++ b/plugins/scaffolder-common/src/Template.v1beta3.schema.json @@ -218,6 +218,33 @@ } } } + }, + "text": { + "type": "array", + "description": "A list of Markdown text blobs, like output data from the template.", + "items": { + "type": "object", + "required": [], + "properties": { + "title": { + "type": "string", + "description": "A user friendly display name for the text.", + "examples": ["Output Content"], + "minLength": 1 + }, + "icon": { + "type": "string", + "description": "A key representing a visual icon to be displayed in the UI.", + "examples": ["dashboard"], + "minLength": 1 + }, + "content": { + "type": "string", + "description": "The text blob to display in the UI, rendered as Markdown.", + "examples": ["**hey** _I'm_ Markdown"] + } + } + } } }, "additionalProperties": { diff --git a/plugins/scaffolder-common/src/permissions.ts b/plugins/scaffolder-common/src/permissions.ts index f06d7984f2..5c4c367889 100644 --- a/plugins/scaffolder-common/src/permissions.ts +++ b/plugins/scaffolder-common/src/permissions.ts @@ -87,3 +87,18 @@ export const scaffolderPermissions = [ templateParameterReadPermission, templateStepReadPermission, ]; + +/** + * List of the scaffolder permissions that are associated with template steps and parameters. + * @alpha + */ +export const scaffolderTemplatePermissions = [ + templateParameterReadPermission, + templateStepReadPermission, +]; + +/** + * List of the scaffolder permissions that are associated with scaffolder actions. + * @alpha + */ +export const scaffolderActionPermissions = [actionExecutePermission]; diff --git a/plugins/scaffolder-node/CHANGELOG.md b/plugins/scaffolder-node/CHANGELOG.md index 796c157f7a..5dafb204a0 100644 --- a/plugins/scaffolder-node/CHANGELOG.md +++ b/plugins/scaffolder-node/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-scaffolder-node +## 0.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-common@1.3.0 + +## 0.1.3 + +### Patch Changes + +- 6d954de4b06: Update typing for `RouterOptions::actions` and `ScaffolderActionsExtensionPoint::addActions` to allow any kind of action being assigned to it. +- Updated dependencies + - @backstage/plugin-scaffolder-common@1.3.0 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/types@1.0.2 + +## 0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-common@1.3.0-next.0 + ## 0.1.3-next.1 ### Patch Changes diff --git a/plugins/scaffolder-node/package.json b/plugins/scaffolder-node/package.json index f1e49a52e1..bf8cd06b88 100644 --- a/plugins/scaffolder-node/package.json +++ b/plugins/scaffolder-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-node", "description": "The plugin-scaffolder-node module for @backstage/plugin-scaffolder-backend", - "version": "0.1.3-next.1", + "version": "0.1.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-react/CHANGELOG.md b/plugins/scaffolder-react/CHANGELOG.md index 402c552c79..4d94c23692 100644 --- a/plugins/scaffolder-react/CHANGELOG.md +++ b/plugins/scaffolder-react/CHANGELOG.md @@ -1,5 +1,63 @@ # @backstage/plugin-scaffolder-react +## 1.4.1-next.0 + +### Patch Changes + +- 84a5c7724c7e: fixed refresh problem when backstage backend disconnects without any feedback to user. Now we send a generic message and try to reconnect after 15 seconds +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.4 + - @backstage/plugin-scaffolder-common@1.3.0 + +## 1.4.0 + +### Minor Changes + +- 82e10a6939c: Add support for Markdown text blob outputs from templates + +### Patch Changes + +- ad1a1429de4: Improvements to the `scaffolder/next` buttons UX: + + - Added padding around the "Create" button in the `Stepper` component + - Added a button bar that includes the "Cancel" and "Start Over" buttons to the `OngoingTask` component. The state of these buttons match their existing counter parts in the Context Menu + - Added a "Show Button Bar"/"Hide Button Bar" item to the `ContextMenu` component + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/plugin-scaffolder-common@1.3.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.4 + +## 1.4.0-next.2 + +### Minor Changes + +- 82e10a6939c: Add support for Markdown text blob outputs from templates + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/plugin-scaffolder-common@1.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 1.3.1-next.1 ### Patch Changes diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index baf5afb312..1761c88edf 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -217,6 +217,13 @@ export type ScaffolderOutputLink = { entityRef?: string; }; +// @public (undocumented) +export type ScaffolderOutputText = { + title?: string; + icon?: string; + content?: string; +}; + // @public export interface ScaffolderScaffoldOptions { // (undocumented) @@ -261,6 +268,7 @@ export type ScaffolderTask = { // @public (undocumented) export type ScaffolderTaskOutput = { links?: ScaffolderOutputLink[]; + text?: ScaffolderOutputText[]; } & { [key: string]: unknown; }; diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index 571b356a2d..14c82170d7 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-react", "description": "A frontend library that helps other Backstage plugins interact with the Scaffolder", - "version": "1.3.1-next.1", + "version": "1.4.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-react/src/api/types.ts b/plugins/scaffolder-react/src/api/types.ts index b39555c14f..2adecdd0d2 100644 --- a/plugins/scaffolder-react/src/api/types.ts +++ b/plugins/scaffolder-react/src/api/types.ts @@ -84,9 +84,17 @@ export type ScaffolderOutputLink = { entityRef?: string; }; +/** @public */ +export type ScaffolderOutputText = { + title?: string; + icon?: string; + content?: string; +}; + /** @public */ export type ScaffolderTaskOutput = { links?: ScaffolderOutputLink[]; + text?: ScaffolderOutputText[]; } & { [key: string]: unknown; }; diff --git a/plugins/scaffolder-react/src/hooks/useEventStream.ts b/plugins/scaffolder-react/src/hooks/useEventStream.ts index ec49911471..ad802dba99 100644 --- a/plugins/scaffolder-react/src/hooks/useEventStream.ts +++ b/plugins/scaffolder-react/src/hooks/useEventStream.ts @@ -169,67 +169,85 @@ export const useTaskEventStream = (taskId: string): TaskStream => { let didCancel = false; let subscription: Subscription | undefined; let logPusher: NodeJS.Timeout | undefined; - - scaffolderApi.getTask(taskId).then( - task => { - if (didCancel) { - return; - } - dispatch({ type: 'INIT', data: task }); - - // TODO(blam): Use a normal fetch to fetch the current log for the event stream - // and use that for an INIT_EVENTs dispatch event, and then - // use the last event ID to subscribe using after option to - // stream logs. Without this, if you have a lot of logs, it can look like the - // task is being rebuilt on load as it progresses through the steps at a slower - // rate whilst it builds the status from the event logs - const observable = scaffolderApi.streamLogs({ taskId }); - - const collectedLogEvents = new Array(); - - function emitLogs() { - if (collectedLogEvents.length) { - const logs = collectedLogEvents.splice( - 0, - collectedLogEvents.length, - ); - dispatch({ type: 'LOGS', data: logs }); + let retryCount = 1; + const startStreamLogProcess = () => + scaffolderApi.getTask(taskId).then( + task => { + if (didCancel) { + return; } - } + dispatch({ type: 'INIT', data: task }); - logPusher = setInterval(emitLogs, 500); + // TODO(blam): Use a normal fetch to fetch the current log for the event stream + // and use that for an INIT_EVENTs dispatch event, and then + // use the last event ID to subscribe using after option to + // stream logs. Without this, if you have a lot of logs, it can look like the + // task is being rebuilt on load as it progresses through the steps at a slower + // rate whilst it builds the status from the event logs + const observable = scaffolderApi.streamLogs({ taskId }); - subscription = observable.subscribe({ - next: event => { - switch (event.type) { - case 'log': - return collectedLogEvents.push(event); - case 'cancelled': - dispatch({ type: 'CANCELLED' }); - return undefined; - case 'completion': - emitLogs(); - dispatch({ type: 'COMPLETED', data: event }); - return undefined; - default: - throw new Error( - `Unhandled event type ${event.type} in observer`, - ); + const collectedLogEvents = new Array(); + + function emitLogs() { + if (collectedLogEvents.length) { + const logs = collectedLogEvents.splice( + 0, + collectedLogEvents.length, + ); + dispatch({ type: 'LOGS', data: logs }); } - }, - error: error => { - emitLogs(); - dispatch({ type: 'ERROR', data: error }); - }, - }); - }, - error => { - if (!didCancel) { - dispatch({ type: 'ERROR', data: error }); - } - }, - ); + } + logPusher = setInterval(emitLogs, 500); + + subscription = observable.subscribe({ + next: event => { + switch (event.type) { + case 'log': + return collectedLogEvents.push(event); + case 'cancelled': + dispatch({ type: 'CANCELLED' }); + return undefined; + case 'completion': + emitLogs(); + dispatch({ type: 'COMPLETED', data: event }); + return undefined; + default: + throw new Error( + `Unhandled event type ${event.type} in observer`, + ); + } + }, + error: error => { + emitLogs(); + // in some cases the error is a refused connection from backend + // this can happen from internet issues or proxy problems + // so we try to reconnect again after some time + // just to restart the fetch process + // details here https://github.com/backstage/backstage/issues/15002 + + if (!error.message) { + error.message = `We cannot connect at the moment, trying again in some seconds... Retrying (${retryCount}/3 retries)`; + } + + if (retryCount <= 3) { + setTimeout(() => { + retryCount += 1; + startStreamLogProcess(); + }, 15000); + } + + dispatch({ type: 'ERROR', data: error }); + }, + }); + }, + error => { + if (!didCancel) { + dispatch({ type: 'ERROR', data: error }); + } + }, + ); + startStreamLogProcess(); return () => { didCancel = true; if (subscription) { diff --git a/plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.test.tsx b/plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.test.tsx new file mode 100644 index 0000000000..8366dcadf8 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.test.tsx @@ -0,0 +1,56 @@ +/* + * Copyright 2022 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 { entityRouteRef } from '@backstage/plugin-catalog-react'; +import { renderInTestApp } from '@backstage/test-utils'; +import { fireEvent } from '@testing-library/react'; +import React from 'react'; +import { act } from 'react-dom/test-utils'; +import { DefaultTemplateOutputs } from '.'; + +describe('', () => { + it('should render template output', async () => { + const output = { + links: [{ title: 'Link 1', url: 'https://backstage.io/' }], + text: [{ title: 'Text 1', content: 'Hello, **world**!' }], + }; + + const { getByRole } = await renderInTestApp( + , + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name': entityRouteRef, + }, + }, + ); + + // test link outputs + for (const link of output.links ?? []) { + expect( + getByRole('button', { name: link.title }).closest('a'), + ).toHaveAttribute('href', link.url); + } + + // test text outputs + for (const text of output.text ?? []) { + await act(async () => { + fireEvent.click(getByRole('button', { name: text.title })); + }); + + expect(getByRole('heading', { level: 2 }).innerHTML).toBe(text.title); + } + }); +}); diff --git a/plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx b/plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx index 4d908461b0..a495e4ca9e 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx @@ -13,10 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; -import { Box, Paper } from '@material-ui/core'; -import { LinkOutputs } from './LinkOutputs'; +import { InfoCard, MarkdownContent } from '@backstage/core-components'; import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; +import { Box, Paper } from '@material-ui/core'; +import React, { useMemo, useState } from 'react'; +import { LinkOutputs } from './LinkOutputs'; +import { TextOutputs } from './TextOutputs'; /** * The DefaultOutputs renderer for the scaffolder task output @@ -26,17 +28,47 @@ import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; export const DefaultTemplateOutputs = (props: { output?: ScaffolderTaskOutput; }) => { - if (!props.output?.links) { + const [textOutputIndex, setTextOutputIndex] = useState(); + + const textOutput = useMemo( + () => + textOutputIndex !== undefined + ? props.output?.text?.[textOutputIndex] + : null, + [props.output, textOutputIndex], + ); + + if (!props.output) { return null; } return ( - - - - + <> + + + + + + + + + {textOutput ? ( + + + + + + - - + ) : null} + ); }; diff --git a/plugins/scaffolder-react/src/next/components/TemplateOutputs/TextOutputs.tsx b/plugins/scaffolder-react/src/next/components/TemplateOutputs/TextOutputs.tsx new file mode 100644 index 0000000000..7e64603e92 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/TemplateOutputs/TextOutputs.tsx @@ -0,0 +1,59 @@ +/* + * Copyright 2023 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 { IconComponent, useApp } from '@backstage/core-plugin-api'; +import { Button } from '@material-ui/core'; +import WebIcon from '@material-ui/icons/Web'; +import React from 'react'; +import { ScaffolderTaskOutput } from '../../../api'; + +export const TextOutputs = (props: { + output: ScaffolderTaskOutput; + index?: number; + setIndex?: (index: number | undefined) => void; +}) => { + const { + output: { text = [] }, + index, + setIndex, + } = props; + + const app = useApp(); + + const iconResolver = (key?: string): IconComponent => + app.getSystemIcon(key!) ?? WebIcon; + + return ( + <> + {text + .filter(({ content }) => content !== undefined) + .map(({ title, icon }, i) => { + const Icon = iconResolver(icon); + return ( + + ); + })} + + ); +}; diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index 11cc2224aa..05607eb83c 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,70 @@ # @backstage/plugin-scaffolder +## 1.13.2-next.0 + +### Patch Changes + +- cda753a797b5: Forward `Authorization` header for `EventSource` when credentials are available. +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-scaffolder-react@1.4.1-next.0 + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/plugin-permission-react@0.4.12 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-scaffolder-common@1.3.0 + +## 1.13.1 + +### Patch Changes + +- d560d457c98: Fix case GitLab workspace is a nested subgroup +- ad1a1429de4: Improvements to the `scaffolder/next` buttons UX: + + - Added padding around the "Create" button in the `Stepper` component + - Added a button bar that includes the "Cancel" and "Start Over" buttons to the `OngoingTask` component. The state of these buttons match their existing counter parts in the Context Menu + - Added a "Show Button Bar"/"Hide Button Bar" item to the `ContextMenu` component + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/integration@1.4.5 + - @backstage/plugin-scaffolder-common@1.3.0 + - @backstage/plugin-scaffolder-react@1.4.0 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-react@0.4.12 + +## 1.13.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/plugin-scaffolder-common@1.3.0-next.0 + - @backstage/plugin-scaffolder-react@1.4.0-next.2 + - @backstage/core-components@0.13.1-next.1 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-permission-react@0.4.12 + ## 1.13.1-next.1 ### Patch Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 2d618d6960..ff1d2f104e 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder", "description": "The Backstage plugin that helps you create new things", - "version": "1.13.1-next.1", + "version": "1.13.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -74,6 +74,7 @@ "@types/react": "^16.13.1 || ^17.0.0", "@uiw/react-codemirror": "^4.9.3", "classnames": "^2.2.6", + "event-source-polyfill": "^1.0.31", "git-url-parse": "^13.0.0", "humanize-duration": "^3.25.1", "immer": "^9.0.1", @@ -108,7 +109,6 @@ "@types/json-schema": "^7.0.9", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "event-source-polyfill": "1.0.25", "msw": "^1.0.0" }, "files": [ diff --git a/plugins/scaffolder/src/api.test.ts b/plugins/scaffolder/src/api.test.ts index e21bda8fd7..b9b1881066 100644 --- a/plugins/scaffolder/src/api.test.ts +++ b/plugins/scaffolder/src/api.test.ts @@ -20,11 +20,14 @@ import { MockFetchApi, setupRequestMockHandlers } from '@backstage/test-utils'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { ScaffolderClient } from './api'; +import { EventSourcePolyfill } from 'event-source-polyfill'; -const MockedEventSource = global.EventSource as jest.MockedClass< - typeof EventSource +const MockedEventSource = EventSourcePolyfill as jest.MockedClass< + typeof EventSourcePolyfill >; +jest.mock('event-source-polyfill'); + const server = setupServer(); describe('api', () => { @@ -102,6 +105,9 @@ describe('api', () => { }, ); + const token = 'fake-token'; + identityApi.getCredentials.mockResolvedValue({ token: token }); + const next = jest.fn(); await new Promise(complete => { @@ -112,7 +118,10 @@ describe('api', () => { expect(MockedEventSource).toHaveBeenCalledWith( 'http://backstage/api/v2/tasks/a-random-task-id/eventstream', - { withCredentials: true }, + { + withCredentials: true, + headers: { Authorization: `Bearer ${token}` }, + }, ); expect(MockedEventSource.prototype.close).toHaveBeenCalled(); diff --git a/plugins/scaffolder/src/api.ts b/plugins/scaffolder/src/api.ts index 7a3f6c14bb..c67a5c944e 100644 --- a/plugins/scaffolder/src/api.ts +++ b/plugins/scaffolder/src/api.ts @@ -41,6 +41,7 @@ import { } from '@backstage/plugin-scaffolder-react'; import queryString from 'qs'; +import { EventSourcePolyfill } from 'event-source-polyfill'; /** * An API to interact with the scaffolder backend. @@ -224,8 +225,11 @@ export class ScaffolderClient implements ScaffolderApi { params.set('after', String(Number(after))); } - this.discoveryApi.getBaseUrl('scaffolder').then( - baseUrl => { + Promise.all([ + this.discoveryApi.getBaseUrl('scaffolder'), + this.identityApi?.getCredentials(), + ]).then( + ([baseUrl, credentials]) => { const url = `${baseUrl}/v2/tasks/${encodeURIComponent( taskId, )}/eventstream`; @@ -240,7 +244,12 @@ export class ScaffolderClient implements ScaffolderApi { } }; - const eventSource = new EventSource(url, { withCredentials: true }); + const eventSource = new EventSourcePolyfill(url, { + withCredentials: true, + headers: credentials?.token + ? { Authorization: `Bearer ${credentials.token}` } + : {}, + }); eventSource.addEventListener('log', processEvent); eventSource.addEventListener('cancelled', processEvent); eventSource.addEventListener('completion', (event: any) => { diff --git a/plugins/search-backend-module-catalog/CHANGELOG.md b/plugins/search-backend-module-catalog/CHANGELOG.md index bf64047538..6702760fb6 100644 --- a/plugins/search-backend-module-catalog/CHANGELOG.md +++ b/plugins/search-backend-module-catalog/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-search-backend-module-catalog +## 0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-backend-node@1.2.2-next.0 + - @backstage/plugin-search-common@1.2.3 + +## 0.1.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-search-backend-node@1.2.1 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-common@1.2.3 + ## 0.1.1-next.1 ### Patch Changes diff --git a/plugins/search-backend-module-catalog/package.json b/plugins/search-backend-module-catalog/package.json index 15421990e2..ea6fe7ddba 100644 --- a/plugins/search-backend-module-catalog/package.json +++ b/plugins/search-backend-module-catalog/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-catalog", "description": "A module for the search backend that exports catalog modules", - "version": "0.1.1-next.1", + "version": "0.1.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-elasticsearch/CHANGELOG.md b/plugins/search-backend-module-elasticsearch/CHANGELOG.md index f5c5d9acd5..bc0547ac6d 100644 --- a/plugins/search-backend-module-elasticsearch/CHANGELOG.md +++ b/plugins/search-backend-module-elasticsearch/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-search-backend-module-elasticsearch +## 1.3.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration-aws-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/plugin-search-backend-node@1.2.2-next.0 + - @backstage/plugin-search-common@1.2.3 + +## 1.3.0 + +### Minor Changes + +- 3d72bdb41c7: Upgrade to aws-sdk v3 and include OpenSearch Serverless support + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration-aws-node@0.1.3 + - @backstage/plugin-search-backend-node@1.2.1 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/plugin-search-common@1.2.3 + +## 1.3.0-next.2 + +### Minor Changes + +- 3d72bdb41c7: Upgrade to aws-sdk v3 and include OpenSearch Serverless support + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/integration-aws-node@0.1.2 + ## 1.2.1-next.1 ### Patch Changes diff --git a/plugins/search-backend-module-elasticsearch/api-report.md b/plugins/search-backend-module-elasticsearch/api-report.md index c7add1e8cb..b567414b22 100644 --- a/plugins/search-backend-module-elasticsearch/api-report.md +++ b/plugins/search-backend-module-elasticsearch/api-report.md @@ -8,8 +8,8 @@ import { ApiResponse } from '@opensearch-project/opensearch'; import { ApiResponse as ApiResponse_2 } from '@elastic/elasticsearch'; import { BatchSearchEngineIndexer } from '@backstage/plugin-search-backend-node'; -import { BulkHelper } from '@opensearch-project/opensearch/lib/Helpers'; -import { BulkStats } from '@opensearch-project/opensearch/lib/Helpers'; +import { BulkHelper } from '@elastic/elasticsearch/lib/Helpers'; +import { BulkStats } from '@elastic/elasticsearch/lib/Helpers'; import { Config } from '@backstage/config'; import type { ConnectionOptions } from 'tls'; import { IndexableDocument } from '@backstage/plugin-search-common'; @@ -424,6 +424,10 @@ export interface OpenSearchElasticSearchClientOptions nodes?: string | string[] | OpenSearchNodeOptions | OpenSearchNodeOptions[]; // (undocumented) provider?: 'aws' | 'opensearch'; + // (undocumented) + region?: string; + // (undocumented) + service?: 'es' | 'aoss'; } // @public (undocumented) diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index 73c3a5d7dc..eb95891e3b 100644 --- a/plugins/search-backend-module-elasticsearch/package.json +++ b/plugins/search-backend-module-elasticsearch/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-elasticsearch", "description": "A module for the search backend that implements search using ElasticSearch", - "version": "1.2.1-next.1", + "version": "1.3.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -39,12 +39,12 @@ "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", + "@backstage/integration-aws-node": "workspace:^", "@backstage/plugin-search-backend-node": "workspace:^", "@backstage/plugin-search-common": "workspace:^", "@elastic/elasticsearch": "^7.13.0", - "@opensearch-project/opensearch": "^2.0.0", - "aws-os-connection": "^0.2.0", - "aws-sdk": "^2.948.0", + "@opensearch-project/opensearch": "^2.2.1", + "aws4": "^1.12.0", "elastic-builder": "^2.16.0", "lodash": "^4.17.21", "uuid": "^8.3.2", diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientOptions.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientOptions.ts index 8cb2f67fce..2974f03331 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientOptions.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientOptions.ts @@ -51,6 +51,8 @@ export type ElasticSearchClientOptions = export interface OpenSearchElasticSearchClientOptions extends BaseElasticSearchClientOptions { provider?: 'aws' | 'opensearch'; + region?: string; + service?: 'es' | 'aoss'; auth?: OpenSearchAuth; connection?: OpenSearchConnectionConstructor; node?: string | string[] | OpenSearchNodeOptions | OpenSearchNodeOptions[]; diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientWrapper.test.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientWrapper.test.ts index 7355daf3b9..75f2e36b2b 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientWrapper.test.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientWrapper.test.ts @@ -14,17 +14,13 @@ * limitations under the License. */ -import { ConfigReader } from '@backstage/config'; import { Client as ElasticSearchClient } from '@elastic/elasticsearch'; import { Client as OpenSearchClient } from '@opensearch-project/opensearch'; import Mock from '@short.io/opensearch-mock'; import { Readable } from 'stream'; import { ElasticSearchClientWrapper } from './ElasticSearchClientWrapper'; -import { - createElasticSearchClientOptions, - ElasticSearchClientOptions, -} from './ElasticSearchSearchEngine'; +import { ElasticSearchClientOptions } from './ElasticSearchSearchEngine'; jest.mock('@elastic/elasticsearch', () => ({ ...jest.requireActual('@elastic/elasticsearch'), @@ -103,11 +99,9 @@ describe('ElasticSearchClientWrapper', () => { let esOptions: ElasticSearchClientOptions; beforeEach(async () => { - esOptions = await createElasticSearchClientOptions( - new ConfigReader({ - node: 'http://localhost:9200', - }), - ); + esOptions = { + node: 'http://localhost:9200', + }; jest.clearAllMocks(); }); @@ -229,6 +223,7 @@ describe('ElasticSearchClientWrapper', () => { osOptions = { provider: 'aws', node: 'https://my-es-cluster.eu-west-1.es.amazonaws.com', + region: 'eu-west-1', // todo(backstage/techdocs-core): Remove the following ts-ignore when // @short.io/opensearch-mock is updated to work w/opensearch >= 2.0.0 // @ts-ignore diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts index 3294ca9d33..90f6f407d9 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts @@ -21,9 +21,10 @@ import { SearchEngine, SearchQuery, } from '@backstage/plugin-search-common'; -import { awsGetCredentials, createAWSConnection } from 'aws-os-connection'; import { isEmpty, isNumber, isNaN as nan } from 'lodash'; +import { AwsSigv4Signer } from '@opensearch-project/opensearch/aws'; +import { RequestSigner } from 'aws4'; import { Config } from '@backstage/config'; import { ElasticSearchClientOptions } from './ElasticSearchClientOptions'; import { ElasticSearchClientWrapper } from './ElasticSearchClientWrapper'; @@ -33,6 +34,10 @@ import { Logger } from 'winston'; import { MissingIndexError } from '@backstage/plugin-search-backend-node'; import esb from 'elastic-builder'; import { v4 as uuid } from 'uuid'; +import { + AwsCredentialProvider, + DefaultAwsCredentialsManager, +} from '@backstage/integration-aws-node'; export type { ElasticSearchClientOptions }; @@ -145,8 +150,9 @@ export class ElasticSearchSearchEngine implements SearchEngine { aliasPostfix = `search`, indexPrefix = ``, } = options; - - const clientOptions = await createElasticSearchClientOptions( + const credentialProvider = DefaultAwsCredentialsManager.fromConfig(config); + const clientOptions = await this.createElasticSearchClientOptions( + await credentialProvider?.getCredentialProvider(), config.getConfig('search.elasticsearch'), ); if (clientOptions.provider === 'elastic') { @@ -412,6 +418,106 @@ export class ElasticSearchSearchEngine implements SearchEngine { const postFix = this.aliasPostfix ? `__${this.aliasPostfix}` : ''; return `${this.indexPrefix}${type}${postFix}`; } + + private static async createElasticSearchClientOptions( + credentialProvider: AwsCredentialProvider, + config?: Config, + ): Promise { + if (!config) { + throw new Error('No elastic search config found'); + } + const clientOptionsConfig = config.getOptionalConfig('clientOptions'); + const sslConfig = clientOptionsConfig?.getOptionalConfig('ssl'); + + if (config.getOptionalString('provider') === 'elastic') { + const authConfig = config.getConfig('auth'); + return { + provider: 'elastic', + cloud: { + id: config.getString('cloudId'), + }, + auth: { + username: authConfig.getString('username'), + password: authConfig.getString('password'), + }, + ...(sslConfig + ? { + ssl: { + rejectUnauthorized: + sslConfig?.getOptionalBoolean('rejectUnauthorized'), + }, + } + : {}), + }; + } + if (config.getOptionalString('provider') === 'aws') { + const requestSigner = new RequestSigner(config.getString('node')); + const service = + config.getOptionalString('service') ?? requestSigner.service; + if (service !== 'es' && service !== 'aoss') + throw new Error(`Unrecognized serivce type: ${service}`); + return { + provider: 'aws', + node: config.getString('node'), + ...(sslConfig + ? { + ssl: { + rejectUnauthorized: + sslConfig?.getOptionalBoolean('rejectUnauthorized'), + }, + } + : {}), + ...AwsSigv4Signer({ + region: config.getOptionalString('region') ?? requestSigner.region, // for backwards compatibility + service: service, + getCredentials: async () => + await credentialProvider.sdkCredentialProvider(), + }), + }; + } + if (config.getOptionalString('provider') === 'opensearch') { + const authConfig = config.getConfig('auth'); + return { + provider: 'opensearch', + node: config.getString('node'), + auth: { + username: authConfig.getString('username'), + password: authConfig.getString('password'), + }, + ...(sslConfig + ? { + ssl: { + rejectUnauthorized: + sslConfig?.getOptionalBoolean('rejectUnauthorized'), + }, + } + : {}), + }; + } + const authConfig = config.getOptionalConfig('auth'); + const auth = + authConfig && + (authConfig.has('apiKey') + ? { + apiKey: authConfig.getString('apiKey'), + } + : { + username: authConfig.getString('username'), + password: authConfig.getString('password'), + }); + return { + node: config.getString('node'), + auth, + ...(sslConfig + ? { + ssl: { + rejectUnauthorized: + sslConfig?.getOptionalBoolean('rejectUnauthorized'), + }, + } + : {}), + }; + } } /** @@ -430,97 +536,3 @@ export function decodePageCursor(pageCursor?: string): { page: number } { export function encodePageCursor({ page }: { page: number }): string { return Buffer.from(`${page}`, 'utf-8').toString('base64'); } - -export async function createElasticSearchClientOptions( - config?: Config, -): Promise { - if (!config) { - throw new Error('No elastic search config found'); - } - const clientOptionsConfig = config.getOptionalConfig('clientOptions'); - const sslConfig = clientOptionsConfig?.getOptionalConfig('ssl'); - - if (config.getOptionalString('provider') === 'elastic') { - const authConfig = config.getConfig('auth'); - return { - provider: 'elastic', - cloud: { - id: config.getString('cloudId'), - }, - auth: { - username: authConfig.getString('username'), - password: authConfig.getString('password'), - }, - ...(sslConfig - ? { - ssl: { - rejectUnauthorized: - sslConfig?.getOptionalBoolean('rejectUnauthorized'), - }, - } - : {}), - }; - } - if (config.getOptionalString('provider') === 'aws') { - const awsCredentials = await awsGetCredentials(); - const AWSConnection = createAWSConnection(awsCredentials); - return { - provider: 'aws', - // todo(backstage/techdocs-core): Remove the following ts-ignore when - // aws-os-connection is updated to work with opensearch >= 2.0.0 - // @ts-ignore - node: config.getString('node'), - ...AWSConnection, - ...(sslConfig - ? { - ssl: { - rejectUnauthorized: - sslConfig?.getOptionalBoolean('rejectUnauthorized'), - }, - } - : {}), - }; - } - if (config.getOptionalString('provider') === 'opensearch') { - const authConfig = config.getConfig('auth'); - return { - provider: 'opensearch', - node: config.getString('node'), - auth: { - username: authConfig.getString('username'), - password: authConfig.getString('password'), - }, - ...(sslConfig - ? { - ssl: { - rejectUnauthorized: - sslConfig?.getOptionalBoolean('rejectUnauthorized'), - }, - } - : {}), - }; - } - const authConfig = config.getOptionalConfig('auth'); - const auth = - authConfig && - (authConfig.has('apiKey') - ? { - apiKey: authConfig.getString('apiKey'), - } - : { - username: authConfig.getString('username'), - password: authConfig.getString('password'), - }); - return { - node: config.getString('node'), - auth, - ...(sslConfig - ? { - ssl: { - rejectUnauthorized: - sslConfig?.getOptionalBoolean('rejectUnauthorized'), - }, - } - : {}), - }; -} diff --git a/plugins/search-backend-module-explore/CHANGELOG.md b/plugins/search-backend-module-explore/CHANGELOG.md index df693832db..8011908809 100644 --- a/plugins/search-backend-module-explore/CHANGELOG.md +++ b/plugins/search-backend-module-explore/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-search-backend-module-explore +## 0.1.2-next.0 + +### Patch Changes + +- a5baeea2cb87: Allows for an optional `tokenManager` to authenticate requests from the collator to the explore backend. For example: + + ```diff + indexBuilder.addCollator({ + schedule: every10MinutesSchedule, + factory: ToolDocumentCollatorFactory.fromConfig(env.config, { + discovery: env.discovery, + logger: env.logger, + + tokenManager: env.tokenManager, + }), + }); + ``` + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-backend-node@1.2.2-next.0 + - @backstage/plugin-search-common@1.2.3 + +## 0.1.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-search-backend-node@1.2.1 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.3 + ## 0.1.1-next.1 ### Patch Changes diff --git a/plugins/search-backend-module-explore/README.md b/plugins/search-backend-module-explore/README.md index a87f2d78f9..e775cf42b6 100644 --- a/plugins/search-backend-module-explore/README.md +++ b/plugins/search-backend-module-explore/README.md @@ -39,3 +39,18 @@ backend.add(searchPlugin()); backend.add(searchModuleExploreCollator({ schedule })); backend.start(); ``` + +### Using Auth Middleware + +If your Backstage instance uses service-to-service authentication you can pass an optional `tokenManager` to the collator factory. This will ensure that the collator makes authenticated requests to the explore backend. + +```tsx +indexBuilder.addCollator({ + schedule: every10MinutesSchedule, + factory: ToolDocumentCollatorFactory.fromConfig(env.config, { + discovery: env.discovery, + logger: env.logger, + tokenManager: env.tokenManager, + }), +}); +``` diff --git a/plugins/search-backend-module-explore/api-report.md b/plugins/search-backend-module-explore/api-report.md index 80e8c0c06b..50cda184a9 100644 --- a/plugins/search-backend-module-explore/api-report.md +++ b/plugins/search-backend-module-explore/api-report.md @@ -12,6 +12,7 @@ import { IndexableDocument } from '@backstage/plugin-search-common'; import { Logger } from 'winston'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { Readable } from 'stream'; +import { TokenManager } from '@backstage/backend-common'; // @public export interface ToolDocument extends IndexableDocument, ExploreTool {} @@ -35,5 +36,6 @@ export class ToolDocumentCollatorFactory implements DocumentCollatorFactory { export type ToolDocumentCollatorFactoryOptions = { discovery: PluginEndpointDiscovery; logger: Logger; + tokenManager?: TokenManager; }; ``` diff --git a/plugins/search-backend-module-explore/package.json b/plugins/search-backend-module-explore/package.json index 00f63ef41e..34a03d26fc 100644 --- a/plugins/search-backend-module-explore/package.json +++ b/plugins/search-backend-module-explore/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-explore", "description": "A module for the search backend that exports explore modules", - "version": "0.1.1-next.1", + "version": "0.1.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-explore/src/collators/ToolDocumentCollatorFactory.ts b/plugins/search-backend-module-explore/src/collators/ToolDocumentCollatorFactory.ts index dd9872acec..bf6f07839b 100644 --- a/plugins/search-backend-module-explore/src/collators/ToolDocumentCollatorFactory.ts +++ b/plugins/search-backend-module-explore/src/collators/ToolDocumentCollatorFactory.ts @@ -14,7 +14,10 @@ * limitations under the License. */ -import { PluginEndpointDiscovery } from '@backstage/backend-common'; +import { + PluginEndpointDiscovery, + TokenManager, +} from '@backstage/backend-common'; import { Config } from '@backstage/config'; import { ExploreTool } from '@backstage/plugin-explore-common'; import { @@ -40,6 +43,7 @@ export interface ToolDocument extends IndexableDocument, ExploreTool {} export type ToolDocumentCollatorFactoryOptions = { discovery: PluginEndpointDiscovery; logger: Logger; + tokenManager?: TokenManager; }; /** @@ -52,10 +56,12 @@ export class ToolDocumentCollatorFactory implements DocumentCollatorFactory { private readonly discovery: PluginEndpointDiscovery; private readonly logger: Logger; + private readonly tokenManager?: TokenManager; private constructor(options: ToolDocumentCollatorFactoryOptions) { this.discovery = options.discovery; this.logger = options.logger; + this.tokenManager = options.tokenManager; } static fromConfig( @@ -87,7 +93,17 @@ export class ToolDocumentCollatorFactory implements DocumentCollatorFactory { private async fetchTools() { const baseUrl = await this.discovery.getBaseUrl('explore'); - const response = await fetch(`${baseUrl}/tools`); + + let headers = {}; + + if (this.tokenManager) { + const { token } = await this.tokenManager.getToken(); + headers = { + Authorization: `Bearer ${token}`, + }; + } + + const response = await fetch(`${baseUrl}/tools`, headers); if (!response.ok) { throw new Error( diff --git a/plugins/search-backend-module-pg/CHANGELOG.md b/plugins/search-backend-module-pg/CHANGELOG.md index 9b9ddfa0ff..09f5c9a688 100644 --- a/plugins/search-backend-module-pg/CHANGELOG.md +++ b/plugins/search-backend-module-pg/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-search-backend-module-pg +## 0.5.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/plugin-search-backend-node@1.2.2-next.0 + - @backstage/plugin-search-common@1.2.3 + +## 0.5.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-search-backend-node@1.2.1 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/plugin-search-common@1.2.3 + ## 0.5.6-next.1 ### Patch Changes diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index 5d63d913e0..1f3d82f30c 100644 --- a/plugins/search-backend-module-pg/package.json +++ b/plugins/search-backend-module-pg/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-pg", "description": "A module for the search backend that implements search using PostgreSQL", - "version": "0.5.6-next.1", + "version": "0.5.7-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.test.ts b/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.test.ts index 2f99a02521..c5dbb74da1 100644 --- a/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.test.ts +++ b/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.test.ts @@ -453,6 +453,18 @@ describe('DatabaseDocumentStore', () => { text: 'Around the world', location: 'LOCATION-1', }, + { + title: 'Sed ut perspiciatis', + text: 'Hello World', + myField: ['that', 'not'], + location: 'LOCATION-1', + } as unknown as IndexableDocument, + { + title: 'Consectetur adipiscing', + text: 'Hello World', + myField: ['that', 'not', 'where'], + location: 'LOCATION-1', + } as unknown as IndexableDocument, ]); await store.completeInsert(tx, 'my-type'); }); @@ -488,6 +500,26 @@ describe('DatabaseDocumentStore', () => { rank: expect.any(Number), type: 'my-type', }, + { + document: { + location: 'LOCATION-1', + text: 'Hello World', + title: 'Sed ut perspiciatis', + myField: ['that', 'not'], + }, + rank: expect.any(Number), + type: 'my-type', + }, + { + document: { + location: 'LOCATION-1', + text: 'Hello World', + title: 'Consectetur adipiscing', + myField: ['that', 'not', 'where'], + }, + rank: expect.any(Number), + type: 'my-type', + }, ]); }, ); diff --git a/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.ts b/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.ts index 023992a335..719cc1c755 100644 --- a/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.ts +++ b/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.ts @@ -171,9 +171,13 @@ export class DatabaseDocumentStore implements DatabaseStore { Object.keys(fields).forEach(key => { const value = fields[key]; const valueArray = Array.isArray(value) ? value : [value]; - const valueCompare = valueArray + const fieldValueCompare = valueArray .map(v => ({ [key]: v })) .map(v => JSON.stringify(v)); + const arrayValueCompare = valueArray + .map(v => ({ [key]: [v] })) + .map(v => JSON.stringify(v)); + const valueCompare = [...fieldValueCompare, ...arrayValueCompare]; query.whereRaw( `(${valueCompare.map(() => 'document @> ?').join(' OR ')})`, valueCompare, diff --git a/plugins/search-backend-module-techdocs/CHANGELOG.md b/plugins/search-backend-module-techdocs/CHANGELOG.md index 83eed95d8e..80b8580d04 100644 --- a/plugins/search-backend-module-techdocs/CHANGELOG.md +++ b/plugins/search-backend-module-techdocs/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-search-backend-module-techdocs +## 0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-backend-node@1.2.2-next.0 + - @backstage/plugin-search-common@1.2.3 + - @backstage/plugin-techdocs-node@1.7.2-next.0 + +## 0.1.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-techdocs-node@1.7.1 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-search-backend-node@1.2.1 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-common@1.2.3 + ## 0.1.1-next.1 ### Patch Changes diff --git a/plugins/search-backend-module-techdocs/package.json b/plugins/search-backend-module-techdocs/package.json index f7d7151aeb..274dfb601d 100644 --- a/plugins/search-backend-module-techdocs/package.json +++ b/plugins/search-backend-module-techdocs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-techdocs", "description": "A module for the search backend that exports techdocs modules", - "version": "0.1.1-next.1", + "version": "0.1.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-node/CHANGELOG.md b/plugins/search-backend-node/CHANGELOG.md index 00a828f132..a58afbca32 100644 --- a/plugins/search-backend-node/CHANGELOG.md +++ b/plugins/search-backend-node/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-search-backend-node +## 1.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-common@1.2.3 + +## 1.2.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-common@1.2.3 + ## 1.2.1-next.1 ### Patch Changes diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index 9d7b0b0210..b5ffe939c3 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-node", "description": "A library for Backstage backend plugins that want to interact with the search backend plugin", - "version": "1.2.1-next.1", + "version": "1.2.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend/CHANGELOG.md b/plugins/search-backend/CHANGELOG.md index 321fdefbc1..08795a7eba 100644 --- a/plugins/search-backend/CHANGELOG.md +++ b/plugins/search-backend/CHANGELOG.md @@ -1,5 +1,46 @@ # @backstage/plugin-search-backend +## 1.3.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.15-next.0 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-permission-node@0.7.9-next.0 + - @backstage/plugin-search-backend-node@1.2.2-next.0 + - @backstage/plugin-search-common@1.2.3 + +## 1.3.1 + +### Patch Changes + +- 021cfbb5152: Added an OpenAPI 3.0 spec and enforced schema-first model on the router. +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-permission-node@0.7.8 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/plugin-search-backend-node@1.2.1 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-common@1.2.3 + +## 1.3.1-next.2 + +### Patch Changes + +- 021cfbb5152: Added an OpenAPI 3.0 spec and enforced schema-first model on the router. +- Updated dependencies + - @backstage/config@1.0.7 + ## 1.3.1-next.1 ### Patch Changes diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index d3648c33bf..b927672b30 100644 --- a/plugins/search-backend/package.json +++ b/plugins/search-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend", "description": "The Backstage backend plugin that provides your backstage app with search", - "version": "1.3.1-next.1", + "version": "1.3.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-react/CHANGELOG.md b/plugins/search-react/CHANGELOG.md index 569e66eaba..88653b40e2 100644 --- a/plugins/search-react/CHANGELOG.md +++ b/plugins/search-react/CHANGELOG.md @@ -1,5 +1,55 @@ # @backstage/plugin-search-react +## 1.6.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.4 + - @backstage/plugin-search-common@1.2.3 + +## 1.6.0 + +### Minor Changes + +- 750e45539ad: Add close button & improve search input. + + MUI's Paper wrapping the SearchBar in the SearchPage was removed, we recommend users update their apps accordingly. + + SearchBarBase's TextField's label support added & aria-label uses label string if present, tests relying on the default placeholder value should still work unless custom placeholder was given. + +- 1ce7f84b2e8: accepts InputProp property that can override keys from default + +### Patch Changes + +- f785f0804cd: `SearchPagination` now automatically resets the page cursor when the page limit is changed +- adb31096bc2: Fix text-overflow UI issue for Lifecycle spans in SearchFilter checkbox labels. +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.4 + - @backstage/plugin-search-common@1.2.3 + +## 1.6.0-next.2 + +### Minor Changes + +- 1ce7f84b2e8: accepts InputProp property that can override keys from default + +### Patch Changes + +- adb31096bc2: Fix text-overflow UI issue for Lifecycle spans in SearchFilter checkbox labels. +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 1.6.0-next.1 ### Patch Changes diff --git a/plugins/search-react/api-report.md b/plugins/search-react/api-report.md index e39e91de72..8afde8c4a5 100644 --- a/plugins/search-react/api-report.md +++ b/plugins/search-react/api-report.md @@ -260,7 +260,7 @@ export type SearchPaginationLimitText = (params: { export type SearchPaginationProps = Omit< SearchPaginationBaseProps, | 'pageLimit' - | 'onPageLimitChange' + | 'onLimitChange' | 'pageCursor' | 'onPageCursorChange' | 'hasNextPage' diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index 2467c60b09..510fe3c741 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-react", - "version": "1.6.0-next.1", + "version": "1.6.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-react/src/components/SearchAutocomplete/SearchAutocomplete.stories.tsx b/plugins/search-react/src/components/SearchAutocomplete/SearchAutocomplete.stories.tsx index a43b6b048e..6db7955ec8 100644 --- a/plugins/search-react/src/components/SearchAutocomplete/SearchAutocomplete.stories.tsx +++ b/plugins/search-react/src/components/SearchAutocomplete/SearchAutocomplete.stories.tsx @@ -16,7 +16,7 @@ import React, { ComponentType } from 'react'; -import { Grid, makeStyles, Paper } from '@material-ui/core'; +import { Grid } from '@material-ui/core'; import LabelIcon from '@material-ui/icons/Label'; import { TestApiProvider } from '@backstage/test-utils'; @@ -45,51 +45,24 @@ export default { ], }; -const useStyles = makeStyles(theme => ({ - root: { - padding: theme.spacing(1), - }, -})); - export const Default = () => { - const classes = useStyles(); - return ( - - - - ); + return ; }; export const Outlined = () => { - const classes = useStyles(); - return ( - - - - ); + return ; }; export const Initialized = () => { - const classes = useStyles(); const options = ['hello-word', 'petstore', 'spotify']; - return ( - - - - ); + return ; }; export const LoadingOptions = () => { - const classes = useStyles(); - return ( - - - - ); + return ; }; export const RenderingCustomOptions = () => { - const classes = useStyles(); const options = [ { title: 'hello-world', @@ -106,17 +79,15 @@ export const RenderingCustomOptions = () => { ]; return ( - - ( - } - primaryText={option.title} - secondaryText={option.text} - /> - )} - /> - + ( + } + primaryText={option.title} + secondaryText={option.text} + /> + )} + /> ); }; diff --git a/plugins/search-react/src/components/SearchAutocomplete/SearchAutocomplete.tsx b/plugins/search-react/src/components/SearchAutocomplete/SearchAutocomplete.tsx index 8a5ae7a3ce..2a3cb6bee4 100644 --- a/plugins/search-react/src/components/SearchAutocomplete/SearchAutocomplete.tsx +++ b/plugins/search-react/src/components/SearchAutocomplete/SearchAutocomplete.tsx @@ -16,7 +16,7 @@ import React, { ChangeEvent, useCallback, useMemo } from 'react'; -import { CircularProgress } from '@material-ui/core'; +import { CircularProgress, makeStyles } from '@material-ui/core'; import { Autocomplete, AutocompleteProps, @@ -28,6 +28,13 @@ import { import { SearchContextProvider, useSearch } from '../../context'; import { SearchBar, SearchBarProps } from '../SearchBar'; +const useStyles = makeStyles(theme => ({ + loading: { + right: theme.spacing(1), + position: 'absolute', + }, +})); + /** * Props for {@link SearchAutocomplete}. * @@ -61,6 +68,18 @@ const withContext = ( ); }; +const SearchAutocompleteLoadingAdornment = () => { + const classes = useStyles(); + return ( + + ); +}; + /** * Recommended search autocomplete when you use the Search Provider or Search Context. * @@ -116,7 +135,7 @@ export const SearchAutocomplete = withContext( const renderInput = useCallback( ({ - InputProps: { ref, endAdornment }, + InputProps: { ref, className, endAdornment }, InputLabelProps, ...params }: AutocompleteRenderInputParams) => ( @@ -128,16 +147,9 @@ export const SearchAutocomplete = withContext( placeholder={inputPlaceholder} debounceTime={inputDebounceTime} endAdornment={ - loading ? ( - - ) : ( - endAdornment - ) + loading ? : endAdornment } + InputProps={{ className }} /> ), [loading, inputValue, inputPlaceholder, inputDebounceTime], diff --git a/plugins/search-react/src/components/SearchBar/SearchBar.stories.tsx b/plugins/search-react/src/components/SearchBar/SearchBar.stories.tsx index 559ae1776e..05a46d11e1 100644 --- a/plugins/search-react/src/components/SearchBar/SearchBar.stories.tsx +++ b/plugins/search-react/src/components/SearchBar/SearchBar.stories.tsx @@ -15,7 +15,7 @@ */ import React, { ComponentType } from 'react'; -import { Grid, makeStyles, Paper } from '@material-ui/core'; +import { Grid, makeStyles } from '@material-ui/core'; import { TestApiProvider } from '@backstage/test-utils'; @@ -43,62 +43,51 @@ export default { }; export const Default = () => { - return ( - - - - ); + return ; }; export const CustomPlaceholder = () => { - return ( - - - - ); + return ; }; export const CustomLabel = () => { - return ( - - - - ); + return ; }; export const Focused = () => { return ( - - {/* decision up to adopter, read https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-autofocus.md#no-autofocus */} - {/* eslint-disable-next-line jsx-a11y/no-autofocus */} - - + // decision up to adopter, read https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-autofocus.md#no-autofocus + // eslint-disable-next-line jsx-a11y/no-autofocus + ); }; export const WithoutClearButton = () => { - return ( - - - - ); + return ; }; -const useStyles = makeStyles({ - search: { - display: 'flex', - justifyContent: 'space-between', +const useStyles = makeStyles(theme => ({ + searchBarRoot: { padding: '8px 16px', + background: theme.palette.background.paper, + boxShadow: theme.shadows[1], borderRadius: '50px', - margin: 'auto', }, -}); + searchBarOutline: { + borderStyle: 'none', + }, +})); export const CustomStyles = () => { const classes = useStyles(); return ( - - - + ); }; diff --git a/plugins/search-react/src/components/SearchBar/SearchBar.tsx b/plugins/search-react/src/components/SearchBar/SearchBar.tsx index 913f515aaa..cfd0538694 100644 --- a/plugins/search-react/src/components/SearchBar/SearchBar.tsx +++ b/plugins/search-react/src/components/SearchBar/SearchBar.tsx @@ -80,7 +80,8 @@ export const SearchBarBase: ForwardRefExoticComponent = value: defaultValue, label, placeholder, - inputProps: defaultInputProps = {}, + inputProps = {}, + InputProps = {}, endAdornment, ...rest } = props; @@ -168,10 +169,11 @@ export const SearchBarBase: ForwardRefExoticComponent = endAdornment: clearButton ? clearButtonEndAdornment : endAdornment, + ...InputProps, }} inputProps={{ 'aria-label': ariaLabel, - ...defaultInputProps, + ...inputProps, }} fullWidth={fullWidth} onChange={handleChange} diff --git a/plugins/search-react/src/components/SearchPagination/SearchPagination.test.tsx b/plugins/search-react/src/components/SearchPagination/SearchPagination.test.tsx index d2ecc55d31..65e65d9436 100644 --- a/plugins/search-react/src/components/SearchPagination/SearchPagination.test.tsx +++ b/plugins/search-react/src/components/SearchPagination/SearchPagination.test.tsx @@ -185,4 +185,31 @@ describe('SearchPagination', () => { }), ); }); + + it('Resets page cursor when page limit changes', async () => { + const initialState = { + term: '', + types: [], + filters: {}, + pageCursor: 'Mg==', // page: 2 + }; + + await renderWithEffects( + + + + + , + ); + + await userEvent.click(screen.getByText('25')); // first click to open the options + await userEvent.click(screen.getByText('10')); // second click to select the option + + expect(query).toHaveBeenLastCalledWith( + expect.objectContaining({ + pageCursor: undefined, + pageLimit: 10, + }), + ); + }); }); diff --git a/plugins/search-react/src/components/SearchPagination/SearchPagination.tsx b/plugins/search-react/src/components/SearchPagination/SearchPagination.tsx index 7ab9e8604c..743d3ccb52 100644 --- a/plugins/search-react/src/components/SearchPagination/SearchPagination.tsx +++ b/plugins/search-react/src/components/SearchPagination/SearchPagination.tsx @@ -176,7 +176,7 @@ export const SearchPaginationBase = (props: SearchPaginationBaseProps) => { export type SearchPaginationProps = Omit< SearchPaginationBaseProps, | 'pageLimit' - | 'onPageLimitChange' + | 'onLimitChange' | 'pageCursor' | 'onPageCursorChange' | 'hasNextPage' @@ -191,12 +191,20 @@ export const SearchPagination = (props: SearchPaginationProps) => { const { pageLimit, setPageLimit, pageCursor, setPageCursor, fetchNextPage } = useSearch(); + const handlePageLimitChange = useCallback( + (newPageLimit: number) => { + setPageLimit(newPageLimit); + setPageCursor(undefined); + }, + [setPageLimit, setPageCursor], + ); + return ( diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index c5209d2859..5127ca04eb 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,60 @@ # @backstage/plugin-search +## 1.3.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-search-react@1.6.1-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.4 + - @backstage/plugin-search-common@1.2.3 + +## 1.3.0 + +### Minor Changes + +- 750e45539ad: Add close button & improve search input. + + MUI's Paper wrapping the SearchBar in the SearchPage was removed, we recommend users update their apps accordingly. + + SearchBarBase's TextField's label support added & aria-label uses label string if present, tests relying on the default placeholder value should still work unless custom placeholder was given. + +### Patch Changes + +- 0e3d8d69318: Fixed 404 Error when fetching search results due to URL encoding changes +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/plugin-search-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.4 + - @backstage/plugin-search-common@1.2.3 + +## 1.3.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-search-react@1.6.0-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + ## 1.3.0-next.1 ### Patch Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index eccd5a8304..0a9b455ef9 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search", "description": "The Backstage plugin that provides your backstage app with search", - "version": "1.3.0-next.1", + "version": "1.3.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search/src/components/HomePageComponent/HomePageSearchBar.stories.tsx b/plugins/search/src/components/HomePageComponent/HomePageSearchBar.stories.tsx index 4c20ddec39..9a10aaa41b 100644 --- a/plugins/search/src/components/HomePageComponent/HomePageSearchBar.stories.tsx +++ b/plugins/search/src/components/HomePageComponent/HomePageSearchBar.stories.tsx @@ -61,6 +61,9 @@ const useStyles = makeStyles(theme => ({ borderRadius: '50px', margin: 'auto', }, + searchBarOutline: { + borderStyle: 'none', + }, })); export const CustomStyles = () => { @@ -71,6 +74,7 @@ export const CustomStyles = () => { diff --git a/plugins/search/src/components/HomePageComponent/HomePageSearchBar.tsx b/plugins/search/src/components/HomePageComponent/HomePageSearchBar.tsx index 4246f76ed0..b829bf8ac2 100644 --- a/plugins/search/src/components/HomePageComponent/HomePageSearchBar.tsx +++ b/plugins/search/src/components/HomePageComponent/HomePageSearchBar.tsx @@ -23,10 +23,12 @@ import { import { useNavigateToQuery } from '../util'; const useStyles = makeStyles({ - root: { + searchBarRoot: { + fontSize: '1.5em', + }, + searchBarOutline: { border: '1px solid #555', borderRadius: '6px', - fontSize: '1.5em', }, }); @@ -60,10 +62,17 @@ export const HomePageSearchBar = (props: HomePageSearchBarProps) => { return ( ); diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index 8fd1432c3a..af5bbbefe5 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-sentry +## 0.5.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.5.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.5.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.5.3-next.1 ### Patch Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index e83531f95a..878464bd28 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sentry", "description": "A Backstage plugin that integrates towards Sentry", - "version": "0.5.3-next.1", + "version": "0.5.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/shortcuts/CHANGELOG.md b/plugins/shortcuts/CHANGELOG.md index bbe2b74584..abc1db6df4 100644 --- a/plugins/shortcuts/CHANGELOG.md +++ b/plugins/shortcuts/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-shortcuts +## 0.3.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/types@1.0.2 + +## 0.3.10 + +### Patch Changes + +- 8a7174e297c: Marked `LocalStoredShortcuts` as deprecated, replacing it with `DefaultShortcutsApi` whose naming more clearly suggests that the shortcuts aren't necessarily stored locally (it depends on the storage implementation). +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/types@1.0.2 + +## 0.3.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 0.3.10-next.1 ### Patch Changes diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index 4695c858c3..57b4e87510 100644 --- a/plugins/shortcuts/package.json +++ b/plugins/shortcuts/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-shortcuts", "description": "A Backstage plugin that provides a shortcuts feature to the sidebar", - "version": "0.3.10-next.1", + "version": "0.3.11-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube-backend/CHANGELOG.md b/plugins/sonarqube-backend/CHANGELOG.md index cf90264ece..11741621a3 100644 --- a/plugins/sonarqube-backend/CHANGELOG.md +++ b/plugins/sonarqube-backend/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-sonarqube-backend +## 0.1.11-next.0 + +### Patch Changes + +- 0bb0b19b0da2: Provide full schema definition for sonarqube plugin, especially to protect api keys. +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + +## 0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + ## 0.1.10-next.1 ### Patch Changes diff --git a/plugins/sonarqube-backend/config.d.ts b/plugins/sonarqube-backend/config.d.ts new file mode 100644 index 0000000000..9e612b6984 --- /dev/null +++ b/plugins/sonarqube-backend/config.d.ts @@ -0,0 +1,56 @@ +/* + * Copyright 2020 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. + */ + +export interface Config { + /** Optional configurations for the SonarQube plugin */ + sonarQube?: { + /** + * The base url of the sonarqube installation. Defaults to https://sonarcloud.io. + * @visibility frontend + */ + baseUrl: string; + + /** + * The api key to access the sonarqube instance under baseUrl. + * @visibility secret + */ + apiKey: string; + + /** + * The optional sonarqube instances. + * @visibility frontend + */ + instances?: Array<{ + /** + * The name of the sonarqube instance. + * @visibility frontend + */ + name: string; + + /** + * The base url of the sonarqube instance. + * @visibility frontend + */ + baseUrl: string; + + /** + * The api key to access the sonarqube instance. + * @visibility secret + */ + apiKey: string; + }>; + }; +} diff --git a/plugins/sonarqube-backend/package.json b/plugins/sonarqube-backend/package.json index 9b452471de..3b9c20c507 100644 --- a/plugins/sonarqube-backend/package.json +++ b/plugins/sonarqube-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube-backend", - "version": "0.1.10-next.1", + "version": "0.1.11-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -40,6 +40,8 @@ "supertest": "^6.2.4" }, "files": [ - "dist" - ] + "dist", + "config.d.ts" + ], + "configSchema": "config.d.ts" } diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index 3a599bfd5f..50ec3d3292 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-sonarqube +## 0.6.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/plugin-sonarqube-react@0.1.5 + +## 0.6.7 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-sonarqube-react@0.1.5 + +## 0.6.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.6.7-next.1 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index 566a5cf757..9240ccdb79 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sonarqube", "description": "", - "version": "0.6.7-next.1", + "version": "0.6.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/splunk-on-call/CHANGELOG.md b/plugins/splunk-on-call/CHANGELOG.md index 1fe8e00511..ebba1db039 100644 --- a/plugins/splunk-on-call/CHANGELOG.md +++ b/plugins/splunk-on-call/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-splunk-on-call +## 0.4.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + +## 0.4.7 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.4.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.4.7-next.1 ### Patch Changes diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index 97204eed93..6d52ed6b04 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-splunk-on-call", "description": "A Backstage plugin that integrates towards Splunk On-Call", - "version": "0.4.7-next.1", + "version": "0.4.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/stack-overflow-backend/CHANGELOG.md b/plugins/stack-overflow-backend/CHANGELOG.md index 03006fd490..08c9ad9f27 100644 --- a/plugins/stack-overflow-backend/CHANGELOG.md +++ b/plugins/stack-overflow-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-stack-overflow-backend +## 0.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/plugin-search-common@1.2.3 + +## 0.2.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/config@1.0.7 + - @backstage/plugin-search-common@1.2.3 + ## 0.2.1-next.1 ### Patch Changes diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index fd08b70f52..12a70b9451 100644 --- a/plugins/stack-overflow-backend/package.json +++ b/plugins/stack-overflow-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-stack-overflow-backend", - "version": "0.2.1-next.1", + "version": "0.2.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/stack-overflow/CHANGELOG.md b/plugins/stack-overflow/CHANGELOG.md index 4e70b57ce3..4cb87f8d32 100644 --- a/plugins/stack-overflow/CHANGELOG.md +++ b/plugins/stack-overflow/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-stack-overflow +## 0.1.16-next.0 + +### Patch Changes + +- 41e8037a8a6d: Extract new plugin-home-react package and deprecate createCardExtension in plugin-home +- Updated dependencies + - @backstage/plugin-home-react@0.1.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-search-react@1.6.1-next.0 + - @backstage/plugin-search-common@1.2.3 + +## 0.1.15 + +### Patch Changes + +- c1ff65f315a: StackOverflowSearchResultListItem can now accept an empty result prop so that it can be rendered in the suggested SearchResultListItem pattern. +- Updated dependencies + - @backstage/plugin-home@0.5.2 + - @backstage/theme@0.3.0 + - @backstage/plugin-search-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/plugin-search-common@1.2.3 + +## 0.1.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-home@0.5.2-next.2 + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-search-react@1.6.0-next.2 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.15-next.1 ### Patch Changes diff --git a/plugins/stack-overflow/api-report.md b/plugins/stack-overflow/api-report.md index b006f263ed..3e27318acb 100644 --- a/plugins/stack-overflow/api-report.md +++ b/plugins/stack-overflow/api-report.md @@ -7,7 +7,7 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; -import { CardExtensionProps } from '@backstage/plugin-home'; +import { CardExtensionProps } from '@backstage/plugin-home-react'; import { default as React_2 } from 'react'; import { ResultHighlight } from '@backstage/plugin-search-common'; import { SearchResultListItemExtensionProps } from '@backstage/plugin-search-react'; diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index d30311eb61..06391f42f6 100644 --- a/plugins/stack-overflow/package.json +++ b/plugins/stack-overflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-stack-overflow", - "version": "0.1.15-next.1", + "version": "0.1.16-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -25,7 +25,7 @@ "@backstage/config": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", - "@backstage/plugin-home": "workspace:^", + "@backstage/plugin-home-react": "workspace:^", "@backstage/plugin-search-common": "workspace:^", "@backstage/plugin-search-react": "workspace:^", "@backstage/theme": "workspace:^", diff --git a/plugins/stack-overflow/src/plugin.ts b/plugins/stack-overflow/src/plugin.ts index 5be4c89cbe..017900bc02 100644 --- a/plugins/stack-overflow/src/plugin.ts +++ b/plugins/stack-overflow/src/plugin.ts @@ -20,7 +20,7 @@ import { createApiFactory, configApiRef, } from '@backstage/core-plugin-api'; -import { createCardExtension } from '@backstage/plugin-home'; +import { createCardExtension } from '@backstage/plugin-home-react'; import { StackOverflowQuestionsContentProps } from './types'; import { stackOverflowApiRef, StackOverflowClient } from './api'; import { SearchResultListItemExtensionProps } from '@backstage/plugin-search-react'; diff --git a/plugins/stackstorm/CHANGELOG.md b/plugins/stackstorm/CHANGELOG.md index bf8fedd4c3..1ecb359ca3 100644 --- a/plugins/stackstorm/CHANGELOG.md +++ b/plugins/stackstorm/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-stackstorm +## 0.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.1.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.2-next.0 ### Patch Changes diff --git a/plugins/stackstorm/package.json b/plugins/stackstorm/package.json index c9a9e7fc16..12fb705557 100644 --- a/plugins/stackstorm/package.json +++ b/plugins/stackstorm/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-stackstorm", "description": "A Backstage plugin that integrates towards StackStorm", - "version": "0.1.2-next.0", + "version": "0.1.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md index 864c0cb830..96a029386c 100644 --- a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md +++ b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-tech-insights-backend-module-jsonfc +## 0.1.30-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-tech-insights-common@0.2.10 + - @backstage/plugin-tech-insights-node@0.4.4-next.0 + +## 0.1.29 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-tech-insights-node@0.4.3 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-tech-insights-common@0.2.10 + ## 0.1.29-next.1 ### Patch Changes diff --git a/plugins/tech-insights-backend-module-jsonfc/package.json b/plugins/tech-insights-backend-module-jsonfc/package.json index 489f36e2f8..77a86fe4b9 100644 --- a/plugins/tech-insights-backend-module-jsonfc/package.json +++ b/plugins/tech-insights-backend-module-jsonfc/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-backend-module-jsonfc", - "version": "0.1.29-next.1", + "version": "0.1.30-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-backend/CHANGELOG.md b/plugins/tech-insights-backend/CHANGELOG.md index 1c3b902c3f..801bc4b03c 100644 --- a/plugins/tech-insights-backend/CHANGELOG.md +++ b/plugins/tech-insights-backend/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-tech-insights-backend +## 0.5.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10 + - @backstage/plugin-tech-insights-node@0.4.4-next.0 + +## 0.5.11 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/plugin-tech-insights-node@0.4.3 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10 + ## 0.5.11-next.1 ### Patch Changes diff --git a/plugins/tech-insights-backend/package.json b/plugins/tech-insights-backend/package.json index 09bb9c8d6f..247fa55853 100644 --- a/plugins/tech-insights-backend/package.json +++ b/plugins/tech-insights-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-backend", - "version": "0.5.11-next.1", + "version": "0.5.12-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-node/CHANGELOG.md b/plugins/tech-insights-node/CHANGELOG.md index e5eec67a40..5c9c24d5c7 100644 --- a/plugins/tech-insights-node/CHANGELOG.md +++ b/plugins/tech-insights-node/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-tech-insights-node +## 0.4.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10 + +## 0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/config@1.0.7 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10 + ## 0.4.3-next.1 ### Patch Changes diff --git a/plugins/tech-insights-node/package.json b/plugins/tech-insights-node/package.json index bc5c0816f7..e514fc3449 100644 --- a/plugins/tech-insights-node/package.json +++ b/plugins/tech-insights-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-node", - "version": "0.4.3-next.1", + "version": "0.4.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights/CHANGELOG.md b/plugins/tech-insights/CHANGELOG.md index a59782e2cc..3e15025359 100644 --- a/plugins/tech-insights/CHANGELOG.md +++ b/plugins/tech-insights/CHANGELOG.md @@ -1,5 +1,50 @@ # @backstage/plugin-tech-insights +## 0.3.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10 + +## 0.3.10 + +### Patch Changes + +- 22963209d23: Added the possibility to customize the check description in the scorecard component. + + - The `CheckResultRenderer` type now exposes an optional `description` method that allows to overwrite the description with a different string or a React component for a provided check result. + + Until now only the `BooleanCheck` element could be overridden, but from now on it's also possible to override the description for a check. + As an example, the description could change depending on the check result. Refer to the [README](https://github.com/backstage/backstage/blob/master/plugins/tech-insights/README.md#adding-custom-rendering-components) file for more details + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10 + +## 0.3.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.3.10-next.1 ### Patch Changes diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index e8ead43ad6..8c0bb9ed5f 100644 --- a/plugins/tech-insights/package.json +++ b/plugins/tech-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights", - "version": "0.3.10-next.1", + "version": "0.3.11-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-radar/CHANGELOG.md b/plugins/tech-radar/CHANGELOG.md index c28aa05ea9..c191a05718 100644 --- a/plugins/tech-radar/CHANGELOG.md +++ b/plugins/tech-radar/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-tech-radar +## 0.6.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + +## 0.6.4 + +### Patch Changes + +- be4fa53fab8: Fix description links when clicking entry in radar. +- Added the ability to display a timeline to each entry in the details box +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + +## 0.6.4-next.2 + +### Patch Changes + +- be4fa53fab8: Fix description links when clicking entry in radar. +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 0.6.4-next.1 ### Patch Changes diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 4621f89c87..eed47f142f 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-tech-radar", "description": "A Backstage plugin that lets you display a Tech Radar for your organization", - "version": "0.6.4-next.1", + "version": "0.6.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-radar/src/components/RadarEntry/RadarEntry.tsx b/plugins/tech-radar/src/components/RadarEntry/RadarEntry.tsx index af9e840ead..66940cd1d7 100644 --- a/plugins/tech-radar/src/components/RadarEntry/RadarEntry.tsx +++ b/plugins/tech-radar/src/components/RadarEntry/RadarEntry.tsx @@ -26,6 +26,7 @@ export type Props = { value: number; color: string; url?: string; + links?: Array<{ title: string; url: string }>; moved?: number; description?: string; timeline?: EntrySnapshot[]; @@ -73,6 +74,7 @@ const RadarEntry = (props: Props): JSX.Element => { title, color, url, + links, value, x, y, @@ -112,6 +114,7 @@ const RadarEntry = (props: Props): JSX.Element => { description={description ? description : 'no description'} timeline={timeline ? timeline : []} url={url} + links={links} /> )} {description ? ( diff --git a/plugins/tech-radar/src/components/RadarPlot/RadarPlot.tsx b/plugins/tech-radar/src/components/RadarPlot/RadarPlot.tsx index 957017692b..0fb6e3a36a 100644 --- a/plugins/tech-radar/src/components/RadarPlot/RadarPlot.tsx +++ b/plugins/tech-radar/src/components/RadarPlot/RadarPlot.tsx @@ -73,6 +73,7 @@ const RadarPlot = (props: Props): JSX.Element => { color={entry.color || ''} value={(entry?.index || 0) + 1} url={entry.url} + links={entry.links} description={entry.description} moved={entry.moved} title={entry.title} diff --git a/plugins/techdocs-addons-test-utils/CHANGELOG.md b/plugins/techdocs-addons-test-utils/CHANGELOG.md index cb41a62031..74b1c18695 100644 --- a/plugins/techdocs-addons-test-utils/CHANGELOG.md +++ b/plugins/techdocs-addons-test-utils/CHANGELOG.md @@ -1,5 +1,54 @@ # @backstage/plugin-techdocs-addons-test-utils +## 1.0.14-next.0 + +### Patch Changes + +- 1fd38bc4141a: Avoiding re-running tests on cleanup. +- Updated dependencies + - @backstage/plugin-techdocs@1.6.3-next.0 + - @backstage/test-utils@1.4.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/plugin-techdocs-react@1.1.7-next.0 + - @backstage/plugin-catalog@1.11.1-next.0 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/plugin-search-react@1.6.1-next.0 + +## 1.0.13 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-techdocs@1.6.2 + - @backstage/plugin-catalog@1.11.0 + - @backstage/core-app-api@1.8.0 + - @backstage/plugin-search-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/test-utils@1.3.1 + - @backstage/plugin-techdocs-react@1.1.6 + - @backstage/core-plugin-api@1.5.1 + +## 1.0.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-search-react@1.6.0-next.2 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/test-utils@1.3.1-next.2 + - @backstage/plugin-catalog@1.11.0-next.2 + - @backstage/plugin-techdocs@1.6.2-next.2 + - @backstage/plugin-techdocs-react@1.1.6-next.1 + - @backstage/core-app-api@1.8.0-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 1.0.13-next.1 ### Patch Changes diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index 27ae3ccadd..7788757639 100644 --- a/plugins/techdocs-addons-test-utils/package.json +++ b/plugins/techdocs-addons-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-addons-test-utils", - "version": "1.0.13-next.1", + "version": "1.0.14-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-addons-test-utils/src/test-utils.tsx b/plugins/techdocs-addons-test-utils/src/test-utils.tsx index e60a96402c..1a921437b1 100644 --- a/plugins/techdocs-addons-test-utils/src/test-utils.tsx +++ b/plugins/techdocs-addons-test-utils/src/test-utils.tsx @@ -278,7 +278,7 @@ export class TechDocsAddonTester { render(this.build()); }); - const shadowHost = screen.getByTestId('techdocs-native-shadowroot'); + const shadowHost = await screen.findByTestId('techdocs-native-shadowroot'); return { ...screen, diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index 8df2623fa0..45f9acfc5c 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-techdocs-backend +## 1.6.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.2-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-common@1.2.3 + - @backstage/plugin-techdocs-node@1.7.2-next.0 + +## 1.6.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/plugin-techdocs-node@1.7.1 + - @backstage/plugin-search-backend-module-techdocs@0.1.1 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-catalog-common@1.0.13 + - @backstage/plugin-permission-common@0.7.5 + - @backstage/plugin-search-common@1.2.3 + ## 1.6.2-next.1 ### Patch Changes diff --git a/plugins/techdocs-backend/examples/documented-component-uffizzi/catalog-info.yaml b/plugins/techdocs-backend/examples/documented-component-uffizzi/catalog-info.yaml new file mode 100644 index 0000000000..a4d46593d3 --- /dev/null +++ b/plugins/techdocs-backend/examples/documented-component-uffizzi/catalog-info.yaml @@ -0,0 +1,12 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: documented-component-uffizzi + title: Documented Component (Uffizzi) + description: A Service with TechDocs documentation. Excl. PlantUML extension. + annotations: + backstage.io/techdocs-ref: dir:. +spec: + type: service + lifecycle: experimental + owner: user:guest diff --git a/plugins/techdocs-backend/examples/documented-component-uffizzi/docs/code/code-sample.md b/plugins/techdocs-backend/examples/documented-component-uffizzi/docs/code/code-sample.md new file mode 100644 index 0000000000..f41ab1d506 --- /dev/null +++ b/plugins/techdocs-backend/examples/documented-component-uffizzi/docs/code/code-sample.md @@ -0,0 +1,31 @@ +# Sample Code + +This page provides some sample code which may be used in your example component. + +This code uses TypeScript, and the Markdown code fence to wrap the code. + +```typescript +const serviceEntityPage = ( + + + + + + + + + + + + +); +``` + +Here is an example of Python code: + +```python +def getUsersInGroup(targetGroup, secure=False): + + if __debug__: + print('targetGroup=[' + targetGroup + ']') +``` diff --git a/plugins/techdocs-backend/examples/documented-component-uffizzi/docs/extensions.md b/plugins/techdocs-backend/examples/documented-component-uffizzi/docs/extensions.md new file mode 100644 index 0000000000..2b101efdef --- /dev/null +++ b/plugins/techdocs-backend/examples/documented-component-uffizzi/docs/extensions.md @@ -0,0 +1,99 @@ +# Plugins & Extensions + +Just by including the TechDocs Core Plugin to your MkDocs site included with Backstage, +you gain the immediate use of a variety of popular plugins and extensions to MkDocs. + +For more information and full details of the available features, see the +[`mkdocs-techdocs-core` repository](https://github.com/backstage/mkdocs-techdocs-core#mkdocs-plugins-and-extensions). + +This page provides a demonstration of some of the available features. + +## Admonitions + +Admonitions are call outs that help catch a users attention. + +To define an admonition simply put the following Markdown into your content: + +``` +!!! warn + Defining admonitions can be addicting. +``` + +And they end up looking like this: + + +!!! warn + Defining admonitions can be addicting. + + +!!! note + You can learn a lot about TechDocs by just visiting the Backstage web site at + https://backstage.io/docs. + + +!!! info + TechDocs is the core feature that supports documentation as code in Backstage. + + +!!! tip + Don't forget to spell check your documentation. + +## Pymdownx Extensions + +Pymdownx (Python Markdown extensions) are a variety of smaller additions. + +### Details + + +??? note "What is the answer to life, the universe, and everything? (click me for the answer)" + The answer is 42. + + +??? note "What is 4 plus 4?" + The answer is 8. + + +???+ note "How do I get support?" + You can get support by opening an issue in this repository. This detail is open by default + so it's more easily visible without requiring the user to click to open it. + +### Task Lists + +Automatic rendering of Markdown task lists. + +- [x] Phase 1 +- [x] Phase 2 +- [ ] Phase 3 + +### Emojis + +Very nice job on documentation! :thumbsup: + +I've read a lot of documentation, but I love :heart: this document. + +Weather: :sunny: :umbrella: :cloud: :snowflake: + +Animals: :tiger: :horse: :turtle: :wolf: :frog: + +### Attributes + +[A Download Link](./images/backstage-logo-cncf.svg){: download } + +![A Scaled Image](./images/backstage-logo-cncf.svg){: style="width: 100px" } + +### MDX truly sane lists + +- `attributes` + +- `customer` + - `first_name` + - `test` + - `family_name` + - `email` +- `person` + - `first_name` + - `family_name` + - `birth_date` +- `subscription_id` + +- `request` diff --git a/plugins/techdocs-backend/examples/documented-component-uffizzi/docs/images/backstage-logo-cncf.svg b/plugins/techdocs-backend/examples/documented-component-uffizzi/docs/images/backstage-logo-cncf.svg new file mode 100644 index 0000000000..b5ff591d1b --- /dev/null +++ b/plugins/techdocs-backend/examples/documented-component-uffizzi/docs/images/backstage-logo-cncf.svg @@ -0,0 +1 @@ +05 Logo_Black \ No newline at end of file diff --git a/plugins/techdocs-backend/examples/documented-component-uffizzi/docs/index.md b/plugins/techdocs-backend/examples/documented-component-uffizzi/docs/index.md new file mode 100644 index 0000000000..6295a69406 --- /dev/null +++ b/plugins/techdocs-backend/examples/documented-component-uffizzi/docs/index.md @@ -0,0 +1,55 @@ +# Welcome! + +This is a basic example of documentation. It is intended as a showcase of some of the +features that TechDocs provides out of the box. + +You can see also: + +- [A sub page](sub-page.md) +- [Inline code examples](code/code-sample.md) +- [Plugin & Extension examples](extensions.md) - Diagrams, emojis, visual formatting. + +## Basic Markdown + +Headings: + +# h1 + +## h2 + +### h3 + +#### h4 + +##### h5 + +###### h6 + +Here is a bulleted list: + +- Item one +- Item two +- Item Three + +Check out the [Markdown Guide](https://www.markdownguide.org/) to learn more about how to +simply create documentation. + +You can also learn more about how to configure and setup this documentation in Backstage, +[read up on the TechDocs Overview](https://backstage.io/docs/features/techdocs/). + +## Image Example + +This documentation is powered by Backstage's TechDocs feature: + +![Backstage Logo](images/backstage-logo-cncf.svg) + +## Table Example + +While this documentation isn't comprehensive, in the future it should cover the following +topics outlined in this example table: + +| Topic | Description | +| ------- | ------------------------------------------------------------ | +| Topic 1 | An introductory topic to help you learn about the component. | +| Topic 2 | A more detailed topic that explains more information. | +| Topic 3 | A final topic that provides conclusions and lessons learned. | diff --git a/plugins/techdocs-backend/examples/documented-component-uffizzi/docs/sub-page.md b/plugins/techdocs-backend/examples/documented-component-uffizzi/docs/sub-page.md new file mode 100644 index 0000000000..987f5e8a95 --- /dev/null +++ b/plugins/techdocs-backend/examples/documented-component-uffizzi/docs/sub-page.md @@ -0,0 +1,12 @@ +# Another page in our documentation + +This sub-page can be used to elaborate on a specific part of the component. + +## Details + +It is linked off the main page, and due to its inclusion in the `mkdocs.yml` file, +becomes part of the auto-generated site navigation. + +## MkDocs + +Visit https://www.mkdocs.org for more information about the MkDocs tool. diff --git a/plugins/techdocs-backend/examples/documented-component-uffizzi/mkdocs.yml b/plugins/techdocs-backend/examples/documented-component-uffizzi/mkdocs.yml new file mode 100644 index 0000000000..1a159a4d12 --- /dev/null +++ b/plugins/techdocs-backend/examples/documented-component-uffizzi/mkdocs.yml @@ -0,0 +1,12 @@ +site_name: 'Example Documentation' +repo_url: https://github.com/backstage/backstage +edit_uri: edit/master/plugins/techdocs-backend/examples/documented-component/docs + +nav: + - Home: index.md + - Subpage: sub-page.md + - 'Code Sample': code/code-sample.md + - Extensions: extensions.md + +plugins: + - techdocs-core diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index b90c299621..9b866e6577 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-backend", "description": "The Backstage backend plugin that renders technical documentation for your components", - "version": "1.6.2-next.1", + "version": "1.6.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-module-addons-contrib/CHANGELOG.md b/plugins/techdocs-module-addons-contrib/CHANGELOG.md index 283f08934f..d0079c44a7 100644 --- a/plugins/techdocs-module-addons-contrib/CHANGELOG.md +++ b/plugins/techdocs-module-addons-contrib/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-techdocs-module-addons-contrib +## 1.0.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/plugin-techdocs-react@1.1.7-next.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + +## 1.0.13 + +### Patch Changes + +- 6afc7f052ca: Show cursor pointer when hovering on lightbox +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/integration@1.4.5 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/plugin-techdocs-react@1.1.6 + - @backstage/core-plugin-api@1.5.1 + +## 1.0.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/plugin-techdocs-react@1.1.6-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 1.0.13-next.1 ### Patch Changes diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 763696fbbf..1f3a08f65d 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-module-addons-contrib", "description": "Plugin module for contributed TechDocs Addons", - "version": "1.0.13-next.1", + "version": "1.0.14-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-module-addons-contrib/src/LigthBox/lightbox.css b/plugins/techdocs-module-addons-contrib/src/LigthBox/lightbox.css index 63170792f1..3371d0fa53 100644 --- a/plugins/techdocs-module-addons-contrib/src/LigthBox/lightbox.css +++ b/plugins/techdocs-module-addons-contrib/src/LigthBox/lightbox.css @@ -5,3 +5,7 @@ color: rgba(0, 0, 0, 0.87); text-shadow: none; } + +.pswp__img { + cursor: pointer !important; +} diff --git a/plugins/techdocs-node/CHANGELOG.md b/plugins/techdocs-node/CHANGELOG.md index e3715430c9..387789bdd7 100644 --- a/plugins/techdocs-node/CHANGELOG.md +++ b/plugins/techdocs-node/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-techdocs-node +## 1.7.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/integration-aws-node@0.1.3 + - @backstage/config@1.0.7 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-search-common@1.2.3 + +## 1.7.1 + +### Patch Changes + +- 3659c71c5d9: Standardize `@aws-sdk` v3 versions +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/integration-aws-node@0.1.3 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + - @backstage/plugin-search-common@1.2.3 + ## 1.7.1-next.1 ### Patch Changes diff --git a/plugins/techdocs-node/api-report.md b/plugins/techdocs-node/api-report.md index 2a2fe12946..b7941ac89a 100644 --- a/plugins/techdocs-node/api-report.md +++ b/plugins/techdocs-node/api-report.md @@ -243,7 +243,7 @@ export class TechdocsGenerator implements GeneratorBase { config: Config; scmIntegrations: ScmIntegrationRegistry; }); - static readonly defaultDockerImage = 'spotify/techdocs:v1.2.0'; + static readonly defaultDockerImage = 'spotify/techdocs:v1.2.1'; static fromConfig( config: Config, options: GeneratorOptions, diff --git a/plugins/techdocs-node/package.json b/plugins/techdocs-node/package.json index 2513033dc3..0732727a96 100644 --- a/plugins/techdocs-node/package.json +++ b/plugins/techdocs-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-node", "description": "Common node.js functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", - "version": "1.7.1-next.1", + "version": "1.7.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -39,11 +39,11 @@ "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@aws-sdk/client-s3": "^3.208.0", - "@aws-sdk/credential-providers": "^3.208.0", - "@aws-sdk/lib-storage": "^3.208.0", - "@aws-sdk/node-http-handler": "^3.208.0", - "@aws-sdk/types": "^3.208.0", + "@aws-sdk/client-s3": "^3.310.0", + "@aws-sdk/credential-providers": "^3.310.0", + "@aws-sdk/lib-storage": "^3.310.0", + "@aws-sdk/node-http-handler": "^3.310.0", + "@aws-sdk/types": "^3.310.0", "@azure/identity": "^2.1.0", "@azure/storage-blob": "^12.5.0", "@backstage/backend-common": "workspace:^", diff --git a/plugins/techdocs-node/src/stages/generate/techdocs.ts b/plugins/techdocs-node/src/stages/generate/techdocs.ts index d2ad0021be..06160b85c9 100644 --- a/plugins/techdocs-node/src/stages/generate/techdocs.ts +++ b/plugins/techdocs-node/src/stages/generate/techdocs.ts @@ -53,7 +53,7 @@ export class TechdocsGenerator implements GeneratorBase { * The default docker image (and version) used to generate content. Public * and static so that techdocs-node consumers can use the same version. */ - public static readonly defaultDockerImage = 'spotify/techdocs:v1.2.0'; + public static readonly defaultDockerImage = 'spotify/techdocs:v1.2.1'; private readonly logger: Logger; private readonly containerRunner?: ContainerRunner; private readonly options: GeneratorConfig; diff --git a/plugins/techdocs-react/CHANGELOG.md b/plugins/techdocs-react/CHANGELOG.md index d201805fb5..b40c348806 100644 --- a/plugins/techdocs-react/CHANGELOG.md +++ b/plugins/techdocs-react/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-techdocs-react +## 1.1.7-next.0 + +### Patch Changes + +- 3d11596a72b5: Update plugin installation docs to be more consistent across documentations +- Updated dependencies + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/version-bridge@1.0.4 + +## 1.1.6 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/version-bridge@1.0.4 + +## 1.1.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.1-next.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + ## 1.1.6-next.0 ### Patch Changes diff --git a/plugins/techdocs-react/README.md b/plugins/techdocs-react/README.md index 548ba8be5a..53e9fc6a3a 100644 --- a/plugins/techdocs-react/README.md +++ b/plugins/techdocs-react/README.md @@ -5,5 +5,6 @@ This package provides frontend utilities for TechDocs and Addons. ## Installation ```sh +# From your Backstage root directory yarn add --cwd packages/app @backstage/plugin-techdocs-react ``` diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index 318f8d56de..9e8d10c960 100644 --- a/plugins/techdocs-react/package.json +++ b/plugins/techdocs-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-react", "description": "Shared frontend utilities for TechDocs and Addons", - "version": "1.1.6-next.0", + "version": "1.1.7-next.0", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 31a3653f2e..7cb6fb67c2 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,57 @@ # @backstage/plugin-techdocs +## 1.6.3-next.0 + +### Patch Changes + +- 956d09e8ea68: Change deprecated local references to import from shared `plugin-techdocs-react` plugin +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/plugin-techdocs-react@1.1.7-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/integration-react@1.1.14-next.0 + - @backstage/plugin-search-react@1.6.1-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/plugin-search-common@1.2.3 + +## 1.6.2 + +### Patch Changes + +- 863beb49498: Re-add the possibility to have trailing slashes in Techdocs navigation. +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/integration@1.4.5 + - @backstage/plugin-search-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/integration-react@1.1.13 + - @backstage/plugin-techdocs-react@1.1.6 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/plugin-search-common@1.2.3 + +## 1.6.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-search-react@1.6.0-next.2 + - @backstage/integration-react@1.1.13-next.2 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/plugin-techdocs-react@1.1.6-next.1 + - @backstage/config@1.0.7 + - @backstage/core-plugin-api@1.5.1 + ## 1.6.2-next.1 ### Patch Changes diff --git a/plugins/techdocs/api-report.md b/plugins/techdocs/api-report.md index 6e14c52939..27af44bb13 100644 --- a/plugins/techdocs/api-report.md +++ b/plugins/techdocs/api-report.md @@ -20,11 +20,14 @@ import { ReactNode } from 'react'; import { ResultHighlight } from '@backstage/plugin-search-common'; import { RouteRef } from '@backstage/core-plugin-api'; import { SearchResultListItemExtensionProps } from '@backstage/plugin-search-react'; +import { SyncResult as SyncResult_2 } from '@backstage/plugin-techdocs-react'; import { TableColumn } from '@backstage/core-components'; import { TableOptions } from '@backstage/core-components'; import { TableProps } from '@backstage/core-components'; +import { TechDocsApi as TechDocsApi_2 } from '@backstage/plugin-techdocs-react'; import { TechDocsEntityMetadata as TechDocsEntityMetadata_2 } from '@backstage/plugin-techdocs-react'; import { TechDocsMetadata as TechDocsMetadata_2 } from '@backstage/plugin-techdocs-react'; +import { TechDocsStorageApi as TechDocsStorageApi_2 } from '@backstage/plugin-techdocs-react'; import { ToolbarProps } from '@material-ui/core'; import { UserListFilterKind } from '@backstage/plugin-catalog-react'; @@ -237,7 +240,7 @@ export interface TechDocsApi { export const techdocsApiRef: ApiRef; // @public -export class TechDocsClient implements TechDocsApi { +export class TechDocsClient implements TechDocsApi_2 { constructor(options: { configApi: Config; discoveryApi: DiscoveryApi; @@ -442,7 +445,7 @@ export interface TechDocsStorageApi { export const techdocsStorageApiRef: ApiRef; // @public -export class TechDocsStorageClient implements TechDocsStorageApi { +export class TechDocsStorageClient implements TechDocsStorageApi_2 { constructor(options: { configApi: Config; discoveryApi: DiscoveryApi; @@ -471,6 +474,6 @@ export class TechDocsStorageClient implements TechDocsStorageApi { syncEntityDocs( entityId: CompoundEntityRef, logHandler?: (line: string) => void, - ): Promise; + ): Promise; } ``` diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index d0a6e49d13..7e49ca02ac 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs", "description": "The Backstage plugin that renders technical documentation for your components", - "version": "1.6.2-next.1", + "version": "1.6.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs/src/client.ts b/plugins/techdocs/src/client.ts index 499a56580c..8680e14468 100644 --- a/plugins/techdocs/src/client.ts +++ b/plugins/techdocs/src/client.ts @@ -23,11 +23,13 @@ import { } from '@backstage/core-plugin-api'; import { NotFoundError, ResponseError } from '@backstage/errors'; import { + SyncResult, + TechDocsApi, TechDocsEntityMetadata, TechDocsMetadata, + TechDocsStorageApi, } from '@backstage/plugin-techdocs-react'; import { EventSourcePolyfill } from 'event-source-polyfill'; -import { SyncResult, TechDocsApi, TechDocsStorageApi } from './api'; /** * API to talk to `techdocs-backend`. @@ -189,7 +191,7 @@ export class TechDocsStorageClient implements TechDocsStorageApi { * @param entityId - Object containing entity data like name, namespace, etc. * @param logHandler - Callback to receive log messages from the build process * @returns Whether documents are currently synchronized to newest version - * @throws Throws error on error from sync endpoint in Techdocs Backend + * @throws Throws error on error from sync endpoint in TechDocs Backend */ async syncEntityDocs( entityId: CompoundEntityRef, diff --git a/plugins/techdocs/src/home/components/TechDocsPageWrapper.tsx b/plugins/techdocs/src/home/components/TechDocsPageWrapper.tsx index 52511bda19..a6192c13ee 100644 --- a/plugins/techdocs/src/home/components/TechDocsPageWrapper.tsx +++ b/plugins/techdocs/src/home/components/TechDocsPageWrapper.tsx @@ -29,7 +29,7 @@ export type TechDocsPageWrapperProps = { }; /** - * Component wrapping a techdocs page with Page and Header components + * Component wrapping a TechDocs page with Page and Header components * * @public */ diff --git a/plugins/techdocs/src/reader/README.md b/plugins/techdocs/src/reader/README.md index fe1d1ff488..58697298c6 100644 --- a/plugins/techdocs/src/reader/README.md +++ b/plugins/techdocs/src/reader/README.md @@ -2,7 +2,7 @@ The TechDocs reader is a component that fetches a remote page, runs transformers on it and renders it into a shadow dom. -Currently there's no easy way to customize which transformers to run or add new ones. If that is needed you would have to fork the techdocs plugin and make your changes in that fork. +Currently there's no easy way to customize which transformers to run or add new ones. If that is needed you would have to fork the TechDocs plugin and make your changes in that fork. Transformers are functions that optionally takes in parameters from the Reader.tsx component and returns a function which gets passed the DOM of the fetched page. A very simple transformer can look like this. diff --git a/plugins/techdocs/src/search/components/TechDocsSearch.tsx b/plugins/techdocs/src/search/components/TechDocsSearch.tsx index 56b51af795..665f99c1bb 100644 --- a/plugins/techdocs/src/search/components/TechDocsSearch.tsx +++ b/plugins/techdocs/src/search/components/TechDocsSearch.tsx @@ -21,20 +21,10 @@ import { SearchContextProvider, useSearch, } from '@backstage/plugin-search-react'; -import { makeStyles, Paper } from '@material-ui/core'; import React, { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { TechDocsSearchResultListItem } from './TechDocsSearchResultListItem'; -const useStyles = makeStyles(theme => ({ - root: { - width: '100%', - }, - bar: { - padding: theme.spacing(1), - }, -})); - /** * Props for {@link TechDocsSearch} * @@ -75,7 +65,6 @@ const TechDocsSearchBar = (props: TechDocsSearchProps) => { setFilters, result: { loading, value: searchVal }, } = useSearch(); - const classes = useStyles(); const [options, setOptions] = useState([]); useEffect(() => { let mounted = true; @@ -117,43 +106,40 @@ const TechDocsSearchBar = (props: TechDocsSearchProps) => { }; return ( - - ''} - filterOptions={x => { - return x; // This is needed to get renderOption to be called after options change. Bug in material-ui? - }} - onClose={() => { - setOpen(false); - }} - onFocus={() => { - setOpen(true); - }} - onChange={handleSelection} - blurOnSelect - noOptionsText="No results found" - value={null} - options={options} - renderOption={({ document, highlight }) => ( - - )} - loading={loading} - inputDebounceTime={debounceTime} - inputPlaceholder={`Search ${entityTitle || entityId.name} docs`} - freeSolo={false} - /> - + ''} + filterOptions={x => { + return x; // This is needed to get renderOption to be called after options change. Bug in material-ui? + }} + onClose={() => { + setOpen(false); + }} + onFocus={() => { + setOpen(true); + }} + onChange={handleSelection} + blurOnSelect + noOptionsText="No results found" + value={null} + options={options} + renderOption={({ document, highlight }) => ( + + )} + loading={loading} + inputDebounceTime={debounceTime} + inputPlaceholder={`Search ${entityTitle || entityId.name} docs`} + freeSolo={false} + /> ); }; diff --git a/plugins/todo-backend/CHANGELOG.md b/plugins/todo-backend/CHANGELOG.md index 84d8807698..ad26eea023 100644 --- a/plugins/todo-backend/CHANGELOG.md +++ b/plugins/todo-backend/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-todo-backend +## 0.1.43-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.2-next.0 + - @backstage/plugin-catalog-node@1.3.7-next.0 + - @backstage/backend-common@0.18.6-next.0 + - @backstage/integration@1.4.5 + - @backstage/config@1.0.7 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## 0.1.42 + +### Patch Changes + +- 901f1ada325: Added OpenAPI schema +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/integration@1.4.5 + - @backstage/plugin-catalog-node@1.3.6 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-client@1.4.1 + - @backstage/catalog-model@1.3.0 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + ## 0.1.42-next.1 ### Patch Changes diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index d98a44f874..e513e4b910 100644 --- a/plugins/todo-backend/package.json +++ b/plugins/todo-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo-backend", "description": "A Backstage backend plugin that lets you browse TODO comments in your source code", - "version": "0.1.42-next.1", + "version": "0.1.43-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -45,6 +45,7 @@ "yn": "^4.0.0" }, "devDependencies": { + "@backstage/backend-openapi-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/supertest": "^2.0.8", "msw": "^1.0.0", diff --git a/plugins/todo-backend/src/schema/openapi.generated.ts b/plugins/todo-backend/src/schema/openapi.generated.ts new file mode 100644 index 0000000000..54486a5615 --- /dev/null +++ b/plugins/todo-backend/src/schema/openapi.generated.ts @@ -0,0 +1,208 @@ +/* + * Copyright 2023 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. + */ + +// ****************************************************************** +// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * +// ****************************************************************** + +export default { + openapi: '3.0.3', + info: { + title: '@backstage/plugin-todo-backend', + version: '1', + description: + 'The Backstage backend plugin that provides source code todo comment browsing.', + license: { + name: 'Apache-2.0', + url: 'http://www.apache.org/licenses/LICENSE-2.0.html', + }, + contact: {}, + }, + servers: [ + { + url: '/', + }, + ], + components: { + examples: {}, + headers: {}, + parameters: {}, + requestBodies: {}, + responses: {}, + schemas: { + TodoItem: { + type: 'object', + properties: { + text: { + type: 'string', + description: 'The contents of the TODO comment', + }, + tag: { + type: 'string', + description: 'The tag used, e.g. TODO, FIXME', + }, + author: { + type: 'string', + description: 'References author, if any', + }, + viewUrl: { + type: 'string', + description: 'URL used to view the file', + }, + lineNumber: { + type: 'integer', + description: 'The line number of the file that the TODO occurs at', + }, + repoFilePath: { + type: 'string', + description: + 'The path of the file containing the TODO within the repo', + }, + }, + required: ['text', 'tag'], + additionalProperties: false, + }, + }, + securitySchemes: { + JWT: { + type: 'http', + scheme: 'bearer', + bearerFormat: 'JWT', + }, + }, + }, + paths: { + '/v1/todos': { + get: { + operationId: 'ListTodos', + responses: { + '200': { + description: 'Ok', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + items: { + type: 'array', + items: { + $ref: '#/components/schemas/TodoItem', + }, + }, + totalCount: { + type: 'integer', + }, + offset: { + type: 'integer', + }, + limit: { + type: 'integer', + }, + }, + required: ['items', 'totalCount', 'offset', 'limit'], + additionalProperties: false, + }, + }, + }, + }, + '400': { + description: 'Bad request', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + error: { + type: 'object', + properties: { + message: { + type: 'string', + }, + }, + }, + }, + }, + }, + }, + }, + }, + security: [ + {}, + { + JWT: [], + }, + ], + parameters: [ + { + name: 'entity', + in: 'query', + required: true, + schema: { + type: 'string', + minLength: 1, + description: 'A reference to the entity to list TODO items for', + }, + }, + { + name: 'orderBy', + in: 'query', + required: false, + schema: { + type: 'string', + pattern: '^(text|tag|author|viewUrl|repoFilePath)=(asc|desc)$', + description: + 'The field and direction used to sort the listed TODO items', + }, + }, + { + name: 'filter', + in: 'query', + required: false, + schema: { + type: 'array', + description: + 'A list of filters used to narrow down the listed TODO items', + items: { + type: 'string', + pattern: '^(text|tag|author|viewUrl|repoFilePath)=.+$', + }, + }, + }, + { + name: 'offset', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 0, + description: 'The offset at which to start listing TODO items', + }, + }, + { + name: 'limit', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + description: 'The number of TODO items to list', + }, + }, + ], + }, + }, + }, +} as const; diff --git a/plugins/todo-backend/src/schema/openapi.yaml b/plugins/todo-backend/src/schema/openapi.yaml new file mode 100644 index 0000000000..3fba129644 --- /dev/null +++ b/plugins/todo-backend/src/schema/openapi.yaml @@ -0,0 +1,132 @@ +openapi: 3.0.3 + +info: + title: '@backstage/plugin-todo-backend' + version: '1' + description: The Backstage backend plugin that provides source code todo comment browsing. + license: + name: Apache-2.0 + url: http://www.apache.org/licenses/LICENSE-2.0.html + contact: {} + +servers: + - url: / + +components: + examples: {} + headers: {} + parameters: {} + requestBodies: {} + responses: {} + schemas: + TodoItem: + type: object + properties: + text: + type: string + description: The contents of the TODO comment + tag: + type: string + description: The tag used, e.g. TODO, FIXME + author: + type: string + description: References author, if any + viewUrl: + type: string + description: URL used to view the file + lineNumber: + type: integer + description: The line number of the file that the TODO occurs at + repoFilePath: + type: string + description: The path of the file containing the TODO within the repo + required: + - text + - tag + additionalProperties: false + securitySchemes: + JWT: + type: http + scheme: bearer + bearerFormat: JWT +paths: + /v1/todos: + get: + operationId: ListTodos + responses: + '200': + description: Ok + content: + application/json: + schema: + type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/TodoItem' + totalCount: + type: integer + offset: + type: integer + limit: + type: integer + required: + - items + - totalCount + - offset + - limit + additionalProperties: false + '400': + description: Bad request + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + message: + type: string + security: + - {} + - JWT: [] + parameters: + - name: entity + in: query + required: true + schema: + type: string + minLength: 1 + description: A reference to the entity to list TODO items for + - name: orderBy + in: query + required: false + schema: + type: string + pattern: '^(text|tag|author|viewUrl|repoFilePath)=(asc|desc)$' + description: The field and direction used to sort the listed TODO items + - name: filter + in: query + required: false + schema: + type: array + description: A list of filters used to narrow down the listed TODO items + items: + type: string + pattern: '^(text|tag|author|viewUrl|repoFilePath)=.+$' + - name: offset + in: query + required: false + schema: + type: integer + minimum: 0 + description: The offset at which to start listing TODO items + - name: limit + in: query + required: false + schema: + type: integer + minimum: 1 + description: The number of TODO items to list diff --git a/plugins/todo-backend/src/service/router.ts b/plugins/todo-backend/src/service/router.ts index 5954fab009..364cbef6b0 100644 --- a/plugins/todo-backend/src/service/router.ts +++ b/plugins/todo-backend/src/service/router.ts @@ -25,6 +25,8 @@ import { parseIntegerParam, parseOrderByParam, } from '../lib/utils'; +import spec from '../schema/openapi.generated'; +import type { ApiRouter } from '@backstage/backend-openapi-utils'; /** @public */ export interface RouterOptions { @@ -37,7 +39,7 @@ export async function createRouter( ): Promise { const { todoService } = options; - const router = Router(); + const router = Router() as ApiRouter; router.use(express.json()); router.get('/v1/todos', async (req, res) => { diff --git a/plugins/todo/CHANGELOG.md b/plugins/todo/CHANGELOG.md index cb9e1464ff..ebe0a8aec0 100644 --- a/plugins/todo/CHANGELOG.md +++ b/plugins/todo/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-todo +## 0.2.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## 0.2.20 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.2.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.2.20-next.1 ### Patch Changes diff --git a/plugins/todo/package.json b/plugins/todo/package.json index f8a86b9cb2..01373e0ace 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo", "description": "A Backstage plugin that lets you browse TODO comments in your source code", - "version": "0.2.20-next.1", + "version": "0.2.21-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/user-settings-backend/CHANGELOG.md b/plugins/user-settings-backend/CHANGELOG.md index 4420e63f8e..94de523b73 100644 --- a/plugins/user-settings-backend/CHANGELOG.md +++ b/plugins/user-settings-backend/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-user-settings-backend +## 0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/backend-plugin-api@0.5.3-next.0 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.15-next.0 + +## 0.1.9 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/plugin-auth-node@0.2.14 + - @backstage/backend-plugin-api@0.5.2 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + ## 0.1.9-next.1 ### Patch Changes diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index 6fdeee038d..362c8d0c19 100644 --- a/plugins/user-settings-backend/package.json +++ b/plugins/user-settings-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-user-settings-backend", "description": "The Backstage backend plugin to manage user settings", - "version": "0.1.9-next.1", + "version": "0.1.10-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index 92558dfba7..44ff953ff8 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-user-settings +## 0.7.4-next.0 + +### Patch Changes + +- 7a8441b9a323: Reflect the updated sign on status for a provider after signing out. +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## 0.7.3 + +### Patch Changes + +- 473db605a4f: Fix config schema definition. +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-app-api@1.8.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + - @backstage/types@1.0.2 + +## 0.7.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-app-api@1.8.0-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 0.7.3-next.1 ### Patch Changes diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index b55293d414..209d3fb6f8 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-user-settings", "description": "A Backstage plugin that provides a settings page", - "version": "0.7.3-next.1", + "version": "0.7.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -78,7 +78,8 @@ "type": "object", "additionalProperties": { "type": "object", - "visibility": "frontend" + "visibility": "frontend", + "additionalProperties": true } } } diff --git a/plugins/user-settings/src/components/AuthProviders/ProviderSettingsItem.tsx b/plugins/user-settings/src/components/AuthProviders/ProviderSettingsItem.tsx index 852af7e78b..e3fb597a15 100644 --- a/plugins/user-settings/src/components/AuthProviders/ProviderSettingsItem.tsx +++ b/plugins/user-settings/src/components/AuthProviders/ProviderSettingsItem.tsx @@ -37,6 +37,8 @@ import { } from '@backstage/core-plugin-api'; import { ProviderSettingsAvatar } from './ProviderSettingsAvatar'; +const emptyProfile: ProfileInfo = {}; + /** @public */ export const ProviderSettingsItem = (props: { title: string; @@ -49,8 +51,7 @@ export const ProviderSettingsItem = (props: { const api = useApi(apiRef); const errorApi = useApi(errorApiRef); const [signedIn, setSignedIn] = useState(false); - const emptyProfile: ProfileInfo = {}; - const [profile, setProfile] = useState(emptyProfile); + const [profile, setProfile] = useState(emptyProfile); useEffect(() => { let didCancel = false; @@ -58,6 +59,10 @@ export const ProviderSettingsItem = (props: { const subscription = api .sessionState$() .subscribe((sessionState: SessionState) => { + if (sessionState !== SessionState.SignedIn) { + setProfile(emptyProfile); + setSignedIn(false); + } if (!didCancel) { api .getProfile({ optional: true }) diff --git a/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx b/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx index c58e637bd2..60b951ab60 100644 --- a/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx +++ b/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx @@ -25,6 +25,8 @@ import { import { EmptyFlags } from './EmptyFlags'; import { FlagItem } from './FeatureFlagsItem'; import { + FeatureFlag, + FeatureFlagsApi, featureFlagsApiRef, FeatureFlagState, useApi, @@ -32,10 +34,26 @@ import { import { InfoCard } from '@backstage/core-components'; import ClearIcon from '@material-ui/icons/Clear'; +export const sortFlags = ( + flags: FeatureFlag[], + featureFlagsApi: FeatureFlagsApi, +): FeatureFlag[] => { + const activeFlags = flags.filter(flag => featureFlagsApi.isActive(flag.name)); + const idleFlags = flags.filter(flag => !featureFlagsApi.isActive(flag.name)); + return [...activeFlags, ...idleFlags]; +}; + /** @public */ export const UserSettingsFeatureFlags = () => { const featureFlagsApi = useApi(featureFlagsApiRef); - const featureFlags = featureFlagsApi.getRegisteredFlags(); + const inputRef = React.useRef(); + + const initialFeatureFlags = featureFlagsApi.getRegisteredFlags(); + const initialFeatureFlagsSorted = sortFlags( + initialFeatureFlags, + featureFlagsApi, + ); + const [featureFlags] = useState(initialFeatureFlagsSorted); const initialFlagState = Object.fromEntries( featureFlags.map(({ name }) => [name, featureFlagsApi.isActive(name)]), @@ -43,7 +61,6 @@ export const UserSettingsFeatureFlags = () => { const [state, setState] = useState>(initialFlagState); const [filterInput, setFilterInput] = useState(''); - const inputRef = React.useRef(); const toggleFlag = useCallback( (flagName: string) => { diff --git a/plugins/vault-backend/CHANGELOG.md b/plugins/vault-backend/CHANGELOG.md index 33fcd6017c..ab1d346877 100644 --- a/plugins/vault-backend/CHANGELOG.md +++ b/plugins/vault-backend/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-vault-backend +## 0.3.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.6-next.0 + - @backstage/config@1.0.7 + - @backstage/backend-tasks@0.5.3-next.0 + - @backstage/errors@1.1.5 + +## 0.3.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.5 + - @backstage/backend-tasks@0.5.2 + - @backstage/config@1.0.7 + - @backstage/errors@1.1.5 + ## 0.3.1-next.1 ### Patch Changes diff --git a/plugins/vault-backend/package.json b/plugins/vault-backend/package.json index 0f4467ca80..34e6d53b5e 100644 --- a/plugins/vault-backend/package.json +++ b/plugins/vault-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-vault-backend", "description": "A Backstage backend plugin that integrates towards Vault", - "version": "0.3.1-next.1", + "version": "0.3.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/vault/CHANGELOG.md b/plugins/vault/CHANGELOG.md index 7af7f47adc..87c415c1ca 100644 --- a/plugins/vault/CHANGELOG.md +++ b/plugins/vault/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-vault +## 0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.7.0-next.0 + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/catalog-model@1.3.0 + - @backstage/errors@1.1.5 + +## 0.1.12 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/plugin-catalog-react@1.6.0 + - @backstage/core-components@0.13.1 + - @backstage/catalog-model@1.3.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.1.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.6.0-next.2 + - @backstage/core-plugin-api@1.5.1 + ## 0.1.12-next.1 ### Patch Changes diff --git a/plugins/vault/package.json b/plugins/vault/package.json index 6d97b0a5e9..f1d0837758 100644 --- a/plugins/vault/package.json +++ b/plugins/vault/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-vault", "description": "A Backstage plugin that integrates towards Vault", - "version": "0.1.12-next.1", + "version": "0.1.13-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/xcmetrics/CHANGELOG.md b/plugins/xcmetrics/CHANGELOG.md index eccce54f0b..38ed4003d5 100644 --- a/plugins/xcmetrics/CHANGELOG.md +++ b/plugins/xcmetrics/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-xcmetrics +## 0.2.39-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.4.0-next.0 + - @backstage/core-components@0.13.2-next.0 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.2.38 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0 + - @backstage/core-components@0.13.1 + - @backstage/core-plugin-api@1.5.1 + - @backstage/errors@1.1.5 + +## 0.2.38-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.3.0-next.0 + - @backstage/core-components@0.13.1-next.1 + - @backstage/core-plugin-api@1.5.1 + ## 0.2.38-next.0 ### Patch Changes diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index 18b86eb0ee..33c20f3f5a 100644 --- a/plugins/xcmetrics/package.json +++ b/plugins/xcmetrics/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-xcmetrics", "description": "A Backstage plugin that shows XCode build metrics for your components", - "version": "0.2.38-next.0", + "version": "0.2.39-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/xcmetrics/src/components/BuildListFilter/BuildListFilter.test.tsx b/plugins/xcmetrics/src/components/BuildListFilter/BuildListFilter.test.tsx index 5062da4749..bc81b57882 100644 --- a/plugins/xcmetrics/src/components/BuildListFilter/BuildListFilter.test.tsx +++ b/plugins/xcmetrics/src/components/BuildListFilter/BuildListFilter.test.tsx @@ -18,7 +18,7 @@ import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import userEvent from '@testing-library/user-event'; import { BuildListFilter } from './BuildListFilter'; import { BuildFilters, xcmetricsApiRef } from '../../api'; -import { RenderResult } from '@testing-library/react'; +import { RenderResult, within } from '@testing-library/react'; jest.mock('../../api/XcmetricsClient'); const client = require('../../api/XcmetricsClient'); @@ -50,13 +50,13 @@ const renderWithFiltersVisible = async ( const setStatusFilter = async (rendered: RenderResult, option: string) => { const statusSelect = rendered.getAllByTestId('select')[0]; - await userEvent.click(statusSelect); + await userEvent.click(within(statusSelect).getByRole('button')); await userEvent.click((await rendered.findAllByText(option))[0]); }; const setProjectFilter = async (rendered: RenderResult, option: string) => { const statusSelect = rendered.getAllByTestId('select')[1]; - await userEvent.click(statusSelect); + await userEvent.click(within(statusSelect).getByRole('button')); const options = await rendered.findAllByText(option); await userEvent.click(options[options.length - 1]); }; diff --git a/storybook/yarn.lock b/storybook/yarn.lock index a4d5837ba5..6204cf564f 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -2943,90 +2943,90 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-darwin-arm64@npm:1.3.51" +"@swc/core-darwin-arm64@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-darwin-arm64@npm:1.3.59" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-darwin-x64@npm:1.3.51" +"@swc/core-darwin-x64@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-darwin-x64@npm:1.3.59" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.51" +"@swc/core-linux-arm-gnueabihf@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.59" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.51" +"@swc/core-linux-arm64-gnu@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.59" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.51" +"@swc/core-linux-arm64-musl@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.59" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.51" +"@swc/core-linux-x64-gnu@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.59" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-linux-x64-musl@npm:1.3.51" +"@swc/core-linux-x64-musl@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-linux-x64-musl@npm:1.3.59" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.51" +"@swc/core-win32-arm64-msvc@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.59" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.51" +"@swc/core-win32-ia32-msvc@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.59" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.51" +"@swc/core-win32-x64-msvc@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.59" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.46": - version: 1.3.51 - resolution: "@swc/core@npm:1.3.51" + version: 1.3.59 + resolution: "@swc/core@npm:1.3.59" dependencies: - "@swc/core-darwin-arm64": 1.3.51 - "@swc/core-darwin-x64": 1.3.51 - "@swc/core-linux-arm-gnueabihf": 1.3.51 - "@swc/core-linux-arm64-gnu": 1.3.51 - "@swc/core-linux-arm64-musl": 1.3.51 - "@swc/core-linux-x64-gnu": 1.3.51 - "@swc/core-linux-x64-musl": 1.3.51 - "@swc/core-win32-arm64-msvc": 1.3.51 - "@swc/core-win32-ia32-msvc": 1.3.51 - "@swc/core-win32-x64-msvc": 1.3.51 + "@swc/core-darwin-arm64": 1.3.59 + "@swc/core-darwin-x64": 1.3.59 + "@swc/core-linux-arm-gnueabihf": 1.3.59 + "@swc/core-linux-arm64-gnu": 1.3.59 + "@swc/core-linux-arm64-musl": 1.3.59 + "@swc/core-linux-x64-gnu": 1.3.59 + "@swc/core-linux-x64-musl": 1.3.59 + "@swc/core-win32-arm64-msvc": 1.3.59 + "@swc/core-win32-ia32-msvc": 1.3.59 + "@swc/core-win32-x64-msvc": 1.3.59 peerDependencies: "@swc/helpers": ^0.5.0 dependenciesMeta: @@ -3053,7 +3053,7 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: f4e72d347b26353fbb48eae110a63c939922a38b20730ea010f5ae3dd15434f212dce582df05556ec35e677c089dfb6d00f5dd6fc655f8c9a7829458e4301469 + checksum: 0283f39cf49cd12a6dc7062ef9ea4fa93e1a4f622ce46903a09605219f4f47ed5ad03925c6146d09ffe6ee02a89bb14e3c82eb86b4c60ecce4985ea6e078ffcf languageName: node linkType: hard @@ -3444,154 +3444,154 @@ __metadata: languageName: node linkType: hard -"@webassemblyjs/ast@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/ast@npm:1.11.1" +"@webassemblyjs/ast@npm:1.11.6, @webassemblyjs/ast@npm:^1.11.5": + version: 1.11.6 + resolution: "@webassemblyjs/ast@npm:1.11.6" dependencies: - "@webassemblyjs/helper-numbers": 1.11.1 - "@webassemblyjs/helper-wasm-bytecode": 1.11.1 - checksum: 1eee1534adebeece635362f8e834ae03e389281972611408d64be7895fc49f48f98fddbbb5339bf8a72cb101bcb066e8bca3ca1bf1ef47dadf89def0395a8d87 + "@webassemblyjs/helper-numbers": 1.11.6 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + checksum: 38ef1b526ca47c210f30975b06df2faf1a8170b1636ce239fc5738fc231ce28389dd61ecedd1bacfc03cbe95b16d1af848c805652080cb60982836eb4ed2c6cf languageName: node linkType: hard -"@webassemblyjs/floating-point-hex-parser@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/floating-point-hex-parser@npm:1.11.1" - checksum: b8efc6fa08e4787b7f8e682182d84dfdf8da9d9c77cae5d293818bc4a55c1f419a87fa265ab85252b3e6c1fd323d799efea68d825d341a7c365c64bc14750e97 +"@webassemblyjs/floating-point-hex-parser@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/floating-point-hex-parser@npm:1.11.6" + checksum: 29b08758841fd8b299c7152eda36b9eb4921e9c584eb4594437b5cd90ed6b920523606eae7316175f89c20628da14326801090167cc7fbffc77af448ac84b7e2 languageName: node linkType: hard -"@webassemblyjs/helper-api-error@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/helper-api-error@npm:1.11.1" - checksum: 0792813f0ed4a0e5ee0750e8b5d0c631f08e927f4bdfdd9fe9105dc410c786850b8c61bff7f9f515fdfb149903bec3c976a1310573a4c6866a94d49bc7271959 +"@webassemblyjs/helper-api-error@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-api-error@npm:1.11.6" + checksum: e8563df85161096343008f9161adb138a6e8f3c2cc338d6a36011aa55eabb32f2fd138ffe63bc278d009ada001cc41d263dadd1c0be01be6c2ed99076103689f languageName: node linkType: hard -"@webassemblyjs/helper-buffer@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/helper-buffer@npm:1.11.1" - checksum: a337ee44b45590c3a30db5a8b7b68a717526cf967ada9f10253995294dbd70a58b2da2165222e0b9830cd4fc6e4c833bf441a721128d1fe2e9a7ab26b36003ce +"@webassemblyjs/helper-buffer@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-buffer@npm:1.11.6" + checksum: b14d0573bf680d22b2522e8a341ec451fddd645d1f9c6bd9012ccb7e587a2973b86ab7b89fe91e1c79939ba96095f503af04369a3b356c8023c13a5893221644 languageName: node linkType: hard -"@webassemblyjs/helper-numbers@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/helper-numbers@npm:1.11.1" +"@webassemblyjs/helper-numbers@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-numbers@npm:1.11.6" dependencies: - "@webassemblyjs/floating-point-hex-parser": 1.11.1 - "@webassemblyjs/helper-api-error": 1.11.1 + "@webassemblyjs/floating-point-hex-parser": 1.11.6 + "@webassemblyjs/helper-api-error": 1.11.6 "@xtuc/long": 4.2.2 - checksum: 44d2905dac2f14d1e9b5765cf1063a0fa3d57295c6d8930f6c59a36462afecc6e763e8a110b97b342a0f13376166c5d41aa928e6ced92e2f06b071fd0db59d3a + checksum: f4b562fa219f84368528339e0f8d273ad44e047a07641ffcaaec6f93e5b76fd86490a009aa91a294584e1436d74b0a01fa9fde45e333a4c657b58168b04da424 languageName: node linkType: hard -"@webassemblyjs/helper-wasm-bytecode@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/helper-wasm-bytecode@npm:1.11.1" - checksum: eac400113127832c88f5826bcc3ad1c0db9b3dbd4c51a723cfdb16af6bfcbceb608170fdaac0ab7731a7e18b291be7af68a47fcdb41cfe0260c10857e7413d97 +"@webassemblyjs/helper-wasm-bytecode@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-wasm-bytecode@npm:1.11.6" + checksum: 3535ef4f1fba38de3475e383b3980f4bbf3de72bbb631c2b6584c7df45be4eccd62c6ff48b5edd3f1bcff275cfd605a37679ec199fc91fd0a7705d7f1e3972dc languageName: node linkType: hard -"@webassemblyjs/helper-wasm-section@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/helper-wasm-section@npm:1.11.1" +"@webassemblyjs/helper-wasm-section@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-wasm-section@npm:1.11.6" dependencies: - "@webassemblyjs/ast": 1.11.1 - "@webassemblyjs/helper-buffer": 1.11.1 - "@webassemblyjs/helper-wasm-bytecode": 1.11.1 - "@webassemblyjs/wasm-gen": 1.11.1 - checksum: 617696cfe8ecaf0532763162aaf748eb69096fb27950219bb87686c6b2e66e11cd0614d95d319d0ab1904bc14ebe4e29068b12c3e7c5e020281379741fe4bedf + "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/helper-buffer": 1.11.6 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + "@webassemblyjs/wasm-gen": 1.11.6 + checksum: b2cf751bf4552b5b9999d27bbb7692d0aca75260140195cb58ea6374d7b9c2dc69b61e10b211a0e773f66209c3ddd612137ed66097e3684d7816f854997682e9 languageName: node linkType: hard -"@webassemblyjs/ieee754@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/ieee754@npm:1.11.1" +"@webassemblyjs/ieee754@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/ieee754@npm:1.11.6" dependencies: "@xtuc/ieee754": ^1.2.0 - checksum: 23a0ac02a50f244471631802798a816524df17e56b1ef929f0c73e3cde70eaf105a24130105c60aff9d64a24ce3b640dad443d6f86e5967f922943a7115022ec + checksum: 13574b8e41f6ca39b700e292d7edf102577db5650fe8add7066a320aa4b7a7c09a5056feccac7a74eb68c10dea9546d4461412af351f13f6b24b5f32379b49de languageName: node linkType: hard -"@webassemblyjs/leb128@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/leb128@npm:1.11.1" +"@webassemblyjs/leb128@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/leb128@npm:1.11.6" dependencies: "@xtuc/long": 4.2.2 - checksum: 33ccc4ade2f24de07bf31690844d0b1ad224304ee2062b0e464a610b0209c79e0b3009ac190efe0e6bd568b0d1578d7c3047fc1f9d0197c92fc061f56224ff4a + checksum: 7ea942dc9777d4b18a5ebfa3a937b30ae9e1d2ce1fee637583ed7f376334dd1d4274f813d2e250056cca803e0952def4b954913f1a3c9068bcd4ab4ee5143bf0 languageName: node linkType: hard -"@webassemblyjs/utf8@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/utf8@npm:1.11.1" - checksum: 972c5cfc769d7af79313a6bfb96517253a270a4bf0c33ba486aa43cac43917184fb35e51dfc9e6b5601548cd5931479a42e42c89a13bb591ffabebf30c8a6a0b +"@webassemblyjs/utf8@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/utf8@npm:1.11.6" + checksum: 807fe5b5ce10c390cfdd93e0fb92abda8aebabb5199980681e7c3743ee3306a75729bcd1e56a3903980e96c885ee53ef901fcbaac8efdfa480f9c0dae1d08713 languageName: node linkType: hard -"@webassemblyjs/wasm-edit@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/wasm-edit@npm:1.11.1" +"@webassemblyjs/wasm-edit@npm:^1.11.5": + version: 1.11.6 + resolution: "@webassemblyjs/wasm-edit@npm:1.11.6" dependencies: - "@webassemblyjs/ast": 1.11.1 - "@webassemblyjs/helper-buffer": 1.11.1 - "@webassemblyjs/helper-wasm-bytecode": 1.11.1 - "@webassemblyjs/helper-wasm-section": 1.11.1 - "@webassemblyjs/wasm-gen": 1.11.1 - "@webassemblyjs/wasm-opt": 1.11.1 - "@webassemblyjs/wasm-parser": 1.11.1 - "@webassemblyjs/wast-printer": 1.11.1 - checksum: 6d7d9efaec1227e7ef7585a5d7ff0be5f329f7c1c6b6c0e906b18ed2e9a28792a5635e450aca2d136770d0207225f204eff70a4b8fd879d3ac79e1dcc26dbeb9 + "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/helper-buffer": 1.11.6 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + "@webassemblyjs/helper-wasm-section": 1.11.6 + "@webassemblyjs/wasm-gen": 1.11.6 + "@webassemblyjs/wasm-opt": 1.11.6 + "@webassemblyjs/wasm-parser": 1.11.6 + "@webassemblyjs/wast-printer": 1.11.6 + checksum: 29ce75870496d6fad864d815ebb072395a8a3a04dc9c3f4e1ffdc63fc5fa58b1f34304a1117296d8240054cfdbc38aca88e71fb51483cf29ffab0a61ef27b481 languageName: node linkType: hard -"@webassemblyjs/wasm-gen@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/wasm-gen@npm:1.11.1" +"@webassemblyjs/wasm-gen@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/wasm-gen@npm:1.11.6" dependencies: - "@webassemblyjs/ast": 1.11.1 - "@webassemblyjs/helper-wasm-bytecode": 1.11.1 - "@webassemblyjs/ieee754": 1.11.1 - "@webassemblyjs/leb128": 1.11.1 - "@webassemblyjs/utf8": 1.11.1 - checksum: 1f6921e640293bf99fb16b21e09acb59b340a79f986c8f979853a0ae9f0b58557534b81e02ea2b4ef11e929d946708533fd0693c7f3712924128fdafd6465f5b + "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + "@webassemblyjs/ieee754": 1.11.6 + "@webassemblyjs/leb128": 1.11.6 + "@webassemblyjs/utf8": 1.11.6 + checksum: a645a2eecbea24833c3260a249704a7f554ef4a94c6000984728e94bb2bc9140a68dfd6fd21d5e0bbb09f6dfc98e083a45760a83ae0417b41a0196ff6d45a23a languageName: node linkType: hard -"@webassemblyjs/wasm-opt@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/wasm-opt@npm:1.11.1" +"@webassemblyjs/wasm-opt@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/wasm-opt@npm:1.11.6" dependencies: - "@webassemblyjs/ast": 1.11.1 - "@webassemblyjs/helper-buffer": 1.11.1 - "@webassemblyjs/wasm-gen": 1.11.1 - "@webassemblyjs/wasm-parser": 1.11.1 - checksum: 21586883a20009e2b20feb67bdc451bbc6942252e038aae4c3a08e6f67b6bae0f5f88f20bfc7bd0452db5000bacaf5ab42b98cf9aa034a6c70e9fc616142e1db + "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/helper-buffer": 1.11.6 + "@webassemblyjs/wasm-gen": 1.11.6 + "@webassemblyjs/wasm-parser": 1.11.6 + checksum: b4557f195487f8e97336ddf79f7bef40d788239169aac707f6eaa2fa5fe243557c2d74e550a8e57f2788e70c7ae4e7d32f7be16101afe183d597b747a3bdd528 languageName: node linkType: hard -"@webassemblyjs/wasm-parser@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/wasm-parser@npm:1.11.1" +"@webassemblyjs/wasm-parser@npm:1.11.6, @webassemblyjs/wasm-parser@npm:^1.11.5": + version: 1.11.6 + resolution: "@webassemblyjs/wasm-parser@npm:1.11.6" dependencies: - "@webassemblyjs/ast": 1.11.1 - "@webassemblyjs/helper-api-error": 1.11.1 - "@webassemblyjs/helper-wasm-bytecode": 1.11.1 - "@webassemblyjs/ieee754": 1.11.1 - "@webassemblyjs/leb128": 1.11.1 - "@webassemblyjs/utf8": 1.11.1 - checksum: 1521644065c360e7b27fad9f4bb2df1802d134dd62937fa1f601a1975cde56bc31a57b6e26408b9ee0228626ff3ba1131ae6f74ffb7d718415b6528c5a6dbfc2 + "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/helper-api-error": 1.11.6 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + "@webassemblyjs/ieee754": 1.11.6 + "@webassemblyjs/leb128": 1.11.6 + "@webassemblyjs/utf8": 1.11.6 + checksum: 8200a8d77c15621724a23fdabe58d5571415cda98a7058f542e670ea965dd75499f5e34a48675184947c66f3df23adf55df060312e6d72d57908e3f049620d8a languageName: node linkType: hard -"@webassemblyjs/wast-printer@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/wast-printer@npm:1.11.1" +"@webassemblyjs/wast-printer@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/wast-printer@npm:1.11.6" dependencies: - "@webassemblyjs/ast": 1.11.1 + "@webassemblyjs/ast": 1.11.6 "@xtuc/long": 4.2.2 - checksum: f15ae4c2441b979a3b4fce78f3d83472fb22350c6dc3fd34bfe7c3da108e0b2360718734d961bba20e7716cb8578e964b870da55b035e209e50ec9db0378a3f7 + checksum: d2fa6a4c427325ec81463e9c809aa6572af6d47f619f3091bf4c4a6fc34f1da3df7caddaac50b8e7a457f8784c62cd58c6311b6cb69b0162ccd8d4c072f79cf8 languageName: node linkType: hard @@ -5513,13 +5513,13 @@ __metadata: languageName: node linkType: hard -"enhanced-resolve@npm:^5.10.0": - version: 5.10.0 - resolution: "enhanced-resolve@npm:5.10.0" +"enhanced-resolve@npm:^5.14.0": + version: 5.14.0 + resolution: "enhanced-resolve@npm:5.14.0" dependencies: graceful-fs: ^4.2.4 tapable: ^2.2.0 - checksum: 0bb9830704db271610f900e8d79d70a740ea16f251263362b0c91af545576d09fe50103496606c1300a05e588372d6f9780a9bc2e30ce8ef9b827ec8f44687ff + checksum: fff1aaebbf376371e5df4502e111967f6247c37611ad3550e4e7fca657f6dcb29ef7ffe88bf14e5010b78997f1ddd984a8db97af87ee0a5477771398fd326f5b languageName: node linkType: hard @@ -10282,14 +10282,14 @@ __metadata: languageName: node linkType: hard -"schema-utils@npm:^3.0.0, schema-utils@npm:^3.1.0, schema-utils@npm:^3.1.1": - version: 3.1.1 - resolution: "schema-utils@npm:3.1.1" +"schema-utils@npm:^3.0.0, schema-utils@npm:^3.1.1, schema-utils@npm:^3.1.2": + version: 3.1.2 + resolution: "schema-utils@npm:3.1.2" dependencies: "@types/json-schema": ^7.0.8 ajv: ^6.12.5 ajv-keywords: ^3.5.2 - checksum: fb73f3d759d43ba033c877628fe9751620a26879f6301d3dbeeb48cf2a65baec5cdf99da65d1bf3b4ff5444b2e59cbe4f81c2456b5e0d2ba7d7fd4aed5da29ce + checksum: 39683edfe3beff018cdb1ae4fa296fc55cea13a080aa2b4d9351895cd64b22ba4d87e2e548c2a2ac1bc76e60980670adb0f413a58104479f1a0c12e5663cb8ca languageName: node linkType: hard @@ -11863,19 +11863,19 @@ __metadata: linkType: hard "webpack@npm:^5.73.0": - version: 5.79.0 - resolution: "webpack@npm:5.79.0" + version: 5.83.1 + resolution: "webpack@npm:5.83.1" dependencies: "@types/eslint-scope": ^3.7.3 "@types/estree": ^1.0.0 - "@webassemblyjs/ast": 1.11.1 - "@webassemblyjs/wasm-edit": 1.11.1 - "@webassemblyjs/wasm-parser": 1.11.1 + "@webassemblyjs/ast": ^1.11.5 + "@webassemblyjs/wasm-edit": ^1.11.5 + "@webassemblyjs/wasm-parser": ^1.11.5 acorn: ^8.7.1 acorn-import-assertions: ^1.7.6 browserslist: ^4.14.5 chrome-trace-event: ^1.0.2 - enhanced-resolve: ^5.10.0 + enhanced-resolve: ^5.14.0 es-module-lexer: ^1.2.1 eslint-scope: 5.1.1 events: ^3.2.0 @@ -11885,7 +11885,7 @@ __metadata: loader-runner: ^4.2.0 mime-types: ^2.1.27 neo-async: ^2.6.2 - schema-utils: ^3.1.0 + schema-utils: ^3.1.2 tapable: ^2.1.1 terser-webpack-plugin: ^5.3.7 watchpack: ^2.4.0 @@ -11895,7 +11895,7 @@ __metadata: optional: true bin: webpack: bin/webpack.js - checksum: 3fbd82dadc75c8f823c900c5d50263830b77e6be6a8abb26eec12f93dec94c2f07fa44c1ef1f28319682404e532d9707ed04ed6cb89af87ca7d544e435d8ef95 + checksum: 219d5ef50380bc0fd3702ed17feddf13819d8173b78f7a5b857dc74ac177e63d1f79c050792754411cc088bbc02e0971b989efddadbb8e393cf27d64c0ad9ff8 languageName: node linkType: hard diff --git a/yarn.lock b/yarn.lock index e4ffb758a5..2071308e32 100644 --- a/yarn.lock +++ b/yarn.lock @@ -531,13 +531,13 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/abort-controller@npm:3.310.0, @aws-sdk/abort-controller@npm:^3.208.0": - version: 3.310.0 - resolution: "@aws-sdk/abort-controller@npm:3.310.0" +"@aws-sdk/abort-controller@npm:3.338.0, @aws-sdk/abort-controller@npm:^3.310.0": + version: 3.338.0 + resolution: "@aws-sdk/abort-controller@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: ca081fbec7419ff7bc03b7fddcfe7be1d5e390290c819069f42672f5a66415b55d90a81de899c384fd3368396390e3573c66345a8f91683e600c6caff64a239f + checksum: e86ceabc2c03a3bf5d97759e1109bc9f13479566278cd3601c614ed7056d58618bd8a2b637e6302491e23d872ffefba42d9dd81ff8142f9801aaca0e7ecb3c83 languageName: node linkType: hard @@ -550,532 +550,628 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/client-cognito-identity@npm:3.312.0": - version: 3.312.0 - resolution: "@aws-sdk/client-cognito-identity@npm:3.312.0" +"@aws-sdk/client-cognito-identity@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/client-cognito-identity@npm:3.338.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/client-sts": 3.312.0 - "@aws-sdk/config-resolver": 3.310.0 - "@aws-sdk/credential-provider-node": 3.310.0 - "@aws-sdk/fetch-http-handler": 3.310.0 - "@aws-sdk/hash-node": 3.310.0 - "@aws-sdk/invalid-dependency": 3.310.0 - "@aws-sdk/middleware-content-length": 3.310.0 - "@aws-sdk/middleware-endpoint": 3.310.0 - "@aws-sdk/middleware-host-header": 3.310.0 - "@aws-sdk/middleware-logger": 3.310.0 - "@aws-sdk/middleware-recursion-detection": 3.310.0 - "@aws-sdk/middleware-retry": 3.310.0 - "@aws-sdk/middleware-serde": 3.310.0 - "@aws-sdk/middleware-signing": 3.310.0 - "@aws-sdk/middleware-stack": 3.310.0 - "@aws-sdk/middleware-user-agent": 3.310.0 - "@aws-sdk/node-config-provider": 3.310.0 - "@aws-sdk/node-http-handler": 3.310.0 - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/smithy-client": 3.310.0 - "@aws-sdk/types": 3.310.0 - "@aws-sdk/url-parser": 3.310.0 + "@aws-sdk/client-sts": 3.338.0 + "@aws-sdk/config-resolver": 3.338.0 + "@aws-sdk/credential-provider-node": 3.338.0 + "@aws-sdk/fetch-http-handler": 3.338.0 + "@aws-sdk/hash-node": 3.338.0 + "@aws-sdk/invalid-dependency": 3.338.0 + "@aws-sdk/middleware-content-length": 3.338.0 + "@aws-sdk/middleware-endpoint": 3.338.0 + "@aws-sdk/middleware-host-header": 3.338.0 + "@aws-sdk/middleware-logger": 3.338.0 + "@aws-sdk/middleware-recursion-detection": 3.338.0 + "@aws-sdk/middleware-retry": 3.338.0 + "@aws-sdk/middleware-serde": 3.338.0 + "@aws-sdk/middleware-signing": 3.338.0 + "@aws-sdk/middleware-stack": 3.338.0 + "@aws-sdk/middleware-user-agent": 3.338.0 + "@aws-sdk/node-config-provider": 3.338.0 + "@aws-sdk/node-http-handler": 3.338.0 + "@aws-sdk/smithy-client": 3.338.0 + "@aws-sdk/types": 3.338.0 + "@aws-sdk/url-parser": 3.338.0 "@aws-sdk/util-base64": 3.310.0 "@aws-sdk/util-body-length-browser": 3.310.0 "@aws-sdk/util-body-length-node": 3.310.0 - "@aws-sdk/util-defaults-mode-browser": 3.310.0 - "@aws-sdk/util-defaults-mode-node": 3.310.0 - "@aws-sdk/util-endpoints": 3.310.0 - "@aws-sdk/util-retry": 3.310.0 - "@aws-sdk/util-user-agent-browser": 3.310.0 - "@aws-sdk/util-user-agent-node": 3.310.0 + "@aws-sdk/util-defaults-mode-browser": 3.338.0 + "@aws-sdk/util-defaults-mode-node": 3.338.0 + "@aws-sdk/util-endpoints": 3.338.0 + "@aws-sdk/util-retry": 3.338.0 + "@aws-sdk/util-user-agent-browser": 3.338.0 + "@aws-sdk/util-user-agent-node": 3.338.0 "@aws-sdk/util-utf8": 3.310.0 + "@smithy/protocol-http": ^1.0.1 + "@smithy/types": ^1.0.0 tslib: ^2.5.0 - checksum: 1bbd307c899e112bc265927e052afebe7e25d111fce8e765c85c40a84152910549dd25d9d8f4cb0561773f9be72c5a71f0ff9577582f61ee30e27d4188dc06d5 + checksum: d560eb2ca9b764d899e012bddfed31d7f283811b5d408eb66b99daa42dfea1077d1eba4bb0edcb8e1068ed18f1ea5fb65b0027a04b4bce935739976665c378a5 languageName: node linkType: hard -"@aws-sdk/client-s3@npm:^3.208.0": - version: 3.312.0 - resolution: "@aws-sdk/client-s3@npm:3.312.0" +"@aws-sdk/client-eks@npm:^3.310.0": + version: 3.338.0 + resolution: "@aws-sdk/client-eks@npm:3.338.0" + dependencies: + "@aws-crypto/sha256-browser": 3.0.0 + "@aws-crypto/sha256-js": 3.0.0 + "@aws-sdk/client-sts": 3.338.0 + "@aws-sdk/config-resolver": 3.338.0 + "@aws-sdk/credential-provider-node": 3.338.0 + "@aws-sdk/fetch-http-handler": 3.338.0 + "@aws-sdk/hash-node": 3.338.0 + "@aws-sdk/invalid-dependency": 3.338.0 + "@aws-sdk/middleware-content-length": 3.338.0 + "@aws-sdk/middleware-endpoint": 3.338.0 + "@aws-sdk/middleware-host-header": 3.338.0 + "@aws-sdk/middleware-logger": 3.338.0 + "@aws-sdk/middleware-recursion-detection": 3.338.0 + "@aws-sdk/middleware-retry": 3.338.0 + "@aws-sdk/middleware-serde": 3.338.0 + "@aws-sdk/middleware-signing": 3.338.0 + "@aws-sdk/middleware-stack": 3.338.0 + "@aws-sdk/middleware-user-agent": 3.338.0 + "@aws-sdk/node-config-provider": 3.338.0 + "@aws-sdk/node-http-handler": 3.338.0 + "@aws-sdk/smithy-client": 3.338.0 + "@aws-sdk/types": 3.338.0 + "@aws-sdk/url-parser": 3.338.0 + "@aws-sdk/util-base64": 3.310.0 + "@aws-sdk/util-body-length-browser": 3.310.0 + "@aws-sdk/util-body-length-node": 3.310.0 + "@aws-sdk/util-defaults-mode-browser": 3.338.0 + "@aws-sdk/util-defaults-mode-node": 3.338.0 + "@aws-sdk/util-endpoints": 3.338.0 + "@aws-sdk/util-retry": 3.338.0 + "@aws-sdk/util-user-agent-browser": 3.338.0 + "@aws-sdk/util-user-agent-node": 3.338.0 + "@aws-sdk/util-utf8": 3.310.0 + "@aws-sdk/util-waiter": 3.338.0 + "@smithy/protocol-http": ^1.0.1 + "@smithy/types": ^1.0.0 + tslib: ^2.5.0 + uuid: ^8.3.2 + checksum: a3e6dfb9b437e58417774b47e7c3eeabc7e6d301bb856516eb2438be72e83f06094703d00076be3534cbcf4dae6201523ab52f51ca0bf11416103a4dd13e2eee + languageName: node + linkType: hard + +"@aws-sdk/client-organizations@npm:^3.310.0": + version: 3.338.0 + resolution: "@aws-sdk/client-organizations@npm:3.338.0" + dependencies: + "@aws-crypto/sha256-browser": 3.0.0 + "@aws-crypto/sha256-js": 3.0.0 + "@aws-sdk/client-sts": 3.338.0 + "@aws-sdk/config-resolver": 3.338.0 + "@aws-sdk/credential-provider-node": 3.338.0 + "@aws-sdk/fetch-http-handler": 3.338.0 + "@aws-sdk/hash-node": 3.338.0 + "@aws-sdk/invalid-dependency": 3.338.0 + "@aws-sdk/middleware-content-length": 3.338.0 + "@aws-sdk/middleware-endpoint": 3.338.0 + "@aws-sdk/middleware-host-header": 3.338.0 + "@aws-sdk/middleware-logger": 3.338.0 + "@aws-sdk/middleware-recursion-detection": 3.338.0 + "@aws-sdk/middleware-retry": 3.338.0 + "@aws-sdk/middleware-serde": 3.338.0 + "@aws-sdk/middleware-signing": 3.338.0 + "@aws-sdk/middleware-stack": 3.338.0 + "@aws-sdk/middleware-user-agent": 3.338.0 + "@aws-sdk/node-config-provider": 3.338.0 + "@aws-sdk/node-http-handler": 3.338.0 + "@aws-sdk/smithy-client": 3.338.0 + "@aws-sdk/types": 3.338.0 + "@aws-sdk/url-parser": 3.338.0 + "@aws-sdk/util-base64": 3.310.0 + "@aws-sdk/util-body-length-browser": 3.310.0 + "@aws-sdk/util-body-length-node": 3.310.0 + "@aws-sdk/util-defaults-mode-browser": 3.338.0 + "@aws-sdk/util-defaults-mode-node": 3.338.0 + "@aws-sdk/util-endpoints": 3.338.0 + "@aws-sdk/util-retry": 3.338.0 + "@aws-sdk/util-user-agent-browser": 3.338.0 + "@aws-sdk/util-user-agent-node": 3.338.0 + "@aws-sdk/util-utf8": 3.310.0 + "@smithy/protocol-http": ^1.0.1 + "@smithy/types": ^1.0.0 + tslib: ^2.5.0 + checksum: 58b712b0d515ac22ce010b98f2c2fe21a5e49c65f16121998fe7dc1008ca43e7cdab576bd096c25509882732b42ef1d629db8cf43bc49f27caea56a7d1f6fa6d + languageName: node + linkType: hard + +"@aws-sdk/client-s3@npm:^3.310.0": + version: 3.338.0 + resolution: "@aws-sdk/client-s3@npm:3.338.0" dependencies: "@aws-crypto/sha1-browser": 3.0.0 "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/client-sts": 3.312.0 - "@aws-sdk/config-resolver": 3.310.0 - "@aws-sdk/credential-provider-node": 3.310.0 - "@aws-sdk/eventstream-serde-browser": 3.310.0 - "@aws-sdk/eventstream-serde-config-resolver": 3.310.0 - "@aws-sdk/eventstream-serde-node": 3.310.0 - "@aws-sdk/fetch-http-handler": 3.310.0 - "@aws-sdk/hash-blob-browser": 3.310.0 - "@aws-sdk/hash-node": 3.310.0 - "@aws-sdk/hash-stream-node": 3.310.0 - "@aws-sdk/invalid-dependency": 3.310.0 - "@aws-sdk/md5-js": 3.310.0 - "@aws-sdk/middleware-bucket-endpoint": 3.310.0 - "@aws-sdk/middleware-content-length": 3.310.0 - "@aws-sdk/middleware-endpoint": 3.310.0 - "@aws-sdk/middleware-expect-continue": 3.310.0 - "@aws-sdk/middleware-flexible-checksums": 3.310.0 - "@aws-sdk/middleware-host-header": 3.310.0 - "@aws-sdk/middleware-location-constraint": 3.310.0 - "@aws-sdk/middleware-logger": 3.310.0 - "@aws-sdk/middleware-recursion-detection": 3.310.0 - "@aws-sdk/middleware-retry": 3.310.0 - "@aws-sdk/middleware-sdk-s3": 3.310.0 - "@aws-sdk/middleware-serde": 3.310.0 - "@aws-sdk/middleware-signing": 3.310.0 - "@aws-sdk/middleware-ssec": 3.310.0 - "@aws-sdk/middleware-stack": 3.310.0 - "@aws-sdk/middleware-user-agent": 3.310.0 - "@aws-sdk/node-config-provider": 3.310.0 - "@aws-sdk/node-http-handler": 3.310.0 - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/signature-v4-multi-region": 3.310.0 - "@aws-sdk/smithy-client": 3.310.0 - "@aws-sdk/types": 3.310.0 - "@aws-sdk/url-parser": 3.310.0 + "@aws-sdk/client-sts": 3.338.0 + "@aws-sdk/config-resolver": 3.338.0 + "@aws-sdk/credential-provider-node": 3.338.0 + "@aws-sdk/eventstream-serde-browser": 3.338.0 + "@aws-sdk/eventstream-serde-config-resolver": 3.338.0 + "@aws-sdk/eventstream-serde-node": 3.338.0 + "@aws-sdk/fetch-http-handler": 3.338.0 + "@aws-sdk/hash-blob-browser": 3.338.0 + "@aws-sdk/hash-node": 3.338.0 + "@aws-sdk/hash-stream-node": 3.338.0 + "@aws-sdk/invalid-dependency": 3.338.0 + "@aws-sdk/md5-js": 3.338.0 + "@aws-sdk/middleware-bucket-endpoint": 3.338.0 + "@aws-sdk/middleware-content-length": 3.338.0 + "@aws-sdk/middleware-endpoint": 3.338.0 + "@aws-sdk/middleware-expect-continue": 3.338.0 + "@aws-sdk/middleware-flexible-checksums": 3.338.0 + "@aws-sdk/middleware-host-header": 3.338.0 + "@aws-sdk/middleware-location-constraint": 3.338.0 + "@aws-sdk/middleware-logger": 3.338.0 + "@aws-sdk/middleware-recursion-detection": 3.338.0 + "@aws-sdk/middleware-retry": 3.338.0 + "@aws-sdk/middleware-sdk-s3": 3.338.0 + "@aws-sdk/middleware-serde": 3.338.0 + "@aws-sdk/middleware-signing": 3.338.0 + "@aws-sdk/middleware-ssec": 3.338.0 + "@aws-sdk/middleware-stack": 3.338.0 + "@aws-sdk/middleware-user-agent": 3.338.0 + "@aws-sdk/node-config-provider": 3.338.0 + "@aws-sdk/node-http-handler": 3.338.0 + "@aws-sdk/signature-v4-multi-region": 3.338.0 + "@aws-sdk/smithy-client": 3.338.0 + "@aws-sdk/types": 3.338.0 + "@aws-sdk/url-parser": 3.338.0 "@aws-sdk/util-base64": 3.310.0 "@aws-sdk/util-body-length-browser": 3.310.0 "@aws-sdk/util-body-length-node": 3.310.0 - "@aws-sdk/util-defaults-mode-browser": 3.310.0 - "@aws-sdk/util-defaults-mode-node": 3.310.0 - "@aws-sdk/util-endpoints": 3.310.0 - "@aws-sdk/util-retry": 3.310.0 - "@aws-sdk/util-stream-browser": 3.310.0 - "@aws-sdk/util-stream-node": 3.310.0 - "@aws-sdk/util-user-agent-browser": 3.310.0 - "@aws-sdk/util-user-agent-node": 3.310.0 + "@aws-sdk/util-defaults-mode-browser": 3.338.0 + "@aws-sdk/util-defaults-mode-node": 3.338.0 + "@aws-sdk/util-endpoints": 3.338.0 + "@aws-sdk/util-retry": 3.338.0 + "@aws-sdk/util-stream-browser": 3.338.0 + "@aws-sdk/util-stream-node": 3.338.0 + "@aws-sdk/util-user-agent-browser": 3.338.0 + "@aws-sdk/util-user-agent-node": 3.338.0 "@aws-sdk/util-utf8": 3.310.0 - "@aws-sdk/util-waiter": 3.310.0 + "@aws-sdk/util-waiter": 3.338.0 "@aws-sdk/xml-builder": 3.310.0 + "@smithy/protocol-http": ^1.0.1 + "@smithy/types": ^1.0.0 fast-xml-parser: 4.1.2 tslib: ^2.5.0 - checksum: 20764e30d10a0280961ba45491f6b26f7ca27e430da348fa4ce257b75fe1b67d5dbf0f4e3109c9db33c8c3269ba1f62d4a2d53a45977e1271dbc189bfcc1d4ef + checksum: f9f6e3c78e382fd595eb624e58d5c296aaadc5f5f378d802daeaaee2abb8803d6fcce88fdcc8a0d693effbc915e2b87554a39cde47a5a3b21074f71396548454 languageName: node linkType: hard -"@aws-sdk/client-sqs@npm:^3.208.0": - version: 3.312.0 - resolution: "@aws-sdk/client-sqs@npm:3.312.0" +"@aws-sdk/client-sqs@npm:^3.310.0": + version: 3.338.0 + resolution: "@aws-sdk/client-sqs@npm:3.338.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/client-sts": 3.312.0 - "@aws-sdk/config-resolver": 3.310.0 - "@aws-sdk/credential-provider-node": 3.310.0 - "@aws-sdk/fetch-http-handler": 3.310.0 - "@aws-sdk/hash-node": 3.310.0 - "@aws-sdk/invalid-dependency": 3.310.0 - "@aws-sdk/md5-js": 3.310.0 - "@aws-sdk/middleware-content-length": 3.310.0 - "@aws-sdk/middleware-endpoint": 3.310.0 - "@aws-sdk/middleware-host-header": 3.310.0 - "@aws-sdk/middleware-logger": 3.310.0 - "@aws-sdk/middleware-recursion-detection": 3.310.0 - "@aws-sdk/middleware-retry": 3.310.0 - "@aws-sdk/middleware-sdk-sqs": 3.310.0 - "@aws-sdk/middleware-serde": 3.310.0 - "@aws-sdk/middleware-signing": 3.310.0 - "@aws-sdk/middleware-stack": 3.310.0 - "@aws-sdk/middleware-user-agent": 3.310.0 - "@aws-sdk/node-config-provider": 3.310.0 - "@aws-sdk/node-http-handler": 3.310.0 - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/smithy-client": 3.310.0 - "@aws-sdk/types": 3.310.0 - "@aws-sdk/url-parser": 3.310.0 + "@aws-sdk/client-sts": 3.338.0 + "@aws-sdk/config-resolver": 3.338.0 + "@aws-sdk/credential-provider-node": 3.338.0 + "@aws-sdk/fetch-http-handler": 3.338.0 + "@aws-sdk/hash-node": 3.338.0 + "@aws-sdk/invalid-dependency": 3.338.0 + "@aws-sdk/md5-js": 3.338.0 + "@aws-sdk/middleware-content-length": 3.338.0 + "@aws-sdk/middleware-endpoint": 3.338.0 + "@aws-sdk/middleware-host-header": 3.338.0 + "@aws-sdk/middleware-logger": 3.338.0 + "@aws-sdk/middleware-recursion-detection": 3.338.0 + "@aws-sdk/middleware-retry": 3.338.0 + "@aws-sdk/middleware-sdk-sqs": 3.338.0 + "@aws-sdk/middleware-serde": 3.338.0 + "@aws-sdk/middleware-signing": 3.338.0 + "@aws-sdk/middleware-stack": 3.338.0 + "@aws-sdk/middleware-user-agent": 3.338.0 + "@aws-sdk/node-config-provider": 3.338.0 + "@aws-sdk/node-http-handler": 3.338.0 + "@aws-sdk/smithy-client": 3.338.0 + "@aws-sdk/types": 3.338.0 + "@aws-sdk/url-parser": 3.338.0 "@aws-sdk/util-base64": 3.310.0 "@aws-sdk/util-body-length-browser": 3.310.0 "@aws-sdk/util-body-length-node": 3.310.0 - "@aws-sdk/util-defaults-mode-browser": 3.310.0 - "@aws-sdk/util-defaults-mode-node": 3.310.0 - "@aws-sdk/util-endpoints": 3.310.0 - "@aws-sdk/util-retry": 3.310.0 - "@aws-sdk/util-user-agent-browser": 3.310.0 - "@aws-sdk/util-user-agent-node": 3.310.0 + "@aws-sdk/util-defaults-mode-browser": 3.338.0 + "@aws-sdk/util-defaults-mode-node": 3.338.0 + "@aws-sdk/util-endpoints": 3.338.0 + "@aws-sdk/util-retry": 3.338.0 + "@aws-sdk/util-user-agent-browser": 3.338.0 + "@aws-sdk/util-user-agent-node": 3.338.0 "@aws-sdk/util-utf8": 3.310.0 + "@smithy/protocol-http": ^1.0.1 + "@smithy/types": ^1.0.0 fast-xml-parser: 4.1.2 tslib: ^2.5.0 - checksum: 0cc2c0cb6b835d5dd29ff0f146fd4f7d4d7501ebdd419144a704a6092a029e774f580a6dcb6e668779fe86c589b6df884ef09f1866d3d28abbeb1787fe7eb58e + checksum: 50912c1b0dfc42e1a0c1aac22bef1be7ea8879484b6b13aa8a753f2da5a435d1d08b33013b34bab73fb6e290816a80ea2808e465844873bcaa627ef347a6d848 languageName: node linkType: hard -"@aws-sdk/client-sso-oidc@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/client-sso-oidc@npm:3.310.0" +"@aws-sdk/client-sso-oidc@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/client-sso-oidc@npm:3.338.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/config-resolver": 3.310.0 - "@aws-sdk/fetch-http-handler": 3.310.0 - "@aws-sdk/hash-node": 3.310.0 - "@aws-sdk/invalid-dependency": 3.310.0 - "@aws-sdk/middleware-content-length": 3.310.0 - "@aws-sdk/middleware-endpoint": 3.310.0 - "@aws-sdk/middleware-host-header": 3.310.0 - "@aws-sdk/middleware-logger": 3.310.0 - "@aws-sdk/middleware-recursion-detection": 3.310.0 - "@aws-sdk/middleware-retry": 3.310.0 - "@aws-sdk/middleware-serde": 3.310.0 - "@aws-sdk/middleware-stack": 3.310.0 - "@aws-sdk/middleware-user-agent": 3.310.0 - "@aws-sdk/node-config-provider": 3.310.0 - "@aws-sdk/node-http-handler": 3.310.0 - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/smithy-client": 3.310.0 - "@aws-sdk/types": 3.310.0 - "@aws-sdk/url-parser": 3.310.0 + "@aws-sdk/config-resolver": 3.338.0 + "@aws-sdk/fetch-http-handler": 3.338.0 + "@aws-sdk/hash-node": 3.338.0 + "@aws-sdk/invalid-dependency": 3.338.0 + "@aws-sdk/middleware-content-length": 3.338.0 + "@aws-sdk/middleware-endpoint": 3.338.0 + "@aws-sdk/middleware-host-header": 3.338.0 + "@aws-sdk/middleware-logger": 3.338.0 + "@aws-sdk/middleware-recursion-detection": 3.338.0 + "@aws-sdk/middleware-retry": 3.338.0 + "@aws-sdk/middleware-serde": 3.338.0 + "@aws-sdk/middleware-stack": 3.338.0 + "@aws-sdk/middleware-user-agent": 3.338.0 + "@aws-sdk/node-config-provider": 3.338.0 + "@aws-sdk/node-http-handler": 3.338.0 + "@aws-sdk/smithy-client": 3.338.0 + "@aws-sdk/types": 3.338.0 + "@aws-sdk/url-parser": 3.338.0 "@aws-sdk/util-base64": 3.310.0 "@aws-sdk/util-body-length-browser": 3.310.0 "@aws-sdk/util-body-length-node": 3.310.0 - "@aws-sdk/util-defaults-mode-browser": 3.310.0 - "@aws-sdk/util-defaults-mode-node": 3.310.0 - "@aws-sdk/util-endpoints": 3.310.0 - "@aws-sdk/util-retry": 3.310.0 - "@aws-sdk/util-user-agent-browser": 3.310.0 - "@aws-sdk/util-user-agent-node": 3.310.0 + "@aws-sdk/util-defaults-mode-browser": 3.338.0 + "@aws-sdk/util-defaults-mode-node": 3.338.0 + "@aws-sdk/util-endpoints": 3.338.0 + "@aws-sdk/util-retry": 3.338.0 + "@aws-sdk/util-user-agent-browser": 3.338.0 + "@aws-sdk/util-user-agent-node": 3.338.0 "@aws-sdk/util-utf8": 3.310.0 + "@smithy/protocol-http": ^1.0.1 + "@smithy/types": ^1.0.0 tslib: ^2.5.0 - checksum: 7e4a013983978a02e390b621d76716c1649eb7b8889ad239f082b737ef204182879c4ab735a702ebd9c9a5a406c1fefd16c53d7f327db2cbaea88ebbf9bc6123 + checksum: bd4d42db2ccbb4e045fc22a59e40c93ddd8a718cc51cddedf7bb5aedf46c5668a548cccd39fb01f495d0076f68fa0a3b0f45f1f0fff1002828680a8127aa32a3 languageName: node linkType: hard -"@aws-sdk/client-sso@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/client-sso@npm:3.310.0" +"@aws-sdk/client-sso@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/client-sso@npm:3.338.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/config-resolver": 3.310.0 - "@aws-sdk/fetch-http-handler": 3.310.0 - "@aws-sdk/hash-node": 3.310.0 - "@aws-sdk/invalid-dependency": 3.310.0 - "@aws-sdk/middleware-content-length": 3.310.0 - "@aws-sdk/middleware-endpoint": 3.310.0 - "@aws-sdk/middleware-host-header": 3.310.0 - "@aws-sdk/middleware-logger": 3.310.0 - "@aws-sdk/middleware-recursion-detection": 3.310.0 - "@aws-sdk/middleware-retry": 3.310.0 - "@aws-sdk/middleware-serde": 3.310.0 - "@aws-sdk/middleware-stack": 3.310.0 - "@aws-sdk/middleware-user-agent": 3.310.0 - "@aws-sdk/node-config-provider": 3.310.0 - "@aws-sdk/node-http-handler": 3.310.0 - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/smithy-client": 3.310.0 - "@aws-sdk/types": 3.310.0 - "@aws-sdk/url-parser": 3.310.0 + "@aws-sdk/config-resolver": 3.338.0 + "@aws-sdk/fetch-http-handler": 3.338.0 + "@aws-sdk/hash-node": 3.338.0 + "@aws-sdk/invalid-dependency": 3.338.0 + "@aws-sdk/middleware-content-length": 3.338.0 + "@aws-sdk/middleware-endpoint": 3.338.0 + "@aws-sdk/middleware-host-header": 3.338.0 + "@aws-sdk/middleware-logger": 3.338.0 + "@aws-sdk/middleware-recursion-detection": 3.338.0 + "@aws-sdk/middleware-retry": 3.338.0 + "@aws-sdk/middleware-serde": 3.338.0 + "@aws-sdk/middleware-stack": 3.338.0 + "@aws-sdk/middleware-user-agent": 3.338.0 + "@aws-sdk/node-config-provider": 3.338.0 + "@aws-sdk/node-http-handler": 3.338.0 + "@aws-sdk/smithy-client": 3.338.0 + "@aws-sdk/types": 3.338.0 + "@aws-sdk/url-parser": 3.338.0 "@aws-sdk/util-base64": 3.310.0 "@aws-sdk/util-body-length-browser": 3.310.0 "@aws-sdk/util-body-length-node": 3.310.0 - "@aws-sdk/util-defaults-mode-browser": 3.310.0 - "@aws-sdk/util-defaults-mode-node": 3.310.0 - "@aws-sdk/util-endpoints": 3.310.0 - "@aws-sdk/util-retry": 3.310.0 - "@aws-sdk/util-user-agent-browser": 3.310.0 - "@aws-sdk/util-user-agent-node": 3.310.0 + "@aws-sdk/util-defaults-mode-browser": 3.338.0 + "@aws-sdk/util-defaults-mode-node": 3.338.0 + "@aws-sdk/util-endpoints": 3.338.0 + "@aws-sdk/util-retry": 3.338.0 + "@aws-sdk/util-user-agent-browser": 3.338.0 + "@aws-sdk/util-user-agent-node": 3.338.0 "@aws-sdk/util-utf8": 3.310.0 + "@smithy/protocol-http": ^1.0.1 + "@smithy/types": ^1.0.0 tslib: ^2.5.0 - checksum: 5d7461e2102634c336e3748f91f51e9e53c8dc2fa50441535fad8f6926f368131224935b958b05a071d9c61357adfc8db885ac2adb5be9cee94243cecc3454d3 + checksum: c4980aff00184a4dc70ac20862b2705a2eff570776c5be8dc014620d69f20d12c19e6feb08d11db14e1b21a38040813997bdd09f02f478e2e95037c483367690 languageName: node linkType: hard -"@aws-sdk/client-sts@npm:3.312.0, @aws-sdk/client-sts@npm:^3.208.0": - version: 3.312.0 - resolution: "@aws-sdk/client-sts@npm:3.312.0" +"@aws-sdk/client-sts@npm:3.338.0, @aws-sdk/client-sts@npm:^3.310.0": + version: 3.338.0 + resolution: "@aws-sdk/client-sts@npm:3.338.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/config-resolver": 3.310.0 - "@aws-sdk/credential-provider-node": 3.310.0 - "@aws-sdk/fetch-http-handler": 3.310.0 - "@aws-sdk/hash-node": 3.310.0 - "@aws-sdk/invalid-dependency": 3.310.0 - "@aws-sdk/middleware-content-length": 3.310.0 - "@aws-sdk/middleware-endpoint": 3.310.0 - "@aws-sdk/middleware-host-header": 3.310.0 - "@aws-sdk/middleware-logger": 3.310.0 - "@aws-sdk/middleware-recursion-detection": 3.310.0 - "@aws-sdk/middleware-retry": 3.310.0 - "@aws-sdk/middleware-sdk-sts": 3.310.0 - "@aws-sdk/middleware-serde": 3.310.0 - "@aws-sdk/middleware-signing": 3.310.0 - "@aws-sdk/middleware-stack": 3.310.0 - "@aws-sdk/middleware-user-agent": 3.310.0 - "@aws-sdk/node-config-provider": 3.310.0 - "@aws-sdk/node-http-handler": 3.310.0 - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/smithy-client": 3.310.0 - "@aws-sdk/types": 3.310.0 - "@aws-sdk/url-parser": 3.310.0 + "@aws-sdk/config-resolver": 3.338.0 + "@aws-sdk/credential-provider-node": 3.338.0 + "@aws-sdk/fetch-http-handler": 3.338.0 + "@aws-sdk/hash-node": 3.338.0 + "@aws-sdk/invalid-dependency": 3.338.0 + "@aws-sdk/middleware-content-length": 3.338.0 + "@aws-sdk/middleware-endpoint": 3.338.0 + "@aws-sdk/middleware-host-header": 3.338.0 + "@aws-sdk/middleware-logger": 3.338.0 + "@aws-sdk/middleware-recursion-detection": 3.338.0 + "@aws-sdk/middleware-retry": 3.338.0 + "@aws-sdk/middleware-sdk-sts": 3.338.0 + "@aws-sdk/middleware-serde": 3.338.0 + "@aws-sdk/middleware-signing": 3.338.0 + "@aws-sdk/middleware-stack": 3.338.0 + "@aws-sdk/middleware-user-agent": 3.338.0 + "@aws-sdk/node-config-provider": 3.338.0 + "@aws-sdk/node-http-handler": 3.338.0 + "@aws-sdk/smithy-client": 3.338.0 + "@aws-sdk/types": 3.338.0 + "@aws-sdk/url-parser": 3.338.0 "@aws-sdk/util-base64": 3.310.0 "@aws-sdk/util-body-length-browser": 3.310.0 "@aws-sdk/util-body-length-node": 3.310.0 - "@aws-sdk/util-defaults-mode-browser": 3.310.0 - "@aws-sdk/util-defaults-mode-node": 3.310.0 - "@aws-sdk/util-endpoints": 3.310.0 - "@aws-sdk/util-retry": 3.310.0 - "@aws-sdk/util-user-agent-browser": 3.310.0 - "@aws-sdk/util-user-agent-node": 3.310.0 + "@aws-sdk/util-defaults-mode-browser": 3.338.0 + "@aws-sdk/util-defaults-mode-node": 3.338.0 + "@aws-sdk/util-endpoints": 3.338.0 + "@aws-sdk/util-retry": 3.338.0 + "@aws-sdk/util-user-agent-browser": 3.338.0 + "@aws-sdk/util-user-agent-node": 3.338.0 "@aws-sdk/util-utf8": 3.310.0 + "@smithy/protocol-http": ^1.0.1 + "@smithy/types": ^1.0.0 fast-xml-parser: 4.1.2 tslib: ^2.5.0 - checksum: ad0b444605cbb53caf7ef2c637a79923adeca133d8fc74ee45208828bc8546ae69a2738ce77f6aae376c53d41e2f59ec7703d4a3c364066cacef06427a746e8c + checksum: 879004560b0f92c9c7708e3ee574ea5822e0015d7e469edd07cf374e2a72924a50184086c00d31506ed44c80c209c5af5680ae00187aa0ff36352265ef0ecdf3 languageName: node linkType: hard -"@aws-sdk/config-resolver@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/config-resolver@npm:3.310.0" +"@aws-sdk/config-resolver@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/config-resolver@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 "@aws-sdk/util-config-provider": 3.310.0 - "@aws-sdk/util-middleware": 3.310.0 + "@aws-sdk/util-middleware": 3.338.0 tslib: ^2.5.0 - checksum: ec80bc867304344d04b6d6bbf369234e7d296540ffb988c3f29bf96ea5e3ac959f86a699c8eecef3fea87491fd413aaed3137e4f7a89544cceedf09cce1c9a15 + checksum: d9b204555405869474ad6e37db6797ab0e829b0e6598fe3aa75022acb19eaaf95d011844396b7abf33a01af24eeb6fe67283f4c3a33aa7abd5e4f651dd964ffa languageName: node linkType: hard -"@aws-sdk/credential-provider-cognito-identity@npm:3.312.0": - version: 3.312.0 - resolution: "@aws-sdk/credential-provider-cognito-identity@npm:3.312.0" +"@aws-sdk/credential-provider-cognito-identity@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/credential-provider-cognito-identity@npm:3.338.0" dependencies: - "@aws-sdk/client-cognito-identity": 3.312.0 - "@aws-sdk/property-provider": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/client-cognito-identity": 3.338.0 + "@aws-sdk/property-provider": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 4acd9f7bbd8cb9adabbd9b6465fe81f7bd47d5808b3a5fd3352e4e573a8ff718e56684e67631649f72d01078dc858278de1b5c227b8557d948d4c43abde99561 + checksum: bdd8af7416e467a2abf21a09069797e2acf0f61b8475635b51aff395e10da323d964ba963f020669eed69bc20c0524e8eec5c804d07cc2d89c121d636b564804 languageName: node linkType: hard -"@aws-sdk/credential-provider-env@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/credential-provider-env@npm:3.310.0" +"@aws-sdk/credential-provider-env@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/credential-provider-env@npm:3.338.0" dependencies: - "@aws-sdk/property-provider": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/property-provider": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 646e634e6f8429c1984475100a60066dd5d0c085b3e170dc0c05c55c824edb3b04d4c40496ab4318e9586b9ca1db0b20090d26919b0273351c82372a12cd9958 + checksum: b28e2ad7850b88ea050a3859d262ce42be09423aa56c9da645407835f669874e8a7ee0c71b4176b86dcf00676641d1bcd3f4c4620dcafde505af399dc271c7b1 languageName: node linkType: hard -"@aws-sdk/credential-provider-imds@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/credential-provider-imds@npm:3.310.0" +"@aws-sdk/credential-provider-imds@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/credential-provider-imds@npm:3.338.0" dependencies: - "@aws-sdk/node-config-provider": 3.310.0 - "@aws-sdk/property-provider": 3.310.0 - "@aws-sdk/types": 3.310.0 - "@aws-sdk/url-parser": 3.310.0 + "@aws-sdk/node-config-provider": 3.338.0 + "@aws-sdk/property-provider": 3.338.0 + "@aws-sdk/types": 3.338.0 + "@aws-sdk/url-parser": 3.338.0 tslib: ^2.5.0 - checksum: 24915e2f108e37bef21b9bec07f7ab38f25bf3ed55c55ad318ae8e030e042123980855b977c13714580232d2c0a514e71efd61848e68c221716c2110c160ab13 + checksum: 4db0137b7a6a1825957b1f0d9744aa5b1ca369cfa39d00ea120e8c5b08a3d904cd1970a96be8ba852b92d1dd271827469def3c08f09ed898a2e8d7ac15b90874 languageName: node linkType: hard -"@aws-sdk/credential-provider-ini@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/credential-provider-ini@npm:3.310.0" +"@aws-sdk/credential-provider-ini@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/credential-provider-ini@npm:3.338.0" dependencies: - "@aws-sdk/credential-provider-env": 3.310.0 - "@aws-sdk/credential-provider-imds": 3.310.0 - "@aws-sdk/credential-provider-process": 3.310.0 - "@aws-sdk/credential-provider-sso": 3.310.0 - "@aws-sdk/credential-provider-web-identity": 3.310.0 - "@aws-sdk/property-provider": 3.310.0 - "@aws-sdk/shared-ini-file-loader": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/credential-provider-env": 3.338.0 + "@aws-sdk/credential-provider-imds": 3.338.0 + "@aws-sdk/credential-provider-process": 3.338.0 + "@aws-sdk/credential-provider-sso": 3.338.0 + "@aws-sdk/credential-provider-web-identity": 3.338.0 + "@aws-sdk/property-provider": 3.338.0 + "@aws-sdk/shared-ini-file-loader": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 9d0adc90a942680ccc1aa135b1d5b42a32a1db1aee0a1d1cfeac2f20347b28a5b8a33bb982eec9e2ff1204ffacfff3cc4b1065cdd11f035edcde4142ff3e3125 + checksum: cfef6a065b69c53ea2b5de81d05b9b37de26441ae813b9d11aa2985a18caa564938058ef527e0c5e10f27fd1d910c0e16f86681f6880e96dffef379e8751eb6d languageName: node linkType: hard -"@aws-sdk/credential-provider-node@npm:3.310.0, @aws-sdk/credential-provider-node@npm:^3.208.0": - version: 3.310.0 - resolution: "@aws-sdk/credential-provider-node@npm:3.310.0" +"@aws-sdk/credential-provider-node@npm:3.338.0, @aws-sdk/credential-provider-node@npm:^3.310.0": + version: 3.338.0 + resolution: "@aws-sdk/credential-provider-node@npm:3.338.0" dependencies: - "@aws-sdk/credential-provider-env": 3.310.0 - "@aws-sdk/credential-provider-imds": 3.310.0 - "@aws-sdk/credential-provider-ini": 3.310.0 - "@aws-sdk/credential-provider-process": 3.310.0 - "@aws-sdk/credential-provider-sso": 3.310.0 - "@aws-sdk/credential-provider-web-identity": 3.310.0 - "@aws-sdk/property-provider": 3.310.0 - "@aws-sdk/shared-ini-file-loader": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/credential-provider-env": 3.338.0 + "@aws-sdk/credential-provider-imds": 3.338.0 + "@aws-sdk/credential-provider-ini": 3.338.0 + "@aws-sdk/credential-provider-process": 3.338.0 + "@aws-sdk/credential-provider-sso": 3.338.0 + "@aws-sdk/credential-provider-web-identity": 3.338.0 + "@aws-sdk/property-provider": 3.338.0 + "@aws-sdk/shared-ini-file-loader": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 893aacd840a69363e11cbfb50c915aa3f515f40d6f5a93018f2fd1d7775af40d2a2fd083422aabc817f433e0f89fe5cdaaea7059b0ec59e8f38c78c97b35995a + checksum: 871d1cd910a97aba33eb82053d7fd9f1cd126d31460a3622174e1ce85588d3d26e1c6f76a1a2e689e41aeba3dc748dd23b1d92af33a2b621c7b6afefaaf2559c languageName: node linkType: hard -"@aws-sdk/credential-provider-process@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/credential-provider-process@npm:3.310.0" +"@aws-sdk/credential-provider-process@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/credential-provider-process@npm:3.338.0" dependencies: - "@aws-sdk/property-provider": 3.310.0 - "@aws-sdk/shared-ini-file-loader": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/property-provider": 3.338.0 + "@aws-sdk/shared-ini-file-loader": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 12c4ab1f34d5a045d56ca22bc6c834292da15d518129133babcbede056adb46f4e898489e1b54e7e5ee3472d1116882217f5a29af0a46cc40d2f3aa00ef6767f + checksum: 5af4d43e7dc5d85f9833dbe65e190ad23b9f360eb681484779106a435a9af08b0a75e42f71c637c4c7ab4443c7f5e3d896af7d4a7ac7971eab42aec426018279 languageName: node linkType: hard -"@aws-sdk/credential-provider-sso@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/credential-provider-sso@npm:3.310.0" +"@aws-sdk/credential-provider-sso@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/credential-provider-sso@npm:3.338.0" dependencies: - "@aws-sdk/client-sso": 3.310.0 - "@aws-sdk/property-provider": 3.310.0 - "@aws-sdk/shared-ini-file-loader": 3.310.0 - "@aws-sdk/token-providers": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/client-sso": 3.338.0 + "@aws-sdk/property-provider": 3.338.0 + "@aws-sdk/shared-ini-file-loader": 3.338.0 + "@aws-sdk/token-providers": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 595c3f393430e1c9ddb0b276b605e87a8a6d461fe5d7bfa7e9b033fd06f3d5bcb1f4fe6b74e7eb5fa38d1d88181f8be5398bb3c1a53ae18caada9a59eed1ba21 + checksum: 35fe15cede3777e3c30770c460ba96c7aa80f4856ef80ab6bcc6788f955ea1c1f745248d53f4c5eda17774e42066a5f23f3c71fa7a0e312cc3235044dde022fa languageName: node linkType: hard -"@aws-sdk/credential-provider-web-identity@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/credential-provider-web-identity@npm:3.310.0" +"@aws-sdk/credential-provider-web-identity@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/credential-provider-web-identity@npm:3.338.0" dependencies: - "@aws-sdk/property-provider": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/property-provider": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 62dd9362bb48e010cb84dfcb92461478b2d1fa830e47e078a9bd074999eb231b0ef4e273e585fce5ed0135768b90bafcbe9ca5df83fc6c0bc5d227ec74271a82 + checksum: aa61393398ff0d06ee83a727f8d967aa7585a28482a6423947f2bce86b8163bd97d2d6420a126e5ad1d5d00aa5bcb3128492412f0d7dfca128179f0600000183 languageName: node linkType: hard -"@aws-sdk/credential-providers@npm:^3.208.0": - version: 3.312.0 - resolution: "@aws-sdk/credential-providers@npm:3.312.0" +"@aws-sdk/credential-providers@npm:^3.310.0": + version: 3.338.0 + resolution: "@aws-sdk/credential-providers@npm:3.338.0" dependencies: - "@aws-sdk/client-cognito-identity": 3.312.0 - "@aws-sdk/client-sso": 3.310.0 - "@aws-sdk/client-sts": 3.312.0 - "@aws-sdk/credential-provider-cognito-identity": 3.312.0 - "@aws-sdk/credential-provider-env": 3.310.0 - "@aws-sdk/credential-provider-imds": 3.310.0 - "@aws-sdk/credential-provider-ini": 3.310.0 - "@aws-sdk/credential-provider-node": 3.310.0 - "@aws-sdk/credential-provider-process": 3.310.0 - "@aws-sdk/credential-provider-sso": 3.310.0 - "@aws-sdk/credential-provider-web-identity": 3.310.0 - "@aws-sdk/property-provider": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/client-cognito-identity": 3.338.0 + "@aws-sdk/client-sso": 3.338.0 + "@aws-sdk/client-sts": 3.338.0 + "@aws-sdk/credential-provider-cognito-identity": 3.338.0 + "@aws-sdk/credential-provider-env": 3.338.0 + "@aws-sdk/credential-provider-imds": 3.338.0 + "@aws-sdk/credential-provider-ini": 3.338.0 + "@aws-sdk/credential-provider-node": 3.338.0 + "@aws-sdk/credential-provider-process": 3.338.0 + "@aws-sdk/credential-provider-sso": 3.338.0 + "@aws-sdk/credential-provider-web-identity": 3.338.0 + "@aws-sdk/property-provider": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: d47501b81e3f37c50110a12f58491407c95bebfa341ed80040aeefab236a3496dc33100da244e1e4467d2e2d62be19faec04f2e52a236a5c5ec2e1feeb12ceee + checksum: 3001b8c829d1624ffb3ab75284bfced8e9c2d991032eae1369713bb190847019dd0061728b705a6e98c9bd152db3174c2df772b437bf0f1ca69f3554d4826835 languageName: node linkType: hard -"@aws-sdk/eventstream-codec@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/eventstream-codec@npm:3.310.0" +"@aws-sdk/eventstream-codec@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/eventstream-codec@npm:3.338.0" dependencies: "@aws-crypto/crc32": 3.0.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 "@aws-sdk/util-hex-encoding": 3.310.0 tslib: ^2.5.0 - checksum: 2866186a5303bb8b9151ea69f22bace420317c4ec3b5c9aa0beb9bd007aca419a519be2d911b8119ddfd1c0a8358cc9e0f957ca3a460b3009846e0e5517a8f7a + checksum: 6fe39c223c6c95b7e8491fd4835abe9a43e37f78dd595b619337be2083be7af77730834f2f0509745a9b9678a13b0ee0a9021913bfef48ed357b54d42e1f6113 languageName: node linkType: hard -"@aws-sdk/eventstream-serde-browser@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/eventstream-serde-browser@npm:3.310.0" +"@aws-sdk/eventstream-serde-browser@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/eventstream-serde-browser@npm:3.338.0" dependencies: - "@aws-sdk/eventstream-serde-universal": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/eventstream-serde-universal": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 10a8dc5999c3f8f683ef399c8866d274232e235bf526c481da2527c24e23836e362c647c92103dcabdf52107b8fd0c46ae8e9f8d2f79741f198022cd94b150f1 + checksum: d565058ffb42d60e870a2bce36495a595de8b706e85b3a4bbc5ec5a63c57b2b8716f7ced83ed7a5a231b13becf7a28979720d85810d45ab7eafb45a9fa7a43d6 languageName: node linkType: hard -"@aws-sdk/eventstream-serde-config-resolver@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/eventstream-serde-config-resolver@npm:3.310.0" +"@aws-sdk/eventstream-serde-config-resolver@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/eventstream-serde-config-resolver@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 9ad39115d8bd163fe441fa8128e102c1e6157890c7731d7ab797b63a636f378f30a2695adcf41b58f52b6bfd71b68c2bafe51d1cf4f984b124746341d13ced6b + checksum: 0535397aa3ce6e655fffbad71b68a42dd1bbf2f8d6fb895108972f38756525a5fa5e033ed25b251e0a74610506c139baadca07719f98254dc75a9c7cdacdb7d0 languageName: node linkType: hard -"@aws-sdk/eventstream-serde-node@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/eventstream-serde-node@npm:3.310.0" +"@aws-sdk/eventstream-serde-node@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/eventstream-serde-node@npm:3.338.0" dependencies: - "@aws-sdk/eventstream-serde-universal": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/eventstream-serde-universal": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 1a695e39e5bbd4088d5790c8b4389dd635b7f6300892868d35e8711ef7ea5c1f2f50886c9ac55de5eae9619c49fe864c6e530e575a06231300294211a36827b3 + checksum: 3804f61d220105122dbd1ad7e20a453f7278ff70927ec0fd941a48c07fb0233af5a6ba29b6cbfd34ea4cd76c2ac639b51d166d0a7e5bd4bc0d7fa7c4930ee0e1 languageName: node linkType: hard -"@aws-sdk/eventstream-serde-universal@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/eventstream-serde-universal@npm:3.310.0" +"@aws-sdk/eventstream-serde-universal@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/eventstream-serde-universal@npm:3.338.0" dependencies: - "@aws-sdk/eventstream-codec": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/eventstream-codec": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 10ce20184cdfd826600f610418e07add4e70073470cf23a5b3b8b4ea479ab096eb70c6eeb9e87bcd30e040270b3c0519fe187aad3363c85bc357a048014a8de4 + checksum: a105442ca33e1eec1091f64c8433a2715e613a963bf9ffc905f1cf5867add67062b43c900651b3decf302098fdcbd95c845688baf1d33e41b8024acec5414f44 languageName: node linkType: hard -"@aws-sdk/fetch-http-handler@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/fetch-http-handler@npm:3.310.0" +"@aws-sdk/fetch-http-handler@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/fetch-http-handler@npm:3.338.0" dependencies: - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/querystring-builder": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/protocol-http": 3.338.0 + "@aws-sdk/querystring-builder": 3.338.0 + "@aws-sdk/types": 3.338.0 "@aws-sdk/util-base64": 3.310.0 tslib: ^2.5.0 - checksum: 5daa78ee3e2a0a6bd07c3b8bc658ebd88a063b17025ec23454c2eb433859972d60a550fdc62969754488c3f4d624fbf3e758af8ea891c994998deca0f8e3903e + checksum: db96ad7a62373df8c394105f0618a9c01d9ddafaa2665f87f08c595f4b0bdc5d0388c44770d6e06268e6dda6944ff43fb5f2f15212209027439af6b3225dc4e3 languageName: node linkType: hard -"@aws-sdk/hash-blob-browser@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/hash-blob-browser@npm:3.310.0" +"@aws-sdk/hash-blob-browser@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/hash-blob-browser@npm:3.338.0" dependencies: "@aws-sdk/chunked-blob-reader": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 58908f51a89f61b5c0ed036beeda58d7e54d1385ca56447c057569671b110be0dad2bec4618daa35a8170c8b3e0e193bd473f695d0be269ec2dd06915bcaa9b9 + checksum: 089efa923647c4c7b62fa1ff590c93044bdb9864a250c96a3bc1fa812add2b87b7e52b750076d4e1d416cd17a69b99ec233d87b8a829ce35896458c3b160969a languageName: node linkType: hard -"@aws-sdk/hash-node@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/hash-node@npm:3.310.0" +"@aws-sdk/hash-node@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/hash-node@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 "@aws-sdk/util-buffer-from": 3.310.0 "@aws-sdk/util-utf8": 3.310.0 tslib: ^2.5.0 - checksum: 379c04c78679d68730272b89fa397cdfcd444ae2f21d7dc51953e9885842469de40593efbb86b2399342e022b2ba17926841ef0a9fb108809296b2df416226c1 + checksum: f45f263fbdd636e882ddca5a34b7f636c0416b77151dd53c61c91fc6048cd3a505b54bc390d5f31a161b72baeeb36358fbc6d0a710dabfa05d64b4c9ee89e05e languageName: node linkType: hard -"@aws-sdk/hash-stream-node@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/hash-stream-node@npm:3.310.0" +"@aws-sdk/hash-stream-node@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/hash-stream-node@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 "@aws-sdk/util-utf8": 3.310.0 tslib: ^2.5.0 - checksum: 42fe6f8eddd67565019d935b109e9f3acf0eacfd940712859e718db8f1ca4550c305f0fc4dad9944624ea10e0ff7e15f895d13cce0cdcf5c614d3bff39263ecf + checksum: 429c3b9358965d173553ffdb47e4b3a8fa9da6148c640ee9559bc36fd14dd97e71e0d9464ebf4ecd1e0445251055e6212365525eec985c05a72e4b13416e5354 languageName: node linkType: hard -"@aws-sdk/invalid-dependency@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/invalid-dependency@npm:3.310.0" +"@aws-sdk/invalid-dependency@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/invalid-dependency@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: e38d09615e273617583e845b2cd3683c9d27d54234a98bec7da1cf959107329f73e62b322479415155016ed62c7d849cd6542d6e9e33572f6ed542013c15821c + checksum: d240b2dab9a3ec46537429ad2e857dfde18d31f345bb30527739cfcf42cbb91d5b77c6d8caf751317506aa5e5912d8dc8be3684714d8a266cec91ab34a90c70a languageName: node linkType: hard @@ -1088,12 +1184,12 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/lib-storage@npm:^3.208.0": - version: 3.312.0 - resolution: "@aws-sdk/lib-storage@npm:3.312.0" +"@aws-sdk/lib-storage@npm:^3.310.0": + version: 3.338.0 + resolution: "@aws-sdk/lib-storage@npm:3.338.0" dependencies: - "@aws-sdk/middleware-endpoint": 3.310.0 - "@aws-sdk/smithy-client": 3.310.0 + "@aws-sdk/middleware-endpoint": 3.338.0 + "@aws-sdk/smithy-client": 3.338.0 buffer: 5.6.0 events: 3.3.0 stream-browserify: 3.0.0 @@ -1101,391 +1197,391 @@ __metadata: peerDependencies: "@aws-sdk/abort-controller": ^3.0.0 "@aws-sdk/client-s3": ^3.0.0 - checksum: ce09963885a749e6347ffe8d2ea94e2572629f31041f7859f71d98436ff863822862c13c2c465af5a11aacc3193d0c599f19d455b8251ebcbe95fc44eba1cd0e + checksum: 642322da53789d7bc2f2965d2da6626e85a4fe65480e8665e287ee21e92ea3d6711a958e4b8dd3b22f61d6fcc547b8194edf5e98aa6bca2919ad874a96d0bdc8 languageName: node linkType: hard -"@aws-sdk/md5-js@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/md5-js@npm:3.310.0" +"@aws-sdk/md5-js@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/md5-js@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 "@aws-sdk/util-utf8": 3.310.0 tslib: ^2.5.0 - checksum: 1939591f5f384e55ce9d610cbf3e8ae25e76c14489385ef73ee0c674b641351820d17e2406943e2b3ee4a3736d280256f2b79bb381e18e78440faf74d4ca04cf + checksum: 851376107748918c92f66ef2c087dc562c9684f0dd93ad84e5454aa8a87244e31c8ab639fa06a1561cf0b6fa38110256c8228abe403d821c6aef4e22e2c3a7bc languageName: node linkType: hard -"@aws-sdk/middleware-bucket-endpoint@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/middleware-bucket-endpoint@npm:3.310.0" +"@aws-sdk/middleware-bucket-endpoint@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/middleware-bucket-endpoint@npm:3.338.0" dependencies: - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/protocol-http": 3.338.0 + "@aws-sdk/types": 3.338.0 "@aws-sdk/util-arn-parser": 3.310.0 "@aws-sdk/util-config-provider": 3.310.0 tslib: ^2.5.0 - checksum: cf300c0226a649bdd7128c5c44ff03bac58119390c8bf82a712094e95c2df4c0b1693a74256968294d8ad397828fb2f7d5f0d9355c08d1d67a24888255d6dfd2 + checksum: 76acf178b8502b7dc91a59eca0a9a0217428d2d340ca8b24d20e577eec499e1c661c8af9ff8ac3ff8c6d57a86fa360a921d4f23df1f01eee9e23756059a34b62 languageName: node linkType: hard -"@aws-sdk/middleware-content-length@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/middleware-content-length@npm:3.310.0" +"@aws-sdk/middleware-content-length@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/middleware-content-length@npm:3.338.0" dependencies: - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/protocol-http": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 66977eac6aa9ce0d7c5640e357608b79eec18919d4e94c37aacf76801ac1b24471a3483755d1ab30a416aa2aa10c9da02fb6241f11e29ea99079ff04bdf012b1 + checksum: bc789ae025923de7f876b5a8e906ea05b662e67b8ce2311fa69bcfe0b6df3e7ca76c0d388db5050ee43cc04c97d5d6f2419aff992920f13896a7bf1a33e8332d languageName: node linkType: hard -"@aws-sdk/middleware-endpoint@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/middleware-endpoint@npm:3.310.0" +"@aws-sdk/middleware-endpoint@npm:3.338.0, @aws-sdk/middleware-endpoint@npm:^3.310.0": + version: 3.338.0 + resolution: "@aws-sdk/middleware-endpoint@npm:3.338.0" dependencies: - "@aws-sdk/middleware-serde": 3.310.0 - "@aws-sdk/types": 3.310.0 - "@aws-sdk/url-parser": 3.310.0 - "@aws-sdk/util-middleware": 3.310.0 + "@aws-sdk/middleware-serde": 3.338.0 + "@aws-sdk/types": 3.338.0 + "@aws-sdk/url-parser": 3.338.0 + "@aws-sdk/util-middleware": 3.338.0 tslib: ^2.5.0 - checksum: 7d61ceaff3fb6be779f9b0597fceccbc1d5ebbc83b83d93ac184fc6451e60b4acca9eebb0c83c9e1c6b34400bd39345b498227860892ed51eda2b99f16ff0566 + checksum: 265eef36686f7b849dce34eb5ccd55379af7b09f749bded039b4d6a6c020fd5ff602a00c2a41c134c821e82c4fef70136d78e5d4767dacbf79bfaefa1b07eb08 languageName: node linkType: hard -"@aws-sdk/middleware-expect-continue@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/middleware-expect-continue@npm:3.310.0" +"@aws-sdk/middleware-expect-continue@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/middleware-expect-continue@npm:3.338.0" dependencies: - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/protocol-http": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 717eb502c00bc5b32cbb210657b0cfdec837f5296f86043bce40f43535f345e689639b017c71271709bdee0a58cc4ade6324ae0bcccfcdc0789e8699b2ce9f76 + checksum: bff8e22e2313458340cf8512dfa0152e683319155bfc63869cca30efedc5062be6a33fb85098230c90dfd835c6f02c27aa96383350247f14b75e2d111606b1e5 languageName: node linkType: hard -"@aws-sdk/middleware-flexible-checksums@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/middleware-flexible-checksums@npm:3.310.0" +"@aws-sdk/middleware-flexible-checksums@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/middleware-flexible-checksums@npm:3.338.0" dependencies: "@aws-crypto/crc32": 3.0.0 "@aws-crypto/crc32c": 3.0.0 "@aws-sdk/is-array-buffer": 3.310.0 - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/protocol-http": 3.338.0 + "@aws-sdk/types": 3.338.0 "@aws-sdk/util-utf8": 3.310.0 tslib: ^2.5.0 - checksum: be99290968c5e00053dd2e43683d77cd08dbe1acff64189e522d9e4aa1440c8e6ae86d784ef4d163a059f725b52fdd5812b54594d70a9773c25feef24e63c9c3 + checksum: 6427816c22184976a0cb1b4c2e0740ab66f632da69f67e5bbb8888ed858f53b865e9e44a13f820d1c81d89b676fd9accbac0afb64378f739da9cd918926afc38 languageName: node linkType: hard -"@aws-sdk/middleware-host-header@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/middleware-host-header@npm:3.310.0" +"@aws-sdk/middleware-host-header@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/middleware-host-header@npm:3.338.0" dependencies: - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/protocol-http": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 9b1bf8598f9bf44a0cd992f08820ce54fb7ce5f33366796b7328a003c2efc00754a3e0bfd56be87b221ca0f15b4c00f5caf736bf196cb9a4b3ca26dfd3e7f7db + checksum: 7ff51a9453bb1dcf93f37bb9c04d84e13be429caa8f65d332e0e9963ca58ad5af6bc5c93110d7e0fb9fab1bb97c7dd7df6df267ffe4ba916c90a72dc6e4ba256 languageName: node linkType: hard -"@aws-sdk/middleware-location-constraint@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/middleware-location-constraint@npm:3.310.0" +"@aws-sdk/middleware-location-constraint@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/middleware-location-constraint@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 2ca1a7d9ca47c29468c4286731f0a1dc15e0233f0a59bc1dad3f3ed5917b1e5d7b344c705660cc3afdecb153f2e2f203e9ae37eb018d6a56aaeba7ad05ebd466 + checksum: 1306d5d6c919990492b9c2869197875d189edbfe83f7f9e1df5ac705c3deb8a42446f812ac5ac6968f4d3ae5f6962953bc8273bc7173a1cb1c9376024d84d8c5 languageName: node linkType: hard -"@aws-sdk/middleware-logger@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/middleware-logger@npm:3.310.0" +"@aws-sdk/middleware-logger@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/middleware-logger@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 13014451afaadf11524754f959aaa4c4e7763442dedef841d693159370720e40d20a6113851b87b6cab6c709d92b1e952adede0ec9948dbaa1546dbff1e477d0 + checksum: 9c4a3e3656fe17a99eca5312c4aefe2031e33239c700de8efeae66be0d0636ad585701714b9832f783be143ebea602534db246dfbe8c90e6b1d325a71b64fa7e languageName: node linkType: hard -"@aws-sdk/middleware-recursion-detection@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/middleware-recursion-detection@npm:3.310.0" +"@aws-sdk/middleware-recursion-detection@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/middleware-recursion-detection@npm:3.338.0" dependencies: - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/protocol-http": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: a5db6bec59a5232ebc28296d165d09fb94d74e9232d32f49f77bccbbae62cda58215d2f8a17979f1714b9dd07c25a989caae8bc7eee1f57c57d67328788fa401 + checksum: 9dddbabf6bf96808583b26a9af06af51fb8f5478d89a93954a60cbcbe5d2dbc3f9f3621b19f38491bc96096b121f446c138c37ab1b1be8a643efcd5ff983d3f1 languageName: node linkType: hard -"@aws-sdk/middleware-retry@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/middleware-retry@npm:3.310.0" +"@aws-sdk/middleware-retry@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/middleware-retry@npm:3.338.0" dependencies: - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/service-error-classification": 3.310.0 - "@aws-sdk/types": 3.310.0 - "@aws-sdk/util-middleware": 3.310.0 - "@aws-sdk/util-retry": 3.310.0 + "@aws-sdk/protocol-http": 3.338.0 + "@aws-sdk/service-error-classification": 3.338.0 + "@aws-sdk/types": 3.338.0 + "@aws-sdk/util-middleware": 3.338.0 + "@aws-sdk/util-retry": 3.338.0 tslib: ^2.5.0 uuid: ^8.3.2 - checksum: 7d69c187d4cfad62df01b445596f812157e4028b377f34c40f6b272df3660a48ebbc6a0c86eba98b1b19454ade6be7b1459c62ffe8a1924725a23e330d2814b7 + checksum: 186d82e32df9dbfe62c90e545847dd74e79088b897c470d9dd753c51d4a6e6006a981734d4c0076ea2ec5155448ccf4bf65c517c6a907ac64b12c48da172dfb3 languageName: node linkType: hard -"@aws-sdk/middleware-sdk-s3@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/middleware-sdk-s3@npm:3.310.0" +"@aws-sdk/middleware-sdk-s3@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/middleware-sdk-s3@npm:3.338.0" dependencies: - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/protocol-http": 3.338.0 + "@aws-sdk/types": 3.338.0 "@aws-sdk/util-arn-parser": 3.310.0 tslib: ^2.5.0 - checksum: b546560c2fc3fcbb37d38b5d02e3f8349592d66a6a2ef4571b72d0bb6c398d0c2bb7008665d58541efc577372f2e1aae88ea1318ba0fe8613583397604dff02e + checksum: a1c7e35b106ab2f12bb700add3dd82afc304f6ea7fdeb69ac9b4192cc049e2e51cd1580740471f6aaaa3aaf83f870fc0873955e3554b6f3dda5c2bd8df42de31 languageName: node linkType: hard -"@aws-sdk/middleware-sdk-sqs@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/middleware-sdk-sqs@npm:3.310.0" +"@aws-sdk/middleware-sdk-sqs@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/middleware-sdk-sqs@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 "@aws-sdk/util-hex-encoding": 3.310.0 "@aws-sdk/util-utf8": 3.310.0 tslib: ^2.5.0 - checksum: b8207b1625e52d02b3a3f28153e84f3a9c44bc9812ceb0ca1da798aa9fe576b9aef26c2da10dd6c8742c64e734eec93fd5123d769079b99a19bd105599fe11e5 + checksum: 609eb416099bb38c7ce459f73129e51d29804690749e3fbfe665c28b0fca61d885ad45cba852bc9b0545915d65dcded09cdf2a49a9da2e1168bff29c58be9a0a languageName: node linkType: hard -"@aws-sdk/middleware-sdk-sts@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/middleware-sdk-sts@npm:3.310.0" +"@aws-sdk/middleware-sdk-sts@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/middleware-sdk-sts@npm:3.338.0" dependencies: - "@aws-sdk/middleware-signing": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/middleware-signing": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 80debd2f2371f65f7c37f2f0101e9e8ac520ef74d6a8ba54fedfbad6d63653732f7ce6095bae7bf3adbfec61bfa4d9f816b8eb5550cdadec825b400cf74bb2ce + checksum: 359cd0b7b47ac97a8ba5fa8dd290d8940515fa8ca0068b9e645f0d4d99fe6679a3086b5b01765b83a20982a81410d8ae4a50ede5e97917af4ee269fca2dd987f languageName: node linkType: hard -"@aws-sdk/middleware-serde@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/middleware-serde@npm:3.310.0" +"@aws-sdk/middleware-serde@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/middleware-serde@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 95c2c1b15906a93c9869be36563757f08cd53a0f385882759943e59a1fd31be777260fb075feaa1a9bb919cf1696739e7b2da89049cec0bee1a649a838f9184c + checksum: f4317c734e1a27001278723bdfe71aadb63d50f1a60b44d0662c12ca5499f32b7208122bb65dd8f2ba809edfc2e333853f463dbeaee7c85e1214e5814875cfba languageName: node linkType: hard -"@aws-sdk/middleware-signing@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/middleware-signing@npm:3.310.0" +"@aws-sdk/middleware-signing@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/middleware-signing@npm:3.338.0" dependencies: - "@aws-sdk/property-provider": 3.310.0 - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/signature-v4": 3.310.0 - "@aws-sdk/types": 3.310.0 - "@aws-sdk/util-middleware": 3.310.0 + "@aws-sdk/property-provider": 3.338.0 + "@aws-sdk/protocol-http": 3.338.0 + "@aws-sdk/signature-v4": 3.338.0 + "@aws-sdk/types": 3.338.0 + "@aws-sdk/util-middleware": 3.338.0 tslib: ^2.5.0 - checksum: f1db11435250075fc563de375c8c513dbaba7b9939ae99c70074d90622f9aea0cc339cd10f0eff63251eba462b73f564389bfb9dcfe6868f36892488dea0494b + checksum: e53478186e0ac9b1a6c8834659716b851afaced1cfdbf99681800ae2fd9e3124573f188ae258d00cda612afbec15dbb613b88567ee604ad3b69c92b1e47f225a languageName: node linkType: hard -"@aws-sdk/middleware-ssec@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/middleware-ssec@npm:3.310.0" +"@aws-sdk/middleware-ssec@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/middleware-ssec@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: a6d9cde8d826c4baae7908e82035e892f8b4706e648efa1ff5a8706285efabd17f9fe8d48b5b0fb42b17f227fba257b7d95b99baf9e152246cb95a2fe23a547f + checksum: 7136d65756f319ae6f051a021c8ca345e01b9ccbbf6ae33a42bc6510a452904bc20e8ef5f0631adde6f6b91ee11615916dd4f69033944ffc549d47892ac9bd30 languageName: node linkType: hard -"@aws-sdk/middleware-stack@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/middleware-stack@npm:3.310.0" +"@aws-sdk/middleware-stack@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/middleware-stack@npm:3.338.0" dependencies: tslib: ^2.5.0 - checksum: ad90bb8cf2a8e3211869ed0c08e240e0df7097ff42a9bbfa6dd96ad79a8b741c096199082f1be40a2ae2b1fbeb56a4bc510cdaf431dd90a5db73e32fe7184ee2 + checksum: f73b04a9f9e3b33a19f0d4c56877248df4016003dda3a4237374bdfe8c1c4358b69894754110a9989ba131dab5ec1fa03de68c50cbe10a399e290da96b5b8d06 languageName: node linkType: hard -"@aws-sdk/middleware-user-agent@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/middleware-user-agent@npm:3.310.0" +"@aws-sdk/middleware-user-agent@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/middleware-user-agent@npm:3.338.0" dependencies: - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/types": 3.310.0 - "@aws-sdk/util-endpoints": 3.310.0 + "@aws-sdk/protocol-http": 3.338.0 + "@aws-sdk/types": 3.338.0 + "@aws-sdk/util-endpoints": 3.338.0 tslib: ^2.5.0 - checksum: 571ebfce481a2d814270248e728c68030661cb3f0de97908b73e1d446c508d5af06cb088c68c67b23ce9671873c1872ab681b9383d48797b5a1c53a7030085ff + checksum: 6b3dce2a4ec82121d13f57f2a426d42380e8198a4a891f89fdaee0698f3b9c8c7f7d08242d0f8b762f7d9515ef44e8beb79b79a96a9e890901cbfc484932bae3 languageName: node linkType: hard -"@aws-sdk/node-config-provider@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/node-config-provider@npm:3.310.0" +"@aws-sdk/node-config-provider@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/node-config-provider@npm:3.338.0" dependencies: - "@aws-sdk/property-provider": 3.310.0 - "@aws-sdk/shared-ini-file-loader": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/property-provider": 3.338.0 + "@aws-sdk/shared-ini-file-loader": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 95d017aa1bb94e323c288bc0ce5edba5c4605eeabe779249beb5faee958c26f6eebb7f1664328b83d1024e441eb4e4f9fce9c1bb764637f83f7ebf20b8359a77 + checksum: e81d311321b582b94d7349f2e225b1be74d7a7b7f6d4d3834de5fb9d80a7861e7cede791d088c613008dcdc00f77dfec23301794756c61452308841d73b9ac1c languageName: node linkType: hard -"@aws-sdk/node-http-handler@npm:3.310.0, @aws-sdk/node-http-handler@npm:^3.208.0": - version: 3.310.0 - resolution: "@aws-sdk/node-http-handler@npm:3.310.0" +"@aws-sdk/node-http-handler@npm:3.338.0, @aws-sdk/node-http-handler@npm:^3.310.0": + version: 3.338.0 + resolution: "@aws-sdk/node-http-handler@npm:3.338.0" dependencies: - "@aws-sdk/abort-controller": 3.310.0 - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/querystring-builder": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/abort-controller": 3.338.0 + "@aws-sdk/protocol-http": 3.338.0 + "@aws-sdk/querystring-builder": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 781cc864972bf52f884b580e43b9b659ab34a6ca7d7772d8e76107a51fe0930124c01024bc7ac1c4e99324319c594b809373ebc4752ea0a2e3a984ccf57aa535 + checksum: 238d573256eed3d7311e9aff92e072fb53486d054516045c443e6218841742e64ce02993fdaeda79cdd081d2d80011261010e0cdf9d63b267aebb86f9ec48a1e languageName: node linkType: hard -"@aws-sdk/property-provider@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/property-provider@npm:3.310.0" +"@aws-sdk/property-provider@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/property-provider@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 8a906b3f4e482f4d5be0ef1277fcb22fb005e834c916919373187f8cf6b17b0d464f37a12770d152a553b7a505ed9981504a0c30f73f273d251ed93ff29616e1 + checksum: 938bd8c29254c24a74f0d505e58a214743a46c7880dc13a24d851fa5fc9871ba7043ff3305da484c9a9660dee305733d508448b7d06728e2ae694151fdaf5ec7 languageName: node linkType: hard -"@aws-sdk/protocol-http@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/protocol-http@npm:3.310.0" +"@aws-sdk/protocol-http@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/protocol-http@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 4bfe2b7a93d52ded21472d6347483fb52dfd2414d4ff07d8e3a2869d7676e866a9bfa29e9e7ac4fa3849c7109740a39e3d1e646a02d8bb4b7c7b402f53b18450 + checksum: a5f87ba4876fb9d4294bfa82aa3da21a7386b4d8725d152f79441b099ef3f865c302dea1df691b23884c95f457671b0837f2aea98381e35cbcc8395796dee412 languageName: node linkType: hard -"@aws-sdk/querystring-builder@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/querystring-builder@npm:3.310.0" +"@aws-sdk/querystring-builder@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/querystring-builder@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 "@aws-sdk/util-uri-escape": 3.310.0 tslib: ^2.5.0 - checksum: c06ba9ec67d6e6a5f4c1099461b9b2d6cb12a278e6ec2fe198f68ba115ce1e05425f29cf6859f8a005ae7123036b6dadc325d18b35165c7049233f9d04670dcb + checksum: d9df52be103420f51b3d4ffa7a6d59825416f520421e4f1c4b95cb55d60d45eb12364dbc434bee1a3c7f1563268bf82b06c365324a79005f340b0abc9554143b languageName: node linkType: hard -"@aws-sdk/querystring-parser@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/querystring-parser@npm:3.310.0" +"@aws-sdk/querystring-parser@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/querystring-parser@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 5e9d8700918db3daa89440f7c0aa9d0ee37e30bab13892f12602267259160ff73eaccd7e01521bf71f4a0f59da9cb632f75e583d927900f2acddc4913e3422f8 + checksum: 8645c79cb27d8a63c3637a9ebf9d97ce603b1c4f114e849ca995432479871a3bc37b1084b2e593d48178dc609f9e3a2535a6b0e44052e62b1cd47966890bd0bd languageName: node linkType: hard -"@aws-sdk/service-error-classification@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/service-error-classification@npm:3.310.0" - checksum: a600a7634fe932b52676ea33851230173ce66b45f4c8350c91616e37f9cbd43e8f6e7e3fc9761fd14ca7ecd2c7ca90ca806fc555e383d0bf0ee2bdb6a4d73888 +"@aws-sdk/service-error-classification@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/service-error-classification@npm:3.338.0" + checksum: 5760007eaa6bd105524fce230a030072c44149ea381451a1c7706e7bc5bb44aa512b40fb14b569b1063dc70b2275f0618fc0e82bbcaf1cecdb74c59a92ba4557 languageName: node linkType: hard -"@aws-sdk/shared-ini-file-loader@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/shared-ini-file-loader@npm:3.310.0" +"@aws-sdk/shared-ini-file-loader@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/shared-ini-file-loader@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: aa3ffb5cb4320ee936102be200dbacb95be0bd85088c692de268d56c175dd4329757a83847d1c4e689b98f3810f729596a1a0b726f1ea0a8d00c78516fc10cc3 + checksum: c50eb70ae5d5a47ac67c12dc0d00c29ae4e6179cabadeda2e5e1f0c3cc36f379ea8f0a55d04d600ad523597a5e8961571d3fea3fab93882496cd0567f80420d5 languageName: node linkType: hard -"@aws-sdk/signature-v4-multi-region@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/signature-v4-multi-region@npm:3.310.0" +"@aws-sdk/signature-v4-multi-region@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/signature-v4-multi-region@npm:3.338.0" dependencies: - "@aws-sdk/protocol-http": 3.310.0 - "@aws-sdk/signature-v4": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/protocol-http": 3.338.0 + "@aws-sdk/signature-v4": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 peerDependencies: "@aws-sdk/signature-v4-crt": ^3.118.0 peerDependenciesMeta: "@aws-sdk/signature-v4-crt": optional: true - checksum: ef88c3ba8dba0fda1204ec9358e46ea2bbefb0a258b21e2c83142b3ea9bb9be3eba428b38297da28bb4a5e93f9c27de8711aa6f219b3cbced4eba0c443c9b68a + checksum: 28f94ed3ee46a96d1f1e62ecfb71f22a6d2be9059b2230afa29753e4a5687d76bcafd9eb1394bd0730aaa6bc94e24d6d9100b0e7b4d39d45ccae09f15b993444 languageName: node linkType: hard -"@aws-sdk/signature-v4@npm:3.310.0, @aws-sdk/signature-v4@npm:^3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/signature-v4@npm:3.310.0" +"@aws-sdk/signature-v4@npm:3.338.0, @aws-sdk/signature-v4@npm:^3.310.0": + version: 3.338.0 + resolution: "@aws-sdk/signature-v4@npm:3.338.0" dependencies: "@aws-sdk/is-array-buffer": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 "@aws-sdk/util-hex-encoding": 3.310.0 - "@aws-sdk/util-middleware": 3.310.0 + "@aws-sdk/util-middleware": 3.338.0 "@aws-sdk/util-uri-escape": 3.310.0 "@aws-sdk/util-utf8": 3.310.0 tslib: ^2.5.0 - checksum: 0adaf05a005a8a468301f24482d25de3a35554debc98ab8eeb0444c529c02a63dc7e7754d990e9464e1a17c1eb1f6ffdcc178bcd7d35c87587e4cc41574c69b3 + checksum: 9d024ad98a84beb9f3d5e66bd68cc93a47b78eb50e00ab4d3ac4bcad34d2e7e4b05053b21d36645e69550c532ccceca38b1b65af7d68da3b7197900c427303ed languageName: node linkType: hard -"@aws-sdk/smithy-client@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/smithy-client@npm:3.310.0" +"@aws-sdk/smithy-client@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/smithy-client@npm:3.338.0" dependencies: - "@aws-sdk/middleware-stack": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/middleware-stack": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: a97b88e6ae3066abf136fe3d59ead258d459c4f37f69e6170a902d85194cb2d798519771b945880072776bbf0e77bfc18e15768dcbafc402f0f255d80bca0ba6 + checksum: 7c2bc4b7fcfe94dd3bb3068947c9ab3d0bf563790f7981f8af312f20f3b43364c7a691019ca53229e81a639379e3d3db5a0f38b846940aba180f6170c2a7a2b9 languageName: node linkType: hard -"@aws-sdk/token-providers@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/token-providers@npm:3.310.0" +"@aws-sdk/token-providers@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/token-providers@npm:3.338.0" dependencies: - "@aws-sdk/client-sso-oidc": 3.310.0 - "@aws-sdk/property-provider": 3.310.0 - "@aws-sdk/shared-ini-file-loader": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/client-sso-oidc": 3.338.0 + "@aws-sdk/property-provider": 3.338.0 + "@aws-sdk/shared-ini-file-loader": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: a38d5c562f0cc29ddcd6b52b8b4c872447824962055cdb77587fdc9e13e24e6a9acda1d7ea60e7b7e2dbfe8b27dc0ff03347e739b298099b7c1ebe67044ff8e1 + checksum: 49b58c59ea372ccf80739925a84f5dcfde9c74fb194fd171bd4c2c3d80576ab4e6c33a7612bba697f588135edb1fb9bb26e88363e256d9c038eb469013a5fa71 languageName: node linkType: hard -"@aws-sdk/types@npm:3.310.0, @aws-sdk/types@npm:^3.208.0, @aws-sdk/types@npm:^3.222.0": - version: 3.310.0 - resolution: "@aws-sdk/types@npm:3.310.0" +"@aws-sdk/types@npm:3.338.0, @aws-sdk/types@npm:^3.222.0, @aws-sdk/types@npm:^3.310.0": + version: 3.338.0 + resolution: "@aws-sdk/types@npm:3.338.0" dependencies: tslib: ^2.5.0 - checksum: b11a91899614e14d40081ceab39cd3702254a5658c7b5e8862ef0d66dbffaa41c9a0f0d31e415d22f31c791b507699ba3a5fc7d87a540273386eb779be3807e4 + checksum: c20619ef22c460c34926c053522163a2b8f4825fd8288dcfefec80ce2d526ab1e0417064dd533739a6037eb1abd16bc035a4be932d9eeec80a05483ec5183140 languageName: node linkType: hard -"@aws-sdk/url-parser@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/url-parser@npm:3.310.0" +"@aws-sdk/url-parser@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/url-parser@npm:3.338.0" dependencies: - "@aws-sdk/querystring-parser": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/querystring-parser": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: a9f5bec1cfa38cf2d244df1f6d7aad0f8e880a285d148678652ba14a3fb03fc0847defdc80a7e3ffb197d91e33d8cfb43325ee39f53c43c40ceb7fbd34f38fda + checksum: c25a26196c6ee5f745bcb684d2b1c85051d913332682a5aa25635b4d4a858178c870639b6cd33c89f0cc456b9a65db48c90f039f7ac07f62963c9fa39fa7b4fe languageName: node linkType: hard -"@aws-sdk/util-arn-parser@npm:3.310.0, @aws-sdk/util-arn-parser@npm:^3.208.0": +"@aws-sdk/util-arn-parser@npm:3.310.0, @aws-sdk/util-arn-parser@npm:^3.310.0": version: 3.310.0 resolution: "@aws-sdk/util-arn-parser@npm:3.310.0" dependencies: @@ -1541,39 +1637,39 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/util-defaults-mode-browser@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/util-defaults-mode-browser@npm:3.310.0" +"@aws-sdk/util-defaults-mode-browser@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/util-defaults-mode-browser@npm:3.338.0" dependencies: - "@aws-sdk/property-provider": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/property-provider": 3.338.0 + "@aws-sdk/types": 3.338.0 bowser: ^2.11.0 tslib: ^2.5.0 - checksum: 1f1847c41c43e167dec2e6f1a128ac9a486cc2e536b65d8d0e247131105cd2a46329297adc865ec164019850cbd425648add521dbde03417cacceaaf249555c2 + checksum: 07e06c0256097979743b0a81d09d69c1f678e6386f9543c1bc9d150b11f3d3c89ea729a5c8f1b99c32326ee60e23ebc7e9d1a985b920c4b2301eb53488e5faa6 languageName: node linkType: hard -"@aws-sdk/util-defaults-mode-node@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/util-defaults-mode-node@npm:3.310.0" +"@aws-sdk/util-defaults-mode-node@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/util-defaults-mode-node@npm:3.338.0" dependencies: - "@aws-sdk/config-resolver": 3.310.0 - "@aws-sdk/credential-provider-imds": 3.310.0 - "@aws-sdk/node-config-provider": 3.310.0 - "@aws-sdk/property-provider": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/config-resolver": 3.338.0 + "@aws-sdk/credential-provider-imds": 3.338.0 + "@aws-sdk/node-config-provider": 3.338.0 + "@aws-sdk/property-provider": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: dca18909df6f8c72ae606c25920e2f686016de969aef2be4568cd6ce1fa0c45b3f946702d607b3279d267aaedff8b67251d4ee7bb4f76a38fca4299c81a7757d + checksum: 1829f7c5035049c43173e78e843b6feaf0acc46b94803e12827985b5b881ca1e8a091072106b3573bb400e7ad80fa7579364d0783e69db6c560cdf49cda0f759 languageName: node linkType: hard -"@aws-sdk/util-endpoints@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/util-endpoints@npm:3.310.0" +"@aws-sdk/util-endpoints@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/util-endpoints@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 3f1c76b4c7662eeaf9dcf782739aa90812ed6920dd602a4a3779c80fbf3215efb15bd1ad82a30d022b577acd6049d35fbf79b45f6ae842e895be94db360d1b03 + checksum: 8c70bcaae2636089b15e6891a31c4c4a19e59d5c945e17ff9a6ffcfce96a9db4dad28df7c7755920a4a670acdd3858a92a95b3d16b74191d8400807dafb6ba75 languageName: node linkType: hard @@ -1595,48 +1691,48 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/util-middleware@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/util-middleware@npm:3.310.0" +"@aws-sdk/util-middleware@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/util-middleware@npm:3.338.0" dependencies: tslib: ^2.5.0 - checksum: 3c25a83361ce95dd3f66170d67fb39911a3f5bc21627ffaccef1880ad8c3602b6351f5c51e9c0bfef5b4037e5c66b9eadb291a9441db644811cf5640c35c587b + checksum: 971338a469dcb709fb7eac2f796fa8db033e614645cd35100327c39f48b66b9faba68560afdd8a88a39b9ace714390b1a6ddb1c8265a98729ae877e3a01ad2cd languageName: node linkType: hard -"@aws-sdk/util-retry@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/util-retry@npm:3.310.0" +"@aws-sdk/util-retry@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/util-retry@npm:3.338.0" dependencies: - "@aws-sdk/service-error-classification": 3.310.0 + "@aws-sdk/service-error-classification": 3.338.0 tslib: ^2.5.0 - checksum: a91b53ca40dd7ac423b46a4916a84567de163e84e63919e77d9a0694337323812b662580f6133442eb1c17885d0a2b5663cba9cadce4dabf5517dc34089b3399 + checksum: 37310fae814faab60351629c9e59a6a06bc2bed5bd296ef5016e1c4e94e4ba9daa892898473690f157f32f91eb70669061a14d3f8cabdc0bc65293496cdfb6c0 languageName: node linkType: hard -"@aws-sdk/util-stream-browser@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/util-stream-browser@npm:3.310.0" +"@aws-sdk/util-stream-browser@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/util-stream-browser@npm:3.338.0" dependencies: - "@aws-sdk/fetch-http-handler": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/fetch-http-handler": 3.338.0 + "@aws-sdk/types": 3.338.0 "@aws-sdk/util-base64": 3.310.0 "@aws-sdk/util-hex-encoding": 3.310.0 "@aws-sdk/util-utf8": 3.310.0 tslib: ^2.5.0 - checksum: 0058cdb410bd5d9365ce28c436dff17a534dfea38cc411f2bc83b34aa1be24850feae19f73b2fc7c2865df5d38d1f2502eb8ab4d061b3a90f4823bc09031f30c + checksum: 0a0cfb601737411e04aa06a502dad8be306e6dafa7d153ba1d446353348d72c844f12571622bc9926175c38121d332027ffaa01ed61090689be0e3cb79aefa08 languageName: node linkType: hard -"@aws-sdk/util-stream-node@npm:3.310.0, @aws-sdk/util-stream-node@npm:^3.208.0": - version: 3.310.0 - resolution: "@aws-sdk/util-stream-node@npm:3.310.0" +"@aws-sdk/util-stream-node@npm:3.338.0, @aws-sdk/util-stream-node@npm:^3.310.0": + version: 3.338.0 + resolution: "@aws-sdk/util-stream-node@npm:3.338.0" dependencies: - "@aws-sdk/node-http-handler": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/node-http-handler": 3.338.0 + "@aws-sdk/types": 3.338.0 "@aws-sdk/util-buffer-from": 3.310.0 tslib: ^2.5.0 - checksum: 05caf55f81dd8151adccc23bc2f3f0007e095fb554bec279ec0c8045a7d8da22ecaed238f5d12705ae77e77b7cd81119bb5da2f1a9788962f5361647cafdf9ca + checksum: 8ab278d971800ec121dda964c65b9be43f58142bf29306fdd292d393f8de5197a59960d4452e8806be01f141343c6d4730484907cb1f6538af547ae58a00c10f languageName: node linkType: hard @@ -1649,30 +1745,30 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/util-user-agent-browser@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/util-user-agent-browser@npm:3.310.0" +"@aws-sdk/util-user-agent-browser@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/util-user-agent-browser@npm:3.338.0" dependencies: - "@aws-sdk/types": 3.310.0 + "@aws-sdk/types": 3.338.0 bowser: ^2.11.0 tslib: ^2.5.0 - checksum: 32fc6249e762fcba3f3111ed627b644855e8127bc354911fdcdbd0332ea1915872bb0984f19c049fbc4feaf17e3bb02ff11b13d3792103ee8902d00c7fe3ff84 + checksum: cea19aebcbc67e943ecfd34a7db53e94060021b1a7b8d79dd39496c42b9991ed80dc46dd42dd2eb4b52d3ce519e07686936cf3c2abd159f807a579c87b1ce1ba languageName: node linkType: hard -"@aws-sdk/util-user-agent-node@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/util-user-agent-node@npm:3.310.0" +"@aws-sdk/util-user-agent-node@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/util-user-agent-node@npm:3.338.0" dependencies: - "@aws-sdk/node-config-provider": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/node-config-provider": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 peerDependencies: aws-crt: ">=1.0.0" peerDependenciesMeta: aws-crt: optional: true - checksum: 82d214f814405a538df8afb259f6a3f2d373cd87adbc2895ac93e9d1f4ed9f4f8f6dcc0ae8ba55887e99e45b5ea83c7b1e5ed3efccbcdbbcaee6a863a638d183 + checksum: dade43fc3218d7828f0f9d3f12c208211b3bae5ccc6018805d49e1a6886d54403d2133856503a76230b7e066e792a8e63ca894368b3e841fb8252e0290282580 languageName: node linkType: hard @@ -1695,14 +1791,14 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/util-waiter@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/util-waiter@npm:3.310.0" +"@aws-sdk/util-waiter@npm:3.338.0": + version: 3.338.0 + resolution: "@aws-sdk/util-waiter@npm:3.338.0" dependencies: - "@aws-sdk/abort-controller": 3.310.0 - "@aws-sdk/types": 3.310.0 + "@aws-sdk/abort-controller": 3.338.0 + "@aws-sdk/types": 3.338.0 tslib: ^2.5.0 - checksum: 51eb9fbb9a21cd02c312f4639e520b934e2d6ea93eb7c0c1c71f3cf415d61b0a681e7f88209f9e49f3e84bba83480d1c14b0c0b069b610bd12753ff1c1d68f42 + checksum: dda7038d1e7d62a8cc7f30523d1a755e5cc5c6c1cd821236a1f16adb16e87146a69260b23061c198a437e4b3a0a0e706b9f23fc592cc9dbd44276b588ba8100c languageName: node linkType: hard @@ -2160,7 +2256,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.0.0, @babel/helper-module-imports@npm:^7.12.13, @babel/helper-module-imports@npm:^7.16.0, @babel/helper-module-imports@npm:^7.18.6": +"@babel/helper-module-imports@npm:^7.0.0, @babel/helper-module-imports@npm:^7.12.13, @babel/helper-module-imports@npm:^7.16.0, @babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.18.6": version: 7.18.6 resolution: "@babel/helper-module-imports@npm:7.18.6" dependencies: @@ -2642,7 +2738,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-jsx@npm:^7.0.0, @babel/plugin-syntax-jsx@npm:^7.18.6, @babel/plugin-syntax-jsx@npm:^7.7.2": +"@babel/plugin-syntax-jsx@npm:^7.0.0, @babel/plugin-syntax-jsx@npm:^7.17.12, @babel/plugin-syntax-jsx@npm:^7.18.6, @babel/plugin-syntax-jsx@npm:^7.7.2": version: 7.18.6 resolution: "@babel/plugin-syntax-jsx@npm:7.18.6" dependencies: @@ -3384,7 +3480,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.14.6, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.1, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.0, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.14.6, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.1, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.0, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": version: 7.21.0 resolution: "@babel/runtime@npm:7.21.0" dependencies: @@ -3508,11 +3604,11 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/backend-common@workspace:packages/backend-common" dependencies: - "@aws-sdk/abort-controller": ^3.208.0 - "@aws-sdk/client-s3": ^3.208.0 - "@aws-sdk/credential-providers": ^3.208.0 - "@aws-sdk/types": ^3.208.0 - "@aws-sdk/util-stream-node": ^3.208.0 + "@aws-sdk/abort-controller": ^3.310.0 + "@aws-sdk/client-s3": ^3.310.0 + "@aws-sdk/credential-providers": ^3.310.0 + "@aws-sdk/types": ^3.310.0 + "@aws-sdk/util-stream-node": ^3.310.0 "@backstage/backend-app-api": "workspace:^" "@backstage/backend-dev-utils": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" @@ -3699,7 +3795,18 @@ __metadata: languageName: unknown linkType: soft -"@backstage/catalog-client@^1.4.1, @backstage/catalog-client@workspace:^, @backstage/catalog-client@workspace:packages/catalog-client": +"@backstage/catalog-client@npm:^1.4.1": + version: 1.4.1 + resolution: "@backstage/catalog-client@npm:1.4.1" + dependencies: + "@backstage/catalog-model": ^1.3.0 + "@backstage/errors": ^1.1.5 + cross-fetch: ^3.1.5 + checksum: 21d6ae8191f97c80b8f75b0a8b9b1d7a0255c865f0c8e08b5bb72492a1cca4769bb1d9766d0c6307910cc1dd41c14abd02307f626772de14e4ebda23b5773465 + languageName: node + linkType: hard + +"@backstage/catalog-client@workspace:^, @backstage/catalog-client@workspace:packages/catalog-client": version: 0.0.0-use.local resolution: "@backstage/catalog-client@workspace:packages/catalog-client" dependencies: @@ -4050,14 +4157,14 @@ __metadata: languageName: node linkType: hard -"@backstage/core-components@npm:^0.13.0": - version: 0.13.0 - resolution: "@backstage/core-components@npm:0.13.0" +"@backstage/core-components@npm:^0.13.0, @backstage/core-components@npm:^0.13.1": + version: 0.13.1 + resolution: "@backstage/core-components@npm:0.13.1" dependencies: "@backstage/config": ^1.0.7 "@backstage/core-plugin-api": ^1.5.1 "@backstage/errors": ^1.1.5 - "@backstage/theme": ^0.2.19 + "@backstage/theme": ^0.3.0 "@backstage/version-bridge": ^1.0.4 "@date-io/core": ^1.3.13 "@material-table/core": ^3.1.0 @@ -4099,7 +4206,7 @@ __metadata: react: ^16.13.1 || ^17.0.0 react-dom: ^16.13.1 || ^17.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: 49c5301ff45c6f7516e78e80f46b25d2efb8d9ba510c7718f94c25b1f7d9b2869840db7ec896fbf9d083ceca8fa8cddf718a78eeb074993e95d474195f4bc9cd + checksum: 9b1b40edb51ab4de6018d0fe063386b0e3f1b56b0427c98421cd5ccaffa790ccd9a5f70d36f6ebf5ce381a1b34ae4df5ffeef38c9074800fe38c352bd173003a languageName: node linkType: hard @@ -4292,11 +4399,11 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/integration-aws-node@workspace:packages/integration-aws-node" dependencies: - "@aws-sdk/client-sts": ^3.208.0 - "@aws-sdk/credential-provider-node": ^3.208.0 - "@aws-sdk/credential-providers": ^3.208.0 - "@aws-sdk/types": ^3.208.0 - "@aws-sdk/util-arn-parser": ^3.208.0 + "@aws-sdk/client-sts": ^3.310.0 + "@aws-sdk/credential-provider-node": ^3.310.0 + "@aws-sdk/credential-providers": ^3.310.0 + "@aws-sdk/types": ^3.310.0 + "@aws-sdk/util-arn-parser": ^3.310.0 "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/config-loader": "workspace:^" @@ -4308,14 +4415,14 @@ __metadata: linkType: soft "@backstage/integration-react@npm:^1.1.12": - version: 1.1.12 - resolution: "@backstage/integration-react@npm:1.1.12" + version: 1.1.13 + resolution: "@backstage/integration-react@npm:1.1.13" dependencies: "@backstage/config": ^1.0.7 - "@backstage/core-components": ^0.13.0 + "@backstage/core-components": ^0.13.1 "@backstage/core-plugin-api": ^1.5.1 - "@backstage/integration": ^1.4.4 - "@backstage/theme": ^0.2.19 + "@backstage/integration": ^1.4.5 + "@backstage/theme": ^0.3.0 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 @@ -4324,7 +4431,7 @@ __metadata: react: ^16.13.1 || ^17.0.0 react-dom: ^16.13.1 || ^17.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: c7ae5754f074f3cee020a5dfca50deecaccd0f5a8510a1446bb1070d7b9b6e32a82564cff77b98ef63b19fde5a29aceaf4b8e8662dd1a3ed00c408c8ae06dc65 + checksum: 72cf0a87699a3a47a518eba0f86ea7980caa946498814ceb71dfed4c5f67ab47dd763289ab3090c1c50b427e368522c9495c4c6d3ffca9296ea4f48d59d40bdb languageName: node linkType: hard @@ -4359,23 +4466,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/integration@npm:^1.4.4": - version: 1.4.4 - resolution: "@backstage/integration@npm:1.4.4" - dependencies: - "@backstage/config": ^1.0.7 - "@backstage/errors": ^1.1.5 - "@octokit/auth-app": ^4.0.0 - "@octokit/rest": ^19.0.3 - cross-fetch: ^3.1.5 - git-url-parse: ^13.0.0 - lodash: ^4.17.21 - luxon: ^3.0.0 - checksum: 715310efe55b3c2fb93f5197bc1422917822a15a7550aae9d84b257bb0a6cff2bfab9a44296a977a56651499fbecd0ef31f954f92a62cc94bfbc7319d9a48c04 - languageName: node - linkType: hard - -"@backstage/integration@workspace:^, @backstage/integration@workspace:packages/integration": +"@backstage/integration@^1.4.5, @backstage/integration@workspace:^, @backstage/integration@workspace:packages/integration": version: 0.0.0-use.local resolution: "@backstage/integration@workspace:packages/integration" dependencies: @@ -4796,6 +4887,7 @@ __metadata: "@types/passport-strategy": ^0.2.35 "@types/xml2js": ^0.4.7 compression: ^1.7.4 + connect-session-knex: ^3.0.1 cookie-parser: ^1.4.5 cors: ^2.8.5 express: ^4.17.1 @@ -4986,18 +5078,24 @@ __metadata: resolution: "@backstage/plugin-badges-backend@workspace:plugins/badges-backend" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-client": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/plugin-auth-node": "workspace:^" "@types/express": ^4.17.6 - "@types/supertest": ^2.0.8 + "@types/node": "*" badge-maker: ^3.3.0 cors: ^2.8.5 + cross-fetch: ^3.1.5 express: ^4.17.1 express-promise-router: ^4.1.0 - supertest: ^6.1.3 + knex: ^2.4.2 + lodash: ^4.17.21 + supertest: ^6.3.3 + uuid: ^9.0.0 winston: ^3.2.1 yn: ^4.0.0 languageName: unknown @@ -5020,14 +5118,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/user-event": ^14.0.0 + "@testing-library/jest-dom": ^5.16.5 "@types/node": ^16.11.26 - "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 - msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -5143,8 +5236,13 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-aws@workspace:plugins/catalog-backend-module-aws" dependencies: - "@aws-sdk/client-s3": ^3.208.0 - "@aws-sdk/util-stream-node": ^3.208.0 + "@aws-sdk/client-eks": ^3.310.0 + "@aws-sdk/client-organizations": ^3.310.0 + "@aws-sdk/client-s3": ^3.310.0 + "@aws-sdk/credential-providers": ^3.310.0 + "@aws-sdk/middleware-endpoint": ^3.310.0 + "@aws-sdk/types": ^3.310.0 + "@aws-sdk/util-stream-node": ^3.310.0 "@backstage/backend-common": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-tasks": "workspace:^" @@ -5154,14 +5252,14 @@ __metadata: "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" + "@backstage/integration-aws-node": "workspace:^" "@backstage/plugin-catalog-common": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-kubernetes-common": "workspace:^" "@backstage/types": "workspace:^" "@types/lodash": ^4.14.151 - aws-sdk: ^2.840.0 aws-sdk-client-mock: ^2.0.0 - aws-sdk-mock: ^5.2.1 + aws-sdk-client-mock-jest: ^2.0.0 lodash: ^4.17.21 luxon: ^3.0.0 p-limit: ^3.0.2 @@ -5466,7 +5564,7 @@ __metadata: "@types/lodash": ^4.14.151 lodash: ^4.17.21 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 uuid: ^8.0.0 winston: ^3.2.1 @@ -5669,20 +5767,20 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-react@npm:^1.2.4, @backstage/plugin-catalog-react@npm:^1.5.0": - version: 1.5.0 - resolution: "@backstage/plugin-catalog-react@npm:1.5.0" +"@backstage/plugin-catalog-react@npm:^1.2.4, @backstage/plugin-catalog-react@npm:^1.5.0, @backstage/plugin-catalog-react@npm:^1.6.0": + version: 1.6.0 + resolution: "@backstage/plugin-catalog-react@npm:1.6.0" dependencies: "@backstage/catalog-client": ^1.4.1 "@backstage/catalog-model": ^1.3.0 - "@backstage/core-components": ^0.13.0 + "@backstage/core-components": ^0.13.1 "@backstage/core-plugin-api": ^1.5.1 "@backstage/errors": ^1.1.5 - "@backstage/integration": ^1.4.4 + "@backstage/integration": ^1.4.5 "@backstage/plugin-catalog-common": ^1.0.13 "@backstage/plugin-permission-common": ^0.7.5 "@backstage/plugin-permission-react": ^0.4.12 - "@backstage/theme": ^0.2.19 + "@backstage/theme": ^0.3.0 "@backstage/types": ^1.0.2 "@backstage/version-bridge": ^1.0.4 "@material-ui/core": ^4.12.2 @@ -5701,7 +5799,7 @@ __metadata: react: ^16.13.1 || ^17.0.0 react-dom: ^16.13.1 || ^17.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: 0ffa1a9ecf142df389e2ecdbda1fae1718d4b65782654d99cd1de562520aae6ecc4677c15aff50a10fee9d9e89a35d2978e53da8f5f7129deef02c7044eb6e46 + checksum: 17e7a05b2e26511a27ce4ff8b09a40b15adf2e09e4cc57937d3479d83972aeb2be0ef74840c7d5a7c433dd03b9773a6864ae87a638d53f75881ac0007f135cf2 languageName: node linkType: hard @@ -5728,6 +5826,7 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 + "@react-hookz/web": ^23.0.0 "@testing-library/dom": ^8.0.0 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 @@ -6142,6 +6241,86 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-devtools-backend@workspace:^, @backstage/plugin-devtools-backend@workspace:plugins/devtools-backend": + version: 0.0.0-use.local + resolution: "@backstage/plugin-devtools-backend@workspace:plugins/devtools-backend" + dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/cli-common": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/config-loader": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/plugin-auth-node": "workspace:^" + "@backstage/plugin-devtools-common": "workspace:^" + "@backstage/plugin-permission-common": "workspace:^" + "@backstage/plugin-permission-node": "workspace:^" + "@backstage/types": "workspace:^" + "@manypkg/get-packages": ^1.1.3 + "@types/express": "*" + "@types/minimist": ^1.2.0 + "@types/ping": ^0.4.1 + "@types/supertest": ^2.0.8 + "@types/yarnpkg__lockfile": ^1.1.4 + "@yarnpkg/lockfile": ^1.1.0 + "@yarnpkg/parsers": ^3.0.0-rc.4 + express: ^4.18.1 + express-promise-router: ^4.1.0 + fs-extra: ^10.0.0 + lodash: ^4.17.21 + msw: ^1.0.0 + node-fetch: ^2.6.7 + ping: ^0.4.1 + semver: ^7.3.2 + supertest: ^6.2.4 + winston: ^3.2.1 + yn: ^4.0.0 + languageName: unknown + linkType: soft + +"@backstage/plugin-devtools-common@workspace:^, @backstage/plugin-devtools-common@workspace:plugins/devtools-common": + version: 0.0.0-use.local + resolution: "@backstage/plugin-devtools-common@workspace:plugins/devtools-common" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/plugin-permission-common": "workspace:^" + "@backstage/types": "workspace:^" + languageName: unknown + linkType: soft + +"@backstage/plugin-devtools@workspace:^, @backstage/plugin-devtools@workspace:plugins/devtools": + version: 0.0.0-use.local + resolution: "@backstage/plugin-devtools@workspace:plugins/devtools" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-components": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/dev-utils": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/plugin-devtools-common": "workspace:^" + "@backstage/plugin-permission-react": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@backstage/theme": "workspace:^" + "@backstage/types": "workspace:^" + "@material-ui/core": ^4.9.13 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": ^4.0.0-alpha.57 + "@testing-library/jest-dom": ^5.10.1 + "@testing-library/react": ^12.1.3 + "@testing-library/user-event": ^14.0.0 + "@types/node": "*" + cross-fetch: ^3.1.5 + msw: ^1.0.0 + react-json-view: ^1.21.3 + react-use: ^17.2.4 + peerDependencies: + "@types/react": ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + languageName: unknown + linkType: soft + "@backstage/plugin-dynatrace@workspace:^, @backstage/plugin-dynatrace@workspace:plugins/dynatrace": version: 0.0.0-use.local resolution: "@backstage/plugin-dynatrace@workspace:plugins/dynatrace" @@ -6288,8 +6467,8 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-events-backend-module-aws-sqs@workspace:plugins/events-backend-module-aws-sqs" dependencies: - "@aws-sdk/client-sqs": ^3.208.0 - "@aws-sdk/types": ^3.208.0 + "@aws-sdk/client-sqs": ^3.310.0 + "@aws-sdk/types": ^3.310.0 "@backstage/backend-common": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-tasks": "workspace:^" @@ -6696,6 +6875,7 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" "@backstage/integration": "workspace:^" + "@backstage/integration-react": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" @@ -6710,6 +6890,7 @@ __metadata: "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 + git-url-parse: ^13.0.0 luxon: ^3.0.0 msw: ^1.0.0 react-use: ^17.2.4 @@ -6987,16 +7168,45 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-home-react@workspace:^, @backstage/plugin-home-react@workspace:plugins/home-react": + version: 0.0.0-use.local + resolution: "@backstage/plugin-home-react@workspace:plugins/home-react" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-components": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/dev-utils": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@rjsf/utils": 5.6.0 + "@testing-library/dom": ^8.0.0 + "@testing-library/jest-dom": ^5.10.1 + "@testing-library/react": ^12.1.3 + "@testing-library/user-event": ^14.0.0 + "@types/node": ^16.11.26 + "@types/react": ^16.13.1 || ^17.0.0 + "@types/react-grid-layout": ^1.3.2 + cross-fetch: ^3.1.5 + msw: ^1.0.0 + peerDependencies: + react: ^16.13.1 || ^17.0.0 + react-dom: ^16.13.1 || ^17.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + languageName: unknown + linkType: soft + "@backstage/plugin-home@npm:^0.5.1": - version: 0.5.1 - resolution: "@backstage/plugin-home@npm:0.5.1" + version: 0.5.2 + resolution: "@backstage/plugin-home@npm:0.5.2" dependencies: "@backstage/catalog-model": ^1.3.0 "@backstage/config": ^1.0.7 - "@backstage/core-components": ^0.13.0 + "@backstage/core-components": ^0.13.1 "@backstage/core-plugin-api": ^1.5.1 - "@backstage/plugin-catalog-react": ^1.5.0 - "@backstage/theme": ^0.2.19 + "@backstage/plugin-catalog-react": ^1.6.0 + "@backstage/theme": ^0.3.0 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 @@ -7006,7 +7216,6 @@ __metadata: "@rjsf/validator-ajv8": 5.6.0 "@types/react": ^16.13.1 || ^17.0.0 lodash: ^4.17.21 - object-hash: ^3.0.0 react-grid-layout: ^1.3.4 react-resizable: ^3.0.4 react-use: ^17.2.4 @@ -7015,7 +7224,7 @@ __metadata: react: ^16.13.1 || ^17.0.0 react-dom: ^16.13.1 || ^17.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: 0470e0d4848818c59fdf5c3765b769c22bf2b47e26b0ed0c80398baac6a8e1ac703e94152dc20498bfda790aec18a2af65605fcd8c6eb2e7ba7b85eb6ce80b69 + checksum: d12e2cfe771a916cfb6e7ee5da26e50071042289b9be8d4a6aa501267ed3e3b2ec88ed6330d3801c9a241c341f62fd2ab871f20e4a368ee042023e3e930b0db9 languageName: node linkType: hard @@ -7031,6 +7240,7 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" + "@backstage/plugin-home-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" "@material-ui/core": ^4.12.2 @@ -7050,7 +7260,6 @@ __metadata: cross-fetch: ^3.1.5 lodash: ^4.17.21 msw: ^1.0.0 - object-hash: ^3.0.0 react-grid-layout: ^1.3.4 react-resizable: ^3.0.4 react-use: ^17.2.4 @@ -7113,6 +7322,7 @@ __metadata: "@backstage/plugin-auth-node": "workspace:^" "@backstage/plugin-jenkins-common": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" + "@backstage/plugin-permission-node": "workspace:^" "@types/express": ^4.17.6 "@types/jenkins": ^0.23.1 "@types/supertest": ^2.0.8 @@ -7120,6 +7330,7 @@ __metadata: express-promise-router: ^4.1.0 jenkins: ^1.0.0 msw: ^1.0.0 + node-fetch: ^2.6.7 supertest: ^6.1.6 winston: ^3.2.1 yn: ^4.0.0 @@ -7235,7 +7446,7 @@ __metadata: resolution: "@backstage/plugin-kubernetes-backend@workspace:plugins/kubernetes-backend" dependencies: "@aws-crypto/sha256-js": ^3.0.0 - "@aws-sdk/credential-providers": ^3.208.0 + "@aws-sdk/credential-providers": ^3.310.0 "@aws-sdk/signature-v4": ^3.310.0 "@azure/identity": ^2.0.4 "@backstage/backend-common": "workspace:^" @@ -7259,7 +7470,6 @@ __metadata: "@types/express": ^4.17.6 "@types/http-proxy-middleware": ^0.19.3 "@types/luxon": ^3.0.0 - aws4: ^1.11.0 compression: ^1.7.4 cors: ^2.8.5 express: ^4.17.1 @@ -7308,6 +7518,7 @@ __metadata: "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" "@kubernetes-models/apimachinery": ^1.1.0 + "@kubernetes-models/base": ^4.0.1 "@kubernetes/client-node": 0.18.1 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -7400,6 +7611,7 @@ __metadata: dependencies: "@backstage/backend-common": "workspace:^" "@backstage/backend-tasks": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-client": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" @@ -7637,9 +7849,12 @@ __metadata: "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" + "@backstage/plugin-catalog": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" + "@backstage/plugin-permission-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" + "@backstage/types": "workspace:^" "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 @@ -8216,7 +8431,7 @@ __metadata: prom-client: ^14.0.1 supertest: ^6.1.3 uuid: ^8.2.0 - vm2: ^3.9.17 + vm2: ^3.9.18 wait-for-expect: ^3.0.2 winston: ^3.2.1 yaml: ^2.0.0 @@ -8357,7 +8572,7 @@ __metadata: "@uiw/react-codemirror": ^4.9.3 classnames: ^2.2.6 cross-fetch: ^3.1.5 - event-source-polyfill: 1.0.25 + event-source-polyfill: ^1.0.31 git-url-parse: ^13.0.0 humanize-duration: ^3.25.1 immer: ^9.0.1 @@ -8407,14 +8622,14 @@ __metadata: "@backstage/backend-plugin-api": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" + "@backstage/integration-aws-node": "workspace:^" "@backstage/plugin-search-backend-node": "workspace:^" "@backstage/plugin-search-common": "workspace:^" "@elastic/elasticsearch": ^7.13.0 "@elastic/elasticsearch-mock": ^1.0.0 - "@opensearch-project/opensearch": ^2.0.0 + "@opensearch-project/opensearch": ^2.2.1 "@short.io/opensearch-mock": ^0.3.1 - aws-os-connection: ^0.2.0 - aws-sdk: ^2.948.0 + aws4: ^1.12.0 elastic-builder: ^2.16.0 lodash: ^4.17.21 uuid: ^8.3.2 @@ -8824,7 +9039,7 @@ __metadata: "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" - "@backstage/plugin-home": "workspace:^" + "@backstage/plugin-home-react": "workspace:^" "@backstage/plugin-search-common": "workspace:^" "@backstage/plugin-search-react": "workspace:^" "@backstage/test-utils": "workspace:^" @@ -9140,11 +9355,11 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-techdocs-node@workspace:plugins/techdocs-node" dependencies: - "@aws-sdk/client-s3": ^3.208.0 - "@aws-sdk/credential-providers": ^3.208.0 - "@aws-sdk/lib-storage": ^3.208.0 - "@aws-sdk/node-http-handler": ^3.208.0 - "@aws-sdk/types": ^3.208.0 + "@aws-sdk/client-s3": ^3.310.0 + "@aws-sdk/credential-providers": ^3.310.0 + "@aws-sdk/lib-storage": ^3.310.0 + "@aws-sdk/node-http-handler": ^3.310.0 + "@aws-sdk/types": ^3.310.0 "@azure/identity": ^2.1.0 "@azure/storage-blob": ^12.5.0 "@backstage/backend-common": "workspace:^" @@ -9266,6 +9481,7 @@ __metadata: resolution: "@backstage/plugin-todo-backend@workspace:plugins/todo-backend" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-openapi-utils": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/catalog-client": "workspace:^" "@backstage/catalog-model": "workspace:^" @@ -9554,14 +9770,42 @@ __metadata: languageName: unknown linkType: soft -"@backstage/theme@^0.2.16, @backstage/theme@^0.2.18, @backstage/theme@^0.2.19, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": +"@backstage/theme@npm:^0.2.16, @backstage/theme@npm:^0.2.18, @backstage/theme@npm:^0.2.19": + version: 0.2.19 + resolution: "@backstage/theme@npm:0.2.19" + dependencies: + "@material-ui/core": ^4.12.2 + peerDependencies: + react: ^16.13.1 || ^17.0.0 + react-dom: ^16.13.1 || ^17.0.0 + checksum: 93ca110a3f953d6d98b4a5f2163beaa1bd1f95adb66a593e85eb523a7012acf654b6148db54008a6434805a4bd9016d67e5c6a317bc56940ee6800aecbb97d6f + languageName: node + linkType: hard + +"@backstage/theme@npm:^0.3.0": + version: 0.3.0 + resolution: "@backstage/theme@npm:0.3.0" + dependencies: + "@material-ui/core": ^4.12.2 + peerDependencies: + react: ^16.13.1 || ^17.0.0 + react-dom: ^16.13.1 || ^17.0.0 + checksum: 3f9c9452a88d214c13c0136302641ee87424649bdc943c993e98fc7eb08904adf14719a7f5b7d863368d68b08276f18f4e5352c9661fcec78688fb52bd34a22f + languageName: node + linkType: hard + +"@backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": version: 0.0.0-use.local resolution: "@backstage/theme@workspace:packages/theme" dependencies: "@backstage/cli": "workspace:^" - "@material-ui/core": ^4.12.2 + "@emotion/react": ^11.10.5 + "@emotion/styled": ^11.10.5 + "@mui/material": ^5.12.2 "@types/react": ^16.13.1 || ^17.0.0 peerDependencies: + "@material-ui/core": ^4.12.2 + "@types/react": ^16.13.1 || ^17.0.0 react: ^16.13.1 || ^17.0.0 react-dom: ^16.13.1 || ^17.0.0 languageName: unknown @@ -9881,8 +10125,8 @@ __metadata: linkType: hard "@codemirror/language@npm:^6.0.0": - version: 6.6.0 - resolution: "@codemirror/language@npm:6.6.0" + version: 6.7.0 + resolution: "@codemirror/language@npm:6.7.0" dependencies: "@codemirror/state": ^6.0.0 "@codemirror/view": ^6.0.0 @@ -9890,7 +10134,7 @@ __metadata: "@lezer/highlight": ^1.0.0 "@lezer/lr": ^1.0.0 style-mod: ^4.0.0 - checksum: bb9411620e2f231653a3f0c4429e0d19a3843bff5dbc117df4649d7bf783ec4ad809c0add8bc0887a4ec3f48b4f8f941621168e47d76101d5383f0d670af1722 + checksum: 673905e9eb80f039a5e6c59a8aeca217e124a9a03734848043192aeff9e5b3a82f150559f7bd637ee197c4b2171eb5b04e757d717922128ea4fecca1ac6ecac4 languageName: node linkType: hard @@ -9945,13 +10189,13 @@ __metadata: linkType: hard "@codemirror/view@npm:^6.0.0": - version: 6.9.5 - resolution: "@codemirror/view@npm:6.9.5" + version: 6.12.0 + resolution: "@codemirror/view@npm:6.12.0" dependencies: "@codemirror/state": ^6.1.4 style-mod: ^4.0.0 w3c-keyname: ^2.2.4 - checksum: 38039ae5d1cf4ec54c5d0252790a942b5788b9e8670dcf58e63c1f2befe11e852581c88f4e044ca664a7b11c634b1c152099da1a4ac9f454939b20d7c649b808 + checksum: 512cbc9c05ac2cfa738cdf7aac711847b44e24ff5869f31839a9fcc11da6a512448fa9bc980535d55b897de80d49e744336a2724ca1fe3dae8bfcb31e339fe64 languageName: node linkType: hard @@ -10089,6 +10333,41 @@ __metadata: languageName: node linkType: hard +"@emotion/babel-plugin@npm:^11.10.5": + version: 11.10.5 + resolution: "@emotion/babel-plugin@npm:11.10.5" + dependencies: + "@babel/helper-module-imports": ^7.16.7 + "@babel/plugin-syntax-jsx": ^7.17.12 + "@babel/runtime": ^7.18.3 + "@emotion/hash": ^0.9.0 + "@emotion/memoize": ^0.8.0 + "@emotion/serialize": ^1.1.1 + babel-plugin-macros: ^3.1.0 + convert-source-map: ^1.5.0 + escape-string-regexp: ^4.0.0 + find-root: ^1.1.0 + source-map: ^0.5.7 + stylis: 4.1.3 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: e3353499c76c4422d6e900c0dfab73607056d9da86161a3f27c3459c193c4908050c5d252c68fcde231e13f02a9d8e0dc07d260317ae0e5206841e331cc4caae + languageName: node + linkType: hard + +"@emotion/cache@npm:^11.10.5, @emotion/cache@npm:^11.10.7": + version: 11.10.7 + resolution: "@emotion/cache@npm:11.10.7" + dependencies: + "@emotion/memoize": ^0.8.0 + "@emotion/sheet": ^1.2.1 + "@emotion/utils": ^1.2.0 + "@emotion/weak-memoize": ^0.3.0 + stylis: 4.1.3 + checksum: 6b1efed2dffc93dac419409d91f6d57a200d858ec5ffa4b7c30080fdbd93db431ff86bb779c5b8830b8373f3c5dd754d9beb386604ed2667c7d55608ff653dfc + languageName: node + linkType: hard + "@emotion/hash@npm:^0.8.0": version: 0.8.0 resolution: "@emotion/hash@npm:0.8.0" @@ -10096,19 +10375,93 @@ __metadata: languageName: node linkType: hard -"@emotion/is-prop-valid@npm:^1.1.0": - version: 1.1.2 - resolution: "@emotion/is-prop-valid@npm:1.1.2" - dependencies: - "@emotion/memoize": ^0.7.4 - checksum: 58b1f2d429a589f8f5bc2c33a8732cbb7bbcb17131a103511ef9a94ac754d7eeb53d627f947da480cd977f9d419fd92e244991680292f3287204159652745707 +"@emotion/hash@npm:^0.9.0": + version: 0.9.0 + resolution: "@emotion/hash@npm:0.9.0" + checksum: b63428f7c8186607acdca5d003700cecf0ded519d0b5c5cc3b3154eafcad6ff433f8361bd2bac8882715b557e6f06945694aeb6ba8b25c6095d7a88570e2e0bb languageName: node linkType: hard -"@emotion/memoize@npm:^0.7.4": - version: 0.7.5 - resolution: "@emotion/memoize@npm:0.7.5" - checksum: 83da8d4a7649a92c72f960817692bc6be13cc13e107b9f7e878d63766525ed4402881bfeb3cda61145c050281e7e260f114a0a2870515527346f2ef896b915b3 +"@emotion/is-prop-valid@npm:^1.1.0, @emotion/is-prop-valid@npm:^1.2.0": + version: 1.2.0 + resolution: "@emotion/is-prop-valid@npm:1.2.0" + dependencies: + "@emotion/memoize": ^0.8.0 + checksum: cc7a19850a4c5b24f1514665289442c8c641709e6f7711067ad550e05df331da0692a16148e85eda6f47e31b3261b64d74c5e25194d053223be16231f969d633 + languageName: node + linkType: hard + +"@emotion/memoize@npm:^0.8.0": + version: 0.8.0 + resolution: "@emotion/memoize@npm:0.8.0" + checksum: c87bb110b829edd8e1c13b90a6bc37cebc39af29c7599a1e66a48e06f9bec43e8e53495ba86278cc52e7589549492c8dfdc81d19f4fdec0cee6ba13d2ad2c928 + languageName: node + linkType: hard + +"@emotion/react@npm:^11.10.5": + version: 11.10.5 + resolution: "@emotion/react@npm:11.10.5" + dependencies: + "@babel/runtime": ^7.18.3 + "@emotion/babel-plugin": ^11.10.5 + "@emotion/cache": ^11.10.5 + "@emotion/serialize": ^1.1.1 + "@emotion/use-insertion-effect-with-fallbacks": ^1.0.0 + "@emotion/utils": ^1.2.0 + "@emotion/weak-memoize": ^0.3.0 + hoist-non-react-statics: ^3.3.1 + peerDependencies: + "@babel/core": ^7.0.0 + react: ">=16.8.0" + peerDependenciesMeta: + "@babel/core": + optional: true + "@types/react": + optional: true + checksum: 32b67b28e9b6d6c53b970072680697f04c2521441050bdeb19a1a7f0164af549b4dad39ff375eda1b6a3cf1cc86ba2c6fa55460ec040e6ebbca3e9ec58353cf7 + languageName: node + linkType: hard + +"@emotion/serialize@npm:^1.1.1": + version: 1.1.1 + resolution: "@emotion/serialize@npm:1.1.1" + dependencies: + "@emotion/hash": ^0.9.0 + "@emotion/memoize": ^0.8.0 + "@emotion/unitless": ^0.8.0 + "@emotion/utils": ^1.2.0 + csstype: ^3.0.2 + checksum: 24cfd5b16e6f2335c032ca33804a876e0442aaf8f9c94d269d23735ebd194fb1ed142542dd92191a3e6ef8bad5bd560dfc5aaf363a1b70954726dbd4dd93085c + languageName: node + linkType: hard + +"@emotion/sheet@npm:^1.2.1": + version: 1.2.1 + resolution: "@emotion/sheet@npm:1.2.1" + checksum: ce78763588ea522438156344d9f592203e2da582d8d67b32e1b0b98eaba26994c6c270f8c7ad46442fc9c0a9f048685d819cd73ca87e544520fd06f0e24a1562 + languageName: node + linkType: hard + +"@emotion/styled@npm:^11.10.5": + version: 11.10.5 + resolution: "@emotion/styled@npm:11.10.5" + dependencies: + "@babel/runtime": ^7.18.3 + "@emotion/babel-plugin": ^11.10.5 + "@emotion/is-prop-valid": ^1.2.0 + "@emotion/serialize": ^1.1.1 + "@emotion/use-insertion-effect-with-fallbacks": ^1.0.0 + "@emotion/utils": ^1.2.0 + peerDependencies: + "@babel/core": ^7.0.0 + "@emotion/react": ^11.0.0-rc.0 + react: ">=16.8.0" + peerDependenciesMeta: + "@babel/core": + optional: true + "@types/react": + optional: true + checksum: 1cec5f6aeb227a7255141031e8594f38ad83902413472aae0a46c27e5f9769c01e23c1ad39adee408d8a2168a697464314d1a0c4f50b31a5d25ea506b2d7bbc8 languageName: node linkType: hard @@ -10126,6 +10479,36 @@ __metadata: languageName: node linkType: hard +"@emotion/unitless@npm:^0.8.0": + version: 0.8.0 + resolution: "@emotion/unitless@npm:0.8.0" + checksum: 176141117ed23c0eb6e53a054a69c63e17ae532ec4210907a20b2208f91771821835f1c63dd2ec63e30e22fcc984026d7f933773ee6526dd038e0850919fae7a + languageName: node + linkType: hard + +"@emotion/use-insertion-effect-with-fallbacks@npm:^1.0.0": + version: 1.0.0 + resolution: "@emotion/use-insertion-effect-with-fallbacks@npm:1.0.0" + peerDependencies: + react: ">=16.8.0" + checksum: 4f06a3b48258c832aa8022a262572061a31ff078d377e9164cccc99951309d70f4466e774fe704461b2f8715007a82ed625a54a5c7a127c89017d3ce3187d4f1 + languageName: node + linkType: hard + +"@emotion/utils@npm:^1.2.0": + version: 1.2.0 + resolution: "@emotion/utils@npm:1.2.0" + checksum: 55457a49ddd4db6a014ea0454dc09eaa23eedfb837095c8ff90470cb26a303f7ceb5fcc1e2190ef64683e64cfd33d3ba3ca3109cd87d12bc9e379e4195c9a4dd + languageName: node + linkType: hard + +"@emotion/weak-memoize@npm:^0.3.0": + version: 0.3.0 + resolution: "@emotion/weak-memoize@npm:0.3.0" + checksum: f43ef4c8b7de70d9fa5eb3105921724651e4188e895beb71f0c5919dc899a7b8743e1fdd99d38b9092dd5722c7be2312ebb47fbdad0c4e38bea58f6df5885cc0 + languageName: node + linkType: hard + "@esbuild-kit/cjs-loader@npm:^2.4.1": version: 2.4.2 resolution: "@esbuild-kit/cjs-loader@npm:2.4.2" @@ -10153,9 +10536,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/android-arm64@npm:0.17.18" +"@esbuild/android-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/android-arm64@npm:0.17.19" conditions: os=android & cpu=arm64 languageName: node linkType: hard @@ -10174,9 +10557,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/android-arm@npm:0.17.18" +"@esbuild/android-arm@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/android-arm@npm:0.17.19" conditions: os=android & cpu=arm languageName: node linkType: hard @@ -10188,9 +10571,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-x64@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/android-x64@npm:0.17.18" +"@esbuild/android-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/android-x64@npm:0.17.19" conditions: os=android & cpu=x64 languageName: node linkType: hard @@ -10202,9 +10585,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/darwin-arm64@npm:0.17.18" +"@esbuild/darwin-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/darwin-arm64@npm:0.17.19" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard @@ -10216,9 +10599,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/darwin-x64@npm:0.17.18" +"@esbuild/darwin-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/darwin-x64@npm:0.17.19" conditions: os=darwin & cpu=x64 languageName: node linkType: hard @@ -10230,9 +10613,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/freebsd-arm64@npm:0.17.18" +"@esbuild/freebsd-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/freebsd-arm64@npm:0.17.19" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard @@ -10244,9 +10627,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/freebsd-x64@npm:0.17.18" +"@esbuild/freebsd-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/freebsd-x64@npm:0.17.19" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard @@ -10258,9 +10641,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/linux-arm64@npm:0.17.18" +"@esbuild/linux-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-arm64@npm:0.17.19" conditions: os=linux & cpu=arm64 languageName: node linkType: hard @@ -10272,9 +10655,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/linux-arm@npm:0.17.18" +"@esbuild/linux-arm@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-arm@npm:0.17.19" conditions: os=linux & cpu=arm languageName: node linkType: hard @@ -10286,9 +10669,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/linux-ia32@npm:0.17.18" +"@esbuild/linux-ia32@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-ia32@npm:0.17.19" conditions: os=linux & cpu=ia32 languageName: node linkType: hard @@ -10307,9 +10690,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/linux-loong64@npm:0.17.18" +"@esbuild/linux-loong64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-loong64@npm:0.17.19" conditions: os=linux & cpu=loong64 languageName: node linkType: hard @@ -10321,9 +10704,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/linux-mips64el@npm:0.17.18" +"@esbuild/linux-mips64el@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-mips64el@npm:0.17.19" conditions: os=linux & cpu=mips64el languageName: node linkType: hard @@ -10335,9 +10718,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/linux-ppc64@npm:0.17.18" +"@esbuild/linux-ppc64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-ppc64@npm:0.17.19" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard @@ -10349,9 +10732,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/linux-riscv64@npm:0.17.18" +"@esbuild/linux-riscv64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-riscv64@npm:0.17.19" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard @@ -10363,9 +10746,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/linux-s390x@npm:0.17.18" +"@esbuild/linux-s390x@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-s390x@npm:0.17.19" conditions: os=linux & cpu=s390x languageName: node linkType: hard @@ -10377,9 +10760,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/linux-x64@npm:0.17.18" +"@esbuild/linux-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-x64@npm:0.17.19" conditions: os=linux & cpu=x64 languageName: node linkType: hard @@ -10391,9 +10774,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/netbsd-x64@npm:0.17.18" +"@esbuild/netbsd-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/netbsd-x64@npm:0.17.19" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard @@ -10405,9 +10788,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/openbsd-x64@npm:0.17.18" +"@esbuild/openbsd-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/openbsd-x64@npm:0.17.19" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard @@ -10419,9 +10802,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/sunos-x64@npm:0.17.18" +"@esbuild/sunos-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/sunos-x64@npm:0.17.19" conditions: os=sunos & cpu=x64 languageName: node linkType: hard @@ -10433,9 +10816,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/win32-arm64@npm:0.17.18" +"@esbuild/win32-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/win32-arm64@npm:0.17.19" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard @@ -10447,9 +10830,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/win32-ia32@npm:0.17.18" +"@esbuild/win32-ia32@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/win32-ia32@npm:0.17.19" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard @@ -10461,9 +10844,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.17.18": - version: 0.17.18 - resolution: "@esbuild/win32-x64@npm:0.17.18" +"@esbuild/win32-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/win32-x64@npm:0.17.19" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -10486,27 +10869,27 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:^2.0.2": - version: 2.0.2 - resolution: "@eslint/eslintrc@npm:2.0.2" +"@eslint/eslintrc@npm:^2.0.3": + version: 2.0.3 + resolution: "@eslint/eslintrc@npm:2.0.3" dependencies: ajv: ^6.12.4 debug: ^4.3.2 - espree: ^9.5.1 + espree: ^9.5.2 globals: ^13.19.0 ignore: ^5.2.0 import-fresh: ^3.2.1 js-yaml: ^4.1.0 minimatch: ^3.1.2 strip-json-comments: ^3.1.1 - checksum: cfcf5e12c7b2c4476482e7f12434e76eae16fcd163ee627309adb10b761e5caa4a4e52ed7be464423320ff3d11eca5b50de5bf8be3e25834222470835dd5c801 + checksum: ddc51f25f8524d8231db9c9bf03177e503d941a332e8d5ce3b10b09241be4d5584a378a529a27a527586bfbccf3031ae539eb891352033c340b012b4d0c81d92 languageName: node linkType: hard -"@eslint/js@npm:8.38.0": - version: 8.38.0 - resolution: "@eslint/js@npm:8.38.0" - checksum: 1f28987aa8c9cd93e23384e16c7220863b39b5dc4b66e46d7cdbccce868040f455a98d24cd8b567a884f26545a0555b761f7328d4a00c051e7ef689cbea5fce1 +"@eslint/js@npm:8.41.0": + version: 8.41.0 + resolution: "@eslint/js@npm:8.41.0" + checksum: af013d70fe8d0429cdf5cd8b5dcc6fc384ed026c1eccb0cfe30f5849b968ab91645111373fd1b83282b38955b1bdfbe667c1a7dbda3b06cae753521223cad775 languageName: node linkType: hard @@ -10569,27 +10952,27 @@ __metadata: languageName: node linkType: hard -"@frsource/base64@npm:1.0.5": - version: 1.0.5 - resolution: "@frsource/base64@npm:1.0.5" - checksum: ba526dd81df4e91b0abbcc34fc6818c8ff132e5230c23a4448a365ba934f782a86abb2a8566050f9450905851e467a7160f01f3d321fbb0fa3c8c516c5a82b9b +"@frsource/base64@npm:1.0.14": + version: 1.0.14 + resolution: "@frsource/base64@npm:1.0.14" + checksum: 9a5b718e4ac12fd1b5bfdefcdf669fb0a125599fb6cd55564da3beeccd7a5707f58bc41f572268a8120af15ccca32355e8384341561f738397521020e0c2564c languageName: node linkType: hard "@frsource/cypress-plugin-visual-regression-diff@npm:^3.2.8": - version: 3.2.14 - resolution: "@frsource/cypress-plugin-visual-regression-diff@npm:3.2.14" + version: 3.3.1 + resolution: "@frsource/cypress-plugin-visual-regression-diff@npm:3.3.1" dependencies: - "@frsource/base64": 1.0.5 + "@frsource/base64": 1.0.14 glob: 8.0.3 - meta-png: 1.0.5 + meta-png: 1.0.6 move-file: 2.1.0 pixelmatch: 5.3.0 - pngjs: 6.0.0 + pngjs: 7.0.0 sharp: 0.31.2 peerDependencies: cypress: ">=4.5.0" - checksum: 1650eded6db559ef13d0d8b3aba8b19e703dc103a9e806c87cb49ce495a37e296c041530f509f4c0372c15217c8b54a17f51b034261b5b109f4503ab24a8181f + checksum: fae1e9de89fcc0f75a71dd7cc78cb870fa4d0989a0dd2e1084eec2fdc95f9ff503a124f05ea88f87b52c3d03463a79e96439e5620a6c0f24ac39135c81af9edc languageName: node linkType: hard @@ -10651,23 +11034,23 @@ __metadata: linkType: hard "@google-cloud/container@npm:^4.0.0": - version: 4.8.0 - resolution: "@google-cloud/container@npm:4.8.0" + version: 4.11.0 + resolution: "@google-cloud/container@npm:4.11.0" dependencies: google-gax: ^3.5.8 - checksum: f9c64a368d16a3fbc79a122987f99b02d15a82205d13381b30fcb7e012a6a06dc869bc3c07b1325517863df3692e07351e4b8998b774c3b72c31ecd225f2f3bc + checksum: c5257d86ff73a1770ef6004965cca4d2107a3814257a97b4bace14a75be19455d8598db29b43cd66173b847a494cb10b35c9bbdcf8c262726afb4c7a521a8120 languageName: node linkType: hard "@google-cloud/firestore@npm:^6.0.0": - version: 6.5.0 - resolution: "@google-cloud/firestore@npm:6.5.0" + version: 6.6.0 + resolution: "@google-cloud/firestore@npm:6.6.0" dependencies: fast-deep-equal: ^3.1.1 functional-red-black-tree: ^1.0.1 google-gax: ^3.5.7 protobufjs: ^7.0.0 - checksum: dd9cf4eee263a976239232143d5caf213c34850a352c6b6cb15b7b17cfddc2c6bee5e72eed0d188f4317eb5cb6a898372d02c54be8a30bbdc7ffbd360e138cb7 + checksum: a3f6e9998159fae81d1a78371dc5d0d2a5b6b4e8e685ed5bf7a5a66c7b4b36beef010c6d38a77131c76ca4cbf6b9be352ac0dd39a9a9d286e931e8c9eaa95456 languageName: node linkType: hard @@ -10696,8 +11079,8 @@ __metadata: linkType: hard "@google-cloud/storage@npm:^6.0.0": - version: 6.9.5 - resolution: "@google-cloud/storage@npm:6.9.5" + version: 6.10.1 + resolution: "@google-cloud/storage@npm:6.10.1" dependencies: "@google-cloud/paginator": ^3.0.7 "@google-cloud/projectify": ^3.0.0 @@ -10716,7 +11099,7 @@ __metadata: retry-request: ^5.0.0 teeny-request: ^8.0.0 uuid: ^8.0.0 - checksum: eff663cc44ee553fbd2f62b67ef422783f29210c67f55c86c13e63a40c36f3c9b78e076b2a08bb6a74a9fdc452de9240aac91e0fa11c3a4f782416a230d88b74 + checksum: 8908500e3057456ccac5cca17224807898a5c51c0423dec336e802ed0bc0785be7658b0050f848102a2f9207dbf3fb2649f6cc8e515c49fce3a134a8f158ecea languageName: node linkType: hard @@ -12096,44 +12479,45 @@ __metadata: linkType: hard "@keyv/redis@npm:^2.5.3": - version: 2.5.7 - resolution: "@keyv/redis@npm:2.5.7" + version: 2.5.8 + resolution: "@keyv/redis@npm:2.5.8" dependencies: - ioredis: ^5.3.1 - checksum: e0ed1b6602afcc339bb2bf014d8801e6b7a3b6392d0f8e4ccfc59d919f59229b8787c50c48fc51636625ffdf55cf1ef6c450425a73bd88f9b866e74f1b3e25f8 + ioredis: ^5.3.2 + checksum: 1050c4997b62e701112b48e5375c4e53a5e49454c1621fbb00b1c2272e55a575f9ace49c5179800f73e6f07ce247a4cf6e1260a6713ad1392fd8f8825079771f languageName: node linkType: hard "@kubernetes-models/apimachinery@npm:^1.1.0": - version: 1.1.1 - resolution: "@kubernetes-models/apimachinery@npm:1.1.1" + version: 1.2.0 + resolution: "@kubernetes-models/apimachinery@npm:1.2.0" dependencies: - "@kubernetes-models/base": ^4.0.1 - "@kubernetes-models/validate": ^3.0.1 + "@kubernetes-models/base": ^4.0.2 + "@kubernetes-models/validate": ^3.1.0 tslib: ^2.4.0 - checksum: 915d6a55b485335622d43c6e1f1031ea949bfb3e985deba6389462b4c0a3b3030e71e6eebfc1e7b894afee543de2e5a1af0ff6694225a372e220f7dccb5b6eed + checksum: ac93980b732239517af47e0cb512e28fc320ed8348eaa8a68f65b16adc98cf90b6b36d9a9752d825e6e1ac84ae0c0d37e2dc8c8de140011506753a058c89bcf2 languageName: node linkType: hard -"@kubernetes-models/base@npm:^4.0.0, @kubernetes-models/base@npm:^4.0.1": - version: 4.0.1 - resolution: "@kubernetes-models/base@npm:4.0.1" +"@kubernetes-models/base@npm:^4.0.0, @kubernetes-models/base@npm:^4.0.1, @kubernetes-models/base@npm:^4.0.2": + version: 4.0.2 + resolution: "@kubernetes-models/base@npm:4.0.2" dependencies: - "@kubernetes-models/validate": ^3.0.1 + "@kubernetes-models/validate": ^3.1.0 is-plain-object: ^5.0.0 tslib: ^2.4.0 - checksum: c2e91b749b39c068631bf5df1f992f890b20106b7a361e3f12a8c6851719170328a83ac7452b62522aabe1d1c0cc465e1dc06bd20ab749b2315c540da52c1369 + checksum: ab6bae58faca3ee0939746b40e1cea30684d6219877de7ba9953aa06adfd7788c14b3696ba092b3b7583ffb137973715704c68c8035905d610fbf88d9e821f67 languageName: node linkType: hard -"@kubernetes-models/validate@npm:^3.0.0, @kubernetes-models/validate@npm:^3.0.1": - version: 3.0.1 - resolution: "@kubernetes-models/validate@npm:3.0.1" +"@kubernetes-models/validate@npm:^3.0.0, @kubernetes-models/validate@npm:^3.1.0": + version: 3.1.0 + resolution: "@kubernetes-models/validate@npm:3.1.0" dependencies: ajv: ^8.11.0 ajv-formats: ^2.1.1 + ajv-formats-draft2019: ^1.6.1 tslib: ^2.4.0 - checksum: 14b2517c0a6244184df6e00927ec682953c36a623975e862c00a12fa1cbe6c0909dc716b41187b37d572d8dc763a8339e8178df19a33fac26161d12fd861896e + checksum: 774cc4a617ebb14271c471bc1443c74380413d7439d40892e7f1b2ea50d4e88483748c2d59de97a530f76cb3cfcf1c220844b102ebf3f4b386ed7883a920116e languageName: node linkType: hard @@ -12615,9 +12999,9 @@ __metadata: linkType: hard "@microsoft/microsoft-graph-types@npm:^2.25.0, @microsoft/microsoft-graph-types@npm:^2.6.0": - version: 2.25.0 - resolution: "@microsoft/microsoft-graph-types@npm:2.25.0" - checksum: b311385e0a51f827082af5a016f35b1d6cd4d861121e8767b3279ab1a17475977cddbbdcc208abdddf0f953fd6ce4634d3c302e317cf50af4cb6111385347b4f + version: 2.33.0 + resolution: "@microsoft/microsoft-graph-types@npm:2.33.0" + checksum: 9a07e258750cfdedebdc05670c9951fe507ba0868839a411ff36592015660a547d1e4fd9abec1533da979238ef674ce2bf4c363ab0ae2082818313fba0978ecb languageName: node linkType: hard @@ -12666,6 +13050,162 @@ __metadata: languageName: node linkType: hard +"@mui/base@npm:5.0.0-alpha.127": + version: 5.0.0-alpha.127 + resolution: "@mui/base@npm:5.0.0-alpha.127" + dependencies: + "@babel/runtime": ^7.21.0 + "@emotion/is-prop-valid": ^1.2.0 + "@mui/types": ^7.2.4 + "@mui/utils": ^5.12.0 + "@popperjs/core": ^2.11.7 + clsx: ^1.2.1 + prop-types: ^15.8.1 + react-is: ^18.2.0 + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 330baeef1fdaa513707f295e07a3436af24d0831a18109ed877f76b86cf1f392309833d33a2c7ca250db79fdf53f5e88c2618f876f50dbbbf9323bbf08e367e7 + languageName: node + linkType: hard + +"@mui/core-downloads-tracker@npm:^5.12.2": + version: 5.12.2 + resolution: "@mui/core-downloads-tracker@npm:5.12.2" + checksum: d748bdc56df6fdfe6712550a94263cf094c53ddcb70f6a8f633caf23927edf5ac88b1f888429d895fe2a5045b27eb7aa9826ccee5b917e31973667d604ed87fe + languageName: node + linkType: hard + +"@mui/material@npm:^5.12.2": + version: 5.12.2 + resolution: "@mui/material@npm:5.12.2" + dependencies: + "@babel/runtime": ^7.21.0 + "@mui/base": 5.0.0-alpha.127 + "@mui/core-downloads-tracker": ^5.12.2 + "@mui/system": ^5.12.1 + "@mui/types": ^7.2.4 + "@mui/utils": ^5.12.0 + "@types/react-transition-group": ^4.4.5 + clsx: ^1.2.1 + csstype: ^3.1.2 + prop-types: ^15.8.1 + react-is: ^18.2.0 + react-transition-group: ^4.4.5 + peerDependencies: + "@emotion/react": ^11.5.0 + "@emotion/styled": ^11.3.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + "@types/react": + optional: true + checksum: a3464dfbcc496164967e134d6f1d40e060ee02fc2ddb5fcf648ca85580efdbd5eff5aab6a73486d0a7f329f7299127b52501a13993bb131cbd4e310c7f2e633f + languageName: node + linkType: hard + +"@mui/private-theming@npm:^5.12.0": + version: 5.12.0 + resolution: "@mui/private-theming@npm:5.12.0" + dependencies: + "@babel/runtime": ^7.21.0 + "@mui/utils": ^5.12.0 + prop-types: ^15.8.1 + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 761bc7a57e1643c2c4c327886882fa5efc7bacae1c6fffe6be4197f49d337261c916a883d96996445efcdedc0672251725c1e5b264b6250d6c9527fd0cafcc62 + languageName: node + linkType: hard + +"@mui/styled-engine@npm:^5.12.0": + version: 5.12.0 + resolution: "@mui/styled-engine@npm:5.12.0" + dependencies: + "@babel/runtime": ^7.21.0 + "@emotion/cache": ^11.10.7 + csstype: ^3.1.2 + prop-types: ^15.8.1 + peerDependencies: + "@emotion/react": ^11.4.1 + "@emotion/styled": ^11.3.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + checksum: 4a415473cf62aa05012f667dd2e9b1dc2fb175be5b0c4d0b8df541e2dac3d7db410e920e0d5910c8e2b8996a4fb51f74d79483e2878a9b5c0d334498f5537d74 + languageName: node + linkType: hard + +"@mui/system@npm:^5.12.1": + version: 5.12.1 + resolution: "@mui/system@npm:5.12.1" + dependencies: + "@babel/runtime": ^7.21.0 + "@mui/private-theming": ^5.12.0 + "@mui/styled-engine": ^5.12.0 + "@mui/types": ^7.2.4 + "@mui/utils": ^5.12.0 + clsx: ^1.2.1 + csstype: ^3.1.2 + prop-types: ^15.8.1 + peerDependencies: + "@emotion/react": ^11.5.0 + "@emotion/styled": ^11.3.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + "@types/react": + optional: true + checksum: b951959bf5e5af581319354c044f441d97849ff120cfec111d2ed5e7fa05efd63721acff96f48093b8e2bdeb5ccbe35c48613fb925be2b58c596447d10dbed3e + languageName: node + linkType: hard + +"@mui/types@npm:^7.2.4": + version: 7.2.4 + resolution: "@mui/types@npm:7.2.4" + peerDependencies: + "@types/react": "*" + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 16bea0547492193a22fd1794382f314698a114f6c673825314c66b56766c3a9d305992cc495684722b7be16a1ecf7e6e48a79caa64f90c439b530e8c02611a61 + languageName: node + linkType: hard + +"@mui/utils@npm:^5.12.0": + version: 5.12.0 + resolution: "@mui/utils@npm:5.12.0" + dependencies: + "@babel/runtime": ^7.21.0 + "@types/prop-types": ^15.7.5 + "@types/react-is": ^16.7.1 || ^17.0.0 + prop-types: ^15.8.1 + react-is: ^18.2.0 + peerDependencies: + react: ^17.0.0 || ^18.0.0 + checksum: 87b2c7468803b083f50af28d7c215c45291e73fef16570848b596d0f1cde1fc613c20e8951f431217b31451de254744abd50eda5013dedec4982420b5bf1c6b6 + languageName: node + linkType: hard + "@n1ru4l/push-pull-async-iterable-iterator@npm:^3.1.0": version: 3.1.0 resolution: "@n1ru4l/push-pull-async-iterable-iterator@npm:3.1.0" @@ -12972,20 +13512,19 @@ __metadata: linkType: hard "@octokit/auth-app@npm:^4.0.0": - version: 4.0.9 - resolution: "@octokit/auth-app@npm:4.0.9" + version: 4.0.13 + resolution: "@octokit/auth-app@npm:4.0.13" dependencies: "@octokit/auth-oauth-app": ^5.0.0 "@octokit/auth-oauth-user": ^2.0.0 "@octokit/request": ^6.0.0 "@octokit/request-error": ^3.0.0 "@octokit/types": ^9.0.0 - "@types/lru-cache": ^5.1.0 deprecation: ^2.3.1 - lru-cache: ^6.0.0 + lru-cache: ^9.0.0 universal-github-app-jwt: ^1.1.1 universal-user-agent: ^6.0.0 - checksum: 3846ebeda40bf88684fa310741ec4b5838d57e18ba5c38986e422161e1ce95c750053fbb2aa18bdce120d6eb857d16bb8e9988597c3dfda40fec985dbdda1b2a + checksum: 809004bc3e985fd4911cc42060fecd7b88e609e1334b90c4f79711aa27cade03fa1d930945ea8f7339ddd8d4514dd220a6ae8489faefa9e0ce6881519a02fc37 languageName: node linkType: hard @@ -13099,19 +13638,19 @@ __metadata: linkType: hard "@octokit/graphql@npm:^5.0.0": - version: 5.0.5 - resolution: "@octokit/graphql@npm:5.0.5" + version: 5.0.6 + resolution: "@octokit/graphql@npm:5.0.6" dependencies: "@octokit/request": ^6.0.0 "@octokit/types": ^9.0.0 universal-user-agent: ^6.0.0 - checksum: eb2d1a6305a3d1f55ff0ce92fb88b677f0bb789757152d58a79ef61171fb65ecf6fe18d6c27e236c0cee6a0c2600c2cb8370f5ac7184f8e9361c085aa4555bb1 + checksum: 7be545d348ef31dcab0a2478dd64d5746419a2f82f61459c774602bcf8a9b577989c18001f50b03f5f61a3d9e34203bdc021a4e4d75ff2d981e8c9c09cf8a65c languageName: node linkType: hard "@octokit/oauth-app@npm:^4.0.4, @octokit/oauth-app@npm:^4.0.6, @octokit/oauth-app@npm:^4.2.0": - version: 4.2.1 - resolution: "@octokit/oauth-app@npm:4.2.1" + version: 4.2.2 + resolution: "@octokit/oauth-app@npm:4.2.2" dependencies: "@octokit/auth-oauth-app": ^5.0.0 "@octokit/auth-oauth-user": ^2.0.0 @@ -13122,7 +13661,7 @@ __metadata: "@types/aws-lambda": ^8.10.83 fromentries: ^1.3.1 universal-user-agent: ^6.0.0 - checksum: 0f5d4036b027c6611147e5669e3fed0319d486149587c9e408751fd6cf1b4bd9b29b4acd00d51feb33dc1d146bc433c6e5fae96b065804c8f0dc3a5718a42dcf + checksum: a15a849fce7c9b95d3d28583ee20a3a6b4df3d972bf65506204e05ef36998b8bc3359f918524b090157153fb3461e222b7094894bd85374159e84ad774f06ccd languageName: node linkType: hard @@ -13319,8 +13858,8 @@ __metadata: linkType: hard "@octokit/request@npm:^6.0.0": - version: 6.2.3 - resolution: "@octokit/request@npm:6.2.3" + version: 6.2.5 + resolution: "@octokit/request@npm:6.2.5" dependencies: "@octokit/endpoint": ^7.0.0 "@octokit/request-error": ^3.0.0 @@ -13328,7 +13867,7 @@ __metadata: is-plain-object: ^5.0.0 node-fetch: ^2.6.7 universal-user-agent: ^6.0.0 - checksum: fef4097be8375d20bb0b3276d8a3adf866ec628f2b0664d334f3c29b92157da847899497abdc7a5be540053819b55564990543175ad48f04e9e6f25f0395d4d3 + checksum: 856451ea8cc6b1dd0f6e350a141e65c318b5e3a25b8dea373d3afd115f9a3077535a0330f5d90e9db81dc3234dba1dd64edd31e68f639553baa10b4d02b99498 languageName: node linkType: hard @@ -13449,7 +13988,7 @@ __metadata: languageName: node linkType: hard -"@opensearch-project/opensearch@npm:^2.0.0": +"@opensearch-project/opensearch@npm:^2.2.1": version: 2.2.1 resolution: "@opensearch-project/opensearch@npm:2.2.1" dependencies: @@ -13578,6 +14117,13 @@ __metadata: languageName: node linkType: hard +"@popperjs/core@npm:^2.11.7": + version: 2.11.7 + resolution: "@popperjs/core@npm:2.11.7" + checksum: 5b6553747899683452a1d28898c1b39173a4efd780e74360bfcda8eb42f1c5e819602769c81a10920fc68c881d07fb40429604517d499567eac079cfa6470f19 + languageName: node + linkType: hard + "@protobufjs/aspromise@npm:^1.1.1, @protobufjs/aspromise@npm:^1.1.2": version: 1.1.2 resolution: "@protobufjs/aspromise@npm:1.1.2" @@ -13674,6 +14220,22 @@ __metadata: languageName: node linkType: hard +"@react-hookz/web@npm:^23.0.0": + version: 23.0.1 + resolution: "@react-hookz/web@npm:23.0.1" + dependencies: + "@react-hookz/deep-equal": ^1.0.4 + peerDependencies: + js-cookie: ^3.0.5 + react: ^16.8 || ^17 || ^18 + react-dom: ^16.8 || ^17 || ^18 + peerDependenciesMeta: + js-cookie: + optional: true + checksum: 321770570c947321ba44de6ecee17337e4bb0c2a0c9d0dff5cf29e999faa2b7c1132c72a15aface46da9a709b715042ab48a30085d2a8feefba91aac96e82037 + languageName: node + linkType: hard + "@remix-run/router@npm:1.3.2": version: 1.3.2 resolution: "@remix-run/router@npm:1.3.2" @@ -13809,8 +14371,8 @@ __metadata: linkType: hard "@roadiehq/backstage-plugin-github-insights@npm:^2.0.5": - version: 2.3.11 - resolution: "@roadiehq/backstage-plugin-github-insights@npm:2.3.11" + version: 2.3.12 + resolution: "@roadiehq/backstage-plugin-github-insights@npm:2.3.12" dependencies: "@backstage/catalog-model": ^1.3.0 "@backstage/core-components": ^0.13.0 @@ -13832,7 +14394,7 @@ __metadata: react: ^16.13.1 || ^17.0.0 react-dom: ^16.13.1 || ^17.0.0 react-router: 6.0.0-beta.0 || ^6.3.0 - checksum: 175b8b1f7e307fe5e06c3caa2845cee45840e64dfb0fd8a4a7e44f6bfa45a4c0ecc07998ec4239ca39246c073ae55bc4541650b0bb1e43d2ee3441efbedfe3cd + checksum: 4c2b14b43e0daa6aa17aef44b51c74c74a3aa41d48d50644cae58e5e9ae5fdf656d2b71aa7175a3c9c8269ac9cdacfa64c1339f212273849e83020342298ed8c languageName: node linkType: hard @@ -14168,6 +14730,25 @@ __metadata: languageName: node linkType: hard +"@smithy/protocol-http@npm:^1.0.1": + version: 1.0.1 + resolution: "@smithy/protocol-http@npm:1.0.1" + dependencies: + "@smithy/types": ^1.0.0 + tslib: ^2.5.0 + checksum: ba9ac4880fed48eeea0813663c94c765fe5b900f2fdac4f5de6524306bbc6645829f48bc175d202076b83acaccf008ed77f4b5546a4c180315f253e22fe6c89f + languageName: node + linkType: hard + +"@smithy/types@npm:^1.0.0": + version: 1.0.0 + resolution: "@smithy/types@npm:1.0.0" + dependencies: + tslib: ^2.5.0 + checksum: ec05163564af050088f3c21cb047640ca842bea645c2a73624475b486d5df8ad9c494bf683a498f4b467b84fab2817cc199893dfb5cee30dce1e0172ab38db00 + languageName: node + linkType: hard + "@spotify/eslint-config-base@npm:^14.0.0": version: 14.0.1 resolution: "@spotify/eslint-config-base@npm:14.0.1" @@ -14768,90 +15349,90 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-darwin-arm64@npm:1.3.51" +"@swc/core-darwin-arm64@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-darwin-arm64@npm:1.3.59" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-darwin-x64@npm:1.3.51" +"@swc/core-darwin-x64@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-darwin-x64@npm:1.3.59" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.51" +"@swc/core-linux-arm-gnueabihf@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.59" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.51" +"@swc/core-linux-arm64-gnu@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.59" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.51" +"@swc/core-linux-arm64-musl@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.59" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.51" +"@swc/core-linux-x64-gnu@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.59" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-linux-x64-musl@npm:1.3.51" +"@swc/core-linux-x64-musl@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-linux-x64-musl@npm:1.3.59" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.51" +"@swc/core-win32-arm64-msvc@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.59" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.51" +"@swc/core-win32-ia32-msvc@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.59" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.51": - version: 1.3.51 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.51" +"@swc/core-win32-x64-msvc@npm:1.3.59": + version: 1.3.59 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.59" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.46": - version: 1.3.51 - resolution: "@swc/core@npm:1.3.51" + version: 1.3.59 + resolution: "@swc/core@npm:1.3.59" dependencies: - "@swc/core-darwin-arm64": 1.3.51 - "@swc/core-darwin-x64": 1.3.51 - "@swc/core-linux-arm-gnueabihf": 1.3.51 - "@swc/core-linux-arm64-gnu": 1.3.51 - "@swc/core-linux-arm64-musl": 1.3.51 - "@swc/core-linux-x64-gnu": 1.3.51 - "@swc/core-linux-x64-musl": 1.3.51 - "@swc/core-win32-arm64-msvc": 1.3.51 - "@swc/core-win32-ia32-msvc": 1.3.51 - "@swc/core-win32-x64-msvc": 1.3.51 + "@swc/core-darwin-arm64": 1.3.59 + "@swc/core-darwin-x64": 1.3.59 + "@swc/core-linux-arm-gnueabihf": 1.3.59 + "@swc/core-linux-arm64-gnu": 1.3.59 + "@swc/core-linux-arm64-musl": 1.3.59 + "@swc/core-linux-x64-gnu": 1.3.59 + "@swc/core-linux-x64-musl": 1.3.59 + "@swc/core-win32-arm64-msvc": 1.3.59 + "@swc/core-win32-ia32-msvc": 1.3.59 + "@swc/core-win32-x64-msvc": 1.3.59 peerDependencies: "@swc/helpers": ^0.5.0 dependenciesMeta: @@ -14878,16 +15459,16 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: f4e72d347b26353fbb48eae110a63c939922a38b20730ea010f5ae3dd15434f212dce582df05556ec35e677c089dfb6d00f5dd6fc655f8c9a7829458e4301469 + checksum: 0283f39cf49cd12a6dc7062ef9ea4fa93e1a4f622ce46903a09605219f4f47ed5ad03925c6146d09ffe6ee02a89bb14e3c82eb86b4c60ecce4985ea6e078ffcf languageName: node linkType: hard "@swc/helpers@npm:^0.5.0": - version: 0.5.0 - resolution: "@swc/helpers@npm:0.5.0" + version: 0.5.1 + resolution: "@swc/helpers@npm:0.5.1" dependencies: tslib: ^2.4.0 - checksum: 61c9c7dddb707deb58b85328cfe9d211887145f1311ae6a6e6c0fa9f781fb29916a8669a7d479e46e26a32a89d6ef4f293a22dee4925e009c84051e9dd10e8b7 + checksum: 71e0e27234590435e4c62b97ef5e796f88e786841a38c7116a5e27a3eafa7b9ead7cdec5249b32165902076de78446945311c973e59bddf77c1e24f33a8f272a languageName: node linkType: hard @@ -15002,7 +15583,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/jest-dom@npm:^5.10.1, @testing-library/jest-dom@npm:^5.16.4": +"@testing-library/jest-dom@npm:^5.10.1, @testing-library/jest-dom@npm:^5.16.4, @testing-library/jest-dom@npm:^5.16.5": version: 5.16.5 resolution: "@testing-library/jest-dom@npm:5.16.5" dependencies: @@ -15584,12 +16165,12 @@ __metadata: linkType: hard "@types/dockerode@npm:^3.3.0, @types/dockerode@npm:^3.3.8": - version: 3.3.16 - resolution: "@types/dockerode@npm:3.3.16" + version: 3.3.18 + resolution: "@types/dockerode@npm:3.3.18" dependencies: "@types/docker-modem": "*" "@types/node": "*" - checksum: ef316e330f8a1a137962d6000cac53bb25b5ba4300e38dd5842f32a6c58bec420278d61526c68865351c48c7e843c9aa45bcbca332737630a0c251e09390bf5b + checksum: 7ad51a0d6db9343637760a86e3d2ffd2c706db545630806ebfda428f5e8f5e458d4c6cb46657832b0638df7caee7c6922fcfbdc9271f88084e236adddaba7fa2 languageName: node linkType: hard @@ -15636,13 +16217,6 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:^0.0.51": - version: 0.0.51 - resolution: "@types/estree@npm:0.0.51" - checksum: e56a3bcf759fd9185e992e7fdb3c6a5f81e8ff120e871641607581fb3728d16c811702a7d40fa5f869b7f7b4437ab6a87eb8d98ffafeee51e85bbe955932a189 - languageName: node - linkType: hard - "@types/event-source-polyfill@npm:^1.0.0": version: 1.0.1 resolution: "@types/event-source-polyfill@npm:1.0.1" @@ -15658,14 +16232,14 @@ __metadata: linkType: hard "@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.30, @types/express-serve-static-core@npm:^4.17.33, @types/express-serve-static-core@npm:^4.17.5": - version: 4.17.34 - resolution: "@types/express-serve-static-core@npm:4.17.34" + version: 4.17.35 + resolution: "@types/express-serve-static-core@npm:4.17.35" dependencies: "@types/node": "*" "@types/qs": "*" "@types/range-parser": "*" "@types/send": "*" - checksum: 3b5242e7d6cfecca5300635fd2af0f63aca3a92754da79a4a355c4d85b57099aa2cabb1c8557fc38a8a9e6f0be996339140ad017e5be405ea1b877a8294a136d + checksum: cc8995d10c6feda475ec1b3a0e69eb0f35f21ab6b49129ad5c6f279e0bc5de8175bc04ec51304cb79a43eec3ed2f5a1e01472eb6d5f827b8c35c6ca8ad24eb6e languageName: node linkType: hard @@ -16071,13 +16645,6 @@ __metadata: languageName: node linkType: hard -"@types/lru-cache@npm:^5.1.0": - version: 5.1.1 - resolution: "@types/lru-cache@npm:5.1.1" - checksum: e1d6c0085f61b16ec5b3073ec76ad1be4844ea036561c3f145fc19f71f084b58a6eb600b14128aa95809d057d28f1d147c910186ae51219f58366ffd2ff2e118 - languageName: node - linkType: hard - "@types/lunr@npm:^2.3.3": version: 2.3.4 resolution: "@types/lunr@npm:2.3.4" @@ -16103,9 +16670,9 @@ __metadata: linkType: hard "@types/marked@npm:^4.0.0": - version: 4.0.8 - resolution: "@types/marked@npm:4.0.8" - checksum: 68278fa7acaa5d920cdc239d675b5daf842e0ad4779e4848cd617d9baf2ac1afccb5a264c331e37d80031d647e1640cb983cd31e73d45b28552670b4853fad8e + version: 4.3.1 + resolution: "@types/marked@npm:4.3.1" + checksum: eb6891b925d53ea53057f088b28f9232016499e62639cbb4a67f7d34f288ec6a8e40aae4836dbd06bd0fc3c541fca1175cd50d9e8d405547b6be7b7781e6a2a5 languageName: node linkType: hard @@ -16196,12 +16763,12 @@ __metadata: linkType: hard "@types/node-fetch@npm:^2.5.0, @types/node-fetch@npm:^2.5.12, @types/node-fetch@npm:^2.5.7, @types/node-fetch@npm:^2.6.1": - version: 2.6.3 - resolution: "@types/node-fetch@npm:2.6.3" + version: 2.6.4 + resolution: "@types/node-fetch@npm:2.6.4" dependencies: "@types/node": "*" form-data: ^3.0.0 - checksum: b68cda58e91535a42dd5337932443c37f8e198ca1e8deeb95bd92a64a9a84d92071867b91c5eb84ee8e13f33d45a70549fe2bc11dd070a894dd561909f4d39f5 + checksum: f3e1d881bb42269e676ecaf49f0e096ab345e22823a2b2d071d60619414817fe02df48a31a8d05adb23054028a2a65521bdb3906ceb763ab6d3339c8d8775058 languageName: node linkType: hard @@ -16214,10 +16781,10 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:>=12.12.47, @types/node@npm:>=13.7.0, @types/node@npm:^18.11.17": - version: 18.16.3 - resolution: "@types/node@npm:18.16.3" - checksum: 816b39d45b05ebdc6f362b630970df3f6d82f71d418a2555353522f4eeeb078fa201de5299f02c09a09faa975e43b2745fe19c263d44069f87ddf37d6c37b717 +"@types/node@npm:*, @types/node@npm:>=12.12.47, @types/node@npm:>=13.7.0": + version: 20.2.2 + resolution: "@types/node@npm:20.2.2" + checksum: a39bef01b7592fd35c5704c74b9167c154a9a357017db8cd8644461c6e6ad87be19f82dfc65ecb2f35a8fb143fc8a0587f17507bc0b0c9bfee676b3fb4bc89ae languageName: node linkType: hard @@ -16236,9 +16803,9 @@ __metadata: linkType: hard "@types/node@npm:^14.14.31": - version: 14.18.43 - resolution: "@types/node@npm:14.18.43" - checksum: 3ef43eda265c346597bc5c8329605255550f7a92300a76e9e3c48e07fd685b4a48d47465997bf6f1a68b235c7339e6e583d73515769efcad70e4f8f4c7f47fd4 + version: 14.18.47 + resolution: "@types/node@npm:14.18.47" + checksum: 249467fa37e60bb7ce631616a5fea53f3b957a6792c6a09f7db7cdff85a7410c9e657dd9fa54bcc9d878e58f35407ce35169b84556f46b2154f90bc71063e1d0 languageName: node linkType: hard @@ -16250,9 +16817,16 @@ __metadata: linkType: hard "@types/node@npm:^16.0.0, @types/node@npm:^16.11.26, @types/node@npm:^16.9.2": - version: 16.18.25 - resolution: "@types/node@npm:16.18.25" - checksum: 181760ad6b54fcc498dfeb249e98bbf0be51d7c35e92e760e1a82004fa42b86e8c33a8f8dd7743b5ef872bda0753d9e6a5b8e3f0aed63e9eb79b4e65760c1fbe + version: 16.18.32 + resolution: "@types/node@npm:16.18.32" + checksum: c5966c8e671205b2971ae66ae548ce92235cef89ae1a0f2ecbf118e775923259dc85f57c58cfc56267089d56dfce967700c058276199c6ed9510d0a0b077af2d + languageName: node + linkType: hard + +"@types/node@npm:^18.11.17": + version: 18.16.14 + resolution: "@types/node@npm:18.16.14" + checksum: c11cb3c787236414efe58240ae71854971592554d82ff9d201876ce7cafd51c37aaa001c63602d002e8238614d7331bd6d48ac4c1c0caa826799980b6846fb08 languageName: node linkType: hard @@ -16385,6 +16959,13 @@ __metadata: languageName: node linkType: hard +"@types/ping@npm:^0.4.1": + version: 0.4.1 + resolution: "@types/ping@npm:0.4.1" + checksum: 9b94837fe66df70558c5a42b0e0c8371b4950ab56b96c42c8df809ff2cf52477dd0a7e01d2e6b38af8bb6683b3dcb54587960b96b4b1f3d40fdb529aea348ad0 + languageName: node + linkType: hard + "@types/pluralize@npm:^0.0.29": version: 0.0.29 resolution: "@types/pluralize@npm:0.0.29" @@ -16399,7 +16980,7 @@ __metadata: languageName: node linkType: hard -"@types/prop-types@npm:*, @types/prop-types@npm:^15.0.0, @types/prop-types@npm:^15.7.3": +"@types/prop-types@npm:*, @types/prop-types@npm:^15.0.0, @types/prop-types@npm:^15.7.3, @types/prop-types@npm:^15.7.5": version: 15.7.5 resolution: "@types/prop-types@npm:15.7.5" checksum: 5b43b8b15415e1f298243165f1d44390403bb2bd42e662bca3b5b5633fdd39c938e91b7fce3a9483699db0f7a715d08cef220c121f723a634972fdf596aec980 @@ -16465,6 +17046,15 @@ __metadata: languageName: node linkType: hard +"@types/react-is@npm:^16.7.1 || ^17.0.0": + version: 17.0.3 + resolution: "@types/react-is@npm:17.0.3" + dependencies: + "@types/react": "*" + checksum: 6abb7c47d54f012272650df8a962a28bd82f219291e5ef8b4dfa7fe0bb98ae243b060bf9fbe8ceff6213141794855a006db194b490b00ffd15842ae19d0ce1f0 + languageName: node + linkType: hard + "@types/react-redux@npm:^7.1.16": version: 7.1.19 resolution: "@types/react-redux@npm:7.1.19" @@ -16513,12 +17103,12 @@ __metadata: languageName: node linkType: hard -"@types/react-transition-group@npm:^4.2.0": - version: 4.2.4 - resolution: "@types/react-transition-group@npm:4.2.4" +"@types/react-transition-group@npm:^4.2.0, @types/react-transition-group@npm:^4.4.5": + version: 4.4.5 + resolution: "@types/react-transition-group@npm:4.4.5" dependencies: "@types/react": "*" - checksum: a8abb3ad3c6e0575c630b591503a78ae3a94e21d1285905a49c36168e5d3de68b0886e2c6d75b751e30f2dc6e4245351cde30e4b3ff2649aec345f2088961e2c + checksum: 265f1c74061556708ffe8d15559e35c60d6c11478c9950d3735575d2c116ca69f461d85effa06d73a613eb8b73c84fd32682feb57cf7c5f9e4284021dbca25b0 languageName: node linkType: hard @@ -16850,12 +17440,12 @@ __metadata: linkType: hard "@types/tar@npm:^6.1.1": - version: 6.1.4 - resolution: "@types/tar@npm:6.1.4" + version: 6.1.5 + resolution: "@types/tar@npm:6.1.5" dependencies: "@types/node": "*" minipass: ^4.0.0 - checksum: 48a1f6b8665ed03f37f74966cfe991a33d6e85cee28aaa6ef42c7ca8448cdbc1e2ca96b473b6b53f1d7bd91423ae0dcfe54a295607d7ac4b4cbb9dbf167df7fa + checksum: 1efa71c8d72f2b02d16ffecb65c4a96be9dacce000c4207532a686477386524dd99b6e26904319354be3ac9ac4d41296a0cb9cf87d05f8f21ae31c68fe446348 languageName: node linkType: hard @@ -16878,11 +17468,11 @@ __metadata: linkType: hard "@types/testing-library__jest-dom@npm:^5.9.1": - version: 5.14.5 - resolution: "@types/testing-library__jest-dom@npm:5.14.5" + version: 5.14.6 + resolution: "@types/testing-library__jest-dom@npm:5.14.6" dependencies: "@types/jest": "*" - checksum: dcb05416758fe88c1f4f3aa97b4699fcb46a5ed8f53c6b81721e66155452a48caf12ecb97dfdfd4130678e65efd66b9fca0ac434b3d63affec84842a84a6bf38 + checksum: 92f81cefeacba3b5c06d4b3fbea0341fe2bcaa6e425c026ae262de39f1148c2588cf3003112aa4ac0880c3972ffb77641a863f3be71518d1d8080402c944e326 languageName: node linkType: hard @@ -16964,13 +17554,13 @@ __metadata: linkType: hard "@types/webpack@npm:^5.28.0": - version: 5.28.0 - resolution: "@types/webpack@npm:5.28.0" + version: 5.28.1 + resolution: "@types/webpack@npm:5.28.1" dependencies: "@types/node": "*" tapable: ^2.2.0 webpack: ^5 - checksum: a038d7e12dd109c6a8d2eb744fd32070ef94f1655e730fb1443b370db98864c3a0e408638b02d12ba08269b9c012b3be8b801117ced2d1102e7676203fd663ed + checksum: 9f9bfe041382acfab36015f95011f6539705ba116fd9b3b8d7599a6396d996b7efcdb71947dba6d24a1a1bf397d15fdfb3c50d2f73e0aa5366a76198d5ec98b3 languageName: node linkType: hard @@ -17344,154 +17934,154 @@ __metadata: languageName: node linkType: hard -"@webassemblyjs/ast@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/ast@npm:1.11.1" +"@webassemblyjs/ast@npm:1.11.6, @webassemblyjs/ast@npm:^1.11.5": + version: 1.11.6 + resolution: "@webassemblyjs/ast@npm:1.11.6" dependencies: - "@webassemblyjs/helper-numbers": 1.11.1 - "@webassemblyjs/helper-wasm-bytecode": 1.11.1 - checksum: 1eee1534adebeece635362f8e834ae03e389281972611408d64be7895fc49f48f98fddbbb5339bf8a72cb101bcb066e8bca3ca1bf1ef47dadf89def0395a8d87 + "@webassemblyjs/helper-numbers": 1.11.6 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + checksum: 38ef1b526ca47c210f30975b06df2faf1a8170b1636ce239fc5738fc231ce28389dd61ecedd1bacfc03cbe95b16d1af848c805652080cb60982836eb4ed2c6cf languageName: node linkType: hard -"@webassemblyjs/floating-point-hex-parser@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/floating-point-hex-parser@npm:1.11.1" - checksum: b8efc6fa08e4787b7f8e682182d84dfdf8da9d9c77cae5d293818bc4a55c1f419a87fa265ab85252b3e6c1fd323d799efea68d825d341a7c365c64bc14750e97 +"@webassemblyjs/floating-point-hex-parser@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/floating-point-hex-parser@npm:1.11.6" + checksum: 29b08758841fd8b299c7152eda36b9eb4921e9c584eb4594437b5cd90ed6b920523606eae7316175f89c20628da14326801090167cc7fbffc77af448ac84b7e2 languageName: node linkType: hard -"@webassemblyjs/helper-api-error@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/helper-api-error@npm:1.11.1" - checksum: 0792813f0ed4a0e5ee0750e8b5d0c631f08e927f4bdfdd9fe9105dc410c786850b8c61bff7f9f515fdfb149903bec3c976a1310573a4c6866a94d49bc7271959 +"@webassemblyjs/helper-api-error@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-api-error@npm:1.11.6" + checksum: e8563df85161096343008f9161adb138a6e8f3c2cc338d6a36011aa55eabb32f2fd138ffe63bc278d009ada001cc41d263dadd1c0be01be6c2ed99076103689f languageName: node linkType: hard -"@webassemblyjs/helper-buffer@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/helper-buffer@npm:1.11.1" - checksum: a337ee44b45590c3a30db5a8b7b68a717526cf967ada9f10253995294dbd70a58b2da2165222e0b9830cd4fc6e4c833bf441a721128d1fe2e9a7ab26b36003ce +"@webassemblyjs/helper-buffer@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-buffer@npm:1.11.6" + checksum: b14d0573bf680d22b2522e8a341ec451fddd645d1f9c6bd9012ccb7e587a2973b86ab7b89fe91e1c79939ba96095f503af04369a3b356c8023c13a5893221644 languageName: node linkType: hard -"@webassemblyjs/helper-numbers@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/helper-numbers@npm:1.11.1" +"@webassemblyjs/helper-numbers@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-numbers@npm:1.11.6" dependencies: - "@webassemblyjs/floating-point-hex-parser": 1.11.1 - "@webassemblyjs/helper-api-error": 1.11.1 + "@webassemblyjs/floating-point-hex-parser": 1.11.6 + "@webassemblyjs/helper-api-error": 1.11.6 "@xtuc/long": 4.2.2 - checksum: 44d2905dac2f14d1e9b5765cf1063a0fa3d57295c6d8930f6c59a36462afecc6e763e8a110b97b342a0f13376166c5d41aa928e6ced92e2f06b071fd0db59d3a + checksum: f4b562fa219f84368528339e0f8d273ad44e047a07641ffcaaec6f93e5b76fd86490a009aa91a294584e1436d74b0a01fa9fde45e333a4c657b58168b04da424 languageName: node linkType: hard -"@webassemblyjs/helper-wasm-bytecode@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/helper-wasm-bytecode@npm:1.11.1" - checksum: eac400113127832c88f5826bcc3ad1c0db9b3dbd4c51a723cfdb16af6bfcbceb608170fdaac0ab7731a7e18b291be7af68a47fcdb41cfe0260c10857e7413d97 +"@webassemblyjs/helper-wasm-bytecode@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-wasm-bytecode@npm:1.11.6" + checksum: 3535ef4f1fba38de3475e383b3980f4bbf3de72bbb631c2b6584c7df45be4eccd62c6ff48b5edd3f1bcff275cfd605a37679ec199fc91fd0a7705d7f1e3972dc languageName: node linkType: hard -"@webassemblyjs/helper-wasm-section@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/helper-wasm-section@npm:1.11.1" +"@webassemblyjs/helper-wasm-section@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-wasm-section@npm:1.11.6" dependencies: - "@webassemblyjs/ast": 1.11.1 - "@webassemblyjs/helper-buffer": 1.11.1 - "@webassemblyjs/helper-wasm-bytecode": 1.11.1 - "@webassemblyjs/wasm-gen": 1.11.1 - checksum: 617696cfe8ecaf0532763162aaf748eb69096fb27950219bb87686c6b2e66e11cd0614d95d319d0ab1904bc14ebe4e29068b12c3e7c5e020281379741fe4bedf + "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/helper-buffer": 1.11.6 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + "@webassemblyjs/wasm-gen": 1.11.6 + checksum: b2cf751bf4552b5b9999d27bbb7692d0aca75260140195cb58ea6374d7b9c2dc69b61e10b211a0e773f66209c3ddd612137ed66097e3684d7816f854997682e9 languageName: node linkType: hard -"@webassemblyjs/ieee754@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/ieee754@npm:1.11.1" +"@webassemblyjs/ieee754@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/ieee754@npm:1.11.6" dependencies: "@xtuc/ieee754": ^1.2.0 - checksum: 23a0ac02a50f244471631802798a816524df17e56b1ef929f0c73e3cde70eaf105a24130105c60aff9d64a24ce3b640dad443d6f86e5967f922943a7115022ec + checksum: 13574b8e41f6ca39b700e292d7edf102577db5650fe8add7066a320aa4b7a7c09a5056feccac7a74eb68c10dea9546d4461412af351f13f6b24b5f32379b49de languageName: node linkType: hard -"@webassemblyjs/leb128@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/leb128@npm:1.11.1" +"@webassemblyjs/leb128@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/leb128@npm:1.11.6" dependencies: "@xtuc/long": 4.2.2 - checksum: 33ccc4ade2f24de07bf31690844d0b1ad224304ee2062b0e464a610b0209c79e0b3009ac190efe0e6bd568b0d1578d7c3047fc1f9d0197c92fc061f56224ff4a + checksum: 7ea942dc9777d4b18a5ebfa3a937b30ae9e1d2ce1fee637583ed7f376334dd1d4274f813d2e250056cca803e0952def4b954913f1a3c9068bcd4ab4ee5143bf0 languageName: node linkType: hard -"@webassemblyjs/utf8@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/utf8@npm:1.11.1" - checksum: 972c5cfc769d7af79313a6bfb96517253a270a4bf0c33ba486aa43cac43917184fb35e51dfc9e6b5601548cd5931479a42e42c89a13bb591ffabebf30c8a6a0b +"@webassemblyjs/utf8@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/utf8@npm:1.11.6" + checksum: 807fe5b5ce10c390cfdd93e0fb92abda8aebabb5199980681e7c3743ee3306a75729bcd1e56a3903980e96c885ee53ef901fcbaac8efdfa480f9c0dae1d08713 languageName: node linkType: hard -"@webassemblyjs/wasm-edit@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/wasm-edit@npm:1.11.1" +"@webassemblyjs/wasm-edit@npm:^1.11.5": + version: 1.11.6 + resolution: "@webassemblyjs/wasm-edit@npm:1.11.6" dependencies: - "@webassemblyjs/ast": 1.11.1 - "@webassemblyjs/helper-buffer": 1.11.1 - "@webassemblyjs/helper-wasm-bytecode": 1.11.1 - "@webassemblyjs/helper-wasm-section": 1.11.1 - "@webassemblyjs/wasm-gen": 1.11.1 - "@webassemblyjs/wasm-opt": 1.11.1 - "@webassemblyjs/wasm-parser": 1.11.1 - "@webassemblyjs/wast-printer": 1.11.1 - checksum: 6d7d9efaec1227e7ef7585a5d7ff0be5f329f7c1c6b6c0e906b18ed2e9a28792a5635e450aca2d136770d0207225f204eff70a4b8fd879d3ac79e1dcc26dbeb9 + "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/helper-buffer": 1.11.6 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + "@webassemblyjs/helper-wasm-section": 1.11.6 + "@webassemblyjs/wasm-gen": 1.11.6 + "@webassemblyjs/wasm-opt": 1.11.6 + "@webassemblyjs/wasm-parser": 1.11.6 + "@webassemblyjs/wast-printer": 1.11.6 + checksum: 29ce75870496d6fad864d815ebb072395a8a3a04dc9c3f4e1ffdc63fc5fa58b1f34304a1117296d8240054cfdbc38aca88e71fb51483cf29ffab0a61ef27b481 languageName: node linkType: hard -"@webassemblyjs/wasm-gen@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/wasm-gen@npm:1.11.1" +"@webassemblyjs/wasm-gen@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/wasm-gen@npm:1.11.6" dependencies: - "@webassemblyjs/ast": 1.11.1 - "@webassemblyjs/helper-wasm-bytecode": 1.11.1 - "@webassemblyjs/ieee754": 1.11.1 - "@webassemblyjs/leb128": 1.11.1 - "@webassemblyjs/utf8": 1.11.1 - checksum: 1f6921e640293bf99fb16b21e09acb59b340a79f986c8f979853a0ae9f0b58557534b81e02ea2b4ef11e929d946708533fd0693c7f3712924128fdafd6465f5b + "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + "@webassemblyjs/ieee754": 1.11.6 + "@webassemblyjs/leb128": 1.11.6 + "@webassemblyjs/utf8": 1.11.6 + checksum: a645a2eecbea24833c3260a249704a7f554ef4a94c6000984728e94bb2bc9140a68dfd6fd21d5e0bbb09f6dfc98e083a45760a83ae0417b41a0196ff6d45a23a languageName: node linkType: hard -"@webassemblyjs/wasm-opt@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/wasm-opt@npm:1.11.1" +"@webassemblyjs/wasm-opt@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/wasm-opt@npm:1.11.6" dependencies: - "@webassemblyjs/ast": 1.11.1 - "@webassemblyjs/helper-buffer": 1.11.1 - "@webassemblyjs/wasm-gen": 1.11.1 - "@webassemblyjs/wasm-parser": 1.11.1 - checksum: 21586883a20009e2b20feb67bdc451bbc6942252e038aae4c3a08e6f67b6bae0f5f88f20bfc7bd0452db5000bacaf5ab42b98cf9aa034a6c70e9fc616142e1db + "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/helper-buffer": 1.11.6 + "@webassemblyjs/wasm-gen": 1.11.6 + "@webassemblyjs/wasm-parser": 1.11.6 + checksum: b4557f195487f8e97336ddf79f7bef40d788239169aac707f6eaa2fa5fe243557c2d74e550a8e57f2788e70c7ae4e7d32f7be16101afe183d597b747a3bdd528 languageName: node linkType: hard -"@webassemblyjs/wasm-parser@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/wasm-parser@npm:1.11.1" +"@webassemblyjs/wasm-parser@npm:1.11.6, @webassemblyjs/wasm-parser@npm:^1.11.5": + version: 1.11.6 + resolution: "@webassemblyjs/wasm-parser@npm:1.11.6" dependencies: - "@webassemblyjs/ast": 1.11.1 - "@webassemblyjs/helper-api-error": 1.11.1 - "@webassemblyjs/helper-wasm-bytecode": 1.11.1 - "@webassemblyjs/ieee754": 1.11.1 - "@webassemblyjs/leb128": 1.11.1 - "@webassemblyjs/utf8": 1.11.1 - checksum: 1521644065c360e7b27fad9f4bb2df1802d134dd62937fa1f601a1975cde56bc31a57b6e26408b9ee0228626ff3ba1131ae6f74ffb7d718415b6528c5a6dbfc2 + "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/helper-api-error": 1.11.6 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + "@webassemblyjs/ieee754": 1.11.6 + "@webassemblyjs/leb128": 1.11.6 + "@webassemblyjs/utf8": 1.11.6 + checksum: 8200a8d77c15621724a23fdabe58d5571415cda98a7058f542e670ea965dd75499f5e34a48675184947c66f3df23adf55df060312e6d72d57908e3f049620d8a languageName: node linkType: hard -"@webassemblyjs/wast-printer@npm:1.11.1": - version: 1.11.1 - resolution: "@webassemblyjs/wast-printer@npm:1.11.1" +"@webassemblyjs/wast-printer@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/wast-printer@npm:1.11.6" dependencies: - "@webassemblyjs/ast": 1.11.1 + "@webassemblyjs/ast": 1.11.6 "@xtuc/long": 4.2.2 - checksum: f15ae4c2441b979a3b4fce78f3d83472fb22350c6dc3fd34bfe7c3da108e0b2360718734d961bba20e7716cb8578e964b870da55b035e209e50ec9db0378a3f7 + checksum: d2fa6a4c427325ec81463e9c809aa6572af6d47f619f3091bf4c4a6fc34f1da3df7caddaac50b8e7a457f8784c62cd58c6311b6cb69b0162ccd8d4c072f79cf8 languageName: node linkType: hard @@ -17808,6 +18398,20 @@ __metadata: languageName: node linkType: hard +"ajv-formats-draft2019@npm:^1.6.1": + version: 1.6.1 + resolution: "ajv-formats-draft2019@npm:1.6.1" + dependencies: + punycode: ^2.1.1 + schemes: ^1.4.0 + smtp-address-parser: ^1.0.3 + uri-js: ^4.4.1 + peerDependencies: + ajv: "*" + checksum: 281f802f76defbb5821fa19e60b38c7be13d2a89d5f915ee11dc32c4be631f4785bb67595edf2657c2b05697e6cb89d50ef4c5fecbd0c814c0e05132ed3a650c + languageName: node + linkType: hard + "ajv-formats@npm:^2.1.1": version: 2.1.1 resolution: "ajv-formats@npm:2.1.1" @@ -18379,18 +18983,6 @@ __metadata: languageName: node linkType: hard -"aws-os-connection@npm:^0.2.0": - version: 0.2.0 - resolution: "aws-os-connection@npm:0.2.0" - dependencies: - aws4: ^1.11.0 - peerDependencies: - "@opensearch-project/opensearch": 2 - aws-sdk: ">=2" - checksum: 1708ffd9bdc5f7bd6b8447f97859936a8657f4df567f61f12dacd040e6f1a25020bbea8027bb28f19fe27d171a0d3a5090c2d84d6f752bb04e387640413fec7c - languageName: node - linkType: hard - "aws-sdk-client-mock-jest@npm:^2.0.0": version: 2.1.1 resolution: "aws-sdk-client-mock-jest@npm:2.1.1" @@ -18425,7 +19017,7 @@ __metadata: languageName: node linkType: hard -"aws-sdk@npm:^2.1231.0, aws-sdk@npm:^2.840.0, aws-sdk@npm:^2.948.0": +"aws-sdk@npm:^2.1231.0": version: 2.1279.0 resolution: "aws-sdk@npm:2.1279.0" dependencies: @@ -18450,7 +19042,7 @@ __metadata: languageName: node linkType: hard -"aws4@npm:^1.11.0, aws4@npm:^1.8.0": +"aws4@npm:^1.11.0, aws4@npm:^1.12.0, aws4@npm:^1.8.0": version: 1.12.0 resolution: "aws4@npm:1.12.0" checksum: 68f79708ac7c335992730bf638286a3ee0a645cf12575d557860100767c500c08b30e24726b9f03265d74116417f628af78509e1333575e9f8d52a80edfe8cbc @@ -18587,6 +19179,17 @@ __metadata: languageName: node linkType: hard +"babel-plugin-macros@npm:^3.1.0": + version: 3.1.0 + resolution: "babel-plugin-macros@npm:3.1.0" + dependencies: + "@babel/runtime": ^7.12.5 + cosmiconfig: ^7.0.0 + resolve: ^1.19.0 + checksum: 765de4abebd3e4688ebdfbff8571ddc8cd8061f839bb6c3e550b0344a4027b04c60491f843296ce3f3379fb356cc873d57a9ee6694262547eb822c14a25be9a6 + languageName: node + linkType: hard + "babel-plugin-polyfill-corejs2@npm:^0.3.1": version: 0.3.1 resolution: "babel-plugin-polyfill-corejs2@npm:0.3.1" @@ -18786,6 +19389,13 @@ __metadata: languageName: node linkType: hard +"base16@npm:^1.0.0": + version: 1.0.0 + resolution: "base16@npm:1.0.0" + checksum: 0cd449a2db0f0f957e4b6b57e33bc43c9e20d4f1dd744065db94b5da35e8e71fa4dc4bc7a901e59a84d5f8b6936e3c520e2471787f667fc155fb0f50d8540f5d + languageName: node + linkType: hard + "base64-js@npm:^1.0.2, base64-js@npm:^1.3.0, base64-js@npm:^1.3.1, base64-js@npm:^1.5.1": version: 1.5.1 resolution: "base64-js@npm:1.5.1" @@ -18849,13 +19459,13 @@ __metadata: linkType: hard "better-sqlite3@npm:^8.0.0": - version: 8.3.0 - resolution: "better-sqlite3@npm:8.3.0" + version: 8.4.0 + resolution: "better-sqlite3@npm:8.4.0" dependencies: bindings: ^1.5.0 node-gyp: latest prebuild-install: ^7.1.0 - checksum: 00fc9f12058d2d157f56fe57b0f5c8ba705aee22a1dfe33ef8f60755531eda8f809cdb2377af314f6ed9396ad036094576e0596649bd6ca5bcaec172613e2dc9 + checksum: f8b180c26428a2d381482e83b4519d0d81a918e00f92cafd255f42eb9583f49b2fed1015121ad49ebe1f3f790cc8c6f4697d1e805193d65e70dacf2e8abbd6af languageName: node linkType: hard @@ -20035,7 +20645,7 @@ __metadata: languageName: node linkType: hard -"clsx@npm:^1.0.2, clsx@npm:^1.0.4, clsx@npm:^1.1.1": +"clsx@npm:^1.0.2, clsx@npm:^1.0.4, clsx@npm:^1.1.1, clsx@npm:^1.2.1": version: 1.2.1 resolution: "clsx@npm:1.2.1" checksum: 30befca8019b2eb7dbad38cff6266cf543091dae2825c856a62a8ccf2c3ab9c2907c4d12b288b73101196767f66812365400a227581484a05f968b0307cfaf12 @@ -20314,7 +20924,7 @@ __metadata: languageName: node linkType: hard -"commander@npm:^2.20.0, commander@npm:^2.7.1": +"commander@npm:^2.19.0, commander@npm:^2.20.0, commander@npm:^2.7.1": version: 2.20.3 resolution: "commander@npm:2.20.3" checksum: ab8c07884e42c3a8dbc5dd9592c606176c7eb5c1ca5ff274bcf907039b2c41de3626f684ea75ccf4d361ba004bbaff1f577d5384c155f3871e456bdf27becf9e @@ -20537,6 +21147,16 @@ __metadata: languageName: node linkType: hard +"connect-session-knex@npm:^3.0.1": + version: 3.0.1 + resolution: "connect-session-knex@npm:3.0.1" + dependencies: + bluebird: ^3.7.2 + knex: ^2.3.0 + checksum: f5a80c3c34d30e7cd4e79a6aae09d112825986d51ddc3a4563ef95ade425178239d4e3e05420fb3b6204b2353b0dfd754d318b288989b539583f6c0e52758b7a + languageName: node + linkType: hard + "consola@npm:^2.15.0": version: 2.15.3 resolution: "consola@npm:2.15.3" @@ -20608,12 +21228,10 @@ __metadata: languageName: node linkType: hard -"convert-source-map@npm:^1.6.0, convert-source-map@npm:^1.7.0": - version: 1.7.0 - resolution: "convert-source-map@npm:1.7.0" - dependencies: - safe-buffer: ~5.1.1 - checksum: bcd2e3ea7d37f96b85a6e362c8a89402ccc73757256e3ee53aa2c22fe915adb854c66b1f81111be815a3a6a6ce3c58e8001858e883c9d5b4fe08a853fa865967 +"convert-source-map@npm:^1.5.0, convert-source-map@npm:^1.6.0, convert-source-map@npm:^1.7.0": + version: 1.9.0 + resolution: "convert-source-map@npm:1.9.0" + checksum: dc55a1f28ddd0e9485ef13565f8f756b342f9a46c4ae18b843fe3c30c675d058d6a4823eff86d472f187b176f0adf51ea7b69ea38be34be4a63cbbf91b0593c8 languageName: node linkType: hard @@ -20662,7 +21280,7 @@ __metadata: languageName: node linkType: hard -"cookiejar@npm:^2.1.3": +"cookiejar@npm:^2.1.4": version: 2.1.4 resolution: "cookiejar@npm:2.1.4" checksum: c4442111963077dc0e5672359956d6556a195d31cbb35b528356ce5f184922b99ac48245ac05ed86cf993f7df157c56da10ab3efdadfed79778a0d9b1b092d5b @@ -20884,7 +21502,7 @@ __metadata: languageName: node linkType: hard -"cross-fetch@npm:3.1.5, cross-fetch@npm:^3.0.4, cross-fetch@npm:^3.1.3, cross-fetch@npm:^3.1.5": +"cross-fetch@npm:3.1.5": version: 3.1.5 resolution: "cross-fetch@npm:3.1.5" dependencies: @@ -20893,6 +21511,15 @@ __metadata: languageName: node linkType: hard +"cross-fetch@npm:^3.1.3, cross-fetch@npm:^3.1.5": + version: 3.1.6 + resolution: "cross-fetch@npm:3.1.6" + dependencies: + node-fetch: ^2.6.11 + checksum: 704b3519ab7de488328cc49a52cf1aa14132ec748382be5b9557b22398c33ffa7f8c2530e8a97ed8cb55da52b0a9740a9791d361271c4591910501682d981d9c + languageName: node + linkType: hard + "cross-spawn@npm:^5.1.0": version: 5.1.0 resolution: "cross-spawn@npm:5.1.0" @@ -20996,20 +21623,20 @@ __metadata: linkType: hard "css-loader@npm:^6.5.1": - version: 6.7.3 - resolution: "css-loader@npm:6.7.3" + version: 6.7.4 + resolution: "css-loader@npm:6.7.4" dependencies: icss-utils: ^5.1.0 - postcss: ^8.4.19 + postcss: ^8.4.21 postcss-modules-extract-imports: ^3.0.0 - postcss-modules-local-by-default: ^4.0.0 + postcss-modules-local-by-default: ^4.0.1 postcss-modules-scope: ^3.0.0 postcss-modules-values: ^4.0.0 postcss-value-parser: ^4.2.0 semver: ^7.3.8 peerDependencies: webpack: ^5.0.0 - checksum: 473cc32b6c837c2848e2051ad1ba331c1457449f47442e75a8c480d9891451434ada241f7e3de2347e57de17fcd84610b3bcfc4a9da41102cdaedd1e17902d31 + checksum: 6021fa9e375d767b9675e295c1513f2ee4ae04f76d9de69a75b8446e05f6e02b2170407ea72939925b788dcd5aa308527f6b41be3870dc1f4b0bfff8d2532c6e languageName: node linkType: hard @@ -21224,10 +21851,10 @@ __metadata: languageName: node linkType: hard -"csstype@npm:^3.0.2, csstype@npm:^3.0.6": - version: 3.0.7 - resolution: "csstype@npm:3.0.7" - checksum: 2f30c993be570c6d0de334b979a718370ee9bca9569c90340f13e05e542146c55b22e87372b858c061f9f8ded494da7a4715957882f9356cf9993ba11ab6f09c +"csstype@npm:^3.0.2, csstype@npm:^3.0.6, csstype@npm:^3.1.2": + version: 3.0.9 + resolution: "csstype@npm:3.0.9" + checksum: 199f9af7e673f9f188525c3102a329d637ff46c52f6385a4427ff5cb17adcb736189150170a7af7c5701d18d7704bdad130273f4aa7e44c6c4f9967e6115dc93 languageName: node linkType: hard @@ -22005,6 +22632,13 @@ __metadata: languageName: node linkType: hard +"discontinuous-range@npm:1.0.0": + version: 1.0.0 + resolution: "discontinuous-range@npm:1.0.0" + checksum: 8ee88d7082445b6eadc7c03bebe6dc978f96760c45e9f65d16ca66174d9e086a9e3855ee16acf65625e1a07a846a17de674f02a5964a6aebe5963662baf8b5c8 + languageName: node + linkType: hard + "dns-equal@npm:^1.0.0": version: 1.0.0 resolution: "dns-equal@npm:1.0.0" @@ -22453,13 +23087,13 @@ __metadata: languageName: node linkType: hard -"enhanced-resolve@npm:^5.10.0": - version: 5.10.0 - resolution: "enhanced-resolve@npm:5.10.0" +"enhanced-resolve@npm:^5.14.0": + version: 5.14.0 + resolution: "enhanced-resolve@npm:5.14.0" dependencies: graceful-fs: ^4.2.4 tapable: ^2.2.0 - checksum: 0bb9830704db271610f900e8d79d70a740ea16f251263362b0c91af545576d09fe50103496606c1300a05e588372d6f9780a9bc2e30ce8ef9b827ec8f44687ff + checksum: fff1aaebbf376371e5df4502e111967f6247c37611ad3550e4e7fca657f6dcb29ef7ffe88bf14e5010b78997f1ddd984a8db97af87ee0a5477771398fd326f5b languageName: node linkType: hard @@ -22601,13 +23235,20 @@ __metadata: languageName: node linkType: hard -"es-module-lexer@npm:^0.9.0, es-module-lexer@npm:^0.9.3": +"es-module-lexer@npm:^0.9.3": version: 0.9.3 resolution: "es-module-lexer@npm:0.9.3" checksum: 84bbab23c396281db2c906c766af58b1ae2a1a2599844a504df10b9e8dc77ec800b3211fdaa133ff700f5703d791198807bba25d9667392d27a5e9feda344da8 languageName: node linkType: hard +"es-module-lexer@npm:^1.2.1": + version: 1.2.1 + resolution: "es-module-lexer@npm:1.2.1" + checksum: c4145b853e1491eaa5d591e4580926d242978c38071ad3d09165c3b6d50314cc0ae3bf6e1dec81a9e53768b9299df2063d2e4a67d7742a5029ddeae6c4fc26f0 + languageName: node + linkType: hard + "es-shim-unscopables@npm:^1.0.0": version: 1.0.0 resolution: "es-shim-unscopables@npm:1.0.0" @@ -22869,31 +23510,31 @@ __metadata: linkType: hard "esbuild@npm:^0.17.0": - version: 0.17.18 - resolution: "esbuild@npm:0.17.18" + version: 0.17.19 + resolution: "esbuild@npm:0.17.19" dependencies: - "@esbuild/android-arm": 0.17.18 - "@esbuild/android-arm64": 0.17.18 - "@esbuild/android-x64": 0.17.18 - "@esbuild/darwin-arm64": 0.17.18 - "@esbuild/darwin-x64": 0.17.18 - "@esbuild/freebsd-arm64": 0.17.18 - "@esbuild/freebsd-x64": 0.17.18 - "@esbuild/linux-arm": 0.17.18 - "@esbuild/linux-arm64": 0.17.18 - "@esbuild/linux-ia32": 0.17.18 - "@esbuild/linux-loong64": 0.17.18 - "@esbuild/linux-mips64el": 0.17.18 - "@esbuild/linux-ppc64": 0.17.18 - "@esbuild/linux-riscv64": 0.17.18 - "@esbuild/linux-s390x": 0.17.18 - "@esbuild/linux-x64": 0.17.18 - "@esbuild/netbsd-x64": 0.17.18 - "@esbuild/openbsd-x64": 0.17.18 - "@esbuild/sunos-x64": 0.17.18 - "@esbuild/win32-arm64": 0.17.18 - "@esbuild/win32-ia32": 0.17.18 - "@esbuild/win32-x64": 0.17.18 + "@esbuild/android-arm": 0.17.19 + "@esbuild/android-arm64": 0.17.19 + "@esbuild/android-x64": 0.17.19 + "@esbuild/darwin-arm64": 0.17.19 + "@esbuild/darwin-x64": 0.17.19 + "@esbuild/freebsd-arm64": 0.17.19 + "@esbuild/freebsd-x64": 0.17.19 + "@esbuild/linux-arm": 0.17.19 + "@esbuild/linux-arm64": 0.17.19 + "@esbuild/linux-ia32": 0.17.19 + "@esbuild/linux-loong64": 0.17.19 + "@esbuild/linux-mips64el": 0.17.19 + "@esbuild/linux-ppc64": 0.17.19 + "@esbuild/linux-riscv64": 0.17.19 + "@esbuild/linux-s390x": 0.17.19 + "@esbuild/linux-x64": 0.17.19 + "@esbuild/netbsd-x64": 0.17.19 + "@esbuild/openbsd-x64": 0.17.19 + "@esbuild/sunos-x64": 0.17.19 + "@esbuild/win32-arm64": 0.17.19 + "@esbuild/win32-ia32": 0.17.19 + "@esbuild/win32-x64": 0.17.19 dependenciesMeta: "@esbuild/android-arm": optional: true @@ -22941,7 +23582,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 900b333f649fd89804216fb61fb5a0ffadc6dc37a2ec3b5981b588f72821676ea649a7c0ec785f0dbe6e774080b084c8af5f6ee7adbc1b138faf2a8c35e2c69c + checksum: ac11b1a5a6008e4e37ccffbd6c2c054746fc58d0ed4a2f9ee643bd030cfcea9a33a235087bc777def8420f2eaafb3486e76adb7bdb7241a9143b43a69a10afd8 languageName: node linkType: hard @@ -23290,13 +23931,13 @@ __metadata: linkType: hard "eslint-plugin-testing-library@npm:^5.9.1": - version: 5.10.3 - resolution: "eslint-plugin-testing-library@npm:5.10.3" + version: 5.11.0 + resolution: "eslint-plugin-testing-library@npm:5.11.0" dependencies: "@typescript-eslint/utils": ^5.58.0 peerDependencies: eslint: ^7.5.0 || ^8.0.0 - checksum: 3033121a0040b98280cd41856273ad1b268f56083759401e7af72ac8a96dcb213892f1248983aa9a18988b44913263e93f0d182dbb0c5b27b00242bfffc9cdcc + checksum: 7f19d3dedd7788b411ca3d9045de682feb26025b9c26d97d4e2f0bf62f5eaa276147d946bd5d0cd967b822e546a954330fdb7ef80485301264f646143f011a02 languageName: node linkType: hard @@ -23310,13 +23951,13 @@ __metadata: languageName: node linkType: hard -"eslint-scope@npm:^7.1.1": - version: 7.1.1 - resolution: "eslint-scope@npm:7.1.1" +"eslint-scope@npm:^7.2.0": + version: 7.2.0 + resolution: "eslint-scope@npm:7.2.0" dependencies: esrecurse: ^4.3.0 estraverse: ^5.2.0 - checksum: 9f6e974ab2db641ca8ab13508c405b7b859e72afe9f254e8131ff154d2f40c99ad4545ce326fd9fde3212ff29707102562a4834f1c48617b35d98c71a97fbf3e + checksum: 64591a2d8b244ade9c690b59ef238a11d5c721a98bcee9e9f445454f442d03d3e04eda88e95a4daec558220a99fa384309d9faae3d459bd40e7a81b4063980ae languageName: node linkType: hard @@ -23338,10 +23979,10 @@ __metadata: languageName: node linkType: hard -"eslint-visitor-keys@npm:^3.0.0, eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.0": - version: 3.4.0 - resolution: "eslint-visitor-keys@npm:3.4.0" - checksum: 33159169462d3989321a1ec1e9aaaf6a24cc403d5d347e9886d1b5bfe18ffa1be73bdc6203143a28a606b142b1af49787f33cff0d6d0813eb5f2e8d2e1a6043c +"eslint-visitor-keys@npm:^3.0.0, eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.1": + version: 3.4.1 + resolution: "eslint-visitor-keys@npm:3.4.1" + checksum: f05121d868202736b97de7d750847a328fcfa8593b031c95ea89425333db59676ac087fa905eba438d0a3c5769632f828187e0c1a0d271832a2153c1d3661c2c languageName: node linkType: hard @@ -23362,13 +24003,13 @@ __metadata: linkType: hard "eslint@npm:^8.33.0, eslint@npm:^8.6.0": - version: 8.38.0 - resolution: "eslint@npm:8.38.0" + version: 8.41.0 + resolution: "eslint@npm:8.41.0" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@eslint-community/regexpp": ^4.4.0 - "@eslint/eslintrc": ^2.0.2 - "@eslint/js": 8.38.0 + "@eslint/eslintrc": ^2.0.3 + "@eslint/js": 8.41.0 "@humanwhocodes/config-array": ^0.11.8 "@humanwhocodes/module-importer": ^1.0.1 "@nodelib/fs.walk": ^1.2.8 @@ -23378,9 +24019,9 @@ __metadata: debug: ^4.3.2 doctrine: ^3.0.0 escape-string-regexp: ^4.0.0 - eslint-scope: ^7.1.1 - eslint-visitor-keys: ^3.4.0 - espree: ^9.5.1 + eslint-scope: ^7.2.0 + eslint-visitor-keys: ^3.4.1 + espree: ^9.5.2 esquery: ^1.4.2 esutils: ^2.0.2 fast-deep-equal: ^3.1.3 @@ -23388,13 +24029,12 @@ __metadata: find-up: ^5.0.0 glob-parent: ^6.0.2 globals: ^13.19.0 - grapheme-splitter: ^1.0.4 + graphemer: ^1.4.0 ignore: ^5.2.0 import-fresh: ^3.0.0 imurmurhash: ^0.1.4 is-glob: ^4.0.0 is-path-inside: ^3.0.3 - js-sdsl: ^4.1.4 js-yaml: ^4.1.0 json-stable-stringify-without-jsonify: ^1.0.1 levn: ^0.4.1 @@ -23407,7 +24047,7 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: 73b6d9b650d0434aa7c07d0a1802f099b086ee70a8d8ba7be730439a26572a5eb71def12125c82942be2ec8ee5be38a6f1b42a13e40d4b67f11a148ec9e263eb + checksum: 09979a6f8451dcc508a7005b6670845c8a518376280b3fd96657a406b8b6ef29d0e480d1ba11b4eb48da93d607e0c55c9b877676fe089d09973ec152354e23b2 languageName: node linkType: hard @@ -23418,14 +24058,14 @@ __metadata: languageName: node linkType: hard -"espree@npm:^9.0.0, espree@npm:^9.5.1": - version: 9.5.1 - resolution: "espree@npm:9.5.1" +"espree@npm:^9.0.0, espree@npm:^9.5.2": + version: 9.5.2 + resolution: "espree@npm:9.5.2" dependencies: acorn: ^8.8.0 acorn-jsx: ^5.3.2 - eslint-visitor-keys: ^3.4.0 - checksum: cdf6e43540433d917c4f2ee087c6e987b2063baa85a1d9cdaf51533d78275ebd5910c42154e7baf8e3e89804b386da0a2f7fad2264d8f04420e7506bf87b3b88 + eslint-visitor-keys: ^3.4.1 + checksum: 6506289d6eb26471c0b383ee24fee5c8ae9d61ad540be956b3127be5ce3bf687d2ba6538ee5a86769812c7c552a9d8239e8c4d150f9ea056c6d5cbe8399c03c1 languageName: node linkType: hard @@ -23513,6 +24153,13 @@ __metadata: languageName: node linkType: hard +"event-source-polyfill@npm:^1.0.31": + version: 1.0.31 + resolution: "event-source-polyfill@npm:1.0.31" + checksum: 973f226404e2a1b14ed7ef15c718b89e213b41d7cfeeb1c10937fd09229f13904f3d7c3075ab28ccf858c213007559908eecdd577577330352f53a351383dd75 + languageName: node + linkType: hard + "event-stream@npm:=3.3.4": version: 3.3.4 resolution: "event-stream@npm:3.3.4" @@ -23620,6 +24267,7 @@ __metadata: "@backstage/plugin-cloudbuild": "workspace:^" "@backstage/plugin-code-coverage": "workspace:^" "@backstage/plugin-cost-insights": "workspace:^" + "@backstage/plugin-devtools": "workspace:^" "@backstage/plugin-dynatrace": "workspace:^" "@backstage/plugin-entity-feedback": "workspace:^" "@backstage/plugin-explore": "workspace:^" @@ -23743,6 +24391,7 @@ __metadata: "@backstage/plugin-catalog-backend": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-code-coverage-backend": "workspace:^" + "@backstage/plugin-devtools-backend": "workspace:^" "@backstage/plugin-entity-feedback-backend": "workspace:^" "@backstage/plugin-events-backend": "workspace:^" "@backstage/plugin-events-node": "workspace:^" @@ -24224,6 +24873,15 @@ __metadata: languageName: node linkType: hard +"fbemitter@npm:^3.0.0": + version: 3.0.0 + resolution: "fbemitter@npm:3.0.0" + dependencies: + fbjs: ^3.0.0 + checksum: 069690b8cdff3521ade3c9beb92ba0a38d818a86ef36dff8690e66749aef58809db4ac0d6938eb1cacea2dbef5f2a508952d455669590264cdc146bbe839f605 + languageName: node + linkType: hard + "fbjs-css-vars@npm:^1.0.0": version: 1.0.2 resolution: "fbjs-css-vars@npm:1.0.2" @@ -24246,18 +24904,18 @@ __metadata: languageName: node linkType: hard -"fbjs@npm:^3.0.0": - version: 3.0.0 - resolution: "fbjs@npm:3.0.0" +"fbjs@npm:^3.0.0, fbjs@npm:^3.0.1": + version: 3.0.4 + resolution: "fbjs@npm:3.0.4" dependencies: - cross-fetch: ^3.0.4 + cross-fetch: ^3.1.5 fbjs-css-vars: ^1.0.0 loose-envify: ^1.0.0 object-assign: ^4.1.0 promise: ^7.1.1 setimmediate: ^1.0.5 - ua-parser-js: ^0.7.18 - checksum: 85ec57d8dbeddd7c82bf8f111a3c7de1abc1f4d7c603d6ccbcc1ec8dce35ff5b7a113dd34acbf7930093e5533c37a2298a92d342077f967bef34dc7cf2f3f07e + ua-parser-js: ^0.7.30 + checksum: 8b23a3550fcda8a9109fca9475a3416590c18bb6825ea884192864ed686f67fcd618e308a140c9e5444fbd0168732e1ff3c092ba3d0c0ae1768969f32ba280c7 languageName: node linkType: hard @@ -24501,6 +25159,18 @@ __metadata: languageName: node linkType: hard +"flux@npm:^4.0.1": + version: 4.0.4 + resolution: "flux@npm:4.0.4" + dependencies: + fbemitter: ^3.0.0 + fbjs: ^3.0.1 + peerDependencies: + react: ^15.0.2 || ^16.0.0 || ^17.0.0 + checksum: 8fa5c2f9322258de3e331f67c6f1078a7f91c4dec9dbe8a54c4b8a80eed19a4f91889028b768668af4a796e8f2ee75e461e1571b8615432a3920ae95cc4ff794 + languageName: node + linkType: hard + "fn.name@npm:1.x.x": version: 1.1.0 resolution: "fn.name@npm:1.1.0" @@ -24667,7 +25337,7 @@ __metadata: languageName: node linkType: hard -"formidable@npm:^2.0.1": +"formidable@npm:^2.1.2": version: 2.1.2 resolution: "formidable@npm:2.1.2" dependencies: @@ -25367,6 +26037,13 @@ __metadata: languageName: node linkType: hard +"graphemer@npm:^1.4.0": + version: 1.4.0 + resolution: "graphemer@npm:1.4.0" + checksum: bab8f0be9b568857c7bec9fda95a89f87b783546d02951c40c33f84d05bb7da3fd10f863a9beb901463669b6583173a8c8cc6d6b306ea2b9b9d5d3d943c3a673 + languageName: node + linkType: hard + "graphiql@npm:^1.5.12, graphiql@npm:^1.8.8": version: 1.11.5 resolution: "graphiql@npm:1.11.5" @@ -25823,7 +26500,7 @@ __metadata: languageName: node linkType: hard -"hoist-non-react-statics@npm:^3.0.0, hoist-non-react-statics@npm:^3.2.1, hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.2": +"hoist-non-react-statics@npm:^3.0.0, hoist-non-react-statics@npm:^3.2.1, hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.1, hoist-non-react-statics@npm:^3.3.2": version: 3.3.2 resolution: "hoist-non-react-statics@npm:3.3.2" dependencies: @@ -26362,15 +27039,6 @@ __metadata: languageName: node linkType: hard -"indefinite-observable@npm:^2.0.1": - version: 2.0.1 - resolution: "indefinite-observable@npm:2.0.1" - dependencies: - symbol-observable: 1.2.0 - checksum: b4305c999b7596901f8798e569b8faa030361dfb77f8b720e229558a29f544826f7e8987c55cc2a84c37ff2723594a965b96a40a6c71daae92b918f3eb393077 - languageName: node - linkType: hard - "indent-string@npm:^4.0.0": version: 4.0.0 resolution: "indent-string@npm:4.0.0" @@ -26534,9 +27202,9 @@ __metadata: languageName: node linkType: hard -"ioredis@npm:^5.3.1": - version: 5.3.1 - resolution: "ioredis@npm:5.3.1" +"ioredis@npm:^5.3.2": + version: 5.3.2 + resolution: "ioredis@npm:5.3.2" dependencies: "@ioredis/commands": ^1.1.1 cluster-key-slot: ^1.1.0 @@ -26547,7 +27215,7 @@ __metadata: redis-errors: ^1.2.0 redis-parser: ^3.0.0 standard-as-callback: ^2.1.0 - checksum: 6c98cb8f8772ad4bb2b6b7a0a224e4a63f4759f9a28e84205f18788552f08221d51f391c10892dca01a1b10b2804d0a7e6082b0b7decd65538a5fb6b0f4f1f82 + checksum: 9a23559133e862a768778301efb68ae8c2af3c33562174b54a4c2d6574b976e85c75a4c34857991af733e35c48faf4c356e7daa8fb0a3543d85ff1768c8754bc languageName: node linkType: hard @@ -28122,13 +28790,6 @@ __metadata: languageName: node linkType: hard -"js-sdsl@npm:^4.1.4": - version: 4.1.4 - resolution: "js-sdsl@npm:4.1.4" - checksum: 1977cea4ab18e0e03e28bdf0371d8b443fad65ca0988e0faa216406faf6bb943714fe8f7cc7a5bfe5f35ba3d94ddae399f4d10200f547f2c3320688b0670d726 - languageName: node - linkType: hard - "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -28711,76 +29372,76 @@ __metadata: linkType: hard "jss-plugin-camel-case@npm:^10.5.1": - version: 10.6.0 - resolution: "jss-plugin-camel-case@npm:10.6.0" + version: 10.9.2 + resolution: "jss-plugin-camel-case@npm:10.9.2" dependencies: "@babel/runtime": ^7.3.1 hyphenate-style-name: ^1.0.3 - jss: 10.6.0 - checksum: 75c23826deef63c3603cfb47331d1eaf9feeafd097bd115a076f2ee9fb696855d3f18b3f41455a046120fddf0ea11985259c1b8b8a37b3556f4de1a1c83affd5 + jss: 10.9.2 + checksum: 5fa617b23ce9718244691c59ace6a0d1271dbcb4430ce3e13b851ee1879c1db8ecab7e941c33802bea763a0f0e2b609d004b8a975b2063f213cdd639cdd384d2 languageName: node linkType: hard "jss-plugin-default-unit@npm:^10.5.1": - version: 10.6.0 - resolution: "jss-plugin-default-unit@npm:10.6.0" + version: 10.9.2 + resolution: "jss-plugin-default-unit@npm:10.9.2" dependencies: "@babel/runtime": ^7.3.1 - jss: 10.6.0 - checksum: 7ae36fadf4f206a16e49c40806ef92ba1f0e60395488ab8ad4df96796b408013b38ea5ed975155ecd7833a42a96c8d5cb1e90aef011279816633e60f807ec330 + jss: 10.9.2 + checksum: 48d8d836d36dd15513d98de11fba6be373ac29e6fd5702eb2edd143c815fb9e2f9969b2af6b1b964e9b8a052828690887042f6bcb34836836d5c359e52702d0f languageName: node linkType: hard "jss-plugin-global@npm:^10.5.1": - version: 10.6.0 - resolution: "jss-plugin-global@npm:10.6.0" + version: 10.9.2 + resolution: "jss-plugin-global@npm:10.9.2" dependencies: "@babel/runtime": ^7.3.1 - jss: 10.6.0 - checksum: 7aab58408c77071c571dd2c2132edad8d40b683513a8de534f0ec7f63926fd9d9fcf6bdda82103eb541452a723b992f061720f8e5cf2014acb7f6bbbde111f56 + jss: 10.9.2 + checksum: 9b29b0c1f169d5a1033890875df072d76364a902d0f6470f448544669a388612a9a4d51844fb2bcb6d25a1c43d67c1637f11a162c2cdd9f4b6b0a8f9c94f6090 languageName: node linkType: hard "jss-plugin-nested@npm:^10.5.1": - version: 10.6.0 - resolution: "jss-plugin-nested@npm:10.6.0" + version: 10.9.2 + resolution: "jss-plugin-nested@npm:10.9.2" dependencies: "@babel/runtime": ^7.3.1 - jss: 10.6.0 + jss: 10.9.2 tiny-warning: ^1.0.2 - checksum: 38095127e8b5ddb0a33ccaf61a4d89dc1b0f78e6d06d079a47a14bca4aed4e885f1957d83f11c5da08b4249b2c629e8bc62b2996f1674ca1302575a7b2b11171 + checksum: ee08df07f3d553931b48037674842a8314bbc7857cc954a52f962a516bfc4b2d4e9871578b06b8fa3981edf5a927cea00021fd368d4ce315870065b7647f7b57 languageName: node linkType: hard "jss-plugin-props-sort@npm:^10.5.1": - version: 10.6.0 - resolution: "jss-plugin-props-sort@npm:10.6.0" + version: 10.9.2 + resolution: "jss-plugin-props-sort@npm:10.9.2" dependencies: "@babel/runtime": ^7.3.1 - jss: 10.6.0 - checksum: 2917ff301e667f75efa15df865a860a50d4319d415d1169c213e66b464edc2b37b6f428be2d974ccdde7c8d61c50123f18e788143a96eacc2a1c42ad250ae375 + jss: 10.9.2 + checksum: 70bd181a458a6078f19ad4d7350570c78d26b9aabc25a1fbde673839edcc19825af7b636861b208a38aa17e551e68d0ea38599480716b4aec08e353bbe737222 languageName: node linkType: hard "jss-plugin-rule-value-function@npm:^10.5.1": - version: 10.6.0 - resolution: "jss-plugin-rule-value-function@npm:10.6.0" + version: 10.9.2 + resolution: "jss-plugin-rule-value-function@npm:10.9.2" dependencies: "@babel/runtime": ^7.3.1 - jss: 10.6.0 + jss: 10.9.2 tiny-warning: ^1.0.2 - checksum: 709e1ce0afdc39a52cb78e371fef626f933e99992790b15771d85056176bdf69365d62cfed6ce95434752cc1a1e7e05a6f2548e4cd5999808d50a28174315be3 + checksum: b1a03209d0249f13ea6de766d3ee14c1769cd1f67d8c543c7d1ce6178c32cf15507c021ecb3e3b7585a8a7a2425dddbe0bdae02f4135c4598725a4152bebfc99 languageName: node linkType: hard "jss-plugin-vendor-prefixer@npm:^10.5.1": - version: 10.6.0 - resolution: "jss-plugin-vendor-prefixer@npm:10.6.0" + version: 10.9.2 + resolution: "jss-plugin-vendor-prefixer@npm:10.9.2" dependencies: "@babel/runtime": ^7.3.1 css-vendor: ^2.0.8 - jss: 10.6.0 - checksum: 9db048022ee2fb79a223a9f1be5976e131715057e3c0200cfcead9b9f8625023942534afa261e3c967cee6ad716bfd7d4a2f356556178f60f4eddcf83bcd8856 + jss: 10.9.2 + checksum: a5c352a500fea82e8a782a090cc9815f6331259f1a331158ed74ed77c750fb45750f5ae95f07d27922742830b45d4c3592cfaab194b3ba4a50591acbdeab04d8 languageName: node linkType: hard @@ -28804,16 +29465,15 @@ __metadata: languageName: node linkType: hard -"jss@npm:10.6.0": - version: 10.6.0 - resolution: "jss@npm:10.6.0" +"jss@npm:10.9.2": + version: 10.9.2 + resolution: "jss@npm:10.9.2" dependencies: "@babel/runtime": ^7.3.1 csstype: ^3.0.2 - indefinite-observable: ^2.0.1 is-in-browser: ^1.1.3 tiny-warning: ^1.0.2 - checksum: 529edd871ddf059beef55ee0f974ad8436fbcf050d6538e6d2d7edab53ce2c09983d2f863e42a1473dd0e42a0447e9912bce6706bb0e539226d92cdaad128d46 + checksum: 7ae5cd2f8602bf197ec90251d774b9f10d55eb2db0854ac78dc7fb6983828c202e8eb0d5c8c59c73b2f64718ebd33d6063afa799d625a995986a22dc1cc27230 languageName: node linkType: hard @@ -28975,7 +29635,7 @@ __metadata: languageName: node linkType: hard -"knex@npm:^2.0.0": +"knex@npm:^2.0.0, knex@npm:^2.3.0, knex@npm:^2.4.2": version: 2.4.2 resolution: "knex@npm:2.4.2" dependencies: @@ -29239,8 +29899,8 @@ __metadata: linkType: hard "lint-staged@npm:^13.0.0": - version: 13.2.1 - resolution: "lint-staged@npm:13.2.1" + version: 13.2.2 + resolution: "lint-staged@npm:13.2.2" dependencies: chalk: 5.2.0 cli-truncate: ^3.1.0 @@ -29254,10 +29914,10 @@ __metadata: object-inspect: ^1.12.3 pidtree: ^0.6.0 string-argv: ^0.3.1 - yaml: ^2.2.1 + yaml: ^2.2.2 bin: lint-staged: bin/lint-staged.js - checksum: 5788d3fe38e69b7f7b7f700284d4e10738978a0916bc77d3f6253c43a030fc4f01f89c09da349fb658f929f3393d8b1e3eaabaac5b604416ebc33476640b51ce + checksum: f34f6e2e85e827364658ab8717bf8b35239473c2d4959d746b053a4cf158ac657348444c755820a8ef3eac2d4753a37c52e9db3e201ee20b085f26d2f2fbc9ed languageName: node linkType: hard @@ -29441,6 +30101,13 @@ __metadata: languageName: node linkType: hard +"lodash.curry@npm:^4.0.1": + version: 4.1.1 + resolution: "lodash.curry@npm:4.1.1" + checksum: 9192b70fe7df4d1ff780c0260bee271afa9168c93fe4fa24bc861900240531b59781b5fdaadf4644fea8f4fbcd96f0700539ab294b579ffc1022c6c15dcc462a + languageName: node + linkType: hard + "lodash.debounce@npm:^4, lodash.debounce@npm:^4.0.8": version: 4.0.8 resolution: "lodash.debounce@npm:4.0.8" @@ -29476,6 +30143,13 @@ __metadata: languageName: node linkType: hard +"lodash.flow@npm:^3.3.0": + version: 3.5.0 + resolution: "lodash.flow@npm:3.5.0" + checksum: a9a62ad344e3c5a1f42bc121da20f64dd855aaafecee24b1db640f29b88bd165d81c37ff7e380a7191de6f70b26f5918abcebbee8396624f78f3618a0b18634c + languageName: node + linkType: hard + "lodash.get@npm:^4.4.2": version: 4.4.2 resolution: "lodash.get@npm:4.4.2" @@ -29768,6 +30442,13 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^9.0.0": + version: 9.1.1 + resolution: "lru-cache@npm:9.1.1" + checksum: 4d703bb9b66216bbee55ead82a9682820a2b6acbdfca491b235390b1ef1056000a032d56dfb373fdf9ad4492f1fa9d04cc9a05a77f25bd7ce6901d21ad9b68b7 + languageName: node + linkType: hard + "lunr@npm:^2.3.9": version: 2.3.9 resolution: "lunr@npm:2.3.9" @@ -30314,10 +30995,10 @@ __metadata: languageName: node linkType: hard -"meta-png@npm:1.0.5": - version: 1.0.5 - resolution: "meta-png@npm:1.0.5" - checksum: b8c92a696d5e78ef7f0ab53eb9039f108ee0c55cdac9d70e92e5fe2187b090176c0489426d58e594c7d1096481dac37913dd1265f28dfa39926db4d702a5e21d +"meta-png@npm:1.0.6": + version: 1.0.6 + resolution: "meta-png@npm:1.0.6" + checksum: aed14b3b53189c9d32002d76c40926bd93dd9d439bae3ad23ffb2645c375c9772c160879aa8af59ac85a2f43ae8bbe06b9648a53fe27815f4aeab238f4e9b79d languageName: node linkType: hard @@ -30780,13 +31461,13 @@ __metadata: linkType: hard "mini-css-extract-plugin@npm:^2.4.2": - version: 2.7.2 - resolution: "mini-css-extract-plugin@npm:2.7.2" + version: 2.7.6 + resolution: "mini-css-extract-plugin@npm:2.7.6" dependencies: schema-utils: ^4.0.0 peerDependencies: webpack: ^5.0.0 - checksum: cd65611d6dc452f230c6ebba8a47bc5f5146b813b13b0b402c6f4a69f6451242eeea781152bebd31cad8ca7c7e95dac91e7e464087f18fb65b2d1097b58cf4ae + checksum: be6f7cefc6275168eb0a6b8fe977083a18c743c9612c9f00e6c1a62c3393ca7960e93fba1a7ebb09b75f36a0204ad087d772c1ef574bc29c90c0e8175a3c0b83 languageName: node linkType: hard @@ -31035,6 +31716,13 @@ __metadata: languageName: node linkType: hard +"moo@npm:^0.5.0": + version: 0.5.2 + resolution: "moo@npm:0.5.2" + checksum: 5a41ddf1059fd0feb674d917c4774e41c877f1ca980253be4d3aae1a37f4bc513f88815041243f36f5cf67a62fb39324f3f997cf7fb17b6cb00767c165e7c499 + languageName: node + linkType: hard + "morgan@npm:^1.10.0": version: 1.10.0 resolution: "morgan@npm:1.10.0" @@ -31092,40 +31780,6 @@ __metadata: languageName: node linkType: hard -"msw@npm:^0.49.0": - version: 0.49.3 - resolution: "msw@npm:0.49.3" - dependencies: - "@mswjs/cookies": ^0.2.2 - "@mswjs/interceptors": ^0.17.5 - "@open-draft/until": ^1.0.3 - "@types/cookie": ^0.4.1 - "@types/js-levenshtein": ^1.1.1 - chalk: 4.1.1 - chokidar: ^3.4.2 - cookie: ^0.4.2 - graphql: ^15.0.0 || ^16.0.0 - headers-polyfill: ^3.1.0 - inquirer: ^8.2.0 - is-node-process: ^1.0.1 - js-levenshtein: ^1.1.6 - node-fetch: ^2.6.7 - outvariant: ^1.3.0 - path-to-regexp: ^6.2.0 - strict-event-emitter: ^0.4.3 - type-fest: ^2.19.0 - yargs: ^17.3.1 - peerDependencies: - typescript: ">= 4.4.x <= 4.9.x" - peerDependenciesMeta: - typescript: - optional: true - bin: - msw: cli/index.js - checksum: 8322cd42cd69f289c05517d02bde22fc2f10e86fc2d0d209d9df54bd03d10b8123723c5587a2654dcd2cd0f314a016f9eccac88cffa30fafd1f9fead16db639e - languageName: node - linkType: hard - "msw@npm:^1.0.0, msw@npm:^1.0.1": version: 1.2.0 resolution: "msw@npm:1.2.0" @@ -31308,6 +31962,23 @@ __metadata: languageName: node linkType: hard +"nearley@npm:^2.20.1": + version: 2.20.1 + resolution: "nearley@npm:2.20.1" + dependencies: + commander: ^2.19.0 + moo: ^0.5.0 + railroad-diagrams: ^1.0.0 + randexp: 0.4.6 + bin: + nearley-railroad: bin/nearley-railroad.js + nearley-test: bin/nearley-test.js + nearley-unparse: bin/nearley-unparse.js + nearleyc: bin/nearleyc.js + checksum: 42c2c330c13c7991b48221c5df00f4352c2f8851636ae4d1f8ca3c8e193fc1b7668c78011d1cad88cca4c1c4dc087425420629c19cc286d7598ec15533aaef26 + languageName: node + linkType: hard + "negotiator@npm:0.6.3, negotiator@npm:^0.6.2, negotiator@npm:^0.6.3": version: 0.6.3 resolution: "negotiator@npm:0.6.3" @@ -31444,9 +32115,9 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.5, node-fetch@npm:^2.6.7": - version: 2.6.9 - resolution: "node-fetch@npm:2.6.9" +"node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.11, node-fetch@npm:^2.6.5, node-fetch@npm:^2.6.7": + version: 2.6.11 + resolution: "node-fetch@npm:2.6.11" dependencies: whatwg-url: ^5.0.0 peerDependencies: @@ -31454,7 +32125,7 @@ __metadata: peerDependenciesMeta: encoding: optional: true - checksum: acb04f9ce7224965b2b59e71b33c639794d8991efd73855b0b250921382b38331ffc9d61bce502571f6cc6e11a8905ca9b1b6d4aeb586ab093e2756a1fd190d0 + checksum: 249d0666a9497553384d46b5ab296ba223521ac88fed4d8a17d6ee6c2efb0fc890f3e8091cafe7f9fba8151a5b8d925db2671543b3409a56c3cd522b468b47b3 languageName: node linkType: hard @@ -32149,9 +32820,9 @@ __metadata: linkType: hard "openapi-types@npm:^12.0.0": - version: 12.1.0 - resolution: "openapi-types@npm:12.1.0" - checksum: d8f3e2bae519aa6bcf2012f4a5592b7283fe928c06f3bdc182776ce637c7ed8d5f9f342724f68c95c9572aefe21ed5e89b18a0295a703da61af5f97bd2aea9a7 + version: 12.1.1 + resolution: "openapi-types@npm:12.1.1" + checksum: 881dbc514e22046eb790c81370e912ca2daf5beec13cde77e8a15b5ec2635140487abdebf681ec969777067bcbb56b3c0880a0a22aa236d075d8fca5da9535ad languageName: node linkType: hard @@ -33163,6 +33834,13 @@ __metadata: languageName: node linkType: hard +"ping@npm:^0.4.1": + version: 0.4.4 + resolution: "ping@npm:0.4.4" + checksum: cab10af309312e3a6822eccb7f323f0c9a1e17ef5895954114e31b6a1cced5e2ced3563990b79c66d074372e75aa4c846d9001120ee296b365de6a2adef5b8f9 + languageName: node + linkType: hard + "pinkie-promise@npm:^2.0.0": version: 2.0.1 resolution: "pinkie-promise@npm:2.0.1" @@ -33287,7 +33965,14 @@ __metadata: languageName: node linkType: hard -"pngjs@npm:6.0.0, pngjs@npm:^6.0.0": +"pngjs@npm:7.0.0": + version: 7.0.0 + resolution: "pngjs@npm:7.0.0" + checksum: b19a018930d27de26229c1b3ff250b3a25d09caa22cbb0b0459987d91eb0a560a18ab5d67da45a38ed7514140f26d1db58de83c31159ec101f2bb270a3c707f1 + languageName: node + linkType: hard + +"pngjs@npm:^6.0.0": version: 6.0.0 resolution: "pngjs@npm:6.0.0" checksum: ab6c285086060087097eab9fe6b5a528a24f9e79c03dea2b4fd6264ed4fdb5beff4a3257eeeaf2a9dc18249b539609c2a4e4013c567164a1f6b5ba2c974d5ecb @@ -33476,16 +34161,16 @@ __metadata: languageName: node linkType: hard -"postcss-modules-local-by-default@npm:^4.0.0": - version: 4.0.0 - resolution: "postcss-modules-local-by-default@npm:4.0.0" +"postcss-modules-local-by-default@npm:^4.0.0, postcss-modules-local-by-default@npm:^4.0.1": + version: 4.0.1 + resolution: "postcss-modules-local-by-default@npm:4.0.1" dependencies: icss-utils: ^5.0.0 postcss-selector-parser: ^6.0.2 postcss-value-parser: ^4.1.0 peerDependencies: postcss: ^8.1.0 - checksum: 6cf570badc7bc26c265e073f3ff9596b69bb954bc6ac9c5c1b8cba2995b80834226b60e0a3cbb87d5f399dbb52e6466bba8aa1d244f6218f99d834aec431a69d + checksum: 1a95eb8bc54a363a77dbd77a0a88f500e7937ecbed5903becef9362eace28de406e6fdf62640126c22964678370e87eb10481eea2703702772935b4515603bfd languageName: node linkType: hard @@ -33716,7 +34401,7 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.1.0, postcss@npm:^8.4.19": +"postcss@npm:^8.1.0, postcss@npm:^8.4.21": version: 8.4.23 resolution: "postcss@npm:8.4.23" dependencies: @@ -34251,6 +34936,13 @@ __metadata: languageName: node linkType: hard +"pure-color@npm:^1.2.0": + version: 1.3.0 + resolution: "pure-color@npm:1.3.0" + checksum: 646d8bed6e6eab89affdd5e2c11f607a85b631a7fb03c061dfa658eb4dc4806881a15feed2ac5fd8c0bad8c00c632c640d5b1cb8b9a972e6e947393a1329371b + languageName: node + linkType: hard + "pvtsutils@npm:^1.3.2": version: 1.3.2 resolution: "pvtsutils@npm:1.3.2" @@ -34267,7 +34959,7 @@ __metadata: languageName: node linkType: hard -"qs@npm:6.11.0, qs@npm:^6.10.1, qs@npm:^6.10.2, qs@npm:^6.10.3, qs@npm:^6.11.0, qs@npm:^6.9.1, qs@npm:^6.9.4, qs@npm:^6.9.6": +"qs@npm:6.11.0": version: 6.11.0 resolution: "qs@npm:6.11.0" dependencies: @@ -34276,6 +34968,15 @@ __metadata: languageName: node linkType: hard +"qs@npm:^6.10.1, qs@npm:^6.10.2, qs@npm:^6.11.0, qs@npm:^6.9.1, qs@npm:^6.9.4, qs@npm:^6.9.6": + version: 6.11.2 + resolution: "qs@npm:6.11.2" + dependencies: + side-channel: ^1.0.4 + checksum: e812f3c590b2262548647d62f1637b6989cc56656dc960b893fe2098d96e1bd633f36576f4cd7564dfbff9db42e17775884db96d846bebe4f37420d073ecdc0b + languageName: node + linkType: hard + "qs@npm:~6.5.2": version: 6.5.3 resolution: "qs@npm:6.5.3" @@ -34344,6 +35045,13 @@ __metadata: languageName: node linkType: hard +"railroad-diagrams@npm:^1.0.0": + version: 1.0.0 + resolution: "railroad-diagrams@npm:1.0.0" + checksum: 9e312af352b5ed89c2118edc0c06cef2cc039681817f65266719606e4e91ff6ae5374c707cc9033fe29a82c2703edf3c63471664f97f0167c85daf6f93496319 + languageName: node + linkType: hard + "ramda-adjunct@npm:=4.0.0": version: 4.0.0 resolution: "ramda-adjunct@npm:4.0.0" @@ -34367,6 +35075,16 @@ __metadata: languageName: node linkType: hard +"randexp@npm:0.4.6": + version: 0.4.6 + resolution: "randexp@npm:0.4.6" + dependencies: + discontinuous-range: 1.0.0 + ret: ~0.1.10 + checksum: 3c0d440a3f89d6d36844aa4dd57b5cdb0cab938a41956a16da743d3a3578ab32538fc41c16cc0984b6938f2ae4cbc0216967e9829e52191f70e32690d8e3445d + languageName: node + linkType: hard + "randexp@npm:^0.5.3": version: 0.5.3 resolution: "randexp@npm:0.5.3" @@ -34483,6 +35201,18 @@ __metadata: languageName: node linkType: hard +"react-base16-styling@npm:^0.6.0": + version: 0.6.0 + resolution: "react-base16-styling@npm:0.6.0" + dependencies: + base16: ^1.0.0 + lodash.curry: ^4.0.1 + lodash.flow: ^3.3.0 + pure-color: ^1.2.0 + checksum: 00a12dddafc8a9025cca933b0dcb65fca41c81fa176d1fc3a6a9d0242127042e2c0a604f4c724a3254dd2c6aeb5ef55095522ff22f5462e419641c1341a658e4 + languageName: node + linkType: hard + "react-beautiful-dnd@npm:^13.0.0": version: 13.0.0 resolution: "react-beautiful-dnd@npm:13.0.0" @@ -34752,6 +35482,21 @@ __metadata: languageName: node linkType: hard +"react-json-view@npm:^1.21.3": + version: 1.21.3 + resolution: "react-json-view@npm:1.21.3" + dependencies: + flux: ^4.0.1 + react-base16-styling: ^0.6.0 + react-lifecycles-compat: ^3.0.4 + react-textarea-autosize: ^8.3.2 + peerDependencies: + react: ^17.0.0 || ^16.3.0 || ^15.5.4 + react-dom: ^17.0.0 || ^16.3.0 || ^15.5.4 + checksum: 5718bcd9210ad5b06eb9469cf8b9b44be9498845a7702e621343618e8251f26357e6e1c865532cf170db6165df1cb30202787e057309d8848c220bc600ec0d1a + languageName: node + linkType: hard + "react-lifecycles-compat@npm:^3.0.2, react-lifecycles-compat@npm:^3.0.4": version: 3.0.4 resolution: "react-lifecycles-compat@npm:3.0.4" @@ -35019,6 +35764,19 @@ __metadata: languageName: node linkType: hard +"react-textarea-autosize@npm:^8.3.2": + version: 8.4.1 + resolution: "react-textarea-autosize@npm:8.4.1" + dependencies: + "@babel/runtime": ^7.20.13 + use-composed-ref: ^1.3.0 + use-latest: ^1.2.1 + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + checksum: b200437cd68938c23b13944fe6fdfeb32a6d949ac88588307f14d6fcdaba3044b8c7d8e239851b081f2101d433b93d4cf5aa027543b170b84f2a0cbe6fc9093f + languageName: node + linkType: hard + "react-transition-group@npm:2.9.0, react-transition-group@npm:^2.2.1": version: 2.9.0 resolution: "react-transition-group@npm:2.9.0" @@ -35034,9 +35792,9 @@ __metadata: languageName: node linkType: hard -"react-transition-group@npm:^4.0.0, react-transition-group@npm:^4.4.0": - version: 4.4.1 - resolution: "react-transition-group@npm:4.4.1" +"react-transition-group@npm:^4.0.0, react-transition-group@npm:^4.4.0, react-transition-group@npm:^4.4.5": + version: 4.4.5 + resolution: "react-transition-group@npm:4.4.5" dependencies: "@babel/runtime": ^7.5.5 dom-helpers: ^5.0.1 @@ -35045,7 +35803,7 @@ __metadata: peerDependencies: react: ">=16.6.0" react-dom: ">=16.6.0" - checksum: 0bcd8af483709832e318dcef84c26ebddeb866bf4f58010286367ef0c1e7c5106e00cfc65688b9102414cb3d572c63909c2eb7ea972b4420fc70a78c10b6e8ad + checksum: 75602840106aa9c6545149d6d7ae1502fb7b7abadcce70a6954c4b64a438ff1cd16fc77a0a1e5197cdd72da398f39eb929ea06f9005c45b132ed34e056ebdeb1 languageName: node linkType: hard @@ -35085,12 +35843,12 @@ __metadata: linkType: hard "react-virtualized-auto-sizer@npm:^1.0.11, react-virtualized-auto-sizer@npm:^1.0.6": - version: 1.0.15 - resolution: "react-virtualized-auto-sizer@npm:1.0.15" + version: 1.0.17 + resolution: "react-virtualized-auto-sizer@npm:1.0.17" peerDependencies: react: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0-rc react-dom: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0-rc - checksum: db6716fff307dcd2b2492ee0539d5fe2922ea067f91a69969aed6ac03f46db105e993e0a9f946e74b1fb3b9caf88ce5629bf1132e3a995457f42b559979d6708 + checksum: a9fc3db981e34e95fa1baf278e0fb5be9c31ae34092b4d3059cb55478a4652efca3f1b0f4253d62d099594173e1c1f45a724730b5eecde34a9fc23fbc70c215c languageName: node linkType: hard @@ -35908,6 +36666,13 @@ __metadata: languageName: node linkType: hard +"ret@npm:~0.1.10": + version: 0.1.15 + resolution: "ret@npm:0.1.15" + checksum: d76a9159eb8c946586567bd934358dfc08a36367b3257f7a3d7255fdd7b56597235af23c6afa0d7f0254159e8051f93c918809962ebd6df24ca2a83dbe4d4151 + languageName: node + linkType: hard + "retry-request@npm:^5.0.0": version: 5.0.0 resolution: "retry-request@npm:5.0.0" @@ -36353,14 +37118,14 @@ __metadata: languageName: node linkType: hard -"schema-utils@npm:^3.0.0, schema-utils@npm:^3.1.0, schema-utils@npm:^3.1.1": - version: 3.1.1 - resolution: "schema-utils@npm:3.1.1" +"schema-utils@npm:^3.0.0, schema-utils@npm:^3.1.1, schema-utils@npm:^3.1.2": + version: 3.1.2 + resolution: "schema-utils@npm:3.1.2" dependencies: "@types/json-schema": ^7.0.8 ajv: ^6.12.5 ajv-keywords: ^3.5.2 - checksum: fb73f3d759d43ba033c877628fe9751620a26879f6301d3dbeeb48cf2a65baec5cdf99da65d1bf3b4ff5444b2e59cbe4f81c2456b5e0d2ba7d7fd4aed5da29ce + checksum: 39683edfe3beff018cdb1ae4fa296fc55cea13a080aa2b4d9351895cd64b22ba4d87e2e548c2a2ac1bc76e60980670adb0f413a58104479f1a0c12e5663cb8ca languageName: node linkType: hard @@ -36376,6 +37141,15 @@ __metadata: languageName: node linkType: hard +"schemes@npm:^1.4.0": + version: 1.4.0 + resolution: "schemes@npm:1.4.0" + dependencies: + extend: ^3.0.0 + checksum: 729646ac65fbf2b76529c8bbb3433b1079891c4916556d2e1302bfb0c6b84dafcc00ee56e76c4572becd70a2c22a8fd4690b656ea43d1e6b70c180720735948e + languageName: node + linkType: hard + "scoped-regex@npm:^2.0.0": version: 2.1.0 resolution: "scoped-regex@npm:2.1.0" @@ -36935,6 +37709,15 @@ __metadata: languageName: node linkType: hard +"smtp-address-parser@npm:^1.0.3": + version: 1.0.10 + resolution: "smtp-address-parser@npm:1.0.10" + dependencies: + nearley: ^2.20.1 + checksum: 5cf2e960a6836ebec68bb5185c62bc3d343e6fdb1434f8d0d6c273e8d5359b11f2560dea5ecbbd98a77f01f8ef94b56c31d3f6ff24a5c44ba6530b9af7b63626 + languageName: node + linkType: hard + "snake-case@npm:^3.0.4": version: 3.0.4 resolution: "snake-case@npm:3.0.4" @@ -37039,6 +37822,13 @@ __metadata: languageName: node linkType: hard +"source-map@npm:^0.5.7": + version: 0.5.7 + resolution: "source-map@npm:0.5.7" + checksum: 5dc2043b93d2f194142c7f38f74a24670cd7a0063acdaf4bf01d2964b402257ae843c2a8fa822ad5b71013b5fcafa55af7421383da919752f22ff488bc553f4d + languageName: node + linkType: hard + "source-map@npm:^0.6.0, source-map@npm:^0.6.1, source-map@npm:~0.6.0, source-map@npm:~0.6.1": version: 0.6.1 resolution: "source-map@npm:0.6.1" @@ -37486,11 +38276,11 @@ __metadata: linkType: hard "strict-event-emitter@npm:^0.2.4": - version: 0.2.7 - resolution: "strict-event-emitter@npm:0.2.7" + version: 0.2.8 + resolution: "strict-event-emitter@npm:0.2.8" dependencies: events: ^3.3.0 - checksum: 111691e7d3fce0810586ccd8e8234af883ad3b121ef69091c7e260c32299d1ba085a95238ad09b43478bc5e9e80370f2fcb8114716e343be6f44bfc08fab4142 + checksum: 6ac06fe72a6ee6ae64d20f1dd42838ea67342f1b5f32b03b3050d73ee6ecee44b4d5c4ed2965a7154b47991e215f373d4e789e2b2be2769cd80e356126c2ca53 languageName: node linkType: hard @@ -37782,11 +38572,11 @@ __metadata: linkType: hard "style-loader@npm:^3.3.1": - version: 3.3.2 - resolution: "style-loader@npm:3.3.2" + version: 3.3.3 + resolution: "style-loader@npm:3.3.3" peerDependencies: webpack: ^5.0.0 - checksum: 5ee5ce2dc885369eccb55d429376e83d02570d473ac5edeb69fd65ee894847f1e51429cf078351f617bd04516ece8a1dd967f9f40464bd8fa76d903c6b2a6f08 + checksum: f59c953f56f6a935bd6a1dfa409f1128fed2b66b48ce4a7a75b85862a7156e5e90ab163878962762f528ec4d510903d828da645e143fbffd26f055dc1c094078 languageName: node linkType: hard @@ -37840,10 +38630,10 @@ __metadata: languageName: node linkType: hard -"stylis@npm:^4.0.6": - version: 4.0.7 - resolution: "stylis@npm:4.0.7" - checksum: 4f9fdc4b131b54cdc5988aaf23e796fcf77927c9d2f3147f6b23b8f3a9568eb38ce91b338b9d1b50a50391da32969c34ff68ff971c453fc3a5af89941c60ab06 +"stylis@npm:4.1.3, stylis@npm:^4.0.6": + version: 4.1.3 + resolution: "stylis@npm:4.1.3" + checksum: d04dbffcb9bf2c5ca8d8dc09534203c75df3bf711d33973ea22038a99cc475412a350b661ebd99cbc01daa50d7eedcf0d130d121800eb7318759a197023442a6 languageName: node linkType: hard @@ -37879,32 +38669,31 @@ __metadata: languageName: node linkType: hard -"superagent@npm:^8.0.0": - version: 8.0.0 - resolution: "superagent@npm:8.0.0" +"superagent@npm:^8.0.5": + version: 8.0.9 + resolution: "superagent@npm:8.0.9" dependencies: component-emitter: ^1.3.0 - cookiejar: ^2.1.3 + cookiejar: ^2.1.4 debug: ^4.3.4 fast-safe-stringify: ^2.1.1 form-data: ^4.0.0 - formidable: ^2.0.1 + formidable: ^2.1.2 methods: ^1.1.2 mime: 2.6.0 - qs: ^6.10.3 - readable-stream: ^3.6.0 - semver: ^7.3.7 - checksum: 14343e59327eafd85fa230acb876017079d5efcecc72a56566abc0f965220bb460af2e070dddecd9e2856410b2d2b318d81d9cc1d342aa5922da93c29a295dd7 + qs: ^6.11.0 + semver: ^7.3.8 + checksum: 5d00cdc7ceb5570663da80604965750e6b1b8d7d7442b7791e285c62bcd8d578a8ead0242a2426432b59a255fb42eb3a196d636157538a1392e7b6c5f1624810 languageName: node linkType: hard -"supertest@npm:^6.1.3, supertest@npm:^6.1.6, supertest@npm:^6.2.4": - version: 6.2.4 - resolution: "supertest@npm:6.2.4" +"supertest@npm:^6.1.3, supertest@npm:^6.1.6, supertest@npm:^6.2.4, supertest@npm:^6.3.3": + version: 6.3.3 + resolution: "supertest@npm:6.3.3" dependencies: methods: ^1.1.2 - superagent: ^8.0.0 - checksum: f2ddc4f3ba467a5c4036dd4aad41351e4b60eb13c39ecf5233ccd2ebb425504073b2b7036c973a70c7047f5c6bc1b9fef096b7bbff114d357cbe80654441db23 + superagent: ^8.0.5 + checksum: 38239e517f7ba62b7a139a79c5c48d55f8d67b5ff4b6e51d5b07732ca8bbc4a28ffa1b10916fbb403dd013a054dbf028edc5850057d9a43aecbff439d494673e languageName: node linkType: hard @@ -38146,8 +38935,8 @@ __metadata: linkType: hard "tar@npm:^6.0.2, tar@npm:^6.1.0, tar@npm:^6.1.11, tar@npm:^6.1.12, tar@npm:^6.1.2": - version: 6.1.14 - resolution: "tar@npm:6.1.14" + version: 6.1.15 + resolution: "tar@npm:6.1.15" dependencies: chownr: ^2.0.0 fs-minipass: ^2.0.0 @@ -38155,7 +38944,7 @@ __metadata: minizlib: ^2.1.1 mkdirp: ^1.0.3 yallist: ^4.0.0 - checksum: a1be0815a9bdc97dfca7c6c2d71d1b836f8ba9314684e2c412832f0f59cc226d4c13da303d6bc30925e82f634cc793f40da79ae72f3e96fb87c23d0f4efd5207 + checksum: f23832fceeba7578bf31907aac744ae21e74a66f4a17a9e94507acf460e48f6db598c7023882db33bab75b80e027c21f276d405e4a0322d58f51c7088d428268 languageName: node linkType: hard @@ -38248,15 +39037,15 @@ __metadata: languageName: node linkType: hard -"terser-webpack-plugin@npm:*, terser-webpack-plugin@npm:^5.1.3": - version: 5.3.7 - resolution: "terser-webpack-plugin@npm:5.3.7" +"terser-webpack-plugin@npm:*, terser-webpack-plugin@npm:^5.1.3, terser-webpack-plugin@npm:^5.3.7": + version: 5.3.9 + resolution: "terser-webpack-plugin@npm:5.3.9" dependencies: "@jridgewell/trace-mapping": ^0.3.17 jest-worker: ^27.4.5 schema-utils: ^3.1.1 serialize-javascript: ^6.0.1 - terser: ^5.16.5 + terser: ^5.16.8 peerDependencies: webpack: ^5.1.0 peerDependenciesMeta: @@ -38266,13 +39055,13 @@ __metadata: optional: true uglify-js: optional: true - checksum: 095e699fdeeb553cdf2c6f75f983949271b396d9c201d7ae9fc633c45c1c1ad14c7257ef9d51ccc62213dd3e97f875870ba31550f6d4f1b6674f2615562da7f7 + checksum: 41705713d6f9cb83287936b21e27c658891c78c4392159f5148b5623f0e8c48559869779619b058382a4c9758e7820ea034695e57dc7c474b4962b79f553bc5f languageName: node linkType: hard -"terser@npm:^5.10.0, terser@npm:^5.16.5": - version: 5.16.6 - resolution: "terser@npm:5.16.6" +"terser@npm:^5.10.0, terser@npm:^5.16.8": + version: 5.17.1 + resolution: "terser@npm:5.17.1" dependencies: "@jridgewell/source-map": ^0.3.2 acorn: ^8.5.0 @@ -38280,7 +39069,7 @@ __metadata: source-map-support: ~0.5.20 bin: terser: bin/terser - checksum: f763a7bcc7b98cb2bfc41434f7b92bfe8a701a12c92ea6049377736c8e6de328240d654a20dfe15ce170fd783491b9873fad9f4cd8fee4f6c6fb8ca407859dee + checksum: 69b0e80e3c4084db2819de4d6ae8a2ba79f2fcd7ed6df40fe4b602ec7bfd8e889cc63c7d5268f30990ffecbf6eeda18f857adad9386fe2c2331b398d58ed855c languageName: node linkType: hard @@ -39055,7 +39844,7 @@ __metadata: languageName: node linkType: hard -"ua-parser-js@npm:^0.7.18, ua-parser-js@npm:^0.7.30": +"ua-parser-js@npm:^0.7.30": version: 0.7.33 resolution: "ua-parser-js@npm:0.7.33" checksum: 1510e9ec26fcaf0d8c6ae8f1078a8230e8816f083e1b5f453ea19d06b8ef2b8a596601c92148fd41899e8b3e5f83fa69c42332bd5729b931a721040339831696 @@ -39400,12 +40189,12 @@ __metadata: languageName: node linkType: hard -"uri-js@npm:^4.2.2": - version: 4.2.2 - resolution: "uri-js@npm:4.2.2" +"uri-js@npm:^4.2.2, uri-js@npm:^4.4.1": + version: 4.4.1 + resolution: "uri-js@npm:4.4.1" dependencies: punycode: ^2.1.0 - checksum: 5a91c55d8ae6d9a1ff9dc1b0774888a99aae7cc6e9056c57b709275c0f6753b05cd1a9f2728a1479244b93a9f57ab37c60d277a48d9f2d032d6ae65837bf9bc7 + checksum: 7167432de6817fe8e9e0c9684f1d2de2bb688c94388f7569f7dbdb1587c9f4ca2a77962f134ec90be0cc4d004c939ff0d05acc9f34a0db39a3c797dada262633 languageName: node linkType: hard @@ -39455,6 +40244,15 @@ __metadata: languageName: node linkType: hard +"use-composed-ref@npm:^1.3.0": + version: 1.3.0 + resolution: "use-composed-ref@npm:1.3.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + checksum: f771cbadfdc91e03b7ab9eb32d0fc0cc647755711801bf507e891ad38c4bbc5f02b2509acadf9c965ec9c5f2f642fd33bdfdfb17b0873c4ad0a9b1f5e5e724bf + languageName: node + linkType: hard + "use-deep-compare-effect@npm:^1.8.1": version: 1.8.1 resolution: "use-deep-compare-effect@npm:1.8.1" @@ -39477,6 +40275,32 @@ __metadata: languageName: node linkType: hard +"use-isomorphic-layout-effect@npm:^1.1.1": + version: 1.1.2 + resolution: "use-isomorphic-layout-effect@npm:1.1.2" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: a6532f7fc9ae222c3725ff0308aaf1f1ddbd3c00d685ef9eee6714fd0684de5cb9741b432fbf51e61a784e2955424864f7ea9f99734a02f237b17ad3e18ea5cb + languageName: node + linkType: hard + +"use-latest@npm:^1.2.1": + version: 1.2.1 + resolution: "use-latest@npm:1.2.1" + dependencies: + use-isomorphic-layout-effect: ^1.1.1 + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: ed3f2ddddf6f21825e2ede4c2e0f0db8dcce5129802b69d1f0575fc1b42380436e8c76a6cd885d4e9aa8e292e60fb8b959c955f33c6a9123b83814a1a1875367 + languageName: node + linkType: hard + "use-memo-one@npm:^1.1.1": version: 1.1.1 resolution: "use-memo-one@npm:1.1.1" @@ -39826,15 +40650,15 @@ __metadata: languageName: node linkType: hard -"vm2@npm:^3.9.17": - version: 3.9.17 - resolution: "vm2@npm:3.9.17" +"vm2@npm:^3.9.18": + version: 3.9.19 + resolution: "vm2@npm:3.9.19" dependencies: acorn: ^8.7.0 acorn-walk: ^8.2.0 bin: vm2: bin/vm2 - checksum: 9a03740a40ab2be5e3348a95fb31512da1a3c85318febb07e5299fa103ff05bcd7b6f458211fa38a1281dc27beccd04ff90355fc1d34fe2ee6ca10d0bb8c6f35 + checksum: fc6cf553134145cd7bb5246985bf242b056e3fb5ea71e2eef6710b2a5d6c6119cc6bc960435ff62480ee82efb43369be8f4db07b6690916ae7d3b2e714f395d8 languageName: node linkType: hard @@ -40125,20 +40949,20 @@ __metadata: linkType: hard "webpack@npm:^5, webpack@npm:^5.70.0": - version: 5.76.3 - resolution: "webpack@npm:5.76.3" + version: 5.83.1 + resolution: "webpack@npm:5.83.1" dependencies: "@types/eslint-scope": ^3.7.3 - "@types/estree": ^0.0.51 - "@webassemblyjs/ast": 1.11.1 - "@webassemblyjs/wasm-edit": 1.11.1 - "@webassemblyjs/wasm-parser": 1.11.1 + "@types/estree": ^1.0.0 + "@webassemblyjs/ast": ^1.11.5 + "@webassemblyjs/wasm-edit": ^1.11.5 + "@webassemblyjs/wasm-parser": ^1.11.5 acorn: ^8.7.1 acorn-import-assertions: ^1.7.6 browserslist: ^4.14.5 chrome-trace-event: ^1.0.2 - enhanced-resolve: ^5.10.0 - es-module-lexer: ^0.9.0 + enhanced-resolve: ^5.14.0 + es-module-lexer: ^1.2.1 eslint-scope: 5.1.1 events: ^3.2.0 glob-to-regexp: ^0.4.1 @@ -40147,9 +40971,9 @@ __metadata: loader-runner: ^4.2.0 mime-types: ^2.1.27 neo-async: ^2.6.2 - schema-utils: ^3.1.0 + schema-utils: ^3.1.2 tapable: ^2.1.1 - terser-webpack-plugin: ^5.1.3 + terser-webpack-plugin: ^5.3.7 watchpack: ^2.4.0 webpack-sources: ^3.2.3 peerDependenciesMeta: @@ -40157,7 +40981,7 @@ __metadata: optional: true bin: webpack: bin/webpack.js - checksum: 363f536b56971d056e34ab4cffa4cbc630b220e51be1a8c3adea87d9f0b51c49cfc7c3720d6614a1fd2c8c63f1ab3100db916fe8367c8bb9299327ff8c3f856d + checksum: 219d5ef50380bc0fd3702ed17feddf13819d8173b78f7a5b857dc74ac177e63d1f79c050792754411cc088bbc02e0971b989efddadbb8e393cf27d64c0ad9ff8 languageName: node linkType: hard @@ -40709,7 +41533,7 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.0.0, yaml@npm:^2.1.1, yaml@npm:^2.2.1": +"yaml@npm:^2.0.0, yaml@npm:^2.1.1, yaml@npm:^2.2.1, yaml@npm:^2.2.2": version: 2.2.2 resolution: "yaml@npm:2.2.2" checksum: d90c235e099e30094dcff61ba3350437aef53325db4a6bcd04ca96e1bfe7e348b191f6a7a52b5211e2dbc4eeedb22a00b291527da030de7c189728ef3f2b4eb3