diff --git a/.changeset/cold-boats-sell.md b/.changeset/cold-boats-sell.md new file mode 100644 index 0000000000..5b0eba7301 --- /dev/null +++ b/.changeset/cold-boats-sell.md @@ -0,0 +1,23 @@ +--- +'@backstage/plugin-auth-backend-module-guest-provider': minor +--- + +Adds a new guest provider that maps guest users to actual tokens. This also shifts the default guest login to `user:development/guest` to reduce overlap with your production/real data. To change that (or set it back to the old default, use the new `auth.providers.guest.userEntityRef` config key) like so, + +```yaml title=app-config.yaml +auth: + providers: + guest: + userEntityRef: user:default/guest +``` + +This also adds a new property to control the ownership entity refs, + +```yaml title=app-config.yaml +auth: + providers: + guest: + ownershipEntityRefs: + - guests + - development/custom +``` diff --git a/.changeset/create-app-1709052411.md b/.changeset/create-app-1709052411.md new file mode 100644 index 0000000000..b50d431d4b --- /dev/null +++ b/.changeset/create-app-1709052411.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Bumped create-app version. diff --git a/.changeset/dirty-apes-divide.md b/.changeset/dirty-apes-divide.md new file mode 100644 index 0000000000..e90bc7f5e1 --- /dev/null +++ b/.changeset/dirty-apes-divide.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-search-backend-module-elasticsearch': patch +'@backstage/plugin-search-backend-module-pg': patch +--- + +Start importing `QueryTranslator`, `QueryRequestOptions` and `SearchEngine` from the `@backstage/plugin-search-backend-node`. diff --git a/.changeset/eighty-suits-admire.md b/.changeset/eighty-suits-admire.md new file mode 100644 index 0000000000..5b889c8087 --- /dev/null +++ b/.changeset/eighty-suits-admire.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-node': patch +--- + +Fixed file corruption for non UTF-8 data in fetch contents diff --git a/.changeset/fifty-insects-yell.md b/.changeset/fifty-insects-yell.md new file mode 100644 index 0000000000..feedd844a5 --- /dev/null +++ b/.changeset/fifty-insects-yell.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-test-utils': patch +--- + +Added `mockServices.userInfo`, which now also automatically is made available in test backends. diff --git a/.changeset/fifty-moons-study.md b/.changeset/fifty-moons-study.md new file mode 100644 index 0000000000..3744960870 --- /dev/null +++ b/.changeset/fifty-moons-study.md @@ -0,0 +1,5 @@ +--- +'@backstage/theme': patch +--- + +Exported `defaultTypography` to make adjusting these values in a custom theme easier diff --git a/.changeset/five-hats-accept.md b/.changeset/five-hats-accept.md new file mode 100644 index 0000000000..11ee4ff276 --- /dev/null +++ b/.changeset/five-hats-accept.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-notifications-backend': patch +'@backstage/plugin-notifications': patch +--- + +The Notifications can be newly filtered based on the Created Date. diff --git a/.changeset/flat-badgers-attack.md b/.changeset/flat-badgers-attack.md new file mode 100644 index 0000000000..69250d0ded --- /dev/null +++ b/.changeset/flat-badgers-attack.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Support i18n for core components diff --git a/.changeset/kind-pants-speak.md b/.changeset/kind-pants-speak.md new file mode 100644 index 0000000000..215cd5fadc --- /dev/null +++ b/.changeset/kind-pants-speak.md @@ -0,0 +1,21 @@ +--- +'@backstage/plugin-scaffolder-backend-module-confluence-to-markdown': patch +'@backstage/plugin-scaffolder-backend-module-bitbucket-server': patch +'@backstage/plugin-scaffolder-backend-module-bitbucket-cloud': patch +'@backstage/plugin-scaffolder-backend-module-cookiecutter': patch +'@backstage/plugin-scaffolder-backend-module-bitbucket': patch +'@backstage/plugin-scaffolder-backend-module-gerrit': patch +'@backstage/plugin-scaffolder-backend-module-github': patch +'@backstage/plugin-scaffolder-backend-module-gitlab': patch +'@backstage/plugin-scaffolder-backend-module-sentry': patch +'@backstage/plugin-scaffolder-backend-module-yeoman': patch +'@backstage/plugin-scaffolder-backend-module-azure': patch +'@backstage/plugin-scaffolder-backend-module-gitea': patch +'@backstage/plugin-scaffolder-backend-module-rails': patch +'@backstage/plugin-scaffolder-node-test-utils': minor +'@backstage/plugin-scaffolder-backend': patch +--- + +Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + +It will help to maintain tests in a long run during structural changes of action context. diff --git a/.changeset/loud-dolls-exist.md b/.changeset/loud-dolls-exist.md new file mode 100644 index 0000000000..5dce8d71f2 --- /dev/null +++ b/.changeset/loud-dolls-exist.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +Added the `UserInfoApi` as both an optional input and as an output for `createLegacyAuthAdapters` diff --git a/.changeset/nice-beans-wait.md b/.changeset/nice-beans-wait.md new file mode 100644 index 0000000000..7cbdbc0fdf --- /dev/null +++ b/.changeset/nice-beans-wait.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-search-backend-module-techdocs': patch +'@backstage/plugin-search-backend-module-catalog': patch +'@backstage/plugin-search-backend-module-explore': patch +--- + +Migrated to support new auth services. diff --git a/.changeset/odd-toys-wonder.md b/.changeset/odd-toys-wonder.md new file mode 100644 index 0000000000..aedd915c6e --- /dev/null +++ b/.changeset/odd-toys-wonder.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-common': patch +--- + +Deprecate `QueryTranslator`, `QueryRequestOptions` and `SearchEngine` in favor of the types exported from `@backstage/plugin-search-backend-node`. diff --git a/.changeset/old-ducks-fetch.md b/.changeset/old-ducks-fetch.md new file mode 100644 index 0000000000..0e719d07e1 --- /dev/null +++ b/.changeset/old-ducks-fetch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search': patch +--- + +Removes ADR from the default set of search filters diff --git a/.changeset/pre.json b/.changeset/pre.json index 8a921bf194..6b08809e2a 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -274,7 +274,114 @@ "@backstage/plugin-vault": "0.1.25", "@backstage/plugin-vault-backend": "0.4.3", "@backstage/plugin-vault-node": "0.1.3", - "@backstage/plugin-xcmetrics": "0.2.48" + "@backstage/plugin-xcmetrics": "0.2.48", + "@backstage/plugin-auth-backend-module-guest-provider": "0.0.0", + "@backstage/plugin-scaffolder-node-test-utils": "0.0.1" }, - "changesets": [] + "changesets": [ + "big-yaks-film", + "breezy-cycles-count", + "bright-bulldogs-whisper", + "calm-pans-work", + "chilled-dolls-accept", + "chilled-dolphins-tap", + "chilled-goats-matter", + "clever-eagles-boil", + "cold-boats-sell", + "cold-dolphins-raise", + "create-app-1709052411", + "cyan-dryers-share", + "dirty-apes-divide", + "dry-impalas-serve", + "eight-fireants-crash", + "eighty-suits-admire", + "eleven-cows-learn", + "empty-wolves-rule", + "fast-buses-exercise", + "fifty-insects-yell", + "fifty-moons-study", + "five-beers-accept", + "five-hats-accept", + "five-mayflies-juggle", + "flat-badgers-attack", + "forty-oranges-joke", + "fresh-rings-tell", + "friendly-coats-travel", + "friendly-news-sin", + "funny-flies-collect", + "healthy-experts-rhyme", + "heavy-coats-sniff", + "hungry-points-burn", + "itchy-news-drive", + "kind-pants-speak", + "kind-students-cross", + "late-turkeys-remember", + "lazy-needles-lick", + "lazy-terms-shake", + "lemon-lemons-sparkle", + "long-emus-talk", + "loud-dolls-exist", + "lovely-donkeys-kneel", + "modern-impalas-add", + "neat-owls-pump", + "nervous-lions-suffer", + "nice-beans-wait", + "odd-toys-wonder", + "old-ducks-fetch", + "olive-mails-tell", + "perfect-taxis-give", + "polite-tips-begin", + "polite-zoos-pay", + "poor-beans-cross", + "poor-ladybugs-smell", + "pretty-boats-promise", + "purple-kiwis-complain", + "rare-dryers-check", + "red-taxis-swim", + "renovate-0300bde", + "renovate-08c5b50", + "renovate-1c2c49d", + "renovate-58582bb", + "renovate-5d40e90", + "renovate-6a81dd3", + "renovate-755938a", + "renovate-7aa519f", + "renovate-8f23b96", + "renovate-914f0df", + "renovate-9850908", + "renovate-ea48bac", + "rude-masks-tan", + "rude-sheep-jam", + "selfish-glasses-cheer", + "selfish-walls-perform", + "silver-flowers-trade", + "silver-impalas-run", + "six-grapes-sniff", + "six-nails-hammer", + "six-sloths-listen", + "sixty-queens-mix", + "slimy-trainers-attend", + "slow-readers-clap", + "smart-owls-tease", + "soft-grapes-cough", + "soft-otters-report", + "sour-olives-carry", + "spicy-dragons-sin", + "tasty-beans-confess", + "ten-spoons-help", + "tender-carrots-care", + "thick-pillows-develop", + "thin-spiders-do", + "thirty-shirts-allow", + "tiny-books-destroy", + "tiny-bugs-enjoy", + "tricky-months-hug", + "two-planets-beam", + "two-snails-fry", + "unlucky-jobs-report", + "unlucky-lizards-suffer", + "violet-rocks-rescue", + "wet-sheep-reply", + "young-flies-wash" + ] } diff --git a/.changeset/purple-kiwis-complain.md b/.changeset/purple-kiwis-complain.md new file mode 100644 index 0000000000..a5bcb3ed67 --- /dev/null +++ b/.changeset/purple-kiwis-complain.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': minor +--- + +Migrated to support new auth services. The `CatalogBuilder.create` method now accepts a `discovery` option, which is recommended to forward from the plugin environment, as it will otherwise fall back to use the `HostDiscovery` implementation. diff --git a/.changeset/rare-dryers-check.md b/.changeset/rare-dryers-check.md new file mode 100644 index 0000000000..584481f54d --- /dev/null +++ b/.changeset/rare-dryers-check.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes-backend': minor +--- + +**BREAKING**: The `KubernetesBuilder.createBuilder` method now requires the `discovery` service to be forwarded from the plugin environment. This is part of the migration to support new auth services. diff --git a/.changeset/selfish-glasses-cheer.md b/.changeset/selfish-glasses-cheer.md new file mode 100644 index 0000000000..be267eb0f3 --- /dev/null +++ b/.changeset/selfish-glasses-cheer.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +`SignInPage`'s `'guest'` provider now supports the `@backstage/plugin-auth-backend-module-guest-provider` package to generate tokens. It will continue to use the old frontend-only auth as a fallback. diff --git a/.changeset/selfish-walls-perform.md b/.changeset/selfish-walls-perform.md new file mode 100644 index 0000000000..3e7565cf04 --- /dev/null +++ b/.changeset/selfish-walls-perform.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-adr': patch +--- + +Remove unused package dependencies diff --git a/.changeset/silver-impalas-run.md b/.changeset/silver-impalas-run.md new file mode 100644 index 0000000000..22df521680 --- /dev/null +++ b/.changeset/silver-impalas-run.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +Fixed an issue generating a wrong entity link at the end of the import process diff --git a/.changeset/six-grapes-sniff.md b/.changeset/six-grapes-sniff.md new file mode 100644 index 0000000000..095e96dd77 --- /dev/null +++ b/.changeset/six-grapes-sniff.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend': patch +--- + +Update the router to use the new `auth` services, it now accepts an optional discovery service option to get credentials for the permission service. diff --git a/.changeset/sixty-queens-mix.md b/.changeset/sixty-queens-mix.md new file mode 100644 index 0000000000..8fe3f74617 --- /dev/null +++ b/.changeset/sixty-queens-mix.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-scaffolder-backend': minor +'@backstage/plugin-scaffolder-node': patch +--- + +Introducing checkpoints for scaffolder task action idempotency diff --git a/.changeset/slow-readers-clap.md b/.changeset/slow-readers-clap.md new file mode 100644 index 0000000000..5f67c6cf46 --- /dev/null +++ b/.changeset/slow-readers-clap.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-devtools-backend': minor +--- + +**BREAKING**: The `createRouter` method now requires the `discovery` service to be forwarded from the plugin environment. This is part of the migration to support new auth services. diff --git a/.changeset/sour-olives-carry.md b/.changeset/sour-olives-carry.md new file mode 100644 index 0000000000..d0c3bdd6d0 --- /dev/null +++ b/.changeset/sour-olives-carry.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': patch +--- + +Made the `DefaultUserInfoService` claims check stricter diff --git a/.changeset/ten-spoons-help.md b/.changeset/ten-spoons-help.md new file mode 100644 index 0000000000..5089154424 --- /dev/null +++ b/.changeset/ten-spoons-help.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-tech-insights-node': minor +--- + +**BREAKING**: The `FactRetrieverContext` type now contains an additional `auth` field. diff --git a/.changeset/tender-carrots-care.md b/.changeset/tender-carrots-care.md new file mode 100644 index 0000000000..8afdbcf884 --- /dev/null +++ b/.changeset/tender-carrots-care.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-notifications-backend': minor +'@backstage/plugin-notifications': minor +'@backstage/plugin-notifications-common': patch +--- + +The Notifications frontend has been redesigned towards list view with condensed row details. The 'done' attribute has been removed to keep the Notifications aligned with the idea of a messaging system instead of a task manager. diff --git a/.changeset/thick-pillows-develop.md b/.changeset/thick-pillows-develop.md new file mode 100644 index 0000000000..9be71da55d --- /dev/null +++ b/.changeset/thick-pillows-develop.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-tech-insights-backend': patch +--- + +Added support for the new `AuthService`. diff --git a/.changeset/unlucky-jobs-report.md b/.changeset/unlucky-jobs-report.md new file mode 100644 index 0000000000..4eab12d53e --- /dev/null +++ b/.changeset/unlucky-jobs-report.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-permission-backend': patch +--- + +Migrated to use the new auth services introduced in [BEP-0003](https://github.com/backstage/backstage/blob/master/beps/0003-auth-architecture-evolution/README.md). + +The `createRouter` function now accepts `auth`, `httpAuth` and `userInfo` options. Theses are used internally to support the new backend system, and can be ignored. diff --git a/.changeset/violet-rocks-rescue.md b/.changeset/violet-rocks-rescue.md new file mode 100644 index 0000000000..91fbcdd871 --- /dev/null +++ b/.changeset/violet-rocks-rescue.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend-node': patch +--- + +Exports `QueryTranslator`, `QueryRequestOptions` and `SearchEngine` types. These new types were extracted from the `@backstage/plugin-search-common` package and the `token` property was deprecated in favor of the a new credentials one. diff --git a/.changeset/wet-sheep-reply.md b/.changeset/wet-sheep-reply.md new file mode 100644 index 0000000000..27635b133e --- /dev/null +++ b/.changeset/wet-sheep-reply.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Allow the `spec.target` field to be searchable in the catalog table for locations. Previously, only the `spec.targets` field was be searchable. This makes locations generated by providers such as the `GithubEntityProvider` searchable in the catalog table. [#23098](https://github.com/backstage/backstage/issues/23098) diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml index eef70ff02c..0c83a05371 100644 --- a/.github/workflows/deploy_docker-image.yml +++ b/.github/workflows/deploy_docker-image.yml @@ -61,7 +61,7 @@ jobs: with: context: './example-app' file: ./example-app/packages/backend/Dockerfile - push: ${{ (github.event_name == "repository_dispatch") && (github.event.action == "release-published") }} + push: ${{ (github.event_name == 'repository_dispatch') && (github.event.action == 'release-published') }} platforms: linux/amd64,linux/arm64 tags: | ghcr.io/${{ github.repository_owner }}/backstage:latest diff --git a/app-config.yaml b/app-config.yaml index 9b059da216..4b92687653 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -242,7 +242,7 @@ catalog: - Domain - Location providers: - openapi: + backstageOpenapi: plugins: - catalog - search @@ -399,6 +399,9 @@ auth: scopes: ${AUTH_ATLASSIAN_SCOPES} myproxy: development: {} + guest: + development: {} + costInsights: engineerCost: 200000 engineerThreshold: 0.5 diff --git a/docs/auth/guest/provider.md b/docs/auth/guest/provider.md new file mode 100644 index 0000000000..c730877a47 --- /dev/null +++ b/docs/auth/guest/provider.md @@ -0,0 +1,66 @@ +--- +id: provider +title: Guest Authentication Provider +sidebar_label: Guest +description: Adding a guest authentication provider in Backstage +--- + +Audience: Admins or developers + +## Summary + +The goal of this guide is to get you set up with a guest authentication provider that emits tokens. This is different than the old guest authentication that is purely stored on the frontend and does not have tokens. The main reason you'd want to use this provider is to use permissioned plugins. + +:::caution +This provider should only ever be enabled for `development`. To prevent unauthorized access to your data, this package is _explicitly_ disabled for non-development environments. +::: + +## Installation + +### Backend + +:::note +This will only work with the new backend system. There is no support for this in the old backend. +::: + +Add the `@backstage/plugin-auth-backend-module-guest-provider` to your backend installation. + +``` +yarn --cwd packages/backend add @backstage/plugin-auth-backend-module-guest-provider +``` + +Then, add it to your backend's `index.ts` file, + +```diff +const backend = createBackend(); + +backend.add('@backstage/plugin-auth-backend'); ++backend.add('@backstage/plugin-auth-backend-module-guest-provider'); + +await backend.start(); +``` + +### Frontend + +Add the following to your `SignInPage` providers, + +```diff +const providers = [ ++ 'guest', + ... +] +``` + +### Config + +Similar to the other authentication providers, you have to enable the provider in config. Add the following to your `app-config.local.yaml`, + +```diff +auth: + providers: ++ guest: ++ userEntityRef: user:default/guest ++ development: {} +``` + +We need to specify that the provider is enabled for the given environment, and as there are no config values for this provider yet, you can just specify an empty object. diff --git a/docs/backend-system/architecture/01-index.md b/docs/backend-system/architecture/01-index.md index 9c37df7b66..681d0fada2 100644 --- a/docs/backend-system/architecture/01-index.md +++ b/docs/backend-system/architecture/01-index.md @@ -56,8 +56,7 @@ Just like plugins, modules also have access to services and can depend on their ## Package structure A detailed explanation of the package architecture can be found in the -[Backstage Architecture -Overview](../../overview/architecture-overview.md#package-architecture). The +[Backstage Architecture Overview](../../overview/architecture-overview.md#package-architecture). The most important packages to consider for this system are the following: - `plugin--backend` houses the implementation of the backend plugins diff --git a/docs/features/software-templates/writing-tests-for-actions.md b/docs/features/software-templates/writing-tests-for-actions.md new file mode 100644 index 0000000000..0c92811b6f --- /dev/null +++ b/docs/features/software-templates/writing-tests-for-actions.md @@ -0,0 +1,57 @@ +--- +id: writing-tests-for-actions +title: Writing Tests For Actions +description: How to write tests for actions +--- + +Once you created a new action, your own custom one, or you would like to contribute new actions, you have to cover it with +Unit tests to be sure that your actions do what they suppose to do. + +Make sure that you cover the most of scenario's, which could happen with the action. +One of indispensable part of the test is to supply the context to a handler of action for the execution. +We encourage you to use a utility method for that, so your tests are immune to structural changes of context. +What is inevitably going to happen during the time. + +Example how to use it: + +```typescript +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; + +const mockContext = createMockActionContext({ + input: { repoUrl: 'dev.azure.com?repo=repo&owner=owner&organization=org' }, +}); + +await action.handler(mockContext); + +expect(mockContext.output).toHaveBeenCalledWith( + 'remoteUrl', + 'https://dev.azure.com/organization/project/_git/repo', +); +``` + +One thing to be aware about: if you would like to call `createMockActionContext` inside `it`, +you have to provide a `workspacePath`. By default, `createMockActionContext` uses +`import { createMockDirectory } from '@backstage/backend-test-utils';` to create it for you. +This implementation contains a hook inside which creates this limitation. So in this case you can do then: + +```typescript +describe('github:autolinks:create', async () => { + const workspacePath = createMockDirectory().resolve('workspace'); + // ... + + it('should call the githubApis for creating alphanumeric autolink reference', async () => { + // ... + await action.handler( + createMockActionContext({ + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + keyPrefix: 'TICKET-', + urlTemplate: 'https://example.com/TICKET?query=', + }, + workspacePath, + }), + ); + //... + }); +}); +``` diff --git a/docs/getting-started/app-custom-theme.md b/docs/getting-started/app-custom-theme.md index d6a13ca6e3..6ce70be063 100644 --- a/docs/getting-started/app-custom-theme.md +++ b/docs/getting-started/app-custom-theme.md @@ -4,56 +4,42 @@ title: Customize the look-and-feel of your App description: Documentation on Customizing look and feel of the App --- -Backstage ships with a default theme with a light and dark mode variant. The -themes are provided as a part of the -[`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme) package, -which also includes utilities for customizing the default theme, or creating -completely new themes. +Backstage ships with a default theme with a light and dark mode variant. The themes are provided as a part of the [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme) package, which also includes utilities for customizing the default theme, or creating completely new themes. ## Creating a Custom Theme -The easiest way to create a new theme is to use the `createTheme` function -exported by the -[`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme) package. You -can use it to override some basic parameters of the default theme such as the -color palette and font. +The easiest way to create a new theme is to use the `createUnifiedTheme` function exported by the [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme) package. You can use it to override some basic parameters of the default theme such as the color palette and font. -For example, you can create a new theme based on the default light theme like -this: +For example, you can create a new theme based on the default light theme like this: -```ts -import { createTheme, lightTheme } from '@backstage/theme'; +```ts title="packages/app/src/theme/myTheme.ts" +import { + createBaseThemeOptions, + createUnifiedTheme, + palettes, +} from '@backstage/theme'; -const myTheme = createTheme({ - palette: lightTheme.palette, +const myTheme = createUnifiedTheme({ + ...createBaseThemeOptions({ + palette: palettes.light, + }), fontFamily: 'Comic Sans MS', defaultPageTheme: 'home', }); ``` -If you want more control over the theme, and for example customize font sizes -and margins, you can use the lower-level `createThemeOverrides` function -exported by [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme) -in combination with -[`createTheme`](https://material-ui.com/customization/theming/#createmuitheme-options-args-theme) -from [`@material-ui/core`](https://www.npmjs.com/package/@material-ui/core). See -the "Overriding Backstage and Material UI css rules" section below. +> Note: we recommend creating a `theme` folder in `packages/app/src` to place your theme file to keep things nicely organized. -You can also create a theme from scratch that matches the `BackstageTheme` type -exported by [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme). -See the -[Material UI docs on theming](https://material-ui.com/customization/theming/) -for more information about how that can be done. +You can also create a theme from scratch that matches the `BackstageTheme` type exported by [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme). See the +[Material UI docs on theming](https://material-ui.com/customization/theming/) for more information about how that can be done. ## Using your Custom Theme -To add a custom theme to your Backstage app, you pass it as configuration to -`createApp`. +To add a custom theme to your Backstage app, you pass it as configuration to `createApp`. -For example, adding the theme that we created in the previous section can be -done like this: +For example, adding the theme that we created in the previous section can be done like this: -```tsx +```tsx title="packages/app/src/App.tsx" import { createApp } from '@backstage/app-defaults'; import { ThemeProvider } from '@material-ui/core/styles'; import CssBaseline from '@material-ui/core/CssBaseline'; @@ -68,70 +54,68 @@ const app = createApp({ variant: 'light', icon: , Provider: ({ children }) => ( - - {children} - + ), }] }) ``` -Note that your list of custom themes overrides the default themes. If you still -want to use the default themes, they are exported as `lightTheme` and -`darkTheme` from -[`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme). +Note that your list of custom themes overrides the default themes. If you still want to use the default themes, they are exported as `themes.light` and `themes.light` from [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme). ## Example of a custom theme -```ts +```ts title="packages/app/src/theme/myTheme.ts" import { - createTheme, + createBaseThemeOptions, + createUnifiedTheme, genPageTheme, - lightTheme, + palettes, shapes, } from '@backstage/theme'; -const myTheme = createTheme({ - palette: { - ...lightTheme.palette, - primary: { - main: '#343b58', +const myTheme = createUnifiedTheme({ + ...createBaseThemeOptions({ + palette: { + ...palettes.light, + primary: { + main: '#343b58', + }, + secondary: { + main: '#565a6e', + }, + error: { + main: '#8c4351', + }, + warning: { + main: '#8f5e15', + }, + info: { + main: '#34548a', + }, + success: { + main: '#485e30', + }, + background: { + default: '#d5d6db', + paper: '#d5d6db', + }, + banner: { + info: '#34548a', + error: '#8c4351', + text: '#343b58', + link: '#565a6e', + }, + errorBackground: '#8c4351', + warningBackground: '#8f5e15', + infoBackground: '#343b58', + navigation: { + background: '#343b58', + indicator: '#8f5e15', + color: '#d5d6db', + selectedColor: '#ffffff', + }, }, - secondary: { - main: '#565a6e', - }, - error: { - main: '#8c4351', - }, - warning: { - main: '#8f5e15', - }, - info: { - main: '#34548a', - }, - success: { - main: '#485e30', - }, - background: { - default: '#d5d6db', - paper: '#d5d6db', - }, - banner: { - info: '#34548a', - error: '#8c4351', - text: '#343b58', - link: '#565a6e', - }, - errorBackground: '#8c4351', - warningBackground: '#8f5e15', - infoBackground: '#343b58', - navigation: { - background: '#343b58', - indicator: '#8f5e15', - color: '#d5d6db', - selectedColor: '#ffffff', - }, - }, + }), defaultPageTheme: 'home', fontFamily: 'Comic Sans MS', /* below drives the header colors */ @@ -161,16 +145,92 @@ const myTheme = createTheme({ }); ``` -For a more complete example of a custom theme including Backstage and -Material UI component overrides, see the [Aperture -theme](https://github.com/backstage/demo/blob/master/packages/app/src/theme/aperture.ts) -from the [Backstage demo site](https://demo.backstage.io). +For a more complete example of a custom theme including Backstage and Material UI component overrides, see the [Aperture theme](https://github.com/backstage/demo/blob/master/packages/app/src/theme/aperture.ts) from the [Backstage demo site](https://demo.backstage.io). + +## Custom Typography + +When creating a custom theme you can also customize various aspects of the default typography, here's an example using simplified theme: + +```ts title="packages/app/src/theme/myTheme.ts" +import { + createBaseThemeOptions, + createUnifiedTheme, + palettes, +} from '@backstage/theme'; + +const myTheme = createUnifiedTheme({ + ...createBaseThemeOptions({ + palette: palettes.light, + typography: { + htmlFontSize: 16, + fontFamily: 'Arial, sans-serif', + 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, + }, + }, + defaultPageTheme: 'home', + }), +}); +``` + +If you wanted to only override a sub-set of the typography setting, for example just `h1` then you would do this: + +```ts title="packages/app/src/theme/myTheme.ts" +import { + createBaseThemeOptions, + createUnifiedTheme, + defaultTypography, + palettes, +} from '@backstage/theme'; + +const myTheme = createUnifiedTheme({ + ...createBaseThemeOptions({ + palette: palettes.light, + typography: { + ...defaultTypography, + htmlFontSize: 16, + fontFamily: 'Roboto, sans-serif', + h1: { + fontSize: 72, + fontWeight: 700, + marginBottom: 10, + }, + }, + defaultPageTheme: 'home', + }), +}); +``` ## Overriding Backstage and Material UI components styles -When creating a custom theme you would be applying different values to -component's css rules that use the theme object. For example, a Backstage -component's styles might look like this: +When creating a custom theme you would be applying different values to component's CSS rules that use the theme object. For example, a Backstage component's styles might look like this: ```tsx const useStyles = makeStyles( @@ -185,83 +245,50 @@ const useStyles = makeStyles( ); ``` -Notice how the `padding` is getting its value from `theme.spacing`, that means -that setting a value for spacing in your custom theme would affect this -component padding property and the same goes for `backgroundImage` which uses -`theme.page.backgroundImage`. However, the `boxShadow` property doesn't -reference any value from the theme, that means that creating a custom theme -wouldn't be enough to alter the `box-shadow` property or to add css rules that -aren't already defined like a margin. For these cases you should also create an -override. +Notice how the `padding` is getting its value from `theme.spacing`, that means that setting a value for spacing in your custom theme would affect this component padding property and the same goes for `backgroundImage` which uses `theme.page.backgroundImage`. However, the `boxShadow` property doesn't reference any value from the theme, that means that creating a custom theme wouldn't be enough to alter the `box-shadow` property or to add css rules that aren't already defined like a margin. For these cases you should also create an override. -```tsx -import { createApp } from '@backstage/core-app-api'; -import { BackstageTheme, lightTheme } from '@backstage/theme'; -/** - * The `@backstage/core-components` package exposes this type that - * contains all Backstage and `material-ui` components that can be - * overridden along with the classes key those components use. - */ -import { BackstageOverrides } from '@backstage/core-components'; +Here's how you would do that: -export const createCustomThemeOverrides = ( - theme: BackstageTheme, -): BackstageOverrides => { - return { +```ts title="packages/app/src/theme/myTheme.ts" +import { + createBaseThemeOptions, + createUnifiedTheme, + palettes, +} from '@backstage/theme'; + +const myTheme = createUnifiedTheme({ + ...createBaseThemeOptions({ + palette: palettes.light, + }), + fontFamily: 'Comic Sans MS', + defaultPageTheme: 'home', + components: { BackstageHeader: { - header: { - width: 'auto', - margin: '20px', - boxShadow: 'none', - borderBottom: `4px solid ${theme.palette.primary.main}`, + styleOverrides: { + header: ({ theme }) => ({ + width: 'auto', + margin: '20px', + boxShadow: 'none', + borderBottom: `4px solid ${theme.palette.primary.main}`, + }), }, }, - }; -}; - -const customTheme: BackstageTheme = { - ...lightTheme, - overrides: { - // These are the overrides that Backstage applies to `material-ui` components - ...lightTheme.overrides, - // These are your custom overrides, either to `material-ui` or Backstage components. - ...createCustomThemeOverrides(lightTheme), }, -}; - -const app = createApp({ - apis: ..., - plugins: ..., - themes: [{ - id: 'my-theme', - title: 'My Custom Theme', - variant: 'light', - Provider: ({ children }) => ( - - {children} - - ), - }] }); ``` ## Custom Logo -In addition to a custom theme, you can also customize the logo displayed at the -far top left of the site. +In addition to a custom theme, you can also customize the logo displayed at the far top left of the site. -In your frontend app, locate `src/components/Root/` folder. You'll find two -components: +In your frontend app, locate `src/components/Root/` folder. You'll find two components: - `LogoFull.tsx` - A larger logo used when the Sidebar navigation is opened. -- `LogoIcon.tsx` - A smaller logo used when the sidebar navigation is closed. +- `LogoIcon.tsx` - A smaller logo used when the Sidebar navigation is closed. -To replace the images, you can simply replace the relevant code in those -components with raw SVG definitions. +To replace the images, you can simply replace the relevant code in those components with raw SVG definitions. -You can also use another web image format such as PNG by importing it. To do -this, place your new image into a new subdirectory such as -`src/components/Root/logo/my-company-logo.png`, and then add this code: +You can also use another web image format such as PNG by importing it. To do this, place your new image into a new subdirectory such as `src/components/Root/logo/my-company-logo.png`, and then add this code: ```tsx import MyCustomLogoFull from './logo/my-company-logo.png'; @@ -408,7 +435,7 @@ For this example we'll show you how you can expand the sidebar with a sub-menu: 3. Then update the `@backstage/core-components` import like this: - ```tsx + ```tsx title="packages/app/src/components/Root/Root.tsx" import { Sidebar, sidebarConfig, @@ -430,7 +457,7 @@ For this example we'll show you how you can expand the sidebar with a sub-menu: 4. Finally replace `` with this: - ```tsx + ```tsx title="packages/app/src/components/Root/Root.tsx" publisher.setEventBroker(eventBroker))); + ``` + + `eventsPlugin` uses the `eventsServiceRef` as dependency. + Unsupported (and deprecated) extension point methods will throw an error to prevent unintended behavior. + + ```ts + import { eventsServiceRef } from '@backstage/plugin-events-node'; + ``` + +### Patch Changes + +- 56969b6: Add new `EventsService` as well as `eventsServiceRef` for the new backend system. + + **Summary:** + + - new: + `EventsService`, `eventsServiceRef`, `TestEventsService` + - deprecated: + `EventBroker`, `EventPublisher`, `EventSubscriber`, `DefaultEventBroker`, `EventsBackend`, + most parts of `EventsExtensionPoint` (alpha), + `TestEventBroker`, `TestEventPublisher`, `TestEventSubscriber` + + Add the `eventsServiceRef` as dependency to your backend plugins + or backend plugin modules. + + **Details:** + + The previous implementation using the `EventsExtensionPoint` was added in the early stages + of the new backend system and does not respect the plugin isolation. + This made it not compatible anymore with the new backend system. + + Additionally, the previous interfaces had some room for simplification, + supporting less exposure of internal concerns as well. + + Hereby, this change adds a new `EventsService` interface as replacement for the now deprecated `EventBroker`. + The new interface does not require any `EventPublisher` or `EventSubscriber` interfaces anymore. + Instead, it is expected that the `EventsService` gets passed into publishers and subscribers, + and used internally. There is no need to expose anything of that at their own interfaces. + + Most parts of `EventsExtensionPoint` (alpha) are deprecated as well and were not usable + (by other plugins or their modules) anyway. + + The `DefaultEventBroker` implementation is deprecated and wraps the new `DefaultEventsService` implementation. + Optionally, an instance can be passed as argument to allow mixed setups to operate alongside. + +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-events-backend-module-aws-sqs@0.3.0-next.0 + +### Minor Changes + +- 132d672: BREAKING CHANGE: Migrate `AwsSqsConsumingEventPublisher` and its backend module to use `EventsService`. + + Uses the `EventsService` instead of `EventBroker` at `AwsSqsConsumingEventPublisher`, + dropping the use of `EventPublisher` including `setEventBroker(..)`. + + Now, `AwsSqsConsumingEventPublisher.fromConfig` requires `events: EventsService` as option. + + ```diff + const sqs = AwsSqsConsumingEventPublisher.fromConfig({ + config: env.config, + + events: env.events, + logger: env.logger, + scheduler: env.scheduler, + }); + + await Promise.all(sqs.map(publisher => publisher.start())); + + // e.g. at packages/backend/src/plugins/events.ts + - await new EventsBackend(env.logger) + - .setEventBroker(env.eventBroker) + - .addPublishers(sqs) + - .start(); + + // or for other kinds of setups + - await Promise.all(sqs.map(publisher => publisher.setEventBroker(eventBroker))); + ``` + + `eventsModuleAwsSqsConsumingEventPublisher` uses the `eventsServiceRef` as dependency, + instead of `eventsExtensionPoint`. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-events-backend-module-azure@0.2.0-next.0 + +### Minor Changes + +- eff3ca9: BREAKING CHANGE: Migrate `EventRouter` implementations from `EventBroker` to `EventsService`. + + `EventRouter` uses the new `EventsService` instead of the `EventBroker` now, + causing a breaking change to its signature. + + All of its extensions and implementations got adjusted accordingly. + (`SubTopicEventRouter`, `AzureDevOpsEventRouter`, `BitbucketCloudEventRouter`, + `GerritEventRouter`, `GithubEventRouter`, `GitlabEventRouter`) + + Required adjustments were made to all backend modules for the new backend system, + now also making use of the `eventsServiceRef` instead of the `eventsExtensionPoint`. + + **Migration:** + + Example for implementations of `SubTopicEventRouter`: + + ```diff + import { + EventParams, + + EventsService, + SubTopicEventRouter, + } from '@backstage/plugin-events-node'; + + export class GithubEventRouter extends SubTopicEventRouter { + - constructor() { + - super('github'); + + constructor(options: { events: EventsService }) { + + super({ + + events: options.events, + + topic: 'github', + + }); + } + + + protected getSubscriberId(): string { + + return 'GithubEventRouter'; + + } + + + // ... + } + ``` + + Example for a direct extension of `EventRouter`: + + ```diff + class MyEventRouter extends EventRouter { + - constructor(/* ... */) { + + constructor(options: { + + events: EventsService; + + // ... + + }) { + - super(); + // ... + + super({ + + events: options.events, + + topics: topics, + + }); + } + + + + protected getSubscriberId(): string { + + return 'MyEventRouter'; + + } + - + - supportsEventTopics(): string[] { + - return this.topics; + - } + } + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.2.0-next.0 + +### Minor Changes + +- eff3ca9: BREAKING CHANGE: Migrate `EventRouter` implementations from `EventBroker` to `EventsService`. + + `EventRouter` uses the new `EventsService` instead of the `EventBroker` now, + causing a breaking change to its signature. + + All of its extensions and implementations got adjusted accordingly. + (`SubTopicEventRouter`, `AzureDevOpsEventRouter`, `BitbucketCloudEventRouter`, + `GerritEventRouter`, `GithubEventRouter`, `GitlabEventRouter`) + + Required adjustments were made to all backend modules for the new backend system, + now also making use of the `eventsServiceRef` instead of the `eventsExtensionPoint`. + + **Migration:** + + Example for implementations of `SubTopicEventRouter`: + + ```diff + import { + EventParams, + + EventsService, + SubTopicEventRouter, + } from '@backstage/plugin-events-node'; + + export class GithubEventRouter extends SubTopicEventRouter { + - constructor() { + - super('github'); + + constructor(options: { events: EventsService }) { + + super({ + + events: options.events, + + topic: 'github', + + }); + } + + + protected getSubscriberId(): string { + + return 'GithubEventRouter'; + + } + + + // ... + } + ``` + + Example for a direct extension of `EventRouter`: + + ```diff + class MyEventRouter extends EventRouter { + - constructor(/* ... */) { + + constructor(options: { + + events: EventsService; + + // ... + + }) { + - super(); + // ... + + super({ + + events: options.events, + + topics: topics, + + }); + } + + + + protected getSubscriberId(): string { + + return 'MyEventRouter'; + + } + - + - supportsEventTopics(): string[] { + - return this.topics; + - } + } + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + +## @backstage/plugin-events-backend-module-gerrit@0.2.0-next.0 + +### Minor Changes + +- eff3ca9: BREAKING CHANGE: Migrate `EventRouter` implementations from `EventBroker` to `EventsService`. + + `EventRouter` uses the new `EventsService` instead of the `EventBroker` now, + causing a breaking change to its signature. + + All of its extensions and implementations got adjusted accordingly. + (`SubTopicEventRouter`, `AzureDevOpsEventRouter`, `BitbucketCloudEventRouter`, + `GerritEventRouter`, `GithubEventRouter`, `GitlabEventRouter`) + + Required adjustments were made to all backend modules for the new backend system, + now also making use of the `eventsServiceRef` instead of the `eventsExtensionPoint`. + + **Migration:** + + Example for implementations of `SubTopicEventRouter`: + + ```diff + import { + EventParams, + + EventsService, + SubTopicEventRouter, + } from '@backstage/plugin-events-node'; + + export class GithubEventRouter extends SubTopicEventRouter { + - constructor() { + - super('github'); + + constructor(options: { events: EventsService }) { + + super({ + + events: options.events, + + topic: 'github', + + }); + } + + + protected getSubscriberId(): string { + + return 'GithubEventRouter'; + + } + + + // ... + } + ``` + + Example for a direct extension of `EventRouter`: + + ```diff + class MyEventRouter extends EventRouter { + - constructor(/* ... */) { + + constructor(options: { + + events: EventsService; + + // ... + + }) { + - super(); + // ... + + super({ + + events: options.events, + + topics: topics, + + }); + } + + + + protected getSubscriberId(): string { + + return 'MyEventRouter'; + + } + - + - supportsEventTopics(): string[] { + - return this.topics; + - } + } + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + +## @backstage/plugin-events-backend-module-github@0.2.0-next.0 + +### Minor Changes + +- eff3ca9: BREAKING CHANGE: Migrate `EventRouter` implementations from `EventBroker` to `EventsService`. + + `EventRouter` uses the new `EventsService` instead of the `EventBroker` now, + causing a breaking change to its signature. + + All of its extensions and implementations got adjusted accordingly. + (`SubTopicEventRouter`, `AzureDevOpsEventRouter`, `BitbucketCloudEventRouter`, + `GerritEventRouter`, `GithubEventRouter`, `GitlabEventRouter`) + + Required adjustments were made to all backend modules for the new backend system, + now also making use of the `eventsServiceRef` instead of the `eventsExtensionPoint`. + + **Migration:** + + Example for implementations of `SubTopicEventRouter`: + + ```diff + import { + EventParams, + + EventsService, + SubTopicEventRouter, + } from '@backstage/plugin-events-node'; + + export class GithubEventRouter extends SubTopicEventRouter { + - constructor() { + - super('github'); + + constructor(options: { events: EventsService }) { + + super({ + + events: options.events, + + topic: 'github', + + }); + } + + + protected getSubscriberId(): string { + + return 'GithubEventRouter'; + + } + + + // ... + } + ``` + + Example for a direct extension of `EventRouter`: + + ```diff + class MyEventRouter extends EventRouter { + - constructor(/* ... */) { + + constructor(options: { + + events: EventsService; + + // ... + + }) { + - super(); + // ... + + super({ + + events: options.events, + + topics: topics, + + }); + } + + + + protected getSubscriberId(): string { + + return 'MyEventRouter'; + + } + - + - supportsEventTopics(): string[] { + - return this.topics; + - } + } + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-events-backend-module-gitlab@0.2.0-next.0 + +### Minor Changes + +- eff3ca9: BREAKING CHANGE: Migrate `EventRouter` implementations from `EventBroker` to `EventsService`. + + `EventRouter` uses the new `EventsService` instead of the `EventBroker` now, + causing a breaking change to its signature. + + All of its extensions and implementations got adjusted accordingly. + (`SubTopicEventRouter`, `AzureDevOpsEventRouter`, `BitbucketCloudEventRouter`, + `GerritEventRouter`, `GithubEventRouter`, `GitlabEventRouter`) + + Required adjustments were made to all backend modules for the new backend system, + now also making use of the `eventsServiceRef` instead of the `eventsExtensionPoint`. + + **Migration:** + + Example for implementations of `SubTopicEventRouter`: + + ```diff + import { + EventParams, + + EventsService, + SubTopicEventRouter, + } from '@backstage/plugin-events-node'; + + export class GithubEventRouter extends SubTopicEventRouter { + - constructor() { + - super('github'); + + constructor(options: { events: EventsService }) { + + super({ + + events: options.events, + + topic: 'github', + + }); + } + + + protected getSubscriberId(): string { + + return 'GithubEventRouter'; + + } + + + // ... + } + ``` + + Example for a direct extension of `EventRouter`: + + ```diff + class MyEventRouter extends EventRouter { + - constructor(/* ... */) { + + constructor(options: { + + events: EventsService; + + // ... + + }) { + - super(); + // ... + + super({ + + events: options.events, + + topics: topics, + + }); + } + + + + protected getSubscriberId(): string { + + return 'MyEventRouter'; + + } + - + - supportsEventTopics(): string[] { + - return this.topics; + - } + } + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-events-node@0.3.0-next.0 + +### Minor Changes + +- eff3ca9: BREAKING CHANGE: Migrate `EventRouter` implementations from `EventBroker` to `EventsService`. + + `EventRouter` uses the new `EventsService` instead of the `EventBroker` now, + causing a breaking change to its signature. + + All of its extensions and implementations got adjusted accordingly. + (`SubTopicEventRouter`, `AzureDevOpsEventRouter`, `BitbucketCloudEventRouter`, + `GerritEventRouter`, `GithubEventRouter`, `GitlabEventRouter`) + + Required adjustments were made to all backend modules for the new backend system, + now also making use of the `eventsServiceRef` instead of the `eventsExtensionPoint`. + + **Migration:** + + Example for implementations of `SubTopicEventRouter`: + + ```diff + import { + EventParams, + + EventsService, + SubTopicEventRouter, + } from '@backstage/plugin-events-node'; + + export class GithubEventRouter extends SubTopicEventRouter { + - constructor() { + - super('github'); + + constructor(options: { events: EventsService }) { + + super({ + + events: options.events, + + topic: 'github', + + }); + } + + + protected getSubscriberId(): string { + + return 'GithubEventRouter'; + + } + + + // ... + } + ``` + + Example for a direct extension of `EventRouter`: + + ```diff + class MyEventRouter extends EventRouter { + - constructor(/* ... */) { + + constructor(options: { + + events: EventsService; + + // ... + + }) { + - super(); + // ... + + super({ + + events: options.events, + + topics: topics, + + }); + } + + + + protected getSubscriberId(): string { + + return 'MyEventRouter'; + + } + - + - supportsEventTopics(): string[] { + - return this.topics; + - } + } + ``` + +### Patch Changes + +- 56969b6: Add new `EventsService` as well as `eventsServiceRef` for the new backend system. + + **Summary:** + + - new: + `EventsService`, `eventsServiceRef`, `TestEventsService` + - deprecated: + `EventBroker`, `EventPublisher`, `EventSubscriber`, `DefaultEventBroker`, `EventsBackend`, + most parts of `EventsExtensionPoint` (alpha), + `TestEventBroker`, `TestEventPublisher`, `TestEventSubscriber` + + Add the `eventsServiceRef` as dependency to your backend plugins + or backend plugin modules. + + **Details:** + + The previous implementation using the `EventsExtensionPoint` was added in the early stages + of the new backend system and does not respect the plugin isolation. + This made it not compatible anymore with the new backend system. + + Additionally, the previous interfaces had some room for simplification, + supporting less exposure of internal concerns as well. + + Hereby, this change adds a new `EventsService` interface as replacement for the now deprecated `EventBroker`. + The new interface does not require any `EventPublisher` or `EventSubscriber` interfaces anymore. + Instead, it is expected that the `EventsService` gets passed into publishers and subscribers, + and used internally. There is no need to expose anything of that at their own interfaces. + + Most parts of `EventsExtensionPoint` (alpha) are deprecated as well and were not usable + (by other plugins or their modules) anyway. + + The `DefaultEventBroker` implementation is deprecated and wraps the new `DefaultEventsService` implementation. + Optionally, an instance can be passed as argument to allow mixed setups to operate alongside. + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.13-next.0 + +## @backstage/plugin-jenkins-backend@0.4.0-next.0 + +### Minor Changes + +- 55191cc: **BREAKING**: Both `createRouter` and `DefaultJenkinsInfoProvider.fromConfig` now require the `discovery` service to be forwarded from the plugin environment. This is part of the migration to support new auth services. + + The `JenkinsInfoProvider` interface has been updated to receive `credentials` of the type `BackstageCredentials` rather than a token. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-jenkins-common@0.1.25-next.0 + +## @backstage/plugin-kubernetes-backend@0.16.0-next.0 + +### Minor Changes + +- e1e540c: **BREAKING**: The `KubernetesBuilder.createBuilder` method now requires the `discovery` service to be forwarded from the plugin environment. This is part of the migration to support new auth services. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/plugin-kubernetes-common@0.7.5-next.0 + - @backstage/plugin-kubernetes-node@0.1.7-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration-aws-node@0.1.10-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-notifications@0.1.0-next.0 + +### Minor Changes + +- 758f2a4: The Notifications frontend has been redesigned towards list view with condensed row details. The 'done' attribute has been removed to keep the Notifications aligned with the idea of a messaging system instead of a task manager. + +### Patch Changes + +- 5d9c5ba: The Notifications can be newly filtered based on the Created Date. +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-notifications-common@0.0.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-signals-react@0.0.2-next.0 + +## @backstage/plugin-notifications-backend@0.1.0-next.0 + +### Minor Changes + +- 758f2a4: The Notifications frontend has been redesigned towards list view with condensed row details. The 'done' attribute has been removed to keep the Notifications aligned with the idea of a messaging system instead of a task manager. + +### Patch Changes + +- 5d9c5ba: The Notifications can be newly filtered based on the Created Date. +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- 84af361: Migrated to using the new auth services. +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-notifications-node@0.1.0-next.0 + - @backstage/plugin-signals-node@0.0.4-next.0 + - @backstage/plugin-notifications-common@0.0.2-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-notifications-node@0.1.0-next.0 + +### Minor Changes + +- 84af361: Migrated to using the new auth services. + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-signals-node@0.0.4-next.0 + - @backstage/plugin-notifications-common@0.0.2-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + +## @backstage/plugin-scaffolder-backend@1.22.0-next.0 + +### Minor Changes + +- c6b132e: Introducing checkpoints for scaffolder task action idempotency + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.3-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.3-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket@0.2.3-next.0 + - @backstage/plugin-scaffolder-backend-module-gerrit@0.1.5-next.0 + - @backstage/plugin-scaffolder-backend-module-github@0.2.3-next.0 + - @backstage/plugin-scaffolder-backend-module-gitlab@0.2.16-next.0 + - @backstage/plugin-scaffolder-backend-module-azure@0.1.5-next.0 + - @backstage/plugin-scaffolder-backend-module-gitea@0.1.3-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.10-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.5.1-next.0 + +## @backstage/plugin-scaffolder-node-test-utils@0.1.0-next.0 + +### Minor Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-test-utils@0.3.3-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.5.1-next.0 + +## @backstage/plugin-tech-insights-node@0.5.0-next.0 + +### Minor Changes + +- d621468: **BREAKING**: The `FactRetrieverContext` type now contains an additional `auth` field. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/app-defaults@1.5.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/core-app-api@1.12.1-next.0 + - @backstage/plugin-permission-react@0.4.21-next.0 + +## @backstage/backend-common@0.21.3-next.0 + +### Patch Changes + +- 7422430: Resolve the `basePath` before constructing the target path + +- 999224f: Bump dependency `minimatch` to v9 + +- e0b997c: Fix issue where `resolveSafeChildPath` path would incorrectly resolve when operating on a symlink + +- 9802004: Added the `UserInfoApi` as both an optional input and as an output for `createLegacyAuthAdapters` + +- 2af5354: Bump dependency `jose` to v5 + +- ff40ada: Updated dependency `mysql2` to `^3.0.0`. + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. + +- 568881f: Updated dependency `yauzl` to `^3.0.0`. + +- 4a3d434: Added a `createLegacyAuthAdapters` function that can be used as a compatibility adapter for backend plugins who want to start using the new [`auth`](https://backstage.io/docs/backend-system/core-services/auth/) and [`httpAuth`](https://backstage.io/docs/backend-system/core-services/http-auth) services that were created as part of [BEP-0003](https://github.com/backstage/backstage/tree/master/beps/0003-auth-architecture-evolution). + + See the [Auth Service Migration tutorial](https://backstage.io/docs/tutorials/auth-service-migration) for more information on the usage of this adapter. + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/backend-app-api@0.6.0-next.0 + - @backstage/config-loader@1.6.3-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/integration-aws-node@0.1.10-next.0 + - @backstage/backend-dev-utils@0.1.4 + - @backstage/cli-common@0.1.13 + - @backstage/types@1.1.1 + +## @backstage/backend-defaults@0.2.13-next.0 + +### Patch Changes + +- 7cbb760: Added support for the new auth services, which are now installed by default. See the [migration guide](https://backstage.io/docs/tutorials/auth-service-migration) for details. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-app-api@0.6.0-next.0 + +## @backstage/backend-dynamic-feature-service@0.2.3-next.0 + +### Patch Changes + +- 5247909: Add `events: EventsService` to `LegacyPluginEnvironment`. +- Updated dependencies + - @backstage/plugin-events-backend@0.3.0-next.0 + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/backend-app-api@0.6.0-next.0 + - @backstage/plugin-catalog-backend@1.18.0-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/cli-node@0.2.4-next.0 + - @backstage/config-loader@1.6.3-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-app-node@0.1.13-next.0 + - @backstage/cli-common@0.1.13 + - @backstage/types@1.1.1 + +## @backstage/backend-openapi-utils@0.1.6-next.0 + +### Patch Changes + +- 85ec23e: Updated dependency `json-schema-to-ts` to `^3.0.0`. +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + +## @backstage/backend-plugin-api@0.6.13-next.0 + +### Patch Changes + +- 4a3d434: Added the new [`auth`](https://backstage.io/docs/backend-system/core-services/auth/), [`httpAuth`](https://backstage.io/docs/backend-system/core-services/http-auth), and [`userInfo`](https://backstage.io/docs/backend-system/core-services/user-info) services that were created as part of [BEP-0003](https://github.com/backstage/backstage/tree/master/beps/0003-auth-architecture-evolution) to the `coreServices`. + + At the same time, the [`httpRouter`](https://backstage.io/docs/backend-system/core-services/http-router) service gained a new `addAuthPolicy` method that lets your plugin declare exemptions to the default auth policy - for example if you want to allow unauthenticated or cookie-based access to some subset of your feature routes. + + If you have migrated to the new backend system, please see the [Auth Service Migration tutorial](https://backstage.io/docs/tutorials/auth-service-migration) for more information on how to move toward using these services. + +- 0502d82: Updated the `PermissionsService` methods to accept `BackstageCredentials` through options. + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + +## @backstage/backend-tasks@0.5.18-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + +## @backstage/backend-test-utils@0.3.3-next.0 + +### Patch Changes + +- 4a3d434: Added support for the new [`auth`](https://backstage.io/docs/backend-system/core-services/auth/) and [`httpAuth`](https://backstage.io/docs/backend-system/core-services/http-auth) services that were created as part of [BEP-0003](https://github.com/backstage/backstage/tree/master/beps/0003-auth-architecture-evolution). These services will be present by default in test apps, and you can access mocked versions of their features under `mockServices.auth` and `mockServices.httpAuth` if you want to inspect or replace their behaviors. + + There is also a new `mockCredentials` that you can use for acquiring mocks of the various types of credentials that are used in the new system. + +- 9802004: Added `mockServices.userInfo`, which now also automatically is made available in test backends. + +- fd61d39: Updated dependency `testcontainers` to `^10.0.0`. + +- ff40ada: Updated dependency `mysql2` to `^3.0.0`. + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/backend-app-api@0.6.0-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + +## @backstage/catalog-client@1.6.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/catalog-model@1.4.5-next.0 + +## @backstage/catalog-model@1.4.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/types@1.1.1 + +## @backstage/cli@0.25.3-next.0 + +### Patch Changes + +- 999224f: Bump dependency `minimatch` to v9 +- f86e34c: Removed unused `replace-in-file` dependency +- f4404e5: Add .ico import support +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/eslint-plugin@0.1.6-next.0 + - @backstage/cli-node@0.2.4-next.0 + - @backstage/config-loader@1.6.3-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/cli-common@0.1.13 + - @backstage/release-manifests@0.0.11 + - @backstage/types@1.1.1 + +## @backstage/cli-node@0.2.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/cli-common@0.1.13 + - @backstage/types@1.1.1 + +## @backstage/config@1.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/types@1.1.1 + +## @backstage/config-loader@1.6.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/cli-common@0.1.13 + - @backstage/types@1.1.1 + +## @backstage/core-app-api@1.12.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/core-compat-api@0.2.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-app-api@1.12.1-next.0 + - @backstage/version-bridge@1.0.7 + +## @backstage/core-components@0.14.1-next.0 + +### Patch Changes + +- ff33ee2: Removed hardcoded font-family on select input +- ff7e126: Support i18n for core components +- 7854120: Create a component abstraction to consume system icons. +- ce73c3b: Removed the inline color from select icon to allow it to be colored via a theme +- a8f7904: `SignInPage`'s `'guest'` provider now supports the `@backstage/plugin-auth-backend-module-guest-provider` package to generate tokens. It will continue to use the old frontend-only auth as a fallback. +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/theme@0.5.2-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/version-bridge@1.0.7 + +## @backstage/core-plugin-api@1.9.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/create-app@0.5.12-next.0 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.13 + +## @backstage/dev-utils@1.0.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/app-defaults@1.5.1-next.0 + - @backstage/core-app-api@1.12.1-next.0 + +## @backstage/errors@1.2.4-next.0 + +### Patch Changes + +- 2636075: Fixed an issue that was causing ResponseError not to report the HTTP status from the provided response. +- Updated dependencies + - @backstage/types@1.1.1 + +## @backstage/eslint-plugin@0.1.6-next.0 + +### Patch Changes + +- 999224f: Bump dependency `minimatch` to v9 + +## @backstage/frontend-app-api@0.6.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-app-api@1.12.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/frontend-plugin-api@0.6.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/frontend-test-utils@0.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.6.1-next.0 + - @backstage/test-utils@1.5.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/integration@1.9.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/integration-aws-node@0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/integration-react@1.1.25-next.0 + +### Patch Changes + +- b38dc55: Updated `microsoftAuthApi` scopes for Azure DevOps to be fully qualified. +- Updated dependencies + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/repo-tools@0.6.3-next.0 + +### Patch Changes + +- 999224f: Bump dependency `minimatch` to v9 +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/cli-node@0.2.4-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/cli-common@0.1.13 + +## @techdocs/cli@1.8.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-techdocs-node@1.11.5-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/cli-common@0.1.13 + +## @backstage/test-utils@1.5.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/core-app-api@1.12.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-react@0.4.21-next.0 + +## @backstage/theme@0.5.2-next.0 + +### Patch Changes + +- 6f4d2a0: Exported `defaultTypography` to make adjusting these values in a custom theme easier + +## @backstage/plugin-adr@0.6.14-next.0 + +### Patch Changes + +- 5335634: Fixed Azure DevOps ADR file path reading +- 669efc6: Remove unused package dependencies +- Updated dependencies + - @backstage/plugin-adr-common@0.2.21-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + +## @backstage/plugin-adr-backend@0.4.10-next.0 + +### Patch Changes + +- 334c5fe: Updated dependency `marked` to `^12.0.0`. +- c8fdd83: Migrated `DefaultAdrCollatorFactory` to support new auth services. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-adr-common@0.2.21-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-adr-common@0.2.21-next.0 + +### Patch Changes + +- 5335634: Fixed Azure DevOps ADR file path reading +- Updated dependencies + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-airbrake@0.3.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/dev-utils@1.0.28-next.0 + - @backstage/test-utils@1.5.1-next.0 + +## @backstage/plugin-airbrake-backend@0.3.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-allure@0.1.47-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-analytics-module-ga@0.2.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + +## @backstage/plugin-analytics-module-ga4@0.2.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + +## @backstage/plugin-analytics-module-newrelic-browser@0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + +## @backstage/plugin-apache-airflow@0.2.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-api-docs@0.11.1-next.0 + +### Patch Changes + +- 7854120: Use the `AppIcon` component in the navigation item extension. +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-catalog@1.17.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + - @backstage/plugin-permission-react@0.4.21-next.0 + +## @backstage/plugin-apollo-explorer@0.1.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-app-backend@0.3.61-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config-loader@1.6.3-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-app-node@0.1.13-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-app-node@0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config-loader@1.6.3-next.0 + +## @backstage/plugin-app-visualizer@0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + +## @backstage/plugin-auth-backend-module-atlassian-provider@0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + +## @backstage/plugin-auth-backend-module-aws-alb-provider@0.1.4-next.0 + +### Patch Changes + +- 2af5354: Bump dependency `jose` to v5 +- b1b012d: Fix issue with `providerInfo` not being set properly for some proxy providers, by making `providerInfo` an explicit optional return from `authenticate` +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-auth-backend@0.22.0-next.0 + +## @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.8-next.0 + +### Patch Changes + +- 38af71a: Updated dependency `google-auth-library` to `^9.0.0`. +- b1b012d: Fix issue with `providerInfo` not being set properly for some proxy providers, by making `providerInfo` an explicit optional return from `authenticate` +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-auth-backend-module-github-provider@0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + +## @backstage/plugin-auth-backend-module-gitlab-provider@0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + +## @backstage/plugin-auth-backend-module-google-provider@0.1.10-next.0 + +### Patch Changes + +- 38af71a: Updated dependency `google-auth-library` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + +## @backstage/plugin-auth-backend-module-microsoft-provider@0.1.8-next.0 + +### Patch Changes + +- 2af5354: Bump dependency `jose` to v5 +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + +## @backstage/plugin-auth-backend-module-oauth2-provider@0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + +## @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.6-next.0 + +### Patch Changes + +- 2af5354: Bump dependency `jose` to v5 +- e77d7a9: Internal refactor to avoid deprecated method. +- b1b012d: Fix issue with `providerInfo` not being set properly for some proxy providers, by making `providerInfo` an explicit optional return from `authenticate` +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + +## @backstage/plugin-auth-backend-module-oidc-provider@0.1.3-next.0 + +### Patch Changes + +- 2af5354: Bump dependency `jose` to v5 +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-auth-backend@0.22.0-next.0 + +## @backstage/plugin-auth-backend-module-okta-provider@0.0.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + +## @backstage/plugin-auth-backend-module-pinniped-provider@0.1.7-next.0 + +### Patch Changes + +- 2af5354: Bump dependency `jose` to v5 +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-auth-backend-module-vmware-cloud-provider@0.1.5-next.0 + +### Patch Changes + +- 2af5354: Bump dependency `jose` to v5 +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/catalog-model@1.4.5-next.0 + +## @backstage/plugin-auth-node@0.4.8-next.0 + +### Patch Changes + +- b4fc6e3: Deprecated the `getBearerTokenFromAuthorizationHeader` function, which is being replaced by the new `HttpAuthService`. +- 2af5354: Bump dependency `jose` to v5 +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- b1b012d: Fix issue with `providerInfo` not being set properly for some proxy providers, by making `providerInfo` an explicit optional return from `authenticate` +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-azure-sites@0.1.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-azure-sites-common@0.1.3-next.0 + - @backstage/plugin-permission-react@0.4.21-next.0 + +## @backstage/plugin-azure-sites-common@0.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + +## @backstage/plugin-badges@0.2.55-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-badges-backend@0.3.10-next.0 + +### Patch Changes + +- 29a1f91: Migrated to support new auth services. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-bazaar@0.2.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-bazaar-backend@0.3.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-bitbucket-cloud-common@0.2.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-bitrise@0.1.58-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-catalog@1.17.1-next.0 + +### Patch Changes + +- 9332425: The entity page extension provided by the `/alpha` plugin now correctly renders the entity 404 page. +- 6727665: Allow the `spec.target` field to be searchable in the catalog table for locations. Previously, only the `spec.targets` field was be searchable. This makes locations generated by providers such as the `GithubEntityProvider` searchable in the catalog table. [#23098](https://github.com/backstage/backstage/issues/23098) +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.22-next.0 + - @backstage/plugin-permission-react@0.4.21-next.0 + - @backstage/plugin-scaffolder-common@1.5.1-next.0 + +## @backstage/plugin-catalog-backend-module-aws@0.3.7-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-kubernetes-common@0.7.5-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/integration-aws-node@0.1.10-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + +## @backstage/plugin-catalog-backend-module-azure@0.1.32-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + +## @backstage/plugin-catalog-backend-module-backstage-openapi@0.1.6-next.0 + +### Patch Changes + +- 43a9ae1: Migrated to use new auth service. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-openapi-utils@0.1.6-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.26-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-catalog-backend-module-gcp@0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-kubernetes-common@0.7.5-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.29-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-catalog-backend-module-github@0.5.3-next.0 + +### Patch Changes + +- a936a8f: Migrated the `GithubLocationAnalyzer` to support new auth services. +- 999224f: Bump dependency `minimatch` to v9 +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-backend@1.18.0-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + +## @backstage/plugin-catalog-backend-module-github-org@0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-catalog-backend-module-github@0.5.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-catalog-backend-module-gitlab@0.3.10-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.4.17-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-backend@1.18.0-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.28-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.22-next.0 + +## @backstage/plugin-catalog-backend-module-msgraph@0.5.20-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.30-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-backend@1.18.0-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.22-next.0 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.1.18-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + - @backstage/plugin-scaffolder-common@1.5.1-next.0 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.3.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/catalog-model@1.4.5-next.0 + +## @backstage/plugin-catalog-common@1.0.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/catalog-model@1.4.5-next.0 + +## @backstage/plugin-catalog-graph@0.4.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-import@0.10.7-next.0 + +### Patch Changes + +- 75f686b: Fixed an issue generating a wrong entity link at the end of the import process +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + +## @backstage/plugin-catalog-react@1.10.1-next.0 + +### Patch Changes + +- 930b5c1: Added 'root' and 'label' class keys for EntityAutocompletePicker, EntityOwnerPicker and EntityProcessingStatusPicker +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-catalog-common@1.0.22-next.0 + - @backstage/plugin-permission-react@0.4.21-next.0 + +## @backstage/plugin-catalog-unprocessed-entities@0.1.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-cicd-statistics@0.1.33-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.27-next.0 + +### Patch Changes + +- 402d991: Align `p-limit` dependency version to v3 +- Updated dependencies + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-cicd-statistics@0.1.33-next.0 + +## @backstage/plugin-circleci@0.3.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-cloudbuild@0.4.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-code-climate@0.1.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-code-coverage@0.2.24-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-code-coverage-backend@0.2.27-next.0 + +### Patch Changes + +- cceebae: Fix jacoco convertor to not require annotation to be set to scm-only. +- 8efe690: Migrated to support new auth services. +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-codescene@0.1.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-config-schema@0.1.51-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-cost-insights@0.12.20-next.0 + +### Patch Changes + +- 1b4fd09: Updated dependency `yup` to `^1.0.0`. +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-cost-insights-common@0.1.2 + +## @backstage/plugin-devtools@0.1.10-next.0 + +### Patch Changes + +- a0e3393: Updated to use `fetchApi` as per [ADR013](https://backstage.io/docs/architecture-decisions/adrs-adr013) +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/plugin-devtools-common@0.1.9-next.0 + - @backstage/plugin-permission-react@0.4.21-next.0 + +## @backstage/plugin-devtools-common@0.1.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-dynatrace@9.0.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-entity-feedback@0.2.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## @backstage/plugin-entity-feedback-backend@0.2.10-next.0 + +### Patch Changes + +- 4f8ecd6: Migrated to support new auth services. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## @backstage/plugin-entity-validation@0.1.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + +## @backstage/plugin-events-backend-test-utils@0.1.23-next.0 + +### Patch Changes + +- 56969b6: Add new `EventsService` as well as `eventsServiceRef` for the new backend system. + + **Summary:** + + - new: + `EventsService`, `eventsServiceRef`, `TestEventsService` + - deprecated: + `EventBroker`, `EventPublisher`, `EventSubscriber`, `DefaultEventBroker`, `EventsBackend`, + most parts of `EventsExtensionPoint` (alpha), + `TestEventBroker`, `TestEventPublisher`, `TestEventSubscriber` + + Add the `eventsServiceRef` as dependency to your backend plugins + or backend plugin modules. + + **Details:** + + The previous implementation using the `EventsExtensionPoint` was added in the early stages + of the new backend system and does not respect the plugin isolation. + This made it not compatible anymore with the new backend system. + + Additionally, the previous interfaces had some room for simplification, + supporting less exposure of internal concerns as well. + + Hereby, this change adds a new `EventsService` interface as replacement for the now deprecated `EventBroker`. + The new interface does not require any `EventPublisher` or `EventSubscriber` interfaces anymore. + Instead, it is expected that the `EventsService` gets passed into publishers and subscribers, + and used internally. There is no need to expose anything of that at their own interfaces. + + Most parts of `EventsExtensionPoint` (alpha) are deprecated as well and were not usable + (by other plugins or their modules) anyway. + + The `DefaultEventBroker` implementation is deprecated and wraps the new `DefaultEventsService` implementation. + Optionally, an instance can be passed as argument to allow mixed setups to operate alongside. + +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + +## @backstage/plugin-explore@0.4.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-explore-react@0.0.37-next.0 + +## @backstage/plugin-explore-backend@0.0.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-search-backend-module-explore@0.1.17-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + +## @backstage/plugin-explore-react@0.0.37-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-explore-common@0.0.2 + +## @backstage/plugin-firehydrant@0.2.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-fossa@0.2.63-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-gcalendar@0.3.24-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-gcp-projects@0.3.47-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-git-release-manager@0.3.43-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-github-actions@0.6.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-github-deployments@0.1.62-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-github-issues@0.2.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-github-pull-requests-board@0.1.25-next.0 + +### Patch Changes + +- 3c2d7c0: The `CardHeader` component in the `github-pull-requests-board` plugin will show the status for the PR +- 402d991: Align `p-limit` dependency version to v3 +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-gitops-profiles@0.3.46-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-gocd@0.1.37-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-graphiql@0.3.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + +## @backstage/plugin-graphql-voyager@0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-home@0.6.3-next.0 + +### Patch Changes + +- 0cecb09: Updated dependency `@rjsf/utils` to `5.17.1`. + Updated dependency `@rjsf/core` to `5.17.1`. + Updated dependency `@rjsf/material-ui` to `5.17.1`. + Updated dependency `@rjsf/validator-ajv8` to `5.17.1`. +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-home-react@0.1.9-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-app-api@1.12.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + +## @backstage/plugin-home-react@0.1.9-next.0 + +### Patch Changes + +- 0cecb09: Updated dependency `@rjsf/utils` to `5.17.1`. + Updated dependency `@rjsf/core` to `5.17.1`. + Updated dependency `@rjsf/material-ui` to `5.17.1`. + Updated dependency `@rjsf/validator-ajv8` to `5.17.1`. +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-ilert@0.2.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-jenkins@0.9.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-jenkins-common@0.1.25-next.0 + +## @backstage/plugin-jenkins-common@0.1.25-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + +## @backstage/plugin-kafka@0.3.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-kafka-backend@0.3.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-kubernetes@0.11.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-kubernetes-common@0.7.5-next.0 + - @backstage/plugin-kubernetes-react@0.3.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-kubernetes-cluster@0.0.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-kubernetes-common@0.7.5-next.0 + - @backstage/plugin-kubernetes-react@0.3.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-kubernetes-common@0.7.5-next.0 + +### Patch Changes + +- 4642cb7: Add support to fetch data for Daemon Sets and display an accordion in the same way as with Deployments +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-kubernetes-node@0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-kubernetes-common@0.7.5-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-kubernetes-react@0.3.1-next.0 + +### Patch Changes + +- 4642cb7: Add support to fetch data for Daemon Sets and display an accordion in the same way as with Deployments +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-kubernetes-common@0.7.5-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-lighthouse@0.4.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-lighthouse-common@0.1.5-next.0 + +## @backstage/plugin-lighthouse-backend@0.4.5-next.0 + +### Patch Changes + +- 9f9ba70: **BREAKING**: The `createScheduler` function now requires the `discovery` service to be forwarded from the plugin environment. This is part of the migration to support new auth services. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.5-next.0 + +## @backstage/plugin-lighthouse-common@0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-linguist@0.1.16-next.0 + +### Patch Changes + +- 4fb9600: Get component's title from translation file. See: +- a0e3393: Updated to use `fetchApi` as per [ADR013](https://backstage.io/docs/architecture-decisions/adrs-adr013) +- 786c9c4: Updated dependency `luxon` to `^3.0.0`. +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/plugin-linguist-common@0.1.2 + +## @backstage/plugin-linguist-backend@0.5.10-next.0 + +### Patch Changes + +- 61ff58f: Migrated to support new auth services. +- 786c9c4: Updated dependency `luxon` to `^3.0.0`. +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-linguist-common@0.1.2 + +## @backstage/plugin-microsoft-calendar@0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-newrelic@0.3.46-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-newrelic-dashboard@0.3.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-nomad@0.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-nomad-backend@0.1.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-notifications-common@0.0.2-next.0 + +### Patch Changes + +- 758f2a4: The Notifications frontend has been redesigned towards list view with condensed row details. The 'done' attribute has been removed to keep the Notifications aligned with the idea of a messaging system instead of a task manager. + +## @backstage/plugin-octopus-deploy@0.2.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-opencost@0.2.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-org@0.6.21-next.0 + +### Patch Changes + +- 526f00a: Document the new frontend system extensions for the org plugin. +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + +## @backstage/plugin-org-react@0.1.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-pagerduty@0.7.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-home-react@0.1.9-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-periskop@0.1.29-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-periskop-backend@0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-permission-backend@0.5.36-next.0 + +### Patch Changes + +- 9802004: Migrated to use the new auth services introduced in [BEP-0003](https://github.com/backstage/backstage/blob/master/beps/0003-auth-architecture-evolution/README.md). + + The `createRouter` function now accepts `auth`, `httpAuth` and `userInfo` options. Theses are used internally to support the new backend system, and can be ignored. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-permission-backend-module-allow-all-policy@0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + +## @backstage/plugin-permission-common@0.7.13-next.0 + +### Patch Changes + +- 0502d82: The `token` option of the `PermissionEvaluator` methods is now deprecated. The options that only apply to backend implementations have been moved to `PermissionsService` from `@backstage/backend-plugin-api` instead. +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-permission-node@0.7.24-next.0 + +### Patch Changes + +- 0502d82: The `ServerPermissionClient` has been migrated to implement the `PermissionsService` interface, now accepting the new `BackstageCredentials` object in addition to the `token` option, which is now deprecated. It now also optionally depends on the new `AuthService`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-permission-react@0.4.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-playlist@0.2.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + - @backstage/plugin-permission-react@0.4.21-next.0 + - @backstage/plugin-playlist-common@0.1.15-next.0 + +## @backstage/plugin-playlist-backend@0.3.17-next.0 + +### Patch Changes + +- 6813366: Migrated to support new auth services. +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-playlist-common@0.1.15-next.0 + +## @backstage/plugin-playlist-common@0.1.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + +## @backstage/plugin-proxy-backend@0.4.11-next.0 + +### Patch Changes + +- 1b4fd09: Updated dependency `yup` to `^1.0.0`. +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-puppetdb@0.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-rollbar@0.4.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-rollbar-backend@0.1.58-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-scaffolder@1.18.1-next.0 + +### Patch Changes + +- 0cecb09: Updated dependency `@rjsf/utils` to `5.17.1`. + Updated dependency `@rjsf/core` to `5.17.1`. + Updated dependency `@rjsf/material-ui` to `5.17.1`. + Updated dependency `@rjsf/validator-ajv8` to `5.17.1`. +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-scaffolder-react@1.8.1-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.22-next.0 + - @backstage/plugin-permission-react@0.4.21-next.0 + - @backstage/plugin-scaffolder-common@1.5.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-azure@0.1.5-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-bitbucket@0.2.3-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.3-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.3-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.3-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.3-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.14-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.37-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-gerrit@0.1.5-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-gitea@0.1.3-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-github@0.2.3-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- 1753898: Updated dependency `octokit-plugin-create-pull-request` to `^5.0.0`. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.2.16-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.30-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.21-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.34-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-scaffolder-node-test-utils@0.1.0-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-common@1.5.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-node@0.3.3-next.0 + +### Patch Changes + +- 85f4723: Fixed file corruption for non UTF-8 data in fetch contents +- c6b132e: Introducing checkpoints for scaffolder task action idempotency +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.5.1-next.0 + +## @backstage/plugin-scaffolder-react@1.8.1-next.0 + +### Patch Changes + +- 930b5c1: Added 'root' and 'label' class key to TemplateCategoryPicker +- 6d649d2: Updated dependency `flatted` to `3.3.1`. +- 0cecb09: Updated dependency `@rjsf/utils` to `5.17.1`. + Updated dependency `@rjsf/core` to `5.17.1`. + Updated dependency `@rjsf/material-ui` to `5.17.1`. + Updated dependency `@rjsf/validator-ajv8` to `5.17.1`. +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-scaffolder-common@1.5.1-next.0 + +## @backstage/plugin-search@1.4.7-next.0 + +### Patch Changes + +- f0464b0: Removes ADR from the default set of search filters +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/plugin-search-backend@1.5.3-next.0 + +### Patch Changes + +- 744c0cb: Update the router to use the new `auth` services, it now accepts an optional discovery service option to get credentials for the permission service. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/backend-openapi-utils@0.1.6-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-search-backend-module-catalog@0.1.17-next.0 + +### Patch Changes + +- bb368a5: Migrated to support new auth services. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + +## @backstage/plugin-search-backend-module-elasticsearch@1.3.16-next.0 + +### Patch Changes + +- 744c0cb: Start importing `QueryTranslator`, `QueryRequestOptions` and `SearchEngine` from the `@backstage/plugin-search-backend-node`. +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration-aws-node@0.1.10-next.0 + +## @backstage/plugin-search-backend-module-explore@0.1.17-next.0 + +### Patch Changes + +- bb368a5: Migrated to support new auth services. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-explore-common@0.0.2 + +## @backstage/plugin-search-backend-module-pg@0.5.22-next.0 + +### Patch Changes + +- 744c0cb: Start importing `QueryTranslator`, `QueryRequestOptions` and `SearchEngine` from the `@backstage/plugin-search-backend-node`. +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-search-backend-module-stack-overflow-collator@0.1.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-search-backend-module-techdocs@0.1.17-next.0 + +### Patch Changes + +- bb368a5: Migrated to support new auth services. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-techdocs-node@1.11.5-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + +## @backstage/plugin-search-backend-node@1.2.17-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- 744c0cb: Exports `QueryTranslator`, `QueryRequestOptions` and `SearchEngine` types. These new types were extracted from the `@backstage/plugin-search-common` package and the `token` property was deprecated in favor of the a new credentials one. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-search-common@1.2.11-next.0 + +### Patch Changes + +- 744c0cb: Deprecate `QueryTranslator`, `QueryRequestOptions` and `SearchEngine` in favor of the types exported from `@backstage/plugin-search-backend-node`. +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-search-react@1.7.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/plugin-sentry@0.5.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-shortcuts@0.3.20-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-signals@0.0.2-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-signals-react@0.0.2-next.0 + +## @backstage/plugin-signals-backend@0.0.4-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-signals-node@0.0.4-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-signals-node@0.0.4-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-signals-react@0.0.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-sonarqube@0.7.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-sonarqube-react@0.1.14-next.0 + +## @backstage/plugin-sonarqube-backend@0.2.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + +## @backstage/plugin-sonarqube-react@0.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-splunk-on-call@0.4.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-stack-overflow@0.1.26-next.0 + +### Patch Changes + +- c6779ac: fix: fix decode issues in title and author fields in `StackOverflowSearchResultListItem` +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/plugin-home-react@0.1.9-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + +## @backstage/plugin-stack-overflow-backend@0.2.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-module-stack-overflow-collator@0.1.6-next.0 + +## @backstage/plugin-stackstorm@0.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-tech-insights@0.3.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-backend@0.5.27-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- d621468: Added support for the new `AuthService`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-tech-insights-node@0.5.0-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.45-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-tech-insights-node@0.5.0-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-radar@0.6.14-next.0 + +### Patch Changes + +- a2327ac: Fixed an issue with the "moved in direction" table header cell getting squished and becoming unreadable if a timeline description is too long +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + +## @backstage/plugin-techdocs@1.10.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/plugin-techdocs-react@1.1.17-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-catalog@1.17.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-techdocs@1.10.1-next.0 + - @backstage/test-utils@1.5.1-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/plugin-techdocs-react@1.1.17-next.0 + - @backstage/core-app-api@1.12.1-next.0 + +## @backstage/plugin-techdocs-backend@1.9.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-techdocs-node@1.11.5-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.17-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/plugin-techdocs-react@1.1.17-next.0 + +## @backstage/plugin-techdocs-node@1.11.5-next.0 + +### Patch Changes + +- 5b4f565: Fix handling of default plugins that have configuration +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/integration-aws-node@0.1.10-next.0 + +## @backstage/plugin-techdocs-react@1.1.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/version-bridge@1.0.7 + +## @backstage/plugin-todo@0.2.35-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-todo-backend@0.3.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/repo-tools@0.6.3-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-openapi-utils@0.1.6-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + +## @backstage/plugin-user-settings@0.8.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-app-api@1.12.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-user-settings-backend@0.2.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-vault@0.1.26-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @backstage/plugin-vault-backend@0.4.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-vault-node@0.1.6-next.0 + +## @backstage/plugin-vault-node@0.1.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.13-next.0 + +## @backstage/plugin-xcmetrics@0.2.49-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## example-app@0.2.93-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-github-pull-requests-board@0.1.25-next.0 + - @backstage/plugin-adr@0.6.14-next.0 + - @backstage/plugin-stack-overflow@0.1.26-next.0 + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-notifications@0.1.0-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/cli@0.25.3-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-azure-devops@0.4.0-next.0 + - @backstage/plugin-linguist@0.1.16-next.0 + - @backstage/plugin-catalog@1.17.1-next.0 + - @backstage/plugin-org@0.6.21-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/plugin-search@1.4.7-next.0 + - @backstage/plugin-devtools@0.1.10-next.0 + - @backstage/plugin-tech-radar@0.6.14-next.0 + - @backstage/plugin-scaffolder-react@1.8.1-next.0 + - @backstage/plugin-api-docs@0.11.1-next.0 + - @backstage/plugin-cost-insights@0.12.20-next.0 + - @backstage/plugin-home@0.6.3-next.0 + - @backstage/plugin-scaffolder@1.18.1-next.0 + - @backstage/plugin-shortcuts@0.3.20-next.0 + - @backstage/plugin-signals@0.0.2-next.0 + - @backstage/plugin-catalog-import@0.10.7-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-app-api@0.6.1-next.0 + - @backstage/plugin-badges@0.2.55-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.1.9-next.0 + - @backstage/plugin-code-coverage@0.2.24-next.0 + - @backstage/plugin-entity-feedback@0.2.14-next.0 + - @backstage/plugin-explore@0.4.17-next.0 + - @backstage/plugin-gcalendar@0.3.24-next.0 + - @backstage/plugin-gocd@0.1.37-next.0 + - @backstage/plugin-jenkins@0.9.6-next.0 + - @backstage/plugin-microsoft-calendar@0.1.13-next.0 + - @backstage/plugin-newrelic-dashboard@0.3.6-next.0 + - @backstage/plugin-pagerduty@0.7.3-next.0 + - @backstage/plugin-playlist@0.2.5-next.0 + - @backstage/plugin-puppetdb@0.1.14-next.0 + - @backstage/plugin-stackstorm@0.1.12-next.0 + - @backstage/plugin-tech-insights@0.3.23-next.0 + - @backstage/plugin-techdocs@1.10.1-next.0 + - @backstage/plugin-todo@0.2.35-next.0 + - @backstage/plugin-user-settings@0.8.2-next.0 + - @backstage/app-defaults@1.5.1-next.0 + - @backstage/plugin-azure-sites@0.1.20-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/plugin-techdocs-react@1.1.17-next.0 + - @backstage/plugin-airbrake@0.3.31-next.0 + - @backstage/plugin-apache-airflow@0.2.21-next.0 + - @backstage/plugin-catalog-graph@0.4.1-next.0 + - @backstage/plugin-cloudbuild@0.4.1-next.0 + - @backstage/plugin-dynatrace@9.0.1-next.0 + - @backstage/plugin-gcp-projects@0.3.47-next.0 + - @backstage/plugin-github-actions@0.6.12-next.0 + - @backstage/plugin-graphiql@0.3.4-next.0 + - @backstage/plugin-kafka@0.3.31-next.0 + - @backstage/plugin-kubernetes@0.11.6-next.0 + - @backstage/plugin-kubernetes-cluster@0.0.7-next.0 + - @backstage/plugin-lighthouse@0.4.16-next.0 + - @backstage/plugin-newrelic@0.3.46-next.0 + - @backstage/plugin-nomad@0.1.12-next.0 + - @backstage/plugin-octopus-deploy@0.2.13-next.0 + - @backstage/plugin-rollbar@0.4.31-next.0 + - @backstage/plugin-sentry@0.5.16-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.6-next.0 + - @backstage/core-app-api@1.12.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-permission-react@0.4.21-next.0 + +## example-app-next@0.0.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-adr@0.6.14-next.0 + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/cli@0.25.3-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-azure-devops@0.4.0-next.0 + - @backstage/plugin-linguist@0.1.16-next.0 + - @backstage/plugin-catalog@1.17.1-next.0 + - @backstage/plugin-org@0.6.21-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/plugin-search@1.4.7-next.0 + - @backstage/plugin-devtools@0.1.10-next.0 + - @backstage/plugin-tech-radar@0.6.14-next.0 + - @backstage/plugin-scaffolder-react@1.8.1-next.0 + - @backstage/plugin-api-docs@0.11.1-next.0 + - @backstage/plugin-cost-insights@0.12.20-next.0 + - @backstage/plugin-home@0.6.3-next.0 + - @backstage/plugin-scaffolder@1.18.1-next.0 + - @backstage/plugin-shortcuts@0.3.20-next.0 + - @backstage/plugin-catalog-import@0.10.7-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-app-api@0.6.1-next.0 + - @backstage/plugin-badges@0.2.55-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.1.9-next.0 + - @backstage/plugin-code-coverage@0.2.24-next.0 + - @backstage/plugin-entity-feedback@0.2.14-next.0 + - @backstage/plugin-explore@0.4.17-next.0 + - @backstage/plugin-gcalendar@0.3.24-next.0 + - @backstage/plugin-gocd@0.1.37-next.0 + - @backstage/plugin-jenkins@0.9.6-next.0 + - @backstage/plugin-microsoft-calendar@0.1.13-next.0 + - @backstage/plugin-newrelic-dashboard@0.3.6-next.0 + - @backstage/plugin-pagerduty@0.7.3-next.0 + - @backstage/plugin-playlist@0.2.5-next.0 + - @backstage/plugin-puppetdb@0.1.14-next.0 + - @backstage/plugin-stackstorm@0.1.12-next.0 + - @backstage/plugin-tech-insights@0.3.23-next.0 + - @backstage/plugin-techdocs@1.10.1-next.0 + - @backstage/plugin-todo@0.2.35-next.0 + - @backstage/plugin-user-settings@0.8.2-next.0 + - @backstage/app-defaults@1.5.1-next.0 + - @backstage/plugin-azure-sites@0.1.20-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/plugin-techdocs-react@1.1.17-next.0 + - app-next-example-plugin@0.0.7-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/plugin-airbrake@0.3.31-next.0 + - @backstage/plugin-apache-airflow@0.2.21-next.0 + - @backstage/plugin-app-visualizer@0.1.2-next.0 + - @backstage/plugin-catalog-graph@0.4.1-next.0 + - @backstage/plugin-cloudbuild@0.4.1-next.0 + - @backstage/plugin-dynatrace@9.0.1-next.0 + - @backstage/plugin-gcp-projects@0.3.47-next.0 + - @backstage/plugin-github-actions@0.6.12-next.0 + - @backstage/plugin-graphiql@0.3.4-next.0 + - @backstage/plugin-kafka@0.3.31-next.0 + - @backstage/plugin-kubernetes@0.11.6-next.0 + - @backstage/plugin-lighthouse@0.4.16-next.0 + - @backstage/plugin-newrelic@0.3.46-next.0 + - @backstage/plugin-octopus-deploy@0.2.13-next.0 + - @backstage/plugin-rollbar@0.4.31-next.0 + - @backstage/plugin-sentry@0.5.16-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.6-next.0 + - @backstage/core-app-api@1.12.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-permission-react@0.4.21-next.0 + +## app-next-example-plugin@0.0.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + +## example-backend@0.2.93-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-backend@0.3.0-next.0 + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/plugin-linguist-backend@0.5.10-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/plugin-lighthouse-backend@0.4.5-next.0 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.16-next.0 + - @backstage/plugin-search-backend-module-pg@0.5.22-next.0 + - @backstage/plugin-playlist-backend@0.3.17-next.0 + - @backstage/plugin-code-coverage-backend@0.2.27-next.0 + - @backstage/plugin-entity-feedback-backend@0.2.10-next.0 + - @backstage/plugin-catalog-backend@1.18.0-next.0 + - @backstage/plugin-auth-backend@0.22.0-next.0 + - @backstage/plugin-jenkins-backend@0.4.0-next.0 + - @backstage/plugin-azure-devops-backend@0.6.0-next.0 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.14-next.0 + - @backstage/plugin-scaffolder-backend-module-gitlab@0.2.16-next.0 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.30-next.0 + - @backstage/plugin-scaffolder-backend@1.22.0-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.17-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.17-next.0 + - @backstage/plugin-search-backend-module-explore@0.1.17-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/plugin-kubernetes-backend@0.16.0-next.0 + - @backstage/plugin-adr-backend@0.4.10-next.0 + - @backstage/plugin-proxy-backend@0.4.11-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/plugin-signals-backend@0.0.4-next.0 + - @backstage/plugin-signals-node@0.0.4-next.0 + - @backstage/plugin-tech-insights-backend@0.5.27-next.0 + - @backstage/plugin-search-backend@1.5.3-next.0 + - @backstage/plugin-devtools-backend@0.3.0-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/plugin-tech-insights-node@0.5.0-next.0 + - @backstage/plugin-badges-backend@0.3.10-next.0 + - @backstage/plugin-permission-backend@0.5.36-next.0 + - @backstage/plugin-app-backend@0.3.61-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.10-next.0 + - @backstage/plugin-explore-backend@0.0.23-next.0 + - @backstage/plugin-rollbar-backend@0.1.58-next.0 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.45-next.0 + - @backstage/plugin-techdocs-backend@1.9.6-next.0 + - @backstage/plugin-kafka-backend@0.3.11-next.0 + - @backstage/plugin-nomad-backend@0.1.15-next.0 + - @backstage/plugin-todo-backend@0.3.11-next.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.10-next.0 + - example-app@0.2.93-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/plugin-azure-sites-common@0.1.3-next.0 + +## example-backend-next@0.0.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-linguist-backend@0.5.10-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/plugin-lighthouse-backend@0.4.5-next.0 + - @backstage/plugin-auth-backend-module-guest-provider@0.1.0-next.0 + - @backstage/plugin-playlist-backend@0.3.17-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-entity-feedback-backend@0.2.10-next.0 + - @backstage/plugin-notifications-backend@0.1.0-next.0 + - @backstage/plugin-catalog-backend@1.18.0-next.0 + - @backstage/plugin-auth-backend@0.22.0-next.0 + - @backstage/plugin-jenkins-backend@0.4.0-next.0 + - @backstage/plugin-azure-devops-backend@0.6.0-next.0 + - @backstage/plugin-scaffolder-backend-module-github@0.2.3-next.0 + - @backstage/plugin-scaffolder-backend@1.22.0-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.17-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.17-next.0 + - @backstage/plugin-search-backend-module-explore@0.1.17-next.0 + - @backstage/backend-defaults@0.2.13-next.0 + - @backstage/plugin-kubernetes-backend@0.16.0-next.0 + - @backstage/plugin-adr-backend@0.4.10-next.0 + - @backstage/plugin-proxy-backend@0.4.11-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/plugin-signals-backend@0.0.4-next.0 + - @backstage/plugin-search-backend@1.5.3-next.0 + - @backstage/plugin-devtools-backend@0.3.0-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.1.6-next.0 + - @backstage/plugin-badges-backend@0.3.10-next.0 + - @backstage/plugin-permission-backend@0.5.36-next.0 + - @backstage/plugin-app-backend@0.3.61-next.0 + - @backstage/plugin-auth-backend-module-github-provider@0.1.10-next.0 + - @backstage/plugin-catalog-backend-module-openapi@0.1.30-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.10-next.0 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.10-next.0 + - @backstage/plugin-sonarqube-backend@0.2.15-next.0 + - @backstage/plugin-techdocs-backend@1.9.6-next.0 + - @backstage/plugin-nomad-backend@0.1.15-next.0 + - @backstage/plugin-todo-backend@0.3.11-next.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.10-next.0 + - @backstage/catalog-model@1.4.5-next.0 + +## e2e-test@0.2.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.12-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/cli-common@0.1.13 + +## techdocs-cli-embedded-app@0.2.92-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/cli@0.25.3-next.0 + - @backstage/plugin-catalog@1.17.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-techdocs@1.10.1-next.0 + - @backstage/app-defaults@1.5.1-next.0 + - @backstage/test-utils@1.5.1-next.0 + - @backstage/plugin-techdocs-react@1.1.17-next.0 + - @backstage/core-app-api@1.12.1-next.0 + +## @internal/plugin-todo-list@1.0.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + +## @internal/plugin-todo-list-backend@1.0.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + +## @internal/plugin-todo-list-common@1.0.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 diff --git a/microsite/sidebars.json b/microsite/sidebars.json index 4f2724c0b6..155227f30a 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -116,6 +116,7 @@ "features/software-templates/input-examples", "features/software-templates/builtin-actions", "features/software-templates/writing-custom-actions", + "features/software-templates/writing-tests-for-actions", "features/software-templates/writing-custom-field-extensions", "features/software-templates/writing-custom-step-layouts", "features/software-templates/authorizing-parameters-steps-and-actions", @@ -307,6 +308,7 @@ "auth/gitlab/provider", "auth/google/provider", "auth/google/gcp-iap-auth", + "auth/guest/provider", "auth/okta/provider", "auth/oauth2-proxy/provider", "auth/onelogin/provider", diff --git a/mkdocs.yml b/mkdocs.yml index 2a17613672..a2b2749233 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -161,6 +161,7 @@ nav: - GitLab: 'auth/gitlab/provider.md' - Google: 'auth/google/provider.md' - Google IAP: 'auth/google/gcp-iap-auth.md' + - Guest: 'auth/guest/provider.md' - OAuth2Proxy: 'auth/oauth2-proxy/provider.md' - Okta: 'auth/okta/provider.md' - OneLogin: 'auth/onelogin/provider.md' diff --git a/package.json b/package.json index 937ea4e19d..f4694c05fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "root", - "version": "1.23.0", + "version": "1.24.0-next.0", "private": true, "repository": { "type": "git", diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index 20a33c612d..7a81f55437 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/app-defaults +## 1.5.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/core-app-api@1.12.1-next.0 + - @backstage/plugin-permission-react@0.4.21-next.0 + ## 1.5.0 ### Minor Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index 3b695129e1..9a31e5bd88 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/app-defaults", - "version": "1.5.0", + "version": "1.5.1-next.0", "description": "Provides the default wiring of a Backstage App", "backstage": { "role": "web-library" diff --git a/packages/app-next-example-plugin/CHANGELOG.md b/packages/app-next-example-plugin/CHANGELOG.md index 29b7877580..444e8e8197 100644 --- a/packages/app-next-example-plugin/CHANGELOG.md +++ b/packages/app-next-example-plugin/CHANGELOG.md @@ -1,5 +1,13 @@ # app-next-example-plugin +## 0.0.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + ## 0.0.6 ### Patch Changes diff --git a/packages/app-next-example-plugin/package.json b/packages/app-next-example-plugin/package.json index 08a08f9603..aa2560bb46 100644 --- a/packages/app-next-example-plugin/package.json +++ b/packages/app-next-example-plugin/package.json @@ -1,6 +1,6 @@ { "name": "app-next-example-plugin", - "version": "0.0.6", + "version": "0.0.7-next.0", "description": "Backstage internal example plugin", "backstage": { "role": "frontend-plugin" diff --git a/packages/app-next/CHANGELOG.md b/packages/app-next/CHANGELOG.md index 89378b491d..eb6c22934d 100644 --- a/packages/app-next/CHANGELOG.md +++ b/packages/app-next/CHANGELOG.md @@ -1,5 +1,81 @@ # example-app-next +## 0.0.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-adr@0.6.14-next.0 + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/cli@0.25.3-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-azure-devops@0.4.0-next.0 + - @backstage/plugin-linguist@0.1.16-next.0 + - @backstage/plugin-catalog@1.17.1-next.0 + - @backstage/plugin-org@0.6.21-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/plugin-search@1.4.7-next.0 + - @backstage/plugin-devtools@0.1.10-next.0 + - @backstage/plugin-tech-radar@0.6.14-next.0 + - @backstage/plugin-scaffolder-react@1.8.1-next.0 + - @backstage/plugin-api-docs@0.11.1-next.0 + - @backstage/plugin-cost-insights@0.12.20-next.0 + - @backstage/plugin-home@0.6.3-next.0 + - @backstage/plugin-scaffolder@1.18.1-next.0 + - @backstage/plugin-shortcuts@0.3.20-next.0 + - @backstage/plugin-catalog-import@0.10.7-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-app-api@0.6.1-next.0 + - @backstage/plugin-badges@0.2.55-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.1.9-next.0 + - @backstage/plugin-code-coverage@0.2.24-next.0 + - @backstage/plugin-entity-feedback@0.2.14-next.0 + - @backstage/plugin-explore@0.4.17-next.0 + - @backstage/plugin-gcalendar@0.3.24-next.0 + - @backstage/plugin-gocd@0.1.37-next.0 + - @backstage/plugin-jenkins@0.9.6-next.0 + - @backstage/plugin-microsoft-calendar@0.1.13-next.0 + - @backstage/plugin-newrelic-dashboard@0.3.6-next.0 + - @backstage/plugin-pagerduty@0.7.3-next.0 + - @backstage/plugin-playlist@0.2.5-next.0 + - @backstage/plugin-puppetdb@0.1.14-next.0 + - @backstage/plugin-stackstorm@0.1.12-next.0 + - @backstage/plugin-tech-insights@0.3.23-next.0 + - @backstage/plugin-techdocs@1.10.1-next.0 + - @backstage/plugin-todo@0.2.35-next.0 + - @backstage/plugin-user-settings@0.8.2-next.0 + - @backstage/app-defaults@1.5.1-next.0 + - @backstage/plugin-azure-sites@0.1.20-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/plugin-techdocs-react@1.1.17-next.0 + - app-next-example-plugin@0.0.7-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/plugin-airbrake@0.3.31-next.0 + - @backstage/plugin-apache-airflow@0.2.21-next.0 + - @backstage/plugin-app-visualizer@0.1.2-next.0 + - @backstage/plugin-catalog-graph@0.4.1-next.0 + - @backstage/plugin-cloudbuild@0.4.1-next.0 + - @backstage/plugin-dynatrace@9.0.1-next.0 + - @backstage/plugin-gcp-projects@0.3.47-next.0 + - @backstage/plugin-github-actions@0.6.12-next.0 + - @backstage/plugin-graphiql@0.3.4-next.0 + - @backstage/plugin-kafka@0.3.31-next.0 + - @backstage/plugin-kubernetes@0.11.6-next.0 + - @backstage/plugin-lighthouse@0.4.16-next.0 + - @backstage/plugin-newrelic@0.3.46-next.0 + - @backstage/plugin-octopus-deploy@0.2.13-next.0 + - @backstage/plugin-rollbar@0.4.31-next.0 + - @backstage/plugin-sentry@0.5.16-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.6-next.0 + - @backstage/core-app-api@1.12.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-permission-react@0.4.21-next.0 + ## 0.0.6 ### Patch Changes diff --git a/packages/app-next/package.json b/packages/app-next/package.json index bd3db0d1c9..39457f8cf7 100644 --- a/packages/app-next/package.json +++ b/packages/app-next/package.json @@ -1,6 +1,6 @@ { "name": "example-app-next", - "version": "0.0.6", + "version": "0.0.7-next.0", "private": true, "repository": { "type": "git", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 766214cb2d..149d101dd9 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,84 @@ # example-app +## 0.2.93-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-github-pull-requests-board@0.1.25-next.0 + - @backstage/plugin-adr@0.6.14-next.0 + - @backstage/plugin-stack-overflow@0.1.26-next.0 + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-notifications@0.1.0-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/cli@0.25.3-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-azure-devops@0.4.0-next.0 + - @backstage/plugin-linguist@0.1.16-next.0 + - @backstage/plugin-catalog@1.17.1-next.0 + - @backstage/plugin-org@0.6.21-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/plugin-search@1.4.7-next.0 + - @backstage/plugin-devtools@0.1.10-next.0 + - @backstage/plugin-tech-radar@0.6.14-next.0 + - @backstage/plugin-scaffolder-react@1.8.1-next.0 + - @backstage/plugin-api-docs@0.11.1-next.0 + - @backstage/plugin-cost-insights@0.12.20-next.0 + - @backstage/plugin-home@0.6.3-next.0 + - @backstage/plugin-scaffolder@1.18.1-next.0 + - @backstage/plugin-shortcuts@0.3.20-next.0 + - @backstage/plugin-signals@0.0.2-next.0 + - @backstage/plugin-catalog-import@0.10.7-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-app-api@0.6.1-next.0 + - @backstage/plugin-badges@0.2.55-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.1.9-next.0 + - @backstage/plugin-code-coverage@0.2.24-next.0 + - @backstage/plugin-entity-feedback@0.2.14-next.0 + - @backstage/plugin-explore@0.4.17-next.0 + - @backstage/plugin-gcalendar@0.3.24-next.0 + - @backstage/plugin-gocd@0.1.37-next.0 + - @backstage/plugin-jenkins@0.9.6-next.0 + - @backstage/plugin-microsoft-calendar@0.1.13-next.0 + - @backstage/plugin-newrelic-dashboard@0.3.6-next.0 + - @backstage/plugin-pagerduty@0.7.3-next.0 + - @backstage/plugin-playlist@0.2.5-next.0 + - @backstage/plugin-puppetdb@0.1.14-next.0 + - @backstage/plugin-stackstorm@0.1.12-next.0 + - @backstage/plugin-tech-insights@0.3.23-next.0 + - @backstage/plugin-techdocs@1.10.1-next.0 + - @backstage/plugin-todo@0.2.35-next.0 + - @backstage/plugin-user-settings@0.8.2-next.0 + - @backstage/app-defaults@1.5.1-next.0 + - @backstage/plugin-azure-sites@0.1.20-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/plugin-techdocs-react@1.1.17-next.0 + - @backstage/plugin-airbrake@0.3.31-next.0 + - @backstage/plugin-apache-airflow@0.2.21-next.0 + - @backstage/plugin-catalog-graph@0.4.1-next.0 + - @backstage/plugin-cloudbuild@0.4.1-next.0 + - @backstage/plugin-dynatrace@9.0.1-next.0 + - @backstage/plugin-gcp-projects@0.3.47-next.0 + - @backstage/plugin-github-actions@0.6.12-next.0 + - @backstage/plugin-graphiql@0.3.4-next.0 + - @backstage/plugin-kafka@0.3.31-next.0 + - @backstage/plugin-kubernetes@0.11.6-next.0 + - @backstage/plugin-kubernetes-cluster@0.0.7-next.0 + - @backstage/plugin-lighthouse@0.4.16-next.0 + - @backstage/plugin-newrelic@0.3.46-next.0 + - @backstage/plugin-nomad@0.1.12-next.0 + - @backstage/plugin-octopus-deploy@0.2.13-next.0 + - @backstage/plugin-rollbar@0.4.31-next.0 + - @backstage/plugin-sentry@0.5.16-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.6-next.0 + - @backstage/core-app-api@1.12.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-permission-react@0.4.21-next.0 + ## 0.2.92 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 7936db0090..c3aa748b58 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.92", + "version": "0.2.93-next.0", "private": true, "backstage": { "role": "frontend" diff --git a/packages/app/src/components/search/SearchPage.tsx b/packages/app/src/components/search/SearchPage.tsx index a9f54cdb49..d904aef45c 100644 --- a/packages/app/src/components/search/SearchPage.tsx +++ b/packages/app/src/components/search/SearchPage.tsx @@ -87,11 +87,6 @@ const SearchPage = () => { name: 'Documentation', icon: , }, - { - value: 'adr', - name: 'Architecture Decision Records', - icon: , - }, ]} /> diff --git a/packages/backend-app-api/CHANGELOG.md b/packages/backend-app-api/CHANGELOG.md index c3ecdc3ed2..a52b2b0d86 100644 --- a/packages/backend-app-api/CHANGELOG.md +++ b/packages/backend-app-api/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/backend-app-api +## 0.6.0-next.0 + +### Minor Changes + +- 4a3d434: **BREAKING**: For users that have migrated to the new backend system, incoming requests will now be rejected if they are not properly authenticated (e.g. with a Backstage bearer token or a backend token). Please see the [Auth Service Migration tutorial](https://backstage.io/docs/tutorials/auth-service-migration) for more information on how to circumvent this behavior in the short term and how to properly leverage it in the longer term. + + Added service factories for the new [`auth`](https://backstage.io/docs/backend-system/core-services/auth/), [`httpAuth`](https://backstage.io/docs/backend-system/core-services/http-auth), and [`userInfo`](https://backstage.io/docs/backend-system/core-services/user-info) services that were created as part of [BEP-0003](https://github.com/backstage/backstage/tree/master/beps/0003-auth-architecture-evolution). + +### Patch Changes + +- 999224f: Bump dependency `minimatch` to v9 +- 0502d82: Updated the `permissionsServiceFactory` to forward the `AuthService` to the implementation. +- 9802004: Made the `DefaultUserInfoService` claims check stricter +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/cli-node@0.2.4-next.0 + - @backstage/config-loader@1.6.3-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/cli-common@0.1.13 + - @backstage/types@1.1.1 + ## 0.5.11 ### Patch Changes diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index ae46e13083..ecc4dce4b5 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.5.11", + "version": "0.6.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-app-api/src/services/implementations/auth/authServiceFactory.test.ts b/packages/backend-app-api/src/services/implementations/auth/authServiceFactory.test.ts index f24264930a..4600110b5c 100644 --- a/packages/backend-app-api/src/services/implementations/auth/authServiceFactory.test.ts +++ b/packages/backend-app-api/src/services/implementations/auth/authServiceFactory.test.ts @@ -28,10 +28,12 @@ import { BackstageServicePrincipal, BackstageUserPrincipal, } from '@backstage/backend-plugin-api'; +import { tokenManagerServiceFactory } from '../tokenManager'; // TODO: Ship discovery mock service in the service factory tester const mockDeps = [ discoveryServiceFactory(), + tokenManagerServiceFactory, mockServices.rootConfig.factory({ data: { backend: { diff --git a/packages/backend-app-api/src/services/implementations/auth/authServiceFactory.ts b/packages/backend-app-api/src/services/implementations/auth/authServiceFactory.ts index 72d5635f61..ac5c1f9399 100644 --- a/packages/backend-app-api/src/services/implementations/auth/authServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/auth/authServiceFactory.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { ServerTokenManager, TokenManager } from '@backstage/backend-common'; +import { TokenManager } from '@backstage/backend-common'; import { AuthService, BackstageCredentials, @@ -27,10 +27,7 @@ import { createServiceFactory, } from '@backstage/backend-plugin-api'; import { AuthenticationError } from '@backstage/errors'; -import { - DefaultIdentityClient, - IdentityApiGetIdentityRequest, -} from '@backstage/plugin-auth-node'; +import { IdentityApiGetIdentityRequest } from '@backstage/plugin-auth-node'; import { decodeJwt } from 'jose'; /** @internal */ @@ -38,37 +35,37 @@ export type InternalBackstageCredentials = BackstageCredentials & { version: string; token?: string; - authMethod: 'token' | 'cookie' | 'none'; }; export function createCredentialsWithServicePrincipal( sub: string, + token?: string, ): InternalBackstageCredentials { return { $$type: '@backstage/BackstageCredentials', version: 'v1', + token, principal: { type: 'service', subject: sub, }, - authMethod: 'token', }; } export function createCredentialsWithUserPrincipal( sub: string, token: string, - authMethod: 'token' | 'cookie' = 'token', + expiresAt?: Date, ): InternalBackstageCredentials { return { $$type: '@backstage/BackstageCredentials', version: 'v1', token, + expiresAt, principal: { type: 'user', userEntityRef: sub, }, - authMethod, }; } @@ -79,7 +76,6 @@ export function createCredentialsWithNonePrincipal(): InternalBackstageCredentia principal: { type: 'none', }, - authMethod: 'none', }; } @@ -114,6 +110,7 @@ class DefaultAuthService implements AuthService { private readonly disableDefaultAuthPolicy: boolean, ) {} + // allowLimitedAccess is currently ignored, since we currently always use the full user tokens async authenticate(token: string): Promise { const { sub, aud } = decodeJwt(token); @@ -137,6 +134,7 @@ class DefaultAuthService implements AuthService { return createCredentialsWithUserPrincipal( identity.identity.userEntityRef, token, + this.#getJwtExpiration(token), ); } @@ -159,6 +157,12 @@ class DefaultAuthService implements AuthService { return true; } + async getNoneCredentials(): Promise< + BackstageCredentials + > { + return createCredentialsWithNonePrincipal(); + } + async getOwnServiceCredentials(): Promise< BackstageCredentials > { @@ -196,6 +200,30 @@ class DefaultAuthService implements AuthService { ); } } + + async getLimitedUserToken( + credentials: BackstageCredentials, + ): Promise<{ token: string; expiresAt: Date }> { + const internalCredentials = toInternalBackstageCredentials(credentials); + + const { token } = internalCredentials; + + if (!token) { + throw new AuthenticationError( + 'User credentials is unexpectedly missing token', + ); + } + + return { token, expiresAt: this.#getJwtExpiration(token) }; + } + + #getJwtExpiration(token: string) { + const { exp } = decodeJwt(token); + if (!exp) { + throw new AuthenticationError('User token is missing expiration'); + } + return new Date(exp * 1000); + } } /** @public */ @@ -204,14 +232,15 @@ export const authServiceFactory = createServiceFactory({ deps: { config: coreServices.rootConfig, logger: coreServices.rootLogger, - discovery: coreServices.discovery, plugin: coreServices.pluginMetadata, + identity: coreServices.identity, + // Re-using the token manager makes sure that we use the same generated keys for + // development as plugins that have not yet been migrated. It's important that this + // keeps working as long as there are plugins that have not been migrated to the + // new auth services in the new backend system. + tokenManager: coreServices.tokenManager, }, - createRootContext({ config, logger }) { - return ServerTokenManager.fromConfig(config, { logger }); - }, - async factory({ discovery, config, plugin }, tokenManager) { - const identity = DefaultIdentityClient.create({ discovery }); + async factory({ config, plugin, identity, tokenManager }) { const disableDefaultAuthPolicy = Boolean( config.getOptionalBoolean( 'backend.auth.dangerouslyDisableDefaultAuthPolicy', diff --git a/packages/backend-app-api/src/services/implementations/httpAuth/httpAuthServiceFactory.ts b/packages/backend-app-api/src/services/implementations/httpAuth/httpAuthServiceFactory.ts index 1bd9d3cf2a..db36e5bf2a 100644 --- a/packages/backend-app-api/src/services/implementations/httpAuth/httpAuthServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/httpAuth/httpAuthServiceFactory.ts @@ -18,6 +18,7 @@ import { AuthService, BackstageCredentials, BackstagePrincipalTypes, + BackstageUserPrincipal, DiscoveryService, HttpAuthService, coreServices, @@ -26,11 +27,8 @@ import { import { AuthenticationError, NotAllowedError } from '@backstage/errors'; import { parse as parseCookie } from 'cookie'; import { Request, Response } from 'express'; -import { decodeJwt } from 'jose'; -import { - createCredentialsWithNonePrincipal, - toInternalBackstageCredentials, -} from '../auth/authServiceFactory'; + +const FIVE_MINUTES_MS = 5 * 60 * 1000; const BACKSTAGE_AUTH_COOKIE = 'backstage-auth'; @@ -41,54 +39,78 @@ function getTokenFromRequest(req: Request) { const matches = authHeader.match(/^Bearer[ ]+(\S+)$/i); const token = matches?.[1]; if (token) { - return { token, isCookie: false }; + return token; } } + return undefined; +} + +function getCookieFromRequest(req: Request) { const cookieHeader = req.headers.cookie; if (cookieHeader) { const cookies = parseCookie(cookieHeader); const token = cookies[BACKSTAGE_AUTH_COOKIE]; if (token) { - return { token, isCookie: true }; + return token; } } - return { token: undefined, isCookie: false }; + return undefined; +} + +function willExpireSoon(expiresAt: Date) { + return Date.now() + FIVE_MINUTES_MS > expiresAt.getTime(); } const credentialsSymbol = Symbol('backstage-credentials'); +const limitedCredentialsSymbol = Symbol('backstage-limited-credentials'); type RequestWithCredentials = Request & { [credentialsSymbol]?: Promise; + [limitedCredentialsSymbol]?: Promise; }; class DefaultHttpAuthService implements HttpAuthService { + readonly #auth: AuthService; + readonly #discovery: DiscoveryService; + readonly #pluginId: string; + constructor( - private readonly auth: AuthService, - private readonly discovery: DiscoveryService, - private readonly pluginId: string, - ) {} + auth: AuthService, + discovery: DiscoveryService, + pluginId: string, + ) { + this.#auth = auth; + this.#discovery = discovery; + this.#pluginId = pluginId; + } async #extractCredentialsFromRequest(req: Request) { - const { token, isCookie } = getTokenFromRequest(req); + const token = getTokenFromRequest(req); if (!token) { - return createCredentialsWithNonePrincipal(); + return await this.#auth.getNoneCredentials(); } - const credentials = toInternalBackstageCredentials( - await this.auth.authenticate(token), - ); - if (isCookie) { - if (credentials.principal.type !== 'user') { - throw new AuthenticationError( - 'Refusing to authenticate non-user principal with cookie auth', - ); - } - credentials.authMethod = 'cookie'; + return await this.#auth.authenticate(token); + } + + async #extractLimitedCredentialsFromRequest(req: Request) { + const token = getTokenFromRequest(req); + if (token) { + return await this.#auth.authenticate(token, { + allowLimitedAccess: true, + }); } - return credentials; + const cookie = getCookieFromRequest(req); + if (cookie) { + return await this.#auth.authenticate(cookie, { + allowLimitedAccess: true, + }); + } + + return await this.#auth.getNoneCredentials(); } async #getCredentials(req: RequestWithCredentials) { @@ -96,73 +118,131 @@ class DefaultHttpAuthService implements HttpAuthService { this.#extractCredentialsFromRequest(req)); } + async #getLimitedCredentials(req: RequestWithCredentials) { + return (req[limitedCredentialsSymbol] ??= + this.#extractLimitedCredentialsFromRequest(req)); + } + async credentials( req: Request, options?: { allow?: Array; - allowedAuthMethods?: Array<'token' | 'cookie'>; + allowLimitedAccess?: boolean; }, ): Promise> { - const credentials = toInternalBackstageCredentials( - await this.#getCredentials(req), - ); + // Limited and full credentials are treated as two separate cases, this lets + // us avoid internal dependencies between the AuthService and + // HttpAuthService implementations + const credentials = options?.allowLimitedAccess + ? await this.#getLimitedCredentials(req) + : await this.#getCredentials(req); - const allowedPrincipalTypes = options?.allow; - const allowedAuthMethods: Array<'token' | 'cookie' | 'none'> = - options?.allowedAuthMethods ?? ['token']; - - if ( - credentials.authMethod !== 'none' && - !allowedAuthMethods.includes(credentials.authMethod) - ) { - throw new NotAllowedError( - `This endpoint does not allow the '${credentials.authMethod}' auth method`, - ); + const allowed = options?.allow; + if (!allowed) { + return credentials as any; } - if ( - allowedPrincipalTypes && - !allowedPrincipalTypes.includes(credentials.principal.type as TAllowed) - ) { - if (credentials.authMethod === 'none') { - throw new AuthenticationError(); + if (this.#auth.isPrincipal(credentials, 'none')) { + if (allowed.includes('none' as TAllowed)) { + return credentials as any; } + + throw new AuthenticationError('Missing credentials'); + } else if (this.#auth.isPrincipal(credentials, 'user')) { + if (allowed.includes('user' as TAllowed)) { + return credentials as any; + } + throw new NotAllowedError( - `This endpoint does not allow '${credentials.principal.type}' credentials`, + `This endpoint does not allow 'user' credentials`, + ); + } else if (this.#auth.isPrincipal(credentials, 'service')) { + if (allowed.includes('service' as TAllowed)) { + return credentials as any; + } + + throw new NotAllowedError( + `This endpoint does not allow 'service' credentials`, ); } - return credentials as any; + throw new NotAllowedError( + 'Unknown principal type, this should never happen', + ); } - async issueUserCookie(res: Response): Promise { - const credentials = await this.credentials(res.req, { allow: ['user'] }); + async issueUserCookie( + res: Response, + options?: { credentials?: BackstageCredentials }, + ): Promise<{ expiresAt: Date }> { + if (res.headersSent) { + throw new Error('Failed to issue user cookie, headers were already sent'); + } + + let credentials: BackstageCredentials; + if (options?.credentials) { + if (!this.#auth.isPrincipal(options.credentials, 'user')) { + throw new AuthenticationError( + 'Refused to issue cookie for non-user principal', + ); + } + credentials = options.credentials; + } else { + credentials = await this.credentials(res.req, { allow: ['user'] }); + } + + const existingExpiresAt = await this.#existingCookieExpiration(res.req); + if (existingExpiresAt && !willExpireSoon(existingExpiresAt)) { + return { expiresAt: existingExpiresAt }; + } + + const originHeader = res.req.headers.origin; + const origin = + !originHeader || originHeader === 'null' ? undefined : originHeader; // https://backstage.example.com/api/catalog - const externalBaseUrlStr = await this.discovery.getExternalBaseUrl( - this.pluginId, + const externalBaseUrlStr = await this.#discovery.getExternalBaseUrl( + this.#pluginId, ); - const externalBaseUrl = new URL(externalBaseUrlStr); + const externalBaseUrl = new URL(origin ?? externalBaseUrlStr); - const { token } = toInternalBackstageCredentials(credentials); + const { token, expiresAt } = await this.#auth.getLimitedUserToken( + credentials, + ); if (!token) { throw new Error('User credentials is unexpectedly missing token'); } - // TODO: Proper refresh and expiration handling - const expires = decodeJwt(token).exp!; + const secure = + externalBaseUrl.protocol === 'https:' || + externalBaseUrl.hostname === 'localhost'; - // TODO: refresh this thing res.cookie(BACKSTAGE_AUTH_COOKIE, token, { domain: externalBaseUrl.hostname, httpOnly: true, - expires: new Date(expires * 1000), - path: externalBaseUrl.pathname, + expires: expiresAt, + secure, priority: 'high', - sameSite: 'lax', // TBD + sameSite: secure ? 'none' : 'lax', }); - throw new Error('Method not implemented.'); + return { expiresAt }; + } + + async #existingCookieExpiration(req: Request): Promise { + const existingCookie = getCookieFromRequest(req); + if (!existingCookie) { + return undefined; + } + + const existingCredentials = await this.#auth.authenticate(existingCookie, { + allowLimitedAccess: true, + }); + if (!this.#auth.isPrincipal(existingCredentials, 'user')) { + return undefined; + } + + return existingCredentials.expiresAt; } } diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/createCredentialsBarrier.test.ts b/packages/backend-app-api/src/services/implementations/httpRouter/createCredentialsBarrier.test.ts index b8430d398e..a5246c91b2 100644 --- a/packages/backend-app-api/src/services/implementations/httpRouter/createCredentialsBarrier.test.ts +++ b/packages/backend-app-api/src/services/implementations/httpRouter/createCredentialsBarrier.test.ts @@ -53,7 +53,10 @@ describe('createCredentialsBarrier', () => { .expect(401) .expect(res => expect(res.body).toMatchObject({ - error: { name: 'AuthenticationError', message: '' }, + error: { + name: 'AuthenticationError', + message: 'Missing credentials', + }, }), ); @@ -98,7 +101,7 @@ describe('createCredentialsBarrier', () => { .expect(200); }); - it('should allow exceptions to the default auth policy to be made', async () => { + it('should allow exceptions for unauthenticated access', async () => { const { app, barrier } = setup(); await request(app).get('/').send().expect(401); @@ -118,5 +121,55 @@ describe('createCredentialsBarrier', () => { await request(app).get('/other').send().expect(200); }); - // TODO: cookie auth + it('should allow exceptions for cookie access', async () => { + const { app, barrier } = setup(); + + await request(app).get('/').send().expect(401); + await request(app).get('/public').send().expect(401); + await request(app).get('/other').send().expect(401); + await request(app) + .get('/static') + .set('cookie', mockCredentials.limitedUser.cookie()) + .send() + .expect(401); + await request(app) + .get('/static') + .set('authorization', mockCredentials.user.header()) + .send() + .expect(200); + + barrier.addAuthPolicy({ allow: 'user-cookie', path: '/static' }); + + await request(app).get('/').send().expect(401); + await request(app).get('/static').send().expect(401); + await request(app) + .get('/static') + .set('cookie', mockCredentials.limitedUser.cookie()) + .send() + .expect(200); + await request(app) + .get('/static') + .set('authorization', mockCredentials.user.header()) + .send() + .expect(200); + + await request(app).get('/other').send().expect(401); + + // Unauthenticated access should take precedence + barrier.addAuthPolicy({ allow: 'unauthenticated', path: '/' }); + + await request(app).get('/').send().expect(200); + await request(app).get('/static').send().expect(200); + await request(app) + .get('/static') + .set('cookie', mockCredentials.limitedUser.cookie()) + .send() + .expect(200); + await request(app) + .get('/static') + .set('cookie', mockCredentials.limitedUser.invalidCookie()) + .send() + .expect(200); + await request(app).get('/other').send().expect(200); + }); }); diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/createCredentialsBarrier.ts b/packages/backend-app-api/src/services/implementations/httpRouter/createCredentialsBarrier.ts index a512c5ac9e..a69fa5a804 100644 --- a/packages/backend-app-api/src/services/implementations/httpRouter/createCredentialsBarrier.ts +++ b/packages/backend-app-api/src/services/implementations/httpRouter/createCredentialsBarrier.ts @@ -76,7 +76,7 @@ export function createCredentialsBarrier(options: { httpAuth .credentials(req, { allow: ['user', 'service'], - allowedAuthMethods: allowsCookie ? ['token', 'cookie'] : ['token'], + allowLimitedAccess: allowsCookie, }) .then( () => next(), diff --git a/packages/backend-app-api/src/services/implementations/userInfo/userInfoServiceFactory.ts b/packages/backend-app-api/src/services/implementations/userInfo/userInfoServiceFactory.ts index a74b8b7002..7d3a2af7b5 100644 --- a/packages/backend-app-api/src/services/implementations/userInfo/userInfoServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/userInfo/userInfoServiceFactory.ts @@ -43,8 +43,11 @@ export class DefaultUserInfoService implements UserInfoService { if (typeof userEntityRef !== 'string') { throw new Error('User entity ref must be a string'); } - if (!Array.isArray(ownershipEntityRefs)) { - throw new Error('Ownership entity refs must be an array'); + if ( + !Array.isArray(ownershipEntityRefs) || + ownershipEntityRefs.some(ref => typeof ref !== 'string') + ) { + throw new Error('Ownership entity refs must be an array of strings'); } return { userEntityRef, ownershipEntityRefs }; diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index 729bd13779..cc5714772e 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/backend-common +## 0.21.3-next.0 + +### Patch Changes + +- 7422430: Resolve the `basePath` before constructing the target path +- 999224f: Bump dependency `minimatch` to v9 +- e0b997c: Fix issue where `resolveSafeChildPath` path would incorrectly resolve when operating on a symlink +- 9802004: Added the `UserInfoApi` as both an optional input and as an output for `createLegacyAuthAdapters` +- 2af5354: Bump dependency `jose` to v5 +- ff40ada: Updated dependency `mysql2` to `^3.0.0`. +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- 568881f: Updated dependency `yauzl` to `^3.0.0`. +- 4a3d434: Added a `createLegacyAuthAdapters` function that can be used as a compatibility adapter for backend plugins who want to start using the new [`auth`](https://backstage.io/docs/backend-system/core-services/auth/) and [`httpAuth`](https://backstage.io/docs/backend-system/core-services/http-auth) services that were created as part of [BEP-0003](https://github.com/backstage/backstage/tree/master/beps/0003-auth-architecture-evolution). + + See the [Auth Service Migration tutorial](https://backstage.io/docs/tutorials/auth-service-migration) for more information on the usage of this adapter. + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/backend-app-api@0.6.0-next.0 + - @backstage/config-loader@1.6.3-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/integration-aws-node@0.1.10-next.0 + - @backstage/backend-dev-utils@0.1.4 + - @backstage/cli-common@0.1.13 + - @backstage/types@1.1.1 + ## 0.21.0 ### Minor Changes diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index 1940a79b78..55cb3b34dc 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -67,6 +67,7 @@ import { ServiceRef } from '@backstage/backend-plugin-api'; import { TokenManagerService as TokenManager } from '@backstage/backend-plugin-api'; import { TransportStreamOptions } from 'winston-transport'; import { UrlReaderService as UrlReader } from '@backstage/backend-plugin-api'; +import { UserInfoService } from '@backstage/backend-plugin-api'; import { V1PodTemplateSpec } from '@kubernetes/client-node'; import * as winston from 'winston'; import { Writable } from 'stream'; @@ -239,30 +240,32 @@ export function createLegacyAuthAdapters< TOptions extends { auth?: AuthService; httpAuth?: HttpAuthService; + userInfo?: UserInfoService; identity?: IdentityService; tokenManager?: TokenManager; discovery: PluginEndpointDiscovery; }, - TAdapters = TOptions extends { + TAdapters = (TOptions extends { auth?: AuthService; } - ? TOptions extends { - httpAuth?: HttpAuthService; + ? { + auth: AuthService; } + : {}) & + (TOptions extends { + httpAuth?: HttpAuthService; + } ? { - auth: AuthService; httpAuth: HttpAuthService; } - : { - auth: AuthService; + : {}) & + (TOptions extends { + userInfo?: UserInfoService; + } + ? { + userInfo: UserInfoService; } - : TOptions extends { - httpAuth?: HttpAuthService; - } - ? { - httpAuth: HttpAuthService; - } - : 'error: at least one of auth and/or httpAuth must be provided', + : {}), >(options: TOptions): TAdapters; // @public diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index f60502ecd1..26b00e1875 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.21.0", + "version": "0.21.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-common/src/auth/createLegacyAuthAdapters.test.ts b/packages/backend-common/src/auth/createLegacyAuthAdapters.test.ts index 7e1f1be858..354b4a57dc 100644 --- a/packages/backend-common/src/auth/createLegacyAuthAdapters.test.ts +++ b/packages/backend-common/src/auth/createLegacyAuthAdapters.test.ts @@ -13,8 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { mockServices } from '@backstage/backend-test-utils'; import { createLegacyAuthAdapters } from './createLegacyAuthAdapters'; +import { Request } from 'express'; describe('createLegacyAuthAdapters', () => { it('should pass through auth if only auth is provided', () => { @@ -56,7 +58,22 @@ describe('createLegacyAuthAdapters', () => { expect(ret.httpAuth).toBe(httpAuth); }); - it('should adapt both auth and httpAuth if neither are provided', () => { + it('should pass through userInfo if it is provided', () => { + const auth = {}; + const userInfo = {}; + const ret = createLegacyAuthAdapters({ + auth: auth as any, + userInfo: userInfo as any, + tokenManager: mockServices.tokenManager(), + discovery: {} as any, + identity: mockServices.identity(), + }); + + expect(ret.auth).toBe(auth); + expect(ret.userInfo).toBe(userInfo); + }); + + it('should adapt all services if none are provided', () => { const ret = createLegacyAuthAdapters({ auth: undefined, httpAuth: undefined, @@ -68,6 +85,57 @@ describe('createLegacyAuthAdapters', () => { expect(ret).toEqual({ auth: expect.any(Object), httpAuth: expect.any(Object), + userInfo: expect.any(Object), }); }); + + it('should forward tokens if no token manager is provided', async () => { + const { auth, httpAuth } = createLegacyAuthAdapters({ + auth: undefined, + httpAuth: undefined, + discovery: {} as any, + identity: mockServices.identity(), + }); + + const credentials = await httpAuth.credentials({ + headers: { + authorization: 'Bearer my-token', + }, + } as Request); + + await expect( + auth.getPluginRequestToken({ + onBehalfOf: credentials, + targetPluginId: 'test', + }), + ).resolves.toEqual({ token: 'my-token' }); + }); + + it('should issue a new token if a token manager is provided', async () => { + const { auth, httpAuth } = createLegacyAuthAdapters({ + auth: undefined, + httpAuth: undefined, + tokenManager: { + ...mockServices.tokenManager(), + async getToken() { + return { token: 'new-token' }; + }, + }, + discovery: {} as any, + identity: mockServices.identity(), + }); + + const credentials = await httpAuth.credentials({ + headers: { + authorization: 'Bearer mock-token', + }, + } as Request); + + await expect( + auth.getPluginRequestToken({ + onBehalfOf: credentials, + targetPluginId: 'test', + }), + ).resolves.toEqual({ token: 'new-token' }); + }); }); diff --git a/packages/backend-common/src/auth/createLegacyAuthAdapters.ts b/packages/backend-common/src/auth/createLegacyAuthAdapters.ts index 98d21ba559..64dcc81bc6 100644 --- a/packages/backend-common/src/auth/createLegacyAuthAdapters.ts +++ b/packages/backend-common/src/auth/createLegacyAuthAdapters.ts @@ -17,14 +17,17 @@ import { AuthService, BackstageCredentials, + BackstageNonePrincipal, BackstagePrincipalTypes, BackstageServicePrincipal, + BackstageUserInfo, BackstageUserPrincipal, HttpAuthService, IdentityService, TokenManagerService, + UserInfoService, } from '@backstage/backend-plugin-api'; -import { ServerTokenManager, TokenManager } from '../tokens'; +import { TokenManager } from '../tokens'; import { AuthenticationError, NotAllowedError } from '@backstage/errors'; import type { Request, Response } from 'express'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports @@ -45,7 +48,7 @@ import { PluginEndpointDiscovery } from '../discovery'; class AuthCompat implements AuthService { constructor( private readonly identity: IdentityService, - private readonly tokenManager: TokenManagerService, + private readonly tokenManager?: TokenManagerService, ) {} isPrincipal( @@ -63,6 +66,12 @@ class AuthCompat implements AuthService { return true; } + async getNoneCredentials(): Promise< + BackstageCredentials + > { + return createCredentialsWithNonePrincipal(); + } + async getOwnServiceCredentials(): Promise< BackstageCredentials > { @@ -70,9 +79,12 @@ class AuthCompat implements AuthService { } async authenticate(token: string): Promise { - const { aud } = decodeJwt(token); + // Defensively check whether it seems token-like first, just to support + // custom TokenManager implementations that don't emit JWTs specifically. + const payload = + token.split('.').length === 3 ? decodeJwt(token) : undefined; - if (aud === 'backstage') { + if (payload?.aud === 'backstage') { // User Backstage token const identity = await this.identity.getIdentity({ request: { @@ -87,12 +99,16 @@ class AuthCompat implements AuthService { return createCredentialsWithUserPrincipal( identity.identity.userEntityRef, token, + this.#getJwtExpiration(token), ); } - await this.tokenManager.authenticate(token); + await this.tokenManager?.authenticate(token); - return createCredentialsWithServicePrincipal('external:backstage-plugin'); + return createCredentialsWithServicePrincipal( + 'external:backstage-plugin', + token, + ); } async getPluginRequestToken(options: { @@ -104,8 +120,12 @@ class AuthCompat implements AuthService { switch (type) { // TODO: Check whether the principal is ourselves - case 'service': - return this.tokenManager.getToken(); + case 'service': { + if (this.tokenManager) { + return this.tokenManager.getToken(); + } + return { token: internalForward.token ?? '' }; + } case 'user': if (!internalForward.token) { throw new Error('User credentials is unexpectedly missing token'); @@ -121,6 +141,30 @@ class AuthCompat implements AuthService { ); } } + + async getLimitedUserToken( + credentials: BackstageCredentials, + ): Promise<{ token: string; expiresAt: Date }> { + const internalCredentials = toInternalBackstageCredentials(credentials); + + const { token } = internalCredentials; + + if (!token) { + throw new AuthenticationError( + 'User credentials is unexpectedly missing token', + ); + } + + return { token, expiresAt: this.#getJwtExpiration(token) }; + } + + #getJwtExpiration(token: string) { + const { exp } = decodeJwt(token); + if (!exp) { + throw new AuthenticationError('User token is missing expiration'); + } + return new Date(exp * 1000); + } } function getTokenFromRequest(req: Request) { @@ -144,22 +188,22 @@ type RequestWithCredentials = Request & { }; class HttpAuthCompat implements HttpAuthService { - constructor(private readonly auth: AuthService) {} + #auth: AuthService; + + constructor(auth: AuthService) { + this.#auth = auth; + } async #extractCredentialsFromRequest(req: Request) { const token = getTokenFromRequest(req); if (!token) { - return createCredentialsWithNonePrincipal(); + return this.#auth.getNoneCredentials(); } - const credentials = toInternalBackstageCredentials( - await this.auth.authenticate(token), - ); - - return credentials; + return this.#auth.authenticate(token); } - async #getCredentials(req: /* */ RequestWithCredentials) { + async #getCredentials(req: RequestWithCredentials) { return (req[credentialsSymbol] ??= this.#extractCredentialsFromRequest(req)); } @@ -168,39 +212,77 @@ class HttpAuthCompat implements HttpAuthService { req: Request, options?: { allow?: Array; - allowedAuthMethods?: Array<'token' | 'cookie'>; + allowLimitedAccess?: boolean; }, ): Promise> { - const credentials = toInternalBackstageCredentials( - await this.#getCredentials(req), + const credentials = await this.#getCredentials(req); + + const allowed = options?.allow; + if (!allowed) { + return credentials as any; + } + + if (this.#auth.isPrincipal(credentials, 'none')) { + if (allowed.includes('none' as TAllowed)) { + return credentials as any; + } + + throw new AuthenticationError('Missing credentials'); + } else if (this.#auth.isPrincipal(credentials, 'user')) { + if (allowed.includes('user' as TAllowed)) { + return credentials as any; + } + + throw new NotAllowedError( + `This endpoint does not allow 'user' credentials`, + ); + } else if (this.#auth.isPrincipal(credentials, 'service')) { + if (allowed.includes('service' as TAllowed)) { + return credentials as any; + } + + throw new NotAllowedError( + `This endpoint does not allow 'service' credentials`, + ); + } + + throw new NotAllowedError( + 'Unknown principal type, this should never happen', ); - - const allowedPrincipalTypes = options?.allow; - const allowedAuthMethods: Array<'token' | 'cookie' | 'none'> = - options?.allowedAuthMethods ?? ['token']; - - if ( - credentials.authMethod !== 'none' && - !allowedAuthMethods.includes(credentials.authMethod) - ) { - throw new NotAllowedError( - `This endpoint does not allow the '${credentials.authMethod}' auth method`, - ); - } - - if ( - allowedPrincipalTypes && - !allowedPrincipalTypes.includes(credentials.principal.type as TAllowed) - ) { - throw new NotAllowedError( - `This endpoint does not allow '${credentials.principal.type}' credentials`, - ); - } - - return credentials as any; } - async issueUserCookie(_res: Response): Promise {} + async issueUserCookie(_res: Response): Promise<{ expiresAt: Date }> { + return { expiresAt: new Date(Date.now() + 3600_000) }; + } +} + +export class UserInfoCompat implements UserInfoService { + async getUserInfo( + credentials: BackstageCredentials, + ): Promise { + const internalCredentials = toInternalBackstageCredentials(credentials); + if (internalCredentials.principal.type !== 'user') { + throw new Error('Only user credentials are supported'); + } + if (!internalCredentials.token) { + throw new Error('User credentials is unexpectedly missing token'); + } + const { sub: userEntityRef, ent: ownershipEntityRefs = [] } = decodeJwt( + internalCredentials.token, + ); + + if (typeof userEntityRef !== 'string') { + throw new Error('User entity ref must be a string'); + } + if ( + !Array.isArray(ownershipEntityRefs) || + ownershipEntityRefs.some(ref => typeof ref !== 'string') + ) { + throw new Error('Ownership entity refs must be an array of strings'); + } + + return { userEntityRef, ownershipEntityRefs }; + } } /** @@ -211,51 +293,60 @@ export function createLegacyAuthAdapters< TOptions extends { auth?: AuthService; httpAuth?: HttpAuthService; + userInfo?: UserInfoService; identity?: IdentityService; tokenManager?: TokenManager; discovery: PluginEndpointDiscovery; }, - TAdapters = TOptions extends { - auth?: AuthService; - } - ? TOptions extends { httpAuth?: HttpAuthService } - ? { auth: AuthService; httpAuth: HttpAuthService } - : { auth: AuthService } - : TOptions extends { httpAuth?: HttpAuthService } - ? { httpAuth: HttpAuthService } - : 'error: at least one of auth and/or httpAuth must be provided', + TAdapters = (TOptions extends { auth?: AuthService } + ? { auth: AuthService } + : {}) & + (TOptions extends { httpAuth?: HttpAuthService } + ? { httpAuth: HttpAuthService } + : {}) & + (TOptions extends { userInfo?: UserInfoService } + ? { userInfo: UserInfoService } + : {}), >(options: TOptions): TAdapters { - const { auth, httpAuth, discovery } = options; + const { + auth, + httpAuth, + userInfo = new UserInfoCompat(), + discovery, + } = options; if (auth && httpAuth) { return { auth, httpAuth, + userInfo, } as TAdapters; } if (auth) { return { auth, + userInfo, } as TAdapters; } if (httpAuth) { return { httpAuth, + userInfo, } as TAdapters; } const identity = options.identity ?? DefaultIdentityClient.create({ discovery }); - const tokenManager = options.tokenManager ?? ServerTokenManager.noop(); - const authImpl = new AuthCompat(identity, tokenManager); + const authImpl = new AuthCompat(identity, options.tokenManager); const httpAuthImpl = new HttpAuthCompat(authImpl); return { auth: authImpl, httpAuth: httpAuthImpl, + userInfo, } as TAdapters; } diff --git a/packages/backend-defaults/CHANGELOG.md b/packages/backend-defaults/CHANGELOG.md index 964410d019..c6ce10a1bb 100644 --- a/packages/backend-defaults/CHANGELOG.md +++ b/packages/backend-defaults/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/backend-defaults +## 0.2.13-next.0 + +### Patch Changes + +- 7cbb760: Added support for the new auth services, which are now installed by default. See the [migration guide](https://backstage.io/docs/tutorials/auth-service-migration) for details. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-app-api@0.6.0-next.0 + ## 0.2.10 ### Patch Changes diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index 05de926b61..da93e5e5a8 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.2.10", + "version": "0.2.13-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-dynamic-feature-service/CHANGELOG.md b/packages/backend-dynamic-feature-service/CHANGELOG.md index bd924a3b39..783fd68c17 100644 --- a/packages/backend-dynamic-feature-service/CHANGELOG.md +++ b/packages/backend-dynamic-feature-service/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/backend-dynamic-feature-service +## 0.2.3-next.0 + +### Patch Changes + +- 5247909: Add `events: EventsService` to `LegacyPluginEnvironment`. +- Updated dependencies + - @backstage/plugin-events-backend@0.3.0-next.0 + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/backend-app-api@0.6.0-next.0 + - @backstage/plugin-catalog-backend@1.18.0-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/cli-node@0.2.4-next.0 + - @backstage/config-loader@1.6.3-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-app-node@0.1.13-next.0 + - @backstage/cli-common@0.1.13 + - @backstage/types@1.1.1 + ## 0.2.0 ### Minor Changes diff --git a/packages/backend-dynamic-feature-service/package.json b/packages/backend-dynamic-feature-service/package.json index 5adbd76afa..e47da0cb05 100644 --- a/packages/backend-dynamic-feature-service/package.json +++ b/packages/backend-dynamic-feature-service/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-dynamic-feature-service", "description": "Backstage dynamic feature service", - "version": "0.2.0", + "version": "0.2.3-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 58625674b7..658f7b6b38 100644 --- a/packages/backend-next/CHANGELOG.md +++ b/packages/backend-next/CHANGELOG.md @@ -1,5 +1,53 @@ # example-backend-next +## 0.0.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-linguist-backend@0.5.10-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/plugin-lighthouse-backend@0.4.5-next.0 + - @backstage/plugin-auth-backend-module-guest-provider@0.1.0-next.0 + - @backstage/plugin-playlist-backend@0.3.17-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-entity-feedback-backend@0.2.10-next.0 + - @backstage/plugin-notifications-backend@0.1.0-next.0 + - @backstage/plugin-catalog-backend@1.18.0-next.0 + - @backstage/plugin-auth-backend@0.22.0-next.0 + - @backstage/plugin-jenkins-backend@0.4.0-next.0 + - @backstage/plugin-azure-devops-backend@0.6.0-next.0 + - @backstage/plugin-scaffolder-backend-module-github@0.2.3-next.0 + - @backstage/plugin-scaffolder-backend@1.22.0-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.17-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.17-next.0 + - @backstage/plugin-search-backend-module-explore@0.1.17-next.0 + - @backstage/backend-defaults@0.2.13-next.0 + - @backstage/plugin-kubernetes-backend@0.16.0-next.0 + - @backstage/plugin-adr-backend@0.4.10-next.0 + - @backstage/plugin-proxy-backend@0.4.11-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/plugin-signals-backend@0.0.4-next.0 + - @backstage/plugin-search-backend@1.5.3-next.0 + - @backstage/plugin-devtools-backend@0.3.0-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.1.6-next.0 + - @backstage/plugin-badges-backend@0.3.10-next.0 + - @backstage/plugin-permission-backend@0.5.36-next.0 + - @backstage/plugin-app-backend@0.3.61-next.0 + - @backstage/plugin-auth-backend-module-github-provider@0.1.10-next.0 + - @backstage/plugin-catalog-backend-module-openapi@0.1.30-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.10-next.0 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.10-next.0 + - @backstage/plugin-sonarqube-backend@0.2.15-next.0 + - @backstage/plugin-techdocs-backend@1.9.6-next.0 + - @backstage/plugin-nomad-backend@0.1.15-next.0 + - @backstage/plugin-todo-backend@0.3.11-next.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.10-next.0 + - @backstage/catalog-model@1.4.5-next.0 + ## 0.0.20 ### Patch Changes diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index 74016539b0..610a46ebf6 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -1,6 +1,6 @@ { "name": "example-backend-next", - "version": "0.0.20", + "version": "0.0.21-next.0", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,6 +33,7 @@ "@backstage/plugin-app-backend": "workspace:^", "@backstage/plugin-auth-backend": "workspace:^", "@backstage/plugin-auth-backend-module-github-provider": "workspace:^", + "@backstage/plugin-auth-backend-module-guest-provider": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "@backstage/plugin-azure-devops-backend": "workspace:^", "@backstage/plugin-badges-backend": "workspace:^", @@ -56,6 +57,7 @@ "@backstage/plugin-playlist-backend": "workspace:^", "@backstage/plugin-proxy-backend": "workspace:^", "@backstage/plugin-scaffolder-backend": "workspace:^", + "@backstage/plugin-scaffolder-backend-module-github": "workspace:^", "@backstage/plugin-search-backend": "workspace:^", "@backstage/plugin-search-backend-module-catalog": "workspace:^", "@backstage/plugin-search-backend-module-explore": "workspace:^", diff --git a/packages/backend-next/src/index.ts b/packages/backend-next/src/index.ts index e4dd127208..4965462b2c 100644 --- a/packages/backend-next/src/index.ts +++ b/packages/backend-next/src/index.ts @@ -20,6 +20,7 @@ const backend = createBackend(); backend.add(import('@backstage/plugin-auth-backend')); backend.add(import('./authModuleGithubProvider')); +backend.add(import('@backstage/plugin-auth-backend-module-guest-provider')); backend.add(import('@backstage/plugin-adr-backend')); backend.add(import('@backstage/plugin-app-backend/alpha')); @@ -44,6 +45,7 @@ backend.add( backend.add(import('@backstage/plugin-permission-backend/alpha')); backend.add(import('@backstage/plugin-proxy-backend/alpha')); backend.add(import('@backstage/plugin-scaffolder-backend/alpha')); +backend.add(import('@backstage/plugin-scaffolder-backend-module-github')); backend.add(import('@backstage/plugin-search-backend-module-catalog/alpha')); backend.add(import('@backstage/plugin-search-backend-module-explore/alpha')); backend.add(import('@backstage/plugin-search-backend-module-techdocs/alpha')); diff --git a/packages/backend-openapi-utils/CHANGELOG.md b/packages/backend-openapi-utils/CHANGELOG.md index 77c2426beb..660eec4f97 100644 --- a/packages/backend-openapi-utils/CHANGELOG.md +++ b/packages/backend-openapi-utils/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/backend-openapi-utils +## 0.1.6-next.0 + +### Patch Changes + +- 85ec23e: Updated dependency `json-schema-to-ts` to `^3.0.0`. +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + ## 0.1.3 ### Patch Changes diff --git a/packages/backend-openapi-utils/package.json b/packages/backend-openapi-utils/package.json index fbb670149f..284216f78f 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.1.3", + "version": "0.1.6-next.0", "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 c927ae0803..416bc7e2d2 100644 --- a/packages/backend-plugin-api/CHANGELOG.md +++ b/packages/backend-plugin-api/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/backend-plugin-api +## 0.6.13-next.0 + +### Patch Changes + +- 4a3d434: Added the new [`auth`](https://backstage.io/docs/backend-system/core-services/auth/), [`httpAuth`](https://backstage.io/docs/backend-system/core-services/http-auth), and [`userInfo`](https://backstage.io/docs/backend-system/core-services/user-info) services that were created as part of [BEP-0003](https://github.com/backstage/backstage/tree/master/beps/0003-auth-architecture-evolution) to the `coreServices`. + + At the same time, the [`httpRouter`](https://backstage.io/docs/backend-system/core-services/http-router) service gained a new `addAuthPolicy` method that lets your plugin declare exemptions to the default auth policy - for example if you want to allow unauthenticated or cookie-based access to some subset of your feature routes. + + If you have migrated to the new backend system, please see the [Auth Service Migration tutorial](https://backstage.io/docs/tutorials/auth-service-migration) for more information on how to move toward using these services. + +- 0502d82: Updated the `PermissionsService` methods to accept `BackstageCredentials` through options. +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + ## 0.6.10 ### Patch Changes diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index cb44ba158d..73c1d15cd1 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -24,7 +24,21 @@ import { Response as Response_2 } from 'express'; // @public (undocumented) export interface AuthService { // (undocumented) - authenticate(token: string): Promise; + authenticate( + token: string, + options?: { + allowLimitedAccess?: boolean; + }, + ): Promise; + // (undocumented) + getLimitedUserToken( + credentials: BackstageCredentials, + ): Promise<{ + token: string; + expiresAt: Date; + }>; + // (undocumented) + getNoneCredentials(): Promise>; // (undocumented) getOwnServiceCredentials(): Promise< BackstageCredentials @@ -107,6 +121,7 @@ export interface BackendPluginRegistrationPoints { // @public (undocumented) export type BackstageCredentials = { $$type: '@backstage/BackstageCredentials'; + expiresAt?: Date; principal: TPrincipal; }; @@ -299,11 +314,18 @@ export interface HttpAuthService { req: Request_2, options?: { allow?: Array; - allowedAuthMethods?: Array<'token' | 'cookie'>; + allowLimitedAccess?: boolean; }, ): Promise>; // (undocumented) - issueUserCookie(res: Response_2): Promise; + issueUserCookie( + res: Response_2, + options?: { + credentials?: BackstageCredentials; + }, + ): Promise<{ + expiresAt: Date; + }>; } // @public (undocumented) diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index ae0037321b..4dd6fd3fcd 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.6.10", + "version": "0.6.13-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-plugin-api/src/services/definitions/AuthService.ts b/packages/backend-plugin-api/src/services/definitions/AuthService.ts index eab0a7fac7..2bcdc975a0 100644 --- a/packages/backend-plugin-api/src/services/definitions/AuthService.ts +++ b/packages/backend-plugin-api/src/services/definitions/AuthService.ts @@ -46,6 +46,8 @@ export type BackstageServicePrincipal = { export type BackstageCredentials = { $$type: '@backstage/BackstageCredentials'; + expiresAt?: Date; + principal: TPrincipal; }; @@ -63,13 +65,20 @@ export type BackstagePrincipalTypes = { * @public */ export interface AuthService { - authenticate(token: string): Promise; + authenticate( + token: string, + options?: { + allowLimitedAccess?: boolean; + }, + ): Promise; isPrincipal( credentials: BackstageCredentials, type: TType, ): credentials is BackstageCredentials; + getNoneCredentials(): Promise>; + getOwnServiceCredentials(): Promise< BackstageCredentials >; @@ -78,4 +87,8 @@ export interface AuthService { onBehalfOf: BackstageCredentials; targetPluginId: string; }): Promise<{ token: string }>; + + getLimitedUserToken( + credentials: BackstageCredentials, + ): Promise<{ token: string; expiresAt: Date }>; } diff --git a/packages/backend-plugin-api/src/services/definitions/HttpAuthService.ts b/packages/backend-plugin-api/src/services/definitions/HttpAuthService.ts index 44696bd777..637109d1f0 100644 --- a/packages/backend-plugin-api/src/services/definitions/HttpAuthService.ts +++ b/packages/backend-plugin-api/src/services/definitions/HttpAuthService.ts @@ -15,7 +15,11 @@ */ import { Request, Response } from 'express'; -import { BackstageCredentials, BackstagePrincipalTypes } from './AuthService'; +import { + BackstageCredentials, + BackstagePrincipalTypes, + BackstageUserPrincipal, +} from './AuthService'; /** @public */ export interface HttpAuthService { @@ -23,9 +27,14 @@ export interface HttpAuthService { req: Request, options?: { allow?: Array; - allowedAuthMethods?: Array<'token' | 'cookie'>; + allowLimitedAccess?: boolean; }, ): Promise>; - issueUserCookie(res: Response): Promise; + issueUserCookie( + res: Response, + options?: { + credentials?: BackstageCredentials; + }, + ): Promise<{ expiresAt: Date }>; } diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md index 53b8f4acca..22d2ea900b 100644 --- a/packages/backend-tasks/CHANGELOG.md +++ b/packages/backend-tasks/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/backend-tasks +## 0.5.18-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + ## 0.5.15 ### Patch Changes diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index 9f6743fe37..510dbae55b 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.15", + "version": "0.5.18-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 61c1a98005..f1da33e64c 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/backend-test-utils +## 0.3.3-next.0 + +### Patch Changes + +- 4a3d434: Added support for the new [`auth`](https://backstage.io/docs/backend-system/core-services/auth/) and [`httpAuth`](https://backstage.io/docs/backend-system/core-services/http-auth) services that were created as part of [BEP-0003](https://github.com/backstage/backstage/tree/master/beps/0003-auth-architecture-evolution). These services will be present by default in test apps, and you can access mocked versions of their features under `mockServices.auth` and `mockServices.httpAuth` if you want to inspect or replace their behaviors. + + There is also a new `mockCredentials` that you can use for acquiring mocks of the various types of credentials that are used in the new system. + +- 9802004: Added `mockServices.userInfo`, which now also automatically is made available in test backends. +- fd61d39: Updated dependency `testcontainers` to `^10.0.0`. +- ff40ada: Updated dependency `mysql2` to `^3.0.0`. +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/backend-app-api@0.6.0-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + ## 0.3.0 ### Minor Changes diff --git a/packages/backend-test-utils/api-report.md b/packages/backend-test-utils/api-report.md index a9ebb402c4..ff3f50ef8c 100644 --- a/packages/backend-test-utils/api-report.md +++ b/packages/backend-test-utils/api-report.md @@ -12,6 +12,7 @@ import { BackendFeature } from '@backstage/backend-plugin-api'; import { BackstageCredentials } from '@backstage/backend-plugin-api'; import { BackstageNonePrincipal } from '@backstage/backend-plugin-api'; import { BackstageServicePrincipal } from '@backstage/backend-plugin-api'; +import { BackstageUserInfo } from '@backstage/backend-plugin-api'; import { BackstageUserPrincipal } from '@backstage/backend-plugin-api'; import { CacheService } from '@backstage/backend-plugin-api'; import { DatabaseService } from '@backstage/backend-plugin-api'; @@ -37,6 +38,7 @@ import { ServiceFactory } from '@backstage/backend-plugin-api'; import { ServiceRef } from '@backstage/backend-plugin-api'; import { TokenManagerService } from '@backstage/backend-plugin-api'; import { UrlReaderService } from '@backstage/backend-plugin-api'; +import { UserInfoService } from '@backstage/backend-plugin-api'; // @public export function createMockDirectory( @@ -48,6 +50,17 @@ export function isDockerDisabledForTests(): boolean; // @public (undocumented) export namespace mockCredentials { + export function limitedUser( + userEntityRef?: string, + ): BackstageCredentials; + export namespace limitedUser { + export function cookie(userEntityRef?: string): string; + // (undocumented) + export function invalidCookie(): string; + // (undocumented) + export function invalidToken(): string; + export function token(userEntityRef?: string): string; + } export function none(): BackstageCredentials; export namespace none { export function header(): string; @@ -316,6 +329,17 @@ export namespace mockServices { partialImpl?: Partial | undefined, ) => ServiceMock; } + export function userInfo( + customInfo?: Partial, + ): UserInfoService; + // (undocumented) + export namespace userInfo { + const factory: () => ServiceFactory; + const // (undocumented) + mock: ( + partialImpl?: Partial | undefined, + ) => ServiceMock; + } } // @public diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index e2fc9dd3e6..d537adfba2 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -1,16 +1,30 @@ { "name": "@backstage/backend-test-utils", + "version": "0.3.3-next.0", "description": "Test helpers library for Backstage backends", - "version": "0.3.0", - "main": "src/index.ts", - "types": "src/index.ts", + "backstage": { + "role": "node-library" + }, "publishConfig": { "access": "public" }, + "keywords": [ + "backstage", + "test" + ], + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/backend-test-utils" + }, + "license": "Apache-2.0", "exports": { ".": "./src/index.ts", "./package.json": "./package.json" }, + "main": "src/index.ts", + "types": "src/index.ts", "typesVersions": { "*": { "package.json": [ @@ -18,28 +32,17 @@ ] } }, - "backstage": { - "role": "node-library" - }, - "homepage": "https://backstage.io", - "repository": { - "type": "git", - "url": "https://github.com/backstage/backstage", - "directory": "packages/backend-test-utils" - }, - "keywords": [ - "backstage", - "test" + "files": [ + "dist" ], - "license": "Apache-2.0", "scripts": { "build": "backstage-cli package build", + "clean": "backstage-cli package clean", "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", - "start": "backstage-cli package start" + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-app-api": "workspace:^", @@ -50,6 +53,7 @@ "@backstage/plugin-auth-node": "workspace:^", "@backstage/types": "workspace:^", "better-sqlite3": "^9.0.0", + "cookie": "^0.6.0", "express": "^4.17.1", "fs-extra": "^11.0.0", "knex": "^3.0.0", @@ -60,15 +64,12 @@ "textextensions": "^5.16.0", "uuid": "^9.0.0" }, - "peerDependencies": { - "@types/jest": "*" - }, "devDependencies": { "@backstage/cli": "workspace:^", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, - "files": [ - "dist" - ] + "peerDependencies": { + "@types/jest": "*" + } } diff --git a/packages/backend-test-utils/src/next/services/MockAuthService.test.ts b/packages/backend-test-utils/src/next/services/MockAuthService.test.ts index dfb54b9762..8741220a68 100644 --- a/packages/backend-test-utils/src/next/services/MockAuthService.test.ts +++ b/packages/backend-test-utils/src/next/services/MockAuthService.test.ts @@ -53,6 +53,12 @@ describe('MockAuthService', () => { auth.authenticate(mockCredentials.user.token()), ).resolves.toEqual(mockCredentials.user()); + await expect( + auth.authenticate(mockCredentials.user.token(), { + allowLimitedAccess: true, + }), + ).resolves.toEqual(mockCredentials.user()); + await expect( auth.authenticate(mockCredentials.user.token()), ).resolves.toEqual(mockCredentials.user(DEFAULT_MOCK_USER_ENTITY_REF)); @@ -66,6 +72,44 @@ describe('MockAuthService', () => { ).rejects.toThrow('User token is invalid'); }); + it('should authenticate mock limited user tokens', async () => { + await expect( + auth.authenticate(mockCredentials.limitedUser.token()), + ).rejects.toThrow('Limited user token is not allowed'); + await expect( + auth.authenticate(mockCredentials.limitedUser.token(), {}), + ).rejects.toThrow('Limited user token is not allowed'); + await expect( + auth.authenticate(mockCredentials.limitedUser.token(), { + allowLimitedAccess: false, + }), + ).rejects.toThrow('Limited user token is not allowed'); + await expect( + auth.authenticate(mockCredentials.limitedUser.token(), { + allowLimitedAccess: true, + }), + ).resolves.toEqual(mockCredentials.user()); + + await expect( + auth.authenticate(mockCredentials.limitedUser.token(), { + allowLimitedAccess: true, + }), + ).resolves.toEqual(mockCredentials.user(DEFAULT_MOCK_USER_ENTITY_REF)); + + await expect( + auth.authenticate( + mockCredentials.limitedUser.token('user:default/other'), + { + allowLimitedAccess: true, + }, + ), + ).resolves.toEqual(mockCredentials.user('user:default/other')); + + await expect( + auth.authenticate(mockCredentials.limitedUser.invalidToken()), + ).rejects.toThrow('Limited user token is invalid'); + }); + it('should authenticate mock service tokens', async () => { await expect( auth.authenticate(mockCredentials.service.token()), @@ -113,6 +157,12 @@ describe('MockAuthService', () => { ).rejects.toThrow('Service token is invalid'); }); + it('should return none credentials', async () => { + await expect(auth.getNoneCredentials()).resolves.toEqual( + mockCredentials.none(), + ); + }); + it('should return own service credentials', async () => { await expect(auth.getOwnServiceCredentials()).resolves.toEqual( mockCredentials.service('plugin:test'), @@ -211,4 +261,32 @@ describe('MockAuthService', () => { `Refused to issue service token for credential type 'none'`, ); }); + + it('should issue limited user tokens', async () => { + await expect( + auth.getLimitedUserToken(mockCredentials.user()), + ).resolves.toEqual({ + token: mockCredentials.limitedUser.token(), + expiresAt: expect.any(Date), + }); + + await expect( + auth.getLimitedUserToken(mockCredentials.user('user:default/other')), + ).resolves.toEqual({ + token: mockCredentials.limitedUser.token('user:default/other'), + expiresAt: expect.any(Date), + }); + + await expect( + auth.getLimitedUserToken(mockCredentials.none() as any), + ).rejects.toThrow( + "Refused to issue limited user token for credential type 'none'", + ); + + await expect( + auth.getLimitedUserToken(mockCredentials.service() as any), + ).rejects.toThrow( + "Refused to issue limited user token for credential type 'service'", + ); + }); }); diff --git a/packages/backend-test-utils/src/next/services/MockAuthService.ts b/packages/backend-test-utils/src/next/services/MockAuthService.ts index 6a18711798..64dc92747a 100644 --- a/packages/backend-test-utils/src/next/services/MockAuthService.ts +++ b/packages/backend-test-utils/src/next/services/MockAuthService.ts @@ -27,9 +27,11 @@ import { mockCredentials, MOCK_USER_TOKEN, MOCK_USER_TOKEN_PREFIX, + MOCK_INVALID_USER_TOKEN, + MOCK_USER_LIMITED_TOKEN_PREFIX, + MOCK_INVALID_USER_LIMITED_TOKEN, MOCK_SERVICE_TOKEN, MOCK_SERVICE_TOKEN_PREFIX, - MOCK_INVALID_USER_TOKEN, MOCK_INVALID_SERVICE_TOKEN, UserTokenPayload, ServiceTokenPayload, @@ -48,7 +50,10 @@ export class MockAuthService implements AuthService { this.disableDefaultAuthPolicy = options.disableDefaultAuthPolicy; } - async authenticate(token: string): Promise { + async authenticate( + token: string, + options?: { allowLimitedAccess?: boolean }, + ): Promise { switch (token) { case MOCK_USER_TOKEN: return mockCredentials.user(); @@ -56,6 +61,8 @@ export class MockAuthService implements AuthService { return mockCredentials.service(); case MOCK_INVALID_USER_TOKEN: throw new AuthenticationError('User token is invalid'); + case MOCK_INVALID_USER_LIMITED_TOKEN: + throw new AuthenticationError('Limited user token is invalid'); case MOCK_INVALID_SERVICE_TOKEN: throw new AuthenticationError('Service token is invalid'); case '': @@ -72,6 +79,18 @@ export class MockAuthService implements AuthService { return mockCredentials.user(userEntityRef); } + if (token.startsWith(MOCK_USER_LIMITED_TOKEN_PREFIX)) { + if (!options?.allowLimitedAccess) { + throw new AuthenticationError('Limited user token is not allowed'); + } + + const { sub: userEntityRef }: UserTokenPayload = JSON.parse( + token.slice(MOCK_USER_LIMITED_TOKEN_PREFIX.length), + ); + + return mockCredentials.user(userEntityRef); + } + if (token.startsWith(MOCK_SERVICE_TOKEN_PREFIX)) { const { sub, target, obo }: ServiceTokenPayload = JSON.parse( token.slice(MOCK_SERVICE_TOKEN_PREFIX.length), @@ -92,6 +111,10 @@ export class MockAuthService implements AuthService { throw new AuthenticationError(`Unknown mock token '${token}'`); } + async getNoneCredentials() { + return mockCredentials.none(); + } + async getOwnServiceCredentials(): Promise< BackstageCredentials > { @@ -144,4 +167,21 @@ export class MockAuthService implements AuthService { }), }; } + + async getLimitedUserToken( + credentials: BackstageCredentials, + ): Promise<{ token: string; expiresAt: Date }> { + if (credentials.principal.type !== 'user') { + throw new AuthenticationError( + `Refused to issue limited user token for credential type '${credentials.principal.type}'`, + ); + } + + return { + token: mockCredentials.limitedUser.token( + credentials.principal.userEntityRef, + ), + expiresAt: new Date(Date.now() + 3600_000), + }; + } } diff --git a/packages/backend-test-utils/src/next/services/MockHttpAuthService.test.ts b/packages/backend-test-utils/src/next/services/MockHttpAuthService.test.ts index 922b3daaf4..b43f448b44 100644 --- a/packages/backend-test-utils/src/next/services/MockHttpAuthService.test.ts +++ b/packages/backend-test-utils/src/next/services/MockHttpAuthService.test.ts @@ -22,8 +22,11 @@ import { AuthenticationError } from '@backstage/errors'; describe('MockHttpAuthService', () => { const httpAuth = new MockHttpAuthService('test', mockCredentials.none()); - function makeAuthReq(header?: string) { - return { headers: { authorization: header } } as Request; + function makeAuthReq(authorization?: string) { + return { headers: { authorization } } as Request; + } + function makeCookieAuthReq(cookie?: string) { + return { headers: { cookie } } as Request; } it('should authenticate unauthenticated requests', async () => { @@ -68,6 +71,59 @@ describe('MockHttpAuthService', () => { ).resolves.toEqual(mockCredentials.user('user:default/other')); }); + it('should authenticate limited user requests', async () => { + await expect( + httpAuth.credentials( + makeCookieAuthReq(mockCredentials.limitedUser.cookie()), + ), + ).resolves.toEqual(mockCredentials.none()); + + await expect( + httpAuth.credentials( + makeCookieAuthReq(mockCredentials.limitedUser.cookie()), + { allowLimitedAccess: true }, + ), + ).resolves.toEqual(mockCredentials.user()); + + await expect( + httpAuth.credentials(makeAuthReq(mockCredentials.user.header()), { + allowLimitedAccess: true, + }), + ).resolves.toEqual(mockCredentials.user()); + + await expect( + httpAuth.credentials( + makeCookieAuthReq(mockCredentials.limitedUser.cookie()), + { + allow: ['user'], + }, + ), + ).rejects.toThrow('Missing credentials'); + + await expect( + httpAuth.credentials( + makeCookieAuthReq(mockCredentials.limitedUser.cookie()), + { + allow: ['none', 'service'], + allowLimitedAccess: true, + }, + ), + ).rejects.toThrow("This endpoint does not allow 'user' credentials"); + + await expect( + httpAuth.credentials( + makeAuthReq(`Bearer ${mockCredentials.limitedUser.token()}`), + { allowLimitedAccess: true }, + ), + ).resolves.toEqual(mockCredentials.user()); + + await expect( + httpAuth.credentials( + makeAuthReq(`Bearer ${mockCredentials.limitedUser.token()}`), + ), + ).rejects.toThrow('Limited user token is not allowed'); + }); + it('should authenticate service requests', async () => { await expect( httpAuth.credentials(makeAuthReq(mockCredentials.service.header())), @@ -161,9 +217,42 @@ describe('MockHttpAuthService', () => { ).rejects.toThrow('Service token is invalid'); }); - it('does not implement .issueUserCookie', async () => { - await expect(httpAuth.issueUserCookie({} as any)).rejects.toThrow( - 'Not implemented', + it('should issue user cookie from request credentials', async () => { + const setHeader = jest.fn(); + + await expect( + httpAuth.issueUserCookie({ + req: makeAuthReq(mockCredentials.user.header()), + setHeader, + } as any), + ).resolves.toEqual({ + expiresAt: expect.any(Date), + }); + + expect(setHeader).toHaveBeenCalledWith( + 'Set-Cookie', + mockCredentials.limitedUser.cookie(), + ); + }); + + it('should issue user cookie from explicit credentials', async () => { + const setHeader = jest.fn(); + + await expect( + httpAuth.issueUserCookie( + { + req: makeAuthReq(mockCredentials.user.header()), + setHeader, + } as any, + { credentials: mockCredentials.user('user:default/other') }, + ), + ).resolves.toEqual({ + expiresAt: expect.any(Date), + }); + + expect(setHeader).toHaveBeenCalledWith( + 'Set-Cookie', + mockCredentials.limitedUser.cookie('user:default/other'), ); }); }); diff --git a/packages/backend-test-utils/src/next/services/MockHttpAuthService.ts b/packages/backend-test-utils/src/next/services/MockHttpAuthService.ts index 9b133f996b..9a69620473 100644 --- a/packages/backend-test-utils/src/next/services/MockHttpAuthService.ts +++ b/packages/backend-test-utils/src/next/services/MockHttpAuthService.ts @@ -18,16 +18,18 @@ import { AuthService, BackstageCredentials, BackstagePrincipalTypes, + BackstageUserPrincipal, HttpAuthService, } from '@backstage/backend-plugin-api'; import { Request, Response } from 'express'; +import { parse as parseCookie } from 'cookie'; import { MockAuthService } from './MockAuthService'; +import { AuthenticationError, NotAllowedError } from '@backstage/errors'; import { - AuthenticationError, - NotAllowedError, - NotImplementedError, -} from '@backstage/errors'; -import { mockCredentials } from './mockCredentials'; + MOCK_NONE_TOKEN, + MOCK_AUTH_COOKIE, + mockCredentials, +} from './mockCredentials'; // TODO: support mock cookie auth? export class MockHttpAuthService implements HttpAuthService { @@ -42,33 +44,52 @@ export class MockHttpAuthService implements HttpAuthService { this.#defaultCredentials = defaultCredentials; } - async #getCredentials(req: Request) { + async #getCredentials(req: Request, allowLimitedAccess: boolean) { const header = req.headers.authorization; - - if (header === mockCredentials.none.header()) { - return mockCredentials.none(); - } - const token = typeof header === 'string' ? header.match(/^Bearer[ ]+(\S+)$/i)?.[1] : undefined; - if (!token) { - return this.#defaultCredentials; + if (token) { + if (token === MOCK_NONE_TOKEN) { + return this.#auth.getNoneCredentials(); + } + + return await this.#auth.authenticate(token, { + allowLimitedAccess, + }); } - return await this.#auth.authenticate(token); + if (allowLimitedAccess) { + const cookieHeader = req.headers.cookie; + + if (cookieHeader) { + const cookies = parseCookie(cookieHeader); + const cookie = cookies[MOCK_AUTH_COOKIE]; + + if (cookie) { + return await this.#auth.authenticate(cookie, { + allowLimitedAccess: true, + }); + } + } + } + + return this.#defaultCredentials; } async credentials( req: Request, options?: { allow?: Array; - allowedAuthMethods?: Array<'token' | 'cookie'>; + allowLimitedAccess?: boolean; }, ): Promise> { - const credentials = await this.#getCredentials(req); + const credentials = await this.#getCredentials( + req, + options?.allowLimitedAccess ?? false, + ); const allowedPrincipalTypes = options?.allow; if (!allowedPrincipalTypes) { @@ -80,7 +101,7 @@ export class MockHttpAuthService implements HttpAuthService { return credentials as any; } - throw new AuthenticationError(); + throw new AuthenticationError('Missing credentials'); } else if (this.#auth.isPrincipal(credentials, 'user')) { if (allowedPrincipalTypes.includes('user' as TAllowed)) { return credentials as any; @@ -104,7 +125,19 @@ export class MockHttpAuthService implements HttpAuthService { ); } - async issueUserCookie(_res: Response): Promise { - throw new NotImplementedError('Not implemented'); + async issueUserCookie( + res: Response, + options?: { credentials?: BackstageCredentials }, + ): Promise<{ expiresAt: Date }> { + const credentials = + options?.credentials ?? + (await this.credentials(res.req, { allow: ['user'] })); + + res.setHeader( + 'Set-Cookie', + mockCredentials.limitedUser.cookie(credentials.principal.userEntityRef), + ); + + return { expiresAt: new Date(Date.now() + 3600_000) }; } } diff --git a/packages/backend-test-utils/src/next/services/MockUserInfoService.test.ts b/packages/backend-test-utils/src/next/services/MockUserInfoService.test.ts new file mode 100644 index 0000000000..13c8a43213 --- /dev/null +++ b/packages/backend-test-utils/src/next/services/MockUserInfoService.test.ts @@ -0,0 +1,55 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { MockUserInfoService } from './MockUserInfoService'; +import { mockCredentials } from './mockCredentials'; + +describe('MockUserInfoService', () => { + it('works without constructor parameters', async () => { + const service = new MockUserInfoService(); + const user = mockCredentials.user(); + await expect(service.getUserInfo(user)).resolves.toEqual({ + userEntityRef: user.principal.userEntityRef, + ownershipEntityRefs: [user.principal.userEntityRef], + }); + }); + + it('works with custom constructor parameters', async () => { + const service = new MockUserInfoService({ + userEntityRef: 'user:default/not-the-mock-1', + ownershipEntityRefs: ['user:default/not-the-mock-2'], + }); + const user = mockCredentials.user(); + await expect(service.getUserInfo(user)).resolves.toEqual({ + userEntityRef: 'user:default/not-the-mock-1', + ownershipEntityRefs: ['user:default/not-the-mock-2'], + }); + }); + + it('rejects non-users', async () => { + const service = new MockUserInfoService(); + await expect( + service.getUserInfo(mockCredentials.none()), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"User info not available for principal type 'none'"`, + ); + await expect( + service.getUserInfo(mockCredentials.service()), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"User info not available for principal type 'service'"`, + ); + }); +}); diff --git a/packages/backend-test-utils/src/next/services/MockUserInfoService.ts b/packages/backend-test-utils/src/next/services/MockUserInfoService.ts new file mode 100644 index 0000000000..68c2a8acae --- /dev/null +++ b/packages/backend-test-utils/src/next/services/MockUserInfoService.ts @@ -0,0 +1,55 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BackstageCredentials, + BackstageNonePrincipal, + BackstageServicePrincipal, + BackstageUserInfo, + BackstageUserPrincipal, + UserInfoService, +} from '@backstage/backend-plugin-api'; +import { InputError } from '@backstage/errors'; + +/** @internal */ +export class MockUserInfoService implements UserInfoService { + private readonly customInfo: Partial; + + constructor(customInfo?: Partial) { + this.customInfo = customInfo ?? {}; + } + + async getUserInfo( + credentials: BackstageCredentials, + ): Promise { + const principal = credentials.principal as + | BackstageUserPrincipal + | BackstageServicePrincipal + | BackstageNonePrincipal; + + if (principal.type !== 'user') { + throw new InputError( + `User info not available for principal type '${principal.type}'`, + ); + } + + return { + userEntityRef: principal.userEntityRef, + ownershipEntityRefs: [principal.userEntityRef], + ...this.customInfo, + }; + } +} diff --git a/packages/backend-test-utils/src/next/services/mockCredentials.test.ts b/packages/backend-test-utils/src/next/services/mockCredentials.test.ts index 67cda92be8..ed0071d4b8 100644 --- a/packages/backend-test-utils/src/next/services/mockCredentials.test.ts +++ b/packages/backend-test-utils/src/next/services/mockCredentials.test.ts @@ -36,6 +36,18 @@ describe('mockCredentials', () => { }); }); + it('creates a mocked credentials object for a limited user principal', () => { + expect(mockCredentials.limitedUser()).toEqual({ + $$type: '@backstage/BackstageCredentials', + principal: { type: 'user', userEntityRef: 'user:default/mock' }, + }); + + expect(mockCredentials.limitedUser('user:default/other')).toEqual({ + $$type: '@backstage/BackstageCredentials', + principal: { type: 'user', userEntityRef: 'user:default/other' }, + }); + }); + it('creates a mocked credentials object for a service principal', () => { expect(mockCredentials.service()).toEqual({ $$type: '@backstage/BackstageCredentials', @@ -68,6 +80,22 @@ describe('mockCredentials', () => { ); }); + it('creates limited user tokens and headers', () => { + expect(mockCredentials.limitedUser.token('user:default/other')).toBe( + 'mock-limited-user-token:{"sub":"user:default/other"}', + ); + expect(mockCredentials.limitedUser.invalidToken()).toBe( + 'mock-invalid-limited-user-token', + ); + + expect(mockCredentials.limitedUser.cookie('user:default/other')).toBe( + 'backstage-auth=mock-limited-user-token:{"sub":"user:default/other"}', + ); + expect(mockCredentials.limitedUser.invalidCookie()).toBe( + 'backstage-auth=mock-invalid-limited-user-token', + ); + }); + it('creates service tokens and headers', () => { expect(mockCredentials.service.token()).toBe('mock-service-token'); expect( diff --git a/packages/backend-test-utils/src/next/services/mockCredentials.ts b/packages/backend-test-utils/src/next/services/mockCredentials.ts index 8dac9c1a4b..16d2381c73 100644 --- a/packages/backend-test-utils/src/next/services/mockCredentials.ts +++ b/packages/backend-test-utils/src/next/services/mockCredentials.ts @@ -24,10 +24,18 @@ import { export const DEFAULT_MOCK_USER_ENTITY_REF = 'user:default/mock'; export const DEFAULT_MOCK_SERVICE_SUBJECT = 'external:test-service'; +export const MOCK_AUTH_COOKIE = 'backstage-auth'; + export const MOCK_NONE_TOKEN = 'mock-none-token'; + export const MOCK_USER_TOKEN = 'mock-user-token'; export const MOCK_USER_TOKEN_PREFIX = 'mock-user-token:'; export const MOCK_INVALID_USER_TOKEN = 'mock-invalid-user-token'; + +export const MOCK_USER_LIMITED_TOKEN_PREFIX = 'mock-limited-user-token:'; +export const MOCK_INVALID_USER_LIMITED_TOKEN = + 'mock-invalid-limited-user-token'; + export const MOCK_SERVICE_TOKEN = 'mock-service-token'; export const MOCK_SERVICE_TOKEN_PREFIX = 'mock-service-token:'; export const MOCK_INVALID_SERVICE_TOKEN = 'mock-invalid-service-token'; @@ -143,6 +151,54 @@ export namespace mockCredentials { } } + /** + * Creates a mocked credentials object for a user principal with limited + * access. + * + * The default user entity reference is 'user:default/mock'. + */ + export function limitedUser( + userEntityRef: string = DEFAULT_MOCK_USER_ENTITY_REF, + ): BackstageCredentials { + return user(userEntityRef); + } + + /** + * Utilities related to limited user credentials. + */ + export namespace limitedUser { + /** + * Creates a mocked limited user token. If a payload is provided it will be + * encoded into the token and forwarded to the credentials object when + * authenticated by the mock auth service. + */ + export function token( + userEntityRef: string = DEFAULT_MOCK_USER_ENTITY_REF, + ): string { + validateUserEntityRef(userEntityRef); + return `${MOCK_USER_LIMITED_TOKEN_PREFIX}${JSON.stringify({ + sub: userEntityRef, + } satisfies UserTokenPayload)}`; + } + + /** + * Returns an authorization header with a mocked limited user token. If a + * payload is provided it will be encoded into the token and forwarded to + * the credentials object when authenticated by the mock auth service. + */ + export function cookie(userEntityRef?: string): string { + return `${MOCK_AUTH_COOKIE}=${token(userEntityRef)}`; + } + + export function invalidToken(): string { + return MOCK_INVALID_USER_LIMITED_TOKEN; + } + + export function invalidCookie(): string { + return `${MOCK_AUTH_COOKIE}=${invalidToken()}`; + } + } + /** * Creates a mocked credentials object for a service principal. * diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts index f72f229434..3ff8a4e017 100644 --- a/packages/backend-test-utils/src/next/services/mockServices.ts +++ b/packages/backend-test-utils/src/next/services/mockServices.ts @@ -27,6 +27,8 @@ import { DiscoveryService, HttpAuthService, BackstageCredentials, + BackstageUserInfo, + UserInfoService, } from '@backstage/backend-plugin-api'; import { cacheServiceFactory, @@ -49,6 +51,7 @@ import { MockRootLoggerService } from './MockRootLoggerService'; import { MockAuthService } from './MockAuthService'; import { MockHttpAuthService } from './MockHttpAuthService'; import { mockCredentials } from './mockCredentials'; +import { MockUserInfoService } from './MockUserInfoService'; /** @internal */ function simpleFactory< @@ -199,9 +202,11 @@ export namespace mockServices { }); export const mock = simpleMock(coreServices.auth, () => ({ authenticate: jest.fn(), + getNoneCredentials: jest.fn(), getOwnServiceCredentials: jest.fn(), isPrincipal: jest.fn() as any, getPluginRequestToken: jest.fn(), + getLimitedUserToken: jest.fn(), })); } @@ -272,6 +277,37 @@ export namespace mockServices { })); } + /** + * Creates a mock implementation of the `UserInfoService`. + * + * By default it extracts the user's entity ref from a user principal and + * returns that as the only ownership entity ref, but this can be overridden + * by passing in a custom set of user info. + */ + export function userInfo( + customInfo?: Partial, + ): UserInfoService { + return new MockUserInfoService(customInfo); + } + export namespace userInfo { + /** + * Creates a mock service factory for the `UserInfoService`. + * + * By default it extracts the user's entity ref from a user principal and + * returns that as the only ownership entity ref. + */ + export const factory = createServiceFactory({ + service: coreServices.userInfo, + deps: {}, + factory() { + return new MockUserInfoService(); + }, + }); + export const mock = simpleMock(coreServices.userInfo, () => ({ + getUserInfo: jest.fn(), + })); + } + // TODO(Rugvip): Not all core services have implementations available here yet. // some may need a bit more refactoring for it to be simpler to // re-implement functioning mock versions here. @@ -284,12 +320,14 @@ export namespace mockServices { withOptions: jest.fn(), })); } + export namespace database { export const factory = databaseServiceFactory; export const mock = simpleMock(coreServices.database, () => ({ getClient: jest.fn(), })); } + export namespace httpRouter { export const factory = httpRouterServiceFactory; export const mock = simpleMock(coreServices.httpRouter, () => ({ @@ -297,12 +335,14 @@ export namespace mockServices { addAuthPolicy: jest.fn(), })); } + export namespace rootHttpRouter { export const factory = rootHttpRouterServiceFactory; export const mock = simpleMock(coreServices.rootHttpRouter, () => ({ use: jest.fn(), })); } + export namespace lifecycle { export const factory = lifecycleServiceFactory; export const mock = simpleMock(coreServices.lifecycle, () => ({ @@ -310,6 +350,7 @@ export namespace mockServices { addStartupHook: jest.fn(), })); } + export namespace logger { export const factory = loggerServiceFactory; export const mock = simpleMock(coreServices.logger, () => ({ @@ -320,6 +361,7 @@ export namespace mockServices { warn: jest.fn(), })); } + export namespace permissions { export const factory = permissionsServiceFactory; export const mock = simpleMock(coreServices.permissions, () => ({ @@ -327,6 +369,7 @@ export namespace mockServices { authorizeConditional: jest.fn(), })); } + export namespace rootLifecycle { export const factory = rootLifecycleServiceFactory; export const mock = simpleMock(coreServices.rootLifecycle, () => ({ @@ -334,6 +377,7 @@ export namespace mockServices { addStartupHook: jest.fn(), })); } + export namespace scheduler { export const factory = schedulerServiceFactory; export const mock = simpleMock(coreServices.scheduler, () => ({ @@ -343,6 +387,7 @@ export namespace mockServices { triggerTask: jest.fn(), })); } + export namespace urlReader { export const factory = urlReaderServiceFactory; export const mock = simpleMock(coreServices.urlReader, () => ({ diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.ts index 72a2ed8edb..6b58ebc5ea 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.ts +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.ts @@ -80,6 +80,7 @@ export const defaultServiceFactories = [ mockServices.rootLogger.factory(), mockServices.scheduler.factory(), mockServices.tokenManager.factory(), + mockServices.userInfo.factory(), mockServices.urlReader.factory(), ]; diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index 68e6c7c803..4ebc76804b 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,65 @@ # example-backend +## 0.2.93-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-backend@0.3.0-next.0 + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/plugin-linguist-backend@0.5.10-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/plugin-lighthouse-backend@0.4.5-next.0 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.16-next.0 + - @backstage/plugin-search-backend-module-pg@0.5.22-next.0 + - @backstage/plugin-playlist-backend@0.3.17-next.0 + - @backstage/plugin-code-coverage-backend@0.2.27-next.0 + - @backstage/plugin-entity-feedback-backend@0.2.10-next.0 + - @backstage/plugin-catalog-backend@1.18.0-next.0 + - @backstage/plugin-auth-backend@0.22.0-next.0 + - @backstage/plugin-jenkins-backend@0.4.0-next.0 + - @backstage/plugin-azure-devops-backend@0.6.0-next.0 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.14-next.0 + - @backstage/plugin-scaffolder-backend-module-gitlab@0.2.16-next.0 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.30-next.0 + - @backstage/plugin-scaffolder-backend@1.22.0-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.17-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.17-next.0 + - @backstage/plugin-search-backend-module-explore@0.1.17-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/plugin-kubernetes-backend@0.16.0-next.0 + - @backstage/plugin-adr-backend@0.4.10-next.0 + - @backstage/plugin-proxy-backend@0.4.11-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/plugin-signals-backend@0.0.4-next.0 + - @backstage/plugin-signals-node@0.0.4-next.0 + - @backstage/plugin-tech-insights-backend@0.5.27-next.0 + - @backstage/plugin-search-backend@1.5.3-next.0 + - @backstage/plugin-devtools-backend@0.3.0-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/plugin-tech-insights-node@0.5.0-next.0 + - @backstage/plugin-badges-backend@0.3.10-next.0 + - @backstage/plugin-permission-backend@0.5.36-next.0 + - @backstage/plugin-app-backend@0.3.61-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.10-next.0 + - @backstage/plugin-explore-backend@0.0.23-next.0 + - @backstage/plugin-rollbar-backend@0.1.58-next.0 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.45-next.0 + - @backstage/plugin-techdocs-backend@1.9.6-next.0 + - @backstage/plugin-kafka-backend@0.3.11-next.0 + - @backstage/plugin-nomad-backend@0.1.15-next.0 + - @backstage/plugin-todo-backend@0.3.11-next.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.10-next.0 + - example-app@0.2.93-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/plugin-azure-sites-common@0.1.3-next.0 + ## 0.2.92 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index e6102b69cf..b66be07caf 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.92", + "version": "0.2.93-next.0", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", @@ -72,7 +72,6 @@ "@backstage/plugin-search-backend-module-pg": "workspace:^", "@backstage/plugin-search-backend-module-techdocs": "workspace:^", "@backstage/plugin-search-backend-node": "workspace:^", - "@backstage/plugin-search-common": "workspace:^", "@backstage/plugin-signals-backend": "workspace:^", "@backstage/plugin-signals-node": "workspace:^", "@backstage/plugin-tech-insights-backend": "workspace:^", diff --git a/packages/backend/src/plugins/devtools.ts b/packages/backend/src/plugins/devtools.ts index 8e1767ddb1..bfa29cd72e 100644 --- a/packages/backend/src/plugins/devtools.ts +++ b/packages/backend/src/plugins/devtools.ts @@ -25,5 +25,6 @@ export default async function createPlugin( logger: env.logger, config: env.config, permissions: env.permissions, + discovery: env.discovery, }); } diff --git a/packages/backend/src/plugins/kubernetes.ts b/packages/backend/src/plugins/kubernetes.ts index 3bc6648862..5581083879 100644 --- a/packages/backend/src/plugins/kubernetes.ts +++ b/packages/backend/src/plugins/kubernetes.ts @@ -28,6 +28,7 @@ export default async function createPlugin( config: env.config, catalogApi, permissions: env.permissions, + discovery: env.discovery, }).build(); return router; } diff --git a/packages/backend/src/plugins/search.ts b/packages/backend/src/plugins/search.ts index 7babfe7e1f..a5b976ec9d 100644 --- a/packages/backend/src/plugins/search.ts +++ b/packages/backend/src/plugins/search.ts @@ -23,9 +23,9 @@ import { ElasticSearchSearchEngine } from '@backstage/plugin-search-backend-modu import { PgSearchEngine } from '@backstage/plugin-search-backend-module-pg'; import { IndexBuilder, + SearchEngine, LunrSearchEngine, } from '@backstage/plugin-search-backend-node'; -import { SearchEngine } from '@backstage/plugin-search-common'; import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-search-backend-module-techdocs'; import { Router } from 'express'; import { PluginEnvironment } from '../types'; @@ -117,6 +117,7 @@ export default async function createPlugin( return await createRouter({ engine: indexBuilder.getSearchEngine(), types: indexBuilder.getDocumentTypes(), + discovery: env.discovery, permissions: env.permissions, config: env.config, logger: env.logger, diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index 5fb66ff4c0..f9606dc14d 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/catalog-client +## 1.6.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/catalog-model@1.4.5-next.0 + ## 1.6.0 ### Minor Changes diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index f2be0fecb1..927286f36c 100644 --- a/packages/catalog-client/package.json +++ b/packages/catalog-client/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/catalog-client", - "version": "1.6.0", + "version": "1.6.1-next.0", "description": "An isomorphic client for the catalog backend", "backstage": { "role": "common-library" diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md index 01b34ddf2a..752e1ad5a0 100644 --- a/packages/catalog-model/CHANGELOG.md +++ b/packages/catalog-model/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/catalog-model +## 1.4.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/types@1.1.1 + ## 1.4.4 ### Patch Changes diff --git a/packages/catalog-model/examples/acme/team-a-group.yaml b/packages/catalog-model/examples/acme/team-a-group.yaml index 7fe0e7b3f3..eb95c47093 100644 --- a/packages/catalog-model/examples/acme/team-a-group.yaml +++ b/packages/catalog-model/examples/acme/team-a-group.yaml @@ -57,3 +57,17 @@ spec: displayName: Guest User email: guest@example.com memberOf: [team-a] +--- +# This user is added as an example, to make it more easy for the "Guest" +# sign-in option to demonstrate some entities being owned. In a regular org, +# a guest user would probably not be registered like this. +apiVersion: backstage.io/v1alpha1 +kind: User +metadata: + name: guest + namespace: development +spec: + profile: + displayName: Guest User + email: guest@example.com + memberOf: [group:default/team-a] diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index ac076ba8d2..232a7d2194 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/catalog-model", - "version": "1.4.4", + "version": "1.4.5-next.0", "description": "Types and validators that help describe the model of a Backstage Catalog", "backstage": { "role": "common-library" diff --git a/packages/cli-node/CHANGELOG.md b/packages/cli-node/CHANGELOG.md index 571a1f412b..8aca4a4842 100644 --- a/packages/cli-node/CHANGELOG.md +++ b/packages/cli-node/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/cli-node +## 0.2.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/cli-common@0.1.13 + - @backstage/types@1.1.1 + ## 0.2.3 ### Patch Changes diff --git a/packages/cli-node/package.json b/packages/cli-node/package.json index ee0e94215f..7e0f4d38b5 100644 --- a/packages/cli-node/package.json +++ b/packages/cli-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli-node", - "version": "0.2.3", + "version": "0.2.4-next.0", "description": "Node.js library for Backstage CLIs", "backstage": { "role": "node-library" diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index b96f93db83..c6609b0249 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/cli +## 0.25.3-next.0 + +### Patch Changes + +- 999224f: Bump dependency `minimatch` to v9 +- f86e34c: Removed unused `replace-in-file` dependency +- f4404e5: Add .ico import support +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/eslint-plugin@0.1.6-next.0 + - @backstage/cli-node@0.2.4-next.0 + - @backstage/config-loader@1.6.3-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/cli-common@0.1.13 + - @backstage/release-manifests@0.0.11 + - @backstage/types@1.1.1 + ## 0.25.2 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 98f7b3bafb..f09bd7a516 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.25.2", + "version": "0.25.3-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md index ea2fcc2f61..f8403f664c 100644 --- a/packages/config-loader/CHANGELOG.md +++ b/packages/config-loader/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/config-loader +## 1.6.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/cli-common@0.1.13 + - @backstage/types@1.1.1 + ## 1.6.2 ### Patch Changes diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index fa549e039b..73ce9fc37c 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/config-loader", - "version": "1.6.2", + "version": "1.6.3-next.0", "description": "Config loading functionality used by Backstage backend, and CLI", "backstage": { "role": "node-library" diff --git a/packages/config/CHANGELOG.md b/packages/config/CHANGELOG.md index 1ba8b45805..675687dffc 100644 --- a/packages/config/CHANGELOG.md +++ b/packages/config/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/config +## 1.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/types@1.1.1 + ## 1.1.1 ### Patch Changes diff --git a/packages/config/package.json b/packages/config/package.json index 97ca8c0af6..ddfe2da633 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/config", - "version": "1.1.1", + "version": "1.1.2-next.0", "description": "Config API used by Backstage core, backend, and CLI", "backstage": { "role": "common-library" diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index ecc332d8eb..96d967f9a5 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/core-app-api +## 1.12.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + ## 1.12.0 ### Minor Changes diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index 8a939fc5b6..60919dc9cd 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.12.0", + "version": "1.12.1-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/core-compat-api/CHANGELOG.md b/packages/core-compat-api/CHANGELOG.md index 168e10d941..a21938e26f 100644 --- a/packages/core-compat-api/CHANGELOG.md +++ b/packages/core-compat-api/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/core-compat-api +## 0.2.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-app-api@1.12.1-next.0 + - @backstage/version-bridge@1.0.7 + ## 0.2.0 ### Minor Changes diff --git a/packages/core-compat-api/package.json b/packages/core-compat-api/package.json index ee70bc8089..cfec392d1f 100644 --- a/packages/core-compat-api/package.json +++ b/packages/core-compat-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/core-compat-api", - "version": "0.2.0", + "version": "0.2.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index 78af1c4a5b..5deaf2dcf4 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/core-components +## 0.14.1-next.0 + +### Patch Changes + +- ff33ee2: Removed hardcoded font-family on select input +- ff7e126: Support i18n for core components +- 7854120: Create a component abstraction to consume system icons. +- ce73c3b: Removed the inline color from select icon to allow it to be colored via a theme +- a8f7904: `SignInPage`'s `'guest'` provider now supports the `@backstage/plugin-auth-backend-module-guest-provider` package to generate tokens. It will continue to use the old frontend-only auth as a fallback. +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/theme@0.5.2-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/version-bridge@1.0.7 + ## 0.14.0 ### Minor Changes diff --git a/packages/core-components/api-report-alpha.md b/packages/core-components/api-report-alpha.md new file mode 100644 index 0000000000..f2b21f6d1e --- /dev/null +++ b/packages/core-components/api-report-alpha.md @@ -0,0 +1,59 @@ +## API Report File for "@backstage/core-components" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { TranslationRef } from '@backstage/core-plugin-api/alpha'; + +// @alpha (undocumented) +export const coreComponentsTranslationRef: TranslationRef< + 'core-components', + { + readonly 'link.openNewWindow': 'Opens in a new window'; + readonly 'table.filter.title': 'Filters'; + readonly 'table.filter.clearAll': 'Clear all'; + readonly 'signIn.title': 'Sign In'; + readonly 'signIn.loginFailed': 'Login failed'; + readonly 'signIn.customProvider.title': 'Custom User'; + readonly 'signIn.customProvider.subtitle': 'Enter your own User ID and credentials.\n This selection will not be stored.'; + readonly 'signIn.customProvider.userId': 'User ID'; + readonly 'signIn.customProvider.tokenInvalid': 'Token is not a valid OpenID Connect JWT Token'; + readonly 'signIn.customProvider.continue': 'Continue'; + readonly 'signIn.customProvider.idToken': 'ID Token (optional)'; + readonly 'signIn.guestProvider.title': 'Guest'; + readonly 'signIn.guestProvider.enter': 'Enter'; + readonly 'signIn.guestProvider.subtitle': 'Enter as a Guest User.\n You will not have a verified identity, meaning some features might be unavailable.'; + readonly skipToContent: 'Skip to content'; + readonly 'copyTextButton.tooltipText': 'Text copied to clipboard'; + readonly 'simpleStepper.finish': 'Finish'; + readonly 'simpleStepper.reset': 'Reset'; + readonly 'simpleStepper.next': 'Next'; + readonly 'simpleStepper.skip': 'Skip'; + readonly 'simpleStepper.back': 'Back'; + readonly 'errorPage.title': 'Looks like someone dropped the mic!'; + readonly 'errorPage.subtitle': 'ERROR {{status}}: {{statusMessage}}'; + readonly 'errorPage.goBack': 'Go back'; + readonly 'errorPage.showMoreDetails': 'Show more details'; + readonly 'errorPage.showLessDetails': 'Show less details'; + readonly 'emptyState.missingAnnotation.title': 'Missing Annotation'; + readonly 'emptyState.missingAnnotation.actionTitle': 'Add the annotation to your component YAML as shown in the highlighted example below:'; + readonly 'emptyState.missingAnnotation.readMore': 'Read more'; + readonly 'supportConfig.default.title': 'Support Not Configured'; + readonly 'supportConfig.default.linkTitle': 'Add `app.support` config key'; + readonly 'errorBoundary.title': 'Please contact {{slackChannel}} for help.'; + readonly 'oauthRequestDialog.title': 'Login Required'; + readonly 'oauthRequestDialog.authRedirectTitle': 'This will trigger a http redirect to OAuth Login.'; + readonly 'oauthRequestDialog.login': 'Log in'; + readonly 'oauthRequestDialog.rejectAll': 'Reject All'; + readonly 'supportButton.title': 'Support'; + readonly 'supportButton.close': 'Close'; + readonly 'alertDisplay.message_one': '({{ count }} older message)'; + readonly 'alertDisplay.message_other': '({{ count }} older messages)'; + readonly 'autoLogout.stillTherePrompt.title': 'Logging out due to inactivity'; + readonly 'autoLogout.stillTherePrompt.buttonText': "Yes! Don't log me out"; + readonly 'proxiedSignInPage.title': 'You do not appear to be signed in. Please try reloading the browser page.'; + } +>; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 73de44d5ed..bdd9a1dc4d 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.14.0", + "version": "0.14.1-next.0", "publishConfig": { "access": "public" }, @@ -22,11 +22,15 @@ "types": "src/index.ts", "exports": { ".": "./src/index.ts", + "./alpha": "./src/alpha.ts", "./testUtils": "./src/testUtils.ts", "./package.json": "./package.json" }, "typesVersions": { "*": { + "alpha": [ + "src/alpha.ts" + ], "testUtils": [ "src/testUtils.ts" ], diff --git a/packages/core-components/src/alpha.ts b/packages/core-components/src/alpha.ts new file mode 100644 index 0000000000..e1f7678bae --- /dev/null +++ b/packages/core-components/src/alpha.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ +export * from './translation'; diff --git a/packages/core-components/src/components/AlertDisplay/AlertDisplay.tsx b/packages/core-components/src/components/AlertDisplay/AlertDisplay.tsx index b1c8273749..0291b6861d 100644 --- a/packages/core-components/src/components/AlertDisplay/AlertDisplay.tsx +++ b/packages/core-components/src/components/AlertDisplay/AlertDisplay.tsx @@ -14,13 +14,14 @@ * limitations under the License. */ import { alertApiRef, AlertMessage, useApi } from '@backstage/core-plugin-api'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; import IconButton from '@material-ui/core/IconButton'; import Snackbar from '@material-ui/core/Snackbar'; import Typography from '@material-ui/core/Typography'; import CloseIcon from '@material-ui/icons/Close'; import { Alert } from '@material-ui/lab'; -import pluralize from 'pluralize'; import React, { useEffect, useState } from 'react'; +import { coreComponentsTranslationRef } from '../../translation'; /** * Properties for {@link AlertDisplay} @@ -63,6 +64,7 @@ export type AlertDisplayProps = { export function AlertDisplay(props: AlertDisplayProps) { const [messages, setMessages] = useState>([]); const alertApi = useApi(alertApiRef); + const { t } = useTranslationRef(coreComponentsTranslationRef); const { anchorOrigin = { vertical: 'top', horizontal: 'center' }, @@ -121,10 +123,11 @@ export function AlertDisplay(props: AlertDisplayProps) { {String(firstMessage.message)} {messages.length > 1 && ( - {` (${messages.length - 1} older ${pluralize( - 'message', - messages.length - 1, - )})`} + + {t('alertDisplay.message', { + count: messages.length - 1, + })} + )} diff --git a/packages/core-components/src/components/AutoLogout/Autologout.test.tsx b/packages/core-components/src/components/AutoLogout/Autologout.test.tsx index 0d414524a5..164ad716d2 100644 --- a/packages/core-components/src/components/AutoLogout/Autologout.test.tsx +++ b/packages/core-components/src/components/AutoLogout/Autologout.test.tsx @@ -18,16 +18,18 @@ import { createMocks } from 'react-idle-timer'; import { MessageChannel } from 'worker_threads'; import { ApiProvider } from '@backstage/core-app-api'; import { identityApiRef } from '@backstage/core-plugin-api'; -import { TestApiRegistry } from '@backstage/test-utils'; +import { TestApiRegistry, renderInTestApp } from '@backstage/test-utils'; import React from 'react'; import { AutoLogout } from './AutoLogout'; -import { cleanup, render } from '@testing-library/react'; +import { cleanup } from '@testing-library/react'; // Mock the signOut function of identityApiRef const mockSignOut = jest.fn(); -const mockIdentityApi = { signOut: mockSignOut }; - +const mockIdentityApi = { + signOut: mockSignOut, + getCredentials: jest.fn().mockReturnValue({ token: 'xxx' }), +}; const apis = TestApiRegistry.from([identityApiRef, mockIdentityApi]); describe('AutoLogout', () => { @@ -44,27 +46,29 @@ describe('AutoLogout', () => { }); it('should throw error if idleTimeoutMinutes is smaller than promptBeforeSeconds', async () => { - expect(() => - render( - - - , - ), - ).toThrow(); + await expect( + async () => + await renderInTestApp( + + + , + ), + ).rejects.toThrow(); }); it('should throw error if idleTimeoutMinutes is smaller than 30 seconds', async () => { - expect(() => - render( - - -
Test Child
-
, - ), - ).toThrow(); + await expect( + async () => + await renderInTestApp( + + +
Test Child
+
, + ), + ).rejects.toThrow(); }); }); diff --git a/packages/core-components/src/components/AutoLogout/StillTherePrompt.tsx b/packages/core-components/src/components/AutoLogout/StillTherePrompt.tsx index e0cfc8dd56..9496199fd9 100644 --- a/packages/core-components/src/components/AutoLogout/StillTherePrompt.tsx +++ b/packages/core-components/src/components/AutoLogout/StillTherePrompt.tsx @@ -22,6 +22,8 @@ import DialogContentText from '@material-ui/core/DialogContentText'; import DialogTitle from '@material-ui/core/DialogTitle'; import React, { useEffect } from 'react'; import { IIdleTimer } from 'react-idle-timer'; +import { coreComponentsTranslationRef } from '../../translation'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; export interface StillTherePromptProps { idleTimer: IIdleTimer; @@ -41,6 +43,7 @@ export const StillTherePrompt = (props: StillTherePromptProps) => { remainingTime, setRemainingTime, } = props; + const { t } = useTranslationRef(coreComponentsTranslationRef); useEffect(() => { const interval = setInterval(() => { @@ -65,7 +68,7 @@ export const StillTherePrompt = (props: StillTherePromptProps) => { return ( - Logging out due to inactivity + {t('autoLogout.stillTherePrompt.title')} You are about to be disconnected in{' '} @@ -82,7 +85,7 @@ export const StillTherePrompt = (props: StillTherePromptProps) => { variant="contained" size="small" > - Yes! Don't log me out + {t('autoLogout.stillTherePrompt.buttonText')} diff --git a/packages/core-components/src/components/CopyTextButton/CopyTextButton.tsx b/packages/core-components/src/components/CopyTextButton/CopyTextButton.tsx index bd900a931d..91b046354a 100644 --- a/packages/core-components/src/components/CopyTextButton/CopyTextButton.tsx +++ b/packages/core-components/src/components/CopyTextButton/CopyTextButton.tsx @@ -20,6 +20,8 @@ import Tooltip from '@material-ui/core/Tooltip'; import CopyIcon from '@material-ui/icons/FileCopy'; import React, { MouseEventHandler, useEffect, useState } from 'react'; import useCopyToClipboard from 'react-use/lib/useCopyToClipboard'; +import { coreComponentsTranslationRef } from '../../translation'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; /** * Properties for {@link CopyTextButton} @@ -78,10 +80,11 @@ export interface CopyTextButtonProps { * ``` */ export function CopyTextButton(props: CopyTextButtonProps) { + const { t } = useTranslationRef(coreComponentsTranslationRef); const { text, tooltipDelay = 1000, - tooltipText = 'Text copied to clipboard', + tooltipText = t('copyTextButton.tooltipText'), 'aria-label': ariaLabel = 'Copy text', } = props; const errorApi = useApi(errorApiRef); diff --git a/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx b/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx index 81b4714531..e185dff8a6 100644 --- a/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx +++ b/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx @@ -23,6 +23,8 @@ import React from 'react'; import { CodeSnippet } from '../CodeSnippet'; import { Link } from '../Link'; import { EmptyState } from './EmptyState'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { coreComponentsTranslationRef } from '../../translation'; const COMPONENT_YAML_TEMPLATE = `apiVersion: backstage.io/v1alpha1 kind: Component @@ -76,7 +78,7 @@ function generateComponentYaml(annotations: string[]) { return COMPONENT_YAML_TEMPLATE.replace(ANNOTATION_YAML, annotationYaml); } -function generateDescription(annotations: string[]) { +function useGenerateDescription(annotations: string[]) { const isSingular = annotations.length <= 1; return ( <> @@ -106,17 +108,17 @@ export function MissingAnnotationEmptyState(props: Props) { readMoreUrl || 'https://backstage.io/docs/features/software-catalog/well-known-annotations'; const classes = useStyles(); + const { t } = useTranslationRef(coreComponentsTranslationRef); return ( - Add the annotation to your component YAML as shown in the - highlighted example below: + {t('emptyState.missingAnnotation.actionTitle')} } diff --git a/packages/core-components/src/components/Link/Link.tsx b/packages/core-components/src/components/Link/Link.tsx index e957390da8..b426402ba9 100644 --- a/packages/core-components/src/components/Link/Link.tsx +++ b/packages/core-components/src/components/Link/Link.tsx @@ -14,6 +14,7 @@ * limitations under the License. */ import { configApiRef, useAnalytics, useApi } from '@backstage/core-plugin-api'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; // eslint-disable-next-line no-restricted-imports import MaterialLink, { LinkProps as MaterialLinkProps, @@ -29,6 +30,7 @@ import { LinkProps as RouterLinkProps, Route, } from 'react-router-dom'; +import { coreComponentsTranslationRef } from '../../translation'; export function isReactRouterBeta(): boolean { const [obj] = createRoutesFromChildren(} />); @@ -161,6 +163,7 @@ export const Link = React.forwardRef( ({ onClick, noTrack, ...props }, ref) => { const classes = useStyles(); const analytics = useAnalytics(); + const { t } = useTranslationRef(coreComponentsTranslationRef); // Adding the base path to URLs breaks react-router v6 stable, so we only // do it for beta. The react router version won't change at runtime so it is @@ -199,7 +202,7 @@ export const Link = React.forwardRef( > {props.children} - , Opens in a new window + {`, ${t('link.openNewWindow')}`} ) : ( diff --git a/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx b/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx index 782624362d..375ea66953 100644 --- a/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx +++ b/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx @@ -23,6 +23,8 @@ import Button from '@material-ui/core/Button'; import React, { useState } from 'react'; import { isError } from '@backstage/errors'; import { PendingOAuthRequest } from '@backstage/core-plugin-api'; +import { coreComponentsTranslationRef } from '../../translation'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; export type LoginRequestListItemClassKey = 'root'; @@ -44,6 +46,7 @@ type RowProps = { const LoginRequestListItem = ({ request, busy, setBusy }: RowProps) => { const classes = useItemStyles(); const [error, setError] = useState(); + const { t } = useTranslationRef(coreComponentsTranslationRef); const handleContinue = async () => { setBusy(true); @@ -68,7 +71,7 @@ const LoginRequestListItem = ({ request, busy, setBusy }: RowProps) => { secondary={error && {error}} /> ); diff --git a/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx b/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx index 7c17e74e4a..2257b776d9 100644 --- a/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx +++ b/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx @@ -30,6 +30,8 @@ import { oauthRequestApiRef, } from '@backstage/core-plugin-api'; import Typography from '@material-ui/core/Typography'; +import { coreComponentsTranslationRef } from '../../translation'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; export type OAuthRequestDialogClassKey = | 'dialog' @@ -63,6 +65,7 @@ export function OAuthRequestDialog(_props: {}) { const [busy, setBusy] = useState(false); const oauthRequestApi = useApi(oauthRequestApiRef); const configApi = useApi(configApiRef); + const { t } = useTranslationRef(coreComponentsTranslationRef); const authRedirect = configApi.getOptionalBoolean('enableExperimentalRedirectFlow') ?? false; @@ -94,12 +97,10 @@ export function OAuthRequestDialog(_props: {}) { variant="h1" variantMapping={{ h1: 'span' }} > - Login Required + {t('oauthRequestDialog.title')} {authRedirect ? ( - - This will trigger a http redirect to OAuth Login. - + {t('oauthRequestDialog.authRedirectTitle')} ) : null} @@ -118,7 +119,9 @@ export function OAuthRequestDialog(_props: {}) { - + ); diff --git a/packages/core-components/src/components/SimpleStepper/SimpleStepperFooter.tsx b/packages/core-components/src/components/SimpleStepper/SimpleStepperFooter.tsx index 224b66533a..8db3ac8d72 100644 --- a/packages/core-components/src/components/SimpleStepper/SimpleStepperFooter.tsx +++ b/packages/core-components/src/components/SimpleStepper/SimpleStepperFooter.tsx @@ -20,6 +20,8 @@ import React, { PropsWithChildren, ReactNode, useContext } from 'react'; import { VerticalStepperContext } from './SimpleStepper'; import { StepActions } from './types'; +import { coreComponentsTranslationRef } from '../../translation'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; export type SimpleStepperFooterClassKey = 'root'; @@ -55,9 +57,12 @@ interface BackBtnProps extends CommonBtnProps { disabled?: boolean; stepIndex: number; } -export const RestartBtn = ({ text, handleClick }: RestartBtnProps) => ( - -); +export const RestartBtn = ({ text, handleClick }: RestartBtnProps) => { + const { t } = useTranslationRef(coreComponentsTranslationRef); + return ( + + ); +}; const NextBtn = ({ text, @@ -65,39 +70,48 @@ const NextBtn = ({ disabled, last, stepIndex, -}: NextBtnProps) => ( - -); +}: NextBtnProps) => { + const { t } = useTranslationRef(coreComponentsTranslationRef); + return ( + + ); +}; -const SkipBtn = ({ text, handleClick, disabled, stepIndex }: SkipBtnProps) => ( - -); +const SkipBtn = ({ text, handleClick, disabled, stepIndex }: SkipBtnProps) => { + const { t } = useTranslationRef(coreComponentsTranslationRef); + return ( + + ); +}; -const BackBtn = ({ text, handleClick, disabled, stepIndex }: BackBtnProps) => ( - -); +const BackBtn = ({ text, handleClick, disabled, stepIndex }: BackBtnProps) => { + const { t } = useTranslationRef(coreComponentsTranslationRef); + return ( + + ); +}; export type SimpleStepperFooterProps = { actions?: StepActions; diff --git a/packages/core-components/src/components/SupportButton/SupportButton.tsx b/packages/core-components/src/components/SupportButton/SupportButton.tsx index 726500c77e..623eda3098 100644 --- a/packages/core-components/src/components/SupportButton/SupportButton.tsx +++ b/packages/core-components/src/components/SupportButton/SupportButton.tsx @@ -31,6 +31,8 @@ import React, { MouseEventHandler, useState } from 'react'; import { SupportItem, SupportItemLink, useSupportConfig } from '../../hooks'; import { HelpIcon } from '../../icons'; import { Link } from '../Link'; +import { coreComponentsTranslationRef } from '../../translation'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; type SupportButtonProps = { title?: string; @@ -85,6 +87,7 @@ const SupportListItem = ({ item }: { item: SupportItem }) => { }; export function SupportButton(props: SupportButtonProps) { + const { t } = useTranslationRef(coreComponentsTranslationRef); const { title, items, children } = props; const { items: configItems } = useSupportConfig(); @@ -125,7 +128,7 @@ export function SupportButton(props: SupportButtonProps) { onClick={onClickHandler} startIcon={} > - Support + {t('supportButton.title')} )} @@ -171,7 +174,7 @@ export function SupportButton(props: SupportButtonProps) { onClick={popoverCloseHandler} aria-label="Close" > - Close + {t('supportButton.close')} diff --git a/packages/core-components/src/components/Table/Filters.tsx b/packages/core-components/src/components/Table/Filters.tsx index 568b22b933..999676f4d9 100644 --- a/packages/core-components/src/components/Table/Filters.tsx +++ b/packages/core-components/src/components/Table/Filters.tsx @@ -21,6 +21,8 @@ import React, { useEffect, useState } from 'react'; import { Select } from '../Select'; import { SelectProps } from '../Select/Select'; +import { coreComponentsTranslationRef } from '../../translation'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; export type TableFiltersClassKey = 'root' | 'value' | 'heder' | 'filters'; @@ -76,6 +78,7 @@ export const Filters = (props: Props) => { const classes = useFilterStyles(); const { onChangeFilters } = props; + const { t } = useTranslationRef(coreComponentsTranslationRef); const [selectedFilters, setSelectedFilters] = useState({ ...props.selectedFilters, @@ -96,9 +99,9 @@ export const Filters = (props: Props) => { return ( - Filters + {t('table.filter.title')} diff --git a/packages/core-components/src/hooks/useSupportConfig.ts b/packages/core-components/src/hooks/useSupportConfig.ts index e80eb457a1..2b969d8b4d 100644 --- a/packages/core-components/src/hooks/useSupportConfig.ts +++ b/packages/core-components/src/hooks/useSupportConfig.ts @@ -15,6 +15,8 @@ */ import { useApiHolder, configApiRef } from '@backstage/core-plugin-api'; +import { coreComponentsTranslationRef } from '../translation'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; export type SupportItemLink = { url: string; @@ -32,30 +34,34 @@ export type SupportConfig = { items: SupportItem[]; }; -const DEFAULT_SUPPORT_CONFIG: SupportConfig = { - url: 'https://github.com/backstage/backstage/issues', - items: [ - { - title: 'Support Not Configured', - icon: 'warning', - links: [ - { - // TODO: Update to dedicated support page on backstage.io/docs - title: 'Add `app.support` config key', - url: 'https://github.com/backstage/backstage/blob/master/app-config.yaml', - }, - ], - }, - ], +const useDefaultSupportConfig = () => { + const { t } = useTranslationRef(coreComponentsTranslationRef); + return { + url: 'https://github.com/backstage/backstage/issues', + items: [ + { + title: t('supportConfig.default.title'), + icon: 'warning', + links: [ + { + // TODO: Update to dedicated support page on backstage.io/docs + title: t('supportConfig.default.linkTitle'), + url: 'https://github.com/backstage/backstage/blob/master/app-config.yaml', + }, + ], + }, + ], + }; }; export function useSupportConfig(): SupportConfig { const apiHolder = useApiHolder(); const config = apiHolder.get(configApiRef); const supportConfig = config?.getOptionalConfig('app.support'); + const defaultSupportConfig = useDefaultSupportConfig(); if (!supportConfig) { - return DEFAULT_SUPPORT_CONFIG; + return defaultSupportConfig; } return { diff --git a/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.tsx b/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.tsx index 0ecaedfc19..8f746882a1 100644 --- a/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.tsx +++ b/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.tsx @@ -18,6 +18,8 @@ import Typography from '@material-ui/core/Typography'; import React, { ComponentClass, Component, ErrorInfo } from 'react'; import { LinkButton } from '../../components/LinkButton'; import { ErrorPanel } from '../../components/ErrorPanel'; +import { coreComponentsTranslationRef } from '../../translation'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; type SlackChannel = { name: string; @@ -37,14 +39,21 @@ type State = { const SlackLink = (props: { slackChannel?: string | SlackChannel }) => { const { slackChannel } = props; + const { t } = useTranslationRef(coreComponentsTranslationRef); if (!slackChannel) { return null; } else if (typeof slackChannel === 'string') { - return Please contact {slackChannel} for help.; + return ( + {t('errorBoundary.title', { slackChannel })} + ); } else if (!slackChannel.href) { return ( - Please contact {slackChannel.name} for help. + + {t('errorBoundary.title', { + slackChannel: slackChannel.name, + })} + ); } diff --git a/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx b/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx index 131df3da3a..72c00ed6a9 100644 --- a/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx +++ b/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx @@ -23,6 +23,8 @@ import { Link } from '../../components/Link'; import { useSupportConfig } from '../../hooks'; import { MicDrop } from './MicDrop'; import { StackDetails } from './StackDetails'; +import { coreComponentsTranslationRef } from '../../translation'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; interface IErrorPageProps { status?: string; @@ -64,10 +66,17 @@ const useStyles = makeStyles( * */ export function ErrorPage(props: IErrorPageProps) { - const { status, statusMessage, additionalInfo, supportUrl, stack } = props; + const { + status = '', + statusMessage, + additionalInfo, + supportUrl, + stack, + } = props; const classes = useStyles(); const navigate = useNavigate(); const support = useSupportConfig(); + const { t } = useTranslationRef(coreComponentsTranslationRef); return ( @@ -77,17 +86,17 @@ export function ErrorPage(props: IErrorPageProps) { variant="body1" className={classes.subtitle} > - ERROR {status}: {statusMessage} + {t('errorPage.subtitle', { status, statusMessage })} {additionalInfo} - Looks like someone dropped the mic! + {t('errorPage.title')} navigate(-1)}> - Go back + {t('errorPage.goBack')} ... or please{' '} contact support if you diff --git a/packages/core-components/src/layout/ErrorPage/StackDetails.tsx b/packages/core-components/src/layout/ErrorPage/StackDetails.tsx index b46a937485..56fabfd5f8 100644 --- a/packages/core-components/src/layout/ErrorPage/StackDetails.tsx +++ b/packages/core-components/src/layout/ErrorPage/StackDetails.tsx @@ -19,6 +19,8 @@ import { useState } from 'react'; import { Link } from '../../components/Link'; import { CodeSnippet } from '../../components'; import { makeStyles } from '@material-ui/core/styles'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { coreComponentsTranslationRef } from '../../translation'; interface IStackDetailsProps { stack: string; @@ -46,6 +48,7 @@ const useStyles = makeStyles( export function StackDetails(props: IStackDetailsProps) { const { stack } = props; const classes = useStyles(); + const { t } = useTranslationRef(coreComponentsTranslationRef); const [detailsOpen, setDetailsOpen] = useState(false); @@ -53,7 +56,7 @@ export function StackDetails(props: IStackDetailsProps) { return ( setDetailsOpen(true)}> - Show more details + {t('errorPage.showMoreDetails')} ); @@ -63,7 +66,7 @@ export function StackDetails(props: IStackDetailsProps) { <> setDetailsOpen(false)}> - Show less details + {t('errorPage.showLessDetails')} { const discoveryApi = useApi(discoveryApiRef); + const { t } = useTranslationRef(coreComponentsTranslationRef); const [{ status, error }, { execute }] = useAsync(async () => { const identity = new ProxiedSignInIdentity({ @@ -79,12 +82,7 @@ export const ProxiedSignInPage = (props: ProxiedSignInPageProps) => { if (status === 'loading') { return ; } else if (error) { - return ( - - ); + return ; } return null; diff --git a/packages/core-components/src/layout/Sidebar/Bar.tsx b/packages/core-components/src/layout/Sidebar/Bar.tsx index 550c614522..c5aa9585bb 100644 --- a/packages/core-components/src/layout/Sidebar/Bar.tsx +++ b/packages/core-components/src/layout/Sidebar/Bar.tsx @@ -34,6 +34,8 @@ import { MobileSidebar } from './MobileSidebar'; import { useContent } from './Page'; import { SidebarOpenStateProvider } from './SidebarOpenStateContext'; import { useSidebarPinState } from './SidebarPinStateContext'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { coreComponentsTranslationRef } from '../../translation'; /** @public */ export type SidebarClassKey = 'drawer' | 'drawerOpen'; @@ -250,6 +252,7 @@ function A11ySkipSidebar() { const { sidebarConfig } = useContext(SidebarConfigContext); const { focusContent, contentRef } = useContent(); const classes = useStyles({ sidebarConfig }); + const { t } = useTranslationRef(coreComponentsTranslationRef); if (!contentRef?.current) { return null; @@ -260,7 +263,7 @@ function A11ySkipSidebar() { variant="contained" className={classnames(classes.visuallyHidden)} > - Skip to content + {t('skipToContent')} ); } diff --git a/packages/core-components/src/layout/SignInPage/GuestUserIdentity.ts b/packages/core-components/src/layout/SignInPage/GuestUserIdentity.ts index db4731704c..6abb412090 100644 --- a/packages/core-components/src/layout/SignInPage/GuestUserIdentity.ts +++ b/packages/core-components/src/layout/SignInPage/GuestUserIdentity.ts @@ -20,6 +20,9 @@ import { BackstageUserIdentity, } from '@backstage/core-plugin-api'; +/** + * @deprecated Use `@backstage/plugin-auth-backend-module-guest-provider` instead. + */ export class GuestUserIdentity implements IdentityApi { getUserId(): string { return 'guest'; diff --git a/packages/core-components/src/layout/SignInPage/SignInPage.tsx b/packages/core-components/src/layout/SignInPage/SignInPage.tsx index 6092f2862f..95d96b701a 100644 --- a/packages/core-components/src/layout/SignInPage/SignInPage.tsx +++ b/packages/core-components/src/layout/SignInPage/SignInPage.tsx @@ -35,6 +35,8 @@ import { Page } from '../Page'; import { getSignInProviders, useSignInProviders } from './providers'; import { GridItem, useStyles } from './styles'; import { IdentityProviders, SignInProviderConfig } from './types'; +import { coreComponentsTranslationRef } from '../../translation'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; type MultiSignInPageProps = SignInPageProps & { providers: IdentityProviders; @@ -95,6 +97,7 @@ export const SingleSignInPage = ({ const classes = useStyles(); const authApi = useApi(provider.apiRef); const configApi = useApi(configApiRef); + const { t } = useTranslationRef(coreComponentsTranslationRef); const [error, setError] = useState(); @@ -174,7 +177,7 @@ export const SingleSignInPage = ({ login({ showPopup: true }); }} > - Sign In + {t('signIn.title')} } > diff --git a/packages/core-components/src/layout/SignInPage/commonProvider.tsx b/packages/core-components/src/layout/SignInPage/commonProvider.tsx index 1827981e6f..07a9d9c98e 100644 --- a/packages/core-components/src/layout/SignInPage/commonProvider.tsx +++ b/packages/core-components/src/layout/SignInPage/commonProvider.tsx @@ -28,6 +28,8 @@ import { useApi, errorApiRef } from '@backstage/core-plugin-api'; import { GridItem } from './styles'; import { ForwardedError } from '@backstage/errors'; import { UserIdentity } from './UserIdentity'; +import { coreComponentsTranslationRef } from '../../translation'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; const Component: ProviderComponent = ({ config, @@ -38,6 +40,7 @@ const Component: ProviderComponent = ({ const { apiRef, title, message } = config as SignInProviderConfig; const authApi = useApi(apiRef); const errorApi = useApi(errorApiRef); + const { t } = useTranslationRef(coreComponentsTranslationRef); const handleLogin = async () => { try { @@ -63,7 +66,7 @@ const Component: ProviderComponent = ({ ); } catch (error) { onSignInFailure(); - errorApi.post(new ForwardedError('Login failed', error)); + errorApi.post(new ForwardedError(t('signIn.loginFailed'), error)); } }; @@ -74,7 +77,7 @@ const Component: ProviderComponent = ({ title={title} actions={ } > diff --git a/packages/core-components/src/layout/SignInPage/customProvider.tsx b/packages/core-components/src/layout/SignInPage/customProvider.tsx index ad02715447..7d1de40d7b 100644 --- a/packages/core-components/src/layout/SignInPage/customProvider.tsx +++ b/packages/core-components/src/layout/SignInPage/customProvider.tsx @@ -27,6 +27,8 @@ import { InfoCard } from '../InfoCard/InfoCard'; import { ProviderComponent, ProviderLoader, SignInProvider } from './types'; import { GridItem } from './styles'; import { UserIdentity } from './UserIdentity'; +import { coreComponentsTranslationRef } from '../../translation'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; // accept base64url format according to RFC7515 (https://tools.ietf.org/html/rfc7515#section-3) const ID_TOKEN_REGEX = /^[a-z0-9_\-]+\.[a-z0-9_\-]+\.[a-z0-9_\-]+$/i; @@ -44,6 +46,9 @@ const useFormStyles = makeStyles( alignSelf: 'center', marginTop: theme.spacing(2), }, + subTitle: { + whiteSpace: 'pre-line', + }, }), { name: 'BackstageCustomProvider' }, ); @@ -63,6 +68,7 @@ const asInputRef = (renderResult: UseFormRegisterReturn) => { const Component: ProviderComponent = ({ onSignInStarted, onSignInSuccess }) => { const classes = useFormStyles(); + const { t } = useTranslationRef(coreComponentsTranslationRef); const { register, handleSubmit, formState } = useForm({ mode: 'onChange', }); @@ -84,18 +90,16 @@ const Component: ProviderComponent = ({ onSignInStarted, onSignInSuccess }) => { return ( - - - Enter your own User ID and credentials. -
- This selection will not be stored. + + + {t('signIn.customProvider.subtitle')}
@@ -111,10 +115,10 @@ const Component: ProviderComponent = ({ onSignInStarted, onSignInSuccess }) => { validate: token => !token || ID_TOKEN_REGEX.test(token) || - 'Token is not a valid OpenID Connect JWT Token', + t('signIn.customProvider.tokenInvalid'), }), )} - label="ID Token (optional)" + label={t('signIn.customProvider.idToken')} margin="normal" autoComplete="off" error={Boolean(errors.idToken)} @@ -130,7 +134,7 @@ const Component: ProviderComponent = ({ onSignInStarted, onSignInSuccess }) => { className={classes.button} disabled={!formState?.isDirty || !isEmpty(errors)} > - Continue + {t('signIn.customProvider.continue')}
diff --git a/packages/core-components/src/layout/SignInPage/guestProvider.tsx b/packages/core-components/src/layout/SignInPage/guestProvider.tsx index 5393c1ea89..e4e02d74fe 100644 --- a/packages/core-components/src/layout/SignInPage/guestProvider.tsx +++ b/packages/core-components/src/layout/SignInPage/guestProvider.tsx @@ -20,39 +20,113 @@ import Button from '@material-ui/core/Button'; import { InfoCard } from '../InfoCard/InfoCard'; import { GridItem } from './styles'; import { ProviderComponent, ProviderLoader, SignInProvider } from './types'; +import { ProxiedSignInIdentity } from '../ProxiedSignInPage/ProxiedSignInIdentity'; +import { discoveryApiRef, useApi } from '@backstage/core-plugin-api'; import { GuestUserIdentity } from './GuestUserIdentity'; +import useLocalStorage from 'react-use/lib/useLocalStorage'; +import { ResponseError } from '@backstage/errors'; +import { coreComponentsTranslationRef } from '../../translation'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; -const Component: ProviderComponent = ({ onSignInStarted, onSignInSuccess }) => ( - - { - onSignInStarted(); - onSignInSuccess(new GuestUserIdentity()); - }} - > - Enter - +const getIdentity = async (identity: ProxiedSignInIdentity) => { + try { + const identityResponse = await identity.getBackstageIdentity(); + return identityResponse; + } catch (error) { + if ( + error.name === 'ResponseError' && + (error as ResponseError).cause.name === 'NotFoundError' + ) { + return undefined; + } + throw error; + } +}; + +const Component: ProviderComponent = ({ + onSignInStarted, + onSignInSuccess, + onSignInFailure, +}) => { + const discoveryApi = useApi(discoveryApiRef); + const [_, setUseLegacyGuestToken] = useLocalStorage('enableLegacyGuestToken'); + const { t } = useTranslationRef(coreComponentsTranslationRef); + + const handle = async () => { + onSignInStarted(); + + const identity = new ProxiedSignInIdentity({ + provider: 'guest', + discoveryApi, + }); + + const identityResponse = await getIdentity(identity); + + if (!identityResponse) { + // eslint-disable-next-line no-alert + const useLegacyGuestTokenResponse = confirm( + 'Failed to sign in as a guest using the auth backend. Do you want to fallback to the legacy guest token?', + ); + if (useLegacyGuestTokenResponse) { + setUseLegacyGuestToken(true); + onSignInSuccess(new GuestUserIdentity()); + return; } - > - - Enter as a Guest User. -
- You will not have a verified identity, -
- meaning some features might be unavailable. -
-
-
-); + onSignInFailure(); + throw new Error( + `You cannot sign in as a guest, you must either enable the legacy guest token or configure the auth backend to support guest sign in.`, + ); + } -const loader: ProviderLoader = async () => { - return new GuestUserIdentity(); + onSignInSuccess(identity); + }; + + return ( + + + {t('signIn.guestProvider.enter')} + + } + > + + {t('signIn.guestProvider.subtitle')} + + + + ); +}; + +const loader: ProviderLoader = async apis => { + const useLegacyGuestToken = + localStorage.getItem('enableLegacyGuestToken') === 'true'; + + const identity = new ProxiedSignInIdentity({ + provider: 'guest', + discoveryApi: apis.get(discoveryApiRef)!, + }); + const identityResponse = await getIdentity(identity); + + if (!identityResponse && !useLegacyGuestToken) { + return undefined; + } else if (identityResponse && useLegacyGuestToken) { + // eslint-disable-next-line no-alert + const switchToNewGuestToken = confirm( + 'You are currently using the legacy guest token, but you have the new guest backend module installed. Do you want to use the new module?', + ); + if (switchToNewGuestToken) { + localStorage.removeItem('enableLegacyGuestToken'); + } else { + return new GuestUserIdentity(); + } + } else if (useLegacyGuestToken) { + return new GuestUserIdentity(); + } + + return identity; }; export const guestProvider: SignInProvider = { Component, loader }; diff --git a/packages/core-components/src/translation.ts b/packages/core-components/src/translation.ts new file mode 100644 index 0000000000..2acb4ea735 --- /dev/null +++ b/packages/core-components/src/translation.ts @@ -0,0 +1,111 @@ +/* + * 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 { createTranslationRef } from '@backstage/core-plugin-api/alpha'; + +/** @alpha */ +export const coreComponentsTranslationRef = createTranslationRef({ + id: 'core-components', + messages: { + signIn: { + title: 'Sign In', + loginFailed: 'Login failed', + customProvider: { + title: 'Custom User', + subtitle: + 'Enter your own User ID and credentials.\n This selection will not be stored.', + userId: 'User ID', + tokenInvalid: 'Token is not a valid OpenID Connect JWT Token', + continue: 'Continue', + idToken: 'ID Token (optional)', + }, + guestProvider: { + title: 'Guest', + subtitle: + 'Enter as a Guest User.\n You will not have a verified identity, meaning some features might be unavailable.', + enter: 'Enter', + }, + }, + skipToContent: 'Skip to content', + copyTextButton: { + tooltipText: 'Text copied to clipboard', + }, + simpleStepper: { + reset: 'Reset', + finish: 'Finish', + next: 'Next', + skip: 'Skip', + back: 'Back', + }, + errorPage: { + subtitle: 'ERROR {{status}}: {{statusMessage}}', + title: 'Looks like someone dropped the mic!', + goBack: 'Go back', + showMoreDetails: 'Show more details', + showLessDetails: 'Show less details', + }, + emptyState: { + missingAnnotation: { + title: 'Missing Annotation', + actionTitle: + 'Add the annotation to your component YAML as shown in the highlighted example below:', + readMore: 'Read more', + }, + }, + supportConfig: { + default: { + title: 'Support Not Configured', + linkTitle: 'Add `app.support` config key', + }, + }, + errorBoundary: { + title: 'Please contact {{slackChannel}} for help.', + }, + oauthRequestDialog: { + title: 'Login Required', + authRedirectTitle: 'This will trigger a http redirect to OAuth Login.', + login: 'Log in', + rejectAll: 'Reject All', + }, + link: { + openNewWindow: 'Opens in a new window', + }, + supportButton: { + title: 'Support', + close: 'Close', + }, + table: { + filter: { + title: 'Filters', + clearAll: 'Clear all', + }, + }, + alertDisplay: { + message_one: '({{ count }} older message)', + message_other: '({{ count }} older messages)', + }, + autoLogout: { + stillTherePrompt: { + title: 'Logging out due to inactivity', + buttonText: "Yes! Don't log me out", + }, + }, + proxiedSignInPage: { + title: + 'You do not appear to be signed in. Please try reloading the browser page.', + }, + }, +}); diff --git a/packages/core-plugin-api/CHANGELOG.md b/packages/core-plugin-api/CHANGELOG.md index a66fb2eb83..ff2ab443b9 100644 --- a/packages/core-plugin-api/CHANGELOG.md +++ b/packages/core-plugin-api/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/core-plugin-api +## 1.9.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + ## 1.9.0 ### Minor Changes diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index 95dd1b40f4..1c79805470 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-plugin-api", "description": "Core API used by Backstage plugins", - "version": "1.9.0", + "version": "1.9.1-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index fe33cafe4c..4a701b3cd1 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/create-app +## 0.5.12-next.0 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.13 + ## 0.5.11 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 354f4d7cd9..94bd6c5a69 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.11", + "version": "0.5.12-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index 7e7915a4bf..ae952e6924 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/dev-utils +## 1.0.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/app-defaults@1.5.1-next.0 + - @backstage/core-app-api@1.12.1-next.0 + ## 1.0.27 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 533ddc469a..2b72bb244d 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/dev-utils", - "version": "1.0.27", + "version": "1.0.28-next.0", "description": "Utilities for developing Backstage plugins.", "backstage": { "role": "web-library" diff --git a/packages/e2e-test/CHANGELOG.md b/packages/e2e-test/CHANGELOG.md index 998bc00a3f..9db25dbe50 100644 --- a/packages/e2e-test/CHANGELOG.md +++ b/packages/e2e-test/CHANGELOG.md @@ -1,5 +1,14 @@ # e2e-test +## 0.2.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.12-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/cli-common@0.1.13 + ## 0.2.12 ### Patch Changes diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index 40d66d7f4b..e4cfce13bb 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.12", + "version": "0.2.13-next.0", "private": true, "backstage": { "role": "cli" diff --git a/packages/errors/CHANGELOG.md b/packages/errors/CHANGELOG.md index 92655a25d8..2a2f8c3461 100644 --- a/packages/errors/CHANGELOG.md +++ b/packages/errors/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/errors +## 1.2.4-next.0 + +### Patch Changes + +- 2636075: Fixed an issue that was causing ResponseError not to report the HTTP status from the provided response. +- Updated dependencies + - @backstage/types@1.1.1 + ## 1.2.3 ### Patch Changes diff --git a/packages/errors/package.json b/packages/errors/package.json index d62c5ea215..42c78287ab 100644 --- a/packages/errors/package.json +++ b/packages/errors/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/errors", - "version": "1.2.3", + "version": "1.2.4-next.0", "description": "Common utilities for error handling within Backstage", "backstage": { "role": "common-library" diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 20bd1d900c..634f9579e9 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/eslint-plugin +## 0.1.6-next.0 + +### Patch Changes + +- 999224f: Bump dependency `minimatch` to v9 + ## 0.1.5 ### Patch Changes diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index ec3b9ceea8..63bec733be 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/eslint-plugin", "description": "Backstage ESLint plugin", - "version": "0.1.5", + "version": "0.1.6-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/frontend-app-api/CHANGELOG.md b/packages/frontend-app-api/CHANGELOG.md index 38553d5fa2..63a9f1a223 100644 --- a/packages/frontend-app-api/CHANGELOG.md +++ b/packages/frontend-app-api/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/frontend-app-api +## 0.6.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-app-api@1.12.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + ## 0.6.0 ### Minor Changes diff --git a/packages/frontend-app-api/package.json b/packages/frontend-app-api/package.json index 40f6ce351f..87725b2211 100644 --- a/packages/frontend-app-api/package.json +++ b/packages/frontend-app-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/frontend-app-api", - "version": "0.6.0", + "version": "0.6.1-next.0", "backstage": { "role": "web-library" }, diff --git a/packages/frontend-plugin-api/CHANGELOG.md b/packages/frontend-plugin-api/CHANGELOG.md index bd287c287b..c72758c50c 100644 --- a/packages/frontend-plugin-api/CHANGELOG.md +++ b/packages/frontend-plugin-api/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/frontend-plugin-api +## 0.6.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + ## 0.6.0 ### Minor Changes diff --git a/packages/frontend-plugin-api/package.json b/packages/frontend-plugin-api/package.json index 493d6fd553..0f2a08c48e 100644 --- a/packages/frontend-plugin-api/package.json +++ b/packages/frontend-plugin-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/frontend-plugin-api", - "version": "0.6.0", + "version": "0.6.1-next.0", "backstage": { "role": "web-library" }, diff --git a/packages/frontend-test-utils/CHANGELOG.md b/packages/frontend-test-utils/CHANGELOG.md index fe590fd8e2..2433c64a6c 100644 --- a/packages/frontend-test-utils/CHANGELOG.md +++ b/packages/frontend-test-utils/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/frontend-test-utils +## 0.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.6.1-next.0 + - @backstage/test-utils@1.5.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/types@1.1.1 + ## 0.1.2 ### Patch Changes diff --git a/packages/frontend-test-utils/package.json b/packages/frontend-test-utils/package.json index 6c5ceb4d7c..4a22373e56 100644 --- a/packages/frontend-test-utils/package.json +++ b/packages/frontend-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/frontend-test-utils", - "version": "0.1.2", + "version": "0.1.3-next.0", "backstage": { "role": "web-library" }, diff --git a/packages/integration-aws-node/CHANGELOG.md b/packages/integration-aws-node/CHANGELOG.md index 17a0711779..1136932c75 100644 --- a/packages/integration-aws-node/CHANGELOG.md +++ b/packages/integration-aws-node/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/integration-aws-node +## 0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.1.9 ### Patch Changes diff --git a/packages/integration-aws-node/package.json b/packages/integration-aws-node/package.json index a515a01d31..9fb6e2f44b 100644 --- a/packages/integration-aws-node/package.json +++ b/packages/integration-aws-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/integration-aws-node", - "version": "0.1.9", + "version": "0.1.10-next.0", "description": "Helpers for fetching AWS account credentials", "backstage": { "role": "node-library" diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index 8512b5b1a7..3160754124 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/integration-react +## 1.1.25-next.0 + +### Patch Changes + +- b38dc55: Updated `microsoftAuthApi` scopes for Azure DevOps to be fully qualified. +- Updated dependencies + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + ## 1.1.24 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index 6fad954df9..056a7cf25b 100644 --- a/packages/integration-react/package.json +++ b/packages/integration-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/integration-react", - "version": "1.1.24", + "version": "1.1.25-next.0", "description": "Frontend package for managing integrations towards external systems", "backstage": { "role": "web-library" diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md index 3cf0701f22..ac1e1ff19f 100644 --- a/packages/integration/CHANGELOG.md +++ b/packages/integration/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/integration +## 1.9.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/config@1.1.2-next.0 + ## 1.9.0 ### Minor Changes diff --git a/packages/integration/package.json b/packages/integration/package.json index 3b156ee323..b1932704ad 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/integration", - "version": "1.9.0", + "version": "1.9.1-next.0", "description": "Helpers for managing integrations towards external systems", "backstage": { "role": "common-library" diff --git a/packages/repo-tools/CHANGELOG.md b/packages/repo-tools/CHANGELOG.md index 3c4ba418b1..5787ba8a7e 100644 --- a/packages/repo-tools/CHANGELOG.md +++ b/packages/repo-tools/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/repo-tools +## 0.6.3-next.0 + +### Patch Changes + +- 999224f: Bump dependency `minimatch` to v9 +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/cli-node@0.2.4-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/cli-common@0.1.13 + ## 0.6.0 ### Minor Changes diff --git a/packages/repo-tools/package.json b/packages/repo-tools/package.json index c14ca74fab..832dbc484e 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.6.0", + "version": "0.6.3-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md index 58757665c8..f1cabfe53f 100644 --- a/packages/techdocs-cli-embedded-app/CHANGELOG.md +++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md @@ -1,5 +1,24 @@ # techdocs-cli-embedded-app +## 0.2.92-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/cli@0.25.3-next.0 + - @backstage/plugin-catalog@1.17.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-techdocs@1.10.1-next.0 + - @backstage/app-defaults@1.5.1-next.0 + - @backstage/test-utils@1.5.1-next.0 + - @backstage/plugin-techdocs-react@1.1.17-next.0 + - @backstage/core-app-api@1.12.1-next.0 + ## 0.2.91 ### Patch Changes diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index 1fcf83cc2f..5e8007a978 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.91", + "version": "0.2.92-next.0", "private": true, "backstage": { "role": "frontend" diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index 0229a95f31..4564113b2c 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,5 +1,16 @@ # @techdocs/cli +## 1.8.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-techdocs-node@1.11.5-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/cli-common@0.1.13 + ## 1.8.2 ### Patch Changes diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index ad5982b093..ffb872856f 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.8.2", + "version": "1.8.5-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index c1db0fb567..2a6a294f2d 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/test-utils +## 1.5.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/core-app-api@1.12.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-react@0.4.21-next.0 + ## 1.5.0 ### Minor Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index c480df3673..f6ffcf7f72 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.5.0", + "version": "1.5.1-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/theme/CHANGELOG.md b/packages/theme/CHANGELOG.md index a0cf6e0a6c..2e6ad4b14d 100644 --- a/packages/theme/CHANGELOG.md +++ b/packages/theme/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/theme +## 0.5.2-next.0 + +### Patch Changes + +- 6f4d2a0: Exported `defaultTypography` to make adjusting these values in a custom theme easier + ## 0.5.1 ### Patch Changes diff --git a/packages/theme/api-report.md b/packages/theme/api-report.md index 21d6be6a78..988569ece7 100644 --- a/packages/theme/api-report.md +++ b/packages/theme/api-report.md @@ -205,6 +205,9 @@ export const darkTheme: Theme_3; // @public export const defaultComponentThemes: ThemeOptions['components']; +// @public +export const defaultTypography: BackstageTypography; + // @public export function genPageTheme(props: { colors: string[]; diff --git a/packages/theme/package.json b/packages/theme/package.json index ef3f56071f..80553c199f 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/theme", - "version": "0.5.1", + "version": "0.5.2-next.0", "description": "material-ui theme for use with Backstage.", "backstage": { "role": "web-library" diff --git a/packages/theme/src/base/createBaseThemeOptions.ts b/packages/theme/src/base/createBaseThemeOptions.ts index f0c8ab5fe9..ab02af61c8 100644 --- a/packages/theme/src/base/createBaseThemeOptions.ts +++ b/packages/theme/src/base/createBaseThemeOptions.ts @@ -22,6 +22,46 @@ const DEFAULT_FONT_FAMILY = '"Helvetica Neue", Helvetica, Roboto, Arial, sans-serif'; const DEFAULT_PAGE_THEME = 'home'; +/** + * Default Typography settings. + * + * @public + */ +export const defaultTypography: BackstageTypography = { + htmlFontSize: DEFAULT_HTML_FONT_SIZE, + fontFamily: DEFAULT_FONT_FAMILY, + 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, + }, +}; + /** * Options for {@link createBaseThemeOptions}. * @@ -57,40 +97,8 @@ export function createBaseThemeOptions( throw new Error(`${defaultPageTheme} is not defined in pageTheme.`); } - const defaultTypography: BackstageTypography = { - 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, - }, - }; + defaultTypography.htmlFontSize = htmlFontSize; + defaultTypography.fontFamily = fontFamily; return { palette, diff --git a/packages/theme/src/base/index.ts b/packages/theme/src/base/index.ts index 2da9fb0fac..f7a6b2fd07 100644 --- a/packages/theme/src/base/index.ts +++ b/packages/theme/src/base/index.ts @@ -14,7 +14,10 @@ * limitations under the License. */ -export { createBaseThemeOptions } from './createBaseThemeOptions'; +export { + createBaseThemeOptions, + defaultTypography, +} from './createBaseThemeOptions'; export type { BaseThemeOptionsInput } from './createBaseThemeOptions'; export { colorVariants, genPageTheme, pageTheme, shapes } from './pageTheme'; export { palettes } from './palettes'; diff --git a/plugins/adr-backend/CHANGELOG.md b/plugins/adr-backend/CHANGELOG.md index 4d6529e4b0..5cdd61452d 100644 --- a/plugins/adr-backend/CHANGELOG.md +++ b/plugins/adr-backend/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-adr-backend +## 0.4.10-next.0 + +### Patch Changes + +- 334c5fe: Updated dependency `marked` to `^12.0.0`. +- c8fdd83: Migrated `DefaultAdrCollatorFactory` to support new auth services. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-adr-common@0.2.21-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.4.7 ### Patch Changes diff --git a/plugins/adr-backend/package.json b/plugins/adr-backend/package.json index 0216a8d4a1..02e4777db9 100644 --- a/plugins/adr-backend/package.json +++ b/plugins/adr-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr-backend", - "version": "0.4.7", + "version": "0.4.10-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 aab9807c8d..3816462f69 100644 --- a/plugins/adr-common/CHANGELOG.md +++ b/plugins/adr-common/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-adr-common +## 0.2.21-next.0 + +### Patch Changes + +- 5335634: Fixed Azure DevOps ADR file path reading +- Updated dependencies + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.2.20 ### Patch Changes diff --git a/plugins/adr-common/package.json b/plugins/adr-common/package.json index d0cc173bbf..4fc8a5b70a 100644 --- a/plugins/adr-common/package.json +++ b/plugins/adr-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr-common", - "version": "0.2.20", + "version": "0.2.21-next.0", "description": "Common functionalities for the adr plugin", "backstage": { "role": "common-library" diff --git a/plugins/adr/CHANGELOG.md b/plugins/adr/CHANGELOG.md index 04612df31a..a5b171dedb 100644 --- a/plugins/adr/CHANGELOG.md +++ b/plugins/adr/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-adr +## 0.6.14-next.0 + +### Patch Changes + +- 5335634: Fixed Azure DevOps ADR file path reading +- 669efc6: Remove unused package dependencies +- Updated dependencies + - @backstage/plugin-adr-common@0.2.21-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + ## 0.6.13 ### Patch Changes diff --git a/plugins/adr/knip-report.md b/plugins/adr/knip-report.md index 91abb6b619..ba9c1dddc5 100644 --- a/plugins/adr/knip-report.md +++ b/plugins/adr/knip-report.md @@ -1,12 +1,5 @@ # Knip report -## Unused dependencies (2) - -| Name | Location | Severity | -| :------------- | :----------- | :------- | -| react-markdown | package.json | error | -| remark-gfm | package.json | error | - ## Unused devDependencies (2) | Name | Location | Severity | diff --git a/plugins/adr/package.json b/plugins/adr/package.json index 1e6f6ece0e..efc2719e1e 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr", - "version": "0.6.13", + "version": "0.6.14-next.0", "backstage": { "role": "frontend-plugin" }, @@ -58,9 +58,7 @@ "@material-ui/icons": "^4.9.1", "@types/react": "^16.13.1 || ^17.0.0 || ^18.0.0", "lodash": "^4.17.21", - "react-markdown": "^8.0.0", - "react-use": "^17.2.4", - "remark-gfm": "^3.0.1" + "react-use": "^17.2.4" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/plugins/airbrake-backend/CHANGELOG.md b/plugins/airbrake-backend/CHANGELOG.md index b029fbcd8e..33b13f5c6f 100644 --- a/plugins/airbrake-backend/CHANGELOG.md +++ b/plugins/airbrake-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-airbrake-backend +## 0.3.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.3.7 ### Patch Changes diff --git a/plugins/airbrake-backend/package.json b/plugins/airbrake-backend/package.json index 62b56edfb6..397f805884 100644 --- a/plugins/airbrake-backend/package.json +++ b/plugins/airbrake-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake-backend", - "version": "0.3.7", + "version": "0.3.10-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 b46890f569..f9a7bb248a 100644 --- a/plugins/airbrake/CHANGELOG.md +++ b/plugins/airbrake/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-airbrake +## 0.3.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/dev-utils@1.0.28-next.0 + - @backstage/test-utils@1.5.1-next.0 + ## 0.3.30 ### Patch Changes diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index 8138bdc19f..83e81c2a83 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake", - "version": "0.3.30", + "version": "0.3.31-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/allure/CHANGELOG.md b/plugins/allure/CHANGELOG.md index 14d76ba90b..f3a2ce6e24 100644 --- a/plugins/allure/CHANGELOG.md +++ b/plugins/allure/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-allure +## 0.1.47-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.1.46 ### Patch Changes diff --git a/plugins/allure/package.json b/plugins/allure/package.json index 130daa540c..767f984144 100644 --- a/plugins/allure/package.json +++ b/plugins/allure/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-allure", - "version": "0.1.46", + "version": "0.1.47-next.0", "description": "A Backstage plugin that integrates with Allure", "backstage": { "role": "frontend-plugin" diff --git a/plugins/analytics-module-ga/CHANGELOG.md b/plugins/analytics-module-ga/CHANGELOG.md index 1101cb71f7..f965d79f0c 100644 --- a/plugins/analytics-module-ga/CHANGELOG.md +++ b/plugins/analytics-module-ga/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-analytics-module-ga +## 0.2.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + ## 0.2.0 ### Minor Changes diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index 5dec21a816..2b65513dda 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.2.0", + "version": "0.2.1-next.0", "backstage": { "role": "frontend-plugin-module" }, diff --git a/plugins/analytics-module-ga4/CHANGELOG.md b/plugins/analytics-module-ga4/CHANGELOG.md index 13d7c9e020..0d44d35ddd 100644 --- a/plugins/analytics-module-ga4/CHANGELOG.md +++ b/plugins/analytics-module-ga4/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-analytics-module-ga4 +## 0.2.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + ## 0.2.0 ### Minor Changes diff --git a/plugins/analytics-module-ga4/package.json b/plugins/analytics-module-ga4/package.json index 396ba80195..f182be09b1 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.2.0", + "version": "0.2.1-next.0", "backstage": { "role": "frontend-plugin-module" }, diff --git a/plugins/analytics-module-newrelic-browser/CHANGELOG.md b/plugins/analytics-module-newrelic-browser/CHANGELOG.md index 18b92da8b2..d4587faa0e 100644 --- a/plugins/analytics-module-newrelic-browser/CHANGELOG.md +++ b/plugins/analytics-module-newrelic-browser/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-analytics-module-newrelic-browser +## 0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + ## 0.1.0 ### Minor Changes diff --git a/plugins/analytics-module-newrelic-browser/package.json b/plugins/analytics-module-newrelic-browser/package.json index e443c5a56d..a704b9eaf0 100644 --- a/plugins/analytics-module-newrelic-browser/package.json +++ b/plugins/analytics-module-newrelic-browser/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-newrelic-browser", - "version": "0.1.0", + "version": "0.1.1-next.0", "backstage": { "role": "frontend-plugin-module" }, diff --git a/plugins/apache-airflow/CHANGELOG.md b/plugins/apache-airflow/CHANGELOG.md index 32b7b76cc4..7752eb590a 100644 --- a/plugins/apache-airflow/CHANGELOG.md +++ b/plugins/apache-airflow/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-apache-airflow +## 0.2.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.2.20 ### Patch Changes diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index 11317ce08f..8f68825418 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.20", + "version": "0.2.21-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index c4121dc841..dd06765163 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-api-docs +## 0.11.1-next.0 + +### Patch Changes + +- 7854120: Use the `AppIcon` component in the navigation item extension. +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-catalog@1.17.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + - @backstage/plugin-permission-react@0.4.21-next.0 + ## 0.11.0 ### Minor Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index fb42a30a27..7de2d4ef21 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-api-docs", - "version": "0.11.0", + "version": "0.11.1-next.0", "description": "A Backstage plugin that helps represent API entities in the frontend", "backstage": { "role": "frontend-plugin" diff --git a/plugins/apollo-explorer/CHANGELOG.md b/plugins/apollo-explorer/CHANGELOG.md index f7ea472981..fd27695321 100644 --- a/plugins/apollo-explorer/CHANGELOG.md +++ b/plugins/apollo-explorer/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-apollo-explorer +## 0.1.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.1.20 ### Patch Changes diff --git a/plugins/apollo-explorer/package.json b/plugins/apollo-explorer/package.json index 2aac8cec9a..60323f87b2 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.20", + "version": "0.1.21-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index fc5f169d7c..d193fe3e9a 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-app-backend +## 0.3.61-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config-loader@1.6.3-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-app-node@0.1.13-next.0 + - @backstage/types@1.1.1 + ## 0.3.58 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index 3a1093528e..1673f8d7b2 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.58", + "version": "0.3.61-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/app-node/CHANGELOG.md b/plugins/app-node/CHANGELOG.md index 10b8a721d8..64fc874317 100644 --- a/plugins/app-node/CHANGELOG.md +++ b/plugins/app-node/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-app-node +## 0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config-loader@1.6.3-next.0 + ## 0.1.10 ### Patch Changes diff --git a/plugins/app-node/package.json b/plugins/app-node/package.json index e9e91d10a3..f509802cd6 100644 --- a/plugins/app-node/package.json +++ b/plugins/app-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-app-node", "description": "Node.js library for the app plugin", - "version": "0.1.10", + "version": "0.1.13-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/app-visualizer/CHANGELOG.md b/plugins/app-visualizer/CHANGELOG.md index c2ec7ce563..99865e1aca 100644 --- a/plugins/app-visualizer/CHANGELOG.md +++ b/plugins/app-visualizer/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-app-visualizer +## 0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + ## 0.1.1 ### Patch Changes diff --git a/plugins/app-visualizer/package.json b/plugins/app-visualizer/package.json index c49386e291..8180412063 100644 --- a/plugins/app-visualizer/package.json +++ b/plugins/app-visualizer/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-app-visualizer", - "version": "0.1.1", + "version": "0.1.2-next.0", "description": "Visualizes the Backstage app structure", "backstage": { "role": "frontend-plugin" diff --git a/plugins/auth-backend-module-atlassian-provider/CHANGELOG.md b/plugins/auth-backend-module-atlassian-provider/CHANGELOG.md index 5325ba7a5e..99859e3299 100644 --- a/plugins/auth-backend-module-atlassian-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-atlassian-provider/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-auth-backend-module-atlassian-provider +## 0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + ## 0.1.2 ### Patch Changes diff --git a/plugins/auth-backend-module-atlassian-provider/package.json b/plugins/auth-backend-module-atlassian-provider/package.json index ba73122270..7d4f129668 100644 --- a/plugins/auth-backend-module-atlassian-provider/package.json +++ b/plugins/auth-backend-module-atlassian-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-atlassian-provider", "description": "The atlassian-provider backend module for the auth plugin.", - "version": "0.1.2", + "version": "0.1.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-aws-alb-provider/CHANGELOG.md b/plugins/auth-backend-module-aws-alb-provider/CHANGELOG.md index c24e78d04d..5cc5aeaa74 100644 --- a/plugins/auth-backend-module-aws-alb-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-aws-alb-provider/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-auth-backend-module-aws-alb-provider +## 0.1.4-next.0 + +### Patch Changes + +- 2af5354: Bump dependency `jose` to v5 +- b1b012d: Fix issue with `providerInfo` not being set properly for some proxy providers, by making `providerInfo` an explicit optional return from `authenticate` +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-auth-backend@0.22.0-next.0 + ## 0.1.0 ### Minor Changes diff --git a/plugins/auth-backend-module-aws-alb-provider/package.json b/plugins/auth-backend-module-aws-alb-provider/package.json index e79b1b8f61..907f0b574e 100644 --- a/plugins/auth-backend-module-aws-alb-provider/package.json +++ b/plugins/auth-backend-module-aws-alb-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-aws-alb-provider", "description": "The aws-alb provider module for the Backstage auth backend.", - "version": "0.1.0", + "version": "0.1.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md b/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md index 44cf3dedda..0a6b9372fb 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-auth-backend-module-gcp-iap-provider +## 0.2.8-next.0 + +### Patch Changes + +- 38af71a: Updated dependency `google-auth-library` to `^9.0.0`. +- b1b012d: Fix issue with `providerInfo` not being set properly for some proxy providers, by making `providerInfo` an explicit optional return from `authenticate` +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/types@1.1.1 + ## 0.2.4 ### Patch Changes diff --git a/plugins/auth-backend-module-gcp-iap-provider/package.json b/plugins/auth-backend-module-gcp-iap-provider/package.json index 54bd916f68..765ef6a11f 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/package.json +++ b/plugins/auth-backend-module-gcp-iap-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-gcp-iap-provider", "description": "A GCP IAP auth provider module for the Backstage auth backend", - "version": "0.2.4", + "version": "0.2.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-github-provider/CHANGELOG.md b/plugins/auth-backend-module-github-provider/CHANGELOG.md index c7dd3d160c..7dd171f7f5 100644 --- a/plugins/auth-backend-module-github-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-github-provider/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-auth-backend-module-github-provider +## 0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + ## 0.1.7 ### Patch Changes diff --git a/plugins/auth-backend-module-github-provider/package.json b/plugins/auth-backend-module-github-provider/package.json index 1f1a02fd43..d684c55c06 100644 --- a/plugins/auth-backend-module-github-provider/package.json +++ b/plugins/auth-backend-module-github-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-github-provider", "description": "The github-provider backend module for the auth plugin.", - "version": "0.1.7", + "version": "0.1.10-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md b/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md index 46b9887e8a..3f0136785c 100644 --- a/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-auth-backend-module-gitlab-provider +## 0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + ## 0.1.7 ### Patch Changes diff --git a/plugins/auth-backend-module-gitlab-provider/package.json b/plugins/auth-backend-module-gitlab-provider/package.json index 2c55a8e6a2..32a5e20f25 100644 --- a/plugins/auth-backend-module-gitlab-provider/package.json +++ b/plugins/auth-backend-module-gitlab-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-gitlab-provider", "description": "The gitlab-provider backend module for the auth plugin.", - "version": "0.1.7", + "version": "0.1.10-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-google-provider/CHANGELOG.md b/plugins/auth-backend-module-google-provider/CHANGELOG.md index d3d3f923ab..478f12970c 100644 --- a/plugins/auth-backend-module-google-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-google-provider/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-backend-module-google-provider +## 0.1.10-next.0 + +### Patch Changes + +- 38af71a: Updated dependency `google-auth-library` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + ## 0.1.7 ### Patch Changes diff --git a/plugins/auth-backend-module-google-provider/package.json b/plugins/auth-backend-module-google-provider/package.json index 724081358a..3750cde69a 100644 --- a/plugins/auth-backend-module-google-provider/package.json +++ b/plugins/auth-backend-module-google-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-google-provider", "description": "A Google auth provider module for the Backstage auth backend", - "version": "0.1.7", + "version": "0.1.10-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-guest-provider/.eslintrc.js b/plugins/auth-backend-module-guest-provider/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/auth-backend-module-guest-provider/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/auth-backend-module-guest-provider/CHANGELOG.md b/plugins/auth-backend-module-guest-provider/CHANGELOG.md new file mode 100644 index 0000000000..b6b9e03bc3 --- /dev/null +++ b/plugins/auth-backend-module-guest-provider/CHANGELOG.md @@ -0,0 +1,34 @@ +# @backstage/plugin-auth-backend-module-guest-provider + +## 0.1.0-next.0 + +### Minor Changes + +- 1bedb23: Adds a new guest provider that maps guest users to actual tokens. This also shifts the default guest login to `user:development/guest` to reduce overlap with your production/real data. To change that (or set it back to the old default, use the new `auth.providers.guest.userEntityRef` config key) like so, + + ```yaml title=app-config.yaml + auth: + providers: + guest: + userEntityRef: user:default/guest + ``` + + This also adds a new property to control the ownership entity refs, + + ```yaml title=app-config.yaml + auth: + providers: + guest: + ownershipEntityRefs: + - guests + - development/custom + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/catalog-model@1.4.5-next.0 diff --git a/plugins/auth-backend-module-guest-provider/README.md b/plugins/auth-backend-module-guest-provider/README.md new file mode 100644 index 0000000000..79591c987b --- /dev/null +++ b/plugins/auth-backend-module-guest-provider/README.md @@ -0,0 +1,8 @@ +# Auth Module: Guest Provider + +This module provides a guest auth provider implementation for `@backstage/plugin-auth-backend`. This is meant to supersede the existing `'guest'` option for authentication that does not emit tokens and is completely stored as frontend state. + +## Links + +- [Backstage](https://backstage.io) +- [Repository](https://github.com/backstage/backstage/tree/master/plugins/auth-backend-module-guest-provider) diff --git a/plugins/auth-backend-module-guest-provider/api-report.md b/plugins/auth-backend-module-guest-provider/api-report.md new file mode 100644 index 0000000000..773b80b9ba --- /dev/null +++ b/plugins/auth-backend-module-guest-provider/api-report.md @@ -0,0 +1,11 @@ +## API Report File for "@backstage/plugin-auth-backend-module-guest-provider" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @public (undocumented) +const authModuleGuestProvider: () => BackendFeature; +export default authModuleGuestProvider; +``` diff --git a/plugins/auth-backend-module-guest-provider/catalog-info.yaml b/plugins/auth-backend-module-guest-provider/catalog-info.yaml new file mode 100644 index 0000000000..5d3513296b --- /dev/null +++ b/plugins/auth-backend-module-guest-provider/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-auth-backend-module-guest-provider + title: '@backstage/plugin-auth-backend-module-guest-provider' + description: The guest-provider backend module for the auth plugin. +spec: + lifecycle: experimental + type: backstage-backend-plugin-module + owner: maintainers diff --git a/plugins/auth-backend-module-guest-provider/config.d.ts b/plugins/auth-backend-module-guest-provider/config.d.ts new file mode 100644 index 0000000000..eb60492393 --- /dev/null +++ b/plugins/auth-backend-module-guest-provider/config.d.ts @@ -0,0 +1,42 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface Config { + /** Configuration options for the auth plugin */ + auth?: { + providers: { + guest?: { + /** + * The entity reference to use for the guest user. + * @default user:development/guest + */ + userEntityRef?: string; + + /** + * A list of entity references to user for ownership of the guest user if the user + * is not found in the catalog. + * @default [userEntityRef] + */ + ownershipEntityRefs?: string[]; + + /** + * Allow users to sign in with the guest provider outside of their development environments. + */ + dangerouslyAllowOutsideDevelopment?: boolean; + }; + }; + }; +} diff --git a/plugins/auth-backend-module-guest-provider/package.json b/plugins/auth-backend-module-guest-provider/package.json new file mode 100644 index 0000000000..46ef0d96d7 --- /dev/null +++ b/plugins/auth-backend-module-guest-provider/package.json @@ -0,0 +1,47 @@ +{ + "name": "@backstage/plugin-auth-backend-module-guest-provider", + "description": "The guest-provider backend module for the auth plugin.", + "version": "0.1.0-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" + }, + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/auth-backend-module-guest-provider" + }, + "backstage": { + "role": "backend-plugin-module" + }, + "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/backend-plugin-api": "workspace:^", + "@backstage/catalog-model": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/plugin-auth-node": "workspace:^", + "passport-oauth2": "^1.7.0" + }, + "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^", + "@backstage/config": "workspace:^", + "express": "^4.18.2" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/auth-backend-module-guest-provider/src/authenticator.ts b/plugins/auth-backend-module-guest-provider/src/authenticator.ts new file mode 100644 index 0000000000..436b72617d --- /dev/null +++ b/plugins/auth-backend-module-guest-provider/src/authenticator.ts @@ -0,0 +1,27 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createProxyAuthenticator } from '@backstage/plugin-auth-node'; + +export const guestAuthenticator = createProxyAuthenticator({ + defaultProfileTransform: async () => { + return { profile: {} }; + }, + initialize() {}, + async authenticate() { + return { result: {} }; + }, +}); diff --git a/plugins/auth-backend-module-guest-provider/src/index.ts b/plugins/auth-backend-module-guest-provider/src/index.ts new file mode 100644 index 0000000000..c6ada31c3a --- /dev/null +++ b/plugins/auth-backend-module-guest-provider/src/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * The guest-provider backend module for the auth plugin. + * + * @packageDocumentation + */ + +export { authModuleGuestProvider as default } from './module'; diff --git a/plugins/auth-backend-module-guest-provider/src/module.ts b/plugins/auth-backend-module-guest-provider/src/module.ts new file mode 100644 index 0000000000..7eac99b0a3 --- /dev/null +++ b/plugins/auth-backend-module-guest-provider/src/module.ts @@ -0,0 +1,56 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + coreServices, + createBackendModule, +} from '@backstage/backend-plugin-api'; +import { + authProvidersExtensionPoint, + createProxyAuthProviderFactory, +} from '@backstage/plugin-auth-node'; +import { guestAuthenticator } from './authenticator'; +import { signInAsGuestUser } from './resolvers'; + +/** @public */ +export const authModuleGuestProvider = createBackendModule({ + pluginId: 'auth', + moduleId: 'guest-provider', + register(reg) { + reg.registerInit({ + deps: { + logger: coreServices.logger, + providers: authProvidersExtensionPoint, + config: coreServices.rootConfig, + }, + async init({ providers, logger, config }) { + if (process.env.NODE_ENV !== 'development') { + logger.warn( + 'You should NOT be using the guest provider outside of a development environment.', + ); + } + providers.registerProvider({ + providerId: 'guest', + factory: createProxyAuthProviderFactory({ + authenticator: guestAuthenticator, + signInResolver: signInAsGuestUser( + config.getConfig('auth.providers.guest'), + ), + }), + }); + }, + }); + }, +}); diff --git a/plugins/auth-backend-module-guest-provider/src/resolvers.ts b/plugins/auth-backend-module-guest-provider/src/resolvers.ts new file mode 100644 index 0000000000..35f724f746 --- /dev/null +++ b/plugins/auth-backend-module-guest-provider/src/resolvers.ts @@ -0,0 +1,59 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { stringifyEntityRef } from '@backstage/catalog-model'; +import type { Config } from '@backstage/config'; +import { SignInResolver } from '@backstage/plugin-auth-node'; +import { NotImplementedError } from '@backstage/errors'; + +/** + * Provide a default implementation of the user to resolve to. By default, this + * is `user:development/guest`. We will attempt to get that user if they're in the + * catalog. If that user doesn't exist in the catalog, we will still create a + * token for them so they can keep viewing. + */ +export const signInAsGuestUser: (config: Config) => SignInResolver<{}> = + (config: Config) => async (_, ctx) => { + if ( + process.env.NODE_ENV !== 'development' && + config.getOptionalBoolean('dangerouslyAllowOutsideDevelopment') !== true + ) { + throw new NotImplementedError( + 'The guest provider is NOT recommended for use outside of a development environment. If you want to enable this, set `auth.providers.guest.dangerouslyAllowOutsideDevelopment: true` in your app config.', + ); + } + const userRef = + config.getOptionalString('userEntityRef') ?? + stringifyEntityRef({ + kind: 'user', + namespace: 'development', + name: 'guest', + }); + const ownershipRefs = config.getOptionalStringArray( + 'ownershipEntityRefs', + ) ?? [userRef]; + try { + return ctx.signInWithCatalogUser({ entityRef: userRef }); + } catch (err) { + // We can't guarantee that a guest user exists in the catalog, so we issue a token directly, + return ctx.issueToken({ + claims: { + sub: userRef, + ent: ownershipRefs, + }, + }); + } + }; diff --git a/plugins/auth-backend-module-guest-provider/src/types.ts b/plugins/auth-backend-module-guest-provider/src/types.ts new file mode 100644 index 0000000000..c831014cb5 --- /dev/null +++ b/plugins/auth-backend-module-guest-provider/src/types.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ProfileTransform } from '@backstage/plugin-auth-node'; + +export interface GuestAuthenticator { + defaultProfileTransform: ProfileTransform<{}>; +} diff --git a/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md b/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md index ac4f11ec6a..993ddfbad5 100644 --- a/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-backend-module-microsoft-provider +## 0.1.8-next.0 + +### Patch Changes + +- 2af5354: Bump dependency `jose` to v5 +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + ## 0.1.5 ### Patch Changes diff --git a/plugins/auth-backend-module-microsoft-provider/package.json b/plugins/auth-backend-module-microsoft-provider/package.json index 028b77f88a..0a9a97cc9d 100644 --- a/plugins/auth-backend-module-microsoft-provider/package.json +++ b/plugins/auth-backend-module-microsoft-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-microsoft-provider", "description": "The microsoft-provider backend module for the auth plugin.", - "version": "0.1.5", + "version": "0.1.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md b/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md index 1f2f90949b..ad5fe30ef1 100644 --- a/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-auth-backend-module-oauth2-provider +## 0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + ## 0.1.7 ### Patch Changes diff --git a/plugins/auth-backend-module-oauth2-provider/package.json b/plugins/auth-backend-module-oauth2-provider/package.json index 007c160c62..79efd86c23 100644 --- a/plugins/auth-backend-module-oauth2-provider/package.json +++ b/plugins/auth-backend-module-oauth2-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-oauth2-provider", "description": "The oauth2-provider backend module for the auth plugin.", - "version": "0.1.7", + "version": "0.1.10-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/CHANGELOG.md b/plugins/auth-backend-module-oauth2-proxy-provider/CHANGELOG.md index edd7670633..0a99aa33bf 100644 --- a/plugins/auth-backend-module-oauth2-proxy-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-oauth2-proxy-provider/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-auth-backend-module-oauth2-proxy-provider +## 0.1.6-next.0 + +### Patch Changes + +- 2af5354: Bump dependency `jose` to v5 +- e77d7a9: Internal refactor to avoid deprecated method. +- b1b012d: Fix issue with `providerInfo` not being set properly for some proxy providers, by making `providerInfo` an explicit optional return from `authenticate` +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + ## 0.1.2 ### Patch Changes diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/package.json b/plugins/auth-backend-module-oauth2-proxy-provider/package.json index 26e2f0d4ff..f1ed2db494 100644 --- a/plugins/auth-backend-module-oauth2-proxy-provider/package.json +++ b/plugins/auth-backend-module-oauth2-proxy-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-oauth2-proxy-provider", "description": "The oauth2-proxy-provider backend module for the auth plugin.", - "version": "0.1.2", + "version": "0.1.6-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-oidc-provider/CHANGELOG.md b/plugins/auth-backend-module-oidc-provider/CHANGELOG.md index b986cb78ca..bd43325f7b 100644 --- a/plugins/auth-backend-module-oidc-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-oidc-provider/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-auth-backend-module-oidc-provider +## 0.1.3-next.0 + +### Patch Changes + +- 2af5354: Bump dependency `jose` to v5 +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-auth-backend@0.22.0-next.0 + ## 0.1.0 ### Minor Changes diff --git a/plugins/auth-backend-module-oidc-provider/package.json b/plugins/auth-backend-module-oidc-provider/package.json index 24cad9cec4..46eb7d1f99 100644 --- a/plugins/auth-backend-module-oidc-provider/package.json +++ b/plugins/auth-backend-module-oidc-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-oidc-provider", "description": "The oidc-provider backend module for the auth plugin.", - "version": "0.1.0", + "version": "0.1.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-okta-provider/CHANGELOG.md b/plugins/auth-backend-module-okta-provider/CHANGELOG.md index c0b4ceca51..aeb7317627 100644 --- a/plugins/auth-backend-module-okta-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-okta-provider/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-auth-backend-module-okta-provider +## 0.0.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + ## 0.0.3 ### Patch Changes diff --git a/plugins/auth-backend-module-okta-provider/package.json b/plugins/auth-backend-module-okta-provider/package.json index dfcab1cdcb..8e765fc51c 100644 --- a/plugins/auth-backend-module-okta-provider/package.json +++ b/plugins/auth-backend-module-okta-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-okta-provider", "description": "The okta-provider backend module for the auth plugin.", - "version": "0.0.3", + "version": "0.0.6-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md b/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md index be35f8d79e..68752b1842 100644 --- a/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-auth-backend-module-pinniped-provider +## 0.1.7-next.0 + +### Patch Changes + +- 2af5354: Bump dependency `jose` to v5 +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.1.4 ### Patch Changes diff --git a/plugins/auth-backend-module-pinniped-provider/package.json b/plugins/auth-backend-module-pinniped-provider/package.json index 9581cb132b..fa35804afc 100644 --- a/plugins/auth-backend-module-pinniped-provider/package.json +++ b/plugins/auth-backend-module-pinniped-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-pinniped-provider", "description": "The pinniped-provider backend module for the auth plugin.", - "version": "0.1.4", + "version": "0.1.7-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-vmware-cloud-provider/CHANGELOG.md b/plugins/auth-backend-module-vmware-cloud-provider/CHANGELOG.md index 3bd1a3f2f7..1340932a92 100644 --- a/plugins/auth-backend-module-vmware-cloud-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-vmware-cloud-provider/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-auth-backend-module-vmware-cloud-provider +## 0.1.5-next.0 + +### Patch Changes + +- 2af5354: Bump dependency `jose` to v5 +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/catalog-model@1.4.5-next.0 + ## 0.1.2 ### Patch Changes diff --git a/plugins/auth-backend-module-vmware-cloud-provider/package.json b/plugins/auth-backend-module-vmware-cloud-provider/package.json index 841709b7ed..f4b66838ec 100644 --- a/plugins/auth-backend-module-vmware-cloud-provider/package.json +++ b/plugins/auth-backend-module-vmware-cloud-provider/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend-module-vmware-cloud-provider", - "version": "0.1.2", + "version": "0.1.5-next.0", "description": "The vmware-cloud-provider backend module for the auth plugin.", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index e2532247cc..c854cc958f 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-auth-backend +## 0.22.0-next.0 + +### Minor Changes + +- 293c835: Add support for Service Tokens to Cloudflare Access auth provider +- 492fe83: **BREAKING**: The `CatalogIdentityClient` constructor now also requires the `discovery` service to be forwarded from the plugin environment. This is part of the migration to support the new auth services, which has also been done for the `createRouter` function. + +### Patch Changes + +- 999224f: Bump dependency `minimatch` to v9 +- 2af5354: Bump dependency `jose` to v5 +- 38af71a: Updated dependency `google-auth-library` to `^9.0.0`. +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- fa7ea3f: Internal refactor to break out how the router is constructed +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.6-next.0 + - @backstage/plugin-auth-backend-module-microsoft-provider@0.1.8-next.0 + - @backstage/plugin-auth-backend-module-aws-alb-provider@0.1.4-next.0 + - @backstage/plugin-auth-backend-module-oidc-provider@0.1.3-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.8-next.0 + - @backstage/plugin-auth-backend-module-google-provider@0.1.10-next.0 + - @backstage/plugin-auth-backend-module-atlassian-provider@0.1.5-next.0 + - @backstage/plugin-auth-backend-module-github-provider@0.1.10-next.0 + - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.10-next.0 + - @backstage/plugin-auth-backend-module-oauth2-provider@0.1.10-next.0 + - @backstage/plugin-auth-backend-module-okta-provider@0.0.6-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + ## 0.21.0 ### Minor Changes diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 456cc18af2..244b507027 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend", - "version": "0.21.0", + "version": "0.22.0-next.0", "description": "A Backstage backend plugin that handles authentication", "backstage": { "role": "backend-plugin" diff --git a/plugins/auth-node/CHANGELOG.md b/plugins/auth-node/CHANGELOG.md index 4f7b578234..72a978dc75 100644 --- a/plugins/auth-node/CHANGELOG.md +++ b/plugins/auth-node/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-auth-node +## 0.4.8-next.0 + +### Patch Changes + +- b4fc6e3: Deprecated the `getBearerTokenFromAuthorizationHeader` function, which is being replaced by the new `HttpAuthService`. +- 2af5354: Bump dependency `jose` to v5 +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- b1b012d: Fix issue with `providerInfo` not being set properly for some proxy providers, by making `providerInfo` an explicit optional return from `authenticate` +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + ## 0.4.4 ### Patch Changes diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index 7830126365..dc6ad90a9b 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-node", - "version": "0.4.4", + "version": "0.4.8-next.0", "backstage": { "role": "node-library" }, diff --git a/plugins/azure-devops-backend/CHANGELOG.md b/plugins/azure-devops-backend/CHANGELOG.md index ca401bb067..68585d47fe 100644 --- a/plugins/azure-devops-backend/CHANGELOG.md +++ b/plugins/azure-devops-backend/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-azure-devops-backend +## 0.6.0-next.0 + +### Minor Changes + +- 9fdb86a: Ability to fetch the README file from a different Azure DevOps path. + + Defaults to the current, Azure DevOps default behaviour (`README.md` in the root of the git repo); to use a different path, add the annotation `dev.azure.com/readme-path` + + Example: + + ```yaml + dev.azure.com/readme-path: /my-path/README.md + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-azure-devops-common@0.4.0-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + ## 0.5.2 ### Patch Changes diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index 2d5300a62a..9741177692 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.5.2", + "version": "0.6.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops-common/CHANGELOG.md b/plugins/azure-devops-common/CHANGELOG.md index 1709b96073..d80c9d36ab 100644 --- a/plugins/azure-devops-common/CHANGELOG.md +++ b/plugins/azure-devops-common/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-azure-devops-common +## 0.4.0-next.0 + +### Minor Changes + +- 9fdb86a: Ability to fetch the README file from a different Azure DevOps path. + + Defaults to the current, Azure DevOps default behaviour (`README.md` in the root of the git repo); to use a different path, add the annotation `dev.azure.com/readme-path` + + Example: + + ```yaml + dev.azure.com/readme-path: /my-path/README.md + ``` + ## 0.3.2 ### Patch Changes diff --git a/plugins/azure-devops-common/package.json b/plugins/azure-devops-common/package.json index 21e9245e38..23a575f95e 100644 --- a/plugins/azure-devops-common/package.json +++ b/plugins/azure-devops-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops-common", - "version": "0.3.2", + "version": "0.4.0-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 10d864ec6c..aae12231c2 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-azure-devops +## 0.4.0-next.0 + +### Minor Changes + +- 9fdb86a: Ability to fetch the README file from a different Azure DevOps path. + + Defaults to the current, Azure DevOps default behaviour (`README.md` in the root of the git repo); to use a different path, add the annotation `dev.azure.com/readme-path` + + Example: + + ```yaml + dev.azure.com/readme-path: /my-path/README.md + ``` + +- a9e7bd6: **BREAKING** The `AzureDevOpsClient` no longer requires `identityAPi` but now requires `fetchApi`. + + Updated to use `fetchApi` as per [ADR013](https://backstage.io/docs/architecture-decisions/adrs-adr013) + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-azure-devops-common@0.4.0-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + ## 0.3.12 ### Patch Changes diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index 356d19cea0..12860d82cc 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops", - "version": "0.3.12", + "version": "0.4.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites-backend/CHANGELOG.md b/plugins/azure-sites-backend/CHANGELOG.md index 695de81aa0..dee6841c25 100644 --- a/plugins/azure-sites-backend/CHANGELOG.md +++ b/plugins/azure-sites-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-azure-sites-backend +## 0.3.0-next.0 + +### Minor Changes + +- 6b802a2: **BREAKING**: The `createRouter` method now requires the `discovery` service to be forwarded from the plugin environment. This is part of the migration to support new auth services. + +### Patch Changes + +- 85db926: Added new backend system for the Azure Sites backend plugin +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-azure-sites-common@0.1.3-next.0 + ## 0.2.0 ### Minor Changes diff --git a/plugins/azure-sites-backend/package.json b/plugins/azure-sites-backend/package.json index 46cd4a5e79..ee03a221a1 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.2.0", + "version": "0.3.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites-backend/src/plugin.ts b/plugins/azure-sites-backend/src/plugin.ts index 90a9c416bd..a8afe4e430 100644 --- a/plugins/azure-sites-backend/src/plugin.ts +++ b/plugins/azure-sites-backend/src/plugin.ts @@ -36,9 +36,21 @@ export const azureSitesPlugin = createBackendPlugin({ logger: coreServices.logger, httpRouter: coreServices.httpRouter, permissions: coreServices.permissions, + discovery: coreServices.discovery, + auth: coreServices.auth, + httpAuth: coreServices.httpAuth, catalogApi: catalogServiceRef, }, - async init({ config, logger, httpRouter, permissions, catalogApi }) { + async init({ + config, + logger, + httpRouter, + permissions, + catalogApi, + discovery, + auth, + httpAuth, + }) { const azureSitesApi = AzureSitesApi.fromConfig(config); httpRouter.use( await createRouter({ @@ -46,6 +58,9 @@ export const azureSitesPlugin = createBackendPlugin({ azureSitesApi, permissions, catalogApi, + discovery, + auth, + httpAuth, }), ); }, diff --git a/plugins/azure-sites-common/CHANGELOG.md b/plugins/azure-sites-common/CHANGELOG.md index 41194fb653..0561e060cb 100644 --- a/plugins/azure-sites-common/CHANGELOG.md +++ b/plugins/azure-sites-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-azure-sites-common +## 0.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + ## 0.1.2 ### Patch Changes diff --git a/plugins/azure-sites-common/package.json b/plugins/azure-sites-common/package.json index 6b3ec694a1..a324d335a6 100644 --- a/plugins/azure-sites-common/package.json +++ b/plugins/azure-sites-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-sites-common", - "version": "0.1.2", + "version": "0.1.3-next.0", "description": "Common functionalities for the azure plugin", "backstage": { "role": "common-library" diff --git a/plugins/azure-sites/CHANGELOG.md b/plugins/azure-sites/CHANGELOG.md index 9761f8062c..5ee251a623 100644 --- a/plugins/azure-sites/CHANGELOG.md +++ b/plugins/azure-sites/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-azure-sites +## 0.1.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-azure-sites-common@0.1.3-next.0 + - @backstage/plugin-permission-react@0.4.21-next.0 + ## 0.1.19 ### Patch Changes diff --git a/plugins/azure-sites/package.json b/plugins/azure-sites/package.json index f1a4e81e9b..5f99e77891 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.19", + "version": "0.1.20-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/badges-backend/CHANGELOG.md b/plugins/badges-backend/CHANGELOG.md index fb05d58184..d9236a71ed 100644 --- a/plugins/badges-backend/CHANGELOG.md +++ b/plugins/badges-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-badges-backend +## 0.3.10-next.0 + +### Patch Changes + +- 29a1f91: Migrated to support new auth services. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.3.7 ### Patch Changes diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index 9c87360a2a..4fd39c0356 100644 --- a/plugins/badges-backend/package.json +++ b/plugins/badges-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-badges-backend", - "version": "0.3.7", + "version": "0.3.10-next.0", "description": "A Backstage backend plugin that generates README badges for your entities", "backstage": { "role": "backend-plugin" diff --git a/plugins/badges/CHANGELOG.md b/plugins/badges/CHANGELOG.md index 2d3f5ad46c..481f79ef2e 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-badges +## 0.2.55-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.2.54 ### Patch Changes diff --git a/plugins/badges/package.json b/plugins/badges/package.json index 0dc5fb81a5..e23f78911f 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-badges", - "version": "0.2.54", + "version": "0.2.55-next.0", "description": "A Backstage plugin that generates README badges for your entities", "backstage": { "role": "frontend-plugin" diff --git a/plugins/badges/src/components/EntityBadgesDialog.test.tsx b/plugins/badges/src/components/EntityBadgesDialog.test.tsx index 5d0e7fe849..94efa1eec8 100644 --- a/plugins/badges/src/components/EntityBadgesDialog.test.tsx +++ b/plugins/badges/src/components/EntityBadgesDialog.test.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { Entity } from '@backstage/catalog-model'; -import { renderWithEffects, TestApiProvider } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { BadgesApi, badgesApiRef } from '../api'; import { EntityBadgesDialog } from './EntityBadgesDialog'; import { EntityProvider } from '@backstage/plugin-catalog-react'; @@ -43,7 +43,7 @@ describe('EntityBadgesDialog', () => { kind: 'MockKind', } as Entity; - const rendered = await renderWithEffects( + const rendered = await renderInTestApp( ({ describe('BitriseArtifactsComponent', () => { entityValue = { entity: { metadata: {} } }; - const renderComponent = () => render(); + const renderComponent = () => renderInTestApp(); it('should display an empty state if an app annotation is missing', async () => { - const rendered = renderComponent(); + const rendered = await renderComponent(); expect(await rendered.findByText('Missing Annotation')).toBeInTheDocument(); }); diff --git a/plugins/catalog-backend-module-aws/CHANGELOG.md b/plugins/catalog-backend-module-aws/CHANGELOG.md index 0b43f3faee..13082e37c6 100644 --- a/plugins/catalog-backend-module-aws/CHANGELOG.md +++ b/plugins/catalog-backend-module-aws/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-catalog-backend-module-aws +## 0.3.7-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-kubernetes-common@0.7.5-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/integration-aws-node@0.1.10-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + ## 0.3.4 ### Patch Changes diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 19e4571d96..10f1621ebc 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-aws", - "version": "0.3.4", + "version": "0.3.7-next.0", "description": "A Backstage catalog backend module that helps integrate towards AWS", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/catalog-backend-module-azure/CHANGELOG.md b/plugins/catalog-backend-module-azure/CHANGELOG.md index 3a0264280d..9502769253 100644 --- a/plugins/catalog-backend-module-azure/CHANGELOG.md +++ b/plugins/catalog-backend-module-azure/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-backend-module-azure +## 0.1.32-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + ## 0.1.29 ### Patch Changes diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index 2d92d7284f..ba645a0414 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-azure", - "version": "0.1.29", + "version": "0.1.32-next.0", "description": "A Backstage catalog backend module that helps integrate towards Azure", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md b/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md index bb149cb885..c16a3b5564 100644 --- a/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-backend-module-backstage-openapi +## 0.1.6-next.0 + +### Patch Changes + +- 43a9ae1: Migrated to use new auth service. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-openapi-utils@0.1.6-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.1.3 ### Patch Changes diff --git a/plugins/catalog-backend-module-backstage-openapi/package.json b/plugins/catalog-backend-module-backstage-openapi/package.json index 3ce3ebd404..dde4e4f591 100644 --- a/plugins/catalog-backend-module-backstage-openapi/package.json +++ b/plugins/catalog-backend-module-backstage-openapi/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-backstage-openapi", - "version": "0.1.3", + "version": "0.1.6-next.0", "backstage": { "role": "backend-plugin-module" }, diff --git a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md index 2f7ee2408e..1a87a2393b 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,63 @@ # @backstage/plugin-catalog-backend-module-bitbucket-cloud +## 0.2.0-next.0 + +### Minor Changes + +- 9e527c9: BREAKING CHANGE: Migrates the `BitbucketCloudEntityProvider` to use the `EventsService`; fix new backend system support. + + `BitbucketCloudEntityProvider.fromConfig` accepts `events: EventsService` as optional argument to its `options`. + With provided `events`, the event-based updates/refresh will be available. + However, the `EventSubscriber` interface was removed including its `supportsEventTopics()` and `onEvent(params)`. + + The event subscription happens on `connect(connection)` if the `events` is available. + + **Migration:** + + ```diff + const bitbucketCloudProvider = BitbucketCloudEntityProvider.fromConfig( + env.config, + { + catalogApi: new CatalogClient({ discoveryApi: env.discovery }), + + events: env.events, + logger: env.logger, + scheduler: env.scheduler, + tokenManager: env.tokenManager, + }, + ); + - env.eventBroker.subscribe(bitbucketCloudProvider); + ``` + + **New Backend System:** + + Before this change, using this module with the new backend system was broken. + Now, you can add the catalog module for Bitbucket Cloud incl. event support backend. + Event support will always be enabled. + However, no updates/refresh will happen without receiving events. + + ```ts + backend.add( + import('@backstage/plugin-catalog-backend-module-bitbucket-cloud/alpha'), + ); + ``` + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/plugin-bitbucket-cloud-common@0.2.17-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + ## 0.1.25 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 441781331e..3bf4e8f8dd 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.25", + "version": "0.2.0-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 be62f12f96..bff0ca6a4c 100644 --- a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-backend-module-bitbucket-server +## 0.1.26-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.1.23 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index 795652603d..36f5033e7f 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.23", + "version": "0.1.26-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-gcp/CHANGELOG.md b/plugins/catalog-backend-module-gcp/CHANGELOG.md index c8f278f494..30f53ce23d 100644 --- a/plugins/catalog-backend-module-gcp/CHANGELOG.md +++ b/plugins/catalog-backend-module-gcp/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-backend-module-gcp +## 0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-kubernetes-common@0.7.5-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.1.10 ### Patch Changes diff --git a/plugins/catalog-backend-module-gcp/package.json b/plugins/catalog-backend-module-gcp/package.json index 64404eff32..cddb339d22 100644 --- a/plugins/catalog-backend-module-gcp/package.json +++ b/plugins/catalog-backend-module-gcp/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gcp", - "version": "0.1.10", + "version": "0.1.13-next.0", "description": "A Backstage catalog backend module that helps integrate towards GCP", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/catalog-backend-module-gerrit/CHANGELOG.md b/plugins/catalog-backend-module-gerrit/CHANGELOG.md index 4fee0317d0..b21ef08d98 100644 --- a/plugins/catalog-backend-module-gerrit/CHANGELOG.md +++ b/plugins/catalog-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-backend-module-gerrit +## 0.1.29-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.1.26 ### Patch Changes diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index b0c0ff81ea..9d00315717 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.26", + "version": "0.1.29-next.0", "backstage": { "role": "backend-plugin-module" }, diff --git a/plugins/catalog-backend-module-github-org/CHANGELOG.md b/plugins/catalog-backend-module-github-org/CHANGELOG.md index e4a4fa5902..89ed3e781c 100644 --- a/plugins/catalog-backend-module-github-org/CHANGELOG.md +++ b/plugins/catalog-backend-module-github-org/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-github-org +## 0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-catalog-backend-module-github@0.5.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.1.4 ### Patch Changes diff --git a/plugins/catalog-backend-module-github-org/package.json b/plugins/catalog-backend-module-github-org/package.json index 8f2b683e61..a73e1c83e6 100644 --- a/plugins/catalog-backend-module-github-org/package.json +++ b/plugins/catalog-backend-module-github-org/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-github-org", - "version": "0.1.4", + "version": "0.1.7-next.0", "description": "The github-org backend module for the catalog plugin.", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/catalog-backend-module-github/CHANGELOG.md b/plugins/catalog-backend-module-github/CHANGELOG.md index 2d6f30a5a9..9aebb866c2 100644 --- a/plugins/catalog-backend-module-github/CHANGELOG.md +++ b/plugins/catalog-backend-module-github/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-catalog-backend-module-github +## 0.5.3-next.0 + +### Patch Changes + +- a936a8f: Migrated the `GithubLocationAnalyzer` to support new auth services. +- 999224f: Bump dependency `minimatch` to v9 +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-backend@1.18.0-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + ## 0.5.0 ### Minor Changes diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index 6f3b933aa8..584b74502b 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-github", - "version": "0.5.0", + "version": "0.5.3-next.0", "description": "A Backstage catalog backend module that helps integrate towards GitHub", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/catalog-backend-module-gitlab/CHANGELOG.md b/plugins/catalog-backend-module-gitlab/CHANGELOG.md index ea85f7cef9..12a755d927 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.3.10-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.3.7 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index 76a20bd97f..dda161f657 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.3.7", + "version": "0.3.10-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md index a3e325c25f..f8cb905df0 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md +++ b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-catalog-backend-module-incremental-ingestion +## 0.4.17-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-backend@1.18.0-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.4.14 ### Patch Changes diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index 02963f6bc1..b3c7df02b4 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-incremental-ingestion", - "version": "0.4.14", + "version": "0.4.17-next.0", "description": "An entity provider for streaming large asset sources into the catalog", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index 2fc6f1f379..49444bdaa0 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.5.28-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.22-next.0 + ## 0.5.25 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index 7720e97aa6..54ecd7b737 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.25", + "version": "0.5.28-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 3f0cc568a4..9473525ad1 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.5.20-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + ## 0.5.17 ### Patch Changes diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index b2c09bf201..afa74aba92 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-msgraph", - "version": "0.5.17", + "version": "0.5.20-next.0", "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/catalog-backend-module-openapi/CHANGELOG.md b/plugins/catalog-backend-module-openapi/CHANGELOG.md index 3d44a724da..ca587bec3f 100644 --- a/plugins/catalog-backend-module-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-openapi/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-backend-module-openapi +## 0.1.30-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-backend@1.18.0-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.22-next.0 + ## 0.1.27 ### Patch Changes diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index dd7cdd487b..192a115b89 100644 --- a/plugins/catalog-backend-module-openapi/package.json +++ b/plugins/catalog-backend-module-openapi/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-openapi", - "version": "0.1.27", + "version": "0.1.30-next.0", "description": "A Backstage catalog backend module that helps with OpenAPI specifications", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md index add24532e0..617c243d53 100644 --- a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md +++ b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-backend-module-puppetdb +## 0.1.18-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + ## 0.1.15 ### Patch Changes diff --git a/plugins/catalog-backend-module-puppetdb/package.json b/plugins/catalog-backend-module-puppetdb/package.json index c971e58299..9be14331e4 100644 --- a/plugins/catalog-backend-module-puppetdb/package.json +++ b/plugins/catalog-backend-module-puppetdb/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-puppetdb", - "version": "0.1.15", + "version": "0.1.18-next.0", "description": "A Backstage catalog backend module that helps integrate towards PuppetDB", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md b/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md index 95689b70b4..7a7cfe753a 100644 --- a/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md +++ b/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-catalog-backend-module-scaffolder-entity-model +## 0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + - @backstage/plugin-scaffolder-common@1.5.1-next.0 + ## 0.1.7 ### Patch Changes diff --git a/plugins/catalog-backend-module-scaffolder-entity-model/package.json b/plugins/catalog-backend-module-scaffolder-entity-model/package.json index d3df44cea7..faeef643df 100644 --- a/plugins/catalog-backend-module-scaffolder-entity-model/package.json +++ b/plugins/catalog-backend-module-scaffolder-entity-model/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-scaffolder-entity-model", - "version": "0.1.7", + "version": "0.1.10-next.0", "description": "Adds support for the scaffolder specific entity model (e.g. the Template kind) to the catalog backend plugin.", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/catalog-backend-module-unprocessed/CHANGELOG.md b/plugins/catalog-backend-module-unprocessed/CHANGELOG.md index 73e67e9a96..cc16e4b51e 100644 --- a/plugins/catalog-backend-module-unprocessed/CHANGELOG.md +++ b/plugins/catalog-backend-module-unprocessed/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-backend-module-unprocessed +## 0.3.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/catalog-model@1.4.5-next.0 + ## 0.3.7 ### Patch Changes diff --git a/plugins/catalog-backend-module-unprocessed/package.json b/plugins/catalog-backend-module-unprocessed/package.json index d0b306fecc..f3126af9f8 100644 --- a/plugins/catalog-backend-module-unprocessed/package.json +++ b/plugins/catalog-backend-module-unprocessed/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-unprocessed", "description": "Backstage Catalog module to view unprocessed entities", - "version": "0.3.7", + "version": "0.3.10-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 3685a74c58..f1b09eb54c 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-catalog-backend +## 1.18.0-next.0 + +### Minor Changes + +- df12231: Allow setting EntityDataParser using CatalogModelExtensionPoint +- 15ba00f: Migrated to support new auth services. The `CatalogBuilder.create` method now accepts a `discovery` option, which is recommended to forward from the plugin environment, as it will otherwise fall back to use the `HostDiscovery` implementation. + +### Patch Changes + +- 999224f: Bump dependency `minimatch` to v9 +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- 280edeb: Add index for original value in search table for faster entity facet response +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/repo-tools@0.6.3-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.17-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-openapi-utils@0.1.6-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.22-next.0 + ## 1.17.0 ### Minor Changes diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index 92a2fbb280..ef2379766d 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -11,6 +11,7 @@ import { AnalyzeLocationGenerateEntity as AnalyzeLocationGenerateEntity_2 } from import { AnalyzeLocationRequest as AnalyzeLocationRequest_2 } from '@backstage/plugin-catalog-common'; import { AnalyzeLocationResponse as AnalyzeLocationResponse_2 } from '@backstage/plugin-catalog-common'; import { AnalyzeOptions as AnalyzeOptions_2 } from '@backstage/plugin-catalog-node'; +import { AuthService } from '@backstage/backend-plugin-api'; import { CatalogApi } from '@backstage/catalog-client'; import { CatalogCollatorEntityTransformer as CatalogCollatorEntityTransformer_2 } from '@backstage/plugin-search-backend-module-catalog'; import { CatalogEntityDocument } from '@backstage/plugin-catalog-common'; @@ -28,6 +29,7 @@ import { Config } from '@backstage/config'; import { DefaultCatalogCollatorFactory as DefaultCatalogCollatorFactory_2 } from '@backstage/plugin-search-backend-module-catalog'; import { DefaultCatalogCollatorFactoryOptions as DefaultCatalogCollatorFactoryOptions_2 } from '@backstage/plugin-search-backend-module-catalog'; import { DeferredEntity as DeferredEntity_2 } from '@backstage/plugin-catalog-node'; +import { DiscoveryService } from '@backstage/backend-plugin-api'; import { EntitiesSearchFilter as EntitiesSearchFilter_2 } from '@backstage/plugin-catalog-node'; import { Entity } from '@backstage/catalog-model'; import { EntityFilter as EntityFilter_2 } from '@backstage/plugin-catalog-node'; @@ -38,15 +40,16 @@ import { EntityProviderMutation as EntityProviderMutation_2 } from '@backstage/p import { EntityRelationSpec as EntityRelationSpec_2 } from '@backstage/plugin-catalog-node'; import { EventBroker } from '@backstage/plugin-events-node'; import { GetEntitiesRequest } from '@backstage/catalog-client'; +import { HttpAuthService } from '@backstage/backend-plugin-api'; import { LocationSpec as LocationSpec_2 } from '@backstage/plugin-catalog-common'; import { locationSpecToLocationEntity as locationSpecToLocationEntity_2 } from '@backstage/plugin-catalog-node'; import { locationSpecToMetadataName as locationSpecToMetadataName_2 } from '@backstage/plugin-catalog-node'; import { Logger } from 'winston'; import { Permission } from '@backstage/plugin-permission-common'; import { PermissionAuthorizer } from '@backstage/plugin-permission-common'; -import { PermissionEvaluator } from '@backstage/plugin-permission-common'; import { PermissionRule } from '@backstage/plugin-permission-node'; import { PermissionRuleParams } from '@backstage/plugin-permission-common'; +import { PermissionsService } from '@backstage/backend-plugin-api'; import { PlaceholderResolver as PlaceholderResolver_2 } from '@backstage/plugin-catalog-node'; import { PlaceholderResolverParams as PlaceholderResolverParams_2 } from '@backstage/plugin-catalog-node'; import { PlaceholderResolverRead as PlaceholderResolverRead_2 } from '@backstage/plugin-catalog-node'; @@ -189,8 +192,11 @@ export type CatalogEnvironment = { database: PluginDatabaseManager; config: Config; reader: UrlReader; - permissions: PermissionEvaluator | PermissionAuthorizer; + permissions: PermissionsService | PermissionAuthorizer; scheduler?: PluginTaskScheduler; + discovery?: DiscoveryService; + auth?: AuthService; + httpAuth?: HttpAuthService; }; // @public diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 7253f2db31..eff1c5838e 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.17.0", + "version": "1.18.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts index e9f5f154c2..9cc83098b3 100644 --- a/plugins/catalog-backend/src/catalog/types.ts +++ b/plugins/catalog-backend/src/catalog/types.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { BackstageCredentials } from '@backstage/backend-plugin-api'; import { Entity } from '@backstage/catalog-model'; import { EntityFilter } from '@backstage/plugin-catalog-node'; @@ -48,7 +49,7 @@ export type EntitiesRequest = { fields?: (entity: Entity) => Entity; order?: EntityOrder[]; pagination?: EntityPagination; - authorizationToken?: string; + credentials: BackstageCredentials; }; export type EntitiesResponse = { @@ -75,9 +76,9 @@ export interface EntitiesBatchRequest { */ fields?: (entity: Entity) => Entity; /** - * The optional token that authorizes the action. + * The credentials that authorizes the action. */ - authorizationToken?: string; + credentials: BackstageCredentials; } export interface EntitiesBatchResponse { @@ -115,9 +116,9 @@ export interface EntityFacetsRequest { */ facets: string[]; /** - * The optional token that authorizes the action. + * The credentials that authorizes the action. */ - authorizationToken?: string; + credentials: BackstageCredentials; } /** @@ -157,7 +158,7 @@ export interface EntitiesCatalog { */ removeEntityByUid( uid: string, - options?: { authorizationToken?: string }, + options: { credentials: BackstageCredentials }, ): Promise; /** @@ -167,7 +168,7 @@ export interface EntitiesCatalog { */ entityAncestry( entityRef: string, - options?: { authorizationToken?: string }, + options: { credentials: BackstageCredentials }, ): Promise; /** @@ -192,7 +193,7 @@ export type QueryEntitiesRequest = * for the current and the next pagination requests. */ export interface QueryEntitiesInitialRequest { - authorizationToken?: string; + credentials: BackstageCredentials; fields?: (entity: Entity) => Entity; limit?: number; filter?: EntityFilter; @@ -208,7 +209,7 @@ export interface QueryEntitiesInitialRequest { * move forward or backward on the data. */ export interface QueryEntitiesCursorRequest { - authorizationToken?: string; + credentials: BackstageCredentials; fields?: (entity: Entity) => Entity; limit?: number; cursor: Cursor; diff --git a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts index 4fe0311fff..3e2dee7ae0 100644 --- a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts @@ -23,6 +23,7 @@ import { AuthorizedEntitiesCatalog } from './AuthorizedEntitiesCatalog'; import { Cursor, QueryEntitiesResponse } from '../catalog/types'; import { Entity } from '@backstage/catalog-model'; import { EntityFilter } from '@backstage/plugin-catalog-node'; +import { mockCredentials } from '@backstage/backend-test-utils'; describe('AuthorizedEntitiesCatalog', () => { const fakeCatalog = { @@ -60,7 +61,7 @@ describe('AuthorizedEntitiesCatalog', () => { expect( await catalog.entities({ - authorizationToken: 'abcd', + credentials: mockCredentials.none(), }), ).toEqual({ entities: [], @@ -77,10 +78,10 @@ describe('AuthorizedEntitiesCatalog', () => { ]); const catalog = createCatalog(isEntityKind); - await catalog.entities({ authorizationToken: 'abcd' }); + await catalog.entities({ credentials: mockCredentials.none() }); expect(fakeCatalog.entities).toHaveBeenCalledWith({ - authorizationToken: 'abcd', + credentials: mockCredentials.none(), filter: { key: 'kind', values: ['b'] }, }); }); @@ -91,10 +92,10 @@ describe('AuthorizedEntitiesCatalog', () => { ]); const catalog = createCatalog(); - await catalog.entities({ authorizationToken: 'abcd' }); + await catalog.entities({ credentials: mockCredentials.none() }); expect(fakeCatalog.entities).toHaveBeenCalledWith({ - authorizationToken: 'abcd', + credentials: mockCredentials.none(), }); }); }); @@ -109,7 +110,7 @@ describe('AuthorizedEntitiesCatalog', () => { await expect( catalog.entitiesBatch({ entityRefs: ['component:default/component-a'], - authorizationToken: 'abcd', + credentials: mockCredentials.none(), }), ).resolves.toEqual({ items: [null], @@ -132,12 +133,12 @@ describe('AuthorizedEntitiesCatalog', () => { await catalog.entitiesBatch({ entityRefs: ['component:default/component-a'], - authorizationToken: 'abcd', + credentials: mockCredentials.none(), }); expect(fakeCatalog.entitiesBatch).toHaveBeenCalledWith({ entityRefs: ['component:default/component-a'], - authorizationToken: 'abcd', + credentials: mockCredentials.none(), filter: { key: 'kind', values: ['b'] }, }); }); @@ -150,12 +151,12 @@ describe('AuthorizedEntitiesCatalog', () => { await catalog.entitiesBatch({ entityRefs: ['component:default/component-a'], - authorizationToken: 'abcd', + credentials: mockCredentials.none(), }); expect(fakeCatalog.entitiesBatch).toHaveBeenCalledWith({ entityRefs: ['component:default/component-a'], - authorizationToken: 'abcd', + credentials: mockCredentials.none(), }); }); }); @@ -169,7 +170,7 @@ describe('AuthorizedEntitiesCatalog', () => { await expect( catalog.queryEntities({ - authorizationToken: 'abcd', + credentials: mockCredentials.none(), filter: { key: 'kind', values: ['b'] }, }), ).resolves.toEqual({ @@ -188,12 +189,12 @@ describe('AuthorizedEntitiesCatalog', () => { const catalog = createCatalog(); await catalog.queryEntities({ - authorizationToken: 'abcd', + credentials: mockCredentials.none(), filter: { key: 'kind', values: ['b'] }, }); expect(fakeCatalog.queryEntities).toHaveBeenCalledWith({ - authorizationToken: 'abcd', + credentials: mockCredentials.none(), filter: { key: 'kind', values: ['b'] }, }); }); @@ -243,12 +244,12 @@ describe('AuthorizedEntitiesCatalog', () => { const catalog = createCatalog(isEntityKind); let response = await catalog.queryEntities({ - authorizationToken: 'abcd', + credentials: mockCredentials.none(), filter: { key: 'name', values: ['name'] }, }); expect(fakeCatalog.queryEntities).toHaveBeenCalledWith({ - authorizationToken: 'abcd', + credentials: mockCredentials.none(), filter: { allOf: [{ key: 'kind', values: ['b'] }, requestFilter] }, }); @@ -276,12 +277,12 @@ describe('AuthorizedEntitiesCatalog', () => { orderFieldValues: ['a', null], }; response = await catalog.queryEntities({ - authorizationToken: 'abcd', + credentials: mockCredentials.none(), cursor, }); expect(fakeCatalog.queryEntities).toHaveBeenNthCalledWith(2, { - authorizationToken: 'abcd', + credentials: mockCredentials.none(), cursor: { ...cursor, filter: { allOf: [{ key: 'kind', values: ['b'] }, requestFilter] }, @@ -324,7 +325,9 @@ describe('AuthorizedEntitiesCatalog', () => { ); await expect(() => - catalog.removeEntityByUid('uid', { authorizationToken: 'abcd' }), + catalog.removeEntityByUid('uid', { + credentials: mockCredentials.none(), + }), ).rejects.toThrow(NotAllowedError); }); @@ -343,7 +346,9 @@ describe('AuthorizedEntitiesCatalog', () => { ); await expect(() => - catalog.removeEntityByUid('uid', { authorizationToken: 'abcd' }), + catalog.removeEntityByUid('uid', { + credentials: mockCredentials.none(), + }), ).rejects.toThrow(NotAllowedError); }); @@ -363,9 +368,13 @@ describe('AuthorizedEntitiesCatalog', () => { createConditionTransformer([isEntityKind]), ); - await catalog.removeEntityByUid('uid', { authorizationToken: 'abcd' }); + await catalog.removeEntityByUid('uid', { + credentials: mockCredentials.none(), + }); - expect(fakeCatalog.removeEntityByUid).toHaveBeenCalledWith('uid'); + expect(fakeCatalog.removeEntityByUid).toHaveBeenCalledWith('uid', { + credentials: mockCredentials.none(), + }); }); it('calls underlying catalog method on ALLOW', async () => { @@ -383,9 +392,13 @@ describe('AuthorizedEntitiesCatalog', () => { createConditionTransformer([]), ); - await catalog.removeEntityByUid('uid', { authorizationToken: 'abcd' }); + await catalog.removeEntityByUid('uid', { + credentials: mockCredentials.none(), + }); - expect(fakeCatalog.removeEntityByUid).toHaveBeenCalledWith('uid'); + expect(fakeCatalog.removeEntityByUid).toHaveBeenCalledWith('uid', { + credentials: mockCredentials.none(), + }); }); }); @@ -398,7 +411,7 @@ describe('AuthorizedEntitiesCatalog', () => { await expect(() => catalog.entityAncestry('backstage:default/component', { - authorizationToken: 'Bearer abcd', + credentials: mockCredentials.none(), }), ).rejects.toThrow(NotAllowedError); }); @@ -443,7 +456,7 @@ describe('AuthorizedEntitiesCatalog', () => { const ancestryResult = await catalog.entityAncestry( 'backstage:default/a', - { authorizationToken: 'Bearer abcd' }, + { credentials: mockCredentials.none() }, ); expect(ancestryResult).toEqual({ @@ -476,7 +489,7 @@ describe('AuthorizedEntitiesCatalog', () => { expect( await catalog.facets({ facets: ['a'], - authorizationToken: 'abcd', + credentials: mockCredentials.none(), }), ).toEqual({ facets: { a: [] }, @@ -492,11 +505,14 @@ describe('AuthorizedEntitiesCatalog', () => { ]); const catalog = createCatalog(isEntityKind); - await catalog.facets({ facets: ['a'], authorizationToken: 'abcd' }); + await catalog.facets({ + facets: ['a'], + credentials: mockCredentials.none(), + }); expect(fakeCatalog.facets).toHaveBeenCalledWith({ facets: ['a'], - authorizationToken: 'abcd', + credentials: mockCredentials.none(), filter: { key: 'kind', values: ['b'] }, }); }); @@ -507,11 +523,14 @@ describe('AuthorizedEntitiesCatalog', () => { ]); const catalog = createCatalog(); - await catalog.facets({ facets: ['a'], authorizationToken: 'abcd' }); + await catalog.facets({ + facets: ['a'], + credentials: mockCredentials.none(), + }); expect(fakeCatalog.facets).toHaveBeenCalledWith({ facets: ['a'], - authorizationToken: 'abcd', + credentials: mockCredentials.none(), }); }); }); diff --git a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts index f302a2b75a..5358e90825 100644 --- a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts @@ -20,10 +20,7 @@ import { catalogEntityReadPermission, } from '@backstage/plugin-catalog-common/alpha'; import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; -import { - AuthorizeResult, - PermissionEvaluator, -} from '@backstage/plugin-permission-common'; +import { AuthorizeResult } from '@backstage/plugin-permission-common'; import { ConditionTransformer } from '@backstage/plugin-permission-node'; import { Cursor, @@ -41,19 +38,23 @@ import { import { basicEntityFilter } from './request'; import { isQueryEntitiesCursorRequest } from './util'; import { EntityFilter } from '@backstage/plugin-catalog-node'; +import { + BackstageCredentials, + PermissionsService, +} from '@backstage/backend-plugin-api'; export class AuthorizedEntitiesCatalog implements EntitiesCatalog { constructor( private readonly entitiesCatalog: EntitiesCatalog, - private readonly permissionApi: PermissionEvaluator, + private readonly permissionApi: PermissionsService, private readonly transformConditions: ConditionTransformer, ) {} - async entities(request?: EntitiesRequest): Promise { + async entities(request: EntitiesRequest): Promise { const authorizeDecision = ( await this.permissionApi.authorizeConditional( [{ permission: catalogEntityReadPermission }], - { token: request?.authorizationToken }, + { credentials: request.credentials }, ) )[0]; @@ -85,7 +86,7 @@ export class AuthorizedEntitiesCatalog implements EntitiesCatalog { const authorizeDecision = ( await this.permissionApi.authorizeConditional( [{ permission: catalogEntityReadPermission }], - { token: request?.authorizationToken }, + { credentials: request.credentials }, ) )[0]; @@ -116,7 +117,7 @@ export class AuthorizedEntitiesCatalog implements EntitiesCatalog { const authorizeDecision = ( await this.permissionApi.authorizeConditional( [{ permission: catalogEntityReadPermission }], - { token: request.authorizationToken }, + { credentials: request.credentials }, ) )[0]; @@ -186,12 +187,12 @@ export class AuthorizedEntitiesCatalog implements EntitiesCatalog { async removeEntityByUid( uid: string, - options?: { authorizationToken?: string }, + options: { credentials: BackstageCredentials }, ): Promise { const authorizeResponse = ( await this.permissionApi.authorizeConditional( [{ permission: catalogEntityDeletePermission }], - { token: options?.authorizationToken }, + { credentials: options.credentials }, ) )[0]; if (authorizeResponse.result === AuthorizeResult.DENY) { @@ -202,6 +203,7 @@ export class AuthorizedEntitiesCatalog implements EntitiesCatalog { authorizeResponse.conditions, ); const { entities } = await this.entitiesCatalog.entities({ + credentials: options.credentials, filter: { allOf: [permissionFilter, basicEntityFilter({ 'metadata.uid': uid })], }, @@ -210,30 +212,35 @@ export class AuthorizedEntitiesCatalog implements EntitiesCatalog { throw new NotAllowedError(); } } - return this.entitiesCatalog.removeEntityByUid(uid); + return this.entitiesCatalog.removeEntityByUid(uid, { + credentials: options.credentials, + }); } async entityAncestry( entityRef: string, - options?: { authorizationToken?: string }, + options: { credentials: BackstageCredentials }, ): Promise { const rootEntityAuthorizeResponse = ( await this.permissionApi.authorize( [{ permission: catalogEntityReadPermission, resourceRef: entityRef }], - { token: options?.authorizationToken }, + { credentials: options.credentials }, ) )[0]; if (rootEntityAuthorizeResponse.result === AuthorizeResult.DENY) { throw new NotAllowedError(); } - const ancestryResult = await this.entitiesCatalog.entityAncestry(entityRef); + const ancestryResult = await this.entitiesCatalog.entityAncestry( + entityRef, + { credentials: options.credentials }, + ); const authorizeResponse = await this.permissionApi.authorize( ancestryResult.items.map(item => ({ permission: catalogEntityReadPermission, resourceRef: stringifyEntityRef(item.entity), })), - { token: options?.authorizationToken }, + { credentials: options.credentials }, ); const unauthorizedAncestryItems = ancestryResult.items.filter( (_, index) => authorizeResponse[index].result === AuthorizeResult.DENY, @@ -268,7 +275,7 @@ export class AuthorizedEntitiesCatalog implements EntitiesCatalog { const authorizeDecision = ( await this.permissionApi.authorizeConditional( [{ permission: catalogEntityReadPermission }], - { token: request?.authorizationToken }, + { credentials: request.credentials }, ) )[0]; diff --git a/plugins/catalog-backend/src/service/AuthorizedLocationService.test.ts b/plugins/catalog-backend/src/service/AuthorizedLocationService.test.ts index c2ffee8003..2eae1c7553 100644 --- a/plugins/catalog-backend/src/service/AuthorizedLocationService.test.ts +++ b/plugins/catalog-backend/src/service/AuthorizedLocationService.test.ts @@ -17,6 +17,7 @@ import { NotAllowedError, NotFoundError } from '@backstage/errors'; import { AuthorizeResult } from '@backstage/plugin-permission-common'; import { AuthorizedLocationService } from './AuthorizedLocationService'; +import { mockCredentials } from '@backstage/backend-test-utils'; describe('AuthorizedLocationService', () => { const fakeLocationService = { @@ -45,6 +46,10 @@ describe('AuthorizedLocationService', () => { const createService = () => new AuthorizedLocationService(fakeLocationService, fakePermissionApi); + const mockOptions = { + credentials: mockCredentials.none(), + }; + afterEach(() => { jest.resetAllMocks(); }); @@ -55,13 +60,12 @@ describe('AuthorizedLocationService', () => { const service = createService(); const spec = { type: 'type', target: 'target' }; - await service.createLocation(spec, false, { - authorizationToken: 'Bearer authtoken', - }); + await service.createLocation(spec, false, mockOptions); expect(fakeLocationService.createLocation).toHaveBeenCalledWith( spec, false, + mockOptions, ); }); @@ -71,9 +75,7 @@ describe('AuthorizedLocationService', () => { const spec = { type: 'type', target: 'target' }; await expect(() => - service.createLocation(spec, false, { - authorizationToken: 'Bearer authtoken', - }), + service.createLocation(spec, false, mockOptions), ).rejects.toThrow(NotAllowedError); }); }); @@ -83,7 +85,7 @@ describe('AuthorizedLocationService', () => { mockAllow(); const service = createService(); - await service.listLocations({ authorizationToken: 'Bearer authtoken' }); + await service.listLocations(mockOptions); expect(fakeLocationService.listLocations).toHaveBeenCalled(); }); @@ -92,9 +94,7 @@ describe('AuthorizedLocationService', () => { mockDeny(); const service = createService(); - const locations = await service.listLocations({ - authorizationToken: 'Bearer authtoken', - }); + const locations = await service.listLocations(mockOptions); expect(locations).toEqual([]); }); @@ -105,11 +105,12 @@ describe('AuthorizedLocationService', () => { mockAllow(); const service = createService(); - await service.getLocation('id', { - authorizationToken: 'Bearer authtoken', - }); + await service.getLocation('id', mockOptions); - expect(fakeLocationService.getLocation).toHaveBeenCalledWith('id'); + expect(fakeLocationService.getLocation).toHaveBeenCalledWith( + 'id', + mockOptions, + ); }); it('throws error on DENY', async () => { @@ -117,7 +118,7 @@ describe('AuthorizedLocationService', () => { const service = createService(); await expect(() => - service.getLocation('id', { authorizationToken: 'Bearer authtoken' }), + service.getLocation('id', mockOptions), ).rejects.toThrow(NotFoundError); }); }); @@ -127,11 +128,12 @@ describe('AuthorizedLocationService', () => { mockAllow(); const service = createService(); - await service.deleteLocation('id', { - authorizationToken: 'Bearer authtoken', - }); + await service.deleteLocation('id', mockOptions); - expect(fakeLocationService.deleteLocation).toHaveBeenCalledWith('id'); + expect(fakeLocationService.deleteLocation).toHaveBeenCalledWith( + 'id', + mockOptions, + ); }); it('throws error on DENY', async () => { @@ -139,9 +141,7 @@ describe('AuthorizedLocationService', () => { const service = createService(); await expect(() => - service.deleteLocation('id', { - authorizationToken: 'Bearer authtoken', - }), + service.deleteLocation('id', mockOptions), ).rejects.toThrow(NotAllowedError); }); }); @@ -153,16 +153,17 @@ describe('AuthorizedLocationService', () => { await service.getLocationByEntity( { kind: 'c', namespace: 'ns', name: 'n' }, - { - authorizationToken: 'Bearer authtoken', - }, + mockOptions, ); - expect(fakeLocationService.getLocationByEntity).toHaveBeenCalledWith({ - kind: 'c', - namespace: 'ns', - name: 'n', - }); + expect(fakeLocationService.getLocationByEntity).toHaveBeenCalledWith( + { + kind: 'c', + namespace: 'ns', + name: 'n', + }, + mockOptions, + ); }); it('throws error on DENY', async () => { @@ -172,7 +173,7 @@ describe('AuthorizedLocationService', () => { await expect(() => service.getLocationByEntity( { kind: 'c', namespace: 'ns', name: 'n' }, - { authorizationToken: 'Bearer authtoken' }, + mockOptions, ), ).rejects.toThrow(NotFoundError); }); diff --git a/plugins/catalog-backend/src/service/AuthorizedLocationService.ts b/plugins/catalog-backend/src/service/AuthorizedLocationService.ts index 0b9d50b20e..3eb3eede12 100644 --- a/plugins/catalog-backend/src/service/AuthorizedLocationService.ts +++ b/plugins/catalog-backend/src/service/AuthorizedLocationService.ts @@ -22,23 +22,24 @@ import { catalogLocationDeletePermission, catalogLocationReadPermission, } from '@backstage/plugin-catalog-common/alpha'; -import { - AuthorizeResult, - PermissionEvaluator, -} from '@backstage/plugin-permission-common'; +import { AuthorizeResult } from '@backstage/plugin-permission-common'; import { LocationInput, LocationService } from './types'; +import { + BackstageCredentials, + PermissionsService, +} from '@backstage/backend-plugin-api'; export class AuthorizedLocationService implements LocationService { constructor( private readonly locationService: LocationService, - private readonly permissionApi: PermissionEvaluator, + private readonly permissionApi: PermissionsService, ) {} async createLocation( spec: LocationInput, dryRun: boolean, - options?: { - authorizationToken?: string; + options: { + credentials: BackstageCredentials; }, ): Promise<{ location: Location; @@ -48,7 +49,7 @@ export class AuthorizedLocationService implements LocationService { const authorizationResponse = ( await this.permissionApi.authorize( [{ permission: catalogLocationCreatePermission }], - { token: options?.authorizationToken }, + { credentials: options.credentials }, ) )[0]; @@ -56,16 +57,16 @@ export class AuthorizedLocationService implements LocationService { throw new NotAllowedError(); } - return this.locationService.createLocation(spec, dryRun); + return this.locationService.createLocation(spec, dryRun, options); } - async listLocations(options?: { - authorizationToken?: string; + async listLocations(options: { + credentials: BackstageCredentials; }): Promise { const authorizationResponse = ( await this.permissionApi.authorize( [{ permission: catalogLocationReadPermission }], - { token: options?.authorizationToken }, + { credentials: options.credentials }, ) )[0]; @@ -73,17 +74,17 @@ export class AuthorizedLocationService implements LocationService { return []; } - return this.locationService.listLocations(); + return this.locationService.listLocations(options); } async getLocation( id: string, - options?: { authorizationToken?: string }, + options: { credentials: BackstageCredentials }, ): Promise { const authorizationResponse = ( await this.permissionApi.authorize( [{ permission: catalogLocationReadPermission }], - { token: options?.authorizationToken }, + { credentials: options.credentials }, ) )[0]; @@ -91,17 +92,17 @@ export class AuthorizedLocationService implements LocationService { throw new NotFoundError(`Found no location with ID ${id}`); } - return this.locationService.getLocation(id); + return this.locationService.getLocation(id, options); } async deleteLocation( id: string, - options?: { authorizationToken?: string }, + options: { credentials: BackstageCredentials }, ): Promise { const authorizationResponse = ( await this.permissionApi.authorize( [{ permission: catalogLocationDeletePermission }], - { token: options?.authorizationToken }, + { credentials: options.credentials }, ) )[0]; @@ -109,23 +110,23 @@ export class AuthorizedLocationService implements LocationService { throw new NotAllowedError(); } - return this.locationService.deleteLocation(id); + return this.locationService.deleteLocation(id, options); } async getLocationByEntity( entityRef: CompoundEntityRef | string, - options?: { authorizationToken?: string | undefined } | undefined, + options: { credentials: BackstageCredentials }, ): Promise { const authorizationResponse = ( await this.permissionApi.authorize( [{ permission: catalogLocationReadPermission }], - { token: options?.authorizationToken }, + { credentials: options.credentials }, ) )[0]; if (authorizationResponse.result === AuthorizeResult.DENY) { throw new NotFoundError(); } - return this.locationService.getLocationByEntity(entityRef); + return this.locationService.getLocationByEntity(entityRef, options); } } diff --git a/plugins/catalog-backend/src/service/AuthorizedRefreshService.test.ts b/plugins/catalog-backend/src/service/AuthorizedRefreshService.test.ts index f37bd0ec49..ba9ef2db73 100644 --- a/plugins/catalog-backend/src/service/AuthorizedRefreshService.test.ts +++ b/plugins/catalog-backend/src/service/AuthorizedRefreshService.test.ts @@ -18,6 +18,7 @@ import { NotAllowedError } from '@backstage/errors'; import { AuthorizeResult } from '@backstage/plugin-permission-common'; import { ServerPermissionClient } from '@backstage/plugin-permission-node'; import { AuthorizedRefreshService } from './AuthorizedRefreshService'; +import { mockCredentials } from '@backstage/backend-test-utils'; describe('AuthorizedRefreshService', () => { const refreshService = { @@ -46,7 +47,7 @@ describe('AuthorizedRefreshService', () => { await expect(() => authorizedService.refresh({ entityRef: 'some entity ref', - authorizationToken: 'some auth token', + credentials: mockCredentials.none(), }), ).rejects.toThrow(NotAllowedError); }); @@ -64,7 +65,7 @@ describe('AuthorizedRefreshService', () => { const options = { entityRef: 'some entity ref', - authorizationToken: 'some auth token', + credentials: mockCredentials.none(), }; await authorizedService.refresh(options); diff --git a/plugins/catalog-backend/src/service/AuthorizedRefreshService.ts b/plugins/catalog-backend/src/service/AuthorizedRefreshService.ts index cbc728750a..a5a2491a04 100644 --- a/plugins/catalog-backend/src/service/AuthorizedRefreshService.ts +++ b/plugins/catalog-backend/src/service/AuthorizedRefreshService.ts @@ -16,16 +16,14 @@ import { NotAllowedError } from '@backstage/errors'; import { catalogEntityRefreshPermission } from '@backstage/plugin-catalog-common/alpha'; -import { - AuthorizeResult, - PermissionEvaluator, -} from '@backstage/plugin-permission-common'; +import { AuthorizeResult } from '@backstage/plugin-permission-common'; import { RefreshOptions, RefreshService } from './types'; +import { PermissionsService } from '@backstage/backend-plugin-api'; export class AuthorizedRefreshService implements RefreshService { constructor( private readonly service: RefreshService, - private readonly permissionApi: PermissionEvaluator, + private readonly permissionApi: PermissionsService, ) {} async refresh(options: RefreshOptions) { @@ -37,7 +35,7 @@ export class AuthorizedRefreshService implements RefreshService { resourceRef: options.entityRef, }, ], - { token: options.authorizationToken }, + { credentials: options.credentials }, ) )[0]; if (authorizeDecision.result !== AuthorizeResult.ALLOW) { diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.ts b/plugins/catalog-backend/src/service/CatalogBuilder.ts index 0abaf2ec0a..7fcee231fd 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.ts @@ -14,7 +14,12 @@ * limitations under the License. */ -import { PluginDatabaseManager, UrlReader } from '@backstage/backend-common'; +import { + PluginDatabaseManager, + HostDiscovery, + UrlReader, + createLegacyAuthAdapters, +} from '@backstage/backend-common'; import { PluginTaskScheduler } from '@backstage/backend-tasks'; import { DefaultNamespaceEntityPolicy, @@ -84,7 +89,6 @@ import { permissionRules as catalogPermissionRules } from '../permissions/rules' import { PermissionRule } from '@backstage/plugin-permission-node'; import { PermissionAuthorizer, - PermissionEvaluator, toPermissionEvaluator, } from '@backstage/plugin-permission-common'; import { @@ -102,6 +106,12 @@ import { DefaultProviderDatabase } from '../database/DefaultProviderDatabase'; import { DefaultCatalogDatabase } from '../database/DefaultCatalogDatabase'; import { EventBroker } from '@backstage/plugin-events-node'; import { durationToMilliseconds } from '@backstage/types'; +import { + DiscoveryService, + AuthService, + HttpAuthService, + PermissionsService, +} from '@backstage/backend-plugin-api'; /** * This is a duplicate of the alpha `CatalogPermissionRule` type, for use in the stable API. @@ -118,8 +128,11 @@ export type CatalogEnvironment = { database: PluginDatabaseManager; config: Config; reader: UrlReader; - permissions: PermissionEvaluator | PermissionAuthorizer; + permissions: PermissionsService | PermissionAuthorizer; scheduler?: PluginTaskScheduler; + discovery?: DiscoveryService; + auth?: AuthService; + httpAuth?: HttpAuthService; }; /** @@ -438,7 +451,19 @@ export class CatalogBuilder { processingEngine: CatalogProcessingEngine; router: Router; }> { - const { config, database, logger, permissions, scheduler } = this.env; + const { + config, + database, + logger, + permissions, + scheduler, + discovery = HostDiscovery.fromConfig(config), + } = this.env; + + const { auth, httpAuth } = createLegacyAuthAdapters({ + ...this.env, + discovery, + }); const policy = this.buildEntityPolicy(); const processors = this.buildProcessors(); @@ -486,25 +511,26 @@ export class CatalogBuilder { stitcher, }); - let permissionEvaluator: PermissionEvaluator; + let permissionsService: PermissionsService; if ('authorizeConditional' in permissions) { - permissionEvaluator = permissions as PermissionEvaluator; + permissionsService = permissions as PermissionsService; } else { logger.warn( 'PermissionAuthorizer is deprecated. Please use an instance of PermissionEvaluator instead of PermissionAuthorizer in PluginEnvironment#permissions', ); - permissionEvaluator = toPermissionEvaluator(permissions); + permissionsService = toPermissionEvaluator(permissions); } const entitiesCatalog = new AuthorizedEntitiesCatalog( unauthorizedEntitiesCatalog, - permissionEvaluator, + permissionsService, createConditionTransformer(this.permissionRules), ); const permissionIntegrationRouter = createPermissionIntegrationRouter({ resourceType: RESOURCE_TYPE_CATALOG_ENTITY, getResources: async (resourceRefs: string[]) => { const { entities } = await unauthorizedEntitiesCatalog.entities({ + credentials: await auth.getOwnServiceCredentials(), filter: { anyOf: resourceRefs.map(resourceRef => { const { kind, namespace, name } = parseEntityRef(resourceRef); @@ -558,12 +584,13 @@ export class CatalogBuilder { new DefaultLocationService(locationStore, orchestrator, { allowedLocationTypes: this.allowedLocationType, }), - permissionEvaluator, + permissionsService, ); const refreshService = new AuthorizedRefreshService( new DefaultRefreshService({ database: catalogDatabase }), - permissionEvaluator, + permissionsService, ); + const router = await createRouter({ entitiesCatalog, locationAnalyzer, @@ -573,6 +600,8 @@ export class CatalogBuilder { logger, config, permissionIntegrationRouter, + auth, + httpAuth, }); await connectEntityProviders(providerDatabase, entityProviders); diff --git a/plugins/catalog-backend/src/service/CatalogPlugin.ts b/plugins/catalog-backend/src/service/CatalogPlugin.ts index 1b4a6fba51..6e4424922d 100644 --- a/plugins/catalog-backend/src/service/CatalogPlugin.ts +++ b/plugins/catalog-backend/src/service/CatalogPlugin.ts @@ -194,6 +194,9 @@ export const catalogPlugin = createBackendPlugin({ httpRouter: coreServices.httpRouter, lifecycle: coreServices.lifecycle, scheduler: coreServices.scheduler, + discovery: coreServices.discovery, + auth: coreServices.auth, + httpAuth: coreServices.httpAuth, }, async init({ logger, @@ -204,6 +207,9 @@ export const catalogPlugin = createBackendPlugin({ httpRouter, lifecycle, scheduler, + discovery, + auth, + httpAuth, }) { const winstonLogger = loggerToWinstonLogger(logger); const builder = await CatalogBuilder.create({ @@ -213,6 +219,9 @@ export const catalogPlugin = createBackendPlugin({ database, scheduler, logger: winstonLogger, + discovery, + auth, + httpAuth, }); if (processingExtensions.onProcessingErrorHandler) { builder.subscribe({ diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index fe7d57c89a..4d8dc7c7a4 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -15,7 +15,11 @@ */ import { getVoidLogger } from '@backstage/backend-common'; -import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; +import { + TestDatabaseId, + TestDatabases, + mockCredentials, +} from '@backstage/backend-test-utils'; import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { Knex } from 'knex'; import { v4 as uuid, v4 } from 'uuid'; @@ -304,8 +308,10 @@ describe('DefaultEntitiesCatalog', () => { const testFilter = { key: 'spec.test', }; - const request = { filter: testFilter }; - const { entities } = await catalog.entities(request); + const { entities } = await catalog.entities({ + filter: testFilter, + credentials: mockCredentials.none(), + }); expect(entities.length).toBe(1); expect(entities[0]).toEqual(entity2); @@ -343,8 +349,10 @@ describe('DefaultEntitiesCatalog', () => { key: 'spec.test', }, }; - const request = { filter: testFilter }; - const { entities } = await catalog.entities(request); + const { entities } = await catalog.entities({ + filter: testFilter, + credentials: mockCredentials.none(), + }); expect(entities.length).toBe(1); expect(entities[0]).toEqual(entity1); @@ -406,7 +414,7 @@ describe('DefaultEntitiesCatalog', () => { values: ['red'], }, }; - const request = { + const { entities } = await catalog.entities({ filter: { allOf: [ testFilter1, @@ -415,8 +423,8 @@ describe('DefaultEntitiesCatalog', () => { }, ], }, - }; - const { entities } = await catalog.entities(request); + credentials: mockCredentials.none(), + }); expect(entities.length).toBe(2); expect(entities).toContainEqual(entity2); @@ -455,14 +463,15 @@ describe('DefaultEntitiesCatalog', () => { const testFilter2 = { key: 'metadata.desc', }; - const request = { + const { entities } = await catalog.entities({ filter: { not: { allOf: [testFilter1, testFilter2], }, }, - }; - const { entities } = await catalog.entities(request); + + credentials: mockCredentials.none(), + }); expect(entities.length).toBe(1); expect(entities).toContainEqual(entity1); @@ -498,8 +507,10 @@ describe('DefaultEntitiesCatalog', () => { key: 'kind', values: [], }; - const request = { filter: testFilter }; - const { entities } = await catalog.entities(request); + const { entities } = await catalog.entities({ + filter: testFilter, + credentials: mockCredentials.none(), + }); expect(entities.length).toBe(0); }, @@ -603,9 +614,11 @@ describe('DefaultEntitiesCatalog', () => { stitcher, }); - function f(request: EntitiesRequest): Promise { + function f( + request: Omit, + ): Promise { return catalog - .entities(request) + .entities({ ...request, credentials: mockCredentials.none() }) .then(response => response.entities.map(e => e.metadata.name)); } @@ -701,6 +714,7 @@ describe('DefaultEntitiesCatalog', () => { 'k:default/does-not-exist', 'k:default/two', ], + credentials: mockCredentials.none(), }); expect(items.map(e => e && stringifyEntityRef(e))).toEqual([ @@ -749,6 +763,7 @@ describe('DefaultEntitiesCatalog', () => { const { items } = await catalog.entitiesBatch({ entityRefs: ['k:default/two', 'k:default/one'], filter: { key: 'spec.owner', values: ['me'] }, + credentials: mockCredentials.none(), }); expect(items.map(e => e && stringifyEntityRef(e))).toEqual([ @@ -804,6 +819,7 @@ describe('DefaultEntitiesCatalog', () => { filter, limit, orderFields: [{ field: 'metadata.name', order: 'asc' }], + credentials: mockCredentials.none(), }; const response1 = await catalog.queryEntities(request1); expect(response1.items).toEqual([entityFrom('A'), entityFrom('B')]); @@ -815,6 +831,7 @@ describe('DefaultEntitiesCatalog', () => { const request2: QueryEntitiesCursorRequest = { cursor: response1.pageInfo.nextCursor!, limit, + credentials: mockCredentials.none(), }; const response2 = await catalog.queryEntities(request2); expect(response2.items).toEqual([entityFrom('C'), entityFrom('D')]); @@ -826,6 +843,7 @@ describe('DefaultEntitiesCatalog', () => { const request3: QueryEntitiesCursorRequest = { cursor: response2.pageInfo.nextCursor!, limit, + credentials: mockCredentials.none(), }; const response3 = await catalog.queryEntities(request3); expect(response3.items).toEqual([entityFrom('E'), entityFrom('F')]); @@ -837,6 +855,7 @@ describe('DefaultEntitiesCatalog', () => { const request4: QueryEntitiesCursorRequest = { cursor: response3.pageInfo.prevCursor!, limit, + credentials: mockCredentials.none(), }; const response4 = await catalog.queryEntities(request4); expect(response4.items).toEqual([entityFrom('C'), entityFrom('D')]); @@ -848,6 +867,7 @@ describe('DefaultEntitiesCatalog', () => { const request5: QueryEntitiesCursorRequest = { cursor: response4.pageInfo.prevCursor!, limit, + credentials: mockCredentials.none(), }; const response5 = await catalog.queryEntities(request5); expect(response5.items).toEqual([entityFrom('A'), entityFrom('B')]); @@ -859,6 +879,7 @@ describe('DefaultEntitiesCatalog', () => { const request6: QueryEntitiesCursorRequest = { cursor: response5.pageInfo.nextCursor!, limit, + credentials: mockCredentials.none(), }; const response6 = await catalog.queryEntities(request6); expect(response6.items).toEqual([entityFrom('C'), entityFrom('D')]); @@ -870,6 +891,7 @@ describe('DefaultEntitiesCatalog', () => { const request7: QueryEntitiesCursorRequest = { cursor: response6.pageInfo.nextCursor!, limit, + credentials: mockCredentials.none(), }; const response7 = await catalog.queryEntities(request7); expect(response7.items).toEqual([entityFrom('E'), entityFrom('F')]); @@ -881,6 +903,7 @@ describe('DefaultEntitiesCatalog', () => { const request7bis: QueryEntitiesCursorRequest = { cursor: response6.pageInfo.nextCursor!, limit: limit + 1, + credentials: mockCredentials.none(), }; const response7bis = await catalog.queryEntities(request7bis); expect(response7bis.items).toEqual([ @@ -896,6 +919,7 @@ describe('DefaultEntitiesCatalog', () => { const request8: QueryEntitiesCursorRequest = { cursor: response7.pageInfo.nextCursor!, limit, + credentials: mockCredentials.none(), }; const response8 = await catalog.queryEntities(request8); expect(response8.items).toEqual([entityFrom('G')]); @@ -949,6 +973,7 @@ describe('DefaultEntitiesCatalog', () => { filter, limit, orderFields: [{ field: 'metadata.name', order: 'desc' }], + credentials: mockCredentials.none(), }; const response1 = await catalog.queryEntities(request1); expect(response1.items).toEqual([entityFrom('G'), entityFrom('F')]); @@ -960,6 +985,7 @@ describe('DefaultEntitiesCatalog', () => { const request2: QueryEntitiesCursorRequest = { cursor: response1.pageInfo.nextCursor!, limit, + credentials: mockCredentials.none(), }; const response2 = await catalog.queryEntities(request2); expect(response2.items).toEqual([entityFrom('E'), entityFrom('D')]); @@ -971,6 +997,7 @@ describe('DefaultEntitiesCatalog', () => { const request3: QueryEntitiesCursorRequest = { cursor: response2.pageInfo.nextCursor!, limit, + credentials: mockCredentials.none(), }; const response3 = await catalog.queryEntities(request3); expect(response3.items).toEqual([entityFrom('C'), entityFrom('B')]); @@ -982,6 +1009,7 @@ describe('DefaultEntitiesCatalog', () => { const request4: QueryEntitiesCursorRequest = { cursor: response3.pageInfo.prevCursor!, limit, + credentials: mockCredentials.none(), }; const response4 = await catalog.queryEntities(request4); @@ -994,6 +1022,7 @@ describe('DefaultEntitiesCatalog', () => { const request5: QueryEntitiesCursorRequest = { cursor: response4.pageInfo.prevCursor!, limit, + credentials: mockCredentials.none(), }; const response5 = await catalog.queryEntities(request5); expect(response5.items).toEqual([entityFrom('G'), entityFrom('F')]); @@ -1005,6 +1034,7 @@ describe('DefaultEntitiesCatalog', () => { const request6: QueryEntitiesCursorRequest = { cursor: response5.pageInfo.nextCursor!, limit, + credentials: mockCredentials.none(), }; const response6 = await catalog.queryEntities(request6); expect(response6.items).toEqual([entityFrom('E'), entityFrom('D')]); @@ -1016,6 +1046,7 @@ describe('DefaultEntitiesCatalog', () => { const request7: QueryEntitiesCursorRequest = { cursor: response6.pageInfo.nextCursor!, limit, + credentials: mockCredentials.none(), }; const response7 = await catalog.queryEntities(request7); expect(response7.items).toEqual([entityFrom('C'), entityFrom('B')]); @@ -1027,6 +1058,7 @@ describe('DefaultEntitiesCatalog', () => { const request7bis: QueryEntitiesCursorRequest = { cursor: response6.pageInfo.nextCursor!, limit: limit + 1, + credentials: mockCredentials.none(), }; const response7bis = await catalog.queryEntities(request7bis); expect(response7bis.items).toEqual([ @@ -1042,6 +1074,7 @@ describe('DefaultEntitiesCatalog', () => { const request8: QueryEntitiesCursorRequest = { cursor: response7.pageInfo.nextCursor!, limit, + credentials: mockCredentials.none(), }; const response8 = await catalog.queryEntities(request8); expect(response8.items).toEqual([entityFrom('A')]); @@ -1094,6 +1127,7 @@ describe('DefaultEntitiesCatalog', () => { orderFields: [{ field: 'metadata.name', order: 'asc' }], fullTextFilter: { term: 'cAt ' }, + credentials: mockCredentials.none(), }; const response = await catalog.queryEntities(request); expect(response.items).toEqual([ @@ -1152,6 +1186,7 @@ describe('DefaultEntitiesCatalog', () => { filter, limit: 100, fullTextFilter: { term: 'cAt ', fields: ['metadata.title'] }, + credentials: mockCredentials.none(), }; const response = await catalog.queryEntities(request); expect(response.items).toEqual([ @@ -1177,6 +1212,7 @@ describe('DefaultEntitiesCatalog', () => { const paginatedResponseNext = await catalog.queryEntities({ cursor: paginatedResponse.pageInfo.nextCursor!, + credentials: mockCredentials.none(), }); expect(paginatedResponseNext.items).toEqual([ entityFrom('4', { uid: 'id4', title: 'dogcat' }), @@ -1187,6 +1223,7 @@ describe('DefaultEntitiesCatalog', () => { const paginatedResponsePrev = await catalog.queryEntities({ cursor: paginatedResponseNext.pageInfo.prevCursor!, + credentials: mockCredentials.none(), }); expect(paginatedResponsePrev).toMatchObject(paginatedResponse); }, @@ -1251,6 +1288,7 @@ describe('DefaultEntitiesCatalog', () => { term: 'KiNg ', fields: ['metadata.title', 'metadata.name'], }, + credentials: mockCredentials.none(), }; const response = await catalog.queryEntities(request); @@ -1278,6 +1316,7 @@ describe('DefaultEntitiesCatalog', () => { const paginatedResponseNext = await catalog.queryEntities({ cursor: paginatedResponse.pageInfo.nextCursor!, + credentials: mockCredentials.none(), }); expect(paginatedResponseNext.items).toEqual([ entityFrom('NotACatKing', { uid: 'id2', title: 'atcatss' }), @@ -1289,6 +1328,7 @@ describe('DefaultEntitiesCatalog', () => { const paginatedResponsePrev = await catalog.queryEntities({ cursor: paginatedResponseNext.pageInfo.prevCursor!, + credentials: mockCredentials.none(), }); expect(paginatedResponsePrev).toMatchObject(paginatedResponse); }, @@ -1319,6 +1359,7 @@ describe('DefaultEntitiesCatalog', () => { const request: QueryEntitiesInitialRequest = { limit: 0, + credentials: mockCredentials.none(), }; const response = await catalog.queryEntities(request); expect(response).toEqual({ totalItems: 20, items: [], pageInfo: {} }); @@ -1351,6 +1392,7 @@ describe('DefaultEntitiesCatalog', () => { const request1: QueryEntitiesInitialRequest = { limit, orderFields: [{ field: 'metadata.name', order: 'asc' }], + credentials: mockCredentials.none(), }; const response1 = await catalog.queryEntities(request1); expect(response1.items).toMatchObject([ @@ -1365,6 +1407,7 @@ describe('DefaultEntitiesCatalog', () => { const request2: QueryEntitiesCursorRequest = { cursor: response1.pageInfo.nextCursor!, limit, + credentials: mockCredentials.none(), }; const response2 = await catalog.queryEntities(request2); expect(response2.items).toMatchObject([ @@ -1379,6 +1422,7 @@ describe('DefaultEntitiesCatalog', () => { const request3: QueryEntitiesCursorRequest = { cursor: response2.pageInfo.nextCursor!, limit, + credentials: mockCredentials.none(), }; const response3 = await catalog.queryEntities(request3); expect(response3.items).toEqual([entityFrom('CC'), entityFrom('DD')]); @@ -1390,6 +1434,7 @@ describe('DefaultEntitiesCatalog', () => { const request4: QueryEntitiesCursorRequest = { cursor: response3.pageInfo.prevCursor!, limit, + credentials: mockCredentials.none(), }; const response4 = await catalog.queryEntities(request4); expect(response4.items).toMatchObject([ @@ -1404,6 +1449,7 @@ describe('DefaultEntitiesCatalog', () => { const request5: QueryEntitiesCursorRequest = { cursor: response4.pageInfo.prevCursor!, limit, + credentials: mockCredentials.none(), }; const response5 = await catalog.queryEntities(request5); expect(response5.items).toMatchObject([ @@ -1471,6 +1517,7 @@ describe('DefaultEntitiesCatalog', () => { values: ['included'], }, orderFields: [{ field: 'metadata.name', order: 'asc' }], + credentials: mockCredentials.none(), }; const response1 = await catalog.queryEntities(request1); expect(response1.items).toMatchObject([ @@ -1485,6 +1532,7 @@ describe('DefaultEntitiesCatalog', () => { const request2: QueryEntitiesCursorRequest = { cursor: response1.pageInfo.nextCursor!, limit, + credentials: mockCredentials.none(), }; const response2 = await catalog.queryEntities(request2); expect(response2.items).toMatchObject([ @@ -1528,6 +1576,7 @@ describe('DefaultEntitiesCatalog', () => { // initial request const request1: QueryEntitiesInitialRequest = { limit, + credentials: mockCredentials.none(), }; const response1 = await catalog.queryEntities(request1); expect(response1.items).toMatchObject([ @@ -1542,6 +1591,7 @@ describe('DefaultEntitiesCatalog', () => { const request2: QueryEntitiesCursorRequest = { cursor: response1.pageInfo.nextCursor!, limit, + credentials: mockCredentials.none(), }; const response2 = await catalog.queryEntities(request2); expect(response2.items).toMatchObject([ @@ -1556,6 +1606,7 @@ describe('DefaultEntitiesCatalog', () => { const request3: QueryEntitiesCursorRequest = { cursor: response2.pageInfo.nextCursor!, limit, + credentials: mockCredentials.none(), }; const response3 = await catalog.queryEntities(request3); expect(response3.items).toMatchObject([ @@ -1570,6 +1621,7 @@ describe('DefaultEntitiesCatalog', () => { const request4: QueryEntitiesCursorRequest = { cursor: response3.pageInfo.prevCursor!, limit, + credentials: mockCredentials.none(), }; const response4 = await catalog.queryEntities(request4); expect(response4.items).toMatchObject([ @@ -1584,6 +1636,7 @@ describe('DefaultEntitiesCatalog', () => { const request5: QueryEntitiesCursorRequest = { cursor: response4.pageInfo.prevCursor!, limit, + credentials: mockCredentials.none(), }; const response5 = await catalog.queryEntities(request5); expect(response5.items).toMatchObject([ @@ -1719,7 +1772,12 @@ describe('DefaultEntitiesCatalog', () => { stitcher, }); - await expect(catalog.facets({ facets: ['kind'] })).resolves.toEqual({ + await expect( + catalog.facets({ + facets: ['kind'], + credentials: mockCredentials.none(), + }), + ).resolves.toEqual({ facets: { kind: [ { value: 'k', count: 2 }, @@ -1732,6 +1790,7 @@ describe('DefaultEntitiesCatalog', () => { catalog.facets({ facets: ['kind'], filter: { not: { key: 'metadata.name', values: ['two'] } }, + credentials: mockCredentials.none(), }), ).resolves.toEqual({ facets: { @@ -1775,6 +1834,7 @@ describe('DefaultEntitiesCatalog', () => { await expect( catalog.facets({ facets: ['metadata.annotations.a.b/c.d', 'metadata.labels.e.f/g.h'], + credentials: mockCredentials.none(), }), ).resolves.toEqual({ facets: { @@ -1823,6 +1883,7 @@ describe('DefaultEntitiesCatalog', () => { await expect( catalog.facets({ facets: ['metadata.tags'], + credentials: mockCredentials.none(), }), ).resolves.toEqual({ facets: { diff --git a/plugins/catalog-backend/src/service/DefaultRefreshService.test.ts b/plugins/catalog-backend/src/service/DefaultRefreshService.test.ts index e1b775cce6..9ca9ae0a5f 100644 --- a/plugins/catalog-backend/src/service/DefaultRefreshService.test.ts +++ b/plugins/catalog-backend/src/service/DefaultRefreshService.test.ts @@ -15,7 +15,11 @@ */ import { getVoidLogger } from '@backstage/backend-common'; -import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; +import { + TestDatabaseId, + TestDatabases, + mockCredentials, +} from '@backstage/backend-test-utils'; import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { createHash } from 'crypto'; import { Knex } from 'knex'; @@ -220,6 +224,7 @@ describe('DefaultRefreshService', () => { await refreshService.refresh({ entityRef: 'component:default/mycomp', + credentials: mockCredentials.none(), }); await expect( @@ -273,6 +278,7 @@ describe('DefaultRefreshService', () => { await refreshService.refresh({ entityRef: 'api:default/myapi', + credentials: mockCredentials.none(), }); await expect(waitForRefresh(knex, 'api:default/myapi')).resolves.toBe( @@ -324,6 +330,7 @@ describe('DefaultRefreshService', () => { await refreshService.refresh({ entityRef: 'component:default/mycomp', + credentials: mockCredentials.none(), }); await expect( @@ -334,6 +341,7 @@ describe('DefaultRefreshService', () => { await refreshService.refresh({ entityRef: 'component:default/mycomp', + credentials: mockCredentials.none(), }); await expect( diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts index 3eb00c5bd6..5177f3b42b 100644 --- a/plugins/catalog-backend/src/service/createRouter.test.ts +++ b/plugins/catalog-backend/src/service/createRouter.test.ts @@ -41,6 +41,7 @@ import { z } from 'zod'; import { decodeCursor, encodeCursor } from './util'; import { wrapInOpenApiTestServer } from '@backstage/backend-openapi-utils'; import { Server } from 'http'; +import { mockCredentials, mockServices } from '@backstage/backend-test-utils'; describe('createRouter readonly disabled', () => { let entitiesCatalog: jest.Mocked; @@ -75,6 +76,8 @@ describe('createRouter readonly disabled', () => { refreshService, config: new ConfigReader(undefined), permissionIntegrationRouter: express.Router(), + auth: mockServices.auth(), + httpAuth: mockServices.httpAuth(), }); app = wrapInOpenApiTestServer(express().use(router)); }); @@ -88,15 +91,30 @@ describe('createRouter readonly disabled', () => { const response = await request(app) .post('/refresh') .set('Content-Type', 'application/json') - .set('authorization', 'Bearer someauthtoken') .send({ entityRef: 'Component/default:foo' }); expect(response.status).toBe(200); expect(refreshService.refresh).toHaveBeenCalledWith({ entityRef: 'Component/default:foo', - authorizationToken: 'someauthtoken', + credentials: mockCredentials.user(), + }); + }); + + it('should support passing the token in the request body for backwards compatibility', async () => { + const response = await request(app) + .post('/refresh') + .set('Content-Type', 'application/json') + .send({ + entityRef: 'Component/default:foo', + authorizationToken: mockCredentials.user.token('user:default/other'), + }); + expect(response.status).toBe(200); + expect(refreshService.refresh).toHaveBeenCalledWith({ + entityRef: 'Component/default:foo', + credentials: mockCredentials.user('user:default/other'), }); }); }); + describe('GET /entities', () => { it('happy path: lists entities', async () => { const entities: Entity[] = [ @@ -137,6 +155,7 @@ describe('createRouter readonly disabled', () => { { allOf: [{ key: 'c', values: ['4'] }] }, ], }, + credentials: mockCredentials.user(), }); }); }); @@ -196,6 +215,7 @@ describe('createRouter readonly disabled', () => { fields: undefined, term: '', }, + credentials: mockCredentials.user(), }); }); @@ -235,6 +255,7 @@ describe('createRouter readonly disabled', () => { fields: undefined, term: '', }, + credentials: mockCredentials.user(), }); }); @@ -257,6 +278,7 @@ describe('createRouter readonly disabled', () => { expect(entitiesCatalog.queryEntities).toHaveBeenCalledTimes(1); expect(entitiesCatalog.queryEntities).toHaveBeenCalledWith({ cursor, + credentials: mockCredentials.user(), }); expect(response.status).toEqual(200); expect(response.body).toEqual({ @@ -291,6 +313,7 @@ describe('createRouter readonly disabled', () => { expect(entitiesCatalog.queryEntities).toHaveBeenCalledTimes(1); expect(entitiesCatalog.queryEntities).toHaveBeenCalledWith({ cursor, + credentials: mockCredentials.user(), }); expect(response.status).toEqual(200); expect(response.body).toEqual({ @@ -370,6 +393,7 @@ describe('createRouter readonly disabled', () => { expect(entitiesCatalog.entities).toHaveBeenCalledTimes(1); expect(entitiesCatalog.entities).toHaveBeenCalledWith({ filter: basicEntityFilter({ 'metadata.uid': 'zzz' }), + credentials: mockCredentials.user(), }); expect(response.status).toEqual(200); expect(response.body).toEqual(expect.objectContaining(entity)); @@ -386,6 +410,7 @@ describe('createRouter readonly disabled', () => { expect(entitiesCatalog.entities).toHaveBeenCalledTimes(1); expect(entitiesCatalog.entities).toHaveBeenCalledWith({ filter: basicEntityFilter({ 'metadata.uid': 'zzz' }), + credentials: mockCredentials.user(), }); expect(response.status).toEqual(404); expect(response.text).toMatch(/uid/); @@ -416,6 +441,7 @@ describe('createRouter readonly disabled', () => { 'metadata.namespace': 'ns', 'metadata.name': 'n', }), + credentials: mockCredentials.user(), }); expect(response.status).toEqual(200); expect(response.body).toEqual(expect.objectContaining(entity)); @@ -436,6 +462,7 @@ describe('createRouter readonly disabled', () => { 'metadata.namespace': 'd', 'metadata.name': 'c', }), + credentials: mockCredentials.user(), }); expect(response.status).toEqual(404); expect(response.text).toMatch(/name/); @@ -446,13 +473,10 @@ describe('createRouter readonly disabled', () => { it('can remove', async () => { entitiesCatalog.removeEntityByUid.mockResolvedValue(undefined); - const response = await request(app) - .delete('/entities/by-uid/apa') - .set('authorization', 'Bearer someauthtoken'); - + const response = await request(app).delete('/entities/by-uid/apa'); expect(entitiesCatalog.removeEntityByUid).toHaveBeenCalledTimes(1); expect(entitiesCatalog.removeEntityByUid).toHaveBeenCalledWith('apa', { - authorizationToken: 'someauthtoken', + credentials: mockCredentials.user(), }); expect(response.status).toEqual(204); }); @@ -462,13 +486,10 @@ describe('createRouter readonly disabled', () => { new NotFoundError('nope'), ); - const response = await request(app) - .delete('/entities/by-uid/apa') - .set('authorization', 'Bearer someauthtoken'); - + const response = await request(app).delete('/entities/by-uid/apa'); expect(entitiesCatalog.removeEntityByUid).toHaveBeenCalledTimes(1); expect(entitiesCatalog.removeEntityByUid).toHaveBeenCalledWith('apa', { - authorizationToken: 'someauthtoken', + credentials: mockCredentials.user(), }); expect(response.status).toEqual(404); }); @@ -518,6 +539,7 @@ describe('createRouter readonly disabled', () => { expect(entitiesCatalog.entitiesBatch).toHaveBeenCalledWith({ entityRefs: [entityRef], fields: expect.any(Function), + credentials: mockCredentials.user(), }); expect(response.status).toEqual(200); expect(response.body).toEqual({ items: [entity] }); @@ -531,13 +553,10 @@ describe('createRouter readonly disabled', () => { ]; locationService.listLocations.mockResolvedValueOnce(locations); - const response = await request(app) - .get('/locations') - .set('authorization', 'Bearer someauthtoken'); - + const response = await request(app).get('/locations'); expect(locationService.listLocations).toHaveBeenCalledTimes(1); expect(locationService.listLocations).toHaveBeenCalledWith({ - authorizationToken: 'someauthtoken', + credentials: mockCredentials.user(), }); expect(response.status).toEqual(200); expect(response.body).toEqual([ @@ -555,13 +574,10 @@ describe('createRouter readonly disabled', () => { }; locationService.getLocation.mockResolvedValueOnce(location); - const response = await request(app) - .get('/locations/foo') - .set('authorization', 'Bearer someauthtoken'); - + const response = await request(app).get('/locations/foo'); expect(locationService.getLocation).toHaveBeenCalledTimes(1); expect(locationService.getLocation).toHaveBeenCalledWith('foo', { - authorizationToken: 'someauthtoken', + credentials: mockCredentials.user(), }); expect(response.status).toEqual(200); @@ -582,7 +598,7 @@ describe('createRouter readonly disabled', () => { const response = await request(app) .post('/locations') - .set('authorization', 'Bearer someauthtoken') + .send(spec); expect(locationService.createLocation).not.toHaveBeenCalled(); @@ -602,12 +618,12 @@ describe('createRouter readonly disabled', () => { const response = await request(app) .post('/locations') - .set('authorization', 'Bearer someauthtoken') + .send(spec); expect(locationService.createLocation).toHaveBeenCalledTimes(1); expect(locationService.createLocation).toHaveBeenCalledWith(spec, false, { - authorizationToken: 'someauthtoken', + credentials: mockCredentials.user(), }); expect(response.status).toEqual(201); expect(response.body).toEqual( @@ -630,12 +646,12 @@ describe('createRouter readonly disabled', () => { const response = await request(app) .post('/locations?dryRun=true') - .set('authorization', 'Bearer someauthtoken') + .send(spec); expect(locationService.createLocation).toHaveBeenCalledTimes(1); expect(locationService.createLocation).toHaveBeenCalledWith(spec, true, { - authorizationToken: 'someauthtoken', + credentials: mockCredentials.user(), }); expect(response.status).toEqual(201); expect(response.body).toEqual( @@ -650,13 +666,10 @@ describe('createRouter readonly disabled', () => { it('deletes the location', async () => { locationService.deleteLocation.mockResolvedValueOnce(undefined); - const response = await request(app) - .delete('/locations/foo') - .set('authorization', 'Bearer someauthtoken'); - + const response = await request(app).delete('/locations/foo'); expect(locationService.deleteLocation).toHaveBeenCalledTimes(1); expect(locationService.deleteLocation).toHaveBeenCalledWith('foo', { - authorizationToken: 'someauthtoken', + credentials: mockCredentials.user(), }); expect(response.status).toEqual(204); @@ -672,15 +685,12 @@ describe('createRouter readonly disabled', () => { }; locationService.getLocationByEntity.mockResolvedValueOnce(location); - const response = await request(app) - .get('/locations/by-entity/c/ns/n') - .set('authorization', 'Bearer someauthtoken'); - + const response = await request(app).get('/locations/by-entity/c/ns/n'); expect(locationService.getLocationByEntity).toHaveBeenCalledTimes(1); expect(locationService.getLocationByEntity).toHaveBeenCalledWith( { kind: 'c', namespace: 'ns', name: 'n' }, { - authorizationToken: 'someauthtoken', + credentials: mockCredentials.user(), }, ); @@ -837,6 +847,8 @@ describe('createRouter readonly enabled', () => { }, }), permissionIntegrationRouter: express.Router(), + auth: mockServices.auth(), + httpAuth: mockServices.httpAuth(), }); app = express().use(router); }); @@ -866,13 +878,10 @@ describe('createRouter readonly enabled', () => { describe('DELETE /entities/by-uid/:uid', () => { // this delete is allowed as there is no other way to remove entities it('is allowed', async () => { - const response = await request(app) - .delete('/entities/by-uid/apa') - .set('authorization', 'Bearer someauthtoken'); - + const response = await request(app).delete('/entities/by-uid/apa'); expect(entitiesCatalog.removeEntityByUid).toHaveBeenCalledTimes(1); expect(entitiesCatalog.removeEntityByUid).toHaveBeenCalledWith('apa', { - authorizationToken: 'someauthtoken', + credentials: mockCredentials.user(), }); expect(response.status).toEqual(204); }); @@ -885,13 +894,10 @@ describe('createRouter readonly enabled', () => { ]; locationService.listLocations.mockResolvedValueOnce(locations); - const response = await request(app) - .get('/locations') - .set('authorization', 'Bearer someauthtoken'); - + const response = await request(app).get('/locations'); expect(locationService.listLocations).toHaveBeenCalledTimes(1); expect(locationService.listLocations).toHaveBeenCalledWith({ - authorizationToken: 'someauthtoken', + credentials: mockCredentials.user(), }); expect(response.status).toEqual(200); @@ -910,13 +916,10 @@ describe('createRouter readonly enabled', () => { }; locationService.getLocation.mockResolvedValueOnce(location); - const response = await request(app) - .get('/locations/foo') - .set('authorization', 'Bearer someauthtoken'); - + const response = await request(app).get('/locations/foo'); expect(locationService.getLocation).toHaveBeenCalledTimes(1); expect(locationService.getLocation).toHaveBeenCalledWith('foo', { - authorizationToken: 'someauthtoken', + credentials: mockCredentials.user(), }); expect(response.status).toEqual(200); @@ -937,7 +940,7 @@ describe('createRouter readonly enabled', () => { const response = await request(app) .post('/locations') - .set('authorization', 'Bearer someauthtoken') + .send(spec); expect(locationService.createLocation).not.toHaveBeenCalled(); @@ -958,12 +961,12 @@ describe('createRouter readonly enabled', () => { const response = await request(app) .post('/locations?dryRun=true') - .set('authorization', 'Bearer someauthtoken') + .send(spec); expect(locationService.createLocation).toHaveBeenCalledTimes(1); expect(locationService.createLocation).toHaveBeenCalledWith(spec, true, { - authorizationToken: 'someauthtoken', + credentials: mockCredentials.user(), }); expect(response.status).toEqual(201); expect(response.body).toEqual( @@ -976,10 +979,7 @@ describe('createRouter readonly enabled', () => { describe('DELETE /locations', () => { it('is not allowed', async () => { - const response = await request(app) - .delete('/locations/foo') - .set('authorization', 'Bearer someauthtoken'); - + const response = await request(app).delete('/locations/foo'); expect(locationService.deleteLocation).not.toHaveBeenCalled(); expect(response.status).toEqual(403); }); @@ -994,15 +994,12 @@ describe('createRouter readonly enabled', () => { }; locationService.getLocationByEntity.mockResolvedValueOnce(location); - const response = await request(app) - .get('/locations/by-entity/c/ns/n') - .set('authorization', 'Bearer someauthtoken'); - + const response = await request(app).get('/locations/by-entity/c/ns/n'); expect(locationService.getLocationByEntity).toHaveBeenCalledTimes(1); expect(locationService.getLocationByEntity).toHaveBeenCalledWith( { kind: 'c', namespace: 'ns', name: 'n' }, { - authorizationToken: 'someauthtoken', + credentials: mockCredentials.user(), }, ); @@ -1065,6 +1062,8 @@ describe('NextRouter permissioning', () => { ), ), }), + auth: mockServices.auth(), + httpAuth: mockServices.httpAuth(), }); app = express().use(router); }); diff --git a/plugins/catalog-backend/src/service/createRouter.ts b/plugins/catalog-backend/src/service/createRouter.ts index 2522966408..922782d75a 100644 --- a/plugins/catalog-backend/src/service/createRouter.ts +++ b/plugins/catalog-backend/src/service/createRouter.ts @@ -41,7 +41,7 @@ import { } from './request'; import { parseEntityFacetParams } from './request/parseEntityFacetParams'; import { parseEntityOrderParams } from './request/parseEntityOrderParams'; -import { LocationService, RefreshOptions, RefreshService } from './types'; +import { LocationService, RefreshService } from './types'; import { disallowReadonlyMode, encodeCursor, @@ -50,8 +50,8 @@ import { } from './util'; import { createOpenApiRouter } from '../schema/openapi.generated'; import { PluginTaskScheduler } from '@backstage/backend-tasks'; -import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node'; import { parseEntityPaginationParams } from './request/parseEntityPaginationParams'; +import { AuthService, HttpAuthService } from '@backstage/backend-plugin-api'; /** * Options used by {@link createRouter}. @@ -68,6 +68,8 @@ export interface RouterOptions { logger: Logger; config: Config; permissionIntegrationRouter?: express.Router; + auth: AuthService; + httpAuth: HttpAuthService; } /** @@ -94,6 +96,8 @@ export async function createRouter( config, logger, permissionIntegrationRouter, + auth, + httpAuth, } = options; const readonlyEnabled = @@ -104,12 +108,16 @@ export async function createRouter( if (refreshService) { router.post('/refresh', async (req, res) => { - const refreshOptions: RefreshOptions = req.body; - refreshOptions.authorizationToken = getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ); + const { authorizationToken, ...restBody } = req.body; - await refreshService.refresh(refreshOptions); + const credentials = authorizationToken + ? await auth.authenticate(authorizationToken) + : await httpAuth.credentials(req); + + await refreshService.refresh({ + ...restBody, + credentials, + }); res.status(200).end(); }); } @@ -126,9 +134,7 @@ export async function createRouter( fields: parseEntityTransformParams(req.query), order: parseEntityOrderParams(req.query), pagination: parseEntityPaginationParams(req.query), - authorizationToken: getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ), + credentials: await httpAuth.credentials(req), }); // Add a Link header to the next page @@ -147,9 +153,7 @@ export async function createRouter( await entitiesCatalog.queryEntities({ limit: req.query.limit, ...parseQueryEntitiesParams(req.query), - authorizationToken: getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ), + credentials: await httpAuth.credentials(req), }); res.json({ @@ -169,9 +173,7 @@ export async function createRouter( const { uid } = req.params; const { entities } = await entitiesCatalog.entities({ filter: basicEntityFilter({ 'metadata.uid': uid }), - authorizationToken: getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ), + credentials: await httpAuth.credentials(req), }); if (!entities.length) { throw new NotFoundError(`No entity with uid ${uid}`); @@ -181,9 +183,7 @@ export async function createRouter( .delete('/entities/by-uid/:uid', async (req, res) => { const { uid } = req.params; await entitiesCatalog.removeEntityByUid(uid, { - authorizationToken: getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ), + credentials: await httpAuth.credentials(req), }); res.status(204).end(); }) @@ -195,9 +195,7 @@ export async function createRouter( 'metadata.namespace': namespace, 'metadata.name': name, }), - authorizationToken: getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ), + credentials: await httpAuth.credentials(req), }); if (!entities.length) { throw new NotFoundError( @@ -212,22 +210,17 @@ export async function createRouter( const { kind, namespace, name } = req.params; const entityRef = stringifyEntityRef({ kind, namespace, name }); const response = await entitiesCatalog.entityAncestry(entityRef, { - authorizationToken: getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ), + credentials: await httpAuth.credentials(req), }); res.status(200).json(response); }, ) .post('/entities/by-refs', async (req, res) => { const request = entitiesBatchRequest(req); - const token = getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ); const response = await entitiesCatalog.entitiesBatch({ entityRefs: request.entityRefs, fields: parseEntityTransformParams(req.query, request.fields), - authorizationToken: token, + credentials: await httpAuth.credentials(req), }); res.status(200).json(response); }) @@ -235,9 +228,7 @@ export async function createRouter( const response = await entitiesCatalog.facets({ filter: parseEntityFilterParams(req.query), facets: parseEntityFacetParams(req.query), - authorizationToken: getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ), + credentials: await httpAuth.credentials(req), }); res.status(200).json(response); }); @@ -256,17 +247,13 @@ export async function createRouter( } const output = await locationService.createLocation(location, dryRun, { - authorizationToken: getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ), + credentials: await httpAuth.credentials(req), }); res.status(201).json(output); }) .get('/locations', async (req, res) => { const locations = await locationService.listLocations({ - authorizationToken: getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ), + credentials: await httpAuth.credentials(req), }); res.status(200).json(locations.map(l => ({ data: l }))); }) @@ -274,9 +261,7 @@ export async function createRouter( .get('/locations/:id', async (req, res) => { const { id } = req.params; const output = await locationService.getLocation(id, { - authorizationToken: getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ), + credentials: await httpAuth.credentials(req), }); res.status(200).json(output); }) @@ -285,9 +270,7 @@ export async function createRouter( const { id } = req.params; await locationService.deleteLocation(id, { - authorizationToken: getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ), + credentials: await httpAuth.credentials(req), }); res.status(204).end(); }) @@ -295,11 +278,7 @@ export async function createRouter( const { kind, namespace, name } = req.params; const output = await locationService.getLocationByEntity( { kind, namespace, name }, - { - authorizationToken: getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ), - }, + { credentials: await httpAuth.credentials(req) }, ); res.status(200).json(output); }); diff --git a/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts b/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts index b1d5e8dd1f..919e97a1f7 100644 --- a/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts +++ b/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts @@ -28,12 +28,12 @@ import { internal } from '@backstage/backend-openapi-utils'; export function parseQueryEntitiesParams( params: internal.QuerySchema, -): Omit { +): Omit { const fields = parseEntityTransformParams(params); if (params.cursor) { const decodedCursor = decodeCursor(params.cursor); - const response: Omit = { + const response: Omit = { cursor: decodedCursor, fields, }; @@ -43,7 +43,7 @@ export function parseQueryEntitiesParams( const filter = parseEntityFilterParams(params); const orderFields = parseEntityOrderFieldParams(params); - const response: Omit = { + const response: Omit = { fields, filter, orderFields, diff --git a/plugins/catalog-backend/src/service/types.ts b/plugins/catalog-backend/src/service/types.ts index 878afe5662..30470e5af0 100644 --- a/plugins/catalog-backend/src/service/types.ts +++ b/plugins/catalog-backend/src/service/types.ts @@ -16,6 +16,7 @@ import { CompoundEntityRef, Entity } from '@backstage/catalog-model'; import { Location } from '@backstage/catalog-client'; +import { BackstageCredentials } from '@backstage/backend-plugin-api'; /** * Holds the information required to create a new location in the catalog location store. @@ -35,22 +36,24 @@ export interface LocationService { createLocation( location: LocationInput, dryRun: boolean, - options?: { - authorizationToken?: string; + options: { + credentials: BackstageCredentials; }, ): Promise<{ location: Location; entities: Entity[]; exists?: boolean }>; - listLocations(options?: { authorizationToken?: string }): Promise; + listLocations(options: { + credentials: BackstageCredentials; + }): Promise; getLocation( id: string, - options?: { authorizationToken?: string }, + options: { credentials: BackstageCredentials }, ): Promise; deleteLocation( id: string, - options?: { authorizationToken?: string }, + options: { credentials: BackstageCredentials }, ): Promise; getLocationByEntity( entityRef: CompoundEntityRef | string, - options?: { authorizationToken?: string }, + options: { credentials: BackstageCredentials }, ): Promise; } @@ -62,7 +65,7 @@ export interface LocationService { export type RefreshOptions = { /** The reference to a single entity that should be refreshed */ entityRef: string; - authorizationToken?: string; + credentials: BackstageCredentials; }; /** diff --git a/plugins/catalog-common/CHANGELOG.md b/plugins/catalog-common/CHANGELOG.md index 2dc6c4b356..bdce3bb20e 100644 --- a/plugins/catalog-common/CHANGELOG.md +++ b/plugins/catalog-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-common +## 1.0.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/catalog-model@1.4.5-next.0 + ## 1.0.21 ### Patch Changes diff --git a/plugins/catalog-common/package.json b/plugins/catalog-common/package.json index 35858ee400..36283ba8b5 100644 --- a/plugins/catalog-common/package.json +++ b/plugins/catalog-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-common", - "version": "1.0.21", + "version": "1.0.22-next.0", "description": "Common functionalities for the catalog plugin", "backstage": { "role": "common-library" diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index 8349ebcbff..13261916a9 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-graph +## 0.4.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/types@1.1.1 + ## 0.4.0 ### Minor Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 0aa451d86a..9f32c6c3ca 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graph", - "version": "0.4.0", + "version": "0.4.1-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 3c17240a00..21e5249850 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-catalog-import +## 0.10.7-next.0 + +### Patch Changes + +- 75f686b: Fixed an issue generating a wrong entity link at the end of the import process +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + ## 0.10.6 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 030a1ea036..3ae8336e07 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-import", - "version": "0.10.6", + "version": "0.10.7-next.0", "description": "A Backstage plugin the helps you import entities into your catalog", "backstage": { "role": "frontend-plugin" diff --git a/plugins/catalog-import/src/components/StepFinishImportLocation/StepFinishImportLocation.tsx b/plugins/catalog-import/src/components/StepFinishImportLocation/StepFinishImportLocation.tsx index 38372e59ba..cf5427517a 100644 --- a/plugins/catalog-import/src/components/StepFinishImportLocation/StepFinishImportLocation.tsx +++ b/plugins/catalog-import/src/components/StepFinishImportLocation/StepFinishImportLocation.tsx @@ -22,7 +22,7 @@ import { EntityListComponent } from '../EntityListComponent'; import { PrepareResult } from '../useImportState'; import { Link } from '@backstage/core-components'; import partition from 'lodash/partition'; -import { CompoundEntityRef } from '@backstage/catalog-model'; +import { CompoundEntityRef, DEFAULT_NAMESPACE } from '@backstage/catalog-model'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; import { useRouteRef } from '@backstage/core-plugin-api'; @@ -46,7 +46,12 @@ const filterComponentEntity = ( entity.kind.toLocaleLowerCase('en-US'), ) ) { - return entity; + return { + kind: entity.kind.toLocaleLowerCase('en-US'), + namespace: + entity.namespace?.toLocaleLowerCase('en-US') ?? DEFAULT_NAMESPACE, + name: entity.name, + }; } } } diff --git a/plugins/catalog-node/CHANGELOG.md b/plugins/catalog-node/CHANGELOG.md index 76697f2b61..a7f1e6720b 100644 --- a/plugins/catalog-node/CHANGELOG.md +++ b/plugins/catalog-node/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-catalog-node +## 1.8.0-next.0 + +### Minor Changes + +- df12231: Allow setting EntityDataParser using CatalogModelExtensionPoint + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.22-next.0 + ## 1.7.0 ### Minor Changes diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index 14d805b4d1..da50834dcc 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-node", - "version": "1.7.0", + "version": "1.8.0-next.0", "description": "The plugin-catalog-node module for @backstage/plugin-catalog-backend", "backstage": { "role": "node-library" diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index 52074a5503..d98b9dcf9c 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-catalog-react +## 1.10.1-next.0 + +### Patch Changes + +- 930b5c1: Added 'root' and 'label' class keys for EntityAutocompletePicker, EntityOwnerPicker and EntityProcessingStatusPicker +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-catalog-common@1.0.22-next.0 + - @backstage/plugin-permission-react@0.4.21-next.0 + ## 1.10.0 ### Minor Changes diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md index a492a72e9f..57fa247171 100644 --- a/plugins/catalog-react/api-report.md +++ b/plugins/catalog-react/api-report.md @@ -109,13 +109,10 @@ export type CatalogReactEntityLifecyclePickerClassKey = 'input'; export type CatalogReactEntityNamespacePickerClassKey = 'input'; // @public (undocumented) -export type CatalogReactEntityOwnerPickerClassKey = 'input' | 'root' | 'label'; +export type CatalogReactEntityOwnerPickerClassKey = 'input'; // @public (undocumented) -export type CatalogReactEntityProcessingStatusPickerClassKey = - | 'input' - | 'root' - | 'label'; +export type CatalogReactEntityProcessingStatusPickerClassKey = 'input'; // @public (undocumented) export type CatalogReactEntitySearchBarClassKey = 'searchToolbar' | 'input'; diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index ff89215fd7..407021ea0c 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.10.0", + "version": "1.10.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx b/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx index 87de6411b2..abba751e28 100644 --- a/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx +++ b/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx @@ -44,7 +44,7 @@ import { withStyles } from '@material-ui/core/styles'; import { useEntityPresentation } from '../../apis'; /** @public */ -export type CatalogReactEntityOwnerPickerClassKey = 'input' | 'root' | 'label'; +export type CatalogReactEntityOwnerPickerClassKey = 'input'; const useStyles = makeStyles( { diff --git a/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.tsx b/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.tsx index 2f63323967..e62fa7a6c7 100644 --- a/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.tsx +++ b/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.tsx @@ -31,10 +31,7 @@ import { useEntityList } from '../../hooks'; import { Autocomplete } from '@material-ui/lab'; /** @public */ -export type CatalogReactEntityProcessingStatusPickerClassKey = - | 'input' - | 'root' - | 'label'; +export type CatalogReactEntityProcessingStatusPickerClassKey = 'input'; const useStyles = makeStyles( { diff --git a/plugins/catalog-unprocessed-entities/CHANGELOG.md b/plugins/catalog-unprocessed-entities/CHANGELOG.md index be33d71aa3..d1a60a2b3c 100644 --- a/plugins/catalog-unprocessed-entities/CHANGELOG.md +++ b/plugins/catalog-unprocessed-entities/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-catalog-unprocessed-entities +## 0.1.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.1.8 ### Patch Changes diff --git a/plugins/catalog-unprocessed-entities/package.json b/plugins/catalog-unprocessed-entities/package.json index 4279cf4dcc..99c994a6eb 100644 --- a/plugins/catalog-unprocessed-entities/package.json +++ b/plugins/catalog-unprocessed-entities/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-unprocessed-entities", - "version": "0.1.8", + "version": "0.1.9-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index 54ce9bb816..205c7a7cff 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-catalog +## 1.17.1-next.0 + +### Patch Changes + +- 9332425: The entity page extension provided by the `/alpha` plugin now correctly renders the entity 404 page. +- 6727665: Allow the `spec.target` field to be searchable in the catalog table for locations. Previously, only the `spec.targets` field was be searchable. This makes locations generated by providers such as the `GithubEntityProvider` searchable in the catalog table. [#23098](https://github.com/backstage/backstage/issues/23098) +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.22-next.0 + - @backstage/plugin-permission-react@0.4.21-next.0 + - @backstage/plugin-scaffolder-common@1.5.1-next.0 + ## 1.17.0 ### Minor Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index e87b325991..d98cf25223 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog", - "version": "1.17.0", + "version": "1.17.1-next.0", "description": "The Backstage plugin for browsing the Backstage catalog", "backstage": { "role": "frontend-plugin" diff --git a/plugins/catalog/src/components/CatalogTable/columns.tsx b/plugins/catalog/src/components/CatalogTable/columns.tsx index 4260a0c26b..a955aaadb9 100644 --- a/plugins/catalog/src/components/CatalogTable/columns.tsx +++ b/plugins/catalog/src/components/CatalogTable/columns.tsx @@ -86,6 +86,21 @@ export const columnFactories = Object.freeze({ return { title: 'Targets', field: 'entity.spec.targets', + customFilterAndSearch: (query, row) => { + let targets: JsonArray = []; + if ( + row.entity?.spec?.targets && + Array.isArray(row.entity?.spec?.targets) + ) { + targets = row.entity?.spec?.targets; + } else if (row.entity?.spec?.target) { + targets = [row.entity?.spec?.target]; + } + return targets + .join(', ') + .toLocaleUpperCase('en-US') + .includes(query.toLocaleUpperCase('en-US')); + }, render: ({ entity }) => ( <> {(entity?.spec?.targets || entity?.spec?.target) && ( diff --git a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md index 75ed91f7a0..e06c671b69 100644 --- a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md +++ b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-cicd-statistics-module-gitlab +## 0.1.27-next.0 + +### Patch Changes + +- 402d991: Align `p-limit` dependency version to v3 +- Updated dependencies + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-cicd-statistics@0.1.33-next.0 + ## 0.1.26 ### Patch Changes diff --git a/plugins/cicd-statistics-module-gitlab/package.json b/plugins/cicd-statistics-module-gitlab/package.json index a08a2cb07c..48a0f1e3c4 100644 --- a/plugins/cicd-statistics-module-gitlab/package.json +++ b/plugins/cicd-statistics-module-gitlab/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cicd-statistics-module-gitlab", "description": "CI/CD Statistics plugin module; Gitlab CICD", - "version": "0.1.26", + "version": "0.1.27-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cicd-statistics/CHANGELOG.md b/plugins/cicd-statistics/CHANGELOG.md index 93cce5a7fe..f737bdaded 100644 --- a/plugins/cicd-statistics/CHANGELOG.md +++ b/plugins/cicd-statistics/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-cicd-statistics +## 0.1.33-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.1.32 ### Patch Changes diff --git a/plugins/cicd-statistics/package.json b/plugins/cicd-statistics/package.json index d0a90efcc9..cd800ada52 100644 --- a/plugins/cicd-statistics/package.json +++ b/plugins/cicd-statistics/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-cicd-statistics", - "version": "0.1.32", + "version": "0.1.33-next.0", "description": "A frontend plugin visualizing CI/CD pipeline statistics (build time)", "backstage": { "role": "frontend-plugin" diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md index 3e4f5ad208..41d4d7e944 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-circleci +## 0.3.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.3.30 ### Patch Changes diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index f60a3bb2bc..9f24bd7851 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-circleci", - "version": "0.3.30", + "version": "0.3.31-next.0", "description": "A Backstage plugin that integrates towards Circle CI", "backstage": { "role": "frontend-plugin" diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md index e744db0a91..71117b654c 100644 --- a/plugins/cloudbuild/CHANGELOG.md +++ b/plugins/cloudbuild/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-cloudbuild +## 0.4.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.4.0 ### Minor Changes diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 0aed36d3cc..066d651338 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-cloudbuild", - "version": "0.4.0", + "version": "0.4.1-next.0", "description": "A Backstage plugin that integrates towards Google Cloud Build", "backstage": { "role": "frontend-plugin" diff --git a/plugins/code-climate/CHANGELOG.md b/plugins/code-climate/CHANGELOG.md index 76c0241349..7ddd662395 100644 --- a/plugins/code-climate/CHANGELOG.md +++ b/plugins/code-climate/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-code-climate +## 0.1.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.1.30 ### Patch Changes diff --git a/plugins/code-climate/package.json b/plugins/code-climate/package.json index 137c8729a4..ce31bea3ee 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.30", + "version": "0.1.31-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/code-coverage-backend/CHANGELOG.md b/plugins/code-coverage-backend/CHANGELOG.md index f582f5a30e..98bf06357b 100644 --- a/plugins/code-coverage-backend/CHANGELOG.md +++ b/plugins/code-coverage-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-code-coverage-backend +## 0.2.27-next.0 + +### Patch Changes + +- cceebae: Fix jacoco convertor to not require annotation to be set to scm-only. +- 8efe690: Migrated to support new auth services. +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.2.24 ### Patch Changes diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index b44f608bbb..a0142c3265 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.24", + "version": "0.2.27-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 c672a138f2..2824a72abc 100644 --- a/plugins/code-coverage/CHANGELOG.md +++ b/plugins/code-coverage/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-code-coverage +## 0.2.24-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.2.23 ### Patch Changes diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index bdefece916..111a01f196 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.23", + "version": "0.2.24-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 3a5f884af0..9a14ab4e82 100644 --- a/plugins/codescene/CHANGELOG.md +++ b/plugins/codescene/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-codescene +## 0.1.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.1.22 ### Patch Changes diff --git a/plugins/codescene/package.json b/plugins/codescene/package.json index cf18ebdaf5..fcb1ddecc3 100644 --- a/plugins/codescene/package.json +++ b/plugins/codescene/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-codescene", - "version": "0.1.22", + "version": "0.1.23-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 216736ce13..23b5672979 100644 --- a/plugins/config-schema/CHANGELOG.md +++ b/plugins/config-schema/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-config-schema +## 0.1.51-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + ## 0.1.50 ### Patch Changes diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index ba1c16af37..6ef240186d 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-config-schema", - "version": "0.1.50", + "version": "0.1.51-next.0", "description": "A Backstage plugin that lets you browse the configuration schema of your app", "backstage": { "role": "frontend-plugin" diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index d9d741db61..9e4c859cef 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-cost-insights +## 0.12.20-next.0 + +### Patch Changes + +- 1b4fd09: Updated dependency `yup` to `^1.0.0`. +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-cost-insights-common@0.1.2 + ## 0.12.19 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 50c6119655..1e6638d792 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-cost-insights", - "version": "0.12.19", + "version": "0.12.20-next.0", "description": "A Backstage plugin that helps you keep track of your cloud spend", "backstage": { "role": "frontend-plugin" diff --git a/plugins/devtools-backend/CHANGELOG.md b/plugins/devtools-backend/CHANGELOG.md index 7f076b0c9f..8b611fc7e9 100644 --- a/plugins/devtools-backend/CHANGELOG.md +++ b/plugins/devtools-backend/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-devtools-backend +## 0.3.0-next.0 + +### Minor Changes + +- 4dc5b48: **BREAKING**: The `createRouter` method now requires the `discovery` service to be forwarded from the plugin environment. This is part of the migration to support new auth services. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/config-loader@1.6.3-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/cli-common@0.1.13 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.9-next.0 + ## 0.2.7 ### Patch Changes diff --git a/plugins/devtools-backend/api-report.md b/plugins/devtools-backend/api-report.md index b9eb7b5a0c..9bde25bd54 100644 --- a/plugins/devtools-backend/api-report.md +++ b/plugins/devtools-backend/api-report.md @@ -7,10 +7,12 @@ import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { ConfigInfo } from '@backstage/plugin-devtools-common'; import { DevToolsInfo } from '@backstage/plugin-devtools-common'; +import { DiscoveryService } from '@backstage/backend-plugin-api'; import express from 'express'; import { ExternalDependency } from '@backstage/plugin-devtools-common'; +import { HttpAuthService } from '@backstage/backend-plugin-api'; import { Logger } from 'winston'; -import { PermissionEvaluator } from '@backstage/plugin-permission-common'; +import { PermissionsService } from '@backstage/backend-plugin-api'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; @@ -37,8 +39,12 @@ export interface RouterOptions { // (undocumented) devToolsBackendApi?: DevToolsBackendApi; // (undocumented) + discovery: DiscoveryService; + // (undocumented) + httpAuth?: HttpAuthService; + // (undocumented) logger: Logger; // (undocumented) - permissions: PermissionEvaluator; + permissions: PermissionsService; } ``` diff --git a/plugins/devtools-backend/package.json b/plugins/devtools-backend/package.json index 3b6f3b60ca..15d2f0d8a2 100644 --- a/plugins/devtools-backend/package.json +++ b/plugins/devtools-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-devtools-backend", - "version": "0.2.7", + "version": "0.3.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -54,6 +54,7 @@ "yn": "^4.0.0" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/minimist": "^1.2.0", "@types/ping": "^0.4.1", diff --git a/plugins/devtools-backend/src/plugin.ts b/plugins/devtools-backend/src/plugin.ts index 685522557e..28447e02cc 100644 --- a/plugins/devtools-backend/src/plugin.ts +++ b/plugins/devtools-backend/src/plugin.ts @@ -35,13 +35,24 @@ export const devtoolsPlugin = createBackendPlugin({ logger: coreServices.logger, permissions: coreServices.permissions, httpRouter: coreServices.httpRouter, + discovery: coreServices.discovery, + httpAuth: coreServices.httpAuth, }, - async init({ config, logger, permissions, httpRouter }) { + async init({ + config, + logger, + permissions, + httpRouter, + discovery, + httpAuth, + }) { httpRouter.use( await createRouter({ config, logger: loggerToWinstonLogger(logger), permissions, + discovery, + httpAuth, }), ); }, diff --git a/plugins/devtools-backend/src/service/router.test.ts b/plugins/devtools-backend/src/service/router.test.ts index f3c78242cf..fe4f176a04 100644 --- a/plugins/devtools-backend/src/service/router.test.ts +++ b/plugins/devtools-backend/src/service/router.test.ts @@ -20,6 +20,7 @@ import express from 'express'; import request from 'supertest'; import { PermissionEvaluator } from '@backstage/plugin-permission-common'; import { createRouter } from './router'; +import { mockServices } from '@backstage/backend-test-utils'; const mockedAuthorize: jest.MockedFunction = jest.fn(); @@ -49,6 +50,7 @@ describe('createRouter', () => { ], }, }), + discovery: mockServices.discovery(), permissions: permissionEvaluator, }); app = express().use(router); diff --git a/plugins/devtools-backend/src/service/router.ts b/plugins/devtools-backend/src/service/router.ts index fbeeb5af84..4c964dfbc5 100644 --- a/plugins/devtools-backend/src/service/router.ts +++ b/plugins/devtools-backend/src/service/router.ts @@ -13,10 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { - AuthorizeResult, - PermissionEvaluator, -} from '@backstage/plugin-permission-common'; +import { AuthorizeResult } from '@backstage/plugin-permission-common'; import { devToolsConfigReadPermission, devToolsExternalDependenciesReadPermission, @@ -29,17 +26,26 @@ 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 { + createLegacyAuthAdapters, + errorHandler, +} from '@backstage/backend-common'; import express from 'express'; -import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node'; import { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node'; +import { + DiscoveryService, + HttpAuthService, + PermissionsService, +} from '@backstage/backend-plugin-api'; /** @public */ export interface RouterOptions { devToolsBackendApi?: DevToolsBackendApi; logger: Logger; config: Config; - permissions: PermissionEvaluator; + permissions: PermissionsService; + discovery: DiscoveryService; + httpAuth?: HttpAuthService; } /** @public */ @@ -48,6 +54,8 @@ export async function createRouter( ): Promise { const { logger, config, permissions } = options; + const { httpAuth } = createLegacyAuthAdapters(options); + const devToolsBackendApi = options.devToolsBackendApi || new DevToolsBackendApi(logger, config); @@ -64,16 +72,10 @@ export async function createRouter( }); router.get('/info', async (req, response) => { - const token = getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ); - const decision = ( await permissions.authorize( [{ permission: devToolsInfoReadPermission }], - { - token, - }, + { credentials: await httpAuth.credentials(req) }, ) )[0]; @@ -87,16 +89,10 @@ export async function createRouter( }); router.get('/config', async (req, response) => { - const token = getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ); - const decision = ( await permissions.authorize( [{ permission: devToolsConfigReadPermission }], - { - token, - }, + { credentials: await httpAuth.credentials(req) }, ) )[0]; @@ -110,16 +106,10 @@ export async function createRouter( }); router.get('/external-dependencies', async (req, response) => { - const token = getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ); - const decision = ( await permissions.authorize( [{ permission: devToolsExternalDependenciesReadPermission }], - { - token, - }, + { credentials: await httpAuth.credentials(req) }, ) )[0]; diff --git a/plugins/devtools-backend/src/service/standaloneServer.ts b/plugins/devtools-backend/src/service/standaloneServer.ts index 43edb47935..75404e98b2 100644 --- a/plugins/devtools-backend/src/service/standaloneServer.ts +++ b/plugins/devtools-backend/src/service/standaloneServer.ts @@ -50,6 +50,7 @@ export async function startStandaloneServer( logger, config, permissions, + discovery, }); let service = createServiceBuilder(module) diff --git a/plugins/devtools-common/CHANGELOG.md b/plugins/devtools-common/CHANGELOG.md index 3bbc48a585..d5036b1086 100644 --- a/plugins/devtools-common/CHANGELOG.md +++ b/plugins/devtools-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-devtools-common +## 0.1.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/types@1.1.1 + ## 0.1.8 ### Patch Changes diff --git a/plugins/devtools-common/package.json b/plugins/devtools-common/package.json index 8f127fa063..af0aa6aef7 100644 --- a/plugins/devtools-common/package.json +++ b/plugins/devtools-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-devtools-common", - "version": "0.1.8", + "version": "0.1.9-next.0", "description": "Common functionalities for the devtools plugin", "backstage": { "role": "common-library" diff --git a/plugins/devtools/CHANGELOG.md b/plugins/devtools/CHANGELOG.md index 31ce5e2065..9efec5be1e 100644 --- a/plugins/devtools/CHANGELOG.md +++ b/plugins/devtools/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-devtools +## 0.1.10-next.0 + +### Patch Changes + +- a0e3393: Updated to use `fetchApi` as per [ADR013](https://backstage.io/docs/architecture-decisions/adrs-adr013) +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/plugin-devtools-common@0.1.9-next.0 + - @backstage/plugin-permission-react@0.4.21-next.0 + ## 0.1.9 ### Patch Changes diff --git a/plugins/devtools/package.json b/plugins/devtools/package.json index 987c01cf2c..cc80401309 100644 --- a/plugins/devtools/package.json +++ b/plugins/devtools/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-devtools", - "version": "0.1.9", + "version": "0.1.10-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/dynatrace/CHANGELOG.md b/plugins/dynatrace/CHANGELOG.md index d3d3ce0540..a59ad0f76c 100644 --- a/plugins/dynatrace/CHANGELOG.md +++ b/plugins/dynatrace/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-dynatrace +## 9.0.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 9.0.0 ### Patch Changes diff --git a/plugins/dynatrace/package.json b/plugins/dynatrace/package.json index cc318ece25..442248ab48 100644 --- a/plugins/dynatrace/package.json +++ b/plugins/dynatrace/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-dynatrace", - "version": "9.0.0", + "version": "9.0.1-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/entity-feedback-backend/CHANGELOG.md b/plugins/entity-feedback-backend/CHANGELOG.md index 7e74da5f07..803ba234af 100644 --- a/plugins/entity-feedback-backend/CHANGELOG.md +++ b/plugins/entity-feedback-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-entity-feedback-backend +## 0.2.10-next.0 + +### Patch Changes + +- 4f8ecd6: Migrated to support new auth services. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-entity-feedback-common@0.1.3 + ## 0.2.7 ### Patch Changes diff --git a/plugins/entity-feedback-backend/package.json b/plugins/entity-feedback-backend/package.json index 896b2c9c14..8906b52aae 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.2.7", + "version": "0.2.10-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 b65968d94a..17a3827cbf 100644 --- a/plugins/entity-feedback/CHANGELOG.md +++ b/plugins/entity-feedback/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-entity-feedback +## 0.2.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-entity-feedback-common@0.1.3 + ## 0.2.13 ### Patch Changes diff --git a/plugins/entity-feedback/package.json b/plugins/entity-feedback/package.json index 3f888ad1b2..9bd8483600 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.13", + "version": "0.2.14-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/entity-validation/CHANGELOG.md b/plugins/entity-validation/CHANGELOG.md index 4ccd539432..c3dffced2a 100644 --- a/plugins/entity-validation/CHANGELOG.md +++ b/plugins/entity-validation/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-entity-validation +## 0.1.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + ## 0.1.15 ### Patch Changes diff --git a/plugins/entity-validation/package.json b/plugins/entity-validation/package.json index 7ae8a6404e..2c3e1a84d1 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.15", + "version": "0.1.16-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/events-backend-module-aws-sqs/CHANGELOG.md b/plugins/events-backend-module-aws-sqs/CHANGELOG.md index 679c3aeae6..4090745caf 100644 --- a/plugins/events-backend-module-aws-sqs/CHANGELOG.md +++ b/plugins/events-backend-module-aws-sqs/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/plugin-events-backend-module-aws-sqs +## 0.3.0-next.0 + +### Minor Changes + +- 132d672: BREAKING CHANGE: Migrate `AwsSqsConsumingEventPublisher` and its backend module to use `EventsService`. + + Uses the `EventsService` instead of `EventBroker` at `AwsSqsConsumingEventPublisher`, + dropping the use of `EventPublisher` including `setEventBroker(..)`. + + Now, `AwsSqsConsumingEventPublisher.fromConfig` requires `events: EventsService` as option. + + ```diff + const sqs = AwsSqsConsumingEventPublisher.fromConfig({ + config: env.config, + + events: env.events, + logger: env.logger, + scheduler: env.scheduler, + }); + + await Promise.all(sqs.map(publisher => publisher.start())); + + // e.g. at packages/backend/src/plugins/events.ts + - await new EventsBackend(env.logger) + - .setEventBroker(env.eventBroker) + - .addPublishers(sqs) + - .start(); + + // or for other kinds of setups + - await Promise.all(sqs.map(publisher => publisher.setEventBroker(eventBroker))); + ``` + + `eventsModuleAwsSqsConsumingEventPublisher` uses the `eventsServiceRef` as dependency, + instead of `eventsExtensionPoint`. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + ## 0.2.13 ### Patch Changes diff --git a/plugins/events-backend-module-aws-sqs/package.json b/plugins/events-backend-module-aws-sqs/package.json index 41f91d804e..23fbb7e7f7 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.2.13", + "version": "0.3.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-azure/CHANGELOG.md b/plugins/events-backend-module-azure/CHANGELOG.md index 5b24f805e4..b4c7078b18 100644 --- a/plugins/events-backend-module-azure/CHANGELOG.md +++ b/plugins/events-backend-module-azure/CHANGELOG.md @@ -1,5 +1,83 @@ # @backstage/plugin-events-backend-module-azure +## 0.2.0-next.0 + +### Minor Changes + +- eff3ca9: BREAKING CHANGE: Migrate `EventRouter` implementations from `EventBroker` to `EventsService`. + + `EventRouter` uses the new `EventsService` instead of the `EventBroker` now, + causing a breaking change to its signature. + + All of its extensions and implementations got adjusted accordingly. + (`SubTopicEventRouter`, `AzureDevOpsEventRouter`, `BitbucketCloudEventRouter`, + `GerritEventRouter`, `GithubEventRouter`, `GitlabEventRouter`) + + Required adjustments were made to all backend modules for the new backend system, + now also making use of the `eventsServiceRef` instead of the `eventsExtensionPoint`. + + **Migration:** + + Example for implementations of `SubTopicEventRouter`: + + ```diff + import { + EventParams, + + EventsService, + SubTopicEventRouter, + } from '@backstage/plugin-events-node'; + + export class GithubEventRouter extends SubTopicEventRouter { + - constructor() { + - super('github'); + + constructor(options: { events: EventsService }) { + + super({ + + events: options.events, + + topic: 'github', + + }); + } + + + protected getSubscriberId(): string { + + return 'GithubEventRouter'; + + } + + + // ... + } + ``` + + Example for a direct extension of `EventRouter`: + + ```diff + class MyEventRouter extends EventRouter { + - constructor(/* ... */) { + + constructor(options: { + + events: EventsService; + + // ... + + }) { + - super(); + // ... + + super({ + + events: options.events, + + topics: topics, + + }); + } + + + + protected getSubscriberId(): string { + + return 'MyEventRouter'; + + } + - + - supportsEventTopics(): string[] { + - return this.topics; + - } + } + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + ## 0.1.20 ### Patch Changes diff --git a/plugins/events-backend-module-azure/package.json b/plugins/events-backend-module-azure/package.json index 0ee9f2dbfc..abec6269f0 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.20", + "version": "0.2.0-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 0ef47c8ce7..2bf9126fb8 100644 --- a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,83 @@ # @backstage/plugin-events-backend-module-bitbucket-cloud +## 0.2.0-next.0 + +### Minor Changes + +- eff3ca9: BREAKING CHANGE: Migrate `EventRouter` implementations from `EventBroker` to `EventsService`. + + `EventRouter` uses the new `EventsService` instead of the `EventBroker` now, + causing a breaking change to its signature. + + All of its extensions and implementations got adjusted accordingly. + (`SubTopicEventRouter`, `AzureDevOpsEventRouter`, `BitbucketCloudEventRouter`, + `GerritEventRouter`, `GithubEventRouter`, `GitlabEventRouter`) + + Required adjustments were made to all backend modules for the new backend system, + now also making use of the `eventsServiceRef` instead of the `eventsExtensionPoint`. + + **Migration:** + + Example for implementations of `SubTopicEventRouter`: + + ```diff + import { + EventParams, + + EventsService, + SubTopicEventRouter, + } from '@backstage/plugin-events-node'; + + export class GithubEventRouter extends SubTopicEventRouter { + - constructor() { + - super('github'); + + constructor(options: { events: EventsService }) { + + super({ + + events: options.events, + + topic: 'github', + + }); + } + + + protected getSubscriberId(): string { + + return 'GithubEventRouter'; + + } + + + // ... + } + ``` + + Example for a direct extension of `EventRouter`: + + ```diff + class MyEventRouter extends EventRouter { + - constructor(/* ... */) { + + constructor(options: { + + events: EventsService; + + // ... + + }) { + - super(); + // ... + + super({ + + events: options.events, + + topics: topics, + + }); + } + + + + protected getSubscriberId(): string { + + return 'MyEventRouter'; + + } + - + - supportsEventTopics(): string[] { + - return this.topics; + - } + } + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + ## 0.1.20 ### Patch Changes diff --git a/plugins/events-backend-module-bitbucket-cloud/package.json b/plugins/events-backend-module-bitbucket-cloud/package.json index 5273652f44..b57af9a7ec 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.20", + "version": "0.2.0-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 d177b5203d..49d4784451 100644 --- a/plugins/events-backend-module-gerrit/CHANGELOG.md +++ b/plugins/events-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,83 @@ # @backstage/plugin-events-backend-module-gerrit +## 0.2.0-next.0 + +### Minor Changes + +- eff3ca9: BREAKING CHANGE: Migrate `EventRouter` implementations from `EventBroker` to `EventsService`. + + `EventRouter` uses the new `EventsService` instead of the `EventBroker` now, + causing a breaking change to its signature. + + All of its extensions and implementations got adjusted accordingly. + (`SubTopicEventRouter`, `AzureDevOpsEventRouter`, `BitbucketCloudEventRouter`, + `GerritEventRouter`, `GithubEventRouter`, `GitlabEventRouter`) + + Required adjustments were made to all backend modules for the new backend system, + now also making use of the `eventsServiceRef` instead of the `eventsExtensionPoint`. + + **Migration:** + + Example for implementations of `SubTopicEventRouter`: + + ```diff + import { + EventParams, + + EventsService, + SubTopicEventRouter, + } from '@backstage/plugin-events-node'; + + export class GithubEventRouter extends SubTopicEventRouter { + - constructor() { + - super('github'); + + constructor(options: { events: EventsService }) { + + super({ + + events: options.events, + + topic: 'github', + + }); + } + + + protected getSubscriberId(): string { + + return 'GithubEventRouter'; + + } + + + // ... + } + ``` + + Example for a direct extension of `EventRouter`: + + ```diff + class MyEventRouter extends EventRouter { + - constructor(/* ... */) { + + constructor(options: { + + events: EventsService; + + // ... + + }) { + - super(); + // ... + + super({ + + events: options.events, + + topics: topics, + + }); + } + + + + protected getSubscriberId(): string { + + return 'MyEventRouter'; + + } + - + - supportsEventTopics(): string[] { + - return this.topics; + - } + } + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + ## 0.1.20 ### Patch Changes diff --git a/plugins/events-backend-module-gerrit/package.json b/plugins/events-backend-module-gerrit/package.json index 436fbde891..49071816f7 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.20", + "version": "0.2.0-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 ccdc490bb0..921a3cdaac 100644 --- a/plugins/events-backend-module-github/CHANGELOG.md +++ b/plugins/events-backend-module-github/CHANGELOG.md @@ -1,5 +1,84 @@ # @backstage/plugin-events-backend-module-github +## 0.2.0-next.0 + +### Minor Changes + +- eff3ca9: BREAKING CHANGE: Migrate `EventRouter` implementations from `EventBroker` to `EventsService`. + + `EventRouter` uses the new `EventsService` instead of the `EventBroker` now, + causing a breaking change to its signature. + + All of its extensions and implementations got adjusted accordingly. + (`SubTopicEventRouter`, `AzureDevOpsEventRouter`, `BitbucketCloudEventRouter`, + `GerritEventRouter`, `GithubEventRouter`, `GitlabEventRouter`) + + Required adjustments were made to all backend modules for the new backend system, + now also making use of the `eventsServiceRef` instead of the `eventsExtensionPoint`. + + **Migration:** + + Example for implementations of `SubTopicEventRouter`: + + ```diff + import { + EventParams, + + EventsService, + SubTopicEventRouter, + } from '@backstage/plugin-events-node'; + + export class GithubEventRouter extends SubTopicEventRouter { + - constructor() { + - super('github'); + + constructor(options: { events: EventsService }) { + + super({ + + events: options.events, + + topic: 'github', + + }); + } + + + protected getSubscriberId(): string { + + return 'GithubEventRouter'; + + } + + + // ... + } + ``` + + Example for a direct extension of `EventRouter`: + + ```diff + class MyEventRouter extends EventRouter { + - constructor(/* ... */) { + + constructor(options: { + + events: EventsService; + + // ... + + }) { + - super(); + // ... + + super({ + + events: options.events, + + topics: topics, + + }); + } + + + + protected getSubscriberId(): string { + + return 'MyEventRouter'; + + } + - + - supportsEventTopics(): string[] { + - return this.topics; + - } + } + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.1.20 ### Patch Changes diff --git a/plugins/events-backend-module-github/package.json b/plugins/events-backend-module-github/package.json index 209167f64c..18f3cd274e 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.20", + "version": "0.2.0-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 4a91b368bf..96adc084a5 100644 --- a/plugins/events-backend-module-gitlab/CHANGELOG.md +++ b/plugins/events-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,84 @@ # @backstage/plugin-events-backend-module-gitlab +## 0.2.0-next.0 + +### Minor Changes + +- eff3ca9: BREAKING CHANGE: Migrate `EventRouter` implementations from `EventBroker` to `EventsService`. + + `EventRouter` uses the new `EventsService` instead of the `EventBroker` now, + causing a breaking change to its signature. + + All of its extensions and implementations got adjusted accordingly. + (`SubTopicEventRouter`, `AzureDevOpsEventRouter`, `BitbucketCloudEventRouter`, + `GerritEventRouter`, `GithubEventRouter`, `GitlabEventRouter`) + + Required adjustments were made to all backend modules for the new backend system, + now also making use of the `eventsServiceRef` instead of the `eventsExtensionPoint`. + + **Migration:** + + Example for implementations of `SubTopicEventRouter`: + + ```diff + import { + EventParams, + + EventsService, + SubTopicEventRouter, + } from '@backstage/plugin-events-node'; + + export class GithubEventRouter extends SubTopicEventRouter { + - constructor() { + - super('github'); + + constructor(options: { events: EventsService }) { + + super({ + + events: options.events, + + topic: 'github', + + }); + } + + + protected getSubscriberId(): string { + + return 'GithubEventRouter'; + + } + + + // ... + } + ``` + + Example for a direct extension of `EventRouter`: + + ```diff + class MyEventRouter extends EventRouter { + - constructor(/* ... */) { + + constructor(options: { + + events: EventsService; + + // ... + + }) { + - super(); + // ... + + super({ + + events: options.events, + + topics: topics, + + }); + } + + + + protected getSubscriberId(): string { + + return 'MyEventRouter'; + + } + - + - supportsEventTopics(): string[] { + - return this.topics; + - } + } + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.1.20 ### Patch Changes diff --git a/plugins/events-backend-module-gitlab/package.json b/plugins/events-backend-module-gitlab/package.json index 08abb12b8f..0ba3950dff 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.20", + "version": "0.2.0-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 f8a63937dc..a9da4560c9 100644 --- a/plugins/events-backend-test-utils/CHANGELOG.md +++ b/plugins/events-backend-test-utils/CHANGELOG.md @@ -1,5 +1,46 @@ # @backstage/plugin-events-backend-test-utils +## 0.1.23-next.0 + +### Patch Changes + +- 56969b6: Add new `EventsService` as well as `eventsServiceRef` for the new backend system. + + **Summary:** + + - new: + `EventsService`, `eventsServiceRef`, `TestEventsService` + - deprecated: + `EventBroker`, `EventPublisher`, `EventSubscriber`, `DefaultEventBroker`, `EventsBackend`, + most parts of `EventsExtensionPoint` (alpha), + `TestEventBroker`, `TestEventPublisher`, `TestEventSubscriber` + + Add the `eventsServiceRef` as dependency to your backend plugins + or backend plugin modules. + + **Details:** + + The previous implementation using the `EventsExtensionPoint` was added in the early stages + of the new backend system and does not respect the plugin isolation. + This made it not compatible anymore with the new backend system. + + Additionally, the previous interfaces had some room for simplification, + supporting less exposure of internal concerns as well. + + Hereby, this change adds a new `EventsService` interface as replacement for the now deprecated `EventBroker`. + The new interface does not require any `EventPublisher` or `EventSubscriber` interfaces anymore. + Instead, it is expected that the `EventsService` gets passed into publishers and subscribers, + and used internally. There is no need to expose anything of that at their own interfaces. + + Most parts of `EventsExtensionPoint` (alpha) are deprecated as well and were not usable + (by other plugins or their modules) anyway. + + The `DefaultEventBroker` implementation is deprecated and wraps the new `DefaultEventsService` implementation. + Optionally, an instance can be passed as argument to allow mixed setups to operate alongside. + +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + ## 0.1.20 ### Patch Changes diff --git a/plugins/events-backend-test-utils/package.json b/plugins/events-backend-test-utils/package.json index 6479a3e86d..c0254c05b7 100644 --- a/plugins/events-backend-test-utils/package.json +++ b/plugins/events-backend-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-test-utils", - "version": "0.1.20", + "version": "0.1.23-next.0", "description": "The plugin-events-backend-test-utils for @backstage/plugin-events-node", "backstage": { "role": "node-library" diff --git a/plugins/events-backend/CHANGELOG.md b/plugins/events-backend/CHANGELOG.md index 3bf273a16d..73a5eed772 100644 --- a/plugins/events-backend/CHANGELOG.md +++ b/plugins/events-backend/CHANGELOG.md @@ -1,5 +1,83 @@ # @backstage/plugin-events-backend +## 0.3.0-next.0 + +### Minor Changes + +- c4bd794: BREAKING CHANGE: Migrate `HttpPostIngressEventPublisher` and `eventsPlugin` to use `EventsService`. + + Uses the `EventsService` instead of `EventBroker` at `HttpPostIngressEventPublisher`, + dropping the use of `EventPublisher` including `setEventBroker(..)`. + + Now, `HttpPostIngressEventPublisher.fromConfig` requires `events: EventsService` as option. + + ```diff + const http = HttpPostIngressEventPublisher.fromConfig({ + config: env.config, + + events: env.events, + logger: env.logger, + }); + http.bind(eventsRouter); + + // e.g. at packages/backend/src/plugins/events.ts + - await new EventsBackend(env.logger) + - .setEventBroker(env.eventBroker) + - .addPublishers(http) + - .start(); + + // or for other kinds of setups + - await Promise.all(http.map(publisher => publisher.setEventBroker(eventBroker))); + ``` + + `eventsPlugin` uses the `eventsServiceRef` as dependency. + Unsupported (and deprecated) extension point methods will throw an error to prevent unintended behavior. + + ```ts + import { eventsServiceRef } from '@backstage/plugin-events-node'; + ``` + +### Patch Changes + +- 56969b6: Add new `EventsService` as well as `eventsServiceRef` for the new backend system. + + **Summary:** + + - new: + `EventsService`, `eventsServiceRef`, `TestEventsService` + - deprecated: + `EventBroker`, `EventPublisher`, `EventSubscriber`, `DefaultEventBroker`, `EventsBackend`, + most parts of `EventsExtensionPoint` (alpha), + `TestEventBroker`, `TestEventPublisher`, `TestEventSubscriber` + + Add the `eventsServiceRef` as dependency to your backend plugins + or backend plugin modules. + + **Details:** + + The previous implementation using the `EventsExtensionPoint` was added in the early stages + of the new backend system and does not respect the plugin isolation. + This made it not compatible anymore with the new backend system. + + Additionally, the previous interfaces had some room for simplification, + supporting less exposure of internal concerns as well. + + Hereby, this change adds a new `EventsService` interface as replacement for the now deprecated `EventBroker`. + The new interface does not require any `EventPublisher` or `EventSubscriber` interfaces anymore. + Instead, it is expected that the `EventsService` gets passed into publishers and subscribers, + and used internally. There is no need to expose anything of that at their own interfaces. + + Most parts of `EventsExtensionPoint` (alpha) are deprecated as well and were not usable + (by other plugins or their modules) anyway. + + The `DefaultEventBroker` implementation is deprecated and wraps the new `DefaultEventsService` implementation. + Optionally, an instance can be passed as argument to allow mixed setups to operate alongside. + +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.2.19 ### Patch Changes diff --git a/plugins/events-backend/package.json b/plugins/events-backend/package.json index 9365d8c7dc..86962bc9cd 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.19", + "version": "0.3.0-next.0", "backstage": { "role": "backend-plugin" }, diff --git a/plugins/events-node/CHANGELOG.md b/plugins/events-node/CHANGELOG.md index dfa8e3c28c..91625a2b11 100644 --- a/plugins/events-node/CHANGELOG.md +++ b/plugins/events-node/CHANGELOG.md @@ -1,5 +1,116 @@ # @backstage/plugin-events-node +## 0.3.0-next.0 + +### Minor Changes + +- eff3ca9: BREAKING CHANGE: Migrate `EventRouter` implementations from `EventBroker` to `EventsService`. + + `EventRouter` uses the new `EventsService` instead of the `EventBroker` now, + causing a breaking change to its signature. + + All of its extensions and implementations got adjusted accordingly. + (`SubTopicEventRouter`, `AzureDevOpsEventRouter`, `BitbucketCloudEventRouter`, + `GerritEventRouter`, `GithubEventRouter`, `GitlabEventRouter`) + + Required adjustments were made to all backend modules for the new backend system, + now also making use of the `eventsServiceRef` instead of the `eventsExtensionPoint`. + + **Migration:** + + Example for implementations of `SubTopicEventRouter`: + + ```diff + import { + EventParams, + + EventsService, + SubTopicEventRouter, + } from '@backstage/plugin-events-node'; + + export class GithubEventRouter extends SubTopicEventRouter { + - constructor() { + - super('github'); + + constructor(options: { events: EventsService }) { + + super({ + + events: options.events, + + topic: 'github', + + }); + } + + + protected getSubscriberId(): string { + + return 'GithubEventRouter'; + + } + + + // ... + } + ``` + + Example for a direct extension of `EventRouter`: + + ```diff + class MyEventRouter extends EventRouter { + - constructor(/* ... */) { + + constructor(options: { + + events: EventsService; + + // ... + + }) { + - super(); + // ... + + super({ + + events: options.events, + + topics: topics, + + }); + } + + + + protected getSubscriberId(): string { + + return 'MyEventRouter'; + + } + - + - supportsEventTopics(): string[] { + - return this.topics; + - } + } + ``` + +### Patch Changes + +- 56969b6: Add new `EventsService` as well as `eventsServiceRef` for the new backend system. + + **Summary:** + + - new: + `EventsService`, `eventsServiceRef`, `TestEventsService` + - deprecated: + `EventBroker`, `EventPublisher`, `EventSubscriber`, `DefaultEventBroker`, `EventsBackend`, + most parts of `EventsExtensionPoint` (alpha), + `TestEventBroker`, `TestEventPublisher`, `TestEventSubscriber` + + Add the `eventsServiceRef` as dependency to your backend plugins + or backend plugin modules. + + **Details:** + + The previous implementation using the `EventsExtensionPoint` was added in the early stages + of the new backend system and does not respect the plugin isolation. + This made it not compatible anymore with the new backend system. + + Additionally, the previous interfaces had some room for simplification, + supporting less exposure of internal concerns as well. + + Hereby, this change adds a new `EventsService` interface as replacement for the now deprecated `EventBroker`. + The new interface does not require any `EventPublisher` or `EventSubscriber` interfaces anymore. + Instead, it is expected that the `EventsService` gets passed into publishers and subscribers, + and used internally. There is no need to expose anything of that at their own interfaces. + + Most parts of `EventsExtensionPoint` (alpha) are deprecated as well and were not usable + (by other plugins or their modules) anyway. + + The `DefaultEventBroker` implementation is deprecated and wraps the new `DefaultEventsService` implementation. + Optionally, an instance can be passed as argument to allow mixed setups to operate alongside. + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.13-next.0 + ## 0.2.19 ### Patch Changes diff --git a/plugins/events-node/package.json b/plugins/events-node/package.json index de794dfa45..c4c52d80a7 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.19", + "version": "0.3.0-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 cea1a2bc36..1f99edf3a8 100644 --- a/plugins/example-todo-list-backend/CHANGELOG.md +++ b/plugins/example-todo-list-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @internal/plugin-todo-list-backend +## 1.0.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + ## 1.0.22 ### Patch Changes diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index c6792746e9..5763f8646d 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.22", + "version": "1.0.23-next.0", "backstage": { "role": "backend-plugin" }, diff --git a/plugins/example-todo-list-common/CHANGELOG.md b/plugins/example-todo-list-common/CHANGELOG.md index 98d6bafa7f..996e07f24f 100644 --- a/plugins/example-todo-list-common/CHANGELOG.md +++ b/plugins/example-todo-list-common/CHANGELOG.md @@ -1,5 +1,12 @@ # @internal/plugin-todo-list-common +## 1.0.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + ## 1.0.17 ### Patch Changes diff --git a/plugins/example-todo-list-common/package.json b/plugins/example-todo-list-common/package.json index ccc97efe20..781a5d9d58 100644 --- a/plugins/example-todo-list-common/package.json +++ b/plugins/example-todo-list-common/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list-common", - "version": "1.0.17", + "version": "1.0.18-next.0", "backstage": { "role": "common-library" }, diff --git a/plugins/example-todo-list/CHANGELOG.md b/plugins/example-todo-list/CHANGELOG.md index 603c62aa38..40ffc85978 100644 --- a/plugins/example-todo-list/CHANGELOG.md +++ b/plugins/example-todo-list/CHANGELOG.md @@ -1,5 +1,13 @@ # @internal/plugin-todo-list +## 1.0.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 1.0.22 ### Patch Changes diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index 6faf4195a8..c13b594d04 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.22", + "version": "1.0.23-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/explore-backend/CHANGELOG.md b/plugins/explore-backend/CHANGELOG.md index 01121c27b1..f479b92c11 100644 --- a/plugins/explore-backend/CHANGELOG.md +++ b/plugins/explore-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-explore-backend +## 0.0.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-search-backend-module-explore@0.1.17-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + ## 0.0.20 ### Patch Changes diff --git a/plugins/explore-backend/package.json b/plugins/explore-backend/package.json index 285af827a5..ece82cd070 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.20", + "version": "0.0.23-next.0", "backstage": { "role": "backend-plugin" }, diff --git a/plugins/explore-react/CHANGELOG.md b/plugins/explore-react/CHANGELOG.md index 0b932fe2d1..8c8e062c7e 100644 --- a/plugins/explore-react/CHANGELOG.md +++ b/plugins/explore-react/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-explore-react +## 0.0.37-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-explore-common@0.0.2 + ## 0.0.36 ### Patch Changes diff --git a/plugins/explore-react/package.json b/plugins/explore-react/package.json index 6cae83ed87..bf00ed9804 100644 --- a/plugins/explore-react/package.json +++ b/plugins/explore-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-explore-react", - "version": "0.0.36", + "version": "0.0.37-next.0", "description": "A frontend library for Backstage plugins that want to interact with the explore plugin", "backstage": { "role": "web-library" diff --git a/plugins/explore/CHANGELOG.md b/plugins/explore/CHANGELOG.md index 5f33b90d50..c0f0b11390 100644 --- a/plugins/explore/CHANGELOG.md +++ b/plugins/explore/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-explore +## 0.4.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-explore-react@0.0.37-next.0 + ## 0.4.16 ### Patch Changes diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 177464db55..5118a9bfba 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-explore", - "version": "0.4.16", + "version": "0.4.17-next.0", "description": "A Backstage plugin for building an exploration page of your software ecosystem", "backstage": { "role": "frontend-plugin" diff --git a/plugins/firehydrant/CHANGELOG.md b/plugins/firehydrant/CHANGELOG.md index 7802f4de15..c3719e0634 100644 --- a/plugins/firehydrant/CHANGELOG.md +++ b/plugins/firehydrant/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-firehydrant +## 0.2.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.2.14 ### Patch Changes diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index f7eb4ae52e..c35e92bddf 100644 --- a/plugins/firehydrant/package.json +++ b/plugins/firehydrant/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-firehydrant", - "version": "0.2.14", + "version": "0.2.15-next.0", "description": "A Backstage plugin that integrates towards FireHydrant", "backstage": { "role": "frontend-plugin" diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md index e9ea93c948..4d49cfa496 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-fossa +## 0.2.63-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.2.62 ### Patch Changes diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index e3e45688b4..95136e34d2 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-fossa", - "version": "0.2.62", + "version": "0.2.63-next.0", "description": "A Backstage plugin that integrates towards FOSSA", "backstage": { "role": "frontend-plugin" diff --git a/plugins/gcalendar/CHANGELOG.md b/plugins/gcalendar/CHANGELOG.md index bd78001e47..03d51ee394 100644 --- a/plugins/gcalendar/CHANGELOG.md +++ b/plugins/gcalendar/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-gcalendar +## 0.3.24-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.3.23 ### Patch Changes diff --git a/plugins/gcalendar/package.json b/plugins/gcalendar/package.json index cf536e5c69..14dcc698f3 100644 --- a/plugins/gcalendar/package.json +++ b/plugins/gcalendar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gcalendar", - "version": "0.3.23", + "version": "0.3.24-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gcp-projects/CHANGELOG.md b/plugins/gcp-projects/CHANGELOG.md index bcc087cf0d..c05cd8e3fc 100644 --- a/plugins/gcp-projects/CHANGELOG.md +++ b/plugins/gcp-projects/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-gcp-projects +## 0.3.47-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.3.46 ### Patch Changes diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 0d4d30dd4a..5d6e91b97e 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gcp-projects", - "version": "0.3.46", + "version": "0.3.47-next.0", "description": "A Backstage plugin that helps you manage projects in GCP", "backstage": { "role": "frontend-plugin" diff --git a/plugins/git-release-manager/CHANGELOG.md b/plugins/git-release-manager/CHANGELOG.md index 4af88a88f4..adfeba3715 100644 --- a/plugins/git-release-manager/CHANGELOG.md +++ b/plugins/git-release-manager/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-git-release-manager +## 0.3.43-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.3.42 ### Patch Changes diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 85b31d6311..5178246a2b 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.42", + "version": "0.3.43-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -52,6 +52,7 @@ "@backstage/cli": "workspace:^", "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", + "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^14.0.0", diff --git a/plugins/git-release-manager/src/features/Features.test.tsx b/plugins/git-release-manager/src/features/Features.test.tsx index abde878648..ca1517b5dd 100644 --- a/plugins/git-release-manager/src/features/Features.test.tsx +++ b/plugins/git-release-manager/src/features/Features.test.tsx @@ -21,6 +21,10 @@ import { Features } from './Features'; import { mockCalverProject } from '../test-helpers/test-helpers'; import { TEST_IDS } from '../test-helpers/test-ids'; import { mockApiClient } from '../test-helpers/mock-api-client'; +import { MockErrorApi, TestApiProvider } from '@backstage/test-utils'; +import { translationApiRef } from '@backstage/core-plugin-api/alpha'; +import { MockTranslationApi } from '@backstage/test-utils/alpha'; +import { errorApiRef } from '@backstage/core-plugin-api'; jest.mock('@backstage/core-plugin-api', () => ({ ...jest.requireActual('@backstage/core-plugin-api'), @@ -35,18 +39,26 @@ jest.mock('../contexts/ProjectContext', () => ({ describe('Features', () => { it('should omit features omitted via configuration', async () => { const { getByTestId } = render( - [
Custom 1
,
Custom 2
], - }, - }} - />, + + [
Custom 1
,
Custom 2
], + }, + }} + /> + , +
, ); await waitFor(() => getByTestId(TEST_IDS.info.info)); diff --git a/plugins/git-release-manager/src/features/Info/Info.test.tsx b/plugins/git-release-manager/src/features/Info/Info.test.tsx index 1fcd53eb9c..c747a84d6e 100644 --- a/plugins/git-release-manager/src/features/Info/Info.test.tsx +++ b/plugins/git-release-manager/src/features/Info/Info.test.tsx @@ -15,14 +15,13 @@ */ import React from 'react'; -import { render } from '@testing-library/react'; - import { mockCalverProject, mockReleaseBranch, mockReleaseCandidateCalver, } from '../../test-helpers/test-helpers'; import { Info } from './Info'; +import { renderInTestApp } from '@backstage/test-utils'; jest.mock('../../contexts/ProjectContext', () => ({ useProjectContext: () => ({ @@ -32,7 +31,7 @@ jest.mock('../../contexts/ProjectContext', () => ({ describe('Info', () => { it('should return early if no latestRelease exists', async () => { - const { findByText } = render( + const { findByText } = await renderInTestApp( ({ ...jest.requireActual('@backstage/core-plugin-api'), @@ -56,13 +60,21 @@ describe('PatchBody', () => { }); const { getByTestId } = render( - , + + + , + , ); expect(getByTestId(TEST_IDS.patch.loading)).toBeInTheDocument(); @@ -74,13 +86,20 @@ describe('PatchBody', () => { it('should render not-prerelease description', async () => { const { getByTestId } = render( - , + + + , ); expect(getByTestId(TEST_IDS.patch.loading)).toBeInTheDocument(); diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index 573eafffdc..3de69b6bae 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-github-actions +## 0.6.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.6.11 ### Patch Changes diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index c805baa08a..292adc09af 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-actions", - "version": "0.6.11", + "version": "0.6.12-next.0", "description": "A Backstage plugin that integrates towards GitHub Actions", "backstage": { "role": "frontend-plugin" diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md index abeb448e6a..9b69945a56 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-github-deployments +## 0.1.62-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.1.61 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index 35adeb3328..48ca4f1a3e 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-deployments", - "version": "0.1.61", + "version": "0.1.62-next.0", "description": "A Backstage plugin that integrates towards GitHub Deployments", "backstage": { "role": "frontend-plugin" diff --git a/plugins/github-issues/CHANGELOG.md b/plugins/github-issues/CHANGELOG.md index 0fe3cefd17..f288d5048f 100644 --- a/plugins/github-issues/CHANGELOG.md +++ b/plugins/github-issues/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-github-issues +## 0.2.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.2.19 ### Patch Changes diff --git a/plugins/github-issues/package.json b/plugins/github-issues/package.json index 5f00caa0d6..1811e69834 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.19", + "version": "0.2.20-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/github-pull-requests-board/CHANGELOG.md b/plugins/github-pull-requests-board/CHANGELOG.md index 6137cafba0..cf0609e98d 100644 --- a/plugins/github-pull-requests-board/CHANGELOG.md +++ b/plugins/github-pull-requests-board/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-github-pull-requests-board +## 0.1.25-next.0 + +### Patch Changes + +- 3c2d7c0: The `CardHeader` component in the `github-pull-requests-board` plugin will show the status for the PR +- 402d991: Align `p-limit` dependency version to v3 +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.1.24 ### Patch Changes diff --git a/plugins/github-pull-requests-board/package.json b/plugins/github-pull-requests-board/package.json index e76bbb7505..663f08fd14 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.24", + "version": "0.1.25-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 96d6df21dd..abc82ce135 100644 --- a/plugins/gitops-profiles/CHANGELOG.md +++ b/plugins/gitops-profiles/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-gitops-profiles +## 0.3.46-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.3.45 ### Patch Changes diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index d75a81be96..a6b098e1c2 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gitops-profiles", - "version": "0.3.45", + "version": "0.3.46-next.0", "description": "A Backstage plugin that helps you manage GitOps profiles", "backstage": { "role": "frontend-plugin" diff --git a/plugins/gocd/CHANGELOG.md b/plugins/gocd/CHANGELOG.md index 3d333d3535..9d82d1e8a8 100644 --- a/plugins/gocd/CHANGELOG.md +++ b/plugins/gocd/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-gocd +## 0.1.37-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.1.36 ### Patch Changes diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index 42cb7bd1ee..fdc8c3a5ac 100644 --- a/plugins/gocd/package.json +++ b/plugins/gocd/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gocd", - "version": "0.1.36", + "version": "0.1.37-next.0", "description": "A Backstage plugin that integrates towards GoCD", "backstage": { "role": "frontend-plugin" diff --git a/plugins/gocd/src/components/GoCdBuildsComponent/GoCdBuildsComponent.test.tsx b/plugins/gocd/src/components/GoCdBuildsComponent/GoCdBuildsComponent.test.tsx index ebc3502901..57a219eb50 100644 --- a/plugins/gocd/src/components/GoCdBuildsComponent/GoCdBuildsComponent.test.tsx +++ b/plugins/gocd/src/components/GoCdBuildsComponent/GoCdBuildsComponent.test.tsx @@ -18,7 +18,7 @@ import { Entity } from '@backstage/catalog-model'; import { ConfigReader } from '@backstage/core-app-api'; import { ConfigApi, configApiRef } from '@backstage/core-plugin-api'; import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { renderWithEffects, TestApiProvider } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { GoCdBuildsComponent } from './GoCdBuildsComponent'; import { gocdApiRef } from '../../plugin'; import { GoCdApi } from '../../api/gocdApi'; @@ -41,7 +41,7 @@ describe('GoCdArtifactsComponent', () => { }; const renderComponent = () => - renderWithEffects( + renderInTestApp( ', () => { it('renders with mandatory parameters', async () => { - const { getByText } = await render( + const { getByText } = await renderInTestApp( , ); expect(getByText('My title')).toBeInTheDocument(); }); it('renders skeleton when loading is true', async () => { - const { container } = await render( + const { container } = await renderInTestApp( , ); expect(container.querySelectorAll('li')).toHaveLength(8); @@ -36,7 +35,7 @@ describe('', () => { }); it('renders specified amount of items', async () => { - const { container } = await render( + const { container } = await renderInTestApp( ', () => { }); it('renders some items hidden', async () => { - const { container } = await render( + const { container } = await renderInTestApp( ', () => { }); it('renders all items when not collapsed', async () => { - const { container } = await render( + const { container } = await renderInTestApp( ', () => { }); it('renders visit with time-ago', async () => { - const { container, getByText } = await render( - - - , - , + const { container, getByText } = await renderInTestApp( + , ); expect(container.querySelectorAll('li')).toHaveLength(1); expect(getByText('Explore Backstage')).toBeInTheDocument(); @@ -102,23 +98,20 @@ describe('', () => { }); it('renders visit with hits', async () => { - const { container, getByText } = await render( - - - , - , + const { container, getByText } = await renderInTestApp( + , ); expect(container.querySelectorAll('li')).toHaveLength(1); expect(getByText('Explore Backstage')).toBeInTheDocument(); @@ -126,23 +119,20 @@ describe('', () => { }); it('renders text warning about few items', async () => { - const { getByText } = await render( - - - , - , + const { getByText } = await renderInTestApp( + , ); expect( getByText('The more pages you visit, the more pages will appear here.'), @@ -150,10 +140,8 @@ describe('', () => { }); it('renders text warning about no items', async () => { - const { getByText } = await render( - - , - , + const { getByText } = await renderInTestApp( + , ); expect(getByText('There are no visits to show yet.')).toBeInTheDocument(); }); diff --git a/plugins/ilert/CHANGELOG.md b/plugins/ilert/CHANGELOG.md index 73e3332de2..d56468962c 100644 --- a/plugins/ilert/CHANGELOG.md +++ b/plugins/ilert/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-ilert +## 0.2.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.2.19 ### Patch Changes diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index 09ee791a4c..9684ca0472 100644 --- a/plugins/ilert/package.json +++ b/plugins/ilert/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-ilert", - "version": "0.2.19", + "version": "0.2.20-next.0", "description": "A Backstage plugin that integrates towards iLert", "backstage": { "role": "frontend-plugin" diff --git a/plugins/jenkins-backend/CHANGELOG.md b/plugins/jenkins-backend/CHANGELOG.md index facffbe68b..1cf6847e0e 100644 --- a/plugins/jenkins-backend/CHANGELOG.md +++ b/plugins/jenkins-backend/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-jenkins-backend +## 0.4.0-next.0 + +### Minor Changes + +- 55191cc: **BREAKING**: Both `createRouter` and `DefaultJenkinsInfoProvider.fromConfig` now require the `discovery` service to be forwarded from the plugin environment. This is part of the migration to support new auth services. + + The `JenkinsInfoProvider` interface has been updated to receive `credentials` of the type `BackstageCredentials` rather than a token. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-jenkins-common@0.1.25-next.0 + ## 0.3.4 ### Patch Changes diff --git a/plugins/jenkins-backend/package.json b/plugins/jenkins-backend/package.json index eaf8218a01..d4ffee38c3 100644 --- a/plugins/jenkins-backend/package.json +++ b/plugins/jenkins-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-jenkins-backend", "description": "A Backstage backend plugin that integrates towards Jenkins", - "version": "0.3.4", + "version": "0.4.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/jenkins-common/CHANGELOG.md b/plugins/jenkins-common/CHANGELOG.md index ae4f8a3c09..74ce3e0f44 100644 --- a/plugins/jenkins-common/CHANGELOG.md +++ b/plugins/jenkins-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-jenkins-common +## 0.1.25-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + ## 0.1.24 ### Patch Changes diff --git a/plugins/jenkins-common/package.json b/plugins/jenkins-common/package.json index e9f4295645..7293d16c96 100644 --- a/plugins/jenkins-common/package.json +++ b/plugins/jenkins-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-jenkins-common", - "version": "0.1.24", + "version": "0.1.25-next.0", "backstage": { "role": "common-library" }, diff --git a/plugins/jenkins/CHANGELOG.md b/plugins/jenkins/CHANGELOG.md index 91268405bb..9c16246e2c 100644 --- a/plugins/jenkins/CHANGELOG.md +++ b/plugins/jenkins/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-jenkins +## 0.9.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-jenkins-common@0.1.25-next.0 + ## 0.9.5 ### Patch Changes diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index 570c49734c..8ae7bc05a3 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-jenkins", - "version": "0.9.5", + "version": "0.9.6-next.0", "description": "A Backstage plugin that integrates towards Jenkins", "backstage": { "role": "frontend-plugin" diff --git a/plugins/kafka-backend/CHANGELOG.md b/plugins/kafka-backend/CHANGELOG.md index 3f1c86473f..43e85b4f5d 100644 --- a/plugins/kafka-backend/CHANGELOG.md +++ b/plugins/kafka-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-kafka-backend +## 0.3.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.3.8 ### Patch Changes diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index 29d538b354..398510211a 100644 --- a/plugins/kafka-backend/package.json +++ b/plugins/kafka-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kafka-backend", - "version": "0.3.8", + "version": "0.3.11-next.0", "description": "A Backstage backend plugin that integrates towards Kafka", "backstage": { "role": "backend-plugin" diff --git a/plugins/kafka/CHANGELOG.md b/plugins/kafka/CHANGELOG.md index 3eb846527b..354c82553d 100644 --- a/plugins/kafka/CHANGELOG.md +++ b/plugins/kafka/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-kafka +## 0.3.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.3.30 ### Patch Changes diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index 9df3023ab9..7280a2e958 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kafka", - "version": "0.3.30", + "version": "0.3.31-next.0", "description": "A Backstage plugin that integrates towards Kafka", "backstage": { "role": "frontend-plugin" diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index 2c499be769..6fb10afeb5 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-kubernetes-backend +## 0.16.0-next.0 + +### Minor Changes + +- e1e540c: **BREAKING**: The `KubernetesBuilder.createBuilder` method now requires the `discovery` service to be forwarded from the plugin environment. This is part of the migration to support new auth services. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/plugin-kubernetes-common@0.7.5-next.0 + - @backstage/plugin-kubernetes-node@0.1.7-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration-aws-node@0.1.10-next.0 + - @backstage/types@1.1.1 + ## 0.15.0 ### Minor Changes diff --git a/plugins/kubernetes-backend/api-report.md b/plugins/kubernetes-backend/api-report.md index afdb3bcf9a..60331ca044 100644 --- a/plugins/kubernetes-backend/api-report.md +++ b/plugins/kubernetes-backend/api-report.md @@ -5,12 +5,15 @@ ```ts import { AuthenticationStrategy as AuthenticationStrategy_2 } from '@backstage/plugin-kubernetes-node'; import { AuthMetadata as AuthMetadata_2 } from '@backstage/plugin-kubernetes-node'; +import { AuthService } from '@backstage/backend-plugin-api'; import { CatalogApi } from '@backstage/catalog-client'; import { ClusterDetails as ClusterDetails_2 } from '@backstage/plugin-kubernetes-node'; import { Config } from '@backstage/config'; import { CustomResource as CustomResource_2 } from '@backstage/plugin-kubernetes-node'; +import { DiscoveryService } from '@backstage/backend-plugin-api'; import { Duration } from 'luxon'; import express from 'express'; +import { HttpAuthService } from '@backstage/backend-plugin-api'; import * as k8sAuthTypes from '@backstage/plugin-kubernetes-node'; import { KubernetesClustersSupplier as KubernetesClustersSupplier_2 } from '@backstage/plugin-kubernetes-node'; import { KubernetesCredential as KubernetesCredential_2 } from '@backstage/plugin-kubernetes-node'; @@ -190,6 +193,8 @@ export class KubernetesBuilder { catalogApi: CatalogApi, proxy: KubernetesProxy, permissionApi: PermissionEvaluator, + authService: AuthService, + httpAuth: HttpAuthService, ): express.Router; // (undocumented) protected buildServiceLocator( @@ -272,11 +277,17 @@ export type KubernetesCredential = k8sAuthTypes.KubernetesCredential; // @public (undocumented) export interface KubernetesEnvironment { + // (undocumented) + auth?: AuthService; // (undocumented) catalogApi: CatalogApi; // (undocumented) config: Config; // (undocumented) + discovery: DiscoveryService; + // (undocumented) + httpAuth?: HttpAuthService; + // (undocumented) logger: Logger; // (undocumented) permissions: PermissionEvaluator; diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index a0a094588f..0c69e3f5b1 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-backend", "description": "A Backstage backend plugin that integrates towards Kubernetes", - "version": "0.15.0", + "version": "0.16.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes-backend/src/plugin.ts b/plugins/kubernetes-backend/src/plugin.ts index 74a8a68e53..d3aacd5190 100644 --- a/plugins/kubernetes-backend/src/plugin.ts +++ b/plugins/kubernetes-backend/src/plugin.ts @@ -178,10 +178,22 @@ export const kubernetesPlugin = createBackendPlugin({ http: coreServices.httpRouter, logger: coreServices.logger, config: coreServices.rootConfig, + discovery: coreServices.discovery, catalogApi: catalogServiceRef, permissions: coreServices.permissions, + auth: coreServices.auth, + httpAuth: coreServices.httpAuth, }, - async init({ http, logger, config, catalogApi, permissions }) { + async init({ + http, + logger, + config, + discovery, + catalogApi, + permissions, + auth, + httpAuth, + }) { const winstonLogger = loggerToWinstonLogger(logger); // TODO: expose all of the customization & extension points of the builder here const builder: KubernetesBuilder = KubernetesBuilder.createBuilder({ @@ -189,6 +201,9 @@ export const kubernetesPlugin = createBackendPlugin({ config, catalogApi, permissions, + discovery, + auth, + httpAuth, }) .setObjectsProvider(extPointObjectsProvider.getObjectsProvider()) .setClusterSupplier(extPointClusterSuplier.getClusterSupplier()) diff --git a/plugins/kubernetes-backend/src/routes/resourceRoutes.test.ts b/plugins/kubernetes-backend/src/routes/resourceRoutes.test.ts index d3dcc83bb0..cfa89a6bfd 100644 --- a/plugins/kubernetes-backend/src/routes/resourceRoutes.test.ts +++ b/plugins/kubernetes-backend/src/routes/resourceRoutes.test.ts @@ -15,7 +15,11 @@ */ import request from 'supertest'; -import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; +import { + mockCredentials, + mockServices, + startTestBackend, +} from '@backstage/backend-test-utils'; import { ExtendedHttpServer } from '@backstage/backend-app-api'; import { kubernetesObjectsProviderExtensionPoint } from '@backstage/plugin-kubernetes-node'; import { createBackendModule } from '@backstage/backend-plugin-api'; @@ -102,12 +106,6 @@ describe('resourcesRoutes', () => { }, ], }, - backend: { - auth: { - // TODO: Remove once migrated to support new auth services - dangerouslyDisableDefaultAuthPolicy: true, - }, - }, }, }), import('@backstage/plugin-kubernetes-backend/alpha'), @@ -141,7 +139,6 @@ describe('resourcesRoutes', () => { }, }) .set('Content-Type', 'application/json') - .set('Authorization', 'Bearer Zm9vYmFy') .expect(200, { items: [ { @@ -168,7 +165,6 @@ describe('resourcesRoutes', () => { }, }) .set('Content-Type', 'application/json') - .set('Authorization', 'Bearer Zm9vYmFy') .expect(400, { error: { name: 'InputError', message: 'entity is a required field' }, request: { @@ -189,7 +185,6 @@ describe('resourcesRoutes', () => { }, }) .set('Content-Type', 'application/json') - .set('Authorization', 'Bearer Zm9vYmFy') .expect(400, { error: { name: 'InputError', @@ -214,7 +209,6 @@ describe('resourcesRoutes', () => { }, }) .set('Content-Type', 'application/json') - .set('Authorization', 'Bearer Zm9vYmFy') .expect(400, { error: { name: 'InputError', @@ -231,6 +225,7 @@ describe('resourcesRoutes', () => { it('401 when no Auth header', async () => { await request(app) .post('/api/kubernetes/resources/workloads/query') + .set('authorization', mockCredentials.none.header()) .send({ entityRef: 'component:someComponent', auth: { @@ -239,7 +234,10 @@ describe('resourcesRoutes', () => { }) .set('Content-Type', 'application/json') .expect(401, { - error: { name: 'AuthenticationError', message: 'No Backstage token' }, + error: { + name: 'AuthenticationError', + message: 'Missing credentials', + }, request: { method: 'POST', url: '/api/kubernetes/resources/workloads/query', @@ -258,9 +256,12 @@ describe('resourcesRoutes', () => { }, }) .set('Content-Type', 'application/json') - .set('Authorization', 'ffffff') + .set('Authorization', mockCredentials.user.invalidHeader()) .expect(401, { - error: { name: 'AuthenticationError', message: 'No Backstage token' }, + error: { + name: 'AuthenticationError', + message: 'User token is invalid', + }, request: { method: 'POST', url: '/api/kubernetes/resources/workloads/query', @@ -279,7 +280,6 @@ describe('resourcesRoutes', () => { }, }) .set('Content-Type', 'application/json') - .set('Authorization', 'Bearer Zm9vYmFy') .expect(500, { error: { name: 'Error', @@ -312,7 +312,6 @@ describe('resourcesRoutes', () => { ], }) .set('Content-Type', 'application/json') - .set('Authorization', 'Bearer Zm9vYmFy') .expect(200, { items: [ { @@ -340,7 +339,6 @@ describe('resourcesRoutes', () => { }, }) .set('Content-Type', 'application/json') - .set('Authorization', 'Bearer Zm9vYmFy') .expect(400, { error: { name: 'InputError', @@ -365,7 +363,6 @@ describe('resourcesRoutes', () => { customResources: 'somestring', }) .set('Content-Type', 'application/json') - .set('Authorization', 'Bearer Zm9vYmFy') .expect(400, { error: { name: 'InputError', @@ -390,7 +387,6 @@ describe('resourcesRoutes', () => { customResources: [], }) .set('Content-Type', 'application/json') - .set('Authorization', 'Bearer Zm9vYmFy') .expect(400, { error: { name: 'InputError', @@ -420,7 +416,6 @@ describe('resourcesRoutes', () => { ], }) .set('Content-Type', 'application/json') - .set('Authorization', 'Bearer Zm9vYmFy') .expect(400, { error: { name: 'InputError', message: 'entity is a required field' }, request: { @@ -448,7 +443,6 @@ describe('resourcesRoutes', () => { ], }) .set('Content-Type', 'application/json') - .set('Authorization', 'Bearer Zm9vYmFy') .expect(400, { error: { name: 'InputError', @@ -480,7 +474,6 @@ describe('resourcesRoutes', () => { ], }) .set('Content-Type', 'application/json') - .set('Authorization', 'Bearer Zm9vYmFy') .expect(400, { error: { name: 'InputError', @@ -497,6 +490,7 @@ describe('resourcesRoutes', () => { it('401 when no Auth header', async () => { await request(app) .post('/api/kubernetes/resources/custom/query') + .set('authorization', mockCredentials.none.header()) .send({ entityRef: 'component:someComponent', auth: { @@ -512,7 +506,10 @@ describe('resourcesRoutes', () => { }) .set('Content-Type', 'application/json') .expect(401, { - error: { name: 'AuthenticationError', message: 'No Backstage token' }, + error: { + name: 'AuthenticationError', + message: 'Missing credentials', + }, request: { method: 'POST', url: '/api/kubernetes/resources/custom/query', @@ -538,9 +535,12 @@ describe('resourcesRoutes', () => { ], }) .set('Content-Type', 'application/json') - .set('Authorization', 'ffffff') + .set('Authorization', mockCredentials.user.invalidHeader()) .expect(401, { - error: { name: 'AuthenticationError', message: 'No Backstage token' }, + error: { + name: 'AuthenticationError', + message: 'User token is invalid', + }, request: { method: 'POST', url: '/api/kubernetes/resources/custom/query', @@ -566,7 +566,6 @@ describe('resourcesRoutes', () => { ], }) .set('Content-Type', 'application/json') - .set('Authorization', 'Bearer Zm9vYmFy') .expect(500, { error: { name: 'Error', diff --git a/plugins/kubernetes-backend/src/routes/resourcesRoutes.ts b/plugins/kubernetes-backend/src/routes/resourcesRoutes.ts index 0468799908..6e05f69d04 100644 --- a/plugins/kubernetes-backend/src/routes/resourcesRoutes.ts +++ b/plugins/kubernetes-backend/src/routes/resourcesRoutes.ts @@ -19,15 +19,17 @@ import { stringifyEntityRef, } from '@backstage/catalog-model'; import { CatalogApi } from '@backstage/catalog-client'; -import { InputError, AuthenticationError } from '@backstage/errors'; +import { InputError } from '@backstage/errors'; import express, { Request } from 'express'; import { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node'; -import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node'; +import { AuthService, HttpAuthService } from '@backstage/backend-plugin-api'; export const addResourceRoutesToRouter = ( router: express.Router, catalogApi: CatalogApi, objectsProvider: KubernetesObjectsProvider, + auth: AuthService, + httpAuth: HttpAuthService, ) => { const getEntityByReq = async (req: Request) => { const rawEntityRef = req.body.entityRef; @@ -44,23 +46,18 @@ export const addResourceRoutesToRouter = ( throw new InputError(`Invalid entity ref, ${error}`); } - const token = getBearerTokenFromAuthorizationHeader( - req.headers.authorization, - ); - - if (!token) { - throw new AuthenticationError('No Backstage token'); - } - - const entity = await catalogApi.getEntityByRef(entityRef, { - token: token, + const { token } = await auth.getPluginRequestToken({ + onBehalfOf: await httpAuth.credentials(req), + targetPluginId: 'catalog', }); + const entity = await catalogApi.getEntityByRef(entityRef, { token }); if (!entity) { throw new InputError( `Entity ref missing, ${stringifyEntityRef(entityRef)}`, ); } + return entity; }; diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts index 295d11570f..1ac653bb58 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts @@ -36,6 +36,7 @@ import { import { setupServer } from 'msw/node'; import { ServiceMock, + mockCredentials, mockServices, setupRequestMockHandlers, startTestBackend, @@ -757,9 +758,9 @@ metadata: }); it('serves permission integration endpoint', async () => { - const response = await request(app).get( - '/api/kubernetes/.well-known/backstage/permissions/metadata', - ); + const response = await request(app) + .get('/api/kubernetes/.well-known/backstage/permissions/metadata') + .set('authorization', mockCredentials.service.header()); expect(response.status).toEqual(200); expect(response.body).toMatchObject({ diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts index fec4bc5cc0..c63d039ce9 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts @@ -64,6 +64,12 @@ import { } from './KubernetesFanOutHandler'; import { KubernetesClientBasedFetcher } from './KubernetesFetcher'; import { KubernetesProxy } from './KubernetesProxy'; +import { createLegacyAuthAdapters } from '@backstage/backend-common'; +import { + AuthService, + DiscoveryService, + HttpAuthService, +} from '@backstage/backend-plugin-api'; /** * @@ -73,7 +79,10 @@ export interface KubernetesEnvironment { logger: Logger; config: Config; catalogApi: CatalogApi; + discovery: DiscoveryService; permissions: PermissionEvaluator; + auth?: AuthService; + httpAuth?: HttpAuthService; } /** @@ -131,6 +140,13 @@ export class KubernetesBuilder { router: Router(), } as unknown as KubernetesBuilderReturn; } + + const { auth, httpAuth } = createLegacyAuthAdapters({ + auth: this.env.auth, + httpAuth: this.env.httpAuth, + discovery: this.env.discovery, + }); + const customResources = this.buildCustomResources(); const fetcher = this.getFetcher(); @@ -158,6 +174,8 @@ export class KubernetesBuilder { this.env.catalogApi, proxy, permissions, + auth, + httpAuth, ); return { @@ -337,6 +355,8 @@ export class KubernetesBuilder { catalogApi: CatalogApi, proxy: KubernetesProxy, permissionApi: PermissionEvaluator, + authService: AuthService, + httpAuth: HttpAuthService, ): express.Router { const logger = this.env.logger; const router = Router(); @@ -391,7 +411,13 @@ export class KubernetesBuilder { }); }); - addResourceRoutesToRouter(router, catalogApi, objectsProvider); + addResourceRoutesToRouter( + router, + catalogApi, + objectsProvider, + authService, + httpAuth, + ); return router; } diff --git a/plugins/kubernetes-cluster/CHANGELOG.md b/plugins/kubernetes-cluster/CHANGELOG.md index 8e8550daaf..c188b114bc 100644 --- a/plugins/kubernetes-cluster/CHANGELOG.md +++ b/plugins/kubernetes-cluster/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-kubernetes-cluster +## 0.0.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-kubernetes-common@0.7.5-next.0 + - @backstage/plugin-kubernetes-react@0.3.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.0.6 ### Patch Changes diff --git a/plugins/kubernetes-cluster/package.json b/plugins/kubernetes-cluster/package.json index aa30d6b340..47b3ca237c 100644 --- a/plugins/kubernetes-cluster/package.json +++ b/plugins/kubernetes-cluster/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-cluster", - "version": "0.0.6", + "version": "0.0.7-next.0", "description": "A Backstage plugin that shows details of Kubernetes clusters", "backstage": { "role": "frontend-plugin" diff --git a/plugins/kubernetes-common/CHANGELOG.md b/plugins/kubernetes-common/CHANGELOG.md index 8ebb66f857..f7ba85cdaa 100644 --- a/plugins/kubernetes-common/CHANGELOG.md +++ b/plugins/kubernetes-common/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-kubernetes-common +## 0.7.5-next.0 + +### Patch Changes + +- 4642cb7: Add support to fetch data for Daemon Sets and display an accordion in the same way as with Deployments +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/types@1.1.1 + ## 0.7.4 ### Patch Changes diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index 1c9a314a3c..3014a6decc 100644 --- a/plugins/kubernetes-common/package.json +++ b/plugins/kubernetes-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-common", - "version": "0.7.4", + "version": "0.7.5-next.0", "description": "Common functionalities for kubernetes, to be shared between kubernetes and kubernetes-backend plugin", "backstage": { "role": "common-library" diff --git a/plugins/kubernetes-node/CHANGELOG.md b/plugins/kubernetes-node/CHANGELOG.md index 18c9ee67da..d58e60a1ae 100644 --- a/plugins/kubernetes-node/CHANGELOG.md +++ b/plugins/kubernetes-node/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-kubernetes-node +## 0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-kubernetes-common@0.7.5-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/types@1.1.1 + ## 0.1.4 ### Patch Changes diff --git a/plugins/kubernetes-node/package.json b/plugins/kubernetes-node/package.json index 76d2692767..1284133a36 100644 --- a/plugins/kubernetes-node/package.json +++ b/plugins/kubernetes-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-node", - "version": "0.1.4", + "version": "0.1.7-next.0", "description": "Node.js library for the kubernetes plugin", "backstage": { "role": "node-library" diff --git a/plugins/kubernetes-react/CHANGELOG.md b/plugins/kubernetes-react/CHANGELOG.md index 1ab052def7..6618ae55cb 100644 --- a/plugins/kubernetes-react/CHANGELOG.md +++ b/plugins/kubernetes-react/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-kubernetes-react +## 0.3.1-next.0 + +### Patch Changes + +- 4642cb7: Add support to fetch data for Daemon Sets and display an accordion in the same way as with Deployments +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-kubernetes-common@0.7.5-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + ## 0.3.0 ### Minor Changes diff --git a/plugins/kubernetes-react/package.json b/plugins/kubernetes-react/package.json index 2d0eee2430..e3d1e7e371 100644 --- a/plugins/kubernetes-react/package.json +++ b/plugins/kubernetes-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-react", "description": "Web library for the kubernetes-react plugin", - "version": "0.3.0", + "version": "0.3.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes-react/src/components/Pods/FixDialog/FixDialog.test.tsx b/plugins/kubernetes-react/src/components/Pods/FixDialog/FixDialog.test.tsx index 68bfce9c96..7972f4401c 100644 --- a/plugins/kubernetes-react/src/components/Pods/FixDialog/FixDialog.test.tsx +++ b/plugins/kubernetes-react/src/components/Pods/FixDialog/FixDialog.test.tsx @@ -15,10 +15,9 @@ */ import React from 'react'; -import { render } from '@testing-library/react'; - import { FixDialog } from './FixDialog'; import { Pod } from 'kubernetes-models/v1/Pod'; +import { renderInTestApp } from '@backstage/test-utils'; jest.mock('../Events', () => ({ Events: () => { @@ -33,8 +32,8 @@ jest.mock('../PodLogs', () => ({ })); describe('FixDialog', () => { - it('docs link should render', () => { - const { getByText } = render( + it('docs link should render', async () => { + const { getByText } = await renderInTestApp( { expect(getByText('fix1')).toBeInTheDocument(); expect(getByText('fix2')).toBeInTheDocument(); }); - it('events button should render', () => { - const { getByText } = render( + it('events button should render', async () => { + const { getByText } = await renderInTestApp( { expect(getByText('fix1')).toBeInTheDocument(); expect(getByText('fix2')).toBeInTheDocument(); }); - it('Logs button should render', () => { - const { getByText } = render( + it('Logs button should render', async () => { + const { getByText } = await renderInTestApp( { + table.text('link').nullable().alter(); + table.dropColumn('done'); + }); +}; + +exports.down = async function down(knex) { + await knex.schema.alterTable('notification', table => { + table.text('link').notNullable().alter(); + table.datetime('done').nullable(); + }); +}; diff --git a/plugins/notifications-backend/package.json b/plugins/notifications-backend/package.json index 8c11253a01..1689e95df6 100644 --- a/plugins/notifications-backend/package.json +++ b/plugins/notifications-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications-backend", - "version": "0.0.1", + "version": "0.1.0-next.0", "backstage": { "role": "backend-plugin" }, diff --git a/plugins/notifications-backend/src/database/DatabaseNotificationsStore.test.ts b/plugins/notifications-backend/src/database/DatabaseNotificationsStore.test.ts index 35964ff582..e0af93a1d6 100644 --- a/plugins/notifications-backend/src/database/DatabaseNotificationsStore.test.ts +++ b/plugins/notifications-backend/src/database/DatabaseNotificationsStore.test.ts @@ -62,7 +62,6 @@ describe.each(databases.eachSupportedId())( const insertNotification = async ( notification: Partial & { id: string; - done?: Date; saved?: Date; read?: Date; }, @@ -78,7 +77,6 @@ describe.each(databases.eachSupportedId())( title: notification.payload?.title, severity: notification.payload?.severity, scope: notification.payload?.scope, - done: notification.done, saved: notification.saved, read: notification.read, }) @@ -104,44 +102,68 @@ describe.each(databases.eachSupportedId())( const notifications = await storage.getNotifications({ user }); expect(notifications.length).toBe(2); + expect(notifications.find(el => el.id === id1)).toBeTruthy(); + expect(notifications.find(el => el.id === id2)).toBeTruthy(); }); - it('should return undone notifications for user', async () => { + it('should return read notifications for user', async () => { const id1 = uuid(); const id2 = uuid(); - await insertNotification({ - id: id1, - ...testNotification, - done: new Date(), - }); + const id3 = uuid(); + await insertNotification({ id: id1, ...testNotification }); await insertNotification({ id: id2, ...testNotification }); + await insertNotification({ id: id3, ...testNotification }); await insertNotification({ id: uuid(), ...otherUserNotification }); + await storage.markRead({ ids: [id1, id3], user }); + const notifications = await storage.getNotifications({ user, - type: 'undone', + read: true, + }); + expect(notifications.length).toBe(2); + expect(notifications.find(el => el.id === id1)).toBeTruthy(); + expect(notifications.find(el => el.id === id3)).toBeTruthy(); + }); + + it('should return unread notifications for user', async () => { + const id1 = uuid(); + const id2 = uuid(); + const id3 = uuid(); + await insertNotification({ id: id1, ...testNotification }); + await insertNotification({ id: id2, ...testNotification }); + await insertNotification({ id: id3, ...testNotification }); + await insertNotification({ id: uuid(), ...otherUserNotification }); + + await storage.markRead({ ids: [id1, id3], user }); + + const notifications = await storage.getNotifications({ + user, + read: false, }); expect(notifications.length).toBe(1); expect(notifications.at(0)?.id).toEqual(id2); }); - it('should return done notifications for user', async () => { + it('should return both read and unread notifications for user', async () => { const id1 = uuid(); const id2 = uuid(); - await insertNotification({ - id: id1, - ...testNotification, - done: new Date(), - }); + const id3 = uuid(); + await insertNotification({ id: id1, ...testNotification }); await insertNotification({ id: id2, ...testNotification }); + await insertNotification({ id: id3, ...testNotification }); await insertNotification({ id: uuid(), ...otherUserNotification }); + await storage.markRead({ ids: [id1, id3], user }); + const notifications = await storage.getNotifications({ user, - type: 'done', + read: undefined, }); - expect(notifications.length).toBe(1); - expect(notifications.at(0)?.id).toEqual(id1); + expect(notifications.length).toBe(3); + expect(notifications.find(el => el.id === id1)).toBeTruthy(); + expect(notifications.find(el => el.id === id2)).toBeTruthy(); + expect(notifications.find(el => el.id === id3)).toBeTruthy(); }); it('should allow searching for notifications', async () => { @@ -166,6 +188,33 @@ describe.each(databases.eachSupportedId())( expect(notifications.length).toBe(1); expect(notifications.at(0)?.id).toEqual(id1); }); + + it('should filter notifications based on created date', async () => { + const id1 = uuid(); + const id2 = uuid(); + await insertNotification({ + id: id1, + ...testNotification, + created: new Date(Date.now() - 1 * 60 * 60 * 1000 /* an hour ago */), + }); + await insertNotification({ + id: id2, + ...testNotification, + payload: { + severity: 'normal', + title: 'Please find me', + }, + created: new Date() /* now */, + }); + await insertNotification({ id: uuid(), ...otherUserNotification }); + + const notifications = await storage.getNotifications({ + user, + createdAfter: new Date(Date.now() - 5 * 60 * 1000 /* 5mins */), + }); + expect(notifications.length).toBe(1); + expect(notifications.at(0)?.id).toEqual(id2); + }); }); describe('getStatus', () => { @@ -218,7 +267,6 @@ describe.each(databases.eachSupportedId())( ...testNotification, id: id1, read: new Date(), - done: new Date(), payload: { title: 'Notification', link: '/scaffolder/task/1234', @@ -242,7 +290,6 @@ describe.each(databases.eachSupportedId())( expect(existing).not.toBeNull(); expect(existing?.id).toEqual(id1); expect(existing?.payload.title).toEqual('New notification'); - expect(existing?.done).toBeNull(); expect(existing?.read).toBeNull(); }); }); @@ -283,32 +330,6 @@ describe.each(databases.eachSupportedId())( }); }); - describe('markDone', () => { - it('should mark notification done', async () => { - const id1 = uuid(); - await insertNotification({ id: id1, ...testNotification }); - - await storage.markDone({ ids: [id1], user }); - const notification = await storage.getNotification({ id: id1 }); - expect(notification?.done).not.toBeNull(); - }); - }); - - describe('markUndone', () => { - it('should mark notification undone', async () => { - const id1 = uuid(); - await insertNotification({ - id: id1, - ...testNotification, - done: new Date(), - }); - - await storage.markUndone({ ids: [id1], user }); - const notification = await storage.getNotification({ id: id1 }); - expect(notification?.done).toBeNull(); - }); - }); - describe('markSaved', () => { it('should mark notification saved', async () => { const id1 = uuid(); @@ -334,5 +355,26 @@ describe.each(databases.eachSupportedId())( expect(notification?.saved).toBeNull(); }); }); + + describe('saveNotification', () => { + it('should store a notification', async () => { + const id1 = uuid(); + await storage.saveNotification({ + id: id1, + user, + created: new Date(), + origin: 'my-origin', + payload: { + title: 'My title One', + description: 'a description of the notification', + link: 'http://foo.bar', + severity: 'normal', + topic: 'my-topic', + }, + }); + const notification = await storage.getNotification({ id: id1 }); + expect(notification?.payload?.title).toBe('My title One'); + }); + }); }, ); diff --git a/plugins/notifications-backend/src/database/DatabaseNotificationsStore.ts b/plugins/notifications-backend/src/database/DatabaseNotificationsStore.ts index 7e5060106b..9b654cfd04 100644 --- a/plugins/notifications-backend/src/database/DatabaseNotificationsStore.ts +++ b/plugins/notifications-backend/src/database/DatabaseNotificationsStore.ts @@ -61,7 +61,6 @@ export class DatabaseNotificationsStore implements NotificationsStore { id: row.id, user: row.user, created: row.created, - done: row.done, saved: row.saved, read: row.read, updated: row.updated, @@ -78,10 +77,30 @@ export class DatabaseNotificationsStore implements NotificationsStore { })); }; + private mapNotificationToDbRow = (notification: Notification) => { + return { + id: notification.id, + user: notification.user, + origin: notification.origin, + created: notification.created, + topic: notification.payload?.topic, + link: notification.payload?.link, + title: notification.payload?.title, + description: notification.payload?.description, + severity: notification.payload?.severity, + scope: notification.payload?.scope, + saved: notification.saved, + read: notification.read, + }; + }; + private getNotificationsBaseQuery = ( options: NotificationGetOptions | NotificationModifyOptions, ) => { - const { user, type } = options; + const { user } = options; + const isSQLite = this.db.client.config.client.includes('sqlite3'); + // const isPsql = this.db.client.config.client.includes('pg'); + const query = this.db('notification').where('user', user); if (options.sort !== undefined && options.sort !== null) { @@ -90,12 +109,20 @@ export class DatabaseNotificationsStore implements NotificationsStore { query.orderBy('created', options.sortOrder ?? 'desc'); } - if (type === 'undone') { - query.whereNull('done'); - } else if (type === 'done') { - query.whereNotNull('done'); - } else if (type === 'saved') { - query.whereNotNull('saved'); + if (options.createdAfter) { + if (isSQLite) { + query.where( + 'notification.created', + '>=', + options.createdAfter.valueOf(), + ); + } else { + query.where( + 'notification.created', + '>=', + options.createdAfter.toISOString(), + ); + } } if (options.limit) { @@ -117,6 +144,18 @@ export class DatabaseNotificationsStore implements NotificationsStore { query.whereIn('notification.id', options.ids); } + if (options.read) { + query.whereNotNull('notification.read'); + } else if (options.read === false) { + query.whereNull('notification.read'); + } // or match both if undefined + + if (options.saved) { + query.whereNotNull('notification.saved'); + } else if (options.saved === false) { + query.whereNull('notification.saved'); + } // or match both if undefined + return query; }; @@ -127,7 +166,9 @@ export class DatabaseNotificationsStore implements NotificationsStore { } async saveNotification(notification: Notification) { - await this.db.insert(notification).into('notification'); + await this.db + .insert(this.mapNotificationToDbRow(notification)) + .into('notification'); } async getStatus(options: NotificationGetOptions) { @@ -188,10 +229,9 @@ export class DatabaseNotificationsStore implements NotificationsStore { description: options.notification.payload.description, link: options.notification.payload.link, topic: options.notification.payload.topic, - updated: options.notification.created, + updated: new Date(), severity: options.notification.payload.severity, read: null, - done: null, }); return await this.getNotification(options); @@ -218,16 +258,6 @@ export class DatabaseNotificationsStore implements NotificationsStore { await notificationQuery.update({ read: null }); } - async markDone(options: NotificationModifyOptions): Promise { - const notificationQuery = this.getNotificationsBaseQuery(options); - await notificationQuery.update({ done: new Date(), read: new Date() }); - } - - async markUndone(options: NotificationModifyOptions): Promise { - const notificationQuery = this.getNotificationsBaseQuery(options); - await notificationQuery.update({ done: null, read: null }); - } - async markSaved(options: NotificationModifyOptions): Promise { const notificationQuery = this.getNotificationsBaseQuery(options); await notificationQuery.update({ saved: new Date() }); diff --git a/plugins/notifications-backend/src/database/NotificationsStore.ts b/plugins/notifications-backend/src/database/NotificationsStore.ts index 4e3a2fa547..0a7df92f03 100644 --- a/plugins/notifications-backend/src/database/NotificationsStore.ts +++ b/plugins/notifications-backend/src/database/NotificationsStore.ts @@ -17,19 +17,21 @@ import { Notification, NotificationStatus, - NotificationType, } from '@backstage/plugin-notifications-common'; +// TODO: reuse the common part of the type with front-end /** @internal */ export type NotificationGetOptions = { user: string; ids?: string[]; - type?: NotificationType; offset?: number; limit?: number; search?: string; sort?: 'created' | 'read' | 'updated' | null; sortOrder?: 'asc' | 'desc'; + read?: boolean; + saved?: boolean; + createdAfter?: Date; }; /** @internal */ @@ -62,10 +64,6 @@ export interface NotificationsStore { markUnread(options: NotificationModifyOptions): Promise; - markDone(options: NotificationModifyOptions): Promise; - - markUndone(options: NotificationModifyOptions): Promise; - markSaved(options: NotificationModifyOptions): Promise; markUnsaved(options: NotificationModifyOptions): Promise; diff --git a/plugins/notifications-backend/src/service/router.ts b/plugins/notifications-backend/src/service/router.ts index aa03726dfb..78d44dcd44 100644 --- a/plugins/notifications-backend/src/service/router.ts +++ b/plugins/notifications-backend/src/service/router.ts @@ -48,7 +48,6 @@ import { NewNotificationSignal, Notification, NotificationReadSignal, - NotificationType, } from '@backstage/plugin-notifications-common'; /** @internal */ @@ -190,9 +189,6 @@ export async function createRouter( const opts: NotificationGetOptions = { user: user, }; - if (req.query.type) { - opts.type = req.query.type.toString() as NotificationType; - } if (req.query.offset) { opts.offset = Number.parseInt(req.query.offset.toString(), 10); } @@ -202,6 +198,19 @@ export async function createRouter( if (req.query.search) { opts.search = req.query.search.toString(); } + if (req.query.read === 'true') { + opts.read = true; + } else if (req.query.read === 'false') { + opts.read = false; + // or keep undefined + } + if (req.query.created_after) { + const sinceEpoch = Date.parse(req.query.created_after.toString()); + if (isNaN(sinceEpoch)) { + throw new InputError('Unexpected date format'); + } + opts.createdAfter = new Date(sinceEpoch); + } const notifications = await store.getNotifications(opts); res.send(notifications); @@ -224,7 +233,7 @@ export async function createRouter( router.get('/status', async (req, res) => { const user = await getUser(req); - const status = await store.getStatus({ user, type: 'undone' }); + const status = await store.getStatus({ user }); res.send(status); }); diff --git a/plugins/notifications-common/CHANGELOG.md b/plugins/notifications-common/CHANGELOG.md index d327cbcc80..1e6849e4af 100644 --- a/plugins/notifications-common/CHANGELOG.md +++ b/plugins/notifications-common/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-notifications-common +## 0.0.2-next.0 + +### Patch Changes + +- 758f2a4: The Notifications frontend has been redesigned towards list view with condensed row details. The 'done' attribute has been removed to keep the Notifications aligned with the idea of a messaging system instead of a task manager. + ## 0.0.1 ### Patch Changes diff --git a/plugins/notifications-common/api-report.md b/plugins/notifications-common/api-report.md index 6f40c76e58..55c9b28489 100644 --- a/plugins/notifications-common/api-report.md +++ b/plugins/notifications-common/api-report.md @@ -16,7 +16,6 @@ type Notification_2 = { created: Date; saved?: Date; read?: Date; - done?: Date; updated?: Date; origin: string; payload: NotificationPayload; @@ -27,7 +26,7 @@ export { Notification_2 as Notification }; export type NotificationPayload = { title: string; description?: string; - link: string; + link?: string; severity: NotificationSeverity; topic?: string; scope?: string; @@ -51,7 +50,4 @@ export type NotificationStatus = { unread: number; read: number; }; - -// @public (undocumented) -export type NotificationType = 'undone' | 'done' | 'saved'; ``` diff --git a/plugins/notifications-common/package.json b/plugins/notifications-common/package.json index b3b15798ee..dcce213b2f 100644 --- a/plugins/notifications-common/package.json +++ b/plugins/notifications-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications-common", - "version": "0.0.1", + "version": "0.0.2-next.0", "description": "Common functionalities for the notifications plugin", "backstage": { "role": "common-library" diff --git a/plugins/notifications-common/src/types.ts b/plugins/notifications-common/src/types.ts index 4d71004265..c338a772d7 100644 --- a/plugins/notifications-common/src/types.ts +++ b/plugins/notifications-common/src/types.ts @@ -14,9 +14,6 @@ * limitations under the License. */ -/** @public */ -export type NotificationType = 'undone' | 'done' | 'saved'; - /** @public */ export type NotificationSeverity = 'critical' | 'high' | 'normal' | 'low'; @@ -24,7 +21,7 @@ export type NotificationSeverity = 'critical' | 'high' | 'normal' | 'low'; export type NotificationPayload = { title: string; description?: string; - link: string; + link?: string; // TODO: Add support for additional links // additionalLinks?: string[]; severity: NotificationSeverity; @@ -40,7 +37,6 @@ export type Notification = { created: Date; saved?: Date; read?: Date; - done?: Date; updated?: Date; origin: string; payload: NotificationPayload; diff --git a/plugins/notifications-node/CHANGELOG.md b/plugins/notifications-node/CHANGELOG.md index c13ca24733..42afe10206 100644 --- a/plugins/notifications-node/CHANGELOG.md +++ b/plugins/notifications-node/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-notifications-node +## 0.1.0-next.0 + +### Minor Changes + +- 84af361: Migrated to using the new auth services. + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-signals-node@0.0.4-next.0 + - @backstage/plugin-notifications-common@0.0.2-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + ## 0.0.1 ### Patch Changes diff --git a/plugins/notifications-node/package.json b/plugins/notifications-node/package.json index 9150ce1816..d818c3566d 100644 --- a/plugins/notifications-node/package.json +++ b/plugins/notifications-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-notifications-node", "description": "Node.js library for the notifications plugin", - "version": "0.0.1", + "version": "0.1.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/notifications/CHANGELOG.md b/plugins/notifications/CHANGELOG.md index 0e2623ed60..71a8685b8a 100644 --- a/plugins/notifications/CHANGELOG.md +++ b/plugins/notifications/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-notifications +## 0.1.0-next.0 + +### Minor Changes + +- 758f2a4: The Notifications frontend has been redesigned towards list view with condensed row details. The 'done' attribute has been removed to keep the Notifications aligned with the idea of a messaging system instead of a task manager. + +### Patch Changes + +- 5d9c5ba: The Notifications can be newly filtered based on the Created Date. +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-notifications-common@0.0.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-signals-react@0.0.2-next.0 + ## 0.0.1 ### Patch Changes diff --git a/plugins/notifications/api-report.md b/plugins/notifications/api-report.md index 0f5d7a0049..666daebdfe 100644 --- a/plugins/notifications/api-report.md +++ b/plugins/notifications/api-report.md @@ -12,16 +12,16 @@ import { FetchApi } from '@backstage/core-plugin-api'; import { JSX as JSX_2 } from 'react'; import { Notification as Notification_2 } from '@backstage/plugin-notifications-common'; import { NotificationStatus } from '@backstage/plugin-notifications-common'; -import { NotificationType } from '@backstage/plugin-notifications-common'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; // @public (undocumented) export type GetNotificationsOptions = { - type?: NotificationType; offset?: number; limit?: number; search?: string; + read?: boolean; + createdAfter?: Date; }; // @public (undocumented) @@ -78,16 +78,24 @@ export const NotificationsSidebarItem: (props?: { }) => React_2.JSX.Element; // @public (undocumented) -export const NotificationsTable: (props: { - onUpdate: () => void; - type: NotificationType; +export const NotificationsTable: ({ + isLoading, + notifications, + onUpdate, + setContainsText, +}: NotificationsTableProps) => React_2.JSX.Element; + +// @public (undocumented) +export type NotificationsTableProps = { + isLoading?: boolean; notifications?: Notification_2[]; -}) => React_2.JSX.Element; + onUpdate: () => void; + setContainsText: (search: string) => void; +}; // @public (undocumented) export type UpdateNotificationsOptions = { ids: string[]; - done?: boolean; read?: boolean; saved?: boolean; }; diff --git a/plugins/notifications/package.json b/plugins/notifications/package.json index d6efb58c9e..5ffed363e7 100644 --- a/plugins/notifications/package.json +++ b/plugins/notifications/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications", - "version": "0.0.1", + "version": "0.1.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -39,6 +39,7 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "^4.0.0-alpha.61", "@types/react": "^16.13.1 || ^17.0.0", + "lodash": "^4.17.21", "react-relative-time": "^0.0.9", "react-use": "^17.2.4" }, diff --git a/plugins/notifications/src/api/NotificationsApi.ts b/plugins/notifications/src/api/NotificationsApi.ts index 266c8a1ee5..4a1c792012 100644 --- a/plugins/notifications/src/api/NotificationsApi.ts +++ b/plugins/notifications/src/api/NotificationsApi.ts @@ -17,7 +17,6 @@ import { createApiRef } from '@backstage/core-plugin-api'; import { Notification, NotificationStatus, - NotificationType, } from '@backstage/plugin-notifications-common'; /** @public */ @@ -27,16 +26,16 @@ export const notificationsApiRef = createApiRef({ /** @public */ export type GetNotificationsOptions = { - type?: NotificationType; offset?: number; limit?: number; search?: string; + read?: boolean; + createdAfter?: Date; }; /** @public */ export type UpdateNotificationsOptions = { ids: string[]; - done?: boolean; read?: boolean; saved?: boolean; }; diff --git a/plugins/notifications/src/api/NotificationsClient.test.ts b/plugins/notifications/src/api/NotificationsClient.test.ts index 1312b99cf4..daf9e71232 100644 --- a/plugins/notifications/src/api/NotificationsClient.test.ts +++ b/plugins/notifications/src/api/NotificationsClient.test.ts @@ -60,16 +60,31 @@ describe('NotificationsClient', () => { server.use( rest.get(`${mockBaseUrl}/`, (req, res, ctx) => { expect(req.url.search).toBe( - '?type=undone&limit=10&offset=0&search=find+me', + '?limit=10&offset=0&search=find+me&read=true&created_after=1970-01-01T00%3A00%3A00.005Z', ); return res(ctx.json(expectedResp)); }), ); const response = await client.getNotifications({ - type: 'undone', limit: 10, offset: 0, search: 'find me', + read: true, + createdAfter: new Date(5), + }); + expect(response).toEqual(expectedResp); + }); + + it('should omit unselected fetch options', async () => { + server.use( + rest.get(`${mockBaseUrl}/`, (req, res, ctx) => { + expect(req.url.search).toBe('?limit=10'); + return res(ctx.json(expectedResp)); + }), + ); + const response = await client.getNotifications({ + limit: 10, + // do not put more options here }); expect(response).toEqual(expectedResp); }); @@ -103,14 +118,12 @@ describe('NotificationsClient', () => { rest.post(`${mockBaseUrl}/update`, async (req, res, ctx) => { expect(await req.json()).toEqual({ ids: ['acdaa8ca-262b-43c1-b74b-de06e5f3b3c7'], - done: true, }); return res(ctx.json(expectedResp)); }), ); const response = await client.updateNotifications({ ids: ['acdaa8ca-262b-43c1-b74b-de06e5f3b3c7'], - done: true, }); expect(response).toEqual(expectedResp); }); diff --git a/plugins/notifications/src/api/NotificationsClient.ts b/plugins/notifications/src/api/NotificationsClient.ts index 9ef7b287ab..1013497b3d 100644 --- a/plugins/notifications/src/api/NotificationsClient.ts +++ b/plugins/notifications/src/api/NotificationsClient.ts @@ -42,9 +42,6 @@ export class NotificationsClient implements NotificationsApi { options?: GetNotificationsOptions, ): Promise { const queryString = new URLSearchParams(); - if (options?.type) { - queryString.append('type', options.type); - } if (options?.limit !== undefined) { queryString.append('limit', options.limit.toString(10)); } @@ -54,7 +51,12 @@ export class NotificationsClient implements NotificationsApi { if (options?.search) { queryString.append('search', options.search); } - + if (options?.read !== undefined) { + queryString.append('read', options.read ? 'true' : 'false'); + } + if (options?.createdAfter !== undefined) { + queryString.append('created_after', options.createdAfter.toISOString()); + } const urlSegment = `?${queryString}`; return await this.request(urlSegment); diff --git a/plugins/notifications/src/components/NotificationsFilters/NotificationsFilters.tsx b/plugins/notifications/src/components/NotificationsFilters/NotificationsFilters.tsx new file mode 100644 index 0000000000..4645f46249 --- /dev/null +++ b/plugins/notifications/src/components/NotificationsFilters/NotificationsFilters.tsx @@ -0,0 +1,216 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; + +import { + Divider, + FormControl, + Grid, + InputLabel, + MenuItem, + Select, + Typography, +} from '@material-ui/core'; + +export type NotificationsFiltersProps = { + unreadOnly?: boolean; + onUnreadOnlyChanged: (checked: boolean | undefined) => void; + createdAfter?: string; + onCreatedAfterChanged: (value: string) => void; + + // sorting?: { + // orderBy: GetNotificationsOrderByEnum; + // orderByDirec: GetNotificationsOrderByDirecEnum; + // }; + // setSorting: ({ + // orderBy, + // orderByDirec, + // }: { + // orderBy: GetNotificationsOrderByEnum; + // orderByDirec: GetNotificationsOrderByDirecEnum; + // }) => void; +}; + +export const CreatedAfterOptions: { + [key: string]: { label: string; getDate: () => Date }; +} = { + last24h: { + label: 'Last 24h', + getDate: () => new Date(Date.now() - 24 * 3600 * 1000), + }, + lastWeek: { + label: 'Last week', + getDate: () => new Date(Date.now() - 7 * 24 * 3600 * 1000), + }, + all: { + label: 'Any time', + getDate: () => new Date(0), + }, +}; + +// export const SortByOptions: { +// [key: string]: { +// label: string; +// orderBy: GetNotificationsOrderByEnum; +// orderByDirec: GetNotificationsOrderByDirecEnum; +// }; +// } = { +// newest: { +// label: 'Newest on top', +// orderBy: GetNotificationsOrderByEnum.Created, +// orderByDirec: GetNotificationsOrderByDirecEnum.Asc, +// }, +// oldest: { +// label: 'Oldest on top', +// orderBy: GetNotificationsOrderByEnum.Created, +// orderByDirec: GetNotificationsOrderByDirecEnum.Desc, +// }, +// topic: { +// label: 'Topic', +// orderBy: GetNotificationsOrderByEnum.Topic, +// orderByDirec: GetNotificationsOrderByDirecEnum.Asc, +// }, +// origin: { +// label: 'Origin', +// orderBy: GetNotificationsOrderByEnum.Origin, +// orderByDirec: GetNotificationsOrderByDirecEnum.Asc, +// }, +// }; + +// TODO: Implement sorting on server (to work with pagination) +// const getSortBy = (sorting: NotificationsFiltersProps['sorting']): string => { +// if ( +// sorting?.orderBy === GetNotificationsOrderByEnum.Created && +// sorting.orderByDirec === GetNotificationsOrderByDirecEnum.Desc +// ) { +// return 'oldest'; +// } +// if (sorting?.orderBy === GetNotificationsOrderByEnum.Topic) { +// return 'topic'; +// } +// if (sorting?.orderBy === GetNotificationsOrderByEnum.Origin) { +// return 'origin'; +// } + +// return 'newest'; +// }; + +export const NotificationsFilters = ({ + // sorting, + // setSorting, + unreadOnly, + onUnreadOnlyChanged, + createdAfter, + onCreatedAfterChanged, +}: NotificationsFiltersProps) => { + // const sortBy = getSortBy(sorting); + + const handleOnCreatedAfterChanged = ( + event: React.ChangeEvent<{ name?: string; value: unknown }>, + ) => { + onCreatedAfterChanged(event.target.value as string); + }; + + const handleOnUnreadOnlyChanged = ( + event: React.ChangeEvent<{ name?: string; value: unknown }>, + ) => { + let value = undefined; + if (event.target.value === 'unread') value = true; + if (event.target.value === 'read') value = false; + onUnreadOnlyChanged(value); + }; + + // const handleOnSortByChanged = ( + // event: React.ChangeEvent<{ name?: string; value: unknown }>, + // ) => { + // const idx = (event.target.value as string) || 'newest'; + // const option = SortByOptions[idx]; + // setSorting({ + // orderBy: option.orderBy, + // orderByDirec: option.orderByDirec, + // }); + // }; + + let unreadOnlyValue = 'all'; + if (unreadOnly) unreadOnlyValue = 'unread'; + if (unreadOnly === false) unreadOnlyValue = 'read'; + + return ( + <> + + + Filters + + + + + View + + + + + + + Created after + + + + + + + {/* + + + Sort by + + + + */} + + + ); +}; diff --git a/plugins/notifications/src/components/NotificationsFilters/index.ts b/plugins/notifications/src/components/NotificationsFilters/index.ts new file mode 100644 index 0000000000..196aef61e0 --- /dev/null +++ b/plugins/notifications/src/components/NotificationsFilters/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export * from './NotificationsFilters'; diff --git a/plugins/notifications/src/components/NotificationsPage/NotificationsPage.tsx b/plugins/notifications/src/components/NotificationsPage/NotificationsPage.tsx index 85e0937ca3..1f8b141608 100644 --- a/plugins/notifications/src/components/NotificationsPage/NotificationsPage.tsx +++ b/plugins/notifications/src/components/NotificationsPage/NotificationsPage.tsx @@ -14,35 +14,46 @@ * limitations under the License. */ -import React, { useEffect, useState } from 'react'; +import React, { useEffect } from 'react'; import { Content, - ErrorPanel, PageWithHeader, + ResponseErrorPanel, } from '@backstage/core-components'; -import { NotificationsTable } from '../NotificationsTable'; -import { useNotificationsApi } from '../../hooks'; -import { Button, Grid, makeStyles } from '@material-ui/core'; -import Bookmark from '@material-ui/icons/Bookmark'; -import Check from '@material-ui/icons/Check'; -import Inbox from '@material-ui/icons/Inbox'; -import { NotificationType } from '@backstage/plugin-notifications-common'; +import { Grid } from '@material-ui/core'; import { useSignal } from '@backstage/plugin-signals-react'; -const useStyles = makeStyles(_theme => ({ - filterButton: { - width: '100%', - justifyContent: 'start', - }, -})); +import { NotificationsTable } from '../NotificationsTable'; +import { useNotificationsApi } from '../../hooks'; +import { + CreatedAfterOptions, + NotificationsFilters, +} from '../NotificationsFilters'; +import { GetNotificationsOptions } from '../../api'; export const NotificationsPage = () => { - const [type, setType] = useState('undone'); const [refresh, setRefresh] = React.useState(false); + const { lastSignal } = useSignal('notifications'); + const [unreadOnly, setUnreadOnly] = React.useState(true); + const [containsText, setContainsText] = React.useState(); + const [createdAfter, setCreatedAfter] = React.useState('lastWeek'); - const { error, value, retry } = useNotificationsApi( - api => api.getNotifications({ type }), - [type], + const { error, value, retry, loading } = useNotificationsApi( + // TODO: add pagination and other filters + api => { + const options: GetNotificationsOptions = { search: containsText }; + if (unreadOnly !== undefined) { + options.read = !unreadOnly; + } + + const createdAfterDate = CreatedAfterOptions[createdAfter].getDate(); + if (createdAfterDate.valueOf() > 0) { + options.createdAfter = createdAfterDate; + } + + return api.getNotifications(options); + }, + [containsText, unreadOnly, createdAfter], ); useEffect(() => { @@ -52,7 +63,6 @@ export const NotificationsPage = () => { } }, [refresh, setRefresh, retry]); - const { lastSignal } = useSignal('notifications'); useEffect(() => { if (lastSignal && lastSignal.action) { setRefresh(true); @@ -63,9 +73,8 @@ export const NotificationsPage = () => { setRefresh(true); }; - const styles = useStyles(); if (error) { - return ; + return ; } return ( @@ -73,36 +82,21 @@ export const NotificationsPage = () => { - - - + diff --git a/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx b/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx index 8328da1c6d..6bcb6badc7 100644 --- a/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx +++ b/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx @@ -13,296 +13,162 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { useEffect, useState } from 'react'; -import { - Box, - Button, - IconButton, - makeStyles, - Table, - TableBody, - TableCell, - TableHead, - TableRow, - Tooltip, - Typography, -} from '@material-ui/core'; -import { - Notification, - NotificationType, -} from '@backstage/plugin-notifications-common'; -import { useNavigate } from 'react-router-dom'; -import Checkbox from '@material-ui/core/Checkbox'; -import Check from '@material-ui/icons/Check'; -import Bookmark from '@material-ui/icons/Bookmark'; +import React, { useMemo } from 'react'; +import throttle from 'lodash/throttle'; +import { Box, IconButton, Tooltip, Typography } from '@material-ui/core'; +import { Notification } from '@backstage/plugin-notifications-common'; import { notificationsApiRef } from '../../api'; import { useApi } from '@backstage/core-plugin-api'; -import Inbox from '@material-ui/icons/Inbox'; -import CloseIcon from '@material-ui/icons/Close'; +import MarkAsUnreadIcon from '@material-ui/icons/Markunread'; +import MarkAsReadIcon from '@material-ui/icons/CheckCircle'; + // @ts-ignore import RelativeTime from 'react-relative-time'; -import ArrowForwardIcon from '@material-ui/icons/ArrowForward'; +import { Link, Table, TableColumn } from '@backstage/core-components'; -const useStyles = makeStyles(theme => ({ - table: { - border: `1px solid ${theme.palette.divider}`, - }, - header: { - borderBottom: `1px solid ${theme.palette.divider}`, - }, - - notificationRow: { - cursor: 'pointer', - '&.unread': { - border: '1px solid rgba(255, 255, 255, .3)', - }, - '& .hideOnHover': { - display: 'initial', - }, - '& .showOnHover': { - display: 'none', - }, - '&:hover': { - '& .hideOnHover': { - display: 'none', - }, - '& .showOnHover': { - display: 'initial', - }, - }, - }, - actionButton: { - padding: '9px', - }, - checkBox: { - padding: '0 10px 10px 0', - }, -})); +const ThrottleDelayMs = 1000; /** @public */ -export const NotificationsTable = (props: { - onUpdate: () => void; - type: NotificationType; +export type NotificationsTableProps = { + isLoading?: boolean; notifications?: Notification[]; -}) => { - const { notifications, type } = props; - const navigate = useNavigate(); - const styles = useStyles(); - const [selected, setSelected] = useState([]); + onUpdate: () => void; + setContainsText: (search: string) => void; +}; + +/** @public */ +export const NotificationsTable = ({ + isLoading, + notifications = [], + onUpdate, + setContainsText, +}: NotificationsTableProps) => { const notificationsApi = useApi(notificationsApiRef); - const onCheckBoxClick = (id: string) => { - const index = selected.indexOf(id); - if (index !== -1) { - setSelected(selected.filter(s => s !== id)); - } else { - setSelected([...selected, id]); - } - }; + const onSwitchReadStatus = React.useCallback( + (notification: Notification) => { + notificationsApi + .updateNotifications({ + ids: [notification.id], + read: !notification.read, + }) + .then(() => onUpdate()); + }, + [notificationsApi, onUpdate], + ); - useEffect(() => { - setSelected([]); - }, [type]); + const throttledContainsTextHandler = useMemo( + () => throttle(setContainsText, ThrottleDelayMs), + [setContainsText], + ); - const isChecked = (id: string) => { - return selected.indexOf(id) !== -1; - }; - - const isAllSelected = () => { - return ( - selected.length === notifications?.length && notifications.length > 0 - ); - }; - - return ( - - - - - {type !== 'saved' && !notifications?.length && 'No notifications'} - {type !== 'saved' && !!notifications?.length && ( - { - if (isAllSelected()) { - setSelected([]); - } else { - setSelected( - notifications ? notifications.map(n => n.id) : [], - ); - } - }} - /> - )} - {type === 'saved' && - `${notifications?.length ?? 0} saved notifications`} - {selected.length === 0 && - !!notifications?.length && - type !== 'saved' && - 'Select all'} - {selected.length > 0 && `${selected.length} selected`} - {type === 'done' && selected.length > 0 && ( - - )} - - {type === 'undone' && selected.length > 0 && ( - - )} - - - - - {props.notifications?.map(notification => { + const compactColumns = React.useMemo( + (): TableColumn[] => [ + { + customFilterAndSearch: () => + true /* Keep it on backend due to pagination. If recent flickering is an issue, implement search here as well. */, + render: (notification: Notification) => { + // Compact content return ( - - - onCheckBoxClick(notification.id)} - /> - - - notificationsApi - .updateNotifications({ ids: [notification.id], read: true }) - .then(() => navigate(notification.payload.link)) - } - style={{ paddingLeft: 0 }} - > + <> + - {notification.payload.title} + {notification.payload.link ? ( + + {notification.payload.title} + + ) : ( + notification.payload.title + )} {notification.payload.description} - - - - - - - - - notificationsApi - .updateNotifications({ - ids: [notification.id], - read: true, - }) - .then(() => navigate(notification.payload.link)) - } - > - - - - - { - if (notification.read) { - notificationsApi - .updateNotifications({ - ids: [notification.id], - done: false, - }) - .then(() => { - props.onUpdate(); - }); - } else { - notificationsApi - .updateNotifications({ - ids: [notification.id], - done: true, - }) - .then(() => { - props.onUpdate(); - }); - } - }} - > - {notification.read ? ( - - ) : ( - - )} - - - - { - if (notification.saved) { - notificationsApi - .updateNotifications({ - ids: [notification.id], - saved: false, - }) - .then(() => { - props.onUpdate(); - }); - } else { - notificationsApi - .updateNotifications({ - ids: [notification.id], - saved: true, - }) - .then(() => { - props.onUpdate(); - }); - } - }} - > - {notification.saved ? ( - - ) : ( - - )} - - - - - + + {notification.origin && ( + <>{notification.origin} •  + )} + {notification.payload.topic && ( + <>{notification.payload.topic} •  + )} + {notification.created && ( + + )} + + + ); - })} - -
+ }, + }, + // { + // // TODO: additional action links + // width: '25%', + // render: (notification: Notification) => { + // return ( + // notification.payload.link && ( + // + // {/* TODO: render additionalLinks of different titles */} + // + // + //  More info + // + // + // + // ) + // ); + // }, + // }, + { + // TODO: action for saving notifications + // actions + width: '1rem', + render: (notification: Notification) => { + const markAsReadText = !!notification.read + ? 'Return among unread' + : 'Mark as read'; + const IconComponent = !!notification.read + ? MarkAsUnreadIcon + : MarkAsReadIcon; + + return ( + + { + onSwitchReadStatus(notification); + }} + > + + + + ); + }, + }, + ], + [onSwitchReadStatus], + ); + + // TODO: render "Saved notifications" as "Pinned" + return ( + + isLoading={isLoading} + options={{ + search: true, + // TODO: add pagination + // paging: true, + // pageSize, + header: false, + sorting: false, + }} + // onPageChange={setPageNumber} + // onRowsPerPageChange={setPageSize} + // page={offset} + // totalCount={value?.totalCount} + onSearchChange={throttledContainsTextHandler} + data={notifications} + columns={compactColumns} + /> ); }; diff --git a/plugins/octopus-deploy/CHANGELOG.md b/plugins/octopus-deploy/CHANGELOG.md index f63c0b037d..af8a40ac68 100644 --- a/plugins/octopus-deploy/CHANGELOG.md +++ b/plugins/octopus-deploy/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-octopus-deploy +## 0.2.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.2.12 ### Patch Changes diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json index c297f370eb..360af7064c 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.12", + "version": "0.2.13-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/opencost/CHANGELOG.md b/plugins/opencost/CHANGELOG.md index 061801789d..8cd5ae4e5f 100644 --- a/plugins/opencost/CHANGELOG.md +++ b/plugins/opencost/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-opencost +## 0.2.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.2.5 ### Patch Changes diff --git a/plugins/opencost/package.json b/plugins/opencost/package.json index 37ab923ff9..fdeb006ab6 100644 --- a/plugins/opencost/package.json +++ b/plugins/opencost/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-opencost", - "version": "0.2.5", + "version": "0.2.6-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/org-react/CHANGELOG.md b/plugins/org-react/CHANGELOG.md index 7b4fcd13b3..e44dbb9645 100644 --- a/plugins/org-react/CHANGELOG.md +++ b/plugins/org-react/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-org-react +## 0.1.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.1.19 ### Patch Changes diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index 96f77a29b4..39aa5a0752 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.19", + "version": "0.1.20-next.0", "backstage": { "role": "web-library" }, diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index 24243d3ae5..d0b6795b4d 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-org +## 0.6.21-next.0 + +### Patch Changes + +- 526f00a: Document the new frontend system extensions for the org plugin. +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + ## 0.6.20 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index 8981f564d4..f8c87628c0 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-org", - "version": "0.6.20", + "version": "0.6.21-next.0", "description": "A Backstage plugin that helps you create entity pages for your organization", "backstage": { "role": "frontend-plugin" diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index 5110d1ccb4..4036dea415 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-pagerduty +## 0.7.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-home-react@0.1.9-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.7.2 ### Patch Changes diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 128394adfb..539c3aefc9 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-pagerduty", - "version": "0.7.2", + "version": "0.7.3-next.0", "description": "This plugin has been deprecated, consider using [@pagerduty/backstage-plugin](https://github.com/pagerduty/backstage-plugin) instead.", "backstage": { "role": "frontend-plugin" diff --git a/plugins/periskop-backend/CHANGELOG.md b/plugins/periskop-backend/CHANGELOG.md index d53ee5b2f8..0250c9bac6 100644 --- a/plugins/periskop-backend/CHANGELOG.md +++ b/plugins/periskop-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-periskop-backend +## 0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.2.8 ### Patch Changes diff --git a/plugins/periskop-backend/package.json b/plugins/periskop-backend/package.json index 161ab1956c..376312252e 100644 --- a/plugins/periskop-backend/package.json +++ b/plugins/periskop-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop-backend", - "version": "0.2.8", + "version": "0.2.11-next.0", "backstage": { "role": "backend-plugin" }, diff --git a/plugins/periskop/CHANGELOG.md b/plugins/periskop/CHANGELOG.md index 4ddd668bad..ee61a17b98 100644 --- a/plugins/periskop/CHANGELOG.md +++ b/plugins/periskop/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-periskop +## 0.1.29-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.1.28 ### Patch Changes diff --git a/plugins/periskop/package.json b/plugins/periskop/package.json index 52d30cb07a..e1b6c4557b 100644 --- a/plugins/periskop/package.json +++ b/plugins/periskop/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop", - "version": "0.1.28", + "version": "0.1.29-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md b/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md index 91610899ae..77f9cbb245 100644 --- a/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md +++ b/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-permission-backend-module-allow-all-policy +## 0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + ## 0.1.7 ### Patch Changes diff --git a/plugins/permission-backend-module-policy-allow-all/package.json b/plugins/permission-backend-module-policy-allow-all/package.json index 291b267bcf..1841c61351 100644 --- a/plugins/permission-backend-module-policy-allow-all/package.json +++ b/plugins/permission-backend-module-policy-allow-all/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-backend-module-allow-all-policy", - "version": "0.1.7", + "version": "0.1.10-next.0", "description": "Allow all policy backend module for the permission plugin.", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/permission-backend/CHANGELOG.md b/plugins/permission-backend/CHANGELOG.md index d4a5c88f2b..cbce5b6c61 100644 --- a/plugins/permission-backend/CHANGELOG.md +++ b/plugins/permission-backend/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-permission-backend +## 0.5.36-next.0 + +### Patch Changes + +- 9802004: Migrated to use the new auth services introduced in [BEP-0003](https://github.com/backstage/backstage/blob/master/beps/0003-auth-architecture-evolution/README.md). + + The `createRouter` function now accepts `auth`, `httpAuth` and `userInfo` options. Theses are used internally to support the new backend system, and can be ignored. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.5.33 ### Patch Changes diff --git a/plugins/permission-backend/api-report.md b/plugins/permission-backend/api-report.md index e9cc4e6272..8b4336ff23 100644 --- a/plugins/permission-backend/api-report.md +++ b/plugins/permission-backend/api-report.md @@ -3,27 +3,36 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { AuthService } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; +import { DiscoveryService } from '@backstage/backend-plugin-api'; import express from 'express'; +import { HttpAuthService } from '@backstage/backend-plugin-api'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { Logger } from 'winston'; import { PermissionPolicy } from '@backstage/plugin-permission-node'; -import { PluginEndpointDiscovery } from '@backstage/backend-common'; +import { UserInfoService } from '@backstage/backend-plugin-api'; // @public export function createRouter(options: RouterOptions): Promise; // @public export interface RouterOptions { + // (undocumented) + auth?: AuthService; // (undocumented) config: Config; // (undocumented) - discovery: PluginEndpointDiscovery; + discovery: DiscoveryService; // (undocumented) - identity: IdentityApi; + httpAuth?: HttpAuthService; + // (undocumented) + identity?: IdentityApi; // (undocumented) logger: Logger; // (undocumented) policy: PermissionPolicy; + // (undocumented) + userInfo?: UserInfoService; } ``` diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index cc986c4cc8..e34689f2bb 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.33", + "version": "0.5.36-next.0", "backstage": { "role": "backend-plugin" }, @@ -62,6 +62,7 @@ "zod": "^3.22.4" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/lodash": "^4.14.151", "@types/supertest": "^2.0.8", diff --git a/plugins/permission-backend/src/plugin.ts b/plugins/permission-backend/src/plugin.ts index 9cf0024e47..cc7f31dfdd 100644 --- a/plugins/permission-backend/src/plugin.ts +++ b/plugins/permission-backend/src/plugin.ts @@ -55,9 +55,19 @@ export const permissionPlugin = createBackendPlugin({ config: coreServices.rootConfig, logger: coreServices.logger, discovery: coreServices.discovery, - identity: coreServices.identity, + auth: coreServices.auth, + httpAuth: coreServices.httpAuth, + userInfo: coreServices.userInfo, }, - async init({ http, config, logger, discovery, identity }) { + async init({ + http, + config, + logger, + discovery, + auth, + httpAuth, + userInfo, + }) { const winstonLogger = loggerToWinstonLogger(logger); if (!policies.policy) { throw new Error( @@ -69,9 +79,11 @@ export const permissionPlugin = createBackendPlugin({ await createRouter({ config, discovery, - identity, logger: winstonLogger, policy: policies.policy, + auth, + httpAuth, + userInfo, }), ); }, diff --git a/plugins/permission-backend/src/service/PermissionIntegrationClient.test.ts b/plugins/permission-backend/src/service/PermissionIntegrationClient.test.ts index c7a412547d..a36dadd2b5 100644 --- a/plugins/permission-backend/src/service/PermissionIntegrationClient.test.ts +++ b/plugins/permission-backend/src/service/PermissionIntegrationClient.test.ts @@ -19,7 +19,7 @@ import { Server } from 'http'; import express, { Router, RequestHandler } from 'express'; import { RestContext, rest } from 'msw'; import { setupServer, SetupServer } from 'msw/node'; -import { PluginEndpointDiscovery } from '@backstage/backend-common'; +import { mockCredentials, mockServices } from '@backstage/backend-test-utils'; import { AuthorizeResult, PermissionCondition, @@ -31,10 +31,12 @@ import { } from '@backstage/plugin-permission-node'; import { PermissionIntegrationClient } from './PermissionIntegrationClient'; import { z } from 'zod'; +import { DiscoveryService } from '@backstage/backend-plugin-api'; describe('PermissionIntegrationClient', () => { describe('applyConditions', () => { let server: SetupServer; + const auth = mockServices.auth(); const mockConditions: PermissionCriteria = { not: { @@ -58,7 +60,7 @@ describe('PermissionIntegrationClient', () => { ); const mockBaseUrl = 'http://backstage:9191'; - const discovery: PluginEndpointDiscovery = { + const discovery: DiscoveryService = { async getBaseUrl(pluginId) { return `${mockBaseUrl}/${pluginId}`; }, @@ -70,6 +72,7 @@ describe('PermissionIntegrationClient', () => { const client: PermissionIntegrationClient = new PermissionIntegrationClient( { discovery, + auth, }, ); @@ -91,7 +94,7 @@ describe('PermissionIntegrationClient', () => { }); it('should make a POST request to the correct endpoint', async () => { - await client.applyConditions('plugin-1', [ + await client.applyConditions('plugin-1', mockCredentials.none(), [ { id: '123', resourceRef: 'testResource1', @@ -104,7 +107,7 @@ describe('PermissionIntegrationClient', () => { }); it('should include a request body', async () => { - await client.applyConditions('plugin-1', [ + await client.applyConditions('plugin-1', mockCredentials.none(), [ { id: '123', resourceRef: 'testResource1', @@ -132,14 +135,18 @@ describe('PermissionIntegrationClient', () => { }); it('should return the response from the fetch request', async () => { - const response = await client.applyConditions('plugin-1', [ - { - id: '123', - resourceRef: 'testResource1', - resourceType: 'test-resource', - conditions: mockConditions, - }, - ]); + const response = await client.applyConditions( + 'plugin-1', + mockCredentials.none(), + [ + { + id: '123', + resourceRef: 'testResource1', + resourceType: 'test-resource', + conditions: mockConditions, + }, + ], + ); expect(response).toEqual( expect.objectContaining([{ id: '123', result: AuthorizeResult.ALLOW }]), @@ -147,7 +154,7 @@ describe('PermissionIntegrationClient', () => { }); it('should not include authorization headers if no token is supplied', async () => { - await client.applyConditions('plugin-1', [ + await client.applyConditions('plugin-1', mockCredentials.none(), [ { id: '123', resourceRef: 'testResource1', @@ -161,21 +168,22 @@ describe('PermissionIntegrationClient', () => { }); it('should include correctly-constructed authorization header if token is supplied', async () => { - await client.applyConditions( - 'plugin-1', - [ - { - id: '123', - resourceRef: 'testResource1', - resourceType: 'test-resource', - conditions: mockConditions, - }, - ], - 'Bearer fake-token', - ); + await client.applyConditions('plugin-1', mockCredentials.user(), [ + { + id: '123', + resourceRef: 'testResource1', + resourceType: 'test-resource', + conditions: mockConditions, + }, + ]); const request = mockApplyConditionsHandler.mock.calls[0][0]; - expect(request.headers.get('authorization')).toEqual('Bearer fake-token'); + expect(request.headers.get('authorization')).toEqual( + mockCredentials.service.header({ + onBehalfOf: mockCredentials.user(), + targetPluginId: 'plugin-1', + }), + ); }); it('should forward response errors', async () => { @@ -186,7 +194,7 @@ describe('PermissionIntegrationClient', () => { ); await expect( - client.applyConditions('plugin-1', [ + client.applyConditions('plugin-1', mockCredentials.none(), [ { id: '123', resourceRef: 'testResource1', @@ -194,7 +202,7 @@ describe('PermissionIntegrationClient', () => { conditions: mockConditions, }, ]), - ).rejects.toThrow(/401/i); + ).rejects.toThrow(/401/); }); it('should reject invalid responses', async () => { @@ -207,7 +215,7 @@ describe('PermissionIntegrationClient', () => { ); await expect( - client.applyConditions('plugin-1', [ + client.applyConditions('plugin-1', mockCredentials.none(), [ { id: '123', resourceRef: 'testResource1', @@ -234,7 +242,7 @@ describe('PermissionIntegrationClient', () => { ); await expect( - client.applyConditions('plugin-1', [ + client.applyConditions('plugin-1', mockCredentials.none(), [ { id: '123', resourceRef: 'testResource1', @@ -268,6 +276,7 @@ describe('PermissionIntegrationClient', () => { let server: Server; let client: PermissionIntegrationClient; let routerSpy: RequestHandler; + const auth = mockServices.auth(); beforeAll(async () => { const router = Router(); @@ -319,7 +328,7 @@ describe('PermissionIntegrationClient', () => { server = app.listen(resolve); }); - const discovery: PluginEndpointDiscovery = { + const discovery: DiscoveryService = { async getBaseUrl(pluginId: string) { const listenPort = (server.address()! as AddressInfo).port; @@ -332,6 +341,7 @@ describe('PermissionIntegrationClient', () => { client = new PermissionIntegrationClient({ discovery, + auth, }); }); @@ -348,7 +358,7 @@ describe('PermissionIntegrationClient', () => { it('works for simple conditions', async () => { await expect( - client.applyConditions('plugin-1', [ + client.applyConditions('plugin-1', mockCredentials.none(), [ { id: '123', resourceRef: 'testResource1', @@ -367,7 +377,7 @@ describe('PermissionIntegrationClient', () => { it('works for complex criteria', async () => { await expect( - client.applyConditions('plugin-1', [ + client.applyConditions('plugin-1', mockCredentials.none(), [ { id: '123', resourceRef: 'testResource1', diff --git a/plugins/permission-backend/src/service/PermissionIntegrationClient.ts b/plugins/permission-backend/src/service/PermissionIntegrationClient.ts index 2c31d371c3..7567dc8fbb 100644 --- a/plugins/permission-backend/src/service/PermissionIntegrationClient.ts +++ b/plugins/permission-backend/src/service/PermissionIntegrationClient.ts @@ -16,7 +16,6 @@ import fetch from 'node-fetch'; import { z } from 'zod'; -import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { AuthorizeResult, ConditionalPolicyDecision, @@ -25,6 +24,11 @@ import { ApplyConditionsRequestEntry, ApplyConditionsResponseEntry, } from '@backstage/plugin-permission-node'; +import { + AuthService, + BackstageCredentials, + DiscoveryService, +} from '@backstage/backend-plugin-api'; const responseSchema = z.object({ items: z.array( @@ -42,20 +46,30 @@ export type ResourcePolicyDecision = ConditionalPolicyDecision & { }; export class PermissionIntegrationClient { - private readonly discovery: PluginEndpointDiscovery; + private readonly discovery: DiscoveryService; + private readonly auth: AuthService; - constructor(options: { discovery: PluginEndpointDiscovery }) { + constructor(options: { discovery: DiscoveryService; auth: AuthService }) { this.discovery = options.discovery; + this.auth = options.auth; } async applyConditions( pluginId: string, + credentials: BackstageCredentials, decisions: readonly ApplyConditionsRequestEntry[], - authHeader?: string, ): Promise { - const endpoint = `${await this.discovery.getBaseUrl( - pluginId, - )}/.well-known/backstage/permissions/apply-conditions`; + const baseUrl = await this.discovery.getBaseUrl(pluginId); + const endpoint = `${baseUrl}/.well-known/backstage/permissions/apply-conditions`; + + const token = this.auth.isPrincipal(credentials, 'none') + ? undefined + : await this.auth + .getPluginRequestToken({ + onBehalfOf: credentials, + targetPluginId: pluginId, + }) + .then(t => t.token); const response = await fetch(endpoint, { method: 'POST', @@ -70,7 +84,7 @@ export class PermissionIntegrationClient { ), }), headers: { - ...(authHeader ? { authorization: authHeader } : {}), + ...(token ? { authorization: `Bearer ${token}` } : {}), 'content-type': 'application/json', }, }); diff --git a/plugins/permission-backend/src/service/router.test.ts b/plugins/permission-backend/src/service/router.test.ts index 7278835c5c..0da9ecd748 100644 --- a/plugins/permission-backend/src/service/router.test.ts +++ b/plugins/permission-backend/src/service/router.test.ts @@ -26,12 +26,15 @@ import { PermissionIntegrationClient } from './PermissionIntegrationClient'; import { createRouter } from './router'; import { ConfigReader } from '@backstage/config'; +import { BackstageCredentials } from '@backstage/backend-plugin-api'; +import { mockCredentials, mockServices } from '@backstage/backend-test-utils'; const mockApplyConditions: jest.MockedFunction< InstanceType['applyConditions'] > = jest.fn( async ( _pluginId: string, + _credentials: BackstageCredentials, decisions: readonly ApplyConditionsRequestEntry[], ) => decisions.map(decision => ({ @@ -65,28 +68,12 @@ describe('createRouter', () => { const router = await createRouter({ config: new ConfigReader({ permission: { enabled: true } }), logger: getVoidLogger(), - discovery: { - getBaseUrl: jest.fn(), - getExternalBaseUrl: jest.fn(), - }, - identity: { - getIdentity: jest.fn(({ request: req }) => { - const token = req.headers.authorization?.replace(/^Bearer[ ]+/, ''); - - if (!token) { - return Promise.resolve(undefined); - } - - return Promise.resolve({ - identity: { - type: 'user', - userEntityRef: 'test-user', - ownershipEntityRefs: ['blah'], - }, - token, - }); - }), - }, + discovery: mockServices.discovery(), + auth: mockServices.auth(), + httpAuth: mockServices.httpAuth({ + defaultCredentials: mockCredentials.none(), + }), + userInfo: mockServices.userInfo(), policy, }); @@ -163,10 +150,9 @@ describe('createRouter', () => { }); it('resolves identity from the Authorization header', async () => { - const token = 'test-token'; const response = await request(app) .post('/authorize') - .auth(token, { type: 'bearer' }) + .auth(mockCredentials.user.token(), { type: 'bearer' }) .send({ items: [ { @@ -190,11 +176,16 @@ describe('createRouter', () => { }, }, { - token: 'test-token', + token: mockCredentials.service.token({ + onBehalfOf: mockCredentials.user(), + targetPluginId: 'catalog', + }), identity: { type: 'user', - userEntityRef: 'test-user', - ownershipEntityRefs: ['blah'], + userEntityRef: mockCredentials.user().principal.userEntityRef, + ownershipEntityRefs: [ + mockCredentials.user().principal.userEntityRef, + ], }, }, ); @@ -271,7 +262,7 @@ describe('createRouter', () => { const response = await request(app) .post('/authorize') - .auth('test-token', { type: 'bearer' }) + .auth(mockCredentials.user.token(), { type: 'bearer' }) .send({ items: [ { @@ -319,6 +310,7 @@ describe('createRouter', () => { expect(mockApplyConditions).toHaveBeenCalledWith( 'plugin-1', + mockCredentials.user(), [ expect.objectContaining({ id: '123', @@ -333,11 +325,11 @@ describe('createRouter', () => { conditions: { rule: 'test-rule', params: ['no'] }, }), ], - 'Bearer test-token', ); expect(mockApplyConditions).toHaveBeenCalledWith( 'plugin-2', + mockCredentials.user(), [ expect.objectContaining({ id: '234', @@ -352,7 +344,6 @@ describe('createRouter', () => { conditions: { rule: 'test-rule', params: ['no'] }, }), ], - 'Bearer test-token', ); expect(response.status).toEqual(200); @@ -401,7 +392,7 @@ describe('createRouter', () => { const response = await request(app) .post('/authorize') - .auth('test-token', { type: 'bearer' }) + .auth(mockCredentials.user.token(), { type: 'bearer' }) .send({ items: [ { @@ -467,6 +458,7 @@ describe('createRouter', () => { expect(mockApplyConditions).toHaveBeenCalledWith( 'plugin-1', + mockCredentials.user(), [ expect.objectContaining({ id: '123', @@ -481,11 +473,11 @@ describe('createRouter', () => { conditions: { rule: 'test-rule', params: ['yes'] }, }), ], - 'Bearer test-token', ); expect(mockApplyConditions).toHaveBeenCalledWith( 'plugin-2', + mockCredentials.user(), [ expect.objectContaining({ id: '234', @@ -500,7 +492,6 @@ describe('createRouter', () => { conditions: { rule: 'test-rule', params: ['yes'] }, }), ], - 'Bearer test-token', ); expect(response.status).toEqual(200); @@ -542,7 +533,7 @@ describe('createRouter', () => { const response = await request(app) .post('/authorize') - .auth('test-token', { type: 'bearer' }) + .auth(mockCredentials.user.token(), { type: 'bearer' }) .send({ items: [ { @@ -589,6 +580,7 @@ describe('createRouter', () => { expect(mockApplyConditions).toHaveBeenCalledWith( 'plugin-1', + mockCredentials.user(), [ expect.objectContaining({ id: '123', @@ -597,11 +589,11 @@ describe('createRouter', () => { conditions: { rule: 'test-rule', params: ['yes'] }, }), ], - 'Bearer test-token', ); expect(mockApplyConditions).toHaveBeenCalledWith( 'plugin-2', + mockCredentials.user(), [ expect.objectContaining({ id: '234', @@ -610,7 +602,6 @@ describe('createRouter', () => { conditions: { rule: 'test-rule', params: ['yes'] }, }), ], - 'Bearer test-token', ); expect(response.status).toEqual(200); @@ -656,7 +647,7 @@ describe('createRouter', () => { const response = await request(app) .post('/authorize') - .auth('test-token', { type: 'bearer' }) + .auth(mockCredentials.user.token(), { type: 'bearer' }) .send({ items: [ { @@ -684,6 +675,7 @@ describe('createRouter', () => { expect(mockApplyConditions).toHaveBeenCalledWith( 'test-plugin', + mockCredentials.user(), [ expect.objectContaining({ id: '123', @@ -698,7 +690,6 @@ describe('createRouter', () => { conditions: { rule: 'test-rule', params }, }), ], - 'Bearer test-token', ); expect(response.status).toEqual(200); diff --git a/plugins/permission-backend/src/service/router.ts b/plugins/permission-backend/src/service/router.ts index b7e77fdba9..cd7c71fd87 100644 --- a/plugins/permission-backend/src/service/router.ts +++ b/plugins/permission-backend/src/service/router.ts @@ -19,8 +19,8 @@ import express, { Request, Response } from 'express'; import Router from 'express-promise-router'; import { Logger } from 'winston'; import { + createLegacyAuthAdapters, errorHandler, - PluginEndpointDiscovery, } from '@backstage/backend-common'; import { InputError } from '@backstage/errors'; import { @@ -46,6 +46,15 @@ import { PermissionIntegrationClient } from './PermissionIntegrationClient'; import { memoize } from 'lodash'; import DataLoader from 'dataloader'; import { Config } from '@backstage/config'; +import { + AuthService, + BackstageCredentials, + BackstageNonePrincipal, + BackstageUserPrincipal, + DiscoveryService, + HttpAuthService, + UserInfoService, +} from '@backstage/backend-plugin-api'; const attributesSchema: z.ZodSchema = z.object({ action: z @@ -93,28 +102,51 @@ const evaluatePermissionRequestBatchSchema: z.ZodSchema[], - user: BackstageIdentityResponse | undefined, policy: PermissionPolicy, permissionIntegrationClient: PermissionIntegrationClient, - authHeader?: string, + credentials: BackstageCredentials< + BackstageNonePrincipal | BackstageUserPrincipal + >, + auth: AuthService, + userInfo: UserInfoService, ): Promise[]> => { const applyConditionsLoaderFor = memoize((pluginId: string) => { return new DataLoader< ApplyConditionsRequestEntry, ApplyConditionsResponseEntry >(batch => - permissionIntegrationClient.applyConditions(pluginId, batch, authHeader), + permissionIntegrationClient.applyConditions(pluginId, credentials, batch), ); }); + let user: BackstageIdentityResponse | undefined; + if (auth.isPrincipal(credentials, 'user')) { + const { ownershipEntityRefs } = await userInfo.getUserInfo(credentials); + const { token } = await auth.getPluginRequestToken({ + onBehalfOf: credentials, + targetPluginId: 'catalog', // TODO: unknown at this point + }); + user = { + identity: { + type: 'user', + userEntityRef: credentials.principal.userEntityRef, + ownershipEntityRefs, + }, + token, + }; + } + return Promise.all( requests.map(({ id, resourceRef, ...request }) => policy.handle(request, user).then(decision => { @@ -163,7 +195,8 @@ const handleRequest = async ( export async function createRouter( options: RouterOptions, ): Promise { - const { policy, discovery, identity, config, logger } = options; + const { policy, discovery, config, logger } = options; + const { auth, httpAuth, userInfo } = createLegacyAuthAdapters(options); if (!config.getOptionalBoolean('permission.enabled')) { logger.warn( @@ -173,6 +206,7 @@ export async function createRouter( const permissionIntegrationClient = new PermissionIntegrationClient({ discovery, + auth, }); const router = Router(); @@ -188,7 +222,9 @@ export async function createRouter( req: Request, res: Response, ) => { - const user = await identity.getIdentity({ request: req }); + const credentials = await httpAuth.credentials(req, { + allow: ['user', 'none'], + }); const parseResult = evaluatePermissionRequestBatchSchema.safeParse( req.body, @@ -203,10 +239,11 @@ export async function createRouter( res.json({ items: await handleRequest( body.items, - user, policy, permissionIntegrationClient, - req.header('authorization'), + credentials, + auth, + userInfo, ), }); }, diff --git a/plugins/permission-common/CHANGELOG.md b/plugins/permission-common/CHANGELOG.md index 74bd6db59b..1a78b40263 100644 --- a/plugins/permission-common/CHANGELOG.md +++ b/plugins/permission-common/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-permission-common +## 0.7.13-next.0 + +### Patch Changes + +- 0502d82: The `token` option of the `PermissionEvaluator` methods is now deprecated. The options that only apply to backend implementations have been moved to `PermissionsService` from `@backstage/backend-plugin-api` instead. +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + ## 0.7.12 ### Patch Changes diff --git a/plugins/permission-common/package.json b/plugins/permission-common/package.json index 204e146e56..0668ece19c 100644 --- a/plugins/permission-common/package.json +++ b/plugins/permission-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-common", - "version": "0.7.12", + "version": "0.7.13-next.0", "description": "Isomorphic types and client for Backstage permissions and authorization", "backstage": { "role": "common-library" diff --git a/plugins/permission-node/CHANGELOG.md b/plugins/permission-node/CHANGELOG.md index 03be74d5ad..173a3288e9 100644 --- a/plugins/permission-node/CHANGELOG.md +++ b/plugins/permission-node/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-permission-node +## 0.7.24-next.0 + +### Patch Changes + +- 0502d82: The `ServerPermissionClient` has been migrated to implement the `PermissionsService` interface, now accepting the new `BackstageCredentials` object in addition to the `token` option, which is now deprecated. It now also optionally depends on the new `AuthService`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.7.21 ### Patch Changes diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index 1b217d281c..a28de04385 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.21", + "version": "0.7.24-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-react/CHANGELOG.md b/plugins/permission-react/CHANGELOG.md index 8141a61edf..fcde875dc6 100644 --- a/plugins/permission-react/CHANGELOG.md +++ b/plugins/permission-react/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-permission-react +## 0.4.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.4.20 ### Patch Changes diff --git a/plugins/permission-react/package.json b/plugins/permission-react/package.json index ba8eafe830..6f5db94d97 100644 --- a/plugins/permission-react/package.json +++ b/plugins/permission-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-react", - "version": "0.4.20", + "version": "0.4.21-next.0", "backstage": { "role": "web-library" }, diff --git a/plugins/playlist-backend/CHANGELOG.md b/plugins/playlist-backend/CHANGELOG.md index c6f8dd1ab0..29864d0cc8 100644 --- a/plugins/playlist-backend/CHANGELOG.md +++ b/plugins/playlist-backend/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-playlist-backend +## 0.3.17-next.0 + +### Patch Changes + +- 6813366: Migrated to support new auth services. +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-playlist-common@0.1.15-next.0 + ## 0.3.14 ### Patch Changes diff --git a/plugins/playlist-backend/package.json b/plugins/playlist-backend/package.json index e7889830e1..7ae9b8c0a7 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.14", + "version": "0.3.17-next.0", "backstage": { "role": "backend-plugin" }, diff --git a/plugins/playlist-common/CHANGELOG.md b/plugins/playlist-common/CHANGELOG.md index 0b65ee551f..4e67cc4a64 100644 --- a/plugins/playlist-common/CHANGELOG.md +++ b/plugins/playlist-common/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-playlist-common +## 0.1.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + ## 0.1.14 ### Patch Changes diff --git a/plugins/playlist-common/package.json b/plugins/playlist-common/package.json index 2fae0ecdf0..c3eefbbf0b 100644 --- a/plugins/playlist-common/package.json +++ b/plugins/playlist-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist-common", - "version": "0.1.14", + "version": "0.1.15-next.0", "description": "Common functionalities for the playlist plugin", "backstage": { "role": "common-library" diff --git a/plugins/playlist/CHANGELOG.md b/plugins/playlist/CHANGELOG.md index f5d5cadb66..2b4a967700 100644 --- a/plugins/playlist/CHANGELOG.md +++ b/plugins/playlist/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-playlist +## 0.2.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + - @backstage/plugin-permission-react@0.4.21-next.0 + - @backstage/plugin-playlist-common@0.1.15-next.0 + ## 0.2.4 ### Patch Changes diff --git a/plugins/playlist/package.json b/plugins/playlist/package.json index 512cbc74ab..7cd423e800 100644 --- a/plugins/playlist/package.json +++ b/plugins/playlist/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist", - "version": "0.2.4", + "version": "0.2.5-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/proxy-backend/CHANGELOG.md b/plugins/proxy-backend/CHANGELOG.md index 8189aa3ef8..2c59cefb39 100644 --- a/plugins/proxy-backend/CHANGELOG.md +++ b/plugins/proxy-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-proxy-backend +## 0.4.11-next.0 + +### Patch Changes + +- 1b4fd09: Updated dependency `yup` to `^1.0.0`. +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.4.8 ### Patch Changes diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 5e4ed1e728..731d1882fb 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-proxy-backend", - "version": "0.4.8", + "version": "0.4.11-next.0", "description": "A Backstage backend plugin that helps you set up proxy endpoints in the backend", "backstage": { "role": "backend-plugin" diff --git a/plugins/puppetdb/CHANGELOG.md b/plugins/puppetdb/CHANGELOG.md index bae5542cc7..6ff954c2cc 100644 --- a/plugins/puppetdb/CHANGELOG.md +++ b/plugins/puppetdb/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-puppetdb +## 0.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.1.13 ### Patch Changes diff --git a/plugins/puppetdb/package.json b/plugins/puppetdb/package.json index e3017182b4..7c3ff00dc3 100644 --- a/plugins/puppetdb/package.json +++ b/plugins/puppetdb/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-puppetdb", - "version": "0.1.13", + "version": "0.1.14-next.0", "description": "Backstage plugin to visualize resource information and Puppet facts from PuppetDB.", "backstage": { "role": "frontend-plugin" diff --git a/plugins/rollbar-backend/CHANGELOG.md b/plugins/rollbar-backend/CHANGELOG.md index 40924ec9b0..686d37df31 100644 --- a/plugins/rollbar-backend/CHANGELOG.md +++ b/plugins/rollbar-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-rollbar-backend +## 0.1.58-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.1.55 ### Patch Changes diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index aea99d495a..222cb2c30e 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-rollbar-backend", - "version": "0.1.55", + "version": "0.1.58-next.0", "description": "A Backstage backend plugin that integrates towards Rollbar", "backstage": { "role": "backend-plugin" diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md index 928bf3d278..a4f475b6e2 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-rollbar +## 0.4.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.4.30 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 6990f08141..76df170ce5 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-rollbar", - "version": "0.4.30", + "version": "0.4.31-next.0", "description": "A Backstage plugin that integrates towards Rollbar", "backstage": { "role": "frontend-plugin" diff --git a/plugins/scaffolder-backend-module-azure/CHANGELOG.md b/plugins/scaffolder-backend-module-azure/CHANGELOG.md index 994e54a6b1..229a04b961 100644 --- a/plugins/scaffolder-backend-module-azure/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-azure/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-scaffolder-backend-module-azure +## 0.1.5-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.1.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-azure/package.json b/plugins/scaffolder-backend-module-azure/package.json index 26be04f108..a283e42c5e 100644 --- a/plugins/scaffolder-backend-module-azure/package.json +++ b/plugins/scaffolder-backend-module-azure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-azure", "description": "The azure module for @backstage/plugin-scaffolder-backend", - "version": "0.1.2", + "version": "0.1.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -47,7 +47,8 @@ "yaml": "^2.0.0" }, "devDependencies": { - "@backstage/cli": "workspace:^" + "@backstage/cli": "workspace:^", + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" }, "files": [ "dist" diff --git a/plugins/scaffolder-backend-module-azure/src/actions/azure.examples.test.ts b/plugins/scaffolder-backend-module-azure/src/actions/azure.examples.test.ts index 27989650ce..e00362c457 100644 --- a/plugins/scaffolder-backend-module-azure/src/actions/azure.examples.test.ts +++ b/plugins/scaffolder-backend-module-azure/src/actions/azure.examples.test.ts @@ -18,11 +18,10 @@ import yaml from 'yaml'; import { ConfigReader } from '@backstage/config'; import { createPublishAzureAction } from './azure'; import { ScmIntegrations } from '@backstage/integration'; -import { getVoidLogger } from '@backstage/backend-common'; import { WebApi } from 'azure-devops-node-api'; -import { PassThrough } from 'stream'; import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; import { examples } from './azure.examples'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; jest.mock('azure-devops-node-api', () => ({ WebApi: jest.fn(), @@ -55,13 +54,7 @@ describe('publish:azure examples', () => { const integrations = ScmIntegrations.fromConfig(config); const action = createPublishAzureAction({ integrations, config }); - const mockContext = { - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const mockContext = createMockActionContext(); const mockGitClient = { createRepository: jest.fn(), diff --git a/plugins/scaffolder-backend-module-azure/src/actions/azure.test.ts b/plugins/scaffolder-backend-module-azure/src/actions/azure.test.ts index 4401e01007..a23eebb93a 100644 --- a/plugins/scaffolder-backend-module-azure/src/actions/azure.test.ts +++ b/plugins/scaffolder-backend-module-azure/src/actions/azure.test.ts @@ -34,10 +34,9 @@ jest.mock('@backstage/plugin-scaffolder-node', () => { import { createPublishAzureAction } from './azure'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; import { WebApi } from 'azure-devops-node-api'; -import { PassThrough } from 'stream'; import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; describe('publish:azure', () => { const config = new ConfigReader({ @@ -54,16 +53,10 @@ describe('publish:azure', () => { const integrations = ScmIntegrations.fromConfig(config); const action = createPublishAzureAction({ integrations, config }); - const mockContext = { - input: { - repoUrl: 'dev.azure.com?repo=repo&owner=owner&organization=org', - }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + + const mockContext = createMockActionContext({ + input: { repoUrl: 'dev.azure.com?repo=repo&owner=owner&organization=org' }, + }); const mockGitClient = { createRepository: jest.fn(), diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/scaffolder-backend-module-bitbucket-cloud/CHANGELOG.md index 039d7d80a5..28ac34a103 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-scaffolder-backend-module-bitbucket-cloud +## 0.1.3-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.1.0 ### Minor Changes diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/package.json b/plugins/scaffolder-backend-module-bitbucket-cloud/package.json index 1a40b517d6..eab9df6925 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/package.json +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud", "description": "The Bitbucket Cloud module for @backstage/plugin-scaffolder-backend", - "version": "0.1.0", + "version": "0.1.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -50,6 +50,7 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^", "msw": "^1.0.0" }, "files": [ diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloud.test.ts b/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloud.test.ts index 7045d58e01..6a079a3f9b 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloud.test.ts +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloud.test.ts @@ -32,9 +32,8 @@ import { setupServer } from 'msw/node'; import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; -import { PassThrough } from 'stream'; import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; describe('publish:bitbucketCloud', () => { const config = new ConfigReader({ @@ -50,17 +49,12 @@ describe('publish:bitbucketCloud', () => { const integrations = ScmIntegrations.fromConfig(config); const action = createPublishBitbucketCloudAction({ integrations, config }); - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'bitbucket.org?workspace=workspace&project=project&repo=repo', repoVisibility: 'private' as const, }, - workspacePath: 'wsp', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); const server = setupServer(); setupRequestMockHandlers(server); diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudPipelinesRun.examples.test.ts b/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudPipelinesRun.examples.test.ts index 90ae2c08b9..472c7a6a03 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudPipelinesRun.examples.test.ts +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudPipelinesRun.examples.test.ts @@ -14,16 +14,15 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; -import { PassThrough } from 'stream'; import { createBitbucketPipelinesRunAction } from './bitbucketCloudPipelinesRun'; import yaml from 'yaml'; import { examples } from './bitbucketCloudPipelinesRun.examples'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; describe('bitbucket:pipelines:run', () => { const config = new ConfigReader({ @@ -39,14 +38,7 @@ describe('bitbucket:pipelines:run', () => { const integrations = ScmIntegrations.fromConfig(config); const action = createBitbucketPipelinesRunAction({ integrations }); - const mockContext = { - input: {}, - workspacePath: 'wsp', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const mockContext = createMockActionContext(); const responseJson = { repository: { links: { diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudPipelinesRun.test.ts b/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudPipelinesRun.test.ts index dc76a79898..9386246868 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudPipelinesRun.test.ts +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/src/actions/bitbucketCloudPipelinesRun.test.ts @@ -14,14 +14,13 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; -import { PassThrough } from 'stream'; import { createBitbucketPipelinesRunAction } from './bitbucketCloudPipelinesRun'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; describe('bitbucket:pipelines:run', () => { const config = new ConfigReader({ @@ -37,14 +36,7 @@ describe('bitbucket:pipelines:run', () => { const integrations = ScmIntegrations.fromConfig(config); const action = createBitbucketPipelinesRunAction({ integrations }); - const mockContext = { - input: {}, - workspacePath: 'wsp', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const mockContext = createMockActionContext(); const workspace = 'test-workspace'; const repo_slug = 'test-repo-slug'; const responseJson = { diff --git a/plugins/scaffolder-backend-module-bitbucket-server/CHANGELOG.md b/plugins/scaffolder-backend-module-bitbucket-server/CHANGELOG.md index 39293f6299..34e5732af3 100644 --- a/plugins/scaffolder-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-scaffolder-backend-module-bitbucket-server +## 0.1.3-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.1.0 ### Minor Changes diff --git a/plugins/scaffolder-backend-module-bitbucket-server/package.json b/plugins/scaffolder-backend-module-bitbucket-server/package.json index 8f4841180d..c0626baffb 100644 --- a/plugins/scaffolder-backend-module-bitbucket-server/package.json +++ b/plugins/scaffolder-backend-module-bitbucket-server/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-bitbucket-server", "description": "The Bitbucket Server module for @backstage/plugin-scaffolder-backend", - "version": "0.1.0", + "version": "0.1.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -50,6 +50,7 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^", "msw": "^1.0.0" }, "files": [ diff --git a/plugins/scaffolder-backend-module-bitbucket-server/src/actions/bitbucketServer.test.ts b/plugins/scaffolder-backend-module-bitbucket-server/src/actions/bitbucketServer.test.ts index ab7b52996f..1d42e7368c 100644 --- a/plugins/scaffolder-backend-module-bitbucket-server/src/actions/bitbucketServer.test.ts +++ b/plugins/scaffolder-backend-module-bitbucket-server/src/actions/bitbucketServer.test.ts @@ -32,9 +32,8 @@ import { setupServer } from 'msw/node'; import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; -import { PassThrough } from 'stream'; import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; describe('publish:bitbucketServer', () => { const config = new ConfigReader({ @@ -60,17 +59,12 @@ describe('publish:bitbucketServer', () => { const integrations = ScmIntegrations.fromConfig(config); const action = createPublishBitbucketServerAction({ integrations, config }); - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'hosted.bitbucket.com?project=project&repo=repo', repoVisibility: 'private' as const, }, - workspacePath: 'wsp', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); const server = setupServer(); setupRequestMockHandlers(server); diff --git a/plugins/scaffolder-backend-module-bitbucket-server/src/actions/bitbucketServerPullRequest.test.ts b/plugins/scaffolder-backend-module-bitbucket-server/src/actions/bitbucketServerPullRequest.test.ts index 3af47853c3..9d2dd915f8 100644 --- a/plugins/scaffolder-backend-module-bitbucket-server/src/actions/bitbucketServerPullRequest.test.ts +++ b/plugins/scaffolder-backend-module-bitbucket-server/src/actions/bitbucketServerPullRequest.test.ts @@ -32,8 +32,7 @@ import { setupServer } from 'msw/node'; import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; -import { PassThrough } from 'stream'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; describe('publish:bitbucketServer:pull-request', () => { const config = new ConfigReader({ @@ -62,7 +61,7 @@ describe('publish:bitbucketServer:pull-request', () => { integrations, config, }); - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'hosted.bitbucket.com?project=project&repo=repo', title: 'Add Scaffolder actions for Bitbucket Server', @@ -71,12 +70,7 @@ describe('publish:bitbucketServer:pull-request', () => { targetBranch: 'master', sourceBranch: 'develop', }, - workspacePath: 'wsp', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); const responseOfBranches = { size: 3, limit: 25, diff --git a/plugins/scaffolder-backend-module-bitbucket/CHANGELOG.md b/plugins/scaffolder-backend-module-bitbucket/CHANGELOG.md index 658c5f587f..d418e9df6f 100644 --- a/plugins/scaffolder-backend-module-bitbucket/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-bitbucket/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-scaffolder-backend-module-bitbucket +## 0.2.3-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.3-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.3-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.2.0 ### Minor Changes diff --git a/plugins/scaffolder-backend-module-bitbucket/package.json b/plugins/scaffolder-backend-module-bitbucket/package.json index c34c07c008..45c2a6436d 100644 --- a/plugins/scaffolder-backend-module-bitbucket/package.json +++ b/plugins/scaffolder-backend-module-bitbucket/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-bitbucket", "description": "The bitbucket module for @backstage/plugin-scaffolder-backend", - "version": "0.2.0", + "version": "0.2.3-next.0", "deprecated": true, "main": "src/index.ts", "types": "src/index.ts", @@ -53,6 +53,7 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^", "msw": "^1.0.0" }, "files": [ diff --git a/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.examples.test.ts b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.examples.test.ts index 73325ab5bf..c8f35fa0bf 100644 --- a/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.examples.test.ts +++ b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.examples.test.ts @@ -32,12 +32,11 @@ import { setupServer } from 'msw/node'; import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; -import { PassThrough } from 'stream'; import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; import yaml from 'yaml'; import { sep } from 'path'; import { examples } from './bitbucket.examples'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; describe('publish:bitbucket', () => { const config = new ConfigReader({ @@ -61,17 +60,12 @@ describe('publish:bitbucket', () => { const integrations = ScmIntegrations.fromConfig(config); const action = createPublishBitbucketAction({ integrations, config }); - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'bitbucket.org?workspace=workspace&project=project&repo=repo', repoVisibility: 'private' as const, }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); const server = setupServer(); setupRequestMockHandlers(server); diff --git a/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.test.ts b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.test.ts index d6e068c039..a63d657904 100644 --- a/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.test.ts +++ b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.test.ts @@ -31,9 +31,8 @@ import { setupServer } from 'msw/node'; import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; -import { PassThrough } from 'stream'; import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; describe('publish:bitbucket', () => { const config = new ConfigReader({ @@ -57,17 +56,12 @@ describe('publish:bitbucket', () => { const integrations = ScmIntegrations.fromConfig(config); const action = createPublishBitbucketAction({ integrations, config }); - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'bitbucket.org?workspace=workspace&project=project&repo=repo', repoVisibility: 'private' as const, }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); const server = setupServer(); setupRequestMockHandlers(server); diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md b/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md index 4f65016afb..69fdf9782e 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-scaffolder-backend-module-confluence-to-markdown +## 0.2.14-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.2.11 ### 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 07d72d73a6..63d9979f8d 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.2.11", + "version": "0.2.14-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -54,6 +54,7 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^", "msw": "^1.0.0" }, "files": [ diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.test.ts b/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.test.ts index f3bf1fef35..18ff0ad3ec 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.test.ts +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.test.ts @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { PassThrough } from 'stream'; import { createConfluenceToMarkdownAction } from './confluenceToMarkdown'; import { getVoidLogger } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; @@ -28,6 +27,7 @@ import { setupServer } from 'msw/node'; import { examples } from './confluenceToMarkdown.examples'; import yaml from 'yaml'; import { ActionContext } from '@backstage/plugin-scaffolder-node'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; describe('confluence:transform:markdown examples', () => { const baseUrl = `https://confluence.example.com`; @@ -71,14 +71,11 @@ describe('confluence:transform:markdown examples', () => { }), search: jest.fn(), }; - mockContext = { + mockContext = createMockActionContext({ input: yaml.parse(examples[0].example).steps[0].input, workspacePath, logger, - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); mockDir.setContent({ 'workspace/mkdocs.yml': 'File contents' }); }); diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.test.ts b/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.test.ts index 39c9c98544..eccb66f79e 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.test.ts +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.test.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { PassThrough } from 'stream'; + import { createConfluenceToMarkdownAction } from './confluenceToMarkdown'; import { getVoidLogger } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; @@ -26,6 +26,7 @@ import { import type { ActionContext } from '@backstage/plugin-scaffolder-node'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; describe('confluence:transform:markdown', () => { const baseUrl = `https://nodomain.confluence.com`; @@ -69,7 +70,7 @@ describe('confluence:transform:markdown', () => { }), search: jest.fn(), }; - mockContext = { + mockContext = createMockActionContext({ input: { confluenceUrls: [ 'https://nodomain.confluence.com/display/testing/mkdocs', @@ -79,10 +80,7 @@ describe('confluence:transform:markdown', () => { }, workspacePath, logger, - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); mockDir.setContent({ 'workspace/mkdocs.yml': 'File contents' }); }); diff --git a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md index e2535d5b9c..6df6d4e404 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-scaffolder-backend-module-cookiecutter +## 0.2.37-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/types@1.1.1 + ## 0.2.34 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index 236ebd6c88..d1b7fffc34 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.34", + "version": "0.2.37-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -53,6 +53,7 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^", "@types/command-exists": "^1.2.0", "@types/fs-extra": "^11.0.0" }, diff --git a/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts b/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts index af63ca0e48..92a636e58b 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts +++ b/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts @@ -14,19 +14,15 @@ * limitations under the License. */ -import { - getVoidLogger, - UrlReader, - ContainerRunner, -} from '@backstage/backend-common'; +import { UrlReader, ContainerRunner } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { JsonObject } from '@backstage/types'; import { ScmIntegrations } from '@backstage/integration'; import { createMockDirectory } from '@backstage/backend-test-utils'; -import { PassThrough } from 'stream'; import { createFetchCookiecutterAction } from './cookiecutter'; import { join } from 'path'; import type { ActionContext } from '@backstage/plugin-scaffolder-node'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; const executeShellCommand = jest.fn(); const commandExists = jest.fn(); @@ -88,7 +84,7 @@ describe('fetch:cookiecutter', () => { beforeEach(() => { jest.resetAllMocks(); - mockContext = { + mockContext = createMockActionContext({ input: { url: 'https://google.com/cookie/cutter', targetPath: 'something', @@ -101,11 +97,7 @@ describe('fetch:cookiecutter', () => { baseUrl: 'somebase', }, workspacePath: mockTmpDir, - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), - }; + }); mockDir.setContent({ template: {} }); commandExists.mockResolvedValue(null); diff --git a/plugins/scaffolder-backend-module-gerrit/CHANGELOG.md b/plugins/scaffolder-backend-module-gerrit/CHANGELOG.md index 8bfc5820ca..fa6a6641ff 100644 --- a/plugins/scaffolder-backend-module-gerrit/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-scaffolder-backend-module-gerrit +## 0.1.5-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.1.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-gerrit/package.json b/plugins/scaffolder-backend-module-gerrit/package.json index dad19dc06b..643ab5d963 100644 --- a/plugins/scaffolder-backend-module-gerrit/package.json +++ b/plugins/scaffolder-backend-module-gerrit/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-gerrit", "description": "The gerrit module for @backstage/plugin-scaffolder-backend", - "version": "0.1.2", + "version": "0.1.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -49,6 +49,7 @@ "@backstage/backend-common": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^", "msw": "^1.0.0" }, "files": [ diff --git a/plugins/scaffolder-backend-module-gerrit/src/actions/gerrit.test.ts b/plugins/scaffolder-backend-module-gerrit/src/actions/gerrit.test.ts index 2bd7783cb6..c08544843f 100644 --- a/plugins/scaffolder-backend-module-gerrit/src/actions/gerrit.test.ts +++ b/plugins/scaffolder-backend-module-gerrit/src/actions/gerrit.test.ts @@ -33,9 +33,8 @@ import { setupServer } from 'msw/node'; import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; -import { PassThrough } from 'stream'; import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; describe('publish:gerrit', () => { const config = new ConfigReader({ @@ -53,18 +52,13 @@ describe('publish:gerrit', () => { const description = 'for the lols'; const integrations = ScmIntegrations.fromConfig(config); const action = createPublishGerritAction({ integrations, config }); - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'gerrithost.org?owner=owner&workspace=parent&project=project&repo=repo', description, }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); const server = setupServer(); setupRequestMockHandlers(server); diff --git a/plugins/scaffolder-backend-module-gerrit/src/actions/gerritReview.test.ts b/plugins/scaffolder-backend-module-gerrit/src/actions/gerritReview.test.ts index eeae3871ee..91236d4cc0 100644 --- a/plugins/scaffolder-backend-module-gerrit/src/actions/gerritReview.test.ts +++ b/plugins/scaffolder-backend-module-gerrit/src/actions/gerritReview.test.ts @@ -24,9 +24,8 @@ jest.mock('@backstage/plugin-scaffolder-node', () => { import { createPublishGerritReviewAction } from './gerritReview'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; -import { PassThrough } from 'stream'; import { commitAndPushRepo } from '@backstage/plugin-scaffolder-node'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; describe('publish:gerrit:review', () => { const config = new ConfigReader({ @@ -43,18 +42,13 @@ describe('publish:gerrit:review', () => { const integrations = ScmIntegrations.fromConfig(config); const action = createPublishGerritReviewAction({ integrations, config }); - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'gerrithost.org?owner=owner&workspace=parent&project=project&repo=repo', gitCommitMessage: 'Review from backstage', }, - workspacePath: 'workspace', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { jest.resetAllMocks(); diff --git a/plugins/scaffolder-backend-module-gitea/CHANGELOG.md b/plugins/scaffolder-backend-module-gitea/CHANGELOG.md index 30fb0e31b7..920087cdba 100644 --- a/plugins/scaffolder-backend-module-gitea/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-gitea/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-scaffolder-backend-module-gitea +## 0.1.3-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.1.0 ### Minor Changes diff --git a/plugins/scaffolder-backend-module-gitea/package.json b/plugins/scaffolder-backend-module-gitea/package.json index bc4912d76c..055a02d348 100644 --- a/plugins/scaffolder-backend-module-gitea/package.json +++ b/plugins/scaffolder-backend-module-gitea/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-gitea", "description": "The gitea module for @backstage/plugin-scaffolder-backend", - "version": "0.1.0", + "version": "0.1.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -49,6 +49,7 @@ "@backstage/backend-common": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^", "msw": "^1.0.0" }, "files": [ diff --git a/plugins/scaffolder-backend-module-gitea/src/actions/gitea.test.ts b/plugins/scaffolder-backend-module-gitea/src/actions/gitea.test.ts index 5e1e94b1b4..8675b1ff97 100644 --- a/plugins/scaffolder-backend-module-gitea/src/actions/gitea.test.ts +++ b/plugins/scaffolder-backend-module-gitea/src/actions/gitea.test.ts @@ -13,14 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { PassThrough } from 'stream'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; import { createPublishGiteaAction } from './gitea'; import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; import { rest } from 'msw'; import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { setupServer } from 'msw/node'; jest.mock('@backstage/plugin-scaffolder-node', () => { @@ -48,17 +47,12 @@ describe('publish:gitea', () => { const description = 'for the lols'; const integrations = ScmIntegrations.fromConfig(config); const action = createPublishGiteaAction({ integrations, config }); - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'gitea.com?repo=repo&owner=owner', description, }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); const server = setupServer(); setupRequestMockHandlers(server); diff --git a/plugins/scaffolder-backend-module-github/CHANGELOG.md b/plugins/scaffolder-backend-module-github/CHANGELOG.md index 15e8f0adfd..818502d7cd 100644 --- a/plugins/scaffolder-backend-module-github/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-github/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-scaffolder-backend-module-github +## 0.2.3-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- 1753898: Updated dependency `octokit-plugin-create-pull-request` to `^5.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.2.0 ### Minor Changes diff --git a/plugins/scaffolder-backend-module-github/package.json b/plugins/scaffolder-backend-module-github/package.json index 58651b3c07..a3b02ec189 100644 --- a/plugins/scaffolder-backend-module-github/package.json +++ b/plugins/scaffolder-backend-module-github/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-github", "description": "The github module for @backstage/plugin-scaffolder-backend", - "version": "0.2.0", + "version": "0.2.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -53,6 +53,7 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^", "@types/libsodium-wrappers": "^0.7.10", "fs-extra": "^11.2.0", "jest-when": "^3.1.0", diff --git a/plugins/scaffolder-backend-module-github/src/actions/github.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/github.examples.test.ts index 7ea5e025ce..6a6c6daf13 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/github.examples.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/github.examples.test.ts @@ -36,14 +36,13 @@ import { TemplateAction, initRepoAndPush, } from '@backstage/plugin-scaffolder-node'; -import { getVoidLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { DefaultGithubCredentialsProvider, GithubCredentialsProvider, ScmIntegrations, } from '@backstage/integration'; -import { PassThrough } from 'stream'; import { createPublishGithubAction } from './github'; import { examples } from './github.examples'; import yaml from 'yaml'; @@ -101,19 +100,14 @@ describe('publish:github', () => { let githubCredentialsProvider: GithubCredentialsProvider; let action: TemplateAction; - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'github.com?repo=repo&owner=owner', description: 'description', repoVisibility: 'private' as const, access: 'owner/blam', }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { initRepoAndPushMocked.mockResolvedValue({ diff --git a/plugins/scaffolder-backend-module-github/src/actions/github.test.ts b/plugins/scaffolder-backend-module-github/src/actions/github.test.ts index 75d9b74a8b..02d6a2afaf 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/github.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/github.test.ts @@ -34,15 +34,14 @@ jest.mock('@backstage/plugin-scaffolder-node', () => { }); import { TemplateAction } from '@backstage/plugin-scaffolder-node'; -import { getVoidLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { DefaultGithubCredentialsProvider, GithubCredentialsProvider, ScmIntegrations, } from '@backstage/integration'; import { when } from 'jest-when'; -import { PassThrough } from 'stream'; import { createPublishGithubAction } from './github'; import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; import { @@ -103,19 +102,14 @@ describe('publish:github', () => { let githubCredentialsProvider: GithubCredentialsProvider; let action: TemplateAction; - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'github.com?repo=repo&owner=owner', description: 'description', repoVisibility: 'private' as const, access: 'owner/blam', }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { initRepoAndPushMocked.mockResolvedValue({ diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubActionsDispatch.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubActionsDispatch.examples.test.ts index fe04142a98..1e59037c04 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubActionsDispatch.examples.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubActionsDispatch.examples.test.ts @@ -20,10 +20,9 @@ import { GithubCredentialsProvider, } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; -import { PassThrough } from 'stream'; import { createGithubActionsDispatchAction } from './githubActionsDispatch'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import yaml from 'yaml'; import { examples } from './githubActionsDispatch.examples'; @@ -56,18 +55,13 @@ describe('github:actions:dispatch', () => { let githubCredentialsProvider: GithubCredentialsProvider; let action: TemplateAction; - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'github.com?repo=repo&owner=owner', workflowId: 'a-workflow-id', branchOrTagName: 'main', }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { jest.resetAllMocks(); diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubActionsDispatch.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubActionsDispatch.test.ts index 3d59e43695..7f0d9b0490 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubActionsDispatch.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubActionsDispatch.test.ts @@ -20,9 +20,8 @@ import { GithubCredentialsProvider, } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; -import { PassThrough } from 'stream'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { createGithubActionsDispatchAction } from './githubActionsDispatch'; const mockOctokit = { @@ -54,18 +53,13 @@ describe('github:actions:dispatch', () => { let githubCredentialsProvider: GithubCredentialsProvider; let action: TemplateAction; - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'github.com?repo=repo&owner=owner', workflowId: 'a-workflow-id', branchOrTagName: 'main', }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { jest.resetAllMocks(); diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubAutolinks.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubAutolinks.examples.test.ts index 612f68dea2..a686ea7f6d 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubAutolinks.examples.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubAutolinks.examples.test.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { DefaultGithubCredentialsProvider, @@ -22,8 +21,8 @@ import { ScmIntegrations, } from '@backstage/integration'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; -import { PassThrough } from 'stream'; import { createGithubAutolinksAction } from './githubAutolinks'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { examples } from './githubAutolinks.examples'; import yaml from 'yaml'; @@ -55,9 +54,12 @@ describe('github:autolinks:create', () => { const integrations = ScmIntegrations.fromConfig(config); let githubCredentialsProvider: GithubCredentialsProvider; let action: TemplateAction; + const input = yaml.parse(examples[0].example).steps[0].input; + const mockContext = createMockActionContext({ + input, + }); it('should call the githubApis for creating autolink reference', async () => { - const input = yaml.parse(examples[0].example).steps[0].input; githubCredentialsProvider = DefaultGithubCredentialsProvider.fromIntegrations(integrations); action = createGithubAutolinksAction({ @@ -70,14 +72,7 @@ describe('github:autolinks:create', () => { id: '1', }, }); - await action.handler({ - input, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }); + await action.handler(mockContext); expect(mockOctokit.rest.repos.createAutolink).toHaveBeenCalledWith({ owner: 'owner', diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubAutolinks.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubAutolinks.test.ts index 95c0226104..56115c156c 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubAutolinks.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubAutolinks.test.ts @@ -14,15 +14,15 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { DefaultGithubCredentialsProvider, GithubCredentialsProvider, ScmIntegrations, } from '@backstage/integration'; +import { createMockDirectory } from '@backstage/backend-test-utils'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; -import { PassThrough } from 'stream'; import { createGithubAutolinksAction } from './githubAutolinks'; const mockOctokit = { @@ -53,13 +53,7 @@ describe('github:autolinks:create', () => { const integrations = ScmIntegrations.fromConfig(config); let githubCredentialsProvider: GithubCredentialsProvider; let action: TemplateAction; - const mockContext = { - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const workspacePath = createMockDirectory().resolve('workspace'); it('should call the githubApis for creating alphanumeric autolink reference', async () => { githubCredentialsProvider = @@ -74,14 +68,16 @@ describe('github:autolinks:create', () => { id: '1', }, }); - await action.handler({ - input: { - repoUrl: 'github.com?repo=repo&owner=owner', - keyPrefix: 'TICKET-', - urlTemplate: 'https://example.com/TICKET?query=', - }, - ...mockContext, - }); + await action.handler( + createMockActionContext({ + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + keyPrefix: 'TICKET-', + urlTemplate: 'https://example.com/TICKET?query=', + }, + workspacePath, + }), + ); expect(mockOctokit.rest.repos.createAutolink).toHaveBeenCalledWith({ owner: 'owner', @@ -104,15 +100,17 @@ describe('github:autolinks:create', () => { id: '1', }, }); - await action.handler({ - input: { - repoUrl: 'github.com?repo=repo&owner=owner', - keyPrefix: 'TICKET-', - urlTemplate: 'https://example.com/TICKET?query=', - isAlphanumeric: false, - }, - ...mockContext, - }); + await action.handler( + createMockActionContext({ + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + keyPrefix: 'TICKET-', + urlTemplate: 'https://example.com/TICKET?query=', + isAlphanumeric: false, + }, + workspacePath, + }), + ); expect(mockOctokit.rest.repos.createAutolink).toHaveBeenCalledWith({ owner: 'owner', diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.examples.test.ts index c8e2a5f102..62e79dcd68 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.examples.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.examples.test.ts @@ -14,11 +14,10 @@ * limitations under the License. */ import { TemplateAction } from '@backstage/plugin-scaffolder-node'; -import { getVoidLogger } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { createGithubDeployKeyAction } from './githubDeployKey'; import yaml from 'yaml'; import { examples } from './githubDeployKey.examples'; -import { PassThrough } from 'stream'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; @@ -55,13 +54,7 @@ describe('Usage examples', () => { const integrations = ScmIntegrations.fromConfig(config); let action: TemplateAction; - const mockContext = { - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const mockContext = createMockActionContext(); beforeEach(() => { jest.resetAllMocks(); diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.test.ts index 4df9294ff5..798aa7705e 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.test.ts @@ -14,10 +14,9 @@ * limitations under the License. */ -import { PassThrough } from 'stream'; import { createGithubDeployKeyAction } from './githubDeployKey'; -import { getVoidLogger } from '@backstage/backend-common'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; @@ -55,19 +54,14 @@ describe('github:deployKey:create', () => { const integrations = ScmIntegrations.fromConfig(config); let action: TemplateAction; - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'github.com?repo=repository&owner=owner', publicKey: 'pubkey', privateKey: 'privkey', deployKeyName: 'Push Tags', }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { jest.resetAllMocks(); diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubEnvironment.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubEnvironment.examples.test.ts index 9d5dbfd35c..ecb4e9f092 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubEnvironment.examples.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubEnvironment.examples.test.ts @@ -13,9 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { PassThrough } from 'stream'; import { createGithubEnvironmentAction } from './githubEnvironment'; -import { getVoidLogger } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; @@ -59,13 +58,7 @@ describe('github:environment:create examples', () => { const integrations = ScmIntegrations.fromConfig(config); let action: TemplateAction; - const mockContext = { - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const mockContext = createMockActionContext(); beforeEach(() => { mockOctokit.rest.actions.getEnvironmentPublicKey.mockResolvedValue({ diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubEnvironment.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubEnvironment.test.ts index 8ec3d84e36..16872525b4 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubEnvironment.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubEnvironment.test.ts @@ -14,9 +14,8 @@ * limitations under the License. */ -import { PassThrough } from 'stream'; import { createGithubEnvironmentAction } from './githubEnvironment'; -import { getVoidLogger } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; @@ -58,17 +57,12 @@ describe('github:environment:create', () => { const integrations = ScmIntegrations.fromConfig(config); let action: TemplateAction; - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'github.com?repo=repository&owner=owner', name: 'envname', }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { mockOctokit.rest.actions.getEnvironmentPublicKey.mockResolvedValue({ diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubIssuesLabel.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubIssuesLabel.examples.test.ts index 9d74d53c6d..75ac6025ce 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubIssuesLabel.examples.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubIssuesLabel.examples.test.ts @@ -15,14 +15,13 @@ */ import { TemplateAction } from '@backstage/plugin-scaffolder-node'; -import { getVoidLogger } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { ConfigReader } from '@backstage/config'; import { DefaultGithubCredentialsProvider, GithubCredentialsProvider, ScmIntegrations, } from '@backstage/integration'; -import { PassThrough } from 'stream'; import { createGithubIssuesLabelAction } from './githubIssuesLabel'; import yaml from 'yaml'; import { examples } from './githubIssuesLabel.examples'; @@ -64,13 +63,7 @@ describe('github:issues:label examples', () => { let githubCredentialsProvider: GithubCredentialsProvider; let action: TemplateAction; - const mockContext = { - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const mockContext = createMockActionContext(); beforeEach(() => { jest.resetAllMocks(); diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubIssuesLabel.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubIssuesLabel.test.ts index 3da16e677a..13c7df68cb 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubIssuesLabel.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubIssuesLabel.test.ts @@ -20,10 +20,9 @@ import { DefaultGithubCredentialsProvider, GithubCredentialsProvider, } from '@backstage/integration'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; -import { PassThrough } from 'stream'; import { getOctokitOptions } from './helpers'; jest.mock('./helpers', () => { @@ -62,18 +61,13 @@ describe('github:issues:label', () => { let githubCredentialsProvider: GithubCredentialsProvider; let action: TemplateAction; - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'github.com?repo=repo&owner=owner', number: '1', labels: ['label1', 'label2'], }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { jest.resetAllMocks(); diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.examples.test.ts index 7e5d107026..dd07c88a70 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.examples.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.examples.test.ts @@ -15,14 +15,13 @@ */ import { TemplateAction } from '@backstage/plugin-scaffolder-node'; -import { getVoidLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { DefaultGithubCredentialsProvider, GithubCredentialsProvider, ScmIntegrations, } from '@backstage/integration'; -import { PassThrough } from 'stream'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { createPublishGithubPullRequestAction } from './githubPullRequest'; import yaml from 'yaml'; import { examples } from './githubPullRequest.examples'; @@ -57,13 +56,7 @@ describe('publish:github:pull-request examples', () => { let githubCredentialsProvider: GithubCredentialsProvider; let action: TemplateAction; - const mockContext = { - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const mockContext = createMockActionContext(); let fakeClient: { createPullRequest: jest.Mock; rest: { diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.test.ts index 3fe4f62e04..c9d1498187 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { createRootLogger, getRootLogger } from '@backstage/backend-common'; +import { createRootLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { GithubCredentialsProvider, @@ -25,9 +25,9 @@ import { TemplateAction, } from '@backstage/plugin-scaffolder-node'; import fs from 'fs-extra'; -import { Writable } from 'stream'; import { createPublishGithubPullRequestAction } from './githubPullRequest'; import { createMockDirectory } from '@backstage/backend-test-utils'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; // Make sure root logger is initialized ahead of FS mock createRootLogger(); @@ -131,14 +131,7 @@ describe('createPublishGithubPullRequestAction', () => { [workspacePath]: { 'file.txt': 'Hello there!' }, }); - ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + ctx = createMockActionContext({ input, workspacePath }); }); it('creates a pull request', async () => { @@ -196,14 +189,7 @@ describe('createPublishGithubPullRequestAction', () => { [workspacePath]: { 'file.txt': 'Hello there!' }, }); - ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + ctx = createMockActionContext({ input, workspacePath }); }); it('creates a pull request', async () => { @@ -263,14 +249,7 @@ describe('createPublishGithubPullRequestAction', () => { }, }); - ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + ctx = createMockActionContext({ input, workspacePath }); }); it('creates a pull request with only relevant files', async () => { @@ -322,14 +301,7 @@ describe('createPublishGithubPullRequestAction', () => { [workspacePath]: { 'file.txt': 'Hello there!' }, }); - ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + ctx = createMockActionContext({ input, workspacePath }); }); it('creates a pull request', async () => { await instance.handler(ctx); @@ -382,14 +354,7 @@ describe('createPublishGithubPullRequestAction', () => { mockDir.setContent({ [workspacePath]: {} }); - ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + ctx = createMockActionContext({ input, workspacePath }); }); it('creates a pull request and requests a review from the given reviewers', async () => { @@ -434,14 +399,7 @@ describe('createPublishGithubPullRequestAction', () => { mockDir.setContent({ [workspacePath]: {} }); - ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + ctx = createMockActionContext({ input, workspacePath }); }); it('does not call the API endpoint for requesting reviewers', async () => { @@ -470,14 +428,7 @@ describe('createPublishGithubPullRequestAction', () => { }, }); - ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + ctx = createMockActionContext({ input, workspacePath }); }); it('creates a pull request', async () => { await instance.handler(ctx); @@ -526,14 +477,7 @@ describe('createPublishGithubPullRequestAction', () => { }, }); - ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + ctx = createMockActionContext({ input, workspacePath }); }); it('creates a pull request', async () => { await instance.handler(ctx); @@ -592,14 +536,7 @@ describe('createPublishGithubPullRequestAction', () => { }, }); - ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + ctx = createMockActionContext({ input, workspacePath }); }); it('creates a pull request', async () => { await instance.handler(ctx); @@ -653,14 +590,7 @@ describe('createPublishGithubPullRequestAction', () => { [workspacePath]: { 'file.txt': 'Hello there!' }, }); - ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + ctx = createMockActionContext({ input, workspacePath }); }); it('creates a pull request', async () => { @@ -705,14 +635,7 @@ describe('createPublishGithubPullRequestAction', () => { [workspacePath]: { 'file.txt': 'Hello there!' }, }); - ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + ctx = createMockActionContext({ input, workspacePath }); }); it('creates a pull request', async () => { diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.examples.test.ts index 2377e9a7eb..843a32f758 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.examples.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.examples.test.ts @@ -23,14 +23,13 @@ jest.mock('./gitHelpers', () => { }; }); -import { getVoidLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { DefaultGithubCredentialsProvider, GithubCredentialsProvider, ScmIntegrations, } from '@backstage/integration'; -import { PassThrough } from 'stream'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { createGithubRepoCreateAction } from './githubRepoCreate'; import { entityRefToName } from './gitHelpers'; import yaml from 'yaml'; @@ -82,16 +81,11 @@ describe('github:repo:create examples', () => { let githubCredentialsProvider: GithubCredentialsProvider; let action: TemplateAction; - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'github.com?repo=repo&owner=owner', }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { githubCredentialsProvider = diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.test.ts index c72a969e96..25ddd176c1 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.test.ts @@ -15,6 +15,7 @@ */ import { TemplateAction } from '@backstage/plugin-scaffolder-node'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; jest.mock('./gitHelpers', () => { return { @@ -23,7 +24,6 @@ jest.mock('./gitHelpers', () => { }; }); -import { getVoidLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { DefaultGithubCredentialsProvider, @@ -31,7 +31,6 @@ import { ScmIntegrations, } from '@backstage/integration'; import { when } from 'jest-when'; -import { PassThrough } from 'stream'; import { createGithubRepoCreateAction } from './githubRepoCreate'; import { entityRefToName } from './gitHelpers'; @@ -82,19 +81,14 @@ describe('github:repo:create', () => { let githubCredentialsProvider: GithubCredentialsProvider; let action: TemplateAction; - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'github.com?repo=repo&owner=owner', description: 'description', repoVisibility: 'private' as const, access: 'owner/blam', }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { githubCredentialsProvider = diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.examples.test.ts index 8f8c9bf8af..691cebd367 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.examples.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.examples.test.ts @@ -29,14 +29,13 @@ import { TemplateAction, initRepoAndPush, } from '@backstage/plugin-scaffolder-node'; -import { getVoidLogger } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { ConfigReader } from '@backstage/config'; import { DefaultGithubCredentialsProvider, GithubCredentialsProvider, ScmIntegrations, } from '@backstage/integration'; -import { PassThrough } from 'stream'; import { createGithubRepoPushAction } from './githubRepoPush'; import { examples } from './githubRepoPush.examples'; import yaml from 'yaml'; @@ -102,13 +101,7 @@ describe('github:repo:push examples', () => { let githubCredentialsProvider: GithubCredentialsProvider; let action: TemplateAction; - const mockContext = { - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const mockContext = createMockActionContext(); beforeEach(() => { jest.resetAllMocks(); diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.test.ts index e16da0981d..206d4f067d 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.test.ts @@ -59,14 +59,13 @@ import { TemplateAction, initRepoAndPush, } from '@backstage/plugin-scaffolder-node'; -import { getVoidLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { DefaultGithubCredentialsProvider, GithubCredentialsProvider, ScmIntegrations, } from '@backstage/integration'; -import { PassThrough } from 'stream'; import { enableBranchProtectionOnDefaultRepoBranch } from './gitHelpers'; import { createGithubRepoPushAction } from './githubRepoPush'; @@ -103,19 +102,14 @@ describe('github:repo:push', () => { let githubCredentialsProvider: GithubCredentialsProvider; let action: TemplateAction; - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'github.com?repo=repository&owner=owner', description: 'description', repoVisibility: 'private' as const, access: 'owner/blam', }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { jest.resetAllMocks(); diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubWebhook.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubWebhook.examples.test.ts index ce1fe76c53..d58d737f93 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubWebhook.examples.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubWebhook.examples.test.ts @@ -14,14 +14,13 @@ * limitations under the License. */ import { TemplateAction } from '@backstage/plugin-scaffolder-node'; -import { getVoidLogger } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { ConfigReader } from '@backstage/config'; import { DefaultGithubCredentialsProvider, GithubCredentialsProvider, ScmIntegrations, } from '@backstage/integration'; -import { PassThrough } from 'stream'; import { createGithubWebhookAction } from './githubWebhook'; import yaml from 'yaml'; import { examples } from './githubWebhook.examples'; @@ -56,13 +55,7 @@ describe('github:webhook examples', () => { let githubCredentialsProvider: GithubCredentialsProvider; let action: TemplateAction; - const mockContext = { - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const mockContext = createMockActionContext(); beforeEach(() => { jest.resetAllMocks(); diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubWebhook.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubWebhook.test.ts index 7901210a6e..cbdcee6af1 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubWebhook.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubWebhook.test.ts @@ -20,10 +20,9 @@ import { DefaultGithubCredentialsProvider, GithubCredentialsProvider, } from '@backstage/integration'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; -import { PassThrough } from 'stream'; const mockOctokit = { rest: { @@ -66,17 +65,12 @@ describe('github:repository:webhook:create', () => { }); }); - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'github.com?repo=repo&owner=owner', webhookUrl: 'https://example.com/payload', }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); it('should call the githubApi for creating repository Webhook', async () => { const repoUrl = 'github.com?repo=repo&owner=owner'; diff --git a/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md b/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md index 1b1c2de247..9f382185ac 100644 --- a/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-scaffolder-backend-module-gitlab +## 0.2.16-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.2.13 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-gitlab/package.json b/plugins/scaffolder-backend-module-gitlab/package.json index dc96a0f356..b9157b4231 100644 --- a/plugins/scaffolder-backend-module-gitlab/package.json +++ b/plugins/scaffolder-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-gitlab", - "version": "0.2.13", + "version": "0.2.16-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -57,6 +57,7 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@backstage/core-app-api": "workspace:^", + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^", "jest-date-mock": "^1.0.8" }, "files": [ diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabGroupEnsureExistsAction.test.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabGroupEnsureExistsAction.test.ts index 72dcddc83d..4dc0305c2e 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabGroupEnsureExistsAction.test.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabGroupEnsureExistsAction.test.ts @@ -14,9 +14,8 @@ * limitations under the License. */ -import { PassThrough } from 'stream'; import { createGitlabGroupEnsureExistsAction } from './createGitlabGroupEnsureExistsAction'; -import { getVoidLogger } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { ConfigReader } from '@backstage/core-app-api'; import { ScmIntegrations } from '@backstage/integration'; @@ -35,13 +34,7 @@ jest.mock('@gitbeaker/node', () => ({ })); describe('gitlab:group:ensureExists', () => { - const mockContext = { - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const mockContext = createMockActionContext(); afterEach(() => { jest.resetAllMocks(); diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabIssueAction.test.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabIssueAction.test.ts index fe9e556656..820ef8902e 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabIssueAction.test.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabIssueAction.test.ts @@ -14,8 +14,7 @@ * limitations under the License. */ -import { PassThrough } from 'stream'; -import { getVoidLogger } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { createGitlabIssueAction, IssueType } from './createGitlabIssueAction'; import { ConfigReader } from '@backstage/core-app-api'; import { ScmIntegrations } from '@backstage/integration'; @@ -60,18 +59,14 @@ describe('gitlab:issues:create', () => { const action = createGitlabIssueAction({ integrations }); it('should return a Gitlab issue when called with minimal input params', async () => { - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'gitlab.com?repo=repo&owner=owner', projectId: 123, title: 'Computer banks to rule the world', }, workspacePath: 'seen2much', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); mockGitlabClient.Issues.create.mockResolvedValue({ id: 42, @@ -109,7 +104,7 @@ describe('gitlab:issues:create', () => { }); it('should return a Gitlab issue when called with oAuth Token', async () => { - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'gitlab.com?repo=repo&owner=owner', projectId: 123, @@ -117,11 +112,7 @@ describe('gitlab:issues:create', () => { token: 'myAwesomeToken', }, workspacePath: 'seen2much', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); mockGitlabClient.Issues.create.mockResolvedValue({ id: 42, @@ -159,7 +150,7 @@ describe('gitlab:issues:create', () => { }); it('should return a Gitlab issue when called with several input params', async () => { - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'gitlab.com?repo=repo&owner=owner', projectId: 123, @@ -173,11 +164,7 @@ describe('gitlab:issues:create', () => { labels: 'operation:mindcrime', }, workspacePath: 'seen2much', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); mockGitlabClient.Issues.create.mockResolvedValue({ id: 42, diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.examples.test.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.examples.test.ts index ab4fe0e637..5afeaba8ae 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.examples.test.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectAccessTokenAction.examples.test.ts @@ -13,13 +13,12 @@ * 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 { ScmIntegrations } from '@backstage/integration'; -import { PassThrough } from 'stream'; import yaml from 'yaml'; import { createGitlabProjectAccessTokenAction } from './createGitlabProjectAccessTokenAction'; // Adjust the import based on your project structure import { examples } from './createGitlabProjectAccessTokenAction.examples'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { DateTime } from 'luxon'; @@ -59,16 +58,11 @@ describe('gitlab:projectAccessToken:create examples', () => { const integrations = ScmIntegrations.fromConfig(config); const action = createGitlabProjectAccessTokenAction({ integrations }); - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'gitlab.com?repo=repo&owner=owner', }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { jest.resetAllMocks(); diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectDeployTokenAction.test.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectDeployTokenAction.test.ts index 1d3ae804c1..cab72c9a6d 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectDeployTokenAction.test.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabProjectDeployTokenAction.test.ts @@ -15,10 +15,9 @@ */ import { createGitlabProjectDeployTokenAction } from './createGitlabProjectDeployTokenAction'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; -import { PassThrough } from 'stream'; const mockGitlabClient = { ProjectDeployTokens: { @@ -52,7 +51,7 @@ describe('gitlab:create-deploy-token', () => { const integrations = ScmIntegrations.fromConfig(config); const action = createGitlabProjectDeployTokenAction({ integrations }); - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'gitlab.com?repo=repo&owner=owner', projectId: '123', @@ -60,12 +59,7 @@ describe('gitlab:create-deploy-token', () => { username: 'tokenuser', scopes: ['read_repository'], }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { jest.resetAllMocks(); diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.examples.test.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.examples.test.ts index e5aa610ebc..4294e5f137 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.examples.test.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.examples.test.ts @@ -14,6 +14,7 @@ * limitations under the License. */ import yaml from 'yaml'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; jest.mock('@backstage/plugin-scaffolder-node', () => { return { @@ -31,8 +32,6 @@ import { createPublishGitlabAction } from './gitlab'; import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; -import { PassThrough } from 'stream'; import { examples } from './gitlab.examples'; const mockGitlabClient = { @@ -76,16 +75,11 @@ describe('publish:gitlab', () => { const integrations = ScmIntegrations.fromConfig(config); const action = createPublishGitlabAction({ integrations, config }); - const mockContext = { + const mockContext = createMockActionContext({ input: { repoUrl: 'gitlab.com?repo=repo&owner=owner', }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { jest.resetAllMocks(); diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.test.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.test.ts index 5aca0a73e5..bbcae08063 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.test.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.test.ts @@ -29,9 +29,8 @@ jest.mock('@backstage/plugin-scaffolder-node', () => { import { createPublishGitlabAction } from './gitlab'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; -import { PassThrough } from 'stream'; import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; const mockGitlabClient = { Namespaces: { @@ -83,7 +82,8 @@ describe('publish:gitlab', () => { const integrations = ScmIntegrations.fromConfig(config); const action = createPublishGitlabAction({ integrations, config }); - const mockContext = { + + const mockContext = createMockActionContext({ input: { repoUrl: 'gitlab.com?repo=repo&owner=owner', repoVisibility: 'private' as const, @@ -91,13 +91,8 @@ describe('publish:gitlab', () => { ci_config_path: '.gitlab-ci.yml', }, }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; - const mockContextWithSettings = { + }); + const mockContextWithSettings = createMockActionContext({ input: { repoUrl: 'gitlab.com?repo=repo&owner=owner', repoVisibility: 'private' as const, @@ -108,13 +103,8 @@ describe('publish:gitlab', () => { topics: ['topic1', 'topic2'], }, }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; - const mockContextWithBranches = { + }); + const mockContextWithBranches = createMockActionContext({ input: { repoUrl: 'gitlab.com?repo=repo&owner=owner', repoVisibility: 'private' as const, @@ -135,13 +125,8 @@ describe('publish:gitlab', () => { }, ], }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; - const mockContextWithVariables = { + }); + const mockContextWithVariables = createMockActionContext({ input: { repoUrl: 'gitlab.com?repo=repo&owner=owner', repoVisibility: 'private' as const, @@ -155,12 +140,7 @@ describe('publish:gitlab', () => { }, ], }, - workspacePath: 'lol', - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { jest.resetAllMocks(); diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabMergeRequest.test.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabMergeRequest.test.ts index 0883a5e9f0..befc2c01c9 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabMergeRequest.test.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabMergeRequest.test.ts @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createRootLogger, getRootLogger } from '@backstage/backend-common'; +import { createRootLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; -import { Writable } from 'stream'; import { createPublishGitlabMergeRequestAction } from './gitlabMergeRequest'; import { createMockDirectory } from '@backstage/backend-test-utils'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; // Make sure root logger is initialized ahead of FS mock createRootLogger(); @@ -118,14 +118,7 @@ describe('createGitLabMergeRequest', () => { irrelevant: { 'bar.txt': 'Nothing to see here' }, }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); expect(mockGitlabClient.Projects.show).not.toHaveBeenCalled(); @@ -160,14 +153,7 @@ describe('createGitLabMergeRequest', () => { irrelevant: { 'bar.txt': 'Nothing to see here' }, }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); expect(mockGitlabClient.Projects.show).toHaveBeenCalledWith('owner/repo'); @@ -205,14 +191,7 @@ describe('createGitLabMergeRequest', () => { }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); expect(mockGitlabClient.MergeRequests.create).toHaveBeenCalledWith( @@ -240,14 +219,7 @@ describe('createGitLabMergeRequest', () => { }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); expect(mockGitlabClient.MergeRequests.create).toHaveBeenCalledWith( @@ -281,14 +253,7 @@ describe('createGitLabMergeRequest', () => { }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); expect(mockGitlabClient.MergeRequests.create).toHaveBeenCalledWith( @@ -321,14 +286,7 @@ describe('createGitLabMergeRequest', () => { }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); expect(mockGitlabClient.MergeRequests.create).toHaveBeenCalledWith( @@ -361,14 +319,7 @@ describe('createGitLabMergeRequest', () => { }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); expect(mockGitlabClient.MergeRequests.create).toHaveBeenCalledWith( @@ -400,14 +351,7 @@ describe('createGitLabMergeRequest', () => { }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); expect(mockGitlabClient.MergeRequests.create).toHaveBeenCalledWith( @@ -435,14 +379,7 @@ describe('createGitLabMergeRequest', () => { irrelevant: { 'bar.txt': 'Nothing to see here' }, }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); expect(mockGitlabClient.Commits.create).toHaveBeenCalledWith( @@ -484,14 +421,7 @@ describe('createGitLabMergeRequest', () => { irrelevant: { 'bar.txt': 'Nothing to see here' }, }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); expect(mockGitlabClient.Commits.create).toHaveBeenCalledWith( @@ -528,14 +458,7 @@ describe('createGitLabMergeRequest', () => { }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); expect(mockGitlabClient.Commits.create).toHaveBeenCalledWith( @@ -570,14 +493,7 @@ describe('createGitLabMergeRequest', () => { }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); expect(mockGitlabClient.Commits.create).toHaveBeenCalledWith( @@ -612,14 +528,7 @@ describe('createGitLabMergeRequest', () => { }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); expect(mockGitlabClient.Commits.create).toHaveBeenCalledWith( @@ -657,14 +566,7 @@ describe('createGitLabMergeRequest', () => { }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); @@ -702,14 +604,7 @@ describe('createGitLabMergeRequest', () => { }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); @@ -739,14 +634,7 @@ describe('createGitLabMergeRequest', () => { commitAction: 'create', }; - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await expect(instance.handler(ctx)).rejects.toThrow( 'Relative path is not allowed to refer to a directory outside its parent', diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabRepoPush.test.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabRepoPush.test.ts index 840f506540..569d3c0c56 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabRepoPush.test.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabRepoPush.test.ts @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createRootLogger, getRootLogger } from '@backstage/backend-common'; +import { createRootLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; -import { Writable } from 'stream'; import { createMockDirectory } from '@backstage/backend-test-utils'; import { createGitlabRepoPushAction } from './gitlabRepoPush'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; // Make sure root logger is initialized ahead of FS mock createRootLogger(); @@ -93,14 +93,7 @@ describe('createGitLabCommit', () => { 'foo.txt': 'Hello there!', }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); expect(mockGitlabClient.Branches.create).toHaveBeenCalledTimes(0); @@ -139,14 +132,7 @@ describe('createGitLabCommit', () => { }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); expect(mockGitlabClient.Branches.create).toHaveBeenCalledTimes(0); @@ -183,14 +169,7 @@ describe('createGitLabCommit', () => { }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); expect(mockGitlabClient.Branches.create).toHaveBeenCalledTimes(0); @@ -227,14 +206,7 @@ describe('createGitLabCommit', () => { }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); expect(mockGitlabClient.Branches.create).toHaveBeenCalledTimes(0); @@ -276,14 +248,7 @@ describe('createGitLabCommit', () => { }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); @@ -325,14 +290,7 @@ describe('createGitLabCommit', () => { }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); @@ -366,14 +324,7 @@ describe('createGitLabCommit', () => { commitAction: 'create', }; - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await expect(instance.handler(ctx)).rejects.toThrow( 'Relative path is not allowed to refer to a directory outside its parent', @@ -398,14 +349,7 @@ describe('createGitLabCommit', () => { 'foo.txt': 'Hello there!', }, }); - const ctx = { - createTemporaryDirectory: jest.fn(), - output: jest.fn(), - logger: getRootLogger(), - logStream: new Writable(), - input, - workspacePath, - }; + const ctx = createMockActionContext({ input, workspacePath }); await instance.handler(ctx); expect(mockGitlabClient.Branches.create).toHaveBeenCalledWith( diff --git a/plugins/scaffolder-backend-module-rails/CHANGELOG.md b/plugins/scaffolder-backend-module-rails/CHANGELOG.md index ad651f0e3a..582aeb8be6 100644 --- a/plugins/scaffolder-backend-module-rails/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-rails/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-scaffolder-backend-module-rails +## 0.4.30-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/types@1.1.1 + ## 0.4.27 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index f67f3fbb22..7e462fc4d4 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.27", + "version": "0.4.30-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -51,6 +51,7 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^", "@types/command-exists": "^1.2.0", "@types/fs-extra": "^11.0.0", "@types/node": "^18.17.8", diff --git a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts index 7548ddd21d..b43ffcc95c 100644 --- a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts +++ b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts @@ -27,18 +27,14 @@ jest.mock('./railsNewRunner', () => { }; }); -import { - ContainerRunner, - getVoidLogger, - UrlReader, -} from '@backstage/backend-common'; +import { ContainerRunner, UrlReader } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; import { resolve as resolvePath } from 'path'; -import { PassThrough } from 'stream'; import { createFetchRailsAction } from './index'; import { fetchContents } from '@backstage/plugin-scaffolder-node'; import { createMockDirectory } from '@backstage/backend-test-utils'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; describe('fetch:rails', () => { const mockDir = createMockDirectory(); @@ -53,8 +49,7 @@ describe('fetch:rails', () => { }), ); - const mockTmpDir = mockDir.path; - const mockContext = { + const mockContext = createMockActionContext({ input: { url: 'https://rubyonrails.org/generator', targetPath: 'something', @@ -66,12 +61,8 @@ describe('fetch:rails', () => { baseUrl: 'somebase', entityRef: 'template:default/myTemplate', }, - workspacePath: mockTmpDir, - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), - }; + workspacePath: mockDir.path, + }); const mockReader: UrlReader = { readUrl: jest.fn(), @@ -102,7 +93,7 @@ describe('fetch:rails', () => { expect(fetchContents).toHaveBeenCalledWith({ reader: mockReader, integrations, - baseUrl: mockContext.templateInfo.baseUrl, + baseUrl: mockContext.templateInfo?.baseUrl, fetchUrl: mockContext.input.url, outputPath: resolvePath(mockContext.workspacePath), }); @@ -112,7 +103,7 @@ describe('fetch:rails', () => { await action.handler(mockContext); expect(mockRailsTemplater.run).toHaveBeenCalledWith({ - workspacePath: mockTmpDir, + workspacePath: mockContext.workspacePath, logStream: mockContext.logStream, values: mockContext.input.values, }); @@ -128,7 +119,7 @@ describe('fetch:rails', () => { }); expect(mockRailsTemplater.run).toHaveBeenCalledWith({ - workspacePath: mockTmpDir, + workspacePath: mockContext.workspacePath, logStream: mockContext.logStream, values: { ...mockContext.input.values, diff --git a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md index 09aa5f087d..b7a3182d30 100644 --- a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-scaffolder-backend-module-sentry +## 0.1.21-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.1.18 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-sentry/package.json b/plugins/scaffolder-backend-module-sentry/package.json index f1aab87354..0a4bec24b9 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.18", + "version": "0.1.21-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -46,6 +46,7 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^", "@backstage/types": "workspace:^", "msw": "^2.0.0" }, diff --git a/plugins/scaffolder-backend-module-sentry/src/actions/createProject.test.ts b/plugins/scaffolder-backend-module-sentry/src/actions/createProject.test.ts index 972b0f1e8e..158b7db4ae 100644 --- a/plugins/scaffolder-backend-module-sentry/src/actions/createProject.test.ts +++ b/plugins/scaffolder-backend-module-sentry/src/actions/createProject.test.ts @@ -15,6 +15,7 @@ */ import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { ConfigReader } from '@backstage/config'; import { InputError } from '@backstage/errors'; import { ActionContext } from '@backstage/plugin-scaffolder-node'; @@ -42,19 +43,17 @@ describe('sentry:project:create action', () => { name: string; slug?: string; authToken?: string; - }> => ({ - workspacePath: './dev/proj', - createTemporaryDirectory: jest.fn(), - logger: jest.createMockFromModule('winston'), - logStream: jest.createMockFromModule('stream'), - input: { - organizationSlug: 'org', - teamSlug: 'team', - name: 'test project', - authToken: randomBytes(5).toString('hex'), - }, - output: jest.fn(), - }); + }> => + createMockActionContext({ + workspacePath: './dev/proj', + logger: jest.createMockFromModule('winston'), + input: { + organizationSlug: 'org', + teamSlug: 'team', + name: 'test project', + authToken: randomBytes(5).toString('hex'), + }, + }); it('should request sentry project create with specified parameters.', async () => { expect.assertions(3); diff --git a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md index 083a3d9149..880a83db86 100644 --- a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-scaffolder-backend-module-yeoman +## 0.2.34-next.0 + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-scaffolder-node-test-utils@0.1.0-next.0 + - @backstage/types@1.1.1 + ## 0.2.31 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index 2ea82dd5d2..508bc83ac3 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.31", + "version": "0.2.34-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -39,6 +39,7 @@ "dependencies": { "@backstage/backend-plugin-api": "workspace:^", "@backstage/plugin-scaffolder-node": "workspace:^", + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^", "@backstage/types": "workspace:^", "winston": "^3.2.1", "yeoman-environment": "^3.9.1" diff --git a/plugins/scaffolder-backend-module-yeoman/src/actions/run/yeoman.test.ts b/plugins/scaffolder-backend-module-yeoman/src/actions/run/yeoman.test.ts index 146c29f4ac..52bd95a3f9 100644 --- a/plugins/scaffolder-backend-module-yeoman/src/actions/run/yeoman.test.ts +++ b/plugins/scaffolder-backend-module-yeoman/src/actions/run/yeoman.test.ts @@ -18,9 +18,8 @@ import { yeomanRun } from './yeomanRun'; jest.mock('./yeomanRun'); -import { getVoidLogger } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import os from 'os'; -import { PassThrough } from 'stream'; import { createRunYeomanAction } from './yeoman'; import type { ActionContext } from '@backstage/plugin-scaffolder-node'; import { JsonObject } from '@backstage/types'; @@ -46,18 +45,14 @@ describe('run:yeoman', () => { const options = { code: 'owner', }; - mockContext = { + mockContext = createMockActionContext({ input: { namespace, args, options, }, workspacePath: mockTmpDir, - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), - }; + }); await action.handler(mockContext); expect(yeomanRun).toHaveBeenCalledWith( diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index b5786cab14..02ab750500 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-scaffolder-backend +## 1.22.0-next.0 + +### Minor Changes + +- c6b132e: Introducing checkpoints for scaffolder task action idempotency + +### Patch Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.3-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.3-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket@0.2.3-next.0 + - @backstage/plugin-scaffolder-backend-module-gerrit@0.1.5-next.0 + - @backstage/plugin-scaffolder-backend-module-github@0.2.3-next.0 + - @backstage/plugin-scaffolder-backend-module-gitlab@0.2.16-next.0 + - @backstage/plugin-scaffolder-backend-module-azure@0.1.5-next.0 + - @backstage/plugin-scaffolder-backend-module-gitea@0.1.3-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.10-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.5.1-next.0 + ## 1.21.0 ### Minor Changes diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 81e5ffb9f9..f9a810ebea 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -21,6 +21,7 @@ import * as gitlab from '@backstage/plugin-scaffolder-backend-module-gitlab'; import { HumanDuration } from '@backstage/types'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { JsonObject } from '@backstage/types'; +import { JsonValue } from '@backstage/types'; import { Knex } from 'knex'; import { LifecycleService } from '@backstage/backend-plugin-api'; import { Logger } from 'winston'; @@ -359,6 +360,7 @@ export interface CurrentClaimedTask { createdBy?: string; secrets?: TaskSecrets_2; spec: TaskSpec; + state?: JsonObject; taskId: string; } @@ -397,6 +399,13 @@ export class DatabaseTaskStore implements TaskStore { // (undocumented) getTask(taskId: string): Promise; // (undocumented) + getTaskState({ taskId }: { taskId: string }): Promise< + | { + state: JsonObject; + } + | undefined + >; + // (undocumented) heartbeatTask(taskId: string): Promise; // (undocumented) list(options: { createdBy?: string }): Promise<{ @@ -418,6 +427,8 @@ export class DatabaseTaskStore implements TaskStore { ids: string[]; }>; // (undocumented) + saveTaskState(options: { taskId: string; state?: JsonObject }): Promise; + // (undocumented) shutdownTask(options: TaskStoreShutDownTaskOptions): Promise; } @@ -519,11 +530,32 @@ export class TaskManager implements TaskContext_2 { // (undocumented) emitLog(message: string, logMetadata?: JsonObject): Promise; // (undocumented) + getTaskState?(): Promise< + | { + state?: JsonObject; + } + | undefined + >; + // (undocumented) getWorkspaceName(): Promise; // (undocumented) get secrets(): TaskSecrets_2 | undefined; // (undocumented) get spec(): TaskSpecV1beta3; + // (undocumented) + updateCheckpoint?( + options: + | { + key: string; + status: 'success'; + value: JsonValue; + } + | { + key: string; + status: 'failed'; + reason: string; + }, + ): Promise; } // @public @deprecated (undocumented) @@ -553,6 +585,13 @@ export interface TaskStore { // (undocumented) getTask(taskId: string): Promise; // (undocumented) + getTaskState?({ taskId }: { taskId: string }): Promise< + | { + state: JsonObject; + } + | undefined + >; + // (undocumented) heartbeatTask(taskId: string): Promise; // (undocumented) list?(options: { createdBy?: string }): Promise<{ @@ -573,6 +612,11 @@ export interface TaskStore { ids: string[]; }>; // (undocumented) + saveTaskState?(options: { + taskId: string; + state?: JsonObject; + }): Promise; + // (undocumented) shutdownTask?(options: TaskStoreShutDownTaskOptions): Promise; } diff --git a/plugins/scaffolder-backend/migrations/20240203232000_state.js b/plugins/scaffolder-backend/migrations/20240203232000_state.js new file mode 100644 index 0000000000..9ffea1716e --- /dev/null +++ b/plugins/scaffolder-backend/migrations/20240203232000_state.js @@ -0,0 +1,35 @@ +/* + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + await knex.schema.alterTable('tasks', table => { + table.text('state').nullable().comment('A state of the checkpoints'); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.alterTable('tasks', table => { + table.dropColumn('state'); + }); +}; diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 4fec5bdfaf..80db4c1c75 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.21.0", + "version": "1.22.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -95,6 +95,7 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^", "@types/fs-extra": "^11.0.0", "@types/nunjucks": "^3.1.4", "@types/supertest": "^2.0.8", diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.examples.test.ts index 161ff9d1de..a368144784 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.examples.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.examples.test.ts @@ -14,9 +14,7 @@ * limitations under the License. */ -import { PassThrough } from 'stream'; -import os from 'os'; -import { getVoidLogger } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { CatalogApi } from '@backstage/catalog-client'; import { Entity } from '@backstage/catalog-model'; import { createFetchCatalogEntityAction } from './fetch'; @@ -36,14 +34,9 @@ describe('catalog:fetch examples', () => { catalogClient: catalogClient as unknown as CatalogApi, }); - const mockContext = { - workspacePath: os.tmpdir(), - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), + const mockContext = createMockActionContext({ secrets: { backstageToken: 'secret' }, - }; + }); beforeEach(() => { jest.resetAllMocks(); }); 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 bed15f2e39..d3fd398a90 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 @@ -14,9 +14,7 @@ * limitations under the License. */ -import { PassThrough } from 'stream'; -import os from 'os'; -import { getVoidLogger } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { CatalogApi } from '@backstage/catalog-client'; import { Entity } from '@backstage/catalog-model'; import { createFetchCatalogEntityAction } from './fetch'; @@ -34,14 +32,10 @@ describe('catalog:fetch', () => { catalogClient: catalogClient as unknown as CatalogApi, }); - const mockContext = { - workspacePath: os.tmpdir(), - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), + const mockContext = createMockActionContext({ secrets: { backstageToken: 'secret' }, - }; + }); + beforeEach(() => { jest.resetAllMocks(); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.examples.test.ts index eb5aa88c0f..db3d7151d8 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.examples.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.examples.test.ts @@ -14,9 +14,7 @@ * limitations under the License. */ -import { PassThrough } from 'stream'; -import os from 'os'; -import { getVoidLogger } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { CatalogApi } from '@backstage/catalog-client'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; @@ -44,13 +42,7 @@ describe('catalog:register', () => { catalogClient: catalogClient as unknown as CatalogApi, }); - const mockContext = { - workspacePath: os.tmpdir(), - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const mockContext = createMockActionContext(); beforeEach(() => { jest.resetAllMocks(); }); 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 bae9f04575..8f6219b64c 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 @@ -14,9 +14,7 @@ * limitations under the License. */ -import { PassThrough } from 'stream'; -import os from 'os'; -import { getVoidLogger } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { CatalogApi } from '@backstage/catalog-client'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; @@ -42,13 +40,8 @@ describe('catalog:register', () => { catalogClient: catalogClient as unknown as CatalogApi, }); - const mockContext = { - workspacePath: os.tmpdir(), - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const mockContext = createMockActionContext(); + beforeEach(() => { jest.resetAllMocks(); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/write.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/write.examples.test.ts index daa8f4f6b1..e6b4bcde47 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/write.examples.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/write.examples.test.ts @@ -20,24 +20,16 @@ jest.mock('fs-extra'); const fsMock = fs as jest.Mocked; -import { PassThrough } from 'stream'; -import os from 'os'; -import { getVoidLogger } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { createCatalogWriteAction } from './write'; import { resolve as resolvePath } from 'path'; import * as yaml from 'yaml'; import { examples } from './write.examples'; +import os from 'os'; describe('catalog:write', () => { const action = createCatalogWriteAction(); - - const mockContext = { - workspacePath: os.tmpdir(), - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const mockContext = createMockActionContext({ workspacePath: os.tmpdir() }); beforeEach(() => { jest.resetAllMocks(); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/write.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/write.test.ts index dd6f29f99b..cc22b75da2 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/write.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/write.test.ts @@ -20,9 +20,8 @@ jest.mock('fs-extra'); const fsMock = fs as jest.Mocked; -import { PassThrough } from 'stream'; import os from 'os'; -import { getVoidLogger } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { ANNOTATION_ORIGIN_LOCATION } from '@backstage/catalog-model'; import { createCatalogWriteAction } from './write'; import { resolve as resolvePath } from 'path'; @@ -31,18 +30,14 @@ import * as yaml from 'yaml'; describe('catalog:write', () => { const action = createCatalogWriteAction(); - const mockContext = { - workspacePath: os.tmpdir(), - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; - beforeEach(() => { jest.resetAllMocks(); }); + const mockContext = createMockActionContext({ + workspacePath: os.tmpdir(), + }); + it('should write the catalog-info.yml in the workspace', async () => { const entity = { apiVersion: 'backstage.io/v1alpha1', diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.examples.test.ts index 901f3e5011..06addba98d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.examples.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.examples.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { Writable } from 'stream'; import { createDebugLogAction } from './log'; import { join } from 'path'; @@ -30,15 +30,10 @@ describe('debug:log examples', () => { const mockDir = createMockDirectory(); const workspacePath = mockDir.resolve('workspace'); - const mockContext = { - input: {}, - baseUrl: 'somebase', - workspacePath, - logger: getVoidLogger(), + const mockContext = createMockActionContext({ logStream, - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + workspacePath, + }); const action = createDebugLogAction(); @@ -51,12 +46,10 @@ describe('debug:log examples', () => { }); it('should log message', async () => { - const context = { + await action.handler({ ...mockContext, input: yaml.parse(examples[0].example).steps[0].input, - }; - - await action.handler(context); + }); expect(logStream.write).toHaveBeenCalledTimes(1); expect(logStream.write).toHaveBeenCalledWith( @@ -65,12 +58,10 @@ describe('debug:log examples', () => { }); it('should log the workspace content, if active', async () => { - const context = { + await action.handler({ ...mockContext, input: yaml.parse(examples[1].example).steps[0].input, - }; - - await action.handler(context); + }); expect(logStream.write).toHaveBeenCalledTimes(1); expect(logStream.write).toHaveBeenCalledWith( diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.test.ts index d6fc5174b3..09c090582a 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { Writable } from 'stream'; import { createDebugLogAction } from './log'; import { join } from 'path'; @@ -29,15 +29,7 @@ describe('debug:log', () => { const mockDir = createMockDirectory(); const workspacePath = mockDir.resolve('workspace'); - const mockContext = { - input: {}, - baseUrl: 'somebase', - workspacePath, - logger: getVoidLogger(), - logStream, - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const mockContext = createMockActionContext({ workspacePath, logStream }); const action = createDebugLogAction(); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.examples.test.ts index 9b755d86dd..8bc29a74c9 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.examples.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.examples.test.ts @@ -14,12 +14,11 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; import { createWaitAction } from './wait'; import { Writable } from 'stream'; import { examples } from './wait.examples'; import yaml from 'yaml'; -import { createMockDirectory } from '@backstage/backend-test-utils'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; describe('debug:wait examples', () => { const action = createWaitAction(); @@ -28,18 +27,9 @@ describe('debug:wait examples', () => { write: jest.fn(), } as jest.Mocked> as jest.Mocked; - const mockDir = createMockDirectory(); - const workspacePath = mockDir.resolve('workspace'); - - const mockContext = { - input: {}, - baseUrl: 'somebase', - workspacePath, - logger: getVoidLogger(), + const mockContext = createMockActionContext({ logStream, - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { jest.resetAllMocks(); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.test.ts index 6f80604a6d..0dcbd10f0f 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.test.ts @@ -14,10 +14,9 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; import { createWaitAction } from './wait'; import { Writable } from 'stream'; -import { createMockDirectory } from '@backstage/backend-test-utils'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; describe('debug:wait', () => { const action = createWaitAction(); @@ -26,18 +25,9 @@ describe('debug:wait', () => { write: jest.fn(), } as jest.Mocked> as jest.Mocked; - const mockDir = createMockDirectory(); - const workspacePath = mockDir.resolve('workspace'); - - const mockContext = { - input: {}, - baseUrl: 'somebase', - workspacePath, - logger: getVoidLogger(), + const mockContext = createMockActionContext({ logStream, - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { jest.resetAllMocks(); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.examples.test.ts index 6b308a97eb..82a32fcbac 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.examples.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.examples.test.ts @@ -16,14 +16,13 @@ import yaml from 'yaml'; -import os from 'os'; import { resolve as resolvePath } from 'path'; -import { getVoidLogger, UrlReader } from '@backstage/backend-common'; +import { UrlReader } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; import { createFetchPlainAction } from './plain'; -import { PassThrough } from 'stream'; import { fetchContents } from '@backstage/plugin-scaffolder-node'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { examples } from './plain.examples'; jest.mock('@backstage/plugin-scaffolder-node', () => ({ @@ -50,19 +49,15 @@ describe('fetch:plain examples', () => { }); const action = createFetchPlainAction({ integrations, reader }); - const mockContext = { - workspacePath: os.tmpdir(), - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const mockContext = createMockActionContext(); it('should fetch plain', async () => { - await action.handler({ - ...mockContext, - input: yaml.parse(examples[0].example).steps[0].input, - }); + await action.handler( + createMockActionContext({ + ...mockContext, + input: yaml.parse(examples[0].example).steps[0].input, + }), + ); expect(fetchContents).toHaveBeenCalledWith( expect.objectContaining({ outputPath: resolvePath(mockContext.workspacePath), diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.test.ts index 917624acf4..bc20fafe19 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.test.ts @@ -19,14 +19,13 @@ jest.mock('@backstage/plugin-scaffolder-node', () => { return { ...actual, fetchContents: jest.fn() }; }); -import os from 'os'; import { resolve as resolvePath } from 'path'; -import { getVoidLogger, UrlReader } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; +import { UrlReader } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; import { fetchContents } from '@backstage/plugin-scaffolder-node'; import { createFetchPlainAction } from './plain'; -import { PassThrough } from 'stream'; describe('fetch:plain', () => { const integrations = ScmIntegrations.fromConfig( @@ -47,13 +46,7 @@ describe('fetch:plain', () => { }); const action = createFetchPlainAction({ integrations, reader }); - const mockContext = { - workspacePath: os.tmpdir(), - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const mockContext = createMockActionContext(); it('should disallow a target path outside working directory', async () => { await expect( diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plainFile.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plainFile.examples.test.ts index 2ee17c29fe..9978d6d8f5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plainFile.examples.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plainFile.examples.test.ts @@ -14,19 +14,19 @@ * limitations under the License. */ +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; + jest.mock('@backstage/plugin-scaffolder-node', () => { const actual = jest.requireActual('@backstage/plugin-scaffolder-node'); return { ...actual, fetchFile: jest.fn() }; }); import yaml from 'yaml'; -import os from 'os'; import { resolve as resolvePath } from 'path'; -import { getVoidLogger, UrlReader } from '@backstage/backend-common'; +import { UrlReader } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; import { createFetchPlainFileAction } from './plainFile'; -import { PassThrough } from 'stream'; import { fetchFile } from '@backstage/plugin-scaffolder-node'; import { examples } from './plainFile.examples'; @@ -49,13 +49,7 @@ describe('fetch:plain:file examples', () => { }); const action = createFetchPlainFileAction({ integrations, reader }); - const mockContext = { - workspacePath: os.tmpdir(), - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const mockContext = createMockActionContext(); it('should fetch plain', async () => { await action.handler({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plainFile.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plainFile.test.ts index 7ea74a809b..bf40c7ad0e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plainFile.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plainFile.test.ts @@ -19,14 +19,13 @@ jest.mock('@backstage/plugin-scaffolder-node', () => { return { ...actual, fetchFile: jest.fn() }; }); -import os from 'os'; import { resolve as resolvePath } from 'path'; -import { getVoidLogger, UrlReader } from '@backstage/backend-common'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; +import { UrlReader } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; import { fetchFile } from '@backstage/plugin-scaffolder-node'; import { createFetchPlainFileAction } from './plainFile'; -import { PassThrough } from 'stream'; describe('fetch:plain:file', () => { const integrations = ScmIntegrations.fromConfig( @@ -47,13 +46,7 @@ describe('fetch:plain:file', () => { }); const action = createFetchPlainFileAction({ integrations, reader }); - const mockContext = { - workspacePath: os.tmpdir(), - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + const mockContext = createMockActionContext(); it('should disallow a target path outside working directory', async () => { await expect( diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.examples.test.ts index a1c8381178..36f1f00b50 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.examples.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.examples.test.ts @@ -16,13 +16,9 @@ import { join as joinPath, sep as pathSep } from 'path'; import fs from 'fs-extra'; -import { - getVoidLogger, - resolvePackagePath, - UrlReader, -} from '@backstage/backend-common'; +import { resolvePackagePath, UrlReader } from '@backstage/backend-common'; import { ScmIntegrations } from '@backstage/integration'; -import { PassThrough } from 'stream'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { createFetchTemplateAction } from './template'; import { ActionContext, @@ -61,23 +57,15 @@ describe('fetch:template examples', () => { const mockDir = createMockDirectory(); const workspacePath = mockDir.resolve('workspace'); - const logger = getVoidLogger(); - - const mockContext = (input: any) => ({ - templateInfo: { - baseUrl: 'base-url', - entityRef: 'template:default/test-template', - }, - input: input, - output: jest.fn(), - logStream: new PassThrough(), - logger, - workspacePath, - - async createTemporaryDirectory() { - return fs.mkdtemp(mockDir.resolve('tmp-')); - }, - }); + const mockContext = (input: any) => + createMockActionContext({ + templateInfo: { + baseUrl: 'base-url', + entityRef: 'template:default/test-template', + }, + input, + workspacePath, + }); beforeEach(() => { mockDir.clear(); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts index 25b65462e6..fd0ef7d757 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts @@ -21,13 +21,8 @@ jest.mock('@backstage/plugin-scaffolder-node', () => { import { join as joinPath, sep as pathSep } from 'path'; import fs from 'fs-extra'; -import { - getVoidLogger, - resolvePackagePath, - UrlReader, -} from '@backstage/backend-common'; +import { resolvePackagePath, UrlReader } from '@backstage/backend-common'; import { ScmIntegrations } from '@backstage/integration'; -import { PassThrough } from 'stream'; import { createFetchTemplateAction } from './template'; import { fetchContents, @@ -35,6 +30,7 @@ import { TemplateAction, } from '@backstage/plugin-scaffolder-node'; import { createMockDirectory } from '@backstage/backend-test-utils'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; type FetchTemplateInput = ReturnType< typeof createFetchTemplateAction @@ -59,29 +55,22 @@ describe('fetch:template', () => { const mockDir = createMockDirectory(); const workspacePath = mockDir.resolve('workspace'); - const logger = getVoidLogger(); - - const mockContext = (inputPatch: Partial = {}) => ({ - templateInfo: { - baseUrl: 'base-url', - entityRef: 'template:default/test-template', - }, - input: { - url: './skeleton', - targetPath: './target', - values: { - test: 'value', + const mockContext = (inputPatch: Partial = {}) => + createMockActionContext({ + templateInfo: { + baseUrl: 'base-url', + entityRef: 'template:default/test-template', }, - ...inputPatch, - }, - output: jest.fn(), - logStream: new PassThrough(), - logger, - workspacePath, - async createTemporaryDirectory() { - return fs.mkdtemp(mockDir.resolve('tmp-')); - }, - }); + input: { + url: './skeleton', + targetPath: './target', + values: { + test: 'value', + }, + ...inputPatch, + }, + workspacePath, + }); beforeEach(() => { mockDir.setContent({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.examples.test.ts index 023f049ebc..d11b1e4087 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.examples.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.examples.test.ts @@ -15,8 +15,7 @@ */ import { createFilesystemDeleteAction } from './delete'; -import { getVoidLogger } from '@backstage/backend-common'; -import { PassThrough } from 'stream'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { resolve as resolvePath } from 'path'; import fs from 'fs-extra'; import yaml from 'yaml'; @@ -31,16 +30,12 @@ describe('fs:delete examples', () => { const files: string[] = yaml.parse(examples[0].example).steps[0].input.files; - const mockContext = { + const mockContext = createMockActionContext({ input: { files: files, }, workspacePath, - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { jest.restoreAllMocks(); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts index 2a4f45b862..8226133376 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts @@ -16,8 +16,7 @@ import { resolve as resolvePath } from 'path'; import { createFilesystemDeleteAction } from './delete'; -import { getVoidLogger } from '@backstage/backend-common'; -import { PassThrough } from 'stream'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import fs from 'fs-extra'; import { createMockDirectory } from '@backstage/backend-test-utils'; @@ -27,16 +26,12 @@ describe('fs:delete', () => { const mockDir = createMockDirectory(); const workspacePath = resolvePath(mockDir.path, 'workspace'); - const mockContext = { + const mockContext = createMockActionContext({ input: { files: ['unit-test-a.js', 'unit-test-b.js'], }, workspacePath, - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { jest.restoreAllMocks(); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.test.ts index cbb0fa0d0b..0881bb8260 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.test.ts @@ -16,8 +16,7 @@ import { resolve as resolvePath } from 'path'; import { createFilesystemRenameAction } from './rename'; -import { getVoidLogger } from '@backstage/backend-common'; -import { PassThrough } from 'stream'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import fs from 'fs-extra'; import yaml from 'yaml'; import { examples } from './rename.examples'; @@ -31,16 +30,12 @@ describe('fs:rename examples', () => { const mockDir = createMockDirectory(); const workspacePath = resolvePath(mockDir.path, 'workspace'); - const mockContext = { + const mockContext = createMockActionContext({ input: { - files: files, + files, }, workspacePath, - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { jest.restoreAllMocks(); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts index d37e967f43..6696fda693 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts @@ -16,8 +16,7 @@ import { resolve as resolvePath } from 'path'; import { createFilesystemRenameAction } from './rename'; -import { getVoidLogger } from '@backstage/backend-common'; -import { PassThrough } from 'stream'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import fs from 'fs-extra'; import { createMockDirectory } from '@backstage/backend-test-utils'; @@ -41,16 +40,12 @@ describe('fs:rename', () => { to: 'brand-new-folder', }, ]; - const mockContext = { + const mockContext = createMockActionContext({ input: { files: mockInputFiles, }, workspacePath, - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn(), - }; + }); beforeEach(() => { jest.restoreAllMocks(); diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.test.ts index 4c0eb94c82..fe9cf3c661 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.test.ts @@ -188,4 +188,37 @@ describe('DatabaseTaskStore', () => { await store.shutdownTask({ taskId }); }).rejects.toThrow(ConflictError); }); + + it('should store checkpoints and retrieve task state', async () => { + const { store } = await createStore(); + const { taskId } = await store.createTask({ + spec: {} as TaskSpec, + createdBy: 'me', + }); + + await store.saveTaskState({ + taskId, + state: { + checkpoints: { + 'repo.create': { + status: 'success', + value: { repoUrl: 'https://github.com/backstage/backstage.git' }, + }, + }, + }, + }); + + const state = await store.getTaskState({ taskId }); + + expect(state).toStrictEqual({ + state: { + checkpoints: { + 'repo.create': { + status: 'success', + value: { repoUrl: 'https://github.com/backstage/backstage.git' }, + }, + }, + }, + }); + }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts index 766db4646e..2a39440775 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts @@ -52,6 +52,7 @@ export type RawDbTaskRow = { id: string; spec: string; status: TaskStatus; + state?: string; last_heartbeat_at?: string; created_at: string; created_by: string | null; @@ -394,6 +395,32 @@ export class DatabaseTaskStore implements TaskStore { }); } + async getTaskState({ taskId }: { taskId: string }): Promise< + | { + state: JsonObject; + } + | undefined + > { + const [result] = await this.db('tasks') + .where({ id: taskId }) + .select('state'); + return result.state ? JSON.parse(result.state) : undefined; + } + + async saveTaskState(options: { + taskId: string; + state?: JsonObject; + }): Promise { + if (options.state) { + const serializedState = JSON.stringify({ state: options.state }); + await this.db('tasks') + .where({ id: options.taskId }) + .update({ + state: serializedState, + }); + } + } + async listEvents( options: TaskStoreListEventsOptions, ): Promise<{ events: SerializedTaskEvent[] }> { diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts index cf29d43e19..420ec69427 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts @@ -18,6 +18,7 @@ import { getVoidLogger } from '@backstage/backend-common'; import { NunjucksWorkflowRunner } from './NunjucksWorkflowRunner'; import { TemplateActionRegistry } from '../actions'; import { ScmIntegrations } from '@backstage/integration'; +import { JsonObject } from '@backstage/types'; import { ConfigReader } from '@backstage/config'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { @@ -133,6 +134,26 @@ describe('NunjucksWorkflowRunner', () => { }, }); + actionRegistry.register({ + id: 'checkpoints-action', + description: 'Mock action with checkpoints', + handler: async ctx => { + const key1 = await ctx.checkpoint?.('key1', async () => { + return 'updated'; + }); + const key2 = await ctx.checkpoint?.('key2', async () => { + return 'updated'; + }); + const key3 = await ctx.checkpoint?.('key3', async () => { + return 'updated'; + }); + + ctx.output('key1', key1); + ctx.output('key2', key2); + ctx.output('key3', key3); + }, + }); + mockedPermissionApi.authorizeConditional.mockResolvedValue([ { result: AuthorizeResult.ALLOW }, ]); @@ -538,6 +559,54 @@ describe('NunjucksWorkflowRunner', () => { ); }); + it('should deal with checkpoints', async () => { + const task = { + ...createMockTaskWithSpec({ + apiVersion: 'scaffolder.backstage.io/v1beta3', + parameters: {}, + steps: [ + { + id: 'test', + name: 'name', + action: 'checkpoints-action', + input: { foo: 1 }, + }, + ], + output: { + key1: '${{steps.test.output.key1}}', + key2: '${{steps.test.output.key2}}', + key3: '${{steps.test.output.key3}}', + }, + }), + getTaskState: (): Promise< + | { + state: JsonObject; + } + | undefined + > => { + return Promise.resolve({ + state: { + checkpoints: { + ['v1.task.checkpoint.key1']: { + status: 'success', + value: 'initial', + }, + ['v1.task.checkpoint.key2']: { + status: 'failed', + reason: 'fatal error', + }, + }, + }, + }); + }, + }; + const result = await runner.execute(task); + + expect(result.output.key1).toEqual('initial'); + expect(result.output.key2).toEqual('updated'); + expect(result.output.key3).toEqual('updated'); + }); + it('should template the output from simple actions', async () => { const task = createMockTaskWithSpec({ apiVersion: 'scaffolder.backstage.io/v1beta3', diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index f86cf9019e..574f424fe4 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -21,7 +21,7 @@ import fs from 'fs-extra'; import path from 'path'; import nunjucks from 'nunjucks'; import { JsonArray, JsonObject, JsonValue } from '@backstage/types'; -import { InputError, NotAllowedError } from '@backstage/errors'; +import { InputError, NotAllowedError, stringifyError } from '@backstage/errors'; import { PassThrough } from 'stream'; import { generateExampleOutput, isTruthy } from './helper'; import { validate as validateJsonSchema } from 'jsonschema'; @@ -79,6 +79,16 @@ type TemplateContext = { each?: JsonValue; }; +type CheckpointState = + | { + status: 'failed'; + reason: string; + } + | { + status: 'success'; + value: JsonValue; + }; + const isValidTaskSpec = (taskSpec: TaskSpec): taskSpec is TaskSpecV1beta3 => { return taskSpec.apiVersion === 'scaffolder.backstage.io/v1beta3'; }; @@ -330,6 +340,7 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { } const tmpDirs = new Array(); const stepOutput: { [outputName: string]: JsonValue } = {}; + const prevTaskState = await task.getTaskState?.(); for (const iteration of iterations) { if (iteration.each) { @@ -347,6 +358,43 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { logger: taskLogger, logStream: streamLogger, workspacePath, + async checkpoint( + keySuffix: string, + fn: () => Promise, + ) { + const key = `v1.task.checkpoint.${keySuffix}`; + try { + let prevValue: U | undefined; + if (prevTaskState) { + const prevState = ( + prevTaskState.state?.checkpoints as { + [key: string]: CheckpointState; + } + )?.[key]; + if (prevState && prevState.status === 'success') { + prevValue = prevState.value as U; + } + } + + const value = prevValue ? prevValue : await fn(); + + if (!prevValue) { + task.updateCheckpoint?.({ + key, + status: 'success', + value, + }); + } + return value; + } catch (err) { + task.updateCheckpoint?.({ + key, + status: 'failed', + reason: stringifyError(err), + }); + throw err; + } + }, createTemporaryDirectory: async () => { const tmpDir = await fs.mkdtemp( `${workspacePath}_step-${step.id}-`, diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.test.ts index 3d2fb28538..f4bae43dbf 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.test.ts @@ -242,4 +242,31 @@ describe('StorageTaskBroker', () => { const promise = broker.list({ createdBy: 'user:default/foo' }); await expect(promise).resolves.toEqual({ tasks: [task] }); }); + + it('should handle checkpoints in task state', async () => { + const broker = new StorageTaskBroker(storage, logger); + + await broker.dispatch({ + spec: { steps: [] } as unknown as TaskSpec, + createdBy: 'user:default/foo', + }); + + const taskA = await broker.claim(); + await taskA.updateCheckpoint?.({ + key: 'repo.create', + status: 'success', + value: 'https://github.com/backstage/backstage.git', + }); + + expect(await taskA.getTaskState?.()).toEqual({ + state: { + checkpoints: { + 'repo.create': { + status: 'success', + value: 'https://github.com/backstage/backstage.git', + }, + }, + }, + }); + }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts index 1e557512cb..fec745a653 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts @@ -16,6 +16,9 @@ import { Config } from '@backstage/config'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; +import { JsonObject, JsonValue, Observable } from '@backstage/types'; +import { Logger } from 'winston'; +import ObservableImpl from 'zen-observable'; import { TaskSecrets, SerializedTask, @@ -25,12 +28,22 @@ import { TaskCompletionState, TaskContext, } from '@backstage/plugin-scaffolder-node'; -import { JsonObject, Observable } from '@backstage/types'; -import { Logger } from 'winston'; -import ObservableImpl from 'zen-observable'; import { TaskStore } from './types'; import { readDuration } from './helper'; +type TaskState = { + checkpoints: { + [key: string]: + | { + status: 'failed'; + reason: string; + } + | { + status: 'success'; + value: JsonValue; + }; + }; +}; /** * TaskManager * @@ -91,6 +104,40 @@ export class TaskManager implements TaskContext { }); } + async getTaskState?(): Promise< + | { + state?: JsonObject; + } + | undefined + > { + return this.storage.getTaskState?.({ taskId: this.task.taskId }); + } + + async updateCheckpoint?( + options: + | { + key: string; + status: 'success'; + value: JsonValue; + } + | { + key: string; + status: 'failed'; + reason: string; + }, + ): Promise { + const { key, ...value } = options; + if (this.task.state) { + (this.task.state as TaskState).checkpoints[key] = value; + } else { + this.task.state = { checkpoints: { [key]: value } }; + } + await this.storage.saveTaskState?.({ + taskId: this.task.taskId, + state: this.task.state, + }); + } + async complete( result: TaskCompletionState, metadata?: JsonObject, @@ -144,6 +191,10 @@ export interface CurrentClaimedTask { * The secrets that are stored with the task. */ secrets?: TaskSecrets; + /** + * The state of checkpoints of the task. + */ + state?: JsonObject; /** * The creator of the task. */ diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts index c5783ccb49..c0854af391 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts @@ -194,6 +194,18 @@ export interface TaskStore { emitLogEvent(options: TaskStoreEmitOptions): Promise; + getTaskState?({ taskId }: { taskId: string }): Promise< + | { + state: JsonObject; + } + | undefined + >; + + saveTaskState?(options: { + taskId: string; + state?: JsonObject; + }): Promise; + listEvents( options: TaskStoreListEventsOptions, ): Promise<{ events: SerializedTaskEvent[] }>; diff --git a/plugins/scaffolder-common/CHANGELOG.md b/plugins/scaffolder-common/CHANGELOG.md index 5fcfd731b6..1cbeccbd7e 100644 --- a/plugins/scaffolder-common/CHANGELOG.md +++ b/plugins/scaffolder-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-scaffolder-common +## 1.5.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/types@1.1.1 + ## 1.5.0 ### Minor Changes diff --git a/plugins/scaffolder-common/package.json b/plugins/scaffolder-common/package.json index a72ccfbb82..fe2a049db9 100644 --- a/plugins/scaffolder-common/package.json +++ b/plugins/scaffolder-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-common", - "version": "1.5.0", + "version": "1.5.1-next.0", "description": "Common functionalities for the scaffolder, to be shared between scaffolder and scaffolder-backend plugin", "backstage": { "role": "common-library" diff --git a/plugins/scaffolder-node-test-utils/.eslintrc.js b/plugins/scaffolder-node-test-utils/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/scaffolder-node-test-utils/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/scaffolder-node-test-utils/CHANGELOG.md b/plugins/scaffolder-node-test-utils/CHANGELOG.md new file mode 100644 index 0000000000..ea11cd151f --- /dev/null +++ b/plugins/scaffolder-node-test-utils/CHANGELOG.md @@ -0,0 +1,18 @@ +# @backstage/plugin-scaffolder-node-test-utils + +## 0.1.0-next.0 + +### Minor Changes + +- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. + + It will help to maintain tests in a long run during structural changes of action context. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-test-utils@0.3.3-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-scaffolder-node@0.3.3-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.5.1-next.0 diff --git a/plugins/scaffolder-node-test-utils/README.md b/plugins/scaffolder-node-test-utils/README.md new file mode 100644 index 0000000000..851ddf808d --- /dev/null +++ b/plugins/scaffolder-node-test-utils/README.md @@ -0,0 +1,12 @@ +# @backstage/plugin-scaffolder-node-test-utils + +Contains utilities that can be used when testing scaffolder features. + +## Installation + +Install the package via Yarn into your own packages: + +```sh +cd # if within a monorepo +yarn add --dev @backstage/plugin-scaffolder-node-test-utils +``` diff --git a/plugins/scaffolder-node-test-utils/api-report.md b/plugins/scaffolder-node-test-utils/api-report.md new file mode 100644 index 0000000000..d6cda70b48 --- /dev/null +++ b/plugins/scaffolder-node-test-utils/api-report.md @@ -0,0 +1,18 @@ +## API Report File for "@backstage/plugin-scaffolder-node-test-utils" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { ActionContext } from '@backstage/plugin-scaffolder-node'; +import { JsonObject } from '@backstage/types'; + +// @public +export const createMockActionContext: < + TActionInput extends JsonObject = JsonObject, + TActionOutput extends JsonObject = JsonObject, +>( + options?: Partial> | undefined, +) => ActionContext; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/scaffolder-node-test-utils/catalog-info.yaml b/plugins/scaffolder-node-test-utils/catalog-info.yaml new file mode 100644 index 0000000000..980bd07e34 --- /dev/null +++ b/plugins/scaffolder-node-test-utils/catalog-info.yaml @@ -0,0 +1,9 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-scaffolder-node-test-utils + title: '@backstage/plugin-scaffolder-node-test-utils' +spec: + lifecycle: experimental + type: backstage-node-library + owner: maintainers diff --git a/plugins/scaffolder-node-test-utils/knip-report.md b/plugins/scaffolder-node-test-utils/knip-report.md new file mode 100644 index 0000000000..2661c35327 --- /dev/null +++ b/plugins/scaffolder-node-test-utils/knip-report.md @@ -0,0 +1,2 @@ +# Knip report + diff --git a/plugins/scaffolder-node-test-utils/package.json b/plugins/scaffolder-node-test-utils/package.json new file mode 100644 index 0000000000..19d665bc75 --- /dev/null +++ b/plugins/scaffolder-node-test-utils/package.json @@ -0,0 +1,46 @@ +{ + "name": "@backstage/plugin-scaffolder-node-test-utils", + "version": "0.1.0-next.0", + "backstage": { + "role": "node-library" + }, + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/scaffolder-node-test-utils" + }, + "license": "Apache-2.0", + "sideEffects": false, + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start", + "test": "backstage-cli package test" + }, + "dependencies": { + "@backstage/backend-common": "workspace:^", + "@backstage/backend-test-utils": "workspace:^", + "@backstage/plugin-scaffolder-common": "workspace:^", + "@backstage/plugin-scaffolder-node": "workspace:^", + "@backstage/types": "workspace:^", + "winston": "^3.2.1" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@testing-library/jest-dom": "^6.0.0", + "@types/react": "*" + } +} diff --git a/plugins/scaffolder-node-test-utils/src/actions/index.ts b/plugins/scaffolder-node-test-utils/src/actions/index.ts new file mode 100644 index 0000000000..161bae8521 --- /dev/null +++ b/plugins/scaffolder-node-test-utils/src/actions/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 { createMockActionContext } from './mockActionConext'; diff --git a/plugins/scaffolder-node-test-utils/src/actions/mockActionConext.ts b/plugins/scaffolder-node-test-utils/src/actions/mockActionConext.ts new file mode 100644 index 0000000000..33a40ad02c --- /dev/null +++ b/plugins/scaffolder-node-test-utils/src/actions/mockActionConext.ts @@ -0,0 +1,69 @@ +/* + * 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 { PassThrough } from 'stream'; +import { getVoidLogger } from '@backstage/backend-common'; +import { createMockDirectory } from '@backstage/backend-test-utils'; +import { JsonObject } from '@backstage/types'; +import { ActionContext } from '@backstage/plugin-scaffolder-node'; + +/** + * A utility method to create a mock action context for scaffolder actions. + * + * @public + * @param options - optional parameters to override default mock context + */ +export const createMockActionContext = < + TActionInput extends JsonObject = JsonObject, + TActionOutput extends JsonObject = JsonObject, +>( + options?: Partial>, +): ActionContext => { + const defaultContext = { + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + input: {} as TActionInput, + }; + + const createDefaultWorkspace = () => ({ + workspacePath: createMockDirectory().resolve('workspace'), + }); + + if (!options) { + return { + ...defaultContext, + ...createDefaultWorkspace(), + }; + } + + const { input, logger, logStream, secrets, templateInfo, workspacePath } = + options; + + return { + ...defaultContext, + ...(workspacePath ? { workspacePath } : createDefaultWorkspace()), + ...(workspacePath && { + createTemporaryDirectory: jest.fn().mockResolvedValue(workspacePath), + }), + ...(logger && { logger }), + ...(logStream && { logStream }), + ...(input && { input }), + ...(secrets && { secrets }), + templateInfo, + }; +}; diff --git a/plugins/scaffolder-node-test-utils/src/index.ts b/plugins/scaffolder-node-test-utils/src/index.ts new file mode 100644 index 0000000000..19eae8d569 --- /dev/null +++ b/plugins/scaffolder-node-test-utils/src/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 * from './actions'; diff --git a/plugins/scaffolder-node/CHANGELOG.md b/plugins/scaffolder-node/CHANGELOG.md index 3a5c9cd8b6..950a3cd977 100644 --- a/plugins/scaffolder-node/CHANGELOG.md +++ b/plugins/scaffolder-node/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-scaffolder-node +## 0.3.3-next.0 + +### Patch Changes + +- 85f4723: Fixed file corruption for non UTF-8 data in fetch contents +- c6b132e: Introducing checkpoints for scaffolder task action idempotency +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.5.1-next.0 + ## 0.3.0 ### Minor Changes diff --git a/plugins/scaffolder-node/api-report.md b/plugins/scaffolder-node/api-report.md index fec2205462..76e22c0c5a 100644 --- a/plugins/scaffolder-node/api-report.md +++ b/plugins/scaffolder-node/api-report.md @@ -30,6 +30,10 @@ export type ActionContext< secrets?: TaskSecrets; workspacePath: string; input: TActionInput; + checkpoint?( + key: string, + fn: () => Promise, + ): Promise; output( name: keyof TActionOutput, value: TActionOutput[keyof TActionOutput], @@ -345,6 +349,13 @@ export interface TaskContext { // (undocumented) emitLog(message: string, logMetadata?: JsonObject): Promise; // (undocumented) + getTaskState?(): Promise< + | { + state?: JsonObject; + } + | undefined + >; + // (undocumented) getWorkspaceName(): Promise; // (undocumented) isDryRun?: boolean; @@ -352,6 +363,20 @@ export interface TaskContext { secrets?: TaskSecrets; // (undocumented) spec: TaskSpec; + // (undocumented) + updateCheckpoint?( + options: + | { + key: string; + status: 'success'; + value: JsonValue; + } + | { + key: string; + status: 'failed'; + reason: string; + }, + ): Promise; } // @public diff --git a/plugins/scaffolder-node/package.json b/plugins/scaffolder-node/package.json index 6de7c48782..6bb3d96aa8 100644 --- a/plugins/scaffolder-node/package.json +++ b/plugins/scaffolder-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-node", - "version": "0.3.0", + "version": "0.3.3-next.0", "description": "The plugin-scaffolder-node module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "node-library" diff --git a/plugins/scaffolder-node/src/actions/fetch.test.ts b/plugins/scaffolder-node/src/actions/fetch.test.ts index 42f75d02b4..ea7f458fde 100644 --- a/plugins/scaffolder-node/src/actions/fetch.test.ts +++ b/plugins/scaffolder-node/src/actions/fetch.test.ts @@ -210,7 +210,26 @@ describe('fetchContents helper', () => { fetchUrl: 'https://github.com/backstage/foo', }); expect(fs.ensureDir).toHaveBeenCalledWith('.'); - expect(fs.outputFile).toHaveBeenCalledWith('foo', 'test'); + expect(fs.outputFile).toHaveBeenCalledWith( + 'foo', + Buffer.from([116, 101, 115, 116]), + ); + }); + + it('should fetch binary content from url', async () => { + readUrl.mockResolvedValue({ + buffer: () => Buffer.from([0, 1, 2, 3, 255, 254, 253, 252]), + }); + await fetchFile({ + ...options, + outputPath: 'foo', + fetchUrl: 'https://github.com/backstage/foo', + }); + expect(fs.ensureDir).toHaveBeenCalledWith('.'); + expect(fs.outputFile).toHaveBeenCalledWith( + 'foo', + Buffer.from([0, 1, 2, 3, 255, 254, 253, 252]), + ); }); it('should fetch content from url into directory', async () => { @@ -223,7 +242,10 @@ describe('fetchContents helper', () => { fetchUrl: 'https://github.com/backstage/foo', }); expect(fs.ensureDir).toHaveBeenCalledWith('mydir'); - expect(fs.outputFile).toHaveBeenCalledWith('mydir/foo', 'test'); + expect(fs.outputFile).toHaveBeenCalledWith( + 'mydir/foo', + Buffer.from([116, 101, 115, 116]), + ); }); it('should pass through the token provided through to the URL reader', async () => { diff --git a/plugins/scaffolder-node/src/actions/fetch.ts b/plugins/scaffolder-node/src/actions/fetch.ts index 2ddc2b1ae6..6b3e08bc7e 100644 --- a/plugins/scaffolder-node/src/actions/fetch.ts +++ b/plugins/scaffolder-node/src/actions/fetch.ts @@ -95,7 +95,7 @@ export async function fetchFile(options: { const res = await reader.readUrl(readUrl, { token }); await fs.ensureDir(path.dirname(outputPath)); const buffer = await res.buffer(); - await fs.outputFile(outputPath, buffer.toString()); + await fs.outputFile(outputPath, buffer); } } diff --git a/plugins/scaffolder-node/src/actions/types.ts b/plugins/scaffolder-node/src/actions/types.ts index 7e8c2b4f5f..678d6f87d7 100644 --- a/plugins/scaffolder-node/src/actions/types.ts +++ b/plugins/scaffolder-node/src/actions/types.ts @@ -16,7 +16,7 @@ import { Logger } from 'winston'; import { Writable } from 'stream'; -import { JsonObject } from '@backstage/types'; +import { JsonObject, JsonValue } from '@backstage/types'; import { TaskSecrets } from '../tasks'; import { TemplateInfo } from '@backstage/plugin-scaffolder-common'; import { UserEntity } from '@backstage/catalog-model'; @@ -35,6 +35,10 @@ export type ActionContext< secrets?: TaskSecrets; workspacePath: string; input: TActionInput; + checkpoint?( + key: string, + fn: () => Promise, + ): Promise; output( name: keyof TActionOutput, value: TActionOutput[keyof TActionOutput], diff --git a/plugins/scaffolder-node/src/tasks/types.ts b/plugins/scaffolder-node/src/tasks/types.ts index 7cdc044bdf..e57668e346 100644 --- a/plugins/scaffolder-node/src/tasks/types.ts +++ b/plugins/scaffolder-node/src/tasks/types.ts @@ -15,7 +15,7 @@ */ import { TaskSpec } from '@backstage/plugin-scaffolder-common'; -import { JsonObject, Observable } from '@backstage/types'; +import { JsonObject, JsonValue, Observable } from '@backstage/types'; /** * TaskSecrets @@ -118,6 +118,27 @@ export interface TaskContext { emitLog(message: string, logMetadata?: JsonObject): Promise; + getTaskState?(): Promise< + | { + state?: JsonObject; + } + | undefined + >; + + updateCheckpoint?( + options: + | { + key: string; + status: 'success'; + value: JsonValue; + } + | { + key: string; + status: 'failed'; + reason: string; + }, + ): Promise; + getWorkspaceName(): Promise; } diff --git a/plugins/scaffolder-react/CHANGELOG.md b/plugins/scaffolder-react/CHANGELOG.md index 6d08ec19fe..fc7267dba7 100644 --- a/plugins/scaffolder-react/CHANGELOG.md +++ b/plugins/scaffolder-react/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-scaffolder-react +## 1.8.1-next.0 + +### Patch Changes + +- 930b5c1: Added 'root' and 'label' class key to TemplateCategoryPicker +- 6d649d2: Updated dependency `flatted` to `3.3.1`. +- 0cecb09: Updated dependency `@rjsf/utils` to `5.17.1`. + Updated dependency `@rjsf/core` to `5.17.1`. + Updated dependency `@rjsf/material-ui` to `5.17.1`. + Updated dependency `@rjsf/validator-ajv8` to `5.17.1`. +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-scaffolder-common@1.5.1-next.0 + ## 1.8.0 ### Minor Changes diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index 1fa5b63d92..51203909a0 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.8.0", + "version": "1.8.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index 529aacda8a..055516a22f 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-scaffolder +## 1.18.1-next.0 + +### Patch Changes + +- 0cecb09: Updated dependency `@rjsf/utils` to `5.17.1`. + Updated dependency `@rjsf/core` to `5.17.1`. + Updated dependency `@rjsf/material-ui` to `5.17.1`. + Updated dependency `@rjsf/validator-ajv8` to `5.17.1`. +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-scaffolder-react@1.8.1-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.22-next.0 + - @backstage/plugin-permission-react@0.4.21-next.0 + - @backstage/plugin-scaffolder-common@1.5.1-next.0 + ## 1.18.0 ### Minor Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 18d333aa39..1fe465a84e 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.18.0", + "version": "1.18.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-catalog/CHANGELOG.md b/plugins/search-backend-module-catalog/CHANGELOG.md index 32a58d44a5..c03af4c62f 100644 --- a/plugins/search-backend-module-catalog/CHANGELOG.md +++ b/plugins/search-backend-module-catalog/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-search-backend-module-catalog +## 0.1.17-next.0 + +### Patch Changes + +- bb368a5: Migrated to support new auth services. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + ## 0.1.14 ### Patch Changes diff --git a/plugins/search-backend-module-catalog/api-report.md b/plugins/search-backend-module-catalog/api-report.md index 6f5813ca9e..fc19ede2d4 100644 --- a/plugins/search-backend-module-catalog/api-report.md +++ b/plugins/search-backend-module-catalog/api-report.md @@ -5,6 +5,7 @@ ```ts /// +import { AuthService } from '@backstage/backend-plugin-api'; import { CatalogApi } from '@backstage/catalog-client'; import { CatalogEntityDocument } from '@backstage/plugin-catalog-common'; import { Config } from '@backstage/config'; @@ -41,6 +42,7 @@ export class DefaultCatalogCollatorFactory implements DocumentCollatorFactory { // @public (undocumented) export type DefaultCatalogCollatorFactoryOptions = { + auth?: AuthService; discovery: PluginEndpointDiscovery; tokenManager: TokenManager; locationTemplate?: string; diff --git a/plugins/search-backend-module-catalog/package.json b/plugins/search-backend-module-catalog/package.json index ee14c15b1a..31eed8201d 100644 --- a/plugins/search-backend-module-catalog/package.json +++ b/plugins/search-backend-module-catalog/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-catalog", - "version": "0.1.14", + "version": "0.1.17-next.0", "description": "A module for the search backend that exports catalog modules", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/search-backend-module-catalog/src/collators/DefaultCatalogCollatorFactory.ts b/plugins/search-backend-module-catalog/src/collators/DefaultCatalogCollatorFactory.ts index 586346c385..166985f2d5 100644 --- a/plugins/search-backend-module-catalog/src/collators/DefaultCatalogCollatorFactory.ts +++ b/plugins/search-backend-module-catalog/src/collators/DefaultCatalogCollatorFactory.ts @@ -17,6 +17,7 @@ import { PluginEndpointDiscovery, TokenManager, + createLegacyAuthAdapters, } from '@backstage/backend-common'; import { CatalogApi, @@ -33,9 +34,11 @@ import { Readable } from 'stream'; import { CatalogCollatorEntityTransformer } from './CatalogCollatorEntityTransformer'; import { readCollatorConfigOptions } from './config'; import { defaultCatalogCollatorEntityTransformer } from './defaultCatalogCollatorEntityTransformer'; +import { AuthService } from '@backstage/backend-plugin-api'; /** @public */ export type DefaultCatalogCollatorFactoryOptions = { + auth?: AuthService; discovery: PluginEndpointDiscovery; tokenManager: TokenManager; /** @@ -71,20 +74,26 @@ export class DefaultCatalogCollatorFactory implements DocumentCollatorFactory { private filter?: GetEntitiesRequest['filter']; private batchSize: number; private readonly catalogClient: CatalogApi; - private tokenManager: TokenManager; private entityTransformer: CatalogCollatorEntityTransformer; + private auth: AuthService; static fromConfig( configRoot: Config, options: DefaultCatalogCollatorFactoryOptions, ) { const configOptions = readCollatorConfigOptions(configRoot); + const { auth: adaptedAuth } = createLegacyAuthAdapters({ + auth: options.auth, + discovery: options.discovery, + tokenManager: options.tokenManager, + }); return new DefaultCatalogCollatorFactory({ locationTemplate: options.locationTemplate ?? configOptions.locationTemplate, filter: options.filter ?? configOptions.filter, batchSize: options.batchSize ?? configOptions.batchSize, entityTransformer: options.entityTransformer, + auth: adaptedAuth, discovery: options.discovery, tokenManager: options.tokenManager, catalogClient: options.catalogClient, @@ -96,17 +105,18 @@ export class DefaultCatalogCollatorFactory implements DocumentCollatorFactory { filter: GetEntitiesRequest['filter']; batchSize: number; entityTransformer?: CatalogCollatorEntityTransformer; + auth: AuthService; discovery: PluginEndpointDiscovery; tokenManager: TokenManager; catalogClient?: CatalogApi; }) { const { + auth, batchSize, discovery, locationTemplate, filter, catalogClient, - tokenManager, entityTransformer, } = options; @@ -115,9 +125,9 @@ export class DefaultCatalogCollatorFactory implements DocumentCollatorFactory { this.batchSize = batchSize; this.catalogClient = catalogClient || new CatalogClient({ discoveryApi: discovery }); - this.tokenManager = tokenManager; this.entityTransformer = entityTransformer ?? defaultCatalogCollatorEntityTransformer; + this.auth = auth; } async getCollator(): Promise { @@ -125,7 +135,6 @@ export class DefaultCatalogCollatorFactory implements DocumentCollatorFactory { } private async *execute(): AsyncGenerator { - const { token } = await this.tokenManager.getToken(); let entitiesRetrieved = 0; let moreEntitiesToGet = true; @@ -133,6 +142,10 @@ export class DefaultCatalogCollatorFactory implements DocumentCollatorFactory { // limit (and allow some control over) memory used by the search backend // at index-time. while (moreEntitiesToGet) { + const { token } = await this.auth.getPluginRequestToken({ + onBehalfOf: await this.auth.getOwnServiceCredentials(), + targetPluginId: 'catalog', + }); const entities = ( await this.catalogClient.getEntities( { diff --git a/plugins/search-backend-module-elasticsearch/CHANGELOG.md b/plugins/search-backend-module-elasticsearch/CHANGELOG.md index a025cc9264..d27031156d 100644 --- a/plugins/search-backend-module-elasticsearch/CHANGELOG.md +++ b/plugins/search-backend-module-elasticsearch/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-search-backend-module-elasticsearch +## 1.3.16-next.0 + +### Patch Changes + +- 744c0cb: Start importing `QueryTranslator`, `QueryRequestOptions` and `SearchEngine` from the `@backstage/plugin-search-backend-node`. +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration-aws-node@0.1.10-next.0 + ## 1.3.13 ### Patch Changes diff --git a/plugins/search-backend-module-elasticsearch/api-report.md b/plugins/search-backend-module-elasticsearch/api-report.md index 7de3a1857b..053c267f29 100644 --- a/plugins/search-backend-module-elasticsearch/api-report.md +++ b/plugins/search-backend-module-elasticsearch/api-report.md @@ -17,7 +17,7 @@ import { IndexableResultSet } from '@backstage/plugin-search-common'; import { Logger } from 'winston'; import { LoggerService } from '@backstage/backend-plugin-api'; import { Readable } from 'stream'; -import { SearchEngine } from '@backstage/plugin-search-common'; +import { SearchEngine } from '@backstage/plugin-search-backend-node'; import { SearchQuery } from '@backstage/plugin-search-common'; import { TransportRequestPromise } from '@opensearch-project/opensearch/lib/Transport'; import { TransportRequestPromise as TransportRequestPromise_2 } from '@elastic/elasticsearch/lib/Transport'; diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index f177121a2e..7d4b2b3edb 100644 --- a/plugins/search-backend-module-elasticsearch/package.json +++ b/plugins/search-backend-module-elasticsearch/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-elasticsearch", - "version": "1.3.13", + "version": "1.3.16-next.0", "description": "A module for the search backend that implements search using ElasticSearch", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts index 8ccbe9a4ec..f8c996df51 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts @@ -18,9 +18,9 @@ import { IndexableDocument, IndexableResult, IndexableResultSet, - SearchEngine, SearchQuery, } from '@backstage/plugin-search-common'; +import { SearchEngine } from '@backstage/plugin-search-backend-node'; import { isEmpty, isNumber, isNaN as nan } from 'lodash'; import { AwsSigv4Signer } from '@opensearch-project/opensearch/aws'; diff --git a/plugins/search-backend-module-explore/CHANGELOG.md b/plugins/search-backend-module-explore/CHANGELOG.md index c84bd973f9..6e99f20032 100644 --- a/plugins/search-backend-module-explore/CHANGELOG.md +++ b/plugins/search-backend-module-explore/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-search-backend-module-explore +## 0.1.17-next.0 + +### Patch Changes + +- bb368a5: Migrated to support new auth services. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-explore-common@0.0.2 + ## 0.1.14 ### Patch Changes diff --git a/plugins/search-backend-module-explore/api-report.md b/plugins/search-backend-module-explore/api-report.md index 50cda184a9..43788340c0 100644 --- a/plugins/search-backend-module-explore/api-report.md +++ b/plugins/search-backend-module-explore/api-report.md @@ -5,6 +5,7 @@ ```ts /// +import { AuthService } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { DocumentCollatorFactory } from '@backstage/plugin-search-common'; import { ExploreTool } from '@backstage/plugin-explore-common'; @@ -37,5 +38,6 @@ export type ToolDocumentCollatorFactoryOptions = { discovery: PluginEndpointDiscovery; logger: Logger; tokenManager?: TokenManager; + auth?: AuthService; }; ``` diff --git a/plugins/search-backend-module-explore/package.json b/plugins/search-backend-module-explore/package.json index 9a69c90259..6387b0d21b 100644 --- a/plugins/search-backend-module-explore/package.json +++ b/plugins/search-backend-module-explore/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-explore", - "version": "0.1.14", + "version": "0.1.17-next.0", "description": "A module for the search backend that exports explore modules", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/search-backend-module-explore/src/collators/ToolDocumentCollatorFactory.ts b/plugins/search-backend-module-explore/src/collators/ToolDocumentCollatorFactory.ts index bf6f07839b..daf83ec02b 100644 --- a/plugins/search-backend-module-explore/src/collators/ToolDocumentCollatorFactory.ts +++ b/plugins/search-backend-module-explore/src/collators/ToolDocumentCollatorFactory.ts @@ -17,7 +17,9 @@ import { PluginEndpointDiscovery, TokenManager, + createLegacyAuthAdapters, } from '@backstage/backend-common'; +import { AuthService } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { ExploreTool } from '@backstage/plugin-explore-common'; import { @@ -44,6 +46,7 @@ export type ToolDocumentCollatorFactoryOptions = { discovery: PluginEndpointDiscovery; logger: Logger; tokenManager?: TokenManager; + auth?: AuthService; }; /** @@ -56,12 +59,13 @@ export class ToolDocumentCollatorFactory implements DocumentCollatorFactory { private readonly discovery: PluginEndpointDiscovery; private readonly logger: Logger; - private readonly tokenManager?: TokenManager; + private readonly auth: AuthService; private constructor(options: ToolDocumentCollatorFactoryOptions) { this.discovery = options.discovery; this.logger = options.logger; - this.tokenManager = options.tokenManager; + + this.auth = createLegacyAuthAdapters(options).auth; } static fromConfig( @@ -94,16 +98,13 @@ export class ToolDocumentCollatorFactory implements DocumentCollatorFactory { private async fetchTools() { const baseUrl = await this.discovery.getBaseUrl('explore'); - let headers = {}; - - if (this.tokenManager) { - const { token } = await this.tokenManager.getToken(); - headers = { - Authorization: `Bearer ${token}`, - }; - } - - const response = await fetch(`${baseUrl}/tools`, headers); + const { token } = await this.auth.getPluginRequestToken({ + onBehalfOf: await this.auth.getOwnServiceCredentials(), + targetPluginId: 'explore', + }); + const response = await fetch(`${baseUrl}/tools`, { + headers: { Authorization: `Bearer ${token}` }, + }); 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 db27db8394..2f2d19cbff 100644 --- a/plugins/search-backend-module-pg/CHANGELOG.md +++ b/plugins/search-backend-module-pg/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-search-backend-module-pg +## 0.5.22-next.0 + +### Patch Changes + +- 744c0cb: Start importing `QueryTranslator`, `QueryRequestOptions` and `SearchEngine` from the `@backstage/plugin-search-backend-node`. +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.5.19 ### Patch Changes diff --git a/plugins/search-backend-module-pg/api-report.md b/plugins/search-backend-module-pg/api-report.md index 3c6096090e..21f2d7737d 100644 --- a/plugins/search-backend-module-pg/api-report.md +++ b/plugins/search-backend-module-pg/api-report.md @@ -10,7 +10,7 @@ import { IndexableResultSet } from '@backstage/plugin-search-common'; import { Knex } from 'knex'; import { Logger } from 'winston'; import { PluginDatabaseManager } from '@backstage/backend-common'; -import { SearchEngine } from '@backstage/plugin-search-common'; +import { SearchEngine } from '@backstage/plugin-search-backend-node'; import { SearchQuery } from '@backstage/plugin-search-common'; // @public diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index 9344e1c5ba..8bd704e838 100644 --- a/plugins/search-backend-module-pg/package.json +++ b/plugins/search-backend-module-pg/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-pg", - "version": "0.5.19", + "version": "0.5.22-next.0", "description": "A module for the search backend that implements search using PostgreSQL", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts index 1a27b9f981..b6513a0a97 100644 --- a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts +++ b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts @@ -15,7 +15,7 @@ */ import { PluginDatabaseManager } from '@backstage/backend-common'; -import { SearchEngine } from '@backstage/plugin-search-common'; +import { SearchEngine } from '@backstage/plugin-search-backend-node'; import { SearchQuery, IndexableResultSet, diff --git a/plugins/search-backend-module-stack-overflow-collator/CHANGELOG.md b/plugins/search-backend-module-stack-overflow-collator/CHANGELOG.md index f8fa943043..1c09019adf 100644 --- a/plugins/search-backend-module-stack-overflow-collator/CHANGELOG.md +++ b/plugins/search-backend-module-stack-overflow-collator/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-search-backend-module-stack-overflow-collator +## 0.1.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.1.3 ### Patch Changes diff --git a/plugins/search-backend-module-stack-overflow-collator/package.json b/plugins/search-backend-module-stack-overflow-collator/package.json index 4632ea13b8..3d1aa504f1 100644 --- a/plugins/search-backend-module-stack-overflow-collator/package.json +++ b/plugins/search-backend-module-stack-overflow-collator/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-stack-overflow-collator", - "version": "0.1.3", + "version": "0.1.6-next.0", "description": "A module for the search backend that exports stack overflow modules", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/search-backend-module-techdocs/CHANGELOG.md b/plugins/search-backend-module-techdocs/CHANGELOG.md index d0daa993c0..e713a166a2 100644 --- a/plugins/search-backend-module-techdocs/CHANGELOG.md +++ b/plugins/search-backend-module-techdocs/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-search-backend-module-techdocs +## 0.1.17-next.0 + +### Patch Changes + +- bb368a5: Migrated to support new auth services. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-techdocs-node@1.11.5-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + ## 0.1.14 ### Patch Changes diff --git a/plugins/search-backend-module-techdocs/api-report.md b/plugins/search-backend-module-techdocs/api-report.md index 592cf5065a..1a8c92e5bc 100644 --- a/plugins/search-backend-module-techdocs/api-report.md +++ b/plugins/search-backend-module-techdocs/api-report.md @@ -5,10 +5,12 @@ ```ts /// +import { AuthService } from '@backstage/backend-plugin-api'; import { CatalogApi } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; import { DocumentCollatorFactory } from '@backstage/plugin-search-common'; import { Entity } from '@backstage/catalog-model'; +import { HttpAuthService } from '@backstage/backend-plugin-api'; import { Logger } from 'winston'; import { Permission } from '@backstage/plugin-permission-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; @@ -44,6 +46,8 @@ export type TechDocsCollatorFactoryOptions = { discovery: PluginEndpointDiscovery; logger: Logger; tokenManager: TokenManager; + auth?: AuthService; + httpAuth?: HttpAuthService; locationTemplate?: string; catalogClient?: CatalogApi; parallelismLimit?: number; diff --git a/plugins/search-backend-module-techdocs/package.json b/plugins/search-backend-module-techdocs/package.json index f4a17db6b1..22775f8f4a 100644 --- a/plugins/search-backend-module-techdocs/package.json +++ b/plugins/search-backend-module-techdocs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-techdocs", - "version": "0.1.14", + "version": "0.1.17-next.0", "description": "A module for the search backend that exports techdocs modules", "backstage": { "role": "backend-plugin-module" diff --git a/plugins/search-backend-module-techdocs/src/alpha.ts b/plugins/search-backend-module-techdocs/src/alpha.ts index e8be7cc864..f7a6bb0d36 100644 --- a/plugins/search-backend-module-techdocs/src/alpha.ts +++ b/plugins/search-backend-module-techdocs/src/alpha.ts @@ -74,6 +74,8 @@ export default createBackendModule({ deps: { config: coreServices.rootConfig, logger: coreServices.logger, + auth: coreServices.auth, + httpAuth: coreServices.httpAuth, discovery: coreServices.discovery, tokenManager: coreServices.tokenManager, scheduler: coreServices.scheduler, @@ -83,6 +85,8 @@ export default createBackendModule({ async init({ config, logger, + auth, + httpAuth, discovery, tokenManager, scheduler, @@ -106,6 +110,8 @@ export default createBackendModule({ factory: DefaultTechDocsCollatorFactory.fromConfig(config, { discovery, tokenManager, + auth, + httpAuth, logger: loggerToWinstonLogger(logger), catalogClient: catalog, entityTransformer: transformer, diff --git a/plugins/search-backend-module-techdocs/src/collators/DefaultTechDocsCollatorFactory.ts b/plugins/search-backend-module-techdocs/src/collators/DefaultTechDocsCollatorFactory.ts index b76fedbdf9..1234c5c6fa 100644 --- a/plugins/search-backend-module-techdocs/src/collators/DefaultTechDocsCollatorFactory.ts +++ b/plugins/search-backend-module-techdocs/src/collators/DefaultTechDocsCollatorFactory.ts @@ -17,6 +17,7 @@ import { PluginEndpointDiscovery, TokenManager, + createLegacyAuthAdapters, } from '@backstage/backend-common'; import { CatalogApi, @@ -41,6 +42,7 @@ import { Readable } from 'stream'; import { Logger } from 'winston'; import { TechDocsCollatorEntityTransformer } from './TechDocsCollatorEntityTransformer'; import { defaultTechDocsCollatorEntityTransformer } from './defaultTechDocsCollatorEntityTransformer'; +import { AuthService, HttpAuthService } from '@backstage/backend-plugin-api'; interface MkSearchIndexDoc { title: string; @@ -57,6 +59,8 @@ export type TechDocsCollatorFactoryOptions = { discovery: PluginEndpointDiscovery; logger: Logger; tokenManager: TokenManager; + auth?: AuthService; + httpAuth?: HttpAuthService; locationTemplate?: string; catalogClient?: CatalogApi; parallelismLimit?: number; @@ -84,8 +88,8 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory { private discovery: PluginEndpointDiscovery; private locationTemplate: string; private readonly logger: Logger; + private readonly auth: AuthService; private readonly catalogClient: CatalogApi; - private readonly tokenManager: TokenManager; private readonly parallelismLimit: number; private readonly legacyPathCasing: boolean; private entityTransformer: TechDocsCollatorEntityTransformer; @@ -100,9 +104,14 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory { new CatalogClient({ discoveryApi: options.discovery }); this.parallelismLimit = options.parallelismLimit ?? 10; this.legacyPathCasing = options.legacyPathCasing ?? false; - this.tokenManager = options.tokenManager; this.entityTransformer = options.entityTransformer ?? defaultTechDocsCollatorEntityTransformer; + + this.auth = createLegacyAuthAdapters({ + auth: options.auth, + discovery: options.discovery, + tokenManager: options.tokenManager, + }).auth; } static fromConfig(config: Config, options: TechDocsCollatorFactoryOptions) { @@ -131,7 +140,7 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory { private async *execute(): AsyncGenerator { const limit = pLimit(this.parallelismLimit); const techDocsBaseUrl = await this.discovery.getBaseUrl('techdocs'); - const { token } = await this.tokenManager.getToken(); + let entitiesRetrieved = 0; let moreEntitiesToGet = true; @@ -141,6 +150,11 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory { // parallelism limit to simplify configuration. const batchSize = this.parallelismLimit * 50; while (moreEntitiesToGet) { + const { token: catalogToken } = await this.auth.getPluginRequestToken({ + onBehalfOf: await this.auth.getOwnServiceCredentials(), + targetPluginId: 'catalog', + }); + const entities = ( await this.catalogClient.getEntities( { @@ -151,7 +165,7 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory { limit: batchSize, offset: entitiesRetrieved, }, - { token }, + { token: catalogToken }, ) ).items; @@ -174,6 +188,12 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory { ); try { + const { token: techdocsToken } = + await this.auth.getPluginRequestToken({ + onBehalfOf: await this.auth.getOwnServiceCredentials(), + targetPluginId: 'techdocs', + }); + const searchIndexResponse = await fetch( DefaultTechDocsCollatorFactory.constructDocsIndexUrl( techDocsBaseUrl, @@ -181,7 +201,7 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory { ), { headers: { - Authorization: `Bearer ${token}`, + Authorization: `Bearer ${techdocsToken}`, }, }, ); diff --git a/plugins/search-backend-node/CHANGELOG.md b/plugins/search-backend-node/CHANGELOG.md index 6b372d5262..8ab6f671a3 100644 --- a/plugins/search-backend-node/CHANGELOG.md +++ b/plugins/search-backend-node/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-search-backend-node +## 1.2.17-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- 744c0cb: Exports `QueryTranslator`, `QueryRequestOptions` and `SearchEngine` types. These new types were extracted from the `@backstage/plugin-search-common` package and the `token` property was deprecated in favor of the a new credentials one. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/config@1.1.2-next.0 + ## 1.2.14 ### Patch Changes diff --git a/plugins/search-backend-node/api-report-alpha.md b/plugins/search-backend-node/api-report-alpha.md index 74b7a4b4bc..c8e5cbb65d 100644 --- a/plugins/search-backend-node/api-report-alpha.md +++ b/plugins/search-backend-node/api-report-alpha.md @@ -7,7 +7,7 @@ import { DocumentTypeInfo } from '@backstage/plugin-search-common'; import { ExtensionPoint } from '@backstage/backend-plugin-api'; import { RegisterCollatorParameters } from '@backstage/plugin-search-backend-node'; import { RegisterDecoratorParameters } from '@backstage/plugin-search-backend-node'; -import { SearchEngine } from '@backstage/plugin-search-common'; +import { SearchEngine } from '@backstage/plugin-search-backend-node'; import { ServiceRef } from '@backstage/backend-plugin-api'; // @alpha diff --git a/plugins/search-backend-node/api-report.md b/plugins/search-backend-node/api-report.md index 734bf6e1c0..4109b12cf5 100644 --- a/plugins/search-backend-node/api-report.md +++ b/plugins/search-backend-node/api-report.md @@ -5,6 +5,7 @@ ```ts /// +import { BackstageCredentials } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { DocumentCollatorFactory } from '@backstage/plugin-search-common'; import { DocumentDecoratorFactory } from '@backstage/plugin-search-common'; @@ -14,9 +15,7 @@ import { IndexableResultSet } from '@backstage/plugin-search-common'; import { Logger } from 'winston'; import { default as lunr_2 } from 'lunr'; import { Permission } from '@backstage/plugin-permission-common'; -import { QueryTranslator } from '@backstage/plugin-search-common'; import { Readable } from 'stream'; -import { SearchEngine } from '@backstage/plugin-search-common'; import { SearchQuery } from '@backstage/plugin-search-common'; import { TaskFunction } from '@backstage/backend-tasks'; import { TaskRunner } from '@backstage/backend-tasks'; @@ -144,6 +143,18 @@ export type NewlineDelimitedJsonCollatorFactoryOptions = { visibilityPermission?: Permission; }; +// @public +export type QueryRequestOptions = + | { + token?: string; + } + | { + credentials: BackstageCredentials; + }; + +// @public +export type QueryTranslator = (query: SearchQuery) => unknown; + // @public export interface RegisterCollatorParameters { factory: DocumentCollatorFactory; @@ -170,6 +181,16 @@ export type ScheduleTaskParameters = { scheduledRunner: TaskRunner; }; +// @public +export interface SearchEngine { + getIndexer(type: string): Promise; + query( + query: SearchQuery, + options?: QueryRequestOptions, + ): Promise; + setTranslator(translator: QueryTranslator): void; +} + // @public export class TestPipeline { execute(): Promise; diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index 7ef7b7d2c5..8d60757b4e 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-node", - "version": "1.2.14", + "version": "1.2.17-next.0", "description": "A library for Backstage backend plugins that want to interact with the search backend plugin", "backstage": { "role": "node-library" diff --git a/plugins/search-backend-node/src/IndexBuilder.test.ts b/plugins/search-backend-node/src/IndexBuilder.test.ts index 4a2760dde1..70d00f6974 100644 --- a/plugins/search-backend-node/src/IndexBuilder.test.ts +++ b/plugins/search-backend-node/src/IndexBuilder.test.ts @@ -19,11 +19,10 @@ import { TaskInvocationDefinition, TaskRunner } from '@backstage/backend-tasks'; import { DocumentCollatorFactory, DocumentDecoratorFactory, - SearchEngine, } from '@backstage/plugin-search-common'; import { Readable, Transform } from 'stream'; import { IndexBuilder } from './IndexBuilder'; -import { LunrSearchEngine } from './index'; +import { LunrSearchEngine, SearchEngine } from './index'; class TestDocumentCollatorFactory implements DocumentCollatorFactory { readonly type: string = 'anything'; diff --git a/plugins/search-backend-node/src/IndexBuilder.ts b/plugins/search-backend-node/src/IndexBuilder.ts index 907519f289..98c6853cb1 100644 --- a/plugins/search-backend-node/src/IndexBuilder.ts +++ b/plugins/search-backend-node/src/IndexBuilder.ts @@ -17,12 +17,12 @@ import { DocumentDecoratorFactory, DocumentTypeInfo, - SearchEngine, } from '@backstage/plugin-search-common'; import { Transform, pipeline } from 'stream'; import { Logger } from 'winston'; import { Scheduler } from './Scheduler'; import { + SearchEngine, IndexBuilderOptions, RegisterCollatorParameters, RegisterDecoratorParameters, diff --git a/plugins/search-backend-node/src/alpha.ts b/plugins/search-backend-node/src/alpha.ts index 943e11b580..272bef7f84 100644 --- a/plugins/search-backend-node/src/alpha.ts +++ b/plugins/search-backend-node/src/alpha.ts @@ -22,10 +22,7 @@ import { coreServices, } from '@backstage/backend-plugin-api'; import { loggerToWinstonLogger } from '@backstage/backend-common'; -import { - DocumentTypeInfo, - SearchEngine, -} from '@backstage/plugin-search-common'; +import { DocumentTypeInfo } from '@backstage/plugin-search-common'; import { createExtensionPoint } from '@backstage/backend-plugin-api'; import { @@ -33,7 +30,10 @@ import { RegisterDecoratorParameters, } from '@backstage/plugin-search-backend-node'; -import { IndexBuilder } from './IndexBuilder'; +import { + SearchEngine, + IndexBuilder, +} from '@backstage/plugin-search-backend-node'; /** * @alpha diff --git a/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts b/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts index 55c18cd6fc..e5347b3cb1 100644 --- a/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts +++ b/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts @@ -16,10 +16,7 @@ import { getVoidLogger } from '@backstage/backend-common'; import lunr from 'lunr'; -import { - IndexableDocument, - SearchEngine, -} from '@backstage/plugin-search-common'; +import { IndexableDocument } from '@backstage/plugin-search-common'; import { ConcreteLunrQuery, LunrSearchEngine, @@ -28,6 +25,7 @@ import { parseHighlightFields, } from './LunrSearchEngine'; import { LunrSearchEngineIndexer } from './LunrSearchEngineIndexer'; +import { SearchEngine } from '../types'; import { TestPipeline } from '../test-utils'; /** diff --git a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts index 27cfae3fdf..a2db52f960 100644 --- a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts +++ b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts @@ -18,9 +18,8 @@ import { IndexableDocument, IndexableResultSet, SearchQuery, - QueryTranslator, - SearchEngine, } from '@backstage/plugin-search-common'; +import { SearchEngine, QueryTranslator } from '../types'; import { MissingIndexError } from '../errors'; import lunr from 'lunr'; import { v4 as uuid } from 'uuid'; diff --git a/plugins/search-backend-node/src/index.ts b/plugins/search-backend-node/src/index.ts index a188509c1c..78e4880305 100644 --- a/plugins/search-backend-node/src/index.ts +++ b/plugins/search-backend-node/src/index.ts @@ -33,6 +33,9 @@ export type { IndexBuilderOptions, RegisterCollatorParameters, RegisterDecoratorParameters, + SearchEngine, + QueryRequestOptions, + QueryTranslator, } from './types'; export * from './errors'; export * from './indexing'; diff --git a/plugins/search-backend-node/src/types.ts b/plugins/search-backend-node/src/types.ts index dfcf4d12ce..742d575ed3 100644 --- a/plugins/search-backend-node/src/types.ts +++ b/plugins/search-backend-node/src/types.ts @@ -14,12 +14,15 @@ * limitations under the License. */ +import { BackstageCredentials } from '@backstage/backend-plugin-api'; import { TaskRunner } from '@backstage/backend-tasks'; import { DocumentCollatorFactory, DocumentDecoratorFactory, - SearchEngine, + IndexableResultSet, + SearchQuery, } from '@backstage/plugin-search-common'; +import { Writable } from 'stream'; import { Logger } from 'winston'; /** @@ -57,3 +60,55 @@ export interface RegisterDecoratorParameters { */ factory: DocumentDecoratorFactory; } + +/** + * A type of function responsible for translating an abstract search query into + * a concrete query relevant to a particular search engine. + * @public + */ +export type QueryTranslator = (query: SearchQuery) => unknown; + +/** + * Options when querying a search engine. + * @public + */ +export type QueryRequestOptions = + | { + /** @deprecated use the `credentials` option instead. */ + token?: string; + } + | { + credentials: BackstageCredentials; + }; + +/** + * Interface that must be implemented by specific search engines, responsible + * for performing indexing and querying and translating abstract queries into + * concrete, search engine-specific queries. + * @public + */ +export interface SearchEngine { + /** + * Override the default translator provided by the SearchEngine. + */ + setTranslator(translator: QueryTranslator): void; + + /** + * Factory method for getting a search engine indexer for a given document + * type. + * + * @param type - The type or name of the document set for which an indexer + * should be retrieved. This corresponds to the `type` property on the + * document collator/decorator factories and will most often be used to + * identify an index or group to which documents should be written. + */ + getIndexer(type: string): Promise; + + /** + * Perform a search query against the SearchEngine. + */ + query( + query: SearchQuery, + options?: QueryRequestOptions, + ): Promise; +} diff --git a/plugins/search-backend/CHANGELOG.md b/plugins/search-backend/CHANGELOG.md index f9a773139b..cd91d27b41 100644 --- a/plugins/search-backend/CHANGELOG.md +++ b/plugins/search-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-search-backend +## 1.5.3-next.0 + +### Patch Changes + +- 744c0cb: Update the router to use the new `auth` services, it now accepts an optional discovery service option to get credentials for the permission service. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/backend-openapi-utils@0.1.6-next.0 + - @backstage/plugin-search-backend-node@1.2.17-next.0 + - @backstage/plugin-permission-node@0.7.24-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + ## 1.5.0 ### Minor Changes diff --git a/plugins/search-backend/api-report.md b/plugins/search-backend/api-report.md index d6274d9a94..4f99632f28 100644 --- a/plugins/search-backend/api-report.md +++ b/plugins/search-backend/api-report.md @@ -3,13 +3,16 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { AuthService } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; +import { DiscoveryService } from '@backstage/backend-plugin-api'; import { DocumentTypeInfo } from '@backstage/plugin-search-common'; import express from 'express'; +import { HttpAuthService } from '@backstage/backend-plugin-api'; import { Logger } from 'winston'; import { PermissionAuthorizer } from '@backstage/plugin-permission-common'; import { PermissionEvaluator } from '@backstage/plugin-permission-common'; -import { SearchEngine } from '@backstage/plugin-search-common'; +import { SearchEngine } from '@backstage/plugin-search-backend-node'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; @@ -18,8 +21,11 @@ export function createRouter(options: RouterOptions): Promise; export type RouterOptions = { engine: SearchEngine; types: Record; + discovery?: DiscoveryService; permissions: PermissionEvaluator | PermissionAuthorizer; config: Config; logger: Logger; + auth?: AuthService; + httpAuth?: HttpAuthService; }; ``` diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index 9e073d7834..ee7836218f 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.5.0", + "version": "1.5.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend/src/alpha.ts b/plugins/search-backend/src/alpha.ts index 8a9d4498bc..86bbcdeebe 100644 --- a/plugins/search-backend/src/alpha.ts +++ b/plugins/search-backend/src/alpha.ts @@ -22,6 +22,7 @@ import { loggerToWinstonLogger } from '@backstage/backend-common'; import { RegisterCollatorParameters, RegisterDecoratorParameters, + SearchEngine, LunrSearchEngine, } from '@backstage/plugin-search-backend-node'; import { @@ -33,7 +34,6 @@ import { } from '@backstage/plugin-search-backend-node/alpha'; import { createRouter } from './service/router'; -import { SearchEngine } from '@backstage/plugin-search-common'; class SearchIndexRegistry implements SearchIndexRegistryExtensionPoint { private collators: RegisterCollatorParameters[] = []; @@ -94,11 +94,23 @@ export default createBackendPlugin({ deps: { logger: coreServices.logger, config: coreServices.rootConfig, + discovery: coreServices.discovery, permissions: coreServices.permissions, + auth: coreServices.auth, http: coreServices.httpRouter, + httpAuth: coreServices.httpAuth, searchIndexService: searchIndexServiceRef, }, - async init({ config, logger, permissions, http, searchIndexService }) { + async init({ + config, + logger, + discovery, + permissions, + auth, + http, + httpAuth, + searchIndexService, + }) { let searchEngine = searchEngineRegistry.getSearchEngine(); if (!searchEngine) { searchEngine = new LunrSearchEngine({ @@ -117,7 +129,10 @@ export default createBackendPlugin({ const router = await createRouter({ config, + discovery, permissions, + auth, + httpAuth, logger: loggerToWinstonLogger(logger), engine: searchEngine, types: searchIndexService.getDocumentTypes(), diff --git a/plugins/search-backend/src/service/AuthorizedSearchEngine.test.ts b/plugins/search-backend/src/service/AuthorizedSearchEngine.test.ts index b2355a7239..420af5744b 100644 --- a/plugins/search-backend/src/service/AuthorizedSearchEngine.test.ts +++ b/plugins/search-backend/src/service/AuthorizedSearchEngine.test.ts @@ -25,8 +25,8 @@ import { import { DocumentTypeInfo, IndexableDocument, - SearchEngine, } from '@backstage/plugin-search-common'; +import { SearchEngine } from '@backstage/plugin-search-backend-node'; import { encodePageCursor, decodePageCursor, diff --git a/plugins/search-backend/src/service/AuthorizedSearchEngine.ts b/plugins/search-backend/src/service/AuthorizedSearchEngine.ts index 8d285d053e..defb535f42 100644 --- a/plugins/search-backend/src/service/AuthorizedSearchEngine.ts +++ b/plugins/search-backend/src/service/AuthorizedSearchEngine.ts @@ -23,21 +23,23 @@ import { EvaluatePermissionRequest, EvaluatePermissionResponse, isResourcePermission, - PermissionEvaluator, QueryPermissionRequest, } from '@backstage/plugin-permission-common'; import { DocumentTypeInfo, IndexableResult, IndexableResultSet, + SearchQuery, +} from '@backstage/plugin-search-common'; +import { QueryRequestOptions, QueryTranslator, SearchEngine, - SearchQuery, -} from '@backstage/plugin-search-common'; +} from '@backstage/plugin-search-backend-node'; import { Config } from '@backstage/config'; import { InputError } from '@backstage/errors'; import { Writable } from 'stream'; +import { PermissionsService } from '@backstage/backend-plugin-api'; export function decodePageCursor(pageCursor?: string): { page: number } { if (!pageCursor) { @@ -68,7 +70,7 @@ export class AuthorizedSearchEngine implements SearchEngine { constructor( private readonly searchEngine: SearchEngine, private readonly types: Record, - private readonly permissions: PermissionEvaluator, + private readonly permissions: PermissionsService, config: Config, ) { this.queryLatencyBudgetMs = diff --git a/plugins/search-backend/src/service/router.test.ts b/plugins/search-backend/src/service/router.test.ts index 401488dcbf..7c89a8c750 100644 --- a/plugins/search-backend/src/service/router.test.ts +++ b/plugins/search-backend/src/service/router.test.ts @@ -14,16 +14,22 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; +import { + PluginEndpointDiscovery, + getVoidLogger, +} from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { PermissionEvaluator } from '@backstage/plugin-permission-common'; -import { IndexBuilder } from '@backstage/plugin-search-backend-node'; -import { SearchEngine } from '@backstage/plugin-search-common'; +import { + IndexBuilder, + SearchEngine, +} from '@backstage/plugin-search-backend-node'; import express from 'express'; import request from 'supertest'; import { createRouter } from './router'; import { wrapInOpenApiTestServer } from '@backstage/backend-openapi-utils'; import { Server } from 'http'; +import { mockCredentials, mockServices } from '@backstage/backend-test-utils'; const mockPermissionEvaluator: PermissionEvaluator = { authorize: () => { @@ -38,6 +44,16 @@ describe('createRouter', () => { let app: express.Express | Server; let mockSearchEngine: jest.Mocked; + const mockBaseUrl = 'http://backstage:9191/api/proxy'; + const discovery: PluginEndpointDiscovery = { + async getBaseUrl() { + return mockBaseUrl; + }, + async getExternalBaseUrl() { + return mockBaseUrl; + }, + }; + beforeAll(async () => { const logger = getVoidLogger(); mockSearchEngine = { @@ -65,7 +81,10 @@ describe('createRouter', () => { search: { maxPageLimit: 200, maxTermLength: 20 }, }), permissions: mockPermissionEvaluator, + discovery, logger, + auth: mockServices.auth(), + httpAuth: mockServices.httpAuth(), }); app = wrapInOpenApiTestServer(express().use(router)); }); @@ -227,7 +246,11 @@ describe('createRouter', () => { unknownKey2: 'unknownValue1', }; const secondArg = { - token: undefined, + credentials: mockCredentials.user(), + token: mockCredentials.service.token({ + onBehalfOf: mockCredentials.user(), + targetPluginId: 'search', + }), }; expect(response.status).toEqual(200); expect(mockSearchEngine.query).toHaveBeenCalledWith(firstArg, secondArg); @@ -251,6 +274,7 @@ describe('createRouter', () => { types: indexBuilder.getDocumentTypes(), config: new ConfigReader({ permissions: { enabled: false } }), permissions: mockPermissionEvaluator, + discovery, logger, }); app = express().use(router); diff --git a/plugins/search-backend/src/service/router.ts b/plugins/search-backend/src/service/router.ts index 876cb5d103..ae470ba40e 100644 --- a/plugins/search-backend/src/service/router.ts +++ b/plugins/search-backend/src/service/router.ts @@ -17,11 +17,14 @@ import express from 'express'; import { Logger } from 'winston'; import { z } from 'zod'; -import { errorHandler } from '@backstage/backend-common'; +import { + HostDiscovery, + createLegacyAuthAdapters, + errorHandler, +} from '@backstage/backend-common'; import { InputError } from '@backstage/errors'; import { Config } from '@backstage/config'; import { JsonObject, JsonValue } from '@backstage/types'; -import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node'; import { PermissionAuthorizer, PermissionEvaluator, @@ -32,9 +35,14 @@ import { IndexableResultSet, SearchResultSet, } from '@backstage/plugin-search-common'; -import { SearchEngine } from '@backstage/plugin-search-common'; +import { SearchEngine } from '@backstage/plugin-search-backend-node'; import { AuthorizedSearchEngine } from './AuthorizedSearchEngine'; import { createOpenApiRouter } from '../schema/openapi.generated'; +import { + AuthService, + DiscoveryService, + HttpAuthService, +} from '@backstage/backend-plugin-api'; const jsonObjectSchema: z.ZodSchema = z.lazy(() => { const jsonValueSchema: z.ZodSchema = z.lazy(() => @@ -57,9 +65,12 @@ const jsonObjectSchema: z.ZodSchema = z.lazy(() => { export type RouterOptions = { engine: SearchEngine; types: Record; + discovery?: DiscoveryService; permissions: PermissionEvaluator | PermissionAuthorizer; config: Config; logger: Logger; + auth?: AuthService; + httpAuth?: HttpAuthService; }; const defaultMaxPageLimit = 100; @@ -73,7 +84,19 @@ export async function createRouter( options: RouterOptions, ): Promise { const router = await createOpenApiRouter(); - const { engine: inputEngine, types, permissions, config, logger } = options; + const { + engine: inputEngine, + types, + permissions, + config, + logger, + discovery = HostDiscovery.fromConfig(config), + } = options; + + const { auth, httpAuth } = createLegacyAuthAdapters({ + ...options, + discovery, + }); const maxPageLimit = config.getOptionalNumber('search.maxPageLimit') ?? defaultMaxPageLimit; @@ -169,12 +192,16 @@ export async function createRouter( }`, ); - const token = getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ); - try { - const resultSet = await engine?.query(query, { token }); + const credentials = await httpAuth.credentials(req); + const { token } = await auth.getPluginRequestToken({ + onBehalfOf: credentials, + targetPluginId: 'search', + }); + const resultSet = await engine?.query(query, { + token, + credentials, + }); res.json(filterResultSet(toSearchResults(resultSet))); } catch (error) { diff --git a/plugins/search-backend/src/service/standaloneServer.ts b/plugins/search-backend/src/service/standaloneServer.ts index 9e4294d39f..09fa4f87ee 100644 --- a/plugins/search-backend/src/service/standaloneServer.ts +++ b/plugins/search-backend/src/service/standaloneServer.ts @@ -57,6 +57,7 @@ export async function startStandaloneServer( const router = await createRouter({ engine: indexBuilder.getSearchEngine(), types: indexBuilder.getDocumentTypes(), + discovery, permissions, config, logger, diff --git a/plugins/search-common/CHANGELOG.md b/plugins/search-common/CHANGELOG.md index d14a8e37b3..b435f1b361 100644 --- a/plugins/search-common/CHANGELOG.md +++ b/plugins/search-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-search-common +## 1.2.11-next.0 + +### Patch Changes + +- 744c0cb: Deprecate `QueryTranslator`, `QueryRequestOptions` and `SearchEngine` in favor of the types exported from `@backstage/plugin-search-backend-node`. +- Updated dependencies + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/types@1.1.1 + ## 1.2.10 ### Patch Changes diff --git a/plugins/search-common/api-report.md b/plugins/search-common/api-report.md index 2006689ab9..497defc46d 100644 --- a/plugins/search-common/api-report.md +++ b/plugins/search-common/api-report.md @@ -42,12 +42,12 @@ export type IndexableResult = Result; // @public (undocumented) export type IndexableResultSet = ResultSet; -// @public +// @public @deprecated export type QueryRequestOptions = { token?: string; }; -// @public +// @public @deprecated export type QueryTranslator = (query: SearchQuery) => unknown; // @public (undocumented) @@ -87,7 +87,7 @@ export interface SearchDocument { title: string; } -// @public +// @public @deprecated export interface SearchEngine { getIndexer(type: string): Promise; query( diff --git a/plugins/search-common/package.json b/plugins/search-common/package.json index cdec0b98f4..09b3eb928c 100644 --- a/plugins/search-common/package.json +++ b/plugins/search-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-common", - "version": "1.2.10", + "version": "1.2.11-next.0", "description": "Common functionalities for Search, to be shared between various search-enabled plugins", "backstage": { "role": "common-library" diff --git a/plugins/search-common/src/deprecated.ts b/plugins/search-common/src/deprecated.ts new file mode 100644 index 0000000000..8d76d3a22d --- /dev/null +++ b/plugins/search-common/src/deprecated.ts @@ -0,0 +1,68 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Writable } from 'stream'; +import { SearchQuery, IndexableResultSet } from './types'; + +/** + * A type of function responsible for translating an abstract search query into + * a concrete query relevant to a particular search engine. + * @public + * @deprecated Import from `@backstage/plugin-search-backend-node` instead + */ +export type QueryTranslator = (query: SearchQuery) => unknown; + +/** + * Options when querying a search engine. + * @public + * @deprecated Import from `@backstage/plugin-search-backend-node` instead + */ +export type QueryRequestOptions = { + token?: string; +}; + +/** + * Interface that must be implemented by specific search engines, responsible + * for performing indexing and querying and translating abstract queries into + * concrete, search engine-specific queries. + * @public + * @deprecated Import from `@backstage/plugin-search-backend-node` instead + */ +export interface SearchEngine { + /** + * Override the default translator provided by the SearchEngine. + */ + setTranslator(translator: QueryTranslator): void; + + /** + * Factory method for getting a search engine indexer for a given document + * type. + * + * @param type - The type or name of the document set for which an indexer + * should be retrieved. This corresponds to the `type` property on the + * document collator/decorator factories and will most often be used to + * identify an index or group to which documents should be written. + */ + getIndexer(type: string): Promise; + + /** + * Perform a search query against the SearchEngine. + */ + query( + query: SearchQuery, + options?: QueryRequestOptions, + ): Promise; +} diff --git a/plugins/search-common/src/index.ts b/plugins/search-common/src/index.ts index e71f8cd660..5d8ae2d42f 100644 --- a/plugins/search-common/src/index.ts +++ b/plugins/search-common/src/index.ts @@ -21,3 +21,4 @@ */ export * from './types'; +export * from './deprecated'; diff --git a/plugins/search-common/src/types.ts b/plugins/search-common/src/types.ts index 2ea4a490ca..9d1f9aa887 100644 --- a/plugins/search-common/src/types.ts +++ b/plugins/search-common/src/types.ts @@ -16,7 +16,7 @@ import { Permission } from '@backstage/plugin-permission-common'; import { JsonObject } from '@backstage/types'; -import { Readable, Transform, Writable } from 'stream'; +import { Readable, Transform } from 'stream'; /** * @public @@ -206,50 +206,3 @@ export interface DocumentDecoratorFactory { */ getDecorator(): Promise; } - -/** - * A type of function responsible for translating an abstract search query into - * a concrete query relevant to a particular search engine. - * @public - */ -export type QueryTranslator = (query: SearchQuery) => unknown; - -/** - * Options when querying a search engine. - * @public - */ -export type QueryRequestOptions = { - token?: string; -}; - -/** - * Interface that must be implemented by specific search engines, responsible - * for performing indexing and querying and translating abstract queries into - * concrete, search engine-specific queries. - * @public - */ -export interface SearchEngine { - /** - * Override the default translator provided by the SearchEngine. - */ - setTranslator(translator: QueryTranslator): void; - - /** - * Factory method for getting a search engine indexer for a given document - * type. - * - * @param type - The type or name of the document set for which an indexer - * should be retrieved. This corresponds to the `type` property on the - * document collator/decorator factories and will most often be used to - * identify an index or group to which documents should be written. - */ - getIndexer(type: string): Promise; - - /** - * Perform a search query against the SearchEngine. - */ - query( - query: SearchQuery, - options?: QueryRequestOptions, - ): Promise; -} diff --git a/plugins/search-react/CHANGELOG.md b/plugins/search-react/CHANGELOG.md index 055589e9d7..2c7fc67ddc 100644 --- a/plugins/search-react/CHANGELOG.md +++ b/plugins/search-react/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-search-react +## 1.7.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + ## 1.7.6 ### Patch Changes diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index 79223e13b1..747e0e1d6f 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-react", - "version": "1.7.6", + "version": "1.7.7-next.0", "backstage": { "role": "web-library" }, diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index fbae4f5f40..a1ff6bf496 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-search +## 1.4.7-next.0 + +### Patch Changes + +- f0464b0: Removes ADR from the default set of search filters +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + ## 1.4.6 ### Patch Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index 6b67fd95bf..46ae937b4f 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search", - "version": "1.4.6", + "version": "1.4.7-next.0", "description": "The Backstage plugin that provides your backstage app with search", "backstage": { "role": "frontend-plugin" diff --git a/plugins/search/src/alpha.tsx b/plugins/search/src/alpha.tsx index 4f654548f5..f4dd09088a 100644 --- a/plugins/search/src/alpha.tsx +++ b/plugins/search/src/alpha.tsx @@ -153,11 +153,6 @@ export const searchPage = createPageExtension({ name: 'Documentation', icon: , }, - { - value: 'adr', - name: 'Architecture Decision Records', - icon: , - }, ]} /> diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index c9df5802da..1c996c9286 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-sentry +## 0.5.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.5.15 ### Patch Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index c28be2cb47..09aab2400c 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sentry", - "version": "0.5.15", + "version": "0.5.16-next.0", "description": "A Backstage plugin that integrates towards Sentry", "backstage": { "role": "frontend-plugin" diff --git a/plugins/shortcuts/CHANGELOG.md b/plugins/shortcuts/CHANGELOG.md index a6385d0575..18b6f13f30 100644 --- a/plugins/shortcuts/CHANGELOG.md +++ b/plugins/shortcuts/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-shortcuts +## 0.3.20-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + ## 0.3.19 ### Patch Changes diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index ef8bde1043..64e1ee50bd 100644 --- a/plugins/shortcuts/package.json +++ b/plugins/shortcuts/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-shortcuts", - "version": "0.3.19", + "version": "0.3.20-next.0", "description": "A Backstage plugin that provides a shortcuts feature to the sidebar", "backstage": { "role": "frontend-plugin" diff --git a/plugins/signals-backend/CHANGELOG.md b/plugins/signals-backend/CHANGELOG.md index a44910f2a5..21ede277ed 100644 --- a/plugins/signals-backend/CHANGELOG.md +++ b/plugins/signals-backend/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-signals-backend +## 0.0.4-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-signals-node@0.0.4-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + ## 0.0.1 ### Patch Changes diff --git a/plugins/signals-backend/package.json b/plugins/signals-backend/package.json index 4fcca7b0e6..4537229070 100644 --- a/plugins/signals-backend/package.json +++ b/plugins/signals-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-signals-backend", - "version": "0.0.1", + "version": "0.0.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/signals-node/CHANGELOG.md b/plugins/signals-node/CHANGELOG.md index f8c4e9d268..d20cb2dd95 100644 --- a/plugins/signals-node/CHANGELOG.md +++ b/plugins/signals-node/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-signals-node +## 0.0.4-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-events-node@0.3.0-next.0 + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + ## 0.0.1 ### Patch Changes diff --git a/plugins/signals-node/package.json b/plugins/signals-node/package.json index 03ef61739f..8ae5c4411c 100644 --- a/plugins/signals-node/package.json +++ b/plugins/signals-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-signals-node", "description": "Node.js library for the signals plugin", - "version": "0.0.1", + "version": "0.0.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/signals-react/CHANGELOG.md b/plugins/signals-react/CHANGELOG.md index d05ab73868..bb88bccef3 100644 --- a/plugins/signals-react/CHANGELOG.md +++ b/plugins/signals-react/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-signals-react +## 0.0.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + ## 0.0.1 ### Patch Changes diff --git a/plugins/signals-react/package.json b/plugins/signals-react/package.json index ebaecbf337..8c2aa15224 100644 --- a/plugins/signals-react/package.json +++ b/plugins/signals-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-signals-react", - "version": "0.0.1", + "version": "0.0.2-next.0", "description": "Web library for the signals plugin", "backstage": { "role": "web-library" diff --git a/plugins/signals/CHANGELOG.md b/plugins/signals/CHANGELOG.md index 758a607424..d96f7a94c8 100644 --- a/plugins/signals/CHANGELOG.md +++ b/plugins/signals/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-signals +## 0.0.2-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- Updated dependencies + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-signals-react@0.0.2-next.0 + ## 0.0.1 ### Patch Changes diff --git a/plugins/signals/package.json b/plugins/signals/package.json index 5f2f4222c2..2c3f9eb800 100644 --- a/plugins/signals/package.json +++ b/plugins/signals/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-signals", - "version": "0.0.1", + "version": "0.0.2-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/sonarqube-backend/CHANGELOG.md b/plugins/sonarqube-backend/CHANGELOG.md index d43a52df74..8df87e8169 100644 --- a/plugins/sonarqube-backend/CHANGELOG.md +++ b/plugins/sonarqube-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-sonarqube-backend +## 0.2.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + ## 0.2.12 ### Patch Changes diff --git a/plugins/sonarqube-backend/package.json b/plugins/sonarqube-backend/package.json index 0b4c7fe86c..70f936c3ea 100644 --- a/plugins/sonarqube-backend/package.json +++ b/plugins/sonarqube-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube-backend", - "version": "0.2.12", + "version": "0.2.15-next.0", "backstage": { "role": "backend-plugin" }, diff --git a/plugins/sonarqube-react/CHANGELOG.md b/plugins/sonarqube-react/CHANGELOG.md index 9d4843c3ee..de35cce067 100644 --- a/plugins/sonarqube-react/CHANGELOG.md +++ b/plugins/sonarqube-react/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-sonarqube-react +## 0.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.1.13 ### Patch Changes diff --git a/plugins/sonarqube-react/package.json b/plugins/sonarqube-react/package.json index 83b1291edf..090d6b1cf4 100644 --- a/plugins/sonarqube-react/package.json +++ b/plugins/sonarqube-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube-react", - "version": "0.1.13", + "version": "0.1.14-next.0", "backstage": { "role": "web-library" }, diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index 40fe22e151..faf78c194a 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-sonarqube +## 0.7.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-sonarqube-react@0.1.14-next.0 + ## 0.7.12 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index 352254b0e5..7d25781c60 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube", - "version": "0.7.12", + "version": "0.7.13-next.0", "description": "", "backstage": { "role": "frontend-plugin" diff --git a/plugins/splunk-on-call/CHANGELOG.md b/plugins/splunk-on-call/CHANGELOG.md index 596877448a..0c333fbf8e 100644 --- a/plugins/splunk-on-call/CHANGELOG.md +++ b/plugins/splunk-on-call/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-splunk-on-call +## 0.4.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.4.19 ### Patch Changes diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index d14316e21f..d9a10a44c4 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-splunk-on-call", - "version": "0.4.19", + "version": "0.4.20-next.0", "description": "A Backstage plugin that integrates towards Splunk On-Call", "backstage": { "role": "frontend-plugin" diff --git a/plugins/stack-overflow-backend/CHANGELOG.md b/plugins/stack-overflow-backend/CHANGELOG.md index 8bdcf5c7da..d33126467d 100644 --- a/plugins/stack-overflow-backend/CHANGELOG.md +++ b/plugins/stack-overflow-backend/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-stack-overflow-backend +## 0.2.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-module-stack-overflow-collator@0.1.6-next.0 + ## 0.2.14 ### Patch Changes diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index b47ef94c7e..02880d19c7 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.14", + "version": "0.2.17-next.0", "description": "Deprecated, consider using @backstage/plugin-search-backend-module-stack-overflow-collator instead", "backstage": { "role": "backend-plugin" diff --git a/plugins/stack-overflow/CHANGELOG.md b/plugins/stack-overflow/CHANGELOG.md index dddf1b6cb1..bdd79e3a1c 100644 --- a/plugins/stack-overflow/CHANGELOG.md +++ b/plugins/stack-overflow/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-stack-overflow +## 0.1.26-next.0 + +### Patch Changes + +- c6779ac: fix: fix decode issues in title and author fields in `StackOverflowSearchResultListItem` +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/plugin-home-react@0.1.9-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + ## 0.1.25 ### Patch Changes diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index 4a25eec41a..a39dc50e21 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.25", + "version": "0.1.26-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/stackstorm/CHANGELOG.md b/plugins/stackstorm/CHANGELOG.md index c7054de9d1..a55c8606e2 100644 --- a/plugins/stackstorm/CHANGELOG.md +++ b/plugins/stackstorm/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-stackstorm +## 0.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.1.11 ### Patch Changes diff --git a/plugins/stackstorm/package.json b/plugins/stackstorm/package.json index ffec91508f..1ea9267bb2 100644 --- a/plugins/stackstorm/package.json +++ b/plugins/stackstorm/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-stackstorm", - "version": "0.1.11", + "version": "0.1.12-next.0", "description": "A Backstage plugin that integrates towards StackStorm", "backstage": { "role": "frontend-plugin" diff --git a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md index 4f92285aa3..94c365c1d2 100644 --- a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md +++ b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-tech-insights-backend-module-jsonfc +## 0.1.45-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-tech-insights-node@0.5.0-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.1.42 ### Patch Changes diff --git a/plugins/tech-insights-backend-module-jsonfc/package.json b/plugins/tech-insights-backend-module-jsonfc/package.json index d4dcb23f4b..0e8f69695b 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.42", + "version": "0.1.45-next.0", "backstage": { "role": "backend-plugin-module" }, diff --git a/plugins/tech-insights-backend/CHANGELOG.md b/plugins/tech-insights-backend/CHANGELOG.md index efba8e6de8..534b04e161 100644 --- a/plugins/tech-insights-backend/CHANGELOG.md +++ b/plugins/tech-insights-backend/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-tech-insights-backend +## 0.5.27-next.0 + +### Patch Changes + +- 0fb419b: Updated dependency `uuid` to `^9.0.0`. + Updated dependency `@types/uuid` to `^9.0.0`. +- d621468: Added support for the new `AuthService`. +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/plugin-tech-insights-node@0.5.0-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.5.24 ### Patch Changes diff --git a/plugins/tech-insights-backend/api-report.md b/plugins/tech-insights-backend/api-report.md index 631e792141..c2121bf655 100644 --- a/plugins/tech-insights-backend/api-report.md +++ b/plugins/tech-insights-backend/api-report.md @@ -3,6 +3,7 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { AuthService } from '@backstage/backend-plugin-api'; import { BackendFeature } from '@backstage/backend-plugin-api'; import { CheckResult } from '@backstage/plugin-tech-insights-common'; import { Config } from '@backstage/config'; @@ -110,6 +111,8 @@ export interface TechInsightsOptions< CheckType extends TechInsightCheck, CheckResultType extends CheckResult, > { + // (undocumented) + auth?: AuthService; // (undocumented) config: Config; // (undocumented) diff --git a/plugins/tech-insights-backend/package.json b/plugins/tech-insights-backend/package.json index b1d84acae1..d9463612b6 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.24", + "version": "0.5.27-next.0", "backstage": { "role": "backend-plugin" }, diff --git a/plugins/tech-insights-backend/src/plugin/plugin.ts b/plugins/tech-insights-backend/src/plugin/plugin.ts index 6da1ac1637..e97a0c98d8 100644 --- a/plugins/tech-insights-backend/src/plugin/plugin.ts +++ b/plugins/tech-insights-backend/src/plugin/plugin.ts @@ -102,6 +102,7 @@ export const techInsightsPlugin = createBackendPlugin({ logger: coreServices.logger, scheduler: coreServices.scheduler, tokenManager: coreServices.tokenManager, + auth: coreServices.auth, }, async init({ config, @@ -111,6 +112,7 @@ export const techInsightsPlugin = createBackendPlugin({ logger, scheduler, tokenManager, + auth, }) { const winstonLogger = loggerToWinstonLogger(logger); const factRetrievers: FactRetrieverRegistration[] = Object.entries( @@ -136,6 +138,7 @@ export const techInsightsPlugin = createBackendPlugin({ persistenceContext, scheduler, tokenManager, + auth, }); httpRouter.use( diff --git a/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.test.ts b/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.test.ts index 3bbaf9edf5..a6d485d130 100644 --- a/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.test.ts +++ b/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.test.ts @@ -32,7 +32,11 @@ import { ServerTokenManager, } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; -import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; +import { + TestDatabaseId, + TestDatabases, + mockServices, +} from '@backstage/backend-test-utils'; import { TaskScheduler } from '@backstage/backend-tasks'; jest.setTimeout(60_000); @@ -140,6 +144,7 @@ describe('FactRetrieverEngine', () => { logger: getVoidLogger(), config: ConfigReader.fromConfigs([]), tokenManager: ServerTokenManager.noop(), + auth: mockServices.auth(), discovery: { getBaseUrl: (_: string) => Promise.resolve('http://mock.url'), getExternalBaseUrl: (_: string) => Promise.resolve('http://mock.url'), diff --git a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityMetadataFactRetriever.test.ts b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityMetadataFactRetriever.test.ts index 31400788b5..7c608f60bc 100644 --- a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityMetadataFactRetriever.test.ts +++ b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityMetadataFactRetriever.test.ts @@ -23,6 +23,7 @@ import { import { ConfigReader } from '@backstage/config'; import { GetEntitiesResponse } from '@backstage/catalog-client'; import { entityMetadataFactRetriever } from './entityMetadataFactRetriever'; +import { mockServices } from '@backstage/backend-test-utils'; const getEntitiesMock = jest.fn(); jest.mock('@backstage/catalog-client', () => { @@ -104,6 +105,7 @@ const defaultEntityListResponse: GetEntitiesResponse = { const handlerContext = { discovery, logger: getVoidLogger(), + auth: mockServices.auth(), config: ConfigReader.fromConfigs([]), tokenManager: ServerTokenManager.noop(), }; diff --git a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityMetadataFactRetriever.ts b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityMetadataFactRetriever.ts index 3103f9bdd5..cca4911350 100644 --- a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityMetadataFactRetriever.ts +++ b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityMetadataFactRetriever.ts @@ -47,12 +47,11 @@ export const entityMetadataFactRetriever: FactRetriever = { description: 'The entity has tags in metadata', }, }, - handler: async ({ - discovery, - entityFilter, - tokenManager, - }: FactRetrieverContext) => { - const { token } = await tokenManager.getToken(); + handler: async ({ discovery, entityFilter, auth }: FactRetrieverContext) => { + const { token } = await auth.getPluginRequestToken({ + onBehalfOf: await auth.getOwnServiceCredentials(), + targetPluginId: 'catalog', + }); const catalogClient = new CatalogClient({ discoveryApi: discovery, }); diff --git a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityOwnershipFactRetriever.test.ts b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityOwnershipFactRetriever.test.ts index 7a77ef91c4..1c578486ce 100644 --- a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityOwnershipFactRetriever.test.ts +++ b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityOwnershipFactRetriever.test.ts @@ -23,6 +23,7 @@ import { } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { GetEntitiesResponse } from '@backstage/catalog-client'; +import { mockServices } from '@backstage/backend-test-utils'; const getEntitiesMock = jest.fn(); jest.mock('@backstage/catalog-client', () => { @@ -104,6 +105,7 @@ const defaultEntityListResponse: GetEntitiesResponse = { const handlerContext = { discovery, logger: getVoidLogger(), + auth: mockServices.auth(), config: ConfigReader.fromConfigs([]), tokenManager: ServerTokenManager.noop(), }; diff --git a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityOwnershipFactRetriever.ts b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityOwnershipFactRetriever.ts index 974f1d30cd..367bf42c09 100644 --- a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityOwnershipFactRetriever.ts +++ b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityOwnershipFactRetriever.ts @@ -45,12 +45,11 @@ export const entityOwnershipFactRetriever: FactRetriever = { description: 'The spec.owner field is set and refers to a group', }, }, - handler: async ({ - discovery, - entityFilter, - tokenManager, - }: FactRetrieverContext) => { - const { token } = await tokenManager.getToken(); + handler: async ({ discovery, entityFilter, auth }: FactRetrieverContext) => { + const { token } = await auth.getPluginRequestToken({ + onBehalfOf: await auth.getOwnServiceCredentials(), + targetPluginId: 'catalog', + }); const catalogClient = new CatalogClient({ discoveryApi: discovery, }); diff --git a/plugins/tech-insights-backend/src/service/fact/factRetrievers/techdocsFactRetriever.test.ts b/plugins/tech-insights-backend/src/service/fact/factRetrievers/techdocsFactRetriever.test.ts index 0c70f6c9f1..37f82cb4dd 100644 --- a/plugins/tech-insights-backend/src/service/fact/factRetrievers/techdocsFactRetriever.test.ts +++ b/plugins/tech-insights-backend/src/service/fact/factRetrievers/techdocsFactRetriever.test.ts @@ -23,6 +23,7 @@ import { } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { GetEntitiesResponse } from '@backstage/catalog-client'; +import { mockServices } from '@backstage/backend-test-utils'; const getEntitiesMock = jest.fn(); jest.mock('@backstage/catalog-client', () => { @@ -104,6 +105,7 @@ const defaultEntityListResponse: GetEntitiesResponse = { const handlerContext = { discovery, logger: getVoidLogger(), + auth: mockServices.auth(), config: ConfigReader.fromConfigs([]), tokenManager: ServerTokenManager.noop(), }; diff --git a/plugins/tech-insights-backend/src/service/fact/factRetrievers/techdocsFactRetriever.ts b/plugins/tech-insights-backend/src/service/fact/factRetrievers/techdocsFactRetriever.ts index bd07bb3ecc..24f2fc4d6f 100644 --- a/plugins/tech-insights-backend/src/service/fact/factRetrievers/techdocsFactRetriever.ts +++ b/plugins/tech-insights-backend/src/service/fact/factRetrievers/techdocsFactRetriever.ts @@ -43,12 +43,11 @@ export const techdocsFactRetriever: FactRetriever = { description: 'The entity has a TechDocs reference annotation', }, }, - handler: async ({ - discovery, - entityFilter, - tokenManager, - }: FactRetrieverContext) => { - const { token } = await tokenManager.getToken(); + handler: async ({ discovery, entityFilter, auth }: FactRetrieverContext) => { + const { token } = await auth.getPluginRequestToken({ + onBehalfOf: await auth.getOwnServiceCredentials(), + targetPluginId: 'catalog', + }); const catalogClient = new CatalogClient({ discoveryApi: discovery, }); diff --git a/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.ts b/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.ts index 4f49e0031b..7b6f04b183 100644 --- a/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.ts +++ b/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.ts @@ -25,6 +25,7 @@ import { PluginDatabaseManager, PluginEndpointDiscovery, TokenManager, + createLegacyAuthAdapters, } from '@backstage/backend-common'; import { FactChecker, @@ -37,6 +38,7 @@ import { import { initializePersistenceContext } from './persistence'; import { CheckResult } from '@backstage/plugin-tech-insights-common'; import { PluginTaskScheduler } from '@backstage/backend-tasks'; +import { AuthService } from '@backstage/backend-plugin-api'; /** * @public @@ -82,6 +84,7 @@ export interface TechInsightsOptions< database: PluginDatabaseManager; scheduler: PluginTaskScheduler; tokenManager: TokenManager; + auth?: AuthService; } /** @@ -147,6 +150,12 @@ export const buildTechInsightsContext = async < logger, })); + const { auth } = createLegacyAuthAdapters({ + auth: options.auth, + tokenManager, + discovery, + }); + const factRetrieverEngine = await DefaultFactRetrieverEngine.create({ scheduler, repository: persistenceContext.techInsightsStore, @@ -156,6 +165,7 @@ export const buildTechInsightsContext = async < discovery, logger, tokenManager, + auth, }, }); diff --git a/plugins/tech-insights-node/CHANGELOG.md b/plugins/tech-insights-node/CHANGELOG.md index 8cf6cf08c2..0775f196c5 100644 --- a/plugins/tech-insights-node/CHANGELOG.md +++ b/plugins/tech-insights-node/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-tech-insights-node +## 0.5.0-next.0 + +### Minor Changes + +- d621468: **BREAKING**: The `FactRetrieverContext` type now contains an additional `auth` field. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.4.16 ### Patch Changes diff --git a/plugins/tech-insights-node/api-report.md b/plugins/tech-insights-node/api-report.md index 13056b5eaa..bf4ee10dea 100644 --- a/plugins/tech-insights-node/api-report.md +++ b/plugins/tech-insights-node/api-report.md @@ -3,6 +3,7 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { AuthService } from '@backstage/backend-plugin-api'; import { CheckResult } from '@backstage/plugin-tech-insights-common'; import { Config } from '@backstage/config'; import { DateTime } from 'luxon'; @@ -66,6 +67,7 @@ export type FactRetrieverContext = { discovery: PluginEndpointDiscovery; logger: Logger; tokenManager: TokenManager; + auth: AuthService; entityFilter?: | Record[] | Record; diff --git a/plugins/tech-insights-node/package.json b/plugins/tech-insights-node/package.json index b94be91a80..80ec88e839 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.16", + "version": "0.5.0-next.0", "backstage": { "role": "node-library" }, diff --git a/plugins/tech-insights-node/src/facts.ts b/plugins/tech-insights-node/src/facts.ts index 9257ea789e..6d40bf615d 100644 --- a/plugins/tech-insights-node/src/facts.ts +++ b/plugins/tech-insights-node/src/facts.ts @@ -22,6 +22,7 @@ import { } from '@backstage/backend-common'; import { FactSchema } from '@backstage/plugin-tech-insights-common'; import { Logger } from 'winston'; +import { AuthService } from '@backstage/backend-plugin-api'; /** * A container for facts. The shape of the fact records needs to correspond to the FactSchema with same `ref` value. @@ -92,6 +93,7 @@ export type FactRetrieverContext = { discovery: PluginEndpointDiscovery; logger: Logger; tokenManager: TokenManager; + auth: AuthService; entityFilter?: | Record[] | Record; diff --git a/plugins/tech-insights/CHANGELOG.md b/plugins/tech-insights/CHANGELOG.md index 806d5cfc14..158f01e0b6 100644 --- a/plugins/tech-insights/CHANGELOG.md +++ b/plugins/tech-insights/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-tech-insights +## 0.3.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.3.22 ### Patch Changes diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index e2cf61f6b3..1706469c5d 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.22", + "version": "0.3.23-next.0", "backstage": { "role": "frontend-plugin" }, diff --git a/plugins/tech-radar/CHANGELOG.md b/plugins/tech-radar/CHANGELOG.md index 975ed82524..9e71c9cb4a 100644 --- a/plugins/tech-radar/CHANGELOG.md +++ b/plugins/tech-radar/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-tech-radar +## 0.6.14-next.0 + +### Patch Changes + +- a2327ac: Fixed an issue with the "moved in direction" table header cell getting squished and becoming unreadable if a timeline description is too long +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + ## 0.6.13 ### Patch Changes diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index dc329bf37e..48eee12ed3 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-radar", - "version": "0.6.13", + "version": "0.6.14-next.0", "description": "A Backstage plugin that lets you display a Tech Radar for your organization", "backstage": { "role": "frontend-plugin" diff --git a/plugins/techdocs-addons-test-utils/CHANGELOG.md b/plugins/techdocs-addons-test-utils/CHANGELOG.md index a9aa835d6c..9bb4dd054d 100644 --- a/plugins/techdocs-addons-test-utils/CHANGELOG.md +++ b/plugins/techdocs-addons-test-utils/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-techdocs-addons-test-utils +## 1.0.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-catalog@1.17.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/plugin-techdocs@1.10.1-next.0 + - @backstage/test-utils@1.5.1-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/plugin-techdocs-react@1.1.17-next.0 + - @backstage/core-app-api@1.12.1-next.0 + ## 1.0.27 ### Patch Changes diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index 27d58a93ed..1c5ea7f7c3 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.27", + "version": "1.0.28-next.0", "backstage": { "role": "web-library" }, diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index e9826e3efa..61339aa39d 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-techdocs-backend +## 1.9.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-techdocs-node@1.11.5-next.0 + - @backstage/plugin-permission-common@0.7.13-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.17-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/plugin-catalog-common@1.0.22-next.0 + ## 1.9.3 ### Patch Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index 3543dcf5cb..5fc3408931 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-backend", - "version": "1.9.3", + "version": "1.9.6-next.0", "description": "The Backstage backend plugin that renders technical documentation for your components", "backstage": { "role": "backend-plugin" diff --git a/plugins/techdocs-module-addons-contrib/CHANGELOG.md b/plugins/techdocs-module-addons-contrib/CHANGELOG.md index f40a972fd5..3fb94974c4 100644 --- a/plugins/techdocs-module-addons-contrib/CHANGELOG.md +++ b/plugins/techdocs-module-addons-contrib/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-techdocs-module-addons-contrib +## 1.1.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/plugin-techdocs-react@1.1.17-next.0 + ## 1.1.5 ### Patch Changes diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 85e47fea06..3f29feabc9 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-module-addons-contrib", - "version": "1.1.5", + "version": "1.1.6-next.0", "description": "Plugin module for contributed TechDocs Addons", "backstage": { "role": "frontend-plugin-module" diff --git a/plugins/techdocs-node/CHANGELOG.md b/plugins/techdocs-node/CHANGELOG.md index f66baf3e8b..5509ecbddc 100644 --- a/plugins/techdocs-node/CHANGELOG.md +++ b/plugins/techdocs-node/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-techdocs-node +## 1.11.5-next.0 + +### Patch Changes + +- 5b4f565: Fix handling of default plugins that have configuration +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/integration-aws-node@0.1.10-next.0 + ## 1.11.2 ### Patch Changes diff --git a/plugins/techdocs-node/package.json b/plugins/techdocs-node/package.json index 083e595ec9..b368b2fd6d 100644 --- a/plugins/techdocs-node/package.json +++ b/plugins/techdocs-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-node", - "version": "1.11.2", + "version": "1.11.5-next.0", "description": "Common node.js functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", "backstage": { "role": "node-library" diff --git a/plugins/techdocs-react/CHANGELOG.md b/plugins/techdocs-react/CHANGELOG.md index 8d8df2b8d5..f015597280 100644 --- a/plugins/techdocs-react/CHANGELOG.md +++ b/plugins/techdocs-react/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-techdocs-react +## 1.1.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.14.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/version-bridge@1.0.7 + ## 1.1.16 ### Patch Changes diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index e1f50f629d..7e211405fb 100644 --- a/plugins/techdocs-react/package.json +++ b/plugins/techdocs-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-react", - "version": "1.1.16", + "version": "1.1.17-next.0", "description": "Shared frontend utilities for TechDocs and Addons", "backstage": { "role": "web-library" diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 884a639d0e..41fed29cd1 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-techdocs +## 1.10.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/integration-react@1.1.25-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/plugin-search-common@1.2.11-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/integration@1.9.1-next.0 + - @backstage/plugin-search-react@1.7.7-next.0 + - @backstage/plugin-techdocs-react@1.1.17-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + ## 1.10.0 ### Minor Changes diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 47ff100ab0..e3abb21b03 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs", - "version": "1.10.0", + "version": "1.10.1-next.0", "description": "The Backstage plugin that renders technical documentation for your components", "backstage": { "role": "frontend-plugin" diff --git a/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.test.tsx b/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.test.tsx index 7ebdd6c340..15444fca9e 100644 --- a/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.test.tsx +++ b/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.test.tsx @@ -15,8 +15,8 @@ */ import React from 'react'; -import { render } from '@testing-library/react'; import { TechDocsSearchResultListItem } from './TechDocsSearchResultListItem'; +import { renderInTestApp } from '@backstage/test-utils'; // Using canvas to render text.. jest.mock('react-text-truncate', () => { @@ -46,7 +46,7 @@ const validResultWithTitle = { describe('TechDocsSearchResultListItem test', () => { it('should render search doc passed in', async () => { - const { findByText } = render( + const { findByText } = await renderInTestApp( , ); @@ -61,7 +61,7 @@ describe('TechDocsSearchResultListItem test', () => { }); it('should use title if defined', async () => { - const { findByText } = render( + const { findByText } = await renderInTestApp( { }); it('should use entity title if defined', async () => { - const { findByText } = render( + const { findByText } = await renderInTestApp( , ); diff --git a/plugins/todo-backend/CHANGELOG.md b/plugins/todo-backend/CHANGELOG.md index 6c82800c63..d365b145a8 100644 --- a/plugins/todo-backend/CHANGELOG.md +++ b/plugins/todo-backend/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-todo-backend +## 0.3.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/repo-tools@0.6.3-next.0 + - @backstage/plugin-catalog-node@1.8.0-next.0 + - @backstage/backend-openapi-utils@0.1.6-next.0 + - @backstage/catalog-client@1.6.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/integration@1.9.1-next.0 + ## 0.3.8 ### Patch Changes diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index 9d4dcc7c7e..7ddf484089 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.3.8", + "version": "0.3.11-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/todo/CHANGELOG.md b/plugins/todo/CHANGELOG.md index 85bdd7c27f..c083736e94 100644 --- a/plugins/todo/CHANGELOG.md +++ b/plugins/todo/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-todo +## 0.2.35-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.2.34 ### Patch Changes diff --git a/plugins/todo/package.json b/plugins/todo/package.json index 0ec887afa1..39327382fb 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-todo", - "version": "0.2.34", + "version": "0.2.35-next.0", "description": "A Backstage plugin that lets you browse TODO comments in your source code", "backstage": { "role": "frontend-plugin" diff --git a/plugins/todo/src/components/TodoList/TodoList.test.tsx b/plugins/todo/src/components/TodoList/TodoList.test.tsx index 15d4334610..872538c5b7 100644 --- a/plugins/todo/src/components/TodoList/TodoList.test.tsx +++ b/plugins/todo/src/components/TodoList/TodoList.test.tsx @@ -16,7 +16,7 @@ import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { renderWithEffects, TestApiProvider } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { TodoApi, todoApiRef } from '../../api'; import { TodoList } from './TodoList'; @@ -43,7 +43,7 @@ describe('TodoList', () => { kind: 'MockKind', } as Entity; - const rendered = await renderWithEffects( + const rendered = await renderInTestApp( diff --git a/plugins/user-settings-backend/CHANGELOG.md b/plugins/user-settings-backend/CHANGELOG.md index 83ef42c444..3002c9ca79 100644 --- a/plugins/user-settings-backend/CHANGELOG.md +++ b/plugins/user-settings-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-user-settings-backend +## 0.2.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/plugin-auth-node@0.4.8-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/types@1.1.1 + ## 0.2.9 ### Patch Changes diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index 05da152f7f..27e9dde760 100644 --- a/plugins/user-settings-backend/package.json +++ b/plugins/user-settings-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-user-settings-backend", - "version": "0.2.9", + "version": "0.2.12-next.0", "description": "The Backstage backend plugin to manage user settings", "backstage": { "role": "backend-plugin" diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index c78e407f4c..906764c842 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-user-settings +## 0.8.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/theme@0.5.2-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + - @backstage/frontend-plugin-api@0.6.1-next.0 + - @backstage/core-app-api@1.12.1-next.0 + - @backstage/core-compat-api@0.2.1-next.0 + - @backstage/types@1.1.1 + ## 0.8.1 ### Patch Changes diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 2d5a8b118e..f515ddabe4 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-user-settings", - "version": "0.8.1", + "version": "0.8.2-next.0", "description": "A Backstage plugin that provides a settings page", "backstage": { "role": "frontend-plugin" diff --git a/plugins/vault-backend/CHANGELOG.md b/plugins/vault-backend/CHANGELOG.md index 1666a64e99..7c9269d944 100644 --- a/plugins/vault-backend/CHANGELOG.md +++ b/plugins/vault-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-vault-backend +## 0.4.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.21.3-next.0 + - @backstage/errors@1.2.4-next.0 + - @backstage/backend-plugin-api@0.6.13-next.0 + - @backstage/backend-tasks@0.5.18-next.0 + - @backstage/config@1.1.2-next.0 + - @backstage/plugin-vault-node@0.1.6-next.0 + ## 0.4.3 ### Patch Changes diff --git a/plugins/vault-backend/package.json b/plugins/vault-backend/package.json index 8f333003d4..655dbca05c 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.4.3", + "version": "0.4.6-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/vault-node/CHANGELOG.md b/plugins/vault-node/CHANGELOG.md index 85a616ccaf..06ed6c89f3 100644 --- a/plugins/vault-node/CHANGELOG.md +++ b/plugins/vault-node/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-vault-node +## 0.1.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.13-next.0 + ## 0.1.3 ### Patch Changes diff --git a/plugins/vault-node/package.json b/plugins/vault-node/package.json index c4043d44d1..a205c17208 100644 --- a/plugins/vault-node/package.json +++ b/plugins/vault-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-vault-node", - "version": "0.1.3", + "version": "0.1.6-next.0", "description": "Node.js library for the vault plugin", "backstage": { "role": "node-library" diff --git a/plugins/vault/CHANGELOG.md b/plugins/vault/CHANGELOG.md index 33c127cf41..0a803b2f81 100644 --- a/plugins/vault/CHANGELOG.md +++ b/plugins/vault/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-vault +## 0.1.26-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/plugin-catalog-react@1.10.1-next.0 + - @backstage/catalog-model@1.4.5-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.1.25 ### Patch Changes diff --git a/plugins/vault/package.json b/plugins/vault/package.json index d49330fe97..32ff0ea526 100644 --- a/plugins/vault/package.json +++ b/plugins/vault/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-vault", - "version": "0.1.25", + "version": "0.1.26-next.0", "description": "A Backstage plugin that integrates towards Vault", "backstage": { "role": "frontend-plugin" diff --git a/plugins/vault/src/components/EntityVaultCard/EntityVaultCard.test.tsx b/plugins/vault/src/components/EntityVaultCard/EntityVaultCard.test.tsx index ec62ea8757..ccf99bb259 100644 --- a/plugins/vault/src/components/EntityVaultCard/EntityVaultCard.test.tsx +++ b/plugins/vault/src/components/EntityVaultCard/EntityVaultCard.test.tsx @@ -16,9 +16,12 @@ import React from 'react'; import { setupServer } from 'msw/node'; -import { setupRequestMockHandlers } from '@backstage/test-utils'; +import { + renderInTestApp, + setupRequestMockHandlers, +} from '@backstage/test-utils'; import { ComponentEntity } from '@backstage/catalog-model'; -import { render, waitFor } from '@testing-library/react'; +import { waitFor } from '@testing-library/react'; import { EntityVaultCard } from './EntityVaultCard'; import { EntityProvider } from '@backstage/plugin-catalog-react'; @@ -40,7 +43,7 @@ describe('EntityVaultCard', () => { }; it('should render missing entity annotation', async () => { - const rendered = render( + const rendered = await renderInTestApp( , diff --git a/plugins/xcmetrics/CHANGELOG.md b/plugins/xcmetrics/CHANGELOG.md index b1f71c6b31..38289e87df 100644 --- a/plugins/xcmetrics/CHANGELOG.md +++ b/plugins/xcmetrics/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-xcmetrics +## 0.2.49-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.4-next.0 + - @backstage/core-components@0.14.1-next.0 + - @backstage/core-plugin-api@1.9.1-next.0 + ## 0.2.48 ### Patch Changes diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index e0063b8d05..dc0f00d581 100644 --- a/plugins/xcmetrics/package.json +++ b/plugins/xcmetrics/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-xcmetrics", - "version": "0.2.48", + "version": "0.2.49-next.0", "description": "A Backstage plugin that shows XCode build metrics for your components", "backstage": { "role": "frontend-plugin" diff --git a/storybook/.storybook/apis.js b/storybook/.storybook/apis.js index 37cc8eb605..905c5f2dc8 100644 --- a/storybook/.storybook/apis.js +++ b/storybook/.storybook/apis.js @@ -24,6 +24,9 @@ import { featureFlagsApiRef, } from '@backstage/core-plugin-api'; +import { translationApiRef } from '@backstage/core-plugin-api/alpha'; +import { MockTranslationApi } from '@backstage/test-utils/alpha'; + const configApi = new ConfigReader({}); const featureFlagsApi = new LocalStorageFeatureFlags(); const alertApi = new AlertApiForwarder(); @@ -55,6 +58,7 @@ const oktaAuthApi = OktaAuth.create({ basePath: '/auth/', oauthRequestApi, }); +const translationApi = MockTranslationApi.create(); export const apis = [ [configApiRef, configApi], @@ -67,4 +71,5 @@ export const apis = [ [githubAuthApiRef, githubAuthApi], [gitlabAuthApiRef, gitlabAuthApi], [oktaAuthApiRef, oktaAuthApi], + [translationApiRef, translationApi], ]; diff --git a/yarn.lock b/yarn.lock index 500419db19..1693b3c283 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3483,6 +3483,7 @@ __metadata: "@backstage/types": "workspace:^" "@types/supertest": ^2.0.8 better-sqlite3: ^9.0.0 + cookie: ^0.6.0 express: ^4.17.1 fs-extra: ^11.0.0 knex: ^3.0.0 @@ -3498,6 +3499,18 @@ __metadata: languageName: unknown linkType: soft +"@backstage/catalog-client@npm:^1.6.0": + version: 1.6.0 + resolution: "@backstage/catalog-client@npm:1.6.0" + dependencies: + "@backstage/catalog-model": ^1.4.4 + "@backstage/errors": ^1.2.3 + cross-fetch: ^4.0.0 + uri-template: ^2.0.0 + checksum: f9e8117145a63e10c8a7643ebafa78b416724d495efa77ac5d9069f32bc9353b63602e6744e63329381ea3a6e24fea359c5b4e82b1a698cd7743d266049275d2 + 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" @@ -3511,7 +3524,19 @@ __metadata: languageName: unknown linkType: soft -"@backstage/catalog-model@^1.4.3, @backstage/catalog-model@workspace:^, @backstage/catalog-model@workspace:packages/catalog-model": +"@backstage/catalog-model@npm:^1.4.3, @backstage/catalog-model@npm:^1.4.4": + version: 1.4.4 + resolution: "@backstage/catalog-model@npm:1.4.4" + dependencies: + "@backstage/errors": ^1.2.3 + "@backstage/types": ^1.1.1 + ajv: ^8.10.0 + lodash: ^4.17.21 + checksum: c04762fe638bd417dc0959a60d9e5bac47502046fed28ebba66e53e4da36a87ed9e90b4132d8a3d0f23a8e71bec4b1d8f4fdc3a32a7277ef5db2701e5f7a831a + languageName: node + linkType: hard + +"@backstage/catalog-model@workspace:^, @backstage/catalog-model@workspace:packages/catalog-model": version: 0.0.0-use.local resolution: "@backstage/catalog-model@workspace:packages/catalog-model" dependencies: @@ -3759,7 +3784,18 @@ __metadata: languageName: unknown linkType: soft -"@backstage/config@^1.1.1, @backstage/config@workspace:^, @backstage/config@workspace:packages/config": +"@backstage/config@npm:^1.1.1": + version: 1.1.1 + resolution: "@backstage/config@npm:1.1.1" + dependencies: + "@backstage/errors": ^1.2.3 + "@backstage/types": ^1.1.1 + lodash: ^4.17.21 + checksum: 60dec0799a97ef7d99dc43076862b7914bd4b0390d6de6300148cc635ab218c21a3df1bc4fe98f7a49a89de9950c1f562ae29ce9324f93acfd9bd31104e751ef + languageName: node + linkType: hard + +"@backstage/config@workspace:^, @backstage/config@workspace:packages/config": version: 0.0.0-use.local resolution: "@backstage/config@workspace:packages/config" dependencies: @@ -3883,6 +3919,57 @@ __metadata: languageName: node linkType: hard +"@backstage/core-components@npm:^0.14.0": + version: 0.14.0 + resolution: "@backstage/core-components@npm:0.14.0" + dependencies: + "@backstage/config": ^1.1.1 + "@backstage/core-plugin-api": ^1.9.0 + "@backstage/errors": ^1.2.3 + "@backstage/theme": ^0.5.1 + "@backstage/version-bridge": ^1.0.7 + "@date-io/core": ^1.3.13 + "@material-table/core": ^3.1.0 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": 4.0.0-alpha.61 + "@react-hookz/web": ^24.0.0 + "@types/react": ^16.13.1 || ^17.0.0 || ^18.0.0 + "@types/react-sparklines": ^1.7.0 + "@types/react-text-truncate": ^0.14.0 + ansi-regex: ^6.0.1 + classnames: ^2.2.6 + d3-selection: ^3.0.0 + d3-shape: ^3.0.0 + d3-zoom: ^3.0.0 + dagre: ^0.8.5 + linkify-react: 4.1.3 + linkifyjs: 4.1.3 + lodash: ^4.17.21 + pluralize: ^8.0.0 + qs: ^6.9.4 + rc-progress: 3.5.1 + react-helmet: 6.1.0 + react-hook-form: ^7.12.2 + react-idle-timer: 5.6.2 + react-markdown: ^8.0.0 + react-sparklines: ^1.7.0 + react-syntax-highlighter: ^15.4.5 + react-text-truncate: ^0.19.0 + react-use: ^17.3.2 + react-virtualized-auto-sizer: ^1.0.11 + react-window: ^1.8.6 + remark-gfm: ^3.0.1 + zen-observable: ^0.10.0 + zod: ^3.22.4 + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: b6d48b71976361c13d8928e743699baad5788c619bd6e9ca536fbf8edafe1828b16002edc20207ddfce0858b760adf2748d4584beed7daa375afa8eefd827592 + languageName: node + linkType: hard + "@backstage/core-components@workspace:^, @backstage/core-components@workspace:packages/core-components": version: 0.0.0-use.local resolution: "@backstage/core-components@workspace:packages/core-components" @@ -3956,7 +4043,25 @@ __metadata: languageName: unknown linkType: soft -"@backstage/core-plugin-api@^1.8.0, @backstage/core-plugin-api@^1.8.2, @backstage/core-plugin-api@workspace:^, @backstage/core-plugin-api@workspace:packages/core-plugin-api": +"@backstage/core-plugin-api@npm:^1.8.0, @backstage/core-plugin-api@npm:^1.8.2, @backstage/core-plugin-api@npm:^1.9.0": + version: 1.9.0 + resolution: "@backstage/core-plugin-api@npm:1.9.0" + dependencies: + "@backstage/config": ^1.1.1 + "@backstage/errors": ^1.2.3 + "@backstage/types": ^1.1.1 + "@backstage/version-bridge": ^1.0.7 + "@types/react": ^16.13.1 || ^17.0.0 || ^18.0.0 + history: ^5.0.0 + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: 843e1068baeb0b91f2355a5fd22a06a847313da266d1bd9c95b10ac17891672abc6a17993628206e1f2ae63d817934b8729c7d87eadb9efae7be8b0df5a015da + languageName: node + linkType: hard + +"@backstage/core-plugin-api@workspace:^, @backstage/core-plugin-api@workspace:packages/core-plugin-api": version: 0.0.0-use.local resolution: "@backstage/core-plugin-api@workspace:packages/core-plugin-api" dependencies: @@ -4055,7 +4160,17 @@ __metadata: languageName: unknown linkType: soft -"@backstage/errors@^1.2.3, @backstage/errors@workspace:^, @backstage/errors@workspace:packages/errors": +"@backstage/errors@npm:^1.2.3": + version: 1.2.3 + resolution: "@backstage/errors@npm:1.2.3" + dependencies: + "@backstage/types": ^1.1.1 + serialize-error: ^8.0.1 + checksum: 00e367ed9c47404d391d3c4125f5e279fe99393734f86ec0b0102cbea2573c9e9a4a58ca6a09c159b4b543bb3adabe81554a5af6d4d12ee7f45c92ed404705d9 + languageName: node + linkType: hard + +"@backstage/errors@workspace:^, @backstage/errors@workspace:packages/errors": version: 0.0.0-use.local resolution: "@backstage/errors@workspace:packages/errors" dependencies: @@ -4103,6 +4218,26 @@ __metadata: languageName: unknown linkType: soft +"@backstage/frontend-plugin-api@npm:^0.6.0": + version: 0.6.0 + resolution: "@backstage/frontend-plugin-api@npm:0.6.0" + dependencies: + "@backstage/core-components": ^0.14.0 + "@backstage/core-plugin-api": ^1.9.0 + "@backstage/types": ^1.1.1 + "@backstage/version-bridge": ^1.0.7 + "@material-ui/core": ^4.12.4 + "@types/react": ^16.13.1 || ^17.0.0 || ^18.0.0 + lodash: ^4.17.21 + zod: ^3.22.4 + zod-to-json-schema: ^3.21.4 + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: b63395c3cc5d3c2e5eec4acca95d6ae6edf22ecee0ef37a82b6ea6133b9f74a2dcf18e66a4b233cb65057ae764eb9464039b3cc09ec9035075850b3d9267fd6e + languageName: node + linkType: hard + "@backstage/frontend-plugin-api@workspace:^, @backstage/frontend-plugin-api@workspace:packages/frontend-plugin-api": version: 0.0.0-use.local resolution: "@backstage/frontend-plugin-api@workspace:packages/frontend-plugin-api" @@ -4166,7 +4301,25 @@ __metadata: languageName: unknown linkType: soft -"@backstage/integration-react@^1.1.21, @backstage/integration-react@workspace:^, @backstage/integration-react@workspace:packages/integration-react": +"@backstage/integration-react@npm:^1.1.21, @backstage/integration-react@npm:^1.1.24": + version: 1.1.24 + resolution: "@backstage/integration-react@npm:1.1.24" + dependencies: + "@backstage/config": ^1.1.1 + "@backstage/core-plugin-api": ^1.9.0 + "@backstage/integration": ^1.9.0 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@types/react": ^16.13.1 || ^17.0.0 + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: 4a1b35e5dc6707b637b980d332a0a21440e2de50694148439789feeaf891dedf3141b5da833a409a559efe85a7e9b9c77a02e567abc6d9e0740b81cead905c55 + languageName: node + linkType: hard + +"@backstage/integration-react@workspace:^, @backstage/integration-react@workspace:packages/integration-react": version: 0.0.0-use.local resolution: "@backstage/integration-react@workspace:packages/integration-react" dependencies: @@ -4190,6 +4343,23 @@ __metadata: languageName: unknown linkType: soft +"@backstage/integration@npm:^1.9.0": + version: 1.9.0 + resolution: "@backstage/integration@npm:1.9.0" + dependencies: + "@azure/identity": ^4.0.0 + "@backstage/config": ^1.1.1 + "@backstage/errors": ^1.2.3 + "@octokit/auth-app": ^4.0.0 + "@octokit/rest": ^19.0.3 + cross-fetch: ^4.0.0 + git-url-parse: ^14.0.0 + lodash: ^4.17.21 + luxon: ^3.0.0 + checksum: 22427a0bee3e14c7caca7be6fe8daad99413ea798ae0aad349d9c96e0a3e1273f9fd42c89f776dde45287136b56c614c29bdd3d278e43bb1bc58a86c31c610c8 + languageName: node + linkType: hard + "@backstage/integration@workspace:^, @backstage/integration@workspace:packages/integration": version: 0.0.0-use.local resolution: "@backstage/integration@workspace:packages/integration" @@ -4271,9 +4441,7 @@ __metadata: "@testing-library/react": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 || ^18.0.0 lodash: ^4.17.21 - react-markdown: ^8.0.0 react-use: ^17.2.4 - remark-gfm: ^3.0.1 peerDependencies: react: ^16.13.1 || ^17.0.0 || ^18.0.0 react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 @@ -4682,6 +4850,23 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-auth-backend-module-guest-provider@workspace:^, @backstage/plugin-auth-backend-module-guest-provider@workspace:plugins/auth-backend-module-guest-provider": + version: 0.0.0-use.local + resolution: "@backstage/plugin-auth-backend-module-guest-provider@workspace:plugins/auth-backend-module-guest-provider" + dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" + "@backstage/catalog-model": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/plugin-auth-node": "workspace:^" + express: ^4.18.2 + passport-oauth2: ^1.7.0 + languageName: unknown + linkType: soft + "@backstage/plugin-auth-backend-module-microsoft-provider@workspace:^, @backstage/plugin-auth-backend-module-microsoft-provider@workspace:plugins/auth-backend-module-microsoft-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-microsoft-provider@workspace:plugins/auth-backend-module-microsoft-provider" @@ -5656,7 +5841,18 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-common@^1.0.20, @backstage/plugin-catalog-common@workspace:^, @backstage/plugin-catalog-common@workspace:plugins/catalog-common": +"@backstage/plugin-catalog-common@npm:^1.0.20, @backstage/plugin-catalog-common@npm:^1.0.21": + version: 1.0.21 + resolution: "@backstage/plugin-catalog-common@npm:1.0.21" + dependencies: + "@backstage/catalog-model": ^1.4.4 + "@backstage/plugin-permission-common": ^0.7.12 + "@backstage/plugin-search-common": ^1.2.10 + checksum: 06570e20dddaf80f61d49d55ce1aa4a8213969742975902dd21f34cc6e37b0b2bc6e4d05b373425a16329a26bf682fd675ad77dcc60966bac0f4fa1a29e5bb59 + languageName: node + linkType: hard + +"@backstage/plugin-catalog-common@workspace:^, @backstage/plugin-catalog-common@workspace:plugins/catalog-common": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-common@workspace:plugins/catalog-common" dependencies: @@ -5764,7 +5960,43 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-react@^1.9.1, @backstage/plugin-catalog-react@^1.9.3, @backstage/plugin-catalog-react@workspace:^, @backstage/plugin-catalog-react@workspace:plugins/catalog-react": +"@backstage/plugin-catalog-react@npm:^1.9.1, @backstage/plugin-catalog-react@npm:^1.9.3": + version: 1.10.0 + resolution: "@backstage/plugin-catalog-react@npm:1.10.0" + dependencies: + "@backstage/catalog-client": ^1.6.0 + "@backstage/catalog-model": ^1.4.4 + "@backstage/core-components": ^0.14.0 + "@backstage/core-plugin-api": ^1.9.0 + "@backstage/errors": ^1.2.3 + "@backstage/frontend-plugin-api": ^0.6.0 + "@backstage/integration-react": ^1.1.24 + "@backstage/plugin-catalog-common": ^1.0.21 + "@backstage/plugin-permission-common": ^0.7.12 + "@backstage/plugin-permission-react": ^0.4.20 + "@backstage/types": ^1.1.1 + "@backstage/version-bridge": ^1.0.7 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": 4.0.0-alpha.61 + "@react-hookz/web": ^24.0.0 + "@types/react": ^16.13.1 || ^17.0.0 || ^18.0.0 + classnames: ^2.2.6 + lodash: ^4.17.21 + material-ui-popup-state: ^1.9.3 + qs: ^6.9.4 + react-use: ^17.2.4 + yaml: ^2.0.0 + zen-observable: ^0.10.0 + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: b1be2976d20c116fb94662bb944c6713246d944f0a2bfd0b911c58d76278f722b8bb50e400318e087c4f80b60b8fba95086521348828d464add298bdc8808751 + languageName: node + linkType: hard + +"@backstage/plugin-catalog-react@workspace:^, @backstage/plugin-catalog-react@workspace:plugins/catalog-react": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-react@workspace:plugins/catalog-react" dependencies: @@ -6185,6 +6417,7 @@ __metadata: dependencies: "@backstage/backend-common": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/cli-common": "workspace:^" "@backstage/config": "workspace:^" @@ -6705,6 +6938,7 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" "@backstage/integration": "workspace:^" + "@backstage/test-utils": "workspace:^" "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 @@ -6956,7 +7190,25 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-home-react@^0.1.5, @backstage/plugin-home-react@workspace:^, @backstage/plugin-home-react@workspace:plugins/home-react": +"@backstage/plugin-home-react@npm:^0.1.5": + version: 0.1.8 + resolution: "@backstage/plugin-home-react@npm:0.1.8" + dependencies: + "@backstage/core-components": ^0.14.0 + "@backstage/core-plugin-api": ^1.9.0 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@rjsf/utils": 5.17.0 + "@types/react": ^16.13.1 || ^17.0.0 + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: 375a9523fb6fdb6f732c1b453a878f1e18582db4146daee0fe26a26579982a7955c16deefa3c65c11cf92c8c76aac8a5c1949dce10ac2ad16bde6abf6073f0d0 + languageName: node + linkType: hard + +"@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: @@ -7697,6 +7949,7 @@ __metadata: "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 + lodash: ^4.17.21 msw: ^1.0.0 react-relative-time: ^0.0.9 react-use: ^17.2.4 @@ -7915,6 +8168,7 @@ __metadata: dependencies: "@backstage/backend-common": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" @@ -7937,6 +8191,20 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-permission-common@npm:^0.7.12": + version: 0.7.12 + resolution: "@backstage/plugin-permission-common@npm:0.7.12" + dependencies: + "@backstage/config": ^1.1.1 + "@backstage/errors": ^1.2.3 + "@backstage/types": ^1.1.1 + cross-fetch: ^4.0.0 + uuid: ^8.0.0 + zod: ^3.22.4 + checksum: 0535539348e59dde0555c54722f1d6ae3f951f8b900c27b65cf94aa10f57a705b2dad756eca673edeebafaca139ff8b1e8b93a4ca8f371a33c9544b3b0fba744 + languageName: node + linkType: hard + "@backstage/plugin-permission-common@workspace:^, @backstage/plugin-permission-common@workspace:plugins/permission-common": version: 0.0.0-use.local resolution: "@backstage/plugin-permission-common@workspace:plugins/permission-common" @@ -7975,6 +8243,23 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-permission-react@npm:^0.4.20": + version: 0.4.20 + resolution: "@backstage/plugin-permission-react@npm:0.4.20" + dependencies: + "@backstage/config": ^1.1.1 + "@backstage/core-plugin-api": ^1.9.0 + "@backstage/plugin-permission-common": ^0.7.12 + "@types/react": ^16.13.1 || ^17.0.0 || ^18.0.0 + swr: ^2.0.0 + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: f692173a8c5a3aa2351c8f84184bc7984a017791b1dd850333aac8b97b799dd9b0b7c37d36cdc4fa48ada615ecfa44b7150af74aecab33524481b47fe4e412c9 + languageName: node + linkType: hard + "@backstage/plugin-permission-react@workspace:^, @backstage/plugin-permission-react@workspace:plugins/permission-react": version: 0.0.0-use.local resolution: "@backstage/plugin-permission-react@workspace:plugins/permission-react" @@ -8192,6 +8477,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" azure-devops-node-api: ^12.0.0 yaml: ^2.0.0 languageName: unknown @@ -8209,6 +8495,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" fs-extra: ^11.2.0 msw: ^1.0.0 node-fetch: ^2.6.7 @@ -8228,6 +8515,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" fs-extra: ^11.2.0 msw: ^1.0.0 node-fetch: ^2.6.7 @@ -8249,6 +8537,7 @@ __metadata: "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "workspace:^" "@backstage/plugin-scaffolder-backend-module-bitbucket-server": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" fs-extra: ^11.2.0 msw: ^1.0.0 node-fetch: ^2.6.7 @@ -8268,6 +8557,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" fs-extra: ^11.2.0 git-url-parse: ^14.0.0 msw: ^1.0.0 @@ -8289,6 +8579,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" "@backstage/types": "workspace:^" "@types/command-exists": ^1.2.0 "@types/fs-extra": ^11.0.0 @@ -8311,6 +8602,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" msw: ^1.0.0 node-fetch: ^2.6.7 yaml: ^2.0.0 @@ -8329,6 +8621,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" msw: ^1.0.0 node-fetch: ^2.6.7 yaml: ^2.0.0 @@ -8347,6 +8640,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" "@octokit/webhooks": ^10.0.0 "@types/libsodium-wrappers": ^0.7.10 fs-extra: ^11.2.0 @@ -8373,6 +8667,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" "@gitbeaker/core": ^35.8.0 "@gitbeaker/node": ^35.8.0 "@gitbeaker/rest": ^39.25.0 @@ -8395,6 +8690,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" "@backstage/types": "workspace:^" "@types/command-exists": ^1.2.0 "@types/fs-extra": ^11.0.0 @@ -8415,6 +8711,7 @@ __metadata: "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" "@backstage/types": "workspace:^" msw: ^2.0.0 yaml: ^2.3.3 @@ -8429,6 +8726,7 @@ __metadata: "@backstage/backend-plugin-api": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" "@backstage/types": "workspace:^" winston: ^3.2.1 yeoman-environment: ^3.9.1 @@ -8464,6 +8762,7 @@ __metadata: "@backstage/plugin-scaffolder-backend-module-gitlab": "workspace:^" "@backstage/plugin-scaffolder-common": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" + "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" "@backstage/types": "workspace:^" "@types/express": ^4.17.6 "@types/fs-extra": ^11.0.0 @@ -8508,6 +8807,22 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-scaffolder-node-test-utils@workspace:^, @backstage/plugin-scaffolder-node-test-utils@workspace:plugins/scaffolder-node-test-utils": + version: 0.0.0-use.local + resolution: "@backstage/plugin-scaffolder-node-test-utils@workspace:plugins/scaffolder-node-test-utils" + dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/plugin-scaffolder-common": "workspace:^" + "@backstage/plugin-scaffolder-node": "workspace:^" + "@backstage/types": "workspace:^" + "@testing-library/jest-dom": ^6.0.0 + "@types/react": "*" + winston: ^3.2.1 + languageName: unknown + linkType: soft + "@backstage/plugin-scaffolder-node@workspace:^, @backstage/plugin-scaffolder-node@workspace:plugins/scaffolder-node": version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-node@workspace:plugins/scaffolder-node" @@ -8831,6 +9146,16 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-search-common@npm:^1.2.10": + version: 1.2.10 + resolution: "@backstage/plugin-search-common@npm:1.2.10" + dependencies: + "@backstage/plugin-permission-common": ^0.7.12 + "@backstage/types": ^1.1.1 + checksum: e4faae5e46e34c352c6ecb7e981b9efb5c34c62263275cd32e035fe17a77c929e20200a90230e70958496a89b83139ac7168e476b8c1f6497052f1c48d3e1bdd + languageName: node + linkType: hard + "@backstage/plugin-search-common@workspace:^, @backstage/plugin-search-common@workspace:plugins/search-common": version: 0.0.0-use.local resolution: "@backstage/plugin-search-common@workspace:plugins/search-common" @@ -9875,7 +10200,39 @@ __metadata: languageName: unknown linkType: soft -"@backstage/theme@^0.5.0, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": +"@backstage/theme@npm:^0.4.4": + version: 0.4.4 + resolution: "@backstage/theme@npm:0.4.4" + dependencies: + "@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 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + checksum: 562ce0f0fd07202b44971b55bba9c39cd13c91a65873034d2e68fb5833c0d9882c2fd967d6c779a8563618ce035ec159823c865b0163911b7004f1bfce3ce4a1 + languageName: node + linkType: hard + +"@backstage/theme@npm:^0.5.0, @backstage/theme@npm:^0.5.1": + version: 0.5.1 + resolution: "@backstage/theme@npm:0.5.1" + dependencies: + "@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 || ^18.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + checksum: 0c4d6481d6648962c19f8e08206ac2d459edf2fed85371452a5164eaeff4d0322517c99639f745a13bac2f7a8290c1c94e6cde79a1d85300b6c9b4e6b149972c + 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: @@ -9895,22 +10252,6 @@ __metadata: languageName: unknown linkType: soft -"@backstage/theme@npm:^0.4.4": - version: 0.4.4 - resolution: "@backstage/theme@npm:0.4.4" - dependencies: - "@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 || ^18.0.0 - react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 - checksum: 562ce0f0fd07202b44971b55bba9c39cd13c91a65873034d2e68fb5833c0d9882c2fd967d6c779a8563618ce035ec159823c865b0163911b7004f1bfce3ce4a1 - languageName: node - linkType: hard - "@backstage/types@^1.1.1, @backstage/types@workspace:^, @backstage/types@workspace:packages/types": version: 0.0.0-use.local resolution: "@backstage/types@workspace:packages/types" @@ -15464,6 +15805,21 @@ __metadata: languageName: node linkType: hard +"@rjsf/utils@npm:5.17.0": + version: 5.17.0 + resolution: "@rjsf/utils@npm:5.17.0" + dependencies: + json-schema-merge-allof: ^0.8.1 + jsonpointer: ^5.0.1 + lodash: ^4.17.21 + lodash-es: ^4.17.21 + react-is: ^18.2.0 + peerDependencies: + react: ^16.14.0 || >=17 + checksum: 01d0001f83083764a8552e009aa7df084621df9d1fc6ccdfad9d534513084421b1ad7494cab77b9b8205d680fd915f612d87800e20ab242e7066f33184c73d4f + languageName: node + linkType: hard + "@rjsf/utils@npm:5.17.1": version: 5.17.1 resolution: "@rjsf/utils@npm:5.17.1" @@ -27400,6 +27756,7 @@ __metadata: "@backstage/plugin-app-backend": "workspace:^" "@backstage/plugin-auth-backend": "workspace:^" "@backstage/plugin-auth-backend-module-github-provider": "workspace:^" + "@backstage/plugin-auth-backend-module-guest-provider": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" "@backstage/plugin-azure-devops-backend": "workspace:^" "@backstage/plugin-badges-backend": "workspace:^" @@ -27423,6 +27780,7 @@ __metadata: "@backstage/plugin-playlist-backend": "workspace:^" "@backstage/plugin-proxy-backend": "workspace:^" "@backstage/plugin-scaffolder-backend": "workspace:^" + "@backstage/plugin-scaffolder-backend-module-github": "workspace:^" "@backstage/plugin-search-backend": "workspace:^" "@backstage/plugin-search-backend-module-catalog": "workspace:^" "@backstage/plugin-search-backend-module-explore": "workspace:^" @@ -27486,7 +27844,6 @@ __metadata: "@backstage/plugin-search-backend-module-pg": "workspace:^" "@backstage/plugin-search-backend-module-techdocs": "workspace:^" "@backstage/plugin-search-backend-node": "workspace:^" - "@backstage/plugin-search-common": "workspace:^" "@backstage/plugin-signals-backend": "workspace:^" "@backstage/plugin-signals-node": "workspace:^" "@backstage/plugin-tech-insights-backend": "workspace:^" @@ -37336,7 +37693,7 @@ __metadata: languageName: node linkType: hard -"passport-oauth2@npm:1.x.x, passport-oauth2@npm:^1.1.2, passport-oauth2@npm:^1.4.0, passport-oauth2@npm:^1.6.0, passport-oauth2@npm:^1.6.1": +"passport-oauth2@npm:1.x.x, passport-oauth2@npm:^1.1.2, passport-oauth2@npm:^1.4.0, passport-oauth2@npm:^1.6.0, passport-oauth2@npm:^1.6.1, passport-oauth2@npm:^1.7.0": version: 1.8.0 resolution: "passport-oauth2@npm:1.8.0" dependencies: