diff --git a/.changeset/analytics-det-tyckte-inte-jag.md b/.changeset/analytics-det-tyckte-inte-jag.md deleted file mode 100644 index bc486e64c4..0000000000 --- a/.changeset/analytics-det-tyckte-inte-jag.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/core-components': patch -'@backstage/plugin-catalog-react': patch ---- - -The `` component now accepts a `noTrack` prop, which prevents the `click` event from being captured by the Analytics API. This can be used if tracking is explicitly not warranted, or in order to use custom link tracking in specific situations. diff --git a/.changeset/analytics-station-eleven.md b/.changeset/analytics-station-eleven.md deleted file mode 100644 index e1a2366cbe..0000000000 --- a/.changeset/analytics-station-eleven.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-analytics-module-ga': patch ---- - -Added the ability to capture and set user IDs from Backstage's `identityApi`. For full instructions on how to -set this up, see [the User ID section of its README](https://github.com/backstage/backstage/tree/master/plugins/analytics-module-ga#user-ids) diff --git a/.changeset/bright-buttons-rescue.md b/.changeset/bright-buttons-rescue.md deleted file mode 100644 index 71a6b76fa2..0000000000 --- a/.changeset/bright-buttons-rescue.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -'@backstage/plugin-auth-backend': minor ---- - -**BREAKING** Added `tokenManager` as a required property for the auth-backend `createRouter` function. This dependency is used to issue server tokens that are used by the `CatalogIdentityClient` when looking up users and their group membership during authentication. - -These changes are **required** to `packages/backend/src/plugins/auth.ts`: - -```diff -export default async function createPlugin({ - logger, - database, - config, - discovery, -+ tokenManager, -}: PluginEnvironment): Promise { - return await createRouter({ - logger, - config, - database, - discovery, -+ tokenManager, - }); -} -``` - -**BREAKING** The `CatalogIdentityClient` constructor now expects a `TokenManager` instead of a `TokenIssuer`. The `TokenManager` interface is used to generate a server token when [resolving a user's identity and membership through the catalog](https://backstage.io/docs/auth/identity-resolver). Using server tokens for these requests allows the auth-backend to bypass authorization checks when permissions are enabled for Backstage. This change will break apps that rely on the user tokens that were previously used by the client. Refer to the ["Backend-to-backend Authentication" tutorial](https://backstage.io/docs/tutorials/backend-to-backend-auth) for more information on server token usage. diff --git a/.changeset/curly-fireants-crash.md b/.changeset/curly-fireants-crash.md new file mode 100644 index 0000000000..db426a0fde --- /dev/null +++ b/.changeset/curly-fireants-crash.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +chore: bump `ansi-regex` from `5.0.1` to `6.0.1` diff --git a/.changeset/cyan-turtles-relax.md b/.changeset/cyan-turtles-relax.md deleted file mode 100644 index 4f7857c30c..0000000000 --- a/.changeset/cyan-turtles-relax.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-common': patch ---- - -Adds new `catalogEntityCreatePermission` which can be imported and used when authoring a permission policy to restrict/grant a user's access to the catalog import plugin. (And the "Register Existing Component" button which navigates there). diff --git a/.changeset/dependabot-2f11dff.md b/.changeset/dependabot-2f11dff.md deleted file mode 100644 index f3397cad0c..0000000000 --- a/.changeset/dependabot-2f11dff.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-rollbar-backend': patch ---- - -chore(deps): bump `camelcase-keys` from 6.2.2 to 7.0.1 diff --git a/.changeset/dependabot-9ec400d.md b/.changeset/dependabot-9ec400d.md deleted file mode 100644 index 1fd5a85477..0000000000 --- a/.changeset/dependabot-9ec400d.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-backend': patch ---- - -chore(deps): bump `passport` from 0.4.1 to 0.5.2 diff --git a/.changeset/dependabot-f969614.md b/.changeset/dependabot-f969614.md deleted file mode 100644 index c3c8890ec9..0000000000 --- a/.changeset/dependabot-f969614.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -chore(deps): bump `prom-client` from 13.2.0 to 14.0.1 diff --git a/.changeset/early-cooks-brake.md b/.changeset/early-cooks-brake.md deleted file mode 100644 index 3037d71ff4..0000000000 --- a/.changeset/early-cooks-brake.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Apply the fix from `0.4.16`, which is part of the `v0.65.1` release of Backstage. diff --git a/.changeset/flat-cars-begin.md b/.changeset/flat-cars-begin.md deleted file mode 100644 index 3a8837dc0e..0000000000 --- a/.changeset/flat-cars-begin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Change subtitle of Header style to use palette.bursts.fontColor diff --git a/.changeset/fresh-insects-attack.md b/.changeset/fresh-insects-attack.md deleted file mode 100644 index 3c22df67c0..0000000000 --- a/.changeset/fresh-insects-attack.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -Permission the Register Existing Component button diff --git a/.changeset/gold-queens-clap.md b/.changeset/gold-queens-clap.md deleted file mode 100644 index 252fbb1626..0000000000 --- a/.changeset/gold-queens-clap.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Fix an issue where changes related to the `MobileSidebar` prevented scrolling pages. Additionally improve the menu of the `MobileSidebar` to not overlay the `BottomNavigation`. diff --git a/.changeset/grumpy-teachers-remain.md b/.changeset/grumpy-teachers-remain.md deleted file mode 100644 index 60653b084f..0000000000 --- a/.changeset/grumpy-teachers-remain.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Migrate from deprecated package @octokit/rest to octokit diff --git a/.changeset/itchy-bulldogs-dance.md b/.changeset/itchy-bulldogs-dance.md deleted file mode 100644 index a2acad4d34..0000000000 --- a/.changeset/itchy-bulldogs-dance.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@backstage/plugin-catalog-react': patch ---- - -Fix bug: previously the filter would be set to "all" on page load, even if the -`initiallySelectedFilter` on the `DefaultCatalogPage` was set to something else, -or a different query parameter was supplied. Now, the prop and query parameters -control the filter as expected. Additionally, after this change any filters -which match 0 items will be disabled, and the filter will be reverted to 'all' -if they're set on page load. diff --git a/.changeset/nasty-pets-glow.md b/.changeset/nasty-pets-glow.md deleted file mode 100644 index e630736261..0000000000 --- a/.changeset/nasty-pets-glow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-org': patch ---- - -Added `relations.memberof` filter to the catalog api call in `MemberListCard` to avoid fetching all the User entity kinds from catalog-backend. diff --git a/.changeset/neat-mangos-study.md b/.changeset/neat-mangos-study.md deleted file mode 100644 index 7daefcadac..0000000000 --- a/.changeset/neat-mangos-study.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Update backend-to-backend auth link in configuration file comment diff --git a/.changeset/pre.json b/.changeset/pre.json deleted file mode 100644 index f1f3832fce..0000000000 --- a/.changeset/pre.json +++ /dev/null @@ -1,150 +0,0 @@ -{ - "mode": "pre", - "tag": "next", - "initialVersions": { - "example-app": "0.2.62", - "@backstage/app-defaults": "0.1.5", - "example-backend": "0.2.62", - "@backstage/backend-common": "0.10.5", - "@backstage/backend-tasks": "0.1.4", - "@backstage/backend-test-utils": "0.1.15", - "@backstage/catalog-client": "0.5.5", - "@backstage/catalog-model": "0.9.10", - "@backstage/cli": "0.13.0", - "@backstage/cli-common": "0.1.6", - "@backstage/codemods": "0.1.31", - "@backstage/config": "0.1.13", - "@backstage/config-loader": "0.9.3", - "@backstage/core-app-api": "0.5.1", - "@backstage/core-components": "0.8.6", - "@backstage/core-plugin-api": "0.6.0", - "@backstage/create-app": "0.4.15", - "@backstage/dev-utils": "0.2.19", - "e2e-test": "0.2.0", - "embedded-techdocs-app": "0.2.61", - "@backstage/errors": "0.2.0", - "@backstage/integration": "0.7.2", - "@backstage/integration-react": "0.1.19", - "@backstage/search-common": "0.2.2", - "@techdocs/cli": "0.8.11", - "@backstage/techdocs-common": "0.11.5", - "@backstage/test-utils": "0.2.3", - "@backstage/theme": "0.2.14", - "@backstage/types": "0.1.1", - "@backstage/version-bridge": "0.1.1", - "@backstage/plugin-airbrake": "0.1.1", - "@backstage/plugin-allure": "0.1.12", - "@backstage/plugin-analytics-module-ga": "0.1.7", - "@backstage/plugin-apache-airflow": "0.1.4", - "@backstage/plugin-api-docs": "0.7.0", - "@backstage/plugin-app-backend": "0.3.22", - "@backstage/plugin-auth-backend": "0.8.0", - "@backstage/plugin-azure-devops": "0.1.12", - "@backstage/plugin-azure-devops-backend": "0.3.1", - "@backstage/plugin-azure-devops-common": "0.2.0", - "@backstage/plugin-badges": "0.2.20", - "@backstage/plugin-badges-backend": "0.1.16", - "@backstage/plugin-bazaar": "0.1.11", - "@backstage/plugin-bazaar-backend": "0.1.7", - "@backstage/plugin-bitrise": "0.1.23", - "@backstage/plugin-catalog": "0.7.10", - "@backstage/plugin-catalog-backend": "0.21.1", - "@backstage/plugin-catalog-backend-module-ldap": "0.3.10", - "@backstage/plugin-catalog-backend-module-msgraph": "0.2.13", - "@backstage/plugin-catalog-common": "0.1.1", - "@backstage/plugin-catalog-graph": "0.2.8", - "@backstage/plugin-catalog-graphql": "0.3.1", - "@backstage/plugin-catalog-import": "0.7.10", - "@backstage/plugin-catalog-react": "0.6.12", - "@backstage/plugin-circleci": "0.2.35", - "@backstage/plugin-cloudbuild": "0.2.33", - "@backstage/plugin-code-coverage": "0.1.23", - "@backstage/plugin-code-coverage-backend": "0.1.20", - "@backstage/plugin-config-schema": "0.1.19", - "@backstage/plugin-cost-insights": "0.11.18", - "@backstage/plugin-explore": "0.3.27", - "@backstage/plugin-explore-react": "0.0.11", - "@backstage/plugin-firehydrant": "0.1.13", - "@backstage/plugin-fossa": "0.2.28", - "@backstage/plugin-gcp-projects": "0.3.15", - "@backstage/plugin-git-release-manager": "0.3.9", - "@backstage/plugin-github-actions": "0.4.33", - "@backstage/plugin-github-deployments": "0.1.27", - "@backstage/plugin-gitops-profiles": "0.3.14", - "@backstage/plugin-gocd": "0.1.2", - "@backstage/plugin-graphiql": "0.2.28", - "@backstage/plugin-graphql-backend": "0.1.12", - "@backstage/plugin-home": "0.4.12", - "@backstage/plugin-ilert": "0.1.22", - "@backstage/plugin-jenkins": "0.5.18", - "@backstage/plugin-jenkins-backend": "0.1.11", - "@backstage/plugin-kafka": "0.2.26", - "@backstage/plugin-kafka-backend": "0.2.15", - "@backstage/plugin-kubernetes": "0.5.5", - "@backstage/plugin-kubernetes-backend": "0.4.5", - "@backstage/plugin-kubernetes-common": "0.2.2", - "@backstage/plugin-lighthouse": "0.2.35", - "@backstage/plugin-newrelic": "0.3.14", - "@backstage/plugin-newrelic-dashboard": "0.1.4", - "@backstage/plugin-org": "0.4.0", - "@backstage/plugin-pagerduty": "0.3.23", - "@backstage/plugin-permission-backend": "0.4.1", - "@backstage/plugin-permission-common": "0.4.0", - "@backstage/plugin-permission-node": "0.4.1", - "@backstage/plugin-permission-react": "0.3.0", - "@backstage/plugin-proxy-backend": "0.2.16", - "@backstage/plugin-rollbar": "0.3.24", - "@backstage/plugin-rollbar-backend": "0.1.19", - "@backstage/plugin-scaffolder": "0.12.0", - "@backstage/plugin-scaffolder-backend": "0.15.22", - "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.1.9", - "@backstage/plugin-scaffolder-backend-module-rails": "0.2.4", - "@backstage/plugin-scaffolder-backend-module-yeoman": "0.1.3", - "@backstage/plugin-scaffolder-common": "0.1.3", - "@backstage/plugin-search": "0.6.0", - "@backstage/plugin-search-backend": "0.4.0", - "@backstage/plugin-search-backend-module-elasticsearch": "0.0.8", - "@backstage/plugin-search-backend-module-pg": "0.2.4", - "@backstage/plugin-search-backend-node": "0.4.5", - "@backstage/plugin-sentry": "0.3.34", - "@backstage/plugin-shortcuts": "0.1.20", - "@backstage/plugin-sonarqube": "0.2.14", - "@backstage/plugin-splunk-on-call": "0.3.20", - "@backstage/plugin-tech-insights": "0.1.6", - "@backstage/plugin-tech-insights-backend": "0.2.2", - "@backstage/plugin-tech-insights-backend-module-jsonfc": "0.1.6", - "@backstage/plugin-tech-insights-common": "0.2.1", - "@backstage/plugin-tech-insights-node": "0.2.0", - "@backstage/plugin-tech-radar": "0.5.3", - "@backstage/plugin-techdocs": "0.13.1", - "@backstage/plugin-techdocs-backend": "0.13.1", - "@backstage/plugin-todo": "0.1.20", - "@backstage/plugin-todo-backend": "0.1.19", - "@backstage/plugin-user-settings": "0.3.17", - "@backstage/plugin-xcmetrics": "0.2.16" - }, - "changesets": [ - "analytics-station-eleven", - "bright-buttons-rescue", - "dependabot-2f11dff", - "dependabot-9ec400d", - "dependabot-f969614", - "early-cooks-brake", - "flat-cars-begin", - "gold-queens-clap", - "grumpy-teachers-remain", - "nasty-pets-glow", - "neat-mangos-study", - "purple-steaks-design", - "quick-jars-wait", - "sharp-dragons-divide", - "sour-chairs-double", - "tall-rats-lie", - "tame-ads-exercise", - "techdocs-lets-call-the-whole-thing-off", - "thirty-houses-juggle", - "tiny-buses-compete", - "witty-lamps-laugh", - "witty-lizards-nail" - ] -} diff --git a/.changeset/purple-steaks-design.md b/.changeset/purple-steaks-design.md deleted file mode 100644 index 4857c39c73..0000000000 --- a/.changeset/purple-steaks-design.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Adds missing `/catalog-graph` route to ``. - -To fix this problem for a recently created app please update your `app/src/App.tsx` - -```diff -+ import { CatalogGraphPage } from '@backstage/plugin-catalog-graph'; - - ... omitted ... - - - } /> -+ } /> - -``` diff --git a/.changeset/quick-jars-wait.md b/.changeset/quick-jars-wait.md deleted file mode 100644 index bbf6b42a89..0000000000 --- a/.changeset/quick-jars-wait.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -'@backstage/plugin-proxy-backend': patch ---- - -Adds a new option `skipInvalidTargets` for the proxy `createRouter` which allows the proxy backend to be started with an invalid proxy configuration. If configured, it will simply skip the failed proxy and mount the other valid proxies. - -To configure it to pass by failing proxies: - -``` -const router = await createRouter({ - config, - logger, - discovery, - skipInvalidProxies: true, -}); -``` - -If you would like it to fail if a proxy is configured badly: - -``` -const router = await createRouter({ - config, - logger, - discovery, -}); -``` diff --git a/.changeset/shaggy-buckets-confess.md b/.changeset/shaggy-buckets-confess.md new file mode 100644 index 0000000000..186d911b77 --- /dev/null +++ b/.changeset/shaggy-buckets-confess.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-splunk-on-call': patch +--- + +Correct spelling of 'Acknowledge' in tooltip. diff --git a/.changeset/sharp-dragons-divide.md b/.changeset/sharp-dragons-divide.md deleted file mode 100644 index 398d7fb38a..0000000000 --- a/.changeset/sharp-dragons-divide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@techdocs/cli': patch ---- - -Use a local file dependency for embedded-techdocs-app, to ensure that it's always pulled out of the workspace diff --git a/.changeset/silver-eagles-reply.md b/.changeset/silver-eagles-reply.md deleted file mode 100644 index db69525768..0000000000 --- a/.changeset/silver-eagles-reply.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Permission the `catalog-import` route - -The following changes are **required** if you intend to add permissions to your existing app. - -Use the `PermissionedRoute` for `CatalogImportPage` instead of the normal `Route`: - -```diff -// packages/app/src/App.tsx -... -+ import { PermissionedRoute } from '@backstage/plugin-permission-react'; -+ import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common'; - -... - -- } /> -+ } -+ /> -``` diff --git a/.changeset/sour-chairs-double.md b/.changeset/sour-chairs-double.md deleted file mode 100644 index 4f481e20e7..0000000000 --- a/.changeset/sour-chairs-double.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Added `tokenManager` as a required property for the auth-backend `createRouter` function. This dependency is used to issue server tokens that are used by the `CatalogIdentityClient` when looking up users and their group membership during authentication. - -These changes are **required** to `packages/backend/src/plugins/auth.ts`: - -```diff -export default async function createPlugin({ - logger, - database, - config, - discovery, -+ tokenManager, -}: PluginEnvironment): Promise { - return await createRouter({ - logger, - config, - database, - discovery, -+ tokenManager, - }); -} -``` diff --git a/.changeset/tall-rats-lie.md b/.changeset/tall-rats-lie.md deleted file mode 100644 index ed76970df4..0000000000 --- a/.changeset/tall-rats-lie.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-pagerduty': patch ---- - -Fix change events tab error when change events exist diff --git a/.changeset/tame-ads-exercise.md b/.changeset/tame-ads-exercise.md deleted file mode 100644 index a2e11393a6..0000000000 --- a/.changeset/tame-ads-exercise.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -'@backstage/plugin-catalog-import': minor ---- - -Make filename, branch name and examples URLs used in catalog import customizable. - -Catalog backend ingestion loop can be already configured to fetch targets with custom catalog filename (other than `catalog-info.yaml`). It's now possible to customize said filename and branch name used in pull requests created by catalog import flow too. This allows organizations to further customize Backstage experience and to better reflect their branding. - -Filename (default: `catalog-info.yaml`) and branch name (default: `backstage-integration`) used in pull requests can be configured in `app-config.yaml` as follows: - -```yaml -// app-config.yaml - -catalog: - import: - entityFilename: anvil.yaml - pullRequestBranchName: anvil-integration -``` - -Following React components have also been updated to accept optional props for providing example entity and repository paths: - -```tsx - -``` - -```tsx - -``` diff --git a/.changeset/techdocs-funkar-varje-gang.md b/.changeset/techdocs-funkar-varje-gang.md deleted file mode 100644 index 727820e5f8..0000000000 --- a/.changeset/techdocs-funkar-varje-gang.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Fixed a bug where links to files within a TechDocs site that use the `download` attribute would result in a 404 in cases where the TechDocs backend and Backstage frontend application are on the same host. diff --git a/.changeset/techdocs-lets-call-the-whole-thing-off.md b/.changeset/techdocs-lets-call-the-whole-thing-off.md deleted file mode 100644 index 60cf25d65b..0000000000 --- a/.changeset/techdocs-lets-call-the-whole-thing-off.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Added support for documentation using the raw `` tag to point to relative resources like audio or video files. diff --git a/.changeset/thirty-houses-juggle.md b/.changeset/thirty-houses-juggle.md deleted file mode 100644 index c54ab5526f..0000000000 --- a/.changeset/thirty-houses-juggle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Pass authorization token to location service inside location api routes diff --git a/.changeset/tiny-buses-compete.md b/.changeset/tiny-buses-compete.md deleted file mode 100644 index 2cb8d1a87f..0000000000 --- a/.changeset/tiny-buses-compete.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/core-components': patch -'@backstage/plugin-scaffolder': patch ---- - -Make linkTarget configurable for MarkdownContent component diff --git a/.changeset/witty-lamps-laugh.md b/.changeset/witty-lamps-laugh.md deleted file mode 100644 index 1ca4f4e4dc..0000000000 --- a/.changeset/witty-lamps-laugh.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Switched the `app` dependency in the backend to use a file target rather than version. - -To apply this change to an existing app, make the following change to `packages/backend/package.json`: - -```diff - "dependencies": { -- "app": "0.0.0", -+ "app": "file:../app", -``` diff --git a/.changeset/witty-lizards-nail.md b/.changeset/witty-lizards-nail.md deleted file mode 100644 index 2ce3faa3f7..0000000000 --- a/.changeset/witty-lizards-nail.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Log warning if unable to parse yarn.lock diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a587419d50..08057d5af6 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -34,9 +34,9 @@ /tech-insights-backend-module-jsonfc @backstage/reviewers @xantier @iain-b /tech-insights-tech-insights-common @backstage/reviewers @xantier @iain-b /tech-insights-tech-insights-node @backstage/reviewers @xantier @iain-b -/packages/embedded-techdocs-app @backstage/techdocs-core /packages/search-common @backstage/techdocs-core /packages/techdocs-cli @backstage/techdocs-core +/packages/techdocs-cli-embedded-app @backstage/techdocs-core /packages/techdocs-common @backstage/techdocs-core /.changeset/cost-insights-* @backstage/reviewers @backstage/silver-lining /.changeset/search-* @backstage/techdocs-core diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index 3abe840368..8303510e77 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -28,6 +28,7 @@ Blackbox bool boolean builtins +callout Chai changeset changesets @@ -315,6 +316,7 @@ unbreak Unconference unmanaged unregister +unregistering unregistration untracked upsert @@ -338,4 +340,4 @@ Zalando Zhou zoomable zsh -Alef \ No newline at end of file +Alef diff --git a/ADOPTERS.md b/ADOPTERS.md index 64bad7439b..97bfbc255b 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -86,3 +86,6 @@ | [Hopin](https://hopin.com) | [Vladimir Glafirov](https://github.com/vglafirov), [Chloe Lee](https://github.com/msfuko) | Developer portal to streamline the development practices. Integrated with service catalog, software templates, application monitoring, tech docs and plugins. | | [HBO Max](https://hbomax.com) | [@mdb](https://github.com/mdb), [@nesta219](https://github.com/nesta219), [@nmische](https://github.com/nmische), [@hbomark](https://github.com/hbomark) | Developer portal hosting service catalog and API documentation, as well as cloud infrastructure details, operational visibility tools, and a custom plugin for browsing notable platform change events, such as deployments and configuration updates. | | [RCHLO](https://www.riachuelo.com.br) & [MIDWAY](https://www.midway.com.br) | [@marcosborges](https://github.com/marcosborges), [@defaultbr](https://github.com/defaultbr) | Self-Service Platform | +| [HP Inc](https://www.hp.com) | [Damon Kaswell](https://github.com/dekoding) | DevEx engagement hub (dev portal: docs, standards, Q&A) and extensive assets catalog (APIs, services, code, data, etc.) for the pan-HP internal developer community. | +| [VMware](https://www.vmware.com) | [@mpriamo](https://github.com/mpriamo), [@krisapplegate](https://github.com/krisapplegate) | Part of [Tanzu Application Platform](https://docs.vmware.com/en/VMware-Tanzu-Application-Platform/index.html) offering; internal developer portal | +| [Ualá](https://www.uala.com.ar/) | [Santiago Bernal](https://github.com/sabernal) | Initial work being done to centralize documentation for all our microservices and APIs, as well as scaffolding new services and tracking code quality | diff --git a/GOVERNANCE.md b/GOVERNANCE.md index 936c27c7cf..3bcef61021 100644 --- a/GOVERNANCE.md +++ b/GOVERNANCE.md @@ -36,6 +36,25 @@ To become a maintainer you need to demonstrate the following: If a maintainer is no longer interested or cannot perform the maintainer duties listed above, they should volunteer to be moved to emeritus status. In extreme cases this can also occur by a vote of the sponsors and maintainers per the voting process below. +# End User Sponsors + +## Role of a Backstage End User Sponsor + +- Provide support for Backstage by removing blockers, securing funding, providing advocacy, feedback, and ensuring project continuity and long term success. +- Assist Backstage maintainers in prioritizing upcoming roadmap items and planned work. +- Provide neutral mediation for any disputes that arise as part of the project. + +## Backstage End User Sponsor Membership + +The End User Sponsors group comprises at most 5 people. To be eligible for membership in the group, you or the company where you work you must: + +- Be responsible for and end user of a production Backstage deployment of non-trivial size +- Be active contributors to the open source project +- Be willing and able to attend regularly-scheduled End User Sponsor meetings +- Abide by [Backstage’s Code of Conduct](./CODE_OF_CONDUCT.md). + +Candidates for membership will be nominated by current Sponsor members or by Backstage maintainers. If there are more nominations than Sponsor seats remaining, existing sponsors shall vote on the candidates, and the candidates with the most votes will become Sponsors. Any ties will be broken by current Backstage sponsors. + # Reviewers The project also contains a team called [@backstage/reviewers](https://github.com/orgs/backstage/teams/reviewers). This is the team of people who are the fallback in [`CODEOWNERS`](./.github/CODEOWNERS). This team will typically contain the maintainers, and a small number of additional people who are permitted to approve and merge pull requests. The purpose of this group is to offload some of the review work from the maintainers, simplifying and speeding up the review process for contributors. diff --git a/docs/deployment/heroku.md b/docs/deployment/heroku.md index 42ab817b30..1545c34733 100644 --- a/docs/deployment/heroku.md +++ b/docs/deployment/heroku.md @@ -18,11 +18,10 @@ First, install the $ heroku login ``` -Heroku runs a container registry on `registry.heroku.com`. To push Backstage -Docker images, log in to the container registry also: +If you have not yet created a project through the Heroku interface, you can create it through the CLI. ```shell -$ heroku container:login +$ heroku create ``` You _might_ also need to set your Heroku app's stack to `container`: @@ -31,13 +30,43 @@ You _might_ also need to set your Heroku app's stack to `container`: $ heroku stack:set container -a ``` +Configuring your `app-config.yaml`: + +```yaml +app: + # Should be the same as backend.baseUrl when using the `app-backend` plugin + baseUrl: https://.herokuapp.com + +backend: + baseUrl: https://.herokuapp.com + listen: + port: + $env: PORT + # The $PORT environment variable is a feature of Heroku + # https://devcenter.heroku.com/articles/dynos#web-dynos +``` + +> Make sure your file is being copied into your container in the `Dockerfile`. + +Before building the Docker image, run the [backstage host build commands](https://backstage.io/docs/deployment/docker#host-build). They must be run whenever you are going to publish a new image. + +Heroku runs a container registry on `registry.heroku.com`. To push Backstage +Docker images, log in to the container registry also: + +```shell +$ heroku container:login +``` + ## Push and deploy a Docker image Now we can push a Backstage [Docker image](docker.md) to Heroku's container registry and release it to the `web` worker: ```bash -$ heroku container:push web -a +$ docker image build . -f packages/backend/Dockerfile --tag registry.heroku.com//web + +$ docker push registry.heroku.com//web + $ heroku container:release web -a ``` diff --git a/docs/features/software-catalog/api.md b/docs/features/software-catalog/api.md index 71e229651a..3221b9e46a 100644 --- a/docs/features/software-catalog/api.md +++ b/docs/features/software-catalog/api.md @@ -21,7 +21,7 @@ section below is `/entities`, and the catalog is located at `http://localhost:7007/api/catalog` during local development, the full URL would be `http://localhost:7007/api/catalog/entities`. The actual URL may vary from one organization to the other, especially in production, but is commonly your -`backend.baseUrl` in your app config, plus `/catalog` at the end. +`backend.baseUrl` in your app config, plus `/api/catalog` at the end. Some or all of the endpoints may accept or require an `Authorization` header with a `Bearer` token, which should then be the Backstage token returned by the diff --git a/docs/features/software-catalog/life-of-an-entity.md b/docs/features/software-catalog/life-of-an-entity.md index 9e8a3f0563..618923289e 100644 --- a/docs/features/software-catalog/life-of-an-entity.md +++ b/docs/features/software-catalog/life-of-an-entity.md @@ -48,9 +48,9 @@ The details of these processes are described below. ## Ingestion -Each catalog deployment has a number of entity providers installed. They are +Each catalog deployment has a number of _entity providers_ installed. They are responsible for fetching data from external authoritative sources in any way -that they see fit, to translate those into entity objects, and to notify the +that they see fit, translating those into entity objects, and notifying the database when those entities are added or removed. These are the _unprocessed entities_ that will be subject to later processing (see below), and they form the very basis of existence for entities. If there were no entity providers, no @@ -108,7 +108,7 @@ the processing loop should next try to process it. When the entity first appears, this timestamp is set to "now" - asking for it to be picked up as soon as possible. -Each catalog deployment has a number of processors installed. They are +Each catalog deployment has a number of _processors_ installed. They are responsible for receiving unprocessed entities that the catalog decided are due for processing, and then running that data through a number of processing stages, mutating the entity and emitting auxiliary data about it. When all of @@ -185,7 +185,28 @@ happen during ingestion or processing. ## Errors -> TODO: Describe how errors are exposed through entities +Errors during the ingestion and processing of entities can happen in a variety +of ways, and they may happen at a far later point in time than when they were +registered. For example, a registered file may get deleted in the remote system, +or the user may accidentally change the file contents in such a way that they +cannot be parsed successfully, etc. + +There are two main ways that these errors are surfaced. + +First, the catalog backend will produce detailed logs that should contain +sufficient information for a reader to find the causes for errors. Since these +logs are typically not easily found by end users, this can mainly be a useful +tool for Backstage operators who want to debug problems either with statically +registered entities that are under their control, or to help end users find +problems. + +Second, for most classes of errors, the entity itself will contain a status +field that describes the problem. The contents of this field is shown at the top +of your entity page in Backstage, if you have placed the corresponding error +callout component (`EntityProcessingErrorsPanel`) there. + +We are still working to improve the surfacing and observability around +processing loop errors. ## Orphaning @@ -206,17 +227,22 @@ either, it becomes _orphaned_. The end result is as follows: - The catalog page in Backstage for the child entity detects the new annotation and informs users about the orphan status. -Orphaning can occur in several different scenarios. One common cause is that the -end user edited a corresponding catalog catalog-info YAML file removing the -entity's entry. In the case of a `Location` parent entity, orphaning can happen -if removing the target line pointing to the file containing the child entity. -Another common cause is large batch processors such as the ones that crawl -through remote systems looking for entities, no longer finding something that it -used to find before. Maybe the data was moved, or deleted, in the remote system. -So for example when a person leaves the company an LDAP org discovery processor -might leave an orphaned `User` entity behind. Note that this only applies to -processors - ingestion that happens using entity providers work differently, -described below. +Orphaning can occur in several different scenarios. + +- If a catalog-info YAML file is moved from one place to another in the version + control system without updating the registration in the catalog, it will + effectively become orphaned "by" that registered location +- If the user edits a corresponding parent catalog-info YAML file removing the + entity's entry - for example in the case of a `Location` parent entity, + orphaning can happen if editing or removing the `target`/`targets` lines + pointing to the file containing the child entity. +- Another common cause is large batch processors such as the ones that crawl + through remote systems looking for entities, no longer finding something that + it used to find before. Maybe the data was moved, or deleted, in the remote + system. So for example when a person leaves the company an LDAP org discovery + processor might leave an orphaned `User` entity behind. Note that this only + applies to processors - ingestion that happens using entity providers work + differently, described below. > Note that removing a file, or accidentally corrupting a file so that it cannot > be read successfully, does _not_ lead to orphaning. Hard errors, including the @@ -239,8 +265,78 @@ provided out of the box. ## Implicit Deletion -> TODO: Describe the process of entity providers eagerly deleting entities +Entity providers - not processors - are subject to _eager_ deletion of entities, +which may trigger the implicit deletion of more than just the entity you thought +you were deleting. This concept is explained here. + +Recall that all entity providers manage a private "bucket" of entities, as +described in the [External integrations](external-integrations.md) article. They +can perform some operations on those entities, including additions, updates, and +deletions. Entity additions/updates are subject to the regular processing loops, +which means that bucket entities may end up forming roots of an entire graph of +entities that are emitted by those processors as they recursively work they way +through the bucket contents and its descendants. + +When a provider issues a deletion of an entity in its bucket, that entity as +well as _the entire tree of entities processed out of it_, if any, are +considered for immediate deletion. Note "considered" - they are deleted if and +only if they would otherwise have become orphaned (no other parent entities +emitting them). Since the graph of entities is not strictly a tree, multiple +roots may actually end up indirectly referencing a node farther down in the +graph. If that's the case, that node won't go away until all such roots go away. + +URLs to yaml files that you register using either the Create button or add to +your app-config, are both handled by entity providers. That means that this +implicit deletion mechanism comes into play in some everyday circumstances. +Let's illustrate. + +Imagine that you have a monorepo, with a single `Location` entity in a +catalog-info file at the root, and that entity points to three other +catalog-info files in the repo with a `Component` entity in each one. + +```text +/ + feature_one/ + catalog-info.yaml <- kind: Component + feature_two/ + catalog-info.yaml <- kind: Component + feature_three/ + catalog-info.yaml <- kind: Component + catalog-info.yaml <- kind: Location +``` + +If you register the root `Location` entity, the actual effect is that _five_ +entities appear in the catalog. First, one that is named `generated-`-something, +which corresponds to the registered URL itself. That's the one that the provider +has put in its "bucket". Then, as processing loops chug along, the `Location` +entity you pointed to appears as a child of that, and then the three `Component` +entities appear in turn as children of the `Location`. + +As an end user of the Backstage interface, you may now want to delete one of the +three `Component` entities. You do that by visiting the three-dots menu in the +top right of an entity view. The popup dialog that appears will inform you that +actually this entity belongs to a certain root, and that you may want to remove +that root instead (which corresponds to unregistering the originally registered +URL). If you choose to do so, _all_ of the aforementioned five entities will +actually be deleted in the same operation. + +If you did not want to perform this aggressive pruning, you might have instead +chosen to remove one of the `target` rows of your `Location` catalog-info file, +and then deleted the catalog-info file that contained the `Component` you wanted +to get rid of. Now the catalog would be left with an orphaned component, and you +would instead be able to use the explicit deletion (see below) to delete that +single component. ## Explicit Deletion -> TODO: Describe direct deletion via the catalog API +The catalog and its REST API also permits direct deletion of individual +entities. This makes sense to do on orphaned entities; entities that aren't +being actively kept up to date by any parent entities. The popup interface under +the three-dots menu option of entity views does offer this option, and the +orphaned status can be seen in an info box at the top of the entity's overview +page. + +However, if you were to try to do an explicit depletion on an entity that's +being kept actively updated by a parent entity, it would just reappear again +shortly thereafter when the processing loops reconsider the parent entity that's +still in there. diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index a1dffe1580..415f8cd85e 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -287,6 +287,79 @@ The `RepoUrlPicker` is a custom field that we provide part of the `plugin-scaffolder`. You can provide your own custom fields by [writing your own Custom Field Extensions](./writing-custom-field-extensions.md) +##### Using the Users `oauth` token + +There's a little bit of extra magic that you get out of the box when using the +`RepoUrlPicker` as a field input. You can provide some additional options under +`ui:options` to allow the `RepoUrlPicker` to grab an `oauth` token for the user +for the required `repository`. + +This is great for when you are wanting to create a new repository, or wanting to +perform operations on top of an existing repository. + +A sample template that takes advantage of this is like so: + +```yaml +apiVersion: scaffolder.backstage.io/v1beta3 +kind: Template +metadata: + name: v1beta3-demo + title: Test Action template + description: scaffolder v1beta3 template demo +spec: + owner: backstage/techdocs-core + type: service + + parameters: + ... + + - title: Choose a location + required: + - repoUrl + properties: + repoUrl: + title: Repository Location + type: string + ui:field: RepoUrlPicker + ui:options: + # Here's the option you can pass to the RepoUrlPicker + requestUserCredentials: + secretsKey: USER_OAUTH_TOKEN + additionalScopes: + github: + - workflow:write + allowedHosts: + - github.com + ... + + steps: + ... + + - id: publish + name: Publish + action: publish:github + input: + allowedHosts: ['github.com'] + description: This is ${{ parameters.name }} + repoUrl: ${{ parameters.repoUrl }} + # here's where the secret can be used + token: ${{ secrets.USER_OAUTH_TOKEN }} + + ... +``` + +You will see from above that there is an additional `requestUserCredentials` +object that is passed to the `RepoUrlPicker`. This object defines what the +returned `secret` should be stored as when accessing using +`${{ secrets.secretName }}`, in this case it is `USER_OAUTH_TOKEN`. And then you +will see that there is an additional `input` field into the `publish:github` +action called `token`, in which you can use the `secret` like so: +`token: ${{ secrets.USER_OAUTH_TOKEN }}`. + +There's also the ability to pass additional scopes when requesting the `oauth` +token from the user, which you can do on a per-provider basis, in case your +template can be published to multiple providers. + #### The Owner Picker When the scaffolder needs to add new components to the catalog, it needs to have diff --git a/package.json b/package.json index 997e87035b..5c60cc41c6 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "**/@roadiehq/**/@backstage/plugin-catalog": "*", "**/@roadiehq/**/@backstage/catalog-model": "*" }, - "version": "0.66.0-next.0", + "version": "0.66.0", "dependencies": { "@manypkg/get-packages": "^1.1.3", "@microsoft/api-documenter": "^7.15.0", diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index 588b674cfc..b58d61fcca 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/app-defaults +## 0.1.6 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/core-app-api@0.5.2 + +## 0.1.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7-next.1 + - @backstage/core-app-api@0.5.2-next.0 + ## 0.1.6-next.0 ### Patch Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index 37f6061fd5..6a509a22f5 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/app-defaults", "description": "Provides the default wiring of a Backstage App", - "version": "0.1.6-next.0", + "version": "0.1.6", "private": false, "publishConfig": { "access": "public", @@ -29,8 +29,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.8.7-next.0", - "@backstage/core-app-api": "^0.5.1", + "@backstage/core-components": "^0.8.7", + "@backstage/core-app-api": "^0.5.2", "@backstage/core-plugin-api": "^0.6.0", "@backstage/plugin-permission-react": "^0.3.0", "@backstage/theme": "^0.2.14", @@ -42,8 +42,8 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@types/jest": "^26.0.7", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index eefdd6f016..eb9d3cda99 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,70 @@ # example-app +## 0.2.63 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + - @backstage/plugin-code-coverage@0.1.24 + - @backstage/plugin-catalog-common@0.1.2 + - @backstage/cli@0.13.1 + - @backstage/plugin-scaffolder@0.12.1 + - @backstage/integration-react@0.1.20 + - @backstage/plugin-org@0.4.1 + - @backstage/plugin-pagerduty@0.3.24 + - @backstage/plugin-catalog-import@0.8.0 + - @backstage/core-app-api@0.5.2 + - @backstage/plugin-techdocs@0.13.2 + - @backstage/app-defaults@0.1.6 + - @backstage/plugin-airbrake@0.1.2 + - @backstage/plugin-apache-airflow@0.1.5 + - @backstage/plugin-api-docs@0.7.1 + - @backstage/plugin-azure-devops@0.1.13 + - @backstage/plugin-badges@0.2.21 + - @backstage/plugin-catalog@0.7.11 + - @backstage/plugin-catalog-graph@0.2.9 + - @backstage/plugin-circleci@0.2.36 + - @backstage/plugin-cloudbuild@0.2.34 + - @backstage/plugin-cost-insights@0.11.19 + - @backstage/plugin-explore@0.3.28 + - @backstage/plugin-gcp-projects@0.3.16 + - @backstage/plugin-github-actions@0.4.34 + - @backstage/plugin-gocd@0.1.3 + - @backstage/plugin-graphiql@0.2.29 + - @backstage/plugin-home@0.4.13 + - @backstage/plugin-jenkins@0.5.19 + - @backstage/plugin-kafka@0.2.27 + - @backstage/plugin-kubernetes@0.5.6 + - @backstage/plugin-lighthouse@0.2.36 + - @backstage/plugin-newrelic@0.3.15 + - @backstage/plugin-newrelic-dashboard@0.1.5 + - @backstage/plugin-rollbar@0.3.25 + - @backstage/plugin-search@0.6.1 + - @backstage/plugin-sentry@0.3.35 + - @backstage/plugin-shortcuts@0.1.21 + - @backstage/plugin-tech-insights@0.1.7 + - @backstage/plugin-tech-radar@0.5.4 + - @backstage/plugin-todo@0.1.21 + - @backstage/plugin-user-settings@0.3.18 + +## 0.2.63-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7-next.1 + - @backstage/plugin-catalog-react@0.6.13-next.1 + - @backstage/plugin-code-coverage@0.1.24-next.1 + - @backstage/plugin-catalog-common@0.1.2-next.0 + - @backstage/cli@0.13.1-next.1 + - @backstage/plugin-scaffolder@0.12.1-next.1 + - @backstage/core-app-api@0.5.2-next.0 + - @backstage/plugin-techdocs@0.13.2-next.1 + - @backstage/plugin-catalog@0.7.11-next.1 + - @backstage/app-defaults@0.1.6-next.1 + ## 0.2.63-next.0 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index c6e7be8c5d..3447c07059 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,56 +1,56 @@ { "name": "example-app", - "version": "0.2.63-next.0", + "version": "0.2.63", "private": true, "bundled": true, "dependencies": { - "@backstage/app-defaults": "^0.1.6-next.0", + "@backstage/app-defaults": "^0.1.6", "@backstage/catalog-model": "^0.9.10", - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", - "@backstage/integration-react": "^0.1.20-next.0", - "@backstage/plugin-airbrake": "^0.1.2-next.0", - "@backstage/plugin-api-docs": "^0.7.1-next.0", - "@backstage/plugin-azure-devops": "^0.1.13-next.0", - "@backstage/plugin-apache-airflow": "^0.1.5-next.0", - "@backstage/plugin-badges": "^0.2.21-next.0", - "@backstage/plugin-catalog": "^0.7.11-next.0", - "@backstage/plugin-catalog-common": "^0.1.1", - "@backstage/plugin-catalog-graph": "^0.2.9-next.0", - "@backstage/plugin-catalog-import": "^0.8.0-next.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", - "@backstage/plugin-circleci": "^0.2.36-next.0", - "@backstage/plugin-cloudbuild": "^0.2.34-next.0", - "@backstage/plugin-code-coverage": "^0.1.24-next.0", - "@backstage/plugin-cost-insights": "^0.11.19-next.0", - "@backstage/plugin-explore": "^0.3.28-next.0", - "@backstage/plugin-gcp-projects": "^0.3.16-next.0", - "@backstage/plugin-github-actions": "^0.4.34-next.0", - "@backstage/plugin-gocd": "^0.1.3-next.0", - "@backstage/plugin-graphiql": "^0.2.29-next.0", - "@backstage/plugin-home": "^0.4.13-next.0", - "@backstage/plugin-jenkins": "^0.5.19-next.0", - "@backstage/plugin-kafka": "^0.2.27-next.0", - "@backstage/plugin-kubernetes": "^0.5.6-next.0", - "@backstage/plugin-lighthouse": "^0.2.36-next.0", - "@backstage/plugin-newrelic": "^0.3.15-next.0", - "@backstage/plugin-newrelic-dashboard": "^0.1.5-next.0", - "@backstage/plugin-org": "^0.4.1-next.0", - "@backstage/plugin-pagerduty": "0.3.24-next.0", + "@backstage/integration-react": "^0.1.20", + "@backstage/plugin-airbrake": "^0.1.2", + "@backstage/plugin-api-docs": "^0.7.1", + "@backstage/plugin-azure-devops": "^0.1.13", + "@backstage/plugin-apache-airflow": "^0.1.5", + "@backstage/plugin-badges": "^0.2.21", + "@backstage/plugin-catalog": "^0.7.11", + "@backstage/plugin-catalog-common": "^0.1.2", + "@backstage/plugin-catalog-graph": "^0.2.9", + "@backstage/plugin-catalog-import": "^0.8.0", + "@backstage/plugin-catalog-react": "^0.6.13", + "@backstage/plugin-circleci": "^0.2.36", + "@backstage/plugin-cloudbuild": "^0.2.34", + "@backstage/plugin-code-coverage": "^0.1.24", + "@backstage/plugin-cost-insights": "^0.11.19", + "@backstage/plugin-explore": "^0.3.28", + "@backstage/plugin-gcp-projects": "^0.3.16", + "@backstage/plugin-github-actions": "^0.4.34", + "@backstage/plugin-gocd": "^0.1.3", + "@backstage/plugin-graphiql": "^0.2.29", + "@backstage/plugin-home": "^0.4.13", + "@backstage/plugin-jenkins": "^0.5.19", + "@backstage/plugin-kafka": "^0.2.27", + "@backstage/plugin-kubernetes": "^0.5.6", + "@backstage/plugin-lighthouse": "^0.2.36", + "@backstage/plugin-newrelic": "^0.3.15", + "@backstage/plugin-newrelic-dashboard": "^0.1.5", + "@backstage/plugin-org": "^0.4.1", + "@backstage/plugin-pagerduty": "0.3.24", "@backstage/plugin-permission-react": "^0.3.0", - "@backstage/plugin-rollbar": "^0.3.25-next.0", - "@backstage/plugin-scaffolder": "^0.12.1-next.0", - "@backstage/plugin-search": "^0.6.1-next.0", - "@backstage/plugin-sentry": "^0.3.35-next.0", - "@backstage/plugin-shortcuts": "^0.1.21-next.0", - "@backstage/plugin-tech-radar": "^0.5.4-next.0", - "@backstage/plugin-techdocs": "^0.13.2-next.0", - "@backstage/plugin-todo": "^0.1.21-next.0", - "@backstage/plugin-user-settings": "^0.3.18-next.0", + "@backstage/plugin-rollbar": "^0.3.25", + "@backstage/plugin-scaffolder": "^0.12.1", + "@backstage/plugin-search": "^0.6.1", + "@backstage/plugin-sentry": "^0.3.35", + "@backstage/plugin-shortcuts": "^0.1.21", + "@backstage/plugin-tech-radar": "^0.5.4", + "@backstage/plugin-techdocs": "^0.13.2", + "@backstage/plugin-todo": "^0.1.21", + "@backstage/plugin-user-settings": "^0.3.18", "@backstage/search-common": "^0.2.2", - "@backstage/plugin-tech-insights": "^0.1.7-next.0", + "@backstage/plugin-tech-insights": "^0.1.7", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -72,7 +72,7 @@ }, "devDependencies": { "@backstage/plugin-permission-react": "^0.3.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/test-utils": "^0.2.4", "@rjsf/core": "^3.2.1", "@testing-library/cypress": "^8.0.2", "@testing-library/jest-dom": "^5.10.1", diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index 80e5b8f1a6..da731fa441 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/backend-common +## 0.10.6 + +### Patch Changes + +- 50d039577a: Added a `Context` type for the backend, that can propagate an abort signal, a + deadline, and contextual values through the call stack. The main entrypoint is + the `Contexts` utility class that provides a root context creator and commonly + used decorators. + + These are marked as `@alpha` for now, and are therefore only accessible via + `@backstage/backend-common/alpha`. + +## 0.10.6-next.0 + +### Patch Changes + +- 50d039577a: Added a `Context` type for the backend, that can propagate an abort signal, a + deadline, and contextual values through the call stack. The main entrypoint is + the `Contexts` utility class that provides a root context creator and commonly + used decorators. + + These are marked as `@alpha` for now, and are therefore only accessible via + `@backstage/backend-common/alpha`. + ## 0.10.5 ### Patch Changes diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index d63416571d..f53fb9d6e4 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -6,6 +6,7 @@ /// /// +import { AbortController as AbortController_2 } from 'node-abort-controller'; import { AbortSignal as AbortSignal_2 } from 'node-abort-controller'; import { AwsS3Integration } from '@backstage/integration'; import { AzureIntegration } from '@backstage/integration'; @@ -13,6 +14,7 @@ import { BitbucketIntegration } from '@backstage/integration'; import { Config } from '@backstage/config'; import cors from 'cors'; import Docker from 'dockerode'; +import { Duration } from 'luxon'; import { ErrorRequestHandler } from 'express'; import express from 'express'; import { GithubCredentialsProvider } from '@backstage/integration'; @@ -145,6 +147,29 @@ export interface ContainerRunner { runContainer(opts: RunContainerOptions): Promise; } +// @alpha +export interface Context { + readonly abortSignal: AbortSignal_2; + readonly deadline: Date | undefined; + value(key: string): T | undefined; +} + +// @alpha +export class Contexts { + static root(): Context; + static withAbort( + parentCtx: Context, + source: AbortController_2 | AbortSignal_2, + ): Context; + static withTimeoutDuration(parentCtx: Context, timeout: Duration): Context; + static withTimeoutMillis(parentCtx: Context, timeout: number): Context; + static withValue( + parentCtx: Context, + key: string, + value: unknown | ((previous: unknown | undefined) => unknown), + ): Context; +} + // @public @deprecated export const createDatabase: typeof createDatabaseClient; diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index b8f56c1fbe..fdff7ca414 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -1,14 +1,15 @@ { "name": "@backstage/backend-common", "description": "Common functionality library for Backstage backends", - "version": "0.10.5", + "version": "0.10.6", "main": "src/index.ts", "types": "src/index.ts", "private": false, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "types": "dist/index.d.ts", + "alphaTypes": "dist/index.alpha.d.ts" }, "homepage": "https://backstage.io", "repository": { @@ -21,7 +22,7 @@ ], "license": "Apache-2.0", "scripts": { - "build": "backstage-cli build --outputs cjs,types", + "build": "backstage-cli build --experimental-type-build --outputs cjs,types", "lint": "backstage-cli lint", "test": "backstage-cli test", "prepack": "backstage-cli prepack", @@ -41,6 +42,7 @@ "@types/cors": "^2.8.6", "@types/dockerode": "^3.3.0", "@types/express": "^4.17.6", + "@types/luxon": "^2.0.4", "archiver": "^5.0.2", "aws-sdk": "^2.840.0", "compression": "^1.7.4", @@ -59,6 +61,7 @@ "knex": "^0.95.1", "lodash": "^4.17.21", "logform": "^2.3.2", + "luxon": "^2.0.2", "minimatch": "^3.0.4", "minimist": "^1.2.5", "morgan": "^1.10.0", @@ -81,8 +84,8 @@ } }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/test-utils": "^0.2.4", "@types/archiver": "^5.1.0", "@types/compression": "^1.7.0", "@types/concat-stream": "^1.6.0", @@ -109,7 +112,8 @@ }, "files": [ "dist", - "config.d.ts" + "config.d.ts", + "alpha" ], "configSchema": "config.d.ts" } diff --git a/packages/backend-common/src/context/AbortContext.test.ts b/packages/backend-common/src/context/AbortContext.test.ts new file mode 100644 index 0000000000..f47e1d4beb --- /dev/null +++ b/packages/backend-common/src/context/AbortContext.test.ts @@ -0,0 +1,345 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbortController } from 'node-abort-controller'; +import { AbortContext } from './AbortContext'; +import { RootContext } from './RootContext'; + +describe('AbortContext', () => { + afterEach(() => { + jest.useRealTimers(); + }); + + describe('forTimeoutMillis', () => { + it('can abort on a timeout', async () => { + jest.useFakeTimers(); + const timeout = 200; + const deadline = Date.now() + timeout; + + const root = new RootContext(); + + const child = AbortContext.forTimeoutMillis(root, timeout); + const childListener = jest.fn(); + child.abortSignal.addEventListener('abort', childListener); + + expect(child.abortSignal.aborted).toBe(false); + expect(Math.abs(+child.deadline! - deadline)).toBeLessThan(50); + expect(childListener).toBeCalledTimes(0); + + jest.advanceTimersByTime(timeout + 1); + + expect(child.abortSignal.aborted).toBe(true); + expect(childListener).toBeCalledTimes(1); + }); + + it('results in minimum deadline when parent triggers sooner', async () => { + jest.useFakeTimers(); + const parentTimeout = 200; + const childTimeout = 300; + const parentDeadline = Date.now() + parentTimeout; + const childDeadline = parentDeadline; // clamped + + const root = new RootContext(); + + const parent = AbortContext.forTimeoutMillis(root, parentTimeout); + const parentListener = jest.fn(); + parent.abortSignal.addEventListener('abort', parentListener); + + const child = AbortContext.forTimeoutMillis(parent, childTimeout); + const childListener = jest.fn(); + child.abortSignal.addEventListener('abort', childListener); + + expect(parent.abortSignal.aborted).toBe(false); + expect(child.abortSignal.aborted).toBe(false); + expect(Math.abs(+parent.deadline! - parentDeadline)).toBeLessThan(50); + expect(Math.abs(+child.deadline! - childDeadline)).toBeLessThan(50); + expect(parentListener).toBeCalledTimes(0); + expect(childListener).toBeCalledTimes(0); + + jest.advanceTimersByTime(parentTimeout + 1); + + expect(parent.abortSignal.aborted).toBe(true); + expect(child.abortSignal.aborted).toBe(true); + expect(parentListener).toBeCalledTimes(1); + expect(childListener).toBeCalledTimes(1); + }); + + it('results in minimum deadline when child triggers sooner', async () => { + jest.useFakeTimers(); + const parentTimeout = 300; + const childTimeout = 200; + const parentDeadline = Date.now() + parentTimeout; + const childDeadline = Date.now() + childTimeout; + + const root = new RootContext(); + + const parent = AbortContext.forTimeoutMillis(root, parentTimeout); + const parentListener = jest.fn(); + parent.abortSignal.addEventListener('abort', parentListener); + + const child = AbortContext.forTimeoutMillis(parent, childTimeout); + const childListener = jest.fn(); + child.abortSignal.addEventListener('abort', childListener); + + expect(parent.abortSignal.aborted).toBe(false); + expect(child.abortSignal.aborted).toBe(false); + expect(Math.abs(+parent.deadline! - parentDeadline)).toBeLessThan(50); + expect(Math.abs(+child.deadline! - childDeadline)).toBeLessThan(50); + expect(parentListener).toBeCalledTimes(0); + expect(childListener).toBeCalledTimes(0); + + jest.advanceTimersByTime(childTimeout + 1); + + expect(parent.abortSignal.aborted).toBe(false); + expect(child.abortSignal.aborted).toBe(true); + expect(parentListener).toBeCalledTimes(0); + expect(childListener).toBeCalledTimes(1); + + jest.advanceTimersByTime(parentTimeout - childTimeout + 1); + + expect(parent.abortSignal.aborted).toBe(true); + expect(child.abortSignal.aborted).toBe(true); + expect(parentListener).toBeCalledTimes(1); + expect(childListener).toBeCalledTimes(1); + }); + + it('child carries over parent signal state if parent was already aborted and had no deadline', async () => { + jest.useFakeTimers(); + const childTimeout = 200; + const childDeadline = Date.now() + childTimeout; + + const root = new RootContext(); + + const parentController = new AbortController(); + const parent = AbortContext.forSignal(root, parentController.signal); + + parentController.abort(); + + const child = AbortContext.forTimeoutMillis(parent, childTimeout); + const childListener = jest.fn(); + child.abortSignal.addEventListener('abort', childListener); + + expect(child.abortSignal.aborted).toBe(true); + expect(childListener).toBeCalledTimes(0); + expect(Math.abs(+child.deadline! - childDeadline)).toBeLessThan(50); + + jest.advanceTimersByTime(childTimeout + 1); + + expect(child.abortSignal.aborted).toBe(true); + expect(childListener).toBeCalledTimes(0); // still + }); + + it('child carries over parent signal state if parent was already aborted and had a deadline', async () => { + jest.useFakeTimers(); + const first = new RootContext(); + + const secondController = new AbortController(); + const second = AbortContext.forSignal(first, secondController.signal); + secondController.abort(); + + const third = AbortContext.forTimeoutMillis(second, 200); + const fourth = AbortContext.forTimeoutMillis(third, 300); + + expect(third.abortSignal.aborted).toBe(true); + expect(fourth.abortSignal.aborted).toBe(true); + expect(Math.abs(+fourth.deadline! - Date.now() - 200)).toBeLessThan(50); + }); + }); + + describe('forController', () => { + it('signals child when parent is aborted', () => { + const root = new RootContext(); + + const parentController = new AbortController(); + const parent = AbortContext.forController(root, parentController); + const parentListener = jest.fn(); + parent.abortSignal.addEventListener('abort', parentListener); + + const childController = new AbortController(); + const child = AbortContext.forController(parent, childController); + const childListener = jest.fn(); + child.abortSignal.addEventListener('abort', childListener); + + expect(parent.abortSignal.aborted).toBe(false); + expect(child.abortSignal.aborted).toBe(false); + expect(parentListener).toBeCalledTimes(0); + expect(childListener).toBeCalledTimes(0); + + parentController.abort(); + + expect(parent.abortSignal.aborted).toBe(true); + expect(child.abortSignal.aborted).toBe(true); + expect(parentListener).toBeCalledTimes(1); + expect(childListener).toBeCalledTimes(1); + }); + + it('does not signal parent when child is aborted', async () => { + const root = new RootContext(); + + const parentController = new AbortController(); + const parent = AbortContext.forController(root, parentController); + const parentListener = jest.fn(); + parent.abortSignal.addEventListener('abort', parentListener); + + const childController = new AbortController(); + const child = AbortContext.forController(parent, childController); + const childListener = jest.fn(); + child.abortSignal.addEventListener('abort', childListener); + + expect(parent.abortSignal.aborted).toBe(false); + expect(child.abortSignal.aborted).toBe(false); + expect(parentListener).toBeCalledTimes(0); + expect(childListener).toBeCalledTimes(0); + + childController.abort(); + + expect(parent.abortSignal.aborted).toBe(false); + expect(child.abortSignal.aborted).toBe(true); + expect(parentListener).toBeCalledTimes(0); + expect(childListener).toBeCalledTimes(1); + }); + + it('child carries over parent signal state if parent was already aborted', async () => { + const root = new RootContext(); + + const parentController = new AbortController(); + const parent = AbortContext.forController(root, parentController); + + parentController.abort(); + + const childController = new AbortController(); + const child = AbortContext.forController(parent, childController); + const childListener = jest.fn(); + child.abortSignal.addEventListener('abort', childListener); + + expect(parent.abortSignal.aborted).toBe(true); + expect(child.abortSignal.aborted).toBe(true); + expect(childListener).toBeCalledTimes(0); + + childController.abort(); + + expect(parent.abortSignal.aborted).toBe(true); + expect(child.abortSignal.aborted).toBe(true); + expect(childListener).toBeCalledTimes(0); + }); + + it('child carries over given signal state if it was already aborted', async () => { + const root = new RootContext(); + + const childController = new AbortController(); + childController.abort(); + + const child = AbortContext.forController(root, childController); + const childListener = jest.fn(); + child.abortSignal.addEventListener('abort', childListener); + + expect(child.abortSignal.aborted).toBe(true); + expect(childListener).toBeCalledTimes(0); + }); + }); + + describe('forSignal', () => { + it('signals child when parent is aborted', async () => { + const root = new RootContext(); + + const parentController = new AbortController(); + const parent = AbortContext.forSignal(root, parentController.signal); + const parentListener = jest.fn(); + parent.abortSignal.addEventListener('abort', parentListener); + + const childController = new AbortController(); + const child = AbortContext.forSignal(parent, childController.signal); + const childListener = jest.fn(); + child.abortSignal.addEventListener('abort', childListener); + + expect(parent.abortSignal.aborted).toBe(false); + expect(child.abortSignal.aborted).toBe(false); + expect(parentListener).toBeCalledTimes(0); + expect(childListener).toBeCalledTimes(0); + + parentController.abort(); + + expect(parent.abortSignal.aborted).toBe(true); + expect(child.abortSignal.aborted).toBe(true); + expect(parentListener).toBeCalledTimes(1); + expect(childListener).toBeCalledTimes(1); + }); + + it('does not signal parent when child is aborted', async () => { + const root = new RootContext(); + + const parentController = new AbortController(); + const parent = AbortContext.forSignal(root, parentController.signal); + const parentListener = jest.fn(); + parent.abortSignal.addEventListener('abort', parentListener); + + const childController = new AbortController(); + const child = AbortContext.forSignal(parent, childController.signal); + const childListener = jest.fn(); + child.abortSignal.addEventListener('abort', childListener); + + expect(parent.abortSignal.aborted).toBe(false); + expect(child.abortSignal.aborted).toBe(false); + expect(parentListener).toBeCalledTimes(0); + expect(childListener).toBeCalledTimes(0); + + childController.abort(); + + expect(parent.abortSignal.aborted).toBe(false); + expect(child.abortSignal.aborted).toBe(true); + expect(parentListener).toBeCalledTimes(0); + expect(childListener).toBeCalledTimes(1); + }); + + it('child carries over parent signal state if parent was already aborted', async () => { + const root = new RootContext(); + + const parentController = new AbortController(); + const parent = AbortContext.forSignal(root, parentController.signal); + + parentController.abort(); + + const childController = new AbortController(); + const child = AbortContext.forSignal(parent, childController.signal); + const childListener = jest.fn(); + child.abortSignal.addEventListener('abort', childListener); + + expect(parent.abortSignal.aborted).toBe(true); + expect(child.abortSignal.aborted).toBe(true); + expect(childListener).toBeCalledTimes(0); + + childController.abort(); + + expect(parent.abortSignal.aborted).toBe(true); + expect(child.abortSignal.aborted).toBe(true); + expect(childListener).toBeCalledTimes(0); + }); + + it('child carries over given signal state if it was already aborted', async () => { + const root = new RootContext(); + + const childController = new AbortController(); + childController.abort(); + + const child = AbortContext.forSignal(root, childController.signal); + const childListener = jest.fn(); + child.abortSignal.addEventListener('abort', childListener); + + expect(child.abortSignal.aborted).toBe(true); + expect(childListener).toBeCalledTimes(0); + }); + }); +}); diff --git a/packages/backend-common/src/context/AbortContext.ts b/packages/backend-common/src/context/AbortContext.ts new file mode 100644 index 0000000000..8a119358a6 --- /dev/null +++ b/packages/backend-common/src/context/AbortContext.ts @@ -0,0 +1,133 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbortController, AbortSignal } from 'node-abort-controller'; +import { Context } from './types'; + +/** + * A context that implements various abort related functionality. + */ +export class AbortContext implements Context { + /** + * Abort either when the parent aborts, or after the given timeout has + * expired. + * + * @param ctx - The parent context + * @param timeout - A timeout value, in milliseconds + * @returns A new context + */ + static forTimeoutMillis(ctx: Context, timeout: number): Context { + const desiredDeadline = new Date(Date.now() + timeout); + const actualDeadline = + ctx.deadline && ctx.deadline < desiredDeadline + ? ctx.deadline + : desiredDeadline; + + if (ctx.abortSignal.aborted) { + if (ctx.deadline && desiredDeadline === actualDeadline) { + return ctx; + } + return new AbortContext(ctx, ctx.abortSignal, actualDeadline); + } + + const controller = new AbortController(); + const timeoutHandle = setTimeout(abort, timeout); + ctx.abortSignal.addEventListener('abort', abort); + + function abort() { + ctx.abortSignal.removeEventListener('abort', abort); + clearTimeout(timeoutHandle!); + controller.abort(); + } + + return new AbortContext(ctx, controller.signal, actualDeadline); + } + + /** + * Abort either when the parent aborts, or when the given controller is + * triggered. + * + * @remarks + * + * If you have access to the controller, this function is more efficient than + * {@link AbortContext#forSignal}. + * + * @param ctx - The parent context + * @param controller - An abort controller + * @returns A new context + */ + static forController(ctx: Context, controller: AbortController): Context { + // Already aborted context / signal are fine to reuse as-is + if (ctx.abortSignal.aborted) { + return ctx; + } else if (controller.signal.aborted) { + return new AbortContext(ctx, controller.signal, ctx.deadline); + } + + function abort() { + ctx.abortSignal.removeEventListener('abort', abort); + controller.abort(); + } + + ctx.abortSignal.addEventListener('abort', abort); + + return new AbortContext(ctx, controller.signal, ctx.deadline); + } + + /** + * Abort either when the parent aborts, or when the given signal is triggered. + * + * @remarks + * + * If you have access to the controller and not just the signal, + * {@link AbortContext#forController} is slightly more efficient to use. + * + * @param ctx - The parent context + * @param signal - An abort signal + * @returns A new context + */ + static forSignal(ctx: Context, signal: AbortSignal): Context { + // Already aborted context / signal are fine to reuse as-is + if (ctx.abortSignal.aborted) { + return ctx; + } else if (signal.aborted) { + return new AbortContext(ctx, signal, ctx.deadline); + } + + const controller = new AbortController(); + + function abort() { + ctx.abortSignal.removeEventListener('abort', abort); + signal.removeEventListener('abort', abort); + controller.abort(); + } + + ctx.abortSignal.addEventListener('abort', abort); + signal.addEventListener('abort', abort); + + return new AbortContext(ctx, controller.signal, ctx.deadline); + } + + private constructor( + private readonly parent: Context, + readonly abortSignal: AbortSignal, + readonly deadline: Date | undefined, + ) {} + + value(key: string): T | undefined { + return this.parent.value(key); + } +} diff --git a/packages/backend-common/src/context/Contexts.test.ts b/packages/backend-common/src/context/Contexts.test.ts new file mode 100644 index 0000000000..cbd61d20a9 --- /dev/null +++ b/packages/backend-common/src/context/Contexts.test.ts @@ -0,0 +1,90 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Duration } from 'luxon'; +import { AbortController } from 'node-abort-controller'; +import { Contexts } from './Contexts'; + +describe('Contexts', () => { + afterEach(() => { + jest.useRealTimers(); + }); + + describe('root', () => { + it('can create a root', () => { + const ctx = Contexts.root(); + expect(ctx.abortSignal).toBeDefined(); + expect(ctx.deadline).toBeUndefined(); + }); + }); + + describe('setAbort', () => { + it('works for controllers', () => { + const controller = new AbortController(); + const parent = Contexts.root(); + const child = Contexts.withAbort(parent, controller); + expect(child.abortSignal.aborted).toBe(false); + controller.abort(); + expect(child.abortSignal.aborted).toBe(true); + }); + + it('works for signals', () => { + const controller = new AbortController(); + const parent = Contexts.root(); + const child = Contexts.withAbort(parent, controller.signal); + expect(child.abortSignal.aborted).toBe(false); + controller.abort(); + expect(child.abortSignal.aborted).toBe(true); + }); + }); + + describe('setTimeoutDuration', () => { + it('works', () => { + jest.useFakeTimers(); + const parent = Contexts.root(); + const child = Contexts.withTimeoutDuration( + parent, + Duration.fromMillis(200), + ); + expect(child.abortSignal.aborted).toBe(false); + jest.advanceTimersByTime(100); + expect(child.abortSignal.aborted).toBe(false); + jest.advanceTimersByTime(101); + expect(child.abortSignal.aborted).toBe(true); + }); + }); + + describe('setTimeoutMillis', () => { + it('works', () => { + jest.useFakeTimers(); + const parent = Contexts.root(); + const child = Contexts.withTimeoutMillis(parent, 200); + expect(child.abortSignal.aborted).toBe(false); + jest.advanceTimersByTime(100); + expect(child.abortSignal.aborted).toBe(false); + jest.advanceTimersByTime(101); + expect(child.abortSignal.aborted).toBe(true); + }); + }); + + describe('setValue', () => { + it('works', () => { + const parent = Contexts.root(); + const child = Contexts.withValue(parent, 'k', 'v'); + expect(child.value('k')).toBe('v'); + }); + }); +}); diff --git a/packages/backend-common/src/context/Contexts.ts b/packages/backend-common/src/context/Contexts.ts new file mode 100644 index 0000000000..e22a76f673 --- /dev/null +++ b/packages/backend-common/src/context/Contexts.ts @@ -0,0 +1,114 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Duration } from 'luxon'; +import { AbortController, AbortSignal } from 'node-abort-controller'; +import { AbortContext } from './AbortContext'; +import { RootContext } from './RootContext'; +import { Context } from './types'; +import { ValueContext } from './ValueContext'; + +/** + * Common context decorators. + * + * @alpha + */ +export class Contexts { + /** + * Creates a root context. + * + * @remarks + * + * This should normally only be called near the root of an application. The + * created context is meant to be passed down into deeper levels, which may or + * may not make derived contexts out of it. + */ + static root(): Context { + return new RootContext(); + } + + /** + * Creates a derived context, which signals to abort operations either when + * any parent context signals, or when the given source is aborted. + * + * @remarks + * + * If the parent context was already aborted, then it is returned as-is. + * + * If the given source was already aborted, then a new already-aborted context + * is returned. + * + * @param parentCtx - A parent context that shall be used as a base + * @param source - An abort controller or signal that you intend to perhaps + * trigger at some later point in time. + * @returns A new {@link Context} + */ + static withAbort( + parentCtx: Context, + source: AbortController | AbortSignal, + ): Context { + return 'aborted' in source + ? AbortContext.forSignal(parentCtx, source) + : AbortContext.forController(parentCtx, source); + } + + /** + * Creates a derived context, which signals to abort operations either when + * any parent context signals, or when the given amount of time has passed. + * This may affect the deadline. + * + * @param parentCtx - A parent context that shall be used as a base + * @param timeout - The duration of time, after which the derived context will + * signal to abort. + * @returns A new {@link Context} + */ + static withTimeoutDuration(parentCtx: Context, timeout: Duration): Context { + return AbortContext.forTimeoutMillis(parentCtx, timeout.as('milliseconds')); + } + + /** + * Creates a derived context, which signals to abort operations either when + * any parent context signals, or when the given amount of time has passed. + * This may affect the deadline. + * + * @param parentCtx - A parent context that shall be used as a base + * @param timeout - The number of milliseconds, after which the derived + * context will signal to abort. + * @returns A new {@link Context} + */ + static withTimeoutMillis(parentCtx: Context, timeout: number): Context { + return AbortContext.forTimeoutMillis(parentCtx, timeout); + } + + /** + * Creates a derived context, which has a specific key-value pair set as well + * as all key-value pairs that were set in the original context. + * + * @param parentCtx - A parent context that shall be used as a base + * @param key - The key of the value to set + * @param value - The value, or a function that accepts the previous value (or + * undefined if not set yet) and computes the new value + * @returns A new {@link Context} + */ + static withValue( + parentCtx: Context, + key: string, + value: unknown | ((previous: unknown | undefined) => unknown), + ): Context { + const v = typeof value === 'function' ? value(parentCtx.value(key)) : value; + return ValueContext.forConstantValue(parentCtx, key, v); + } +} diff --git a/packages/backend-common/src/context/RootContext.test.ts b/packages/backend-common/src/context/RootContext.test.ts new file mode 100644 index 0000000000..395786e3dc --- /dev/null +++ b/packages/backend-common/src/context/RootContext.test.ts @@ -0,0 +1,27 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { RootContext } from './RootContext'; + +describe('RootContext', () => { + it('returns empty values', async () => { + const ctx = new RootContext(); + expect(ctx.abortSignal).toBeDefined(); + expect(ctx.abortSignal.aborted).toBe(false); + expect(ctx.deadline).toBeUndefined(); + expect(ctx.value('a')).toBeUndefined(); + }); +}); diff --git a/packages/backend-common/src/context/RootContext.ts b/packages/backend-common/src/context/RootContext.ts new file mode 100644 index 0000000000..61962380a4 --- /dev/null +++ b/packages/backend-common/src/context/RootContext.ts @@ -0,0 +1,45 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbortSignal } from 'node-abort-controller'; +import { Context } from './types'; + +/** + * Since the root context can never abort, and since nobody is every meant to + * dispatch events through it, we can use a static dummy instance for + * efficiency. + */ +const dummyAbortSignal: AbortSignal = Object.freeze({ + aborted: false, + addEventListener() {}, + removeEventListener() {}, + dispatchEvent() { + return true; + }, + onabort: null, +}); + +/** + * An empty root context. + */ +export class RootContext implements Context { + readonly abortSignal = dummyAbortSignal; + readonly deadline = undefined; + + value(_key: string): T | undefined { + return undefined; + } +} diff --git a/packages/backend-common/src/context/ValueContext.test.ts b/packages/backend-common/src/context/ValueContext.test.ts new file mode 100644 index 0000000000..6a216d4548 --- /dev/null +++ b/packages/backend-common/src/context/ValueContext.test.ts @@ -0,0 +1,44 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { RootContext } from './RootContext'; +import { ValueContext } from './ValueContext'; + +describe('ValueContext', () => { + it('returns its own values, or delegates to the parent', async () => { + const root = new RootContext(); + const a = ValueContext.forConstantValue(root, 'a', 1); + const b = ValueContext.forConstantValue(a, 'x', 2); + const c = ValueContext.forConstantValue(b, 'a', 3); + const d = ValueContext.forConstantValue(c, 'b', 4); + + expect(a.value('a')).toBe(1); + expect(a.value('b')).toBeUndefined(); + expect(a.value('x')).toBeUndefined(); + + expect(b.value('a')).toBe(1); + expect(b.value('b')).toBeUndefined(); + expect(b.value('x')).toBe(2); + + expect(c.value('a')).toBe(3); + expect(c.value('b')).toBeUndefined(); + expect(c.value('x')).toBe(2); + + expect(d.value('a')).toBe(3); + expect(d.value('b')).toBe(4); + expect(d.value('x')).toBe(2); + }); +}); diff --git a/packages/backend-common/src/context/ValueContext.ts b/packages/backend-common/src/context/ValueContext.ts new file mode 100644 index 0000000000..441aaec984 --- /dev/null +++ b/packages/backend-common/src/context/ValueContext.ts @@ -0,0 +1,46 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbortSignal } from 'node-abort-controller'; +import { Context } from './types'; + +/** + * A context that just holds a single value, and delegates the rest to its + * parent. + */ +export class ValueContext implements Context { + static forConstantValue(ctx: Context, key: string, value: unknown): Context { + return new ValueContext(ctx, key, value); + } + + constructor( + private readonly _parent: Context, + private readonly _key: string, + private readonly _value: unknown, + ) {} + + get abortSignal(): AbortSignal { + return this._parent.abortSignal; + } + + get deadline(): Date | undefined { + return this._parent.deadline; + } + + value(key: string): T | undefined { + return key === this._key ? (this._value as T) : this._parent.value(key); + } +} diff --git a/packages/backend-common/src/context/index.ts b/packages/backend-common/src/context/index.ts new file mode 100644 index 0000000000..37a6e29c8c --- /dev/null +++ b/packages/backend-common/src/context/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { Contexts } from './Contexts'; +export type { Context } from './types'; diff --git a/packages/backend-common/src/context/types.ts b/packages/backend-common/src/context/types.ts new file mode 100644 index 0000000000..664745bbf6 --- /dev/null +++ b/packages/backend-common/src/context/types.ts @@ -0,0 +1,45 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbortSignal } from 'node-abort-controller'; + +/** + * A context that is meant to be passed as a ctx variable down the call chain, + * to pass along scoped information and abort signals. + * + * @alpha + */ +export interface Context { + /** + * Returns an abort signal that triggers when the current context or any of + * its parents signal for it. + */ + readonly abortSignal: AbortSignal; + + /** + * The point in time when the current context shall time out and abort, if + * applicable. + */ + readonly deadline: Date | undefined; + + /** + * Attempts to get a stored value by key from the context. + * + * @param key - The key of the value to get + * @returns The associated value, or undefined if not set + */ + value(key: string): T | undefined; +} diff --git a/packages/backend-common/src/index.ts b/packages/backend-common/src/index.ts index e430ddc1a4..238e58b2a8 100644 --- a/packages/backend-common/src/index.ts +++ b/packages/backend-common/src/index.ts @@ -22,6 +22,7 @@ export * from './cache'; export { loadBackendConfig } from './config'; +export * from './context'; export * from './database'; export * from './discovery'; export * from './hot'; diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md index cfaf40a6d6..b13142a7cf 100644 --- a/packages/backend-tasks/CHANGELOG.md +++ b/packages/backend-tasks/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/backend-tasks +## 0.1.5 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6 + +## 0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + ## 0.1.4 ### Patch Changes diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index 838f38dbd2..a060e5e99c 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.1.4", + "version": "0.1.5", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -29,7 +29,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/config": "^0.1.13", "@backstage/errors": "^0.2.0", "@backstage/types": "^0.1.1", @@ -43,8 +43,8 @@ "zod": "^3.9.5" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.16-next.0", - "@backstage/cli": "^0.13.1-next.0", + "@backstage/backend-test-utils": "^0.1.16", + "@backstage/cli": "^0.13.1", "jest": "^26.0.1", "wait-for-expect": "^3.0.2" }, diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index 006ea6d634..0ecc9afb4f 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/backend-test-utils +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.13.1 + - @backstage/backend-common@0.10.6 + +## 0.1.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.13.1-next.1 + - @backstage/backend-common@0.10.6-next.0 + ## 0.1.16-next.0 ### Patch Changes diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 7aabe3e08d..b6db1694c3 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-test-utils", "description": "Test helpers library for Backstage backends", - "version": "0.1.16-next.0", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -30,8 +30,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", - "@backstage/cli": "^0.13.1-next.0", + "@backstage/backend-common": "^0.10.6", + "@backstage/cli": "^0.13.1", "@backstage/config": "^0.1.13", "knex": "^0.95.1", "mysql2": "^2.2.5", @@ -41,7 +41,7 @@ "uuid": "^8.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "jest": "^26.0.1" }, "files": [ diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index 8882a9203e..40bfad7ddf 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,69 @@ # example-backend +## 0.2.63 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-backend@0.9.0 + - @backstage/plugin-rollbar-backend@0.1.20 + - @backstage/plugin-catalog-backend@0.21.2 + - @backstage/plugin-scaffolder-backend@0.15.23 + - @backstage/plugin-proxy-backend@0.2.17 + - @backstage/backend-common@0.10.6 + - example-app@0.2.63 + - @backstage/backend-tasks@0.1.5 + - @backstage/plugin-app-backend@0.3.23 + - @backstage/plugin-azure-devops-backend@0.3.2 + - @backstage/plugin-badges-backend@0.1.17 + - @backstage/plugin-code-coverage-backend@0.1.21 + - @backstage/plugin-graphql-backend@0.1.13 + - @backstage/plugin-jenkins-backend@0.1.12 + - @backstage/plugin-kafka-backend@0.2.16 + - @backstage/plugin-kubernetes-backend@0.4.6 + - @backstage/plugin-permission-backend@0.4.2 + - @backstage/plugin-permission-node@0.4.2 + - @backstage/plugin-scaffolder-backend-module-rails@0.2.5 + - @backstage/plugin-search-backend@0.4.1 + - @backstage/plugin-search-backend-module-pg@0.2.5 + - @backstage/plugin-tech-insights-backend@0.2.3 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.7 + - @backstage/plugin-tech-insights-node@0.2.1 + - @backstage/plugin-techdocs-backend@0.13.2 + - @backstage/plugin-todo-backend@0.1.20 + +## 0.2.63-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-backend@0.9.0-next.1 + - @backstage/backend-common@0.10.6-next.0 + - example-app@0.2.63-next.1 + - @backstage/plugin-catalog-backend@0.21.2-next.1 + - @backstage/plugin-techdocs-backend@0.13.2-next.0 + - @backstage/backend-tasks@0.1.5-next.0 + - @backstage/plugin-app-backend@0.3.23-next.0 + - @backstage/plugin-azure-devops-backend@0.3.2-next.0 + - @backstage/plugin-badges-backend@0.1.17-next.0 + - @backstage/plugin-code-coverage-backend@0.1.21-next.0 + - @backstage/plugin-graphql-backend@0.1.13-next.0 + - @backstage/plugin-jenkins-backend@0.1.12-next.0 + - @backstage/plugin-kafka-backend@0.2.16-next.0 + - @backstage/plugin-kubernetes-backend@0.4.6-next.0 + - @backstage/plugin-permission-backend@0.4.2-next.1 + - @backstage/plugin-permission-node@0.4.2-next.1 + - @backstage/plugin-proxy-backend@0.2.17-next.1 + - @backstage/plugin-rollbar-backend@0.1.20-next.1 + - @backstage/plugin-scaffolder-backend@0.15.23-next.1 + - @backstage/plugin-scaffolder-backend-module-rails@0.2.5-next.1 + - @backstage/plugin-search-backend@0.4.1-next.1 + - @backstage/plugin-search-backend-module-pg@0.2.5-next.0 + - @backstage/plugin-tech-insights-backend@0.2.3-next.0 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.7-next.0 + - @backstage/plugin-tech-insights-node@0.2.1-next.0 + - @backstage/plugin-todo-backend@0.1.20-next.0 + ## 0.2.63-next.0 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index c9e1c9d7c3..67c959376c 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.63-next.0", + "version": "0.2.63", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,38 +24,38 @@ "migrate:create": "knex migrate:make -x ts" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", - "@backstage/backend-tasks": "^0.1.4", + "@backstage/backend-common": "^0.10.6", + "@backstage/backend-tasks": "^0.1.5", "@backstage/catalog-client": "^0.5.5", "@backstage/catalog-model": "^0.9.10", "@backstage/config": "^0.1.13", "@backstage/integration": "^0.7.2", - "@backstage/plugin-app-backend": "^0.3.22", - "@backstage/plugin-auth-backend": "^0.9.0-next.0", - "@backstage/plugin-azure-devops-backend": "^0.3.1", - "@backstage/plugin-badges-backend": "^0.1.16", - "@backstage/plugin-catalog-backend": "^0.21.2-next.0", - "@backstage/plugin-code-coverage-backend": "^0.1.20", - "@backstage/plugin-graphql-backend": "^0.1.12", - "@backstage/plugin-jenkins-backend": "^0.1.11", - "@backstage/plugin-kubernetes-backend": "^0.4.5", - "@backstage/plugin-kafka-backend": "^0.2.15", - "@backstage/plugin-permission-backend": "^0.4.2-next.0", + "@backstage/plugin-app-backend": "^0.3.23", + "@backstage/plugin-auth-backend": "^0.9.0", + "@backstage/plugin-azure-devops-backend": "^0.3.2", + "@backstage/plugin-badges-backend": "^0.1.17", + "@backstage/plugin-catalog-backend": "^0.21.2", + "@backstage/plugin-code-coverage-backend": "^0.1.21", + "@backstage/plugin-graphql-backend": "^0.1.13", + "@backstage/plugin-jenkins-backend": "^0.1.12", + "@backstage/plugin-kubernetes-backend": "^0.4.6", + "@backstage/plugin-kafka-backend": "^0.2.16", + "@backstage/plugin-permission-backend": "^0.4.2", "@backstage/plugin-permission-common": "^0.4.0", - "@backstage/plugin-permission-node": "^0.4.2-next.0", - "@backstage/plugin-proxy-backend": "^0.2.17-next.0", - "@backstage/plugin-rollbar-backend": "^0.1.20-next.0", - "@backstage/plugin-scaffolder-backend": "^0.15.23-next.0", - "@backstage/plugin-scaffolder-backend-module-rails": "^0.2.5-next.0", - "@backstage/plugin-search-backend": "^0.4.1-next.0", + "@backstage/plugin-permission-node": "^0.4.2", + "@backstage/plugin-proxy-backend": "^0.2.17", + "@backstage/plugin-rollbar-backend": "^0.1.20", + "@backstage/plugin-scaffolder-backend": "^0.15.23", + "@backstage/plugin-scaffolder-backend-module-rails": "^0.2.5", + "@backstage/plugin-search-backend": "^0.4.1", "@backstage/plugin-search-backend-node": "^0.4.5", "@backstage/plugin-search-backend-module-elasticsearch": "^0.0.8", - "@backstage/plugin-search-backend-module-pg": "^0.2.4", - "@backstage/plugin-techdocs-backend": "^0.13.1", - "@backstage/plugin-tech-insights-backend": "^0.2.2", - "@backstage/plugin-tech-insights-node": "^0.2.0", - "@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.6", - "@backstage/plugin-todo-backend": "^0.1.19", + "@backstage/plugin-search-backend-module-pg": "^0.2.5", + "@backstage/plugin-techdocs-backend": "^0.13.2", + "@backstage/plugin-tech-insights-backend": "^0.2.3", + "@backstage/plugin-tech-insights-node": "^0.2.1", + "@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.7", + "@backstage/plugin-todo-backend": "^0.1.20", "@gitbeaker/node": "^35.1.0", "@octokit/rest": "^18.5.3", "azure-devops-node-api": "^11.0.1", @@ -72,7 +72,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@types/dockerode": "^3.3.0", "@types/express": "^4.17.6", "@types/express-serve-static-core": "^4.17.5" diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index bcea1a68ee..a74e3ba0a7 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/cli +## 0.13.1 + +### Patch Changes + +- 5bd0ce9e62: chore(deps): bump `inquirer` from 7.3.3 to 8.2.0 +- 80f510caee: Log warning if unable to parse yarn.lock + +## 0.13.1-next.1 + +### Patch Changes + +- 5bd0ce9e62: chore(deps): bump `inquirer` from 7.3.3 to 8.2.0 + ## 0.13.1-next.0 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 824e8e5efc..aad08a21eb 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.13.1-next.0", + "version": "0.13.1", "private": false, "publishConfig": { "access": "public" @@ -78,7 +78,7 @@ "glob": "^7.1.7", "handlebars": "^4.7.3", "html-webpack-plugin": "^5.3.1", - "inquirer": "^7.0.4", + "inquirer": "^8.2.0", "jest": "^26.0.1", "jest-css-modules": "^2.1.0", "json-schema": "^0.4.0", @@ -115,13 +115,13 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@backstage/theme": "^0.2.14", "@types/diff": "^5.0.0", "@types/express": "^4.17.6", diff --git a/packages/codemods/CHANGELOG.md b/packages/codemods/CHANGELOG.md index ec2fbfee4e..d14d46efd8 100644 --- a/packages/codemods/CHANGELOG.md +++ b/packages/codemods/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/codemods +## 0.1.32 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/core-app-api@0.5.2 + +## 0.1.32-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7-next.1 + - @backstage/core-app-api@0.5.2-next.0 + ## 0.1.32-next.0 ### Patch Changes diff --git a/packages/codemods/package.json b/packages/codemods/package.json index 9cd2cb8567..4ce5d9700d 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/codemods", "description": "A collection of codemods for Backstage projects", - "version": "0.1.32-next.0", + "version": "0.1.32", "private": false, "publishConfig": { "access": "public", diff --git a/packages/config/package.json b/packages/config/package.json index 44fb7ab286..02c63af2b5 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -34,7 +34,7 @@ "lodash": "^4.17.21" }, "devDependencies": { - "@backstage/test-utils": "^0.2.3", + "@backstage/test-utils": "^0.2.4-next.0", "@types/jest": "^26.0.7", "@types/node": "^14.14.32" }, diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index 06692a0b46..cc115a7da2 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/core-app-api +## 0.5.2 + +### Patch Changes + +- 40775bd263: Switched out the `GithubAuth` implementation to use the common `OAuth2` implementation. This relies on the simultaneous change in `@backstage/plugin-auth-backend` that enabled access token storage in cookies rather than the current solution that's based on `LocalStorage`. + + > **NOTE:** Make sure you upgrade the `auth-backend` deployment before or at the same time as you deploy this change. + +## 0.5.2-next.0 + +### Patch Changes + +- 40775bd263: Switched out the `GithubAuth` implementation to use the common `OAuth2` implementation. This relies on the simultaneous change in `@backstage/plugin-auth-backend` that enabled access token storage in cookies rather than the current solution that's based on `LocalStorage`. + + > **NOTE:** Make sure you upgrade the `auth-backend` deployment before or at the same time as you deploy this change. + ## 0.5.1 ### Patch Changes diff --git a/packages/core-app-api/api-report.md b/packages/core-app-api/api-report.md index ba2ed8cb62..3b53813615 100644 --- a/packages/core-app-api/api-report.md +++ b/packages/core-app-api/api-report.md @@ -35,6 +35,7 @@ import { FeatureFlag } from '@backstage/core-plugin-api'; import { FeatureFlagsApi } from '@backstage/core-plugin-api'; import { FeatureFlagsSaveOptions } from '@backstage/core-plugin-api'; import { FetchApi } from '@backstage/core-plugin-api'; +import { githubAuthApiRef } from '@backstage/core-plugin-api'; import { gitlabAuthApiRef } from '@backstage/core-plugin-api'; import { googleAuthApiRef } from '@backstage/core-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; @@ -379,25 +380,11 @@ export type FlatRoutesProps = { }; // @public -export class GithubAuth implements OAuthApi, SessionApi { - // (undocumented) - static create(options: OAuthApiCreateOptions): GithubAuth; - // (undocumented) - getAccessToken(scope?: string, options?: AuthRequestOptions): Promise; - // (undocumented) - getBackstageIdentity( - options?: AuthRequestOptions, - ): Promise; - // (undocumented) - getProfile(options?: AuthRequestOptions): Promise; +export class GithubAuth { // (undocumented) + static create(options: OAuthApiCreateOptions): typeof githubAuthApiRef.T; + // @deprecated (undocumented) static normalizeScope(scope?: string): Set; - // (undocumented) - sessionState$(): Observable; - // (undocumented) - signIn(): Promise; - // (undocumented) - signOut(): Promise; } // @public @deprecated diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index b60008a1a8..a546e29134 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": "0.5.1", + "version": "0.5.2", "private": false, "publishConfig": { "access": "public", @@ -45,8 +45,8 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/packages/core-app-api/src/apis/implementations/auth/github/GithubAuth.test.ts b/packages/core-app-api/src/apis/implementations/auth/github/GithubAuth.test.ts index 8bcd4cb7a5..ea7b4ac688 100644 --- a/packages/core-app-api/src/apis/implementations/auth/github/GithubAuth.test.ts +++ b/packages/core-app-api/src/apis/implementations/auth/github/GithubAuth.test.ts @@ -14,16 +14,33 @@ * limitations under the License. */ +import { UrlPatternDiscovery } from '../../DiscoveryApi'; +import MockOAuthApi from '../../OAuthRequestApi/MockOAuthApi'; import GithubAuth from './GithubAuth'; -describe('GithubAuth', () => { - it('should get access token', async () => { - const getSession = jest - .fn() - .mockResolvedValue({ providerInfo: { accessToken: 'access-token' } }); - const githubAuth = new (GithubAuth as any)({ getSession }) as GithubAuth; +const getSession = jest.fn(); - expect(await githubAuth.getAccessToken()).toBe('access-token'); - expect(getSession).toBeCalledTimes(1); +jest.mock('../../../../lib/AuthSessionManager', () => ({ + ...(jest.requireActual('../../../../lib/AuthSessionManager') as any), + RefreshingAuthSessionManager: class { + getSession = getSession; + }, +})); + +describe('GithubAuth', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + + it('should forward access token request to session manager', async () => { + const githubAuth = GithubAuth.create({ + oauthRequestApi: new MockOAuthApi(), + discoveryApi: UrlPatternDiscovery.compile('http://example.com'), + }); + + githubAuth.getAccessToken('repo'); + expect(getSession).toHaveBeenCalledWith({ + scopes: new Set(['repo']), + }); }); }); diff --git a/packages/core-app-api/src/apis/implementations/auth/github/GithubAuth.ts b/packages/core-app-api/src/apis/implementations/auth/github/GithubAuth.ts index dc2c15bc16..b0af4c7ade 100644 --- a/packages/core-app-api/src/apis/implementations/auth/github/GithubAuth.ts +++ b/packages/core-app-api/src/apis/implementations/auth/github/GithubAuth.ts @@ -14,35 +14,9 @@ * limitations under the License. */ -import { - AuthRequestOptions, - BackstageIdentityResponse, - OAuthApi, - ProfileInfo, - SessionApi, - SessionState, -} from '@backstage/core-plugin-api'; -import { Observable } from '@backstage/types'; -import { DefaultAuthConnector } from '../../../../lib/AuthConnector'; -import { - AuthSessionStore, - RefreshingAuthSessionManager, - StaticAuthSessionManager, -} from '../../../../lib/AuthSessionManager'; -import { OptionalRefreshSessionManagerMux } from '../../../../lib/AuthSessionManager/OptionalRefreshSessionManagerMux'; -import { SessionManager } from '../../../../lib/AuthSessionManager/types'; +import { githubAuthApiRef } from '@backstage/core-plugin-api'; +import { OAuth2 } from '../oauth2'; import { OAuthApiCreateOptions } from '../types'; -import { GithubSession, githubSessionSchema } from './types'; - -export type GithubAuthResponse = { - providerInfo: { - accessToken: string; - scope: string; - expiresInSeconds?: number; - }; - profile: ProfileInfo; - backstageIdentity: BackstageIdentityResponse; -}; const DEFAULT_PROVIDER = { id: 'github', @@ -55,8 +29,8 @@ const DEFAULT_PROVIDER = { * * @public */ -export default class GithubAuth implements OAuthApi, SessionApi { - static create(options: OAuthApiCreateOptions) { +export default class GithubAuth { + static create(options: OAuthApiCreateOptions): typeof githubAuthApiRef.T { const { discoveryApi, environment = 'development', @@ -65,96 +39,18 @@ export default class GithubAuth implements OAuthApi, SessionApi { defaultScopes = ['read:user'], } = options; - const connector = new DefaultAuthConnector({ + return OAuth2.create({ discoveryApi, - environment, + oauthRequestApi, provider, - oauthRequestApi: oauthRequestApi, - sessionTransform(res: GithubAuthResponse): GithubSession { - return { - ...res, - providerInfo: { - accessToken: res.providerInfo.accessToken, - scopes: GithubAuth.normalizeScope(res.providerInfo.scope), - expiresAt: res.providerInfo.expiresInSeconds - ? new Date(Date.now() + res.providerInfo.expiresInSeconds * 1000) - : undefined, - }, - }; - }, + environment, + defaultScopes, }); - - const refreshingSessionManager = new RefreshingAuthSessionManager({ - connector, - defaultScopes: new Set(defaultScopes), - sessionScopes: (session: GithubSession) => session.providerInfo.scopes, - sessionShouldRefresh: (session: GithubSession) => { - const { expiresAt } = session.providerInfo; - if (!expiresAt) { - return false; - } - const expiresInSec = (expiresAt.getTime() - Date.now()) / 1000; - return expiresInSec < 60 * 5; - }, - }); - - const staticSessionManager = new AuthSessionStore({ - manager: new StaticAuthSessionManager({ - connector, - defaultScopes: new Set(defaultScopes), - sessionScopes: (session: GithubSession) => session.providerInfo.scopes, - }), - storageKey: `${provider.id}Session`, - schema: githubSessionSchema, - sessionScopes: (session: GithubSession) => session.providerInfo.scopes, - }); - - const sessionManagerMux = new OptionalRefreshSessionManagerMux({ - refreshingSessionManager, - staticSessionManager, - sessionCanRefresh: session => - session.providerInfo.expiresAt !== undefined, - }); - - return new GithubAuth(sessionManagerMux); - } - - private constructor( - private readonly sessionManager: SessionManager, - ) {} - - async signIn() { - await this.getAccessToken(); - } - - async signOut() { - await this.sessionManager.removeSession(); - } - - sessionState$(): Observable { - return this.sessionManager.sessionState$(); - } - - async getAccessToken(scope?: string, options?: AuthRequestOptions) { - const session = await this.sessionManager.getSession({ - ...options, - scopes: GithubAuth.normalizeScope(scope), - }); - return session?.providerInfo.accessToken ?? ''; - } - - async getBackstageIdentity( - options: AuthRequestOptions = {}, - ): Promise { - const session = await this.sessionManager.getSession(options); - return session?.backstageIdentity; - } - - async getProfile(options: AuthRequestOptions = {}) { - const session = await this.sessionManager.getSession(options); - return session?.profile; } + /** + * @deprecated This method is deprecated and will be removed in a future release. + */ static normalizeScope(scope?: string): Set { if (!scope) { return new Set(); diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index a22b029abd..27cf543205 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/core-components +## 0.8.7 + +### Patch Changes + +- f7257dff6f: The `` component now accepts a `noTrack` prop, which prevents the `click` event from being captured by the Analytics API. This can be used if tracking is explicitly not warranted, or in order to use custom link tracking in specific situations. +- 4c773ed25c: Change subtitle of Header style to use palette.bursts.fontColor +- f465b63b7f: Fix an issue where changes related to the `MobileSidebar` prevented scrolling pages. Additionally improve the menu of the `MobileSidebar` to not overlay the `BottomNavigation`. +- 064e750a50: Adding hover message to the Gauge and an info icon to the GaugeCard. +- a681cb9c2f: Make linkTarget configurable for MarkdownContent component + +## 0.8.7-next.1 + +### Patch Changes + +- f7257dff6f: The `` component now accepts a `noTrack` prop, which prevents the `click` event from being captured by the Analytics API. This can be used if tracking is explicitly not warranted, or in order to use custom link tracking in specific situations. + ## 0.8.7-next.0 ### Patch Changes diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index 47ca3d3cf8..6365b4f9d7 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -384,7 +384,12 @@ export function GaugeCard(props: Props_10): JSX.Element; export type GaugeCardClassKey = 'root'; // @public (undocumented) -export type GaugeClassKey = 'root' | 'overlay' | 'circle' | 'colorUnknown'; +export type GaugeClassKey = + | 'root' + | 'overlay' + | 'description' + | 'circle' + | 'colorUnknown'; // @public (undocumented) export type GaugeProps = { @@ -393,6 +398,7 @@ export type GaugeProps = { inverse?: boolean; unit?: string; max?: number; + description?: ReactNode; getColor?: GaugePropsGetColor; }; diff --git a/packages/core-components/package.json b/packages/core-components/package.json index ed4df67a89..a6e9962abe 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.8.7-next.0", + "version": "0.8.7", "private": false, "publishConfig": { "access": "public", @@ -39,7 +39,7 @@ "@material-ui/lab": "4.0.0-alpha.57", "@types/react-sparklines": "^1.7.0", "@types/react-text-truncate": "^0.14.0", - "ansi-regex": "^5.0.1", + "ansi-regex": "^6.0.1", "classnames": "^2.2.6", "d3-selection": "^3.0.0", "d3-shape": "^3.0.0", @@ -73,9 +73,9 @@ "react-dom": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/core-app-api": "^0.5.1", - "@backstage/cli": "^0.13.1-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/core-app-api": "^0.5.2", + "@backstage/cli": "^0.13.1", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/packages/core-components/src/components/ProgressBars/Gauge.tsx b/packages/core-components/src/components/ProgressBars/Gauge.tsx index 0336ebc990..11f977b387 100644 --- a/packages/core-components/src/components/ProgressBars/Gauge.tsx +++ b/packages/core-components/src/components/ProgressBars/Gauge.tsx @@ -17,10 +17,15 @@ import { BackstagePalette, BackstageTheme } from '@backstage/theme'; import { makeStyles, useTheme } from '@material-ui/core/styles'; import { Circle } from 'rc-progress'; -import React from 'react'; +import React, { ReactNode, useEffect, useState } from 'react'; /** @public */ -export type GaugeClassKey = 'root' | 'overlay' | 'circle' | 'colorUnknown'; +export type GaugeClassKey = + | 'root' + | 'overlay' + | 'description' + | 'circle' + | 'colorUnknown'; const useStyles = makeStyles( theme => ({ @@ -37,6 +42,15 @@ const useStyles = makeStyles( fontWeight: 'bold', color: theme.palette.textContrast, }, + description: { + fontSize: '100%', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + position: 'absolute', + wordBreak: 'break-all', + display: 'inline-block', + }, circle: { width: '80%', transform: 'translate(10%, 0)', @@ -53,6 +67,7 @@ export type GaugeProps = { inverse?: boolean; unit?: string; max?: number; + description?: ReactNode; getColor?: GaugePropsGetColor; }; @@ -104,10 +119,11 @@ export const getProgressColor: GaugePropsGetColor = ({ */ export function Gauge(props: GaugeProps) { + const [hoverRef, setHoverRef] = useState(null); const { getColor = getProgressColor } = props; const classes = useStyles(props); const { palette } = useTheme(); - const { value, fractional, inverse, unit, max } = { + const { value, fractional, inverse, unit, max, description } = { ...defaultGaugeProps, ...props, }; @@ -115,8 +131,28 @@ export function Gauge(props: GaugeProps) { const asPercentage = fractional ? Math.round(value * max) : value; const asActual = max !== 100 ? Math.round(value) : asPercentage; + const [isHovering, setIsHovering] = useState(false); + + useEffect(() => { + const node = hoverRef; + const handleMouseOver = () => setIsHovering(true); + const handleMouseOut = () => setIsHovering(false); + if (node && description) { + node.addEventListener('mouseenter', handleMouseOver); + node.addEventListener('mouseleave', handleMouseOut); + + return () => { + node.removeEventListener('mouseenter', handleMouseOver); + node.removeEventListener('mouseleave', handleMouseOut); + }; + } + return () => { + setIsHovering(false); + }; + }, [description, hoverRef]); + return ( -
+
-
- {isNaN(value) ? 'N/A' : `${asActual}${unit}`} -
+ {description && isHovering ? ( +
{description}
+ ) : ( +
+ {isNaN(value) ? 'N/A' : `${asActual}${unit}`} +
+ )}
); } diff --git a/packages/core-components/src/components/ProgressBars/GaugeCard.stories.tsx b/packages/core-components/src/components/ProgressBars/GaugeCard.stories.tsx index 64a6cc1b16..08c7813643 100644 --- a/packages/core-components/src/components/ProgressBars/GaugeCard.stories.tsx +++ b/packages/core-components/src/components/ProgressBars/GaugeCard.stories.tsx @@ -18,6 +18,8 @@ import React, { PropsWithChildren } from 'react'; import { GaugeCard } from './GaugeCard'; import Grid from '@material-ui/core/Grid'; import { MemoryRouter } from 'react-router'; +import Tooltip from '@material-ui/core/Tooltip'; +import Info from '@material-ui/icons/Info'; const linkInfo = { title: 'Go to XYZ Location', link: '#' }; @@ -118,3 +120,79 @@ export const StaticColor = () => ( ); + +export const InfoMessage = () => ( + + + + + + } + /> + + + + + + } + /> + + + + + + } + /> + + + + + + } + /> + + +); + +export const HoverMessage = () => ( + + + + + + + + + + + + + + +); diff --git a/packages/core-components/src/components/ProgressBars/GaugeCard.tsx b/packages/core-components/src/components/ProgressBars/GaugeCard.tsx index 9e6c19ebfe..1114890523 100644 --- a/packages/core-components/src/components/ProgressBars/GaugeCard.tsx +++ b/packages/core-components/src/components/ProgressBars/GaugeCard.tsx @@ -15,7 +15,7 @@ */ import { makeStyles } from '@material-ui/core/styles'; -import React from 'react'; +import React, { ReactNode } from 'react'; import { BottomLinkProps } from '../../layout/BottomLink'; import { InfoCard, InfoCardVariants } from '../../layout/InfoCard'; import { Gauge, GaugePropsGetColor } from './Gauge'; @@ -26,6 +26,8 @@ type Props = { variant?: InfoCardVariants; /** Progress in % specified as decimal, e.g. "0.23" */ progress: number; + description?: ReactNode; + icon?: ReactNode; inverse?: boolean; deepLink?: BottomLinkProps; getColor?: GaugePropsGetColor; @@ -52,11 +54,21 @@ const useStyles = makeStyles( */ export function GaugeCard(props: Props) { const classes = useStyles(props); - const { title, subheader, progress, inverse, deepLink, variant, getColor } = - props; + const { + title, + subheader, + progress, + inverse, + deepLink, + description, + icon, + variant, + getColor, + } = props; const gaugeProps = { inverse, + description, getColor, value: progress, }; @@ -68,6 +80,7 @@ export function GaugeCard(props: Props) { subheader={subheader} deepLink={deepLink} variant={variant} + icon={icon} > diff --git a/packages/core-components/src/layout/InfoCard/InfoCard.tsx b/packages/core-components/src/layout/InfoCard/InfoCard.tsx index f1e67904f1..256d60cfa2 100644 --- a/packages/core-components/src/layout/InfoCard/InfoCard.tsx +++ b/packages/core-components/src/layout/InfoCard/InfoCard.tsx @@ -55,6 +55,9 @@ const useStyles = makeStyles( headerAvatar: {}, headerAction: {}, headerContent: {}, + subheader: { + display: 'flex', + }, }), { name: 'BackstageInfoCard' }, ); @@ -134,6 +137,7 @@ type Props = { children?: ReactNode; headerStyle?: object; headerProps?: CardHeaderProps; + icon?: ReactNode; action?: ReactNode; actionsClassName?: string; actions?: ReactNode; @@ -162,6 +166,7 @@ export function InfoCard(props: Props): JSX.Element { children, headerStyle, headerProps, + icon, action, actionsClassName, actions, @@ -194,6 +199,15 @@ export function InfoCard(props: Props): JSX.Element { }); } + const cardSubTitle = () => { + return ( +
+ {subheader &&
{subheader}
} + {icon} +
+ ); + }; + const errProps: ErrorBoundaryProps = errorBoundaryProps || (slackChannel ? { slackChannel } : {}); @@ -211,7 +225,7 @@ export function InfoCard(props: Props): JSX.Element { content: classes.headerContent, }} title={title} - subheader={subheader} + subheader={cardSubTitle()} action={action} style={{ ...headerStyle }} titleTypographyProps={titleTypographyProps} diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index 2de6170d73..5186fca4dd 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -43,9 +43,9 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1-next.1", + "@backstage/core-app-api": "^0.5.2-next.0", + "@backstage/test-utils": "^0.2.4-next.0", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 411043b83a..6cb892905b 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,108 @@ # @backstage/create-app +## 0.4.18 + +### Patch Changes + +- 5bd0ce9e62: chore(deps): bump `inquirer` from 7.3.3 to 8.2.0 +- f27f5197e2: Apply the fix from `0.4.16`, which is part of the `v0.65.1` release of Backstage. +- 2687029a67: Update backend-to-backend auth link in configuration file comment +- 24ef62048c: Adds missing `/catalog-graph` route to ``. + + To fix this problem for a recently created app please update your `app/src/App.tsx` + + ```diff + + import { CatalogGraphPage } from '@backstage/plugin-catalog-graph'; + + ... omitted ... + + + } /> + + } /> + + ``` + +- ba59832aed: Permission the `catalog-import` route + + The following changes are **required** if you intend to add permissions to your existing app. + + Use the `PermissionedRoute` for `CatalogImportPage` instead of the normal `Route`: + + ```diff + // packages/app/src/App.tsx + ... + + import { PermissionedRoute } from '@backstage/plugin-permission-react'; + + import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common'; + + ... + + - } /> + + } + + /> + ``` + +- cef64b1561: Added `tokenManager` as a required property for the auth-backend `createRouter` function. This dependency is used to issue server tokens that are used by the `CatalogIdentityClient` when looking up users and their group membership during authentication. + + These changes are **required** to `packages/backend/src/plugins/auth.ts`: + + ```diff + export default async function createPlugin({ + logger, + database, + config, + discovery, + + tokenManager, + }: PluginEnvironment): Promise { + return await createRouter({ + logger, + config, + database, + discovery, + + tokenManager, + }); + } + ``` + +- e39d88bd84: Switched the `app` dependency in the backend to use a file target rather than version. + + To apply this change to an existing app, make the following change to `packages/backend/package.json`: + + ```diff + "dependencies": { + - "app": "0.0.0", + + "app": "file:../app", + ``` + +## 0.4.18-next.1 + +### Patch Changes + +- 5bd0ce9e62: chore(deps): bump `inquirer` from 7.3.3 to 8.2.0 +- ba59832aed: Permission the `catalog-import` route + + The following changes are **required** if you intend to add permissions to your existing app. + + Use the `PermissionedRoute` for `CatalogImportPage` instead of the normal `Route`: + + ```diff + // packages/app/src/App.tsx + ... + + import { PermissionedRoute } from '@backstage/plugin-permission-react'; + + import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common'; + + ... + + - } /> + + } + + /> + ``` + ## 0.4.18-next.0 ### Patch Changes @@ -102,7 +205,7 @@ To make this change to an existing app: - Add `@backstage/catalog-graph-plugin` as a `dependency` in `packages/app/package.json` + Add `@backstage/plugin-catalog-graph` as a `dependency` in `packages/app/package.json` Apply the following changes to the `packages/app/src/components/catalog/EntityPage.tsx` file: diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 2b35b5e289..a679942a53 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.4.18-next.0", + "version": "0.4.18", "private": false, "publishConfig": { "access": "public" @@ -35,7 +35,7 @@ "commander": "^6.1.0", "fs-extra": "9.1.0", "handlebars": "^4.7.3", - "inquirer": "^7.0.4", + "inquirer": "^8.2.0", "ora": "^5.3.0", "recursive-readdir": "^2.2.2" }, diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index f424bce947..2e34bcaefa 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/dev-utils +## 0.2.20 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + - @backstage/integration-react@0.1.20 + - @backstage/core-app-api@0.5.2 + - @backstage/app-defaults@0.1.6 + - @backstage/test-utils@0.2.4 + +## 0.2.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7-next.1 + - @backstage/plugin-catalog-react@0.6.13-next.1 + - @backstage/core-app-api@0.5.2-next.0 + - @backstage/app-defaults@0.1.6-next.1 + - @backstage/test-utils@0.2.4-next.0 + ## 0.2.20-next.0 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 585ff0f83d..1f59a143e1 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/dev-utils", "description": "Utilities for developing Backstage plugins.", - "version": "0.2.20-next.0", + "version": "0.2.20", "private": false, "publishConfig": { "access": "public", @@ -29,14 +29,14 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/app-defaults": "^0.1.6-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/app-defaults": "^0.1.6", + "@backstage/core-app-api": "^0.5.2", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/catalog-model": "^0.9.10", - "@backstage/integration-react": "^0.1.20-next.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/integration-react": "^0.1.20", + "@backstage/plugin-catalog-react": "^0.6.13", + "@backstage/test-utils": "^0.2.4", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -55,7 +55,7 @@ "react-dom": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@types/jest": "^26.0.7", "@types/node": "^14.14.32" }, diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index 35c60a86f1..4e191866b4 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/integration-react +## 0.1.20 + +### Patch Changes + +- cee44ad289: Added the ability to collect users `oauth` token from the `RepoUrlPicker` for use in the template manifest +- Updated dependencies + - @backstage/core-components@0.8.7 + ## 0.1.20-next.0 ### Patch Changes diff --git a/packages/integration-react/api-report.md b/packages/integration-react/api-report.md index 2db29631a3..5b0c9d6174 100644 --- a/packages/integration-react/api-report.md +++ b/packages/integration-react/api-report.md @@ -29,6 +29,7 @@ export class ScmAuth implements ScmAuthApi { ProfileInfoApi & BackstageIdentityApi & SessionApi; + bitbucket: OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi; } >; static forAuthApi( @@ -82,6 +83,12 @@ export const scmAuthApiRef: ApiRef; export interface ScmAuthTokenOptions extends AuthRequestOptions { additionalScope?: { repoWrite?: boolean; + customScopes?: { + github?: string[]; + azure?: string[]; + bitbucket?: string[]; + gitlab?: string[]; + }; }; url: string; } diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index ae028d39c2..255565fafa 100644 --- a/packages/integration-react/package.json +++ b/packages/integration-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration-react", "description": "Frontend package for managing integrations towards external systems", - "version": "0.1.20-next.0", + "version": "0.1.20", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,7 +22,7 @@ }, "dependencies": { "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/integration": "^0.7.2", "@backstage/theme": "^0.2.14", @@ -35,9 +35,9 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/packages/integration-react/src/api/ScmAuth.test.ts b/packages/integration-react/src/api/ScmAuth.test.ts index 2d0ea9b97d..4ebfef749e 100644 --- a/packages/integration-react/src/api/ScmAuth.test.ts +++ b/packages/integration-react/src/api/ScmAuth.test.ts @@ -141,6 +141,58 @@ describe('ScmAuth', () => { }); }); + it('should support additional provided scopes from the caller', async () => { + const mockAuthApi = { + getAccessToken: async (scopes: string[]) => { + return scopes.join(' '); + }, + }; + + const githubAuth = ScmAuth.forGithub(mockAuthApi); + await expect( + githubAuth.getCredentials({ + url: 'http://example.com', + additionalScope: { + customScopes: { github: ['org:read', 'workflow:write'] }, + }, + }), + ).resolves.toMatchObject({ + token: 'repo read:org read:user org:read workflow:write', + }); + + const gitlabAuth = ScmAuth.forGitlab(mockAuthApi); + await expect( + gitlabAuth.getCredentials({ + url: 'http://example.com', + additionalScope: { customScopes: { gitlab: ['write_repository'] } }, + }), + ).resolves.toMatchObject({ + token: 'read_user read_api read_repository write_repository', + }); + + const azureAuth = ScmAuth.forAzure(mockAuthApi); + await expect( + azureAuth.getCredentials({ + url: 'http://example.com', + additionalScope: { customScopes: { azure: ['vso.org'] } }, + }), + ).resolves.toMatchObject({ + token: 'vso.build vso.code vso.graph vso.project vso.profile vso.org', + }); + + const bitbucketAuth = ScmAuth.forBitbucket(mockAuthApi); + await expect( + bitbucketAuth.getCredentials({ + url: 'http://example.com', + additionalScope: { + customScopes: { bitbucket: ['snippet:write', 'issue:write'] }, + }, + }), + ).resolves.toMatchObject({ + token: 'account team pullrequest snippet issue snippet:write issue:write', + }); + }); + it('should handle host option', () => { const mockAuthApi = { getAccessToken: jest.fn(), diff --git a/packages/integration-react/src/api/ScmAuth.ts b/packages/integration-react/src/api/ScmAuth.ts index be3216962d..071374e6cb 100644 --- a/packages/integration-react/src/api/ScmAuth.ts +++ b/packages/integration-react/src/api/ScmAuth.ts @@ -15,6 +15,7 @@ */ import { + bitbucketAuthApiRef, createApiFactory, githubAuthApiRef, gitlabAuthApiRef, @@ -35,6 +36,9 @@ type ScopeMapping = { repoWrite: string[]; }; +// An enum of all supported providers +type ProviderName = 'generic' | 'github' | 'azure' | 'bitbucket' | 'gitlab'; + class ScmAuthMux implements ScmAuthApi { #providers: Array; @@ -93,12 +97,14 @@ export class ScmAuth implements ScmAuthApi { github: githubAuthApiRef, gitlab: gitlabAuthApiRef, azure: microsoftAuthApiRef, + bitbucket: bitbucketAuthApiRef, }, - factory: ({ github, gitlab, azure }) => + factory: ({ github, gitlab, azure, bitbucket }) => ScmAuth.merge( ScmAuth.forGithub(github), ScmAuth.forGitlab(gitlab), ScmAuth.forAzure(azure), + ScmAuth.forBitbucket(bitbucket), ), }); } @@ -116,7 +122,7 @@ export class ScmAuth implements ScmAuthApi { }; }, ): ScmAuth { - return new ScmAuth(authApi, options.host, options.scopeMapping); + return new ScmAuth('generic', authApi, options.host, options.scopeMapping); } /** @@ -139,7 +145,7 @@ export class ScmAuth implements ScmAuthApi { }, ): ScmAuth { const host = options?.host ?? 'github.com'; - return new ScmAuth(githubAuthApi, host, { + return new ScmAuth('github', githubAuthApi, host, { default: ['repo', 'read:org', 'read:user'], repoWrite: ['gist'], }); @@ -165,7 +171,7 @@ export class ScmAuth implements ScmAuthApi { }, ): ScmAuth { const host = options?.host ?? 'gitlab.com'; - return new ScmAuth(gitlabAuthApi, host, { + return new ScmAuth('gitlab', gitlabAuthApi, host, { default: ['read_user', 'read_api', 'read_repository'], repoWrite: ['write_repository', 'api'], }); @@ -191,7 +197,7 @@ export class ScmAuth implements ScmAuthApi { }, ): ScmAuth { const host = options?.host ?? 'dev.azure.com'; - return new ScmAuth(microsoftAuthApi, host, { + return new ScmAuth('azure', microsoftAuthApi, host, { default: [ 'vso.build', 'vso.code', @@ -223,7 +229,7 @@ export class ScmAuth implements ScmAuthApi { }, ): ScmAuth { const host = options?.host ?? 'bitbucket.org'; - return new ScmAuth(bitbucketAuthApi, host, { + return new ScmAuth('bitbucket', bitbucketAuthApi, host, { default: ['account', 'team', 'pullrequest', 'snippet', 'issue'], repoWrite: ['pullrequest:write', 'snippet:write', 'issue:write'], }); @@ -240,11 +246,18 @@ export class ScmAuth implements ScmAuthApi { #api: OAuthApi; #host: string; #scopeMapping: ScopeMapping; + #providerName: ProviderName; - private constructor(api: OAuthApi, host: string, scopeMapping: ScopeMapping) { + private constructor( + providerName: ProviderName, + api: OAuthApi, + host: string, + scopeMapping: ScopeMapping, + ) { this.#api = api; this.#host = host; this.#scopeMapping = scopeMapping; + this.#providerName = providerName; } /** @@ -254,6 +267,16 @@ export class ScmAuth implements ScmAuthApi { return url.host === this.#host; } + private getAdditionalScopesForProvider( + additionalScopes: ScmAuthTokenOptions['additionalScope'], + ): string[] { + if (!additionalScopes?.customScopes || this.#providerName === 'generic') { + return []; + } + + return additionalScopes.customScopes?.[this.#providerName] ?? []; + } + /** * Fetches credentials for the given resource. */ @@ -267,7 +290,17 @@ export class ScmAuth implements ScmAuthApi { scopes.push(...this.#scopeMapping.repoWrite); } - const token = await this.#api.getAccessToken(scopes, restOptions); + const additionalScopes = + this.getAdditionalScopesForProvider(additionalScope); + + if (additionalScopes.length) { + scopes.push(...additionalScopes); + } + + const uniqueScopes = [...new Set(scopes)]; + + const token = await this.#api.getAccessToken(uniqueScopes, restOptions); + return { token, headers: { diff --git a/packages/integration-react/src/api/ScmAuthApi.ts b/packages/integration-react/src/api/ScmAuthApi.ts index 44b007c4a2..be65842bc1 100644 --- a/packages/integration-react/src/api/ScmAuthApi.ts +++ b/packages/integration-react/src/api/ScmAuthApi.ts @@ -44,6 +44,16 @@ export interface ScmAuthTokenOptions extends AuthRequestOptions { * the ability to create things like issues and pull requests. */ repoWrite?: boolean; + /** + * Allow an arbitrary list of scopes provided from the user + * to request from the provider. + */ + customScopes?: { + github?: string[]; + azure?: string[]; + bitbucket?: string[]; + gitlab?: string[]; + }; }; } diff --git a/packages/integration/package.json b/packages/integration/package.json index c4e0b003f2..41ed3f08c3 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -39,9 +39,9 @@ "lodash": "^4.17.21" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1-next.1", "@backstage/config-loader": "^0.9.3", - "@backstage/test-utils": "^0.2.3", + "@backstage/test-utils": "^0.2.4-next.0", "@types/jest": "^26.0.7", "@types/luxon": "^2.0.4", "msw": "^0.35.0" diff --git a/packages/embedded-techdocs-app/.eslintrc.js b/packages/techdocs-cli-embedded-app/.eslintrc.js similarity index 100% rename from packages/embedded-techdocs-app/.eslintrc.js rename to packages/techdocs-cli-embedded-app/.eslintrc.js diff --git a/packages/embedded-techdocs-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md similarity index 82% rename from packages/embedded-techdocs-app/CHANGELOG.md rename to packages/techdocs-cli-embedded-app/CHANGELOG.md index 299423dd1d..27c4719686 100644 --- a/packages/embedded-techdocs-app/CHANGELOG.md +++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md @@ -1,4 +1,31 @@ -# embedded-techdocs-app +# techdocs-cli-embedded-app + +## 0.2.62 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/cli@0.13.1 + - @backstage/integration-react@0.1.20 + - @backstage/core-app-api@0.5.2 + - @backstage/plugin-techdocs@0.13.2 + - @backstage/app-defaults@0.1.6 + - @backstage/test-utils@0.2.4 + - @backstage/plugin-catalog@0.7.11 + +## 0.2.62-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7-next.1 + - @backstage/cli@0.13.1-next.1 + - @backstage/core-app-api@0.5.2-next.0 + - @backstage/plugin-techdocs@0.13.2-next.1 + - @backstage/plugin-catalog@0.7.11-next.1 + - @backstage/app-defaults@0.1.6-next.1 + - @backstage/test-utils@0.2.4-next.0 ## 0.2.62-next.0 diff --git a/packages/embedded-techdocs-app/app-config.dev.yaml b/packages/techdocs-cli-embedded-app/app-config.dev.yaml similarity index 100% rename from packages/embedded-techdocs-app/app-config.dev.yaml rename to packages/techdocs-cli-embedded-app/app-config.dev.yaml diff --git a/packages/embedded-techdocs-app/app-config.yaml b/packages/techdocs-cli-embedded-app/app-config.yaml similarity index 100% rename from packages/embedded-techdocs-app/app-config.yaml rename to packages/techdocs-cli-embedded-app/app-config.yaml diff --git a/packages/embedded-techdocs-app/cypress.json b/packages/techdocs-cli-embedded-app/cypress.json similarity index 100% rename from packages/embedded-techdocs-app/cypress.json rename to packages/techdocs-cli-embedded-app/cypress.json diff --git a/packages/embedded-techdocs-app/cypress/.eslintrc.json b/packages/techdocs-cli-embedded-app/cypress/.eslintrc.json similarity index 100% rename from packages/embedded-techdocs-app/cypress/.eslintrc.json rename to packages/techdocs-cli-embedded-app/cypress/.eslintrc.json diff --git a/packages/embedded-techdocs-app/cypress/integration/app.js b/packages/techdocs-cli-embedded-app/cypress/integration/app.js similarity index 100% rename from packages/embedded-techdocs-app/cypress/integration/app.js rename to packages/techdocs-cli-embedded-app/cypress/integration/app.js diff --git a/packages/embedded-techdocs-app/package.json b/packages/techdocs-cli-embedded-app/package.json similarity index 78% rename from packages/embedded-techdocs-app/package.json rename to packages/techdocs-cli-embedded-app/package.json index bfda40905b..6eb3119b06 100644 --- a/packages/embedded-techdocs-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -1,20 +1,20 @@ { - "name": "embedded-techdocs-app", - "version": "0.2.62-next.0", + "name": "techdocs-cli-embedded-app", + "version": "0.2.62", "private": true, "bundled": true, "dependencies": { - "@backstage/app-defaults": "^0.1.6-next.0", + "@backstage/app-defaults": "^0.1.6", "@backstage/catalog-model": "^0.9.10", - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@backstage/config": "^0.1.13", - "@backstage/core-app-api": "^0.5.1", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-app-api": "^0.5.2", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", - "@backstage/integration-react": "^0.1.20-next.0", - "@backstage/plugin-catalog": "^0.7.11-next.0", - "@backstage/plugin-techdocs": "^0.13.2-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/integration-react": "^0.1.20", + "@backstage/plugin-catalog": "^0.7.11", + "@backstage/plugin-techdocs": "^0.13.2", + "@backstage/test-utils": "^0.2.4", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -26,7 +26,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/packages/embedded-techdocs-app/public/android-chrome-192x192.png b/packages/techdocs-cli-embedded-app/public/android-chrome-192x192.png similarity index 100% rename from packages/embedded-techdocs-app/public/android-chrome-192x192.png rename to packages/techdocs-cli-embedded-app/public/android-chrome-192x192.png diff --git a/packages/embedded-techdocs-app/public/apple-touch-icon.png b/packages/techdocs-cli-embedded-app/public/apple-touch-icon.png similarity index 100% rename from packages/embedded-techdocs-app/public/apple-touch-icon.png rename to packages/techdocs-cli-embedded-app/public/apple-touch-icon.png diff --git a/packages/embedded-techdocs-app/public/favicon-16x16.png b/packages/techdocs-cli-embedded-app/public/favicon-16x16.png similarity index 100% rename from packages/embedded-techdocs-app/public/favicon-16x16.png rename to packages/techdocs-cli-embedded-app/public/favicon-16x16.png diff --git a/packages/embedded-techdocs-app/public/favicon-32x32.png b/packages/techdocs-cli-embedded-app/public/favicon-32x32.png similarity index 100% rename from packages/embedded-techdocs-app/public/favicon-32x32.png rename to packages/techdocs-cli-embedded-app/public/favicon-32x32.png diff --git a/packages/embedded-techdocs-app/public/favicon.ico b/packages/techdocs-cli-embedded-app/public/favicon.ico similarity index 100% rename from packages/embedded-techdocs-app/public/favicon.ico rename to packages/techdocs-cli-embedded-app/public/favicon.ico diff --git a/packages/embedded-techdocs-app/public/index.html b/packages/techdocs-cli-embedded-app/public/index.html similarity index 100% rename from packages/embedded-techdocs-app/public/index.html rename to packages/techdocs-cli-embedded-app/public/index.html diff --git a/packages/embedded-techdocs-app/public/manifest.json b/packages/techdocs-cli-embedded-app/public/manifest.json similarity index 100% rename from packages/embedded-techdocs-app/public/manifest.json rename to packages/techdocs-cli-embedded-app/public/manifest.json diff --git a/packages/embedded-techdocs-app/public/robots.txt b/packages/techdocs-cli-embedded-app/public/robots.txt similarity index 100% rename from packages/embedded-techdocs-app/public/robots.txt rename to packages/techdocs-cli-embedded-app/public/robots.txt diff --git a/packages/embedded-techdocs-app/public/safari-pinned-tab.svg b/packages/techdocs-cli-embedded-app/public/safari-pinned-tab.svg similarity index 100% rename from packages/embedded-techdocs-app/public/safari-pinned-tab.svg rename to packages/techdocs-cli-embedded-app/public/safari-pinned-tab.svg diff --git a/packages/embedded-techdocs-app/src/App.test.tsx b/packages/techdocs-cli-embedded-app/src/App.test.tsx similarity index 100% rename from packages/embedded-techdocs-app/src/App.test.tsx rename to packages/techdocs-cli-embedded-app/src/App.test.tsx diff --git a/packages/embedded-techdocs-app/src/App.tsx b/packages/techdocs-cli-embedded-app/src/App.tsx similarity index 100% rename from packages/embedded-techdocs-app/src/App.tsx rename to packages/techdocs-cli-embedded-app/src/App.tsx diff --git a/packages/embedded-techdocs-app/src/apis.ts b/packages/techdocs-cli-embedded-app/src/apis.ts similarity index 100% rename from packages/embedded-techdocs-app/src/apis.ts rename to packages/techdocs-cli-embedded-app/src/apis.ts diff --git a/packages/embedded-techdocs-app/src/components/Root/LogoFull.tsx b/packages/techdocs-cli-embedded-app/src/components/Root/LogoFull.tsx similarity index 100% rename from packages/embedded-techdocs-app/src/components/Root/LogoFull.tsx rename to packages/techdocs-cli-embedded-app/src/components/Root/LogoFull.tsx diff --git a/packages/embedded-techdocs-app/src/components/Root/LogoIcon.tsx b/packages/techdocs-cli-embedded-app/src/components/Root/LogoIcon.tsx similarity index 100% rename from packages/embedded-techdocs-app/src/components/Root/LogoIcon.tsx rename to packages/techdocs-cli-embedded-app/src/components/Root/LogoIcon.tsx diff --git a/packages/embedded-techdocs-app/src/components/Root/Root.tsx b/packages/techdocs-cli-embedded-app/src/components/Root/Root.tsx similarity index 100% rename from packages/embedded-techdocs-app/src/components/Root/Root.tsx rename to packages/techdocs-cli-embedded-app/src/components/Root/Root.tsx diff --git a/packages/embedded-techdocs-app/src/components/Root/index.ts b/packages/techdocs-cli-embedded-app/src/components/Root/index.ts similarity index 100% rename from packages/embedded-techdocs-app/src/components/Root/index.ts rename to packages/techdocs-cli-embedded-app/src/components/Root/index.ts diff --git a/packages/embedded-techdocs-app/src/components/TechDocsPage/TechDocsPage.tsx b/packages/techdocs-cli-embedded-app/src/components/TechDocsPage/TechDocsPage.tsx similarity index 100% rename from packages/embedded-techdocs-app/src/components/TechDocsPage/TechDocsPage.tsx rename to packages/techdocs-cli-embedded-app/src/components/TechDocsPage/TechDocsPage.tsx diff --git a/packages/embedded-techdocs-app/src/components/TechDocsPage/index.ts b/packages/techdocs-cli-embedded-app/src/components/TechDocsPage/index.ts similarity index 100% rename from packages/embedded-techdocs-app/src/components/TechDocsPage/index.ts rename to packages/techdocs-cli-embedded-app/src/components/TechDocsPage/index.ts diff --git a/packages/embedded-techdocs-app/src/index.tsx b/packages/techdocs-cli-embedded-app/src/index.tsx similarity index 100% rename from packages/embedded-techdocs-app/src/index.tsx rename to packages/techdocs-cli-embedded-app/src/index.tsx diff --git a/packages/embedded-techdocs-app/src/plugins.ts b/packages/techdocs-cli-embedded-app/src/plugins.ts similarity index 100% rename from packages/embedded-techdocs-app/src/plugins.ts rename to packages/techdocs-cli-embedded-app/src/plugins.ts diff --git a/packages/embedded-techdocs-app/src/setupTests.ts b/packages/techdocs-cli-embedded-app/src/setupTests.ts similarity index 100% rename from packages/embedded-techdocs-app/src/setupTests.ts rename to packages/techdocs-cli-embedded-app/src/setupTests.ts diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index 05e621ce62..f68fc44101 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,10 +1,27 @@ # @techdocs/cli +## 0.8.12 + +### Patch Changes + +- 14472509a3: Use a local file dependency for techdocs-cli-embedded-app, to ensure that it's always pulled out of the workspace +- Updated dependencies + - @backstage/backend-common@0.10.6 + - @backstage/techdocs-common@0.11.6 + +## 0.8.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + - @backstage/techdocs-common@0.11.6-next.0 + ## 0.8.12-next.0 ### Patch Changes -- 14472509a3: Use a local file dependency for embedded-techdocs-app, to ensure that it's always pulled out of the workspace +- 14472509a3: Use a local file dependency for techdocs-cli-embedded-app, to ensure that it's always pulled out of the workspace ## 0.8.11 @@ -144,10 +161,10 @@ #### :house: Internal - - `embedded-techdocs-app` - - [#122](https://github.com/backstage/techdocs-cli/pull/122) chore(deps-dev): bump @types/node from 12.20.20 to 16.7.1 in /packages/embedded-techdocs-app ([@dependabot[bot]](https://github.com/apps/dependabot)) - - [#120](https://github.com/backstage/techdocs-cli/pull/120) chore(deps-dev): bump @types/react-dom from 16.9.14 to 17.0.9 in /packages/embedded-techdocs-app ([@dependabot[bot]](https://github.com/apps/dependabot)) - - [#119](https://github.com/backstage/techdocs-cli/pull/119) chore(deps-dev): bump @testing-library/user-event from 12.8.3 to 13.2.1 in /packages/embedded-techdocs-app ([@dependabot[bot]](https://github.com/apps/dependabot)) + - `techdocs-cli-embedded-app` + - [#122](https://github.com/backstage/techdocs-cli/pull/122) chore(deps-dev): bump @types/node from 12.20.20 to 16.7.1 in /packages/techdocs-cli-embedded-app ([@dependabot[bot]](https://github.com/apps/dependabot)) + - [#120](https://github.com/backstage/techdocs-cli/pull/120) chore(deps-dev): bump @types/react-dom from 16.9.14 to 17.0.9 in /packages/techdocs-cli-embedded-app ([@dependabot[bot]](https://github.com/apps/dependabot)) + - [#119](https://github.com/backstage/techdocs-cli/pull/119) chore(deps-dev): bump @testing-library/user-event from 12.8.3 to 13.2.1 in /packages/techdocs-cli-embedded-app ([@dependabot[bot]](https://github.com/apps/dependabot)) - [#118](https://github.com/backstage/techdocs-cli/pull/118) chore(deps-dev): bump @testing-library/react from 10.4.9 to 12.0.0 ([@dependabot[bot]](https://github.com/apps/dependabot)) - Other - [#117](https://github.com/backstage/techdocs-cli/pull/117) chore(deps): bump @backstage/plugin-catalog from 0.6.11 to 0.6.12 ([@dependabot[bot]](https://github.com/apps/dependabot)) diff --git a/packages/techdocs-cli/README.md b/packages/techdocs-cli/README.md index 6f070147eb..3ac423cb38 100644 --- a/packages/techdocs-cli/README.md +++ b/packages/techdocs-cli/README.md @@ -8,7 +8,7 @@ See [techdocs-cli usage docs](https://backstage.io/docs/features/techdocs/cli). ## Development -NOTE: When we build `techdocs-cli` it copies the output `embedded-techdocs-app` +NOTE: When we build `techdocs-cli` it copies the output `techdocs-cli-embedded-app` bundle into the `packages/techdocs-cli/dist` which is then published with the `@techdocs/cli` npm package. @@ -16,7 +16,7 @@ bundle into the `packages/techdocs-cli/dist` which is then published with the ```sh # From the root of this repository run -# NOTE: This will build the embedded-techdocs-app and copy the output into the cli dist directory +# NOTE: This will build the techdocs-cli-embedded-app and copy the output into the cli dist directory yarn build --scope @techdocs/cli # Now execute the binary @@ -26,14 +26,14 @@ packages/techdocs-cli/bin/techdocs-cli export PATH=/path/to/backstage/packages/techdocs-cli/bin:$PATH ``` -If you want to test live test changes to the `packages/embedded-techdocs-app` +If you want to test live test changes to the `packages/techdocs-cli-embedded-app` you can serve the app and run the CLI using the following commands: ```sh -# Open a shell to the embedded-techdocs-app directory -cd packages/embedded-techdocs-app +# Open a shell to the techdocs-cli-embedded-app directory +cd packages/techdocs-cli-embedded-app -# Run the embedded-techdocs-app using dev mode +# Run the techdocs-cli-embedded-app using dev mode yarn start # In another shell use the techdocs-cli from the root of this repo diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index d8a46ed261..a8dab88c55 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": "0.8.12-next.0", + "version": "0.8.12", "private": false, "publishConfig": { "access": "public" @@ -32,7 +32,7 @@ "techdocs-cli": "bin/techdocs-cli" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@types/commander": "^2.12.2", "@types/fs-extra": "^9.0.6", "@types/http-proxy": "^1.17.4", @@ -40,7 +40,7 @@ "@types/node": "^14.14.32", "@types/serve-handler": "^6.1.0", "@types/webpack-env": "^1.15.3", - "embedded-techdocs-app": "file:../embedded-techdocs-app", + "techdocs-cli-embedded-app": "file:../techdocs-cli-embedded-app", "find-process": "^1.4.5", "nodemon": "^2.0.2", "ts-node": "^10.0.0" @@ -55,10 +55,10 @@ "ext": "ts" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/catalog-model": "^0.9.10", "@backstage/config": "^0.1.13", - "@backstage/techdocs-common": "^0.11.5", + "@backstage/techdocs-common": "^0.11.6", "@types/dockerode": "^3.3.0", "commander": "^6.1.0", "dockerode": "^3.3.1", diff --git a/packages/techdocs-cli/scripts/build.sh b/packages/techdocs-cli/scripts/build.sh index 630fef42f0..31c2eae6c3 100755 --- a/packages/techdocs-cli/scripts/build.sh +++ b/packages/techdocs-cli/scripts/build.sh @@ -18,7 +18,7 @@ set -e SCRIPT_DIR=$(dirname $0) TECHDOCS_CLI_DIR="$SCRIPT_DIR"/.. -TECHDOCS_CLI_EMBEDDED_APP_DIR="$TECHDOCS_CLI_DIR"/../embedded-techdocs-app +TECHDOCS_CLI_EMBEDDED_APP_DIR="$TECHDOCS_CLI_DIR"/../techdocs-cli-embedded-app compile_and_build_cli() { echo "📄 Compiling..." @@ -32,9 +32,9 @@ compile_and_build_cli() { build_and_embed_app() { echo "🚚 Embedding app..." if [ "$TECHDOCS_CLI_DEV_MODE" = "true" ] ; then - yarn workspace embedded-techdocs-app build:dev > /dev/null + yarn workspace techdocs-cli-embedded-app build:dev > /dev/null else - yarn workspace embedded-techdocs-app build > /dev/null + yarn workspace techdocs-cli-embedded-app build > /dev/null fi cp -r "$TECHDOCS_CLI_EMBEDDED_APP_DIR"/dist "$TECHDOCS_CLI_DIR"/dist/techdocs-preview-bundle > /dev/null } diff --git a/packages/techdocs-common/CHANGELOG.md b/packages/techdocs-common/CHANGELOG.md index 9a3fa5051b..d03ddb6101 100644 --- a/packages/techdocs-common/CHANGELOG.md +++ b/packages/techdocs-common/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/techdocs-common +## 0.11.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6 + +## 0.11.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + ## 0.11.5 ### Patch Changes diff --git a/packages/techdocs-common/package.json b/packages/techdocs-common/package.json index 5e4d423036..94a87a41e8 100644 --- a/packages/techdocs-common/package.json +++ b/packages/techdocs-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/techdocs-common", "description": "Common functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", - "version": "0.11.5", + "version": "0.11.6", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -38,7 +38,7 @@ "dependencies": { "@azure/identity": "^2.0.1", "@azure/storage-blob": "^12.5.0", - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/catalog-model": "^0.9.10", "@backstage/config": "^0.1.13", "@backstage/errors": "^0.2.0", @@ -60,7 +60,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@types/fs-extra": "^9.0.5", "@types/js-yaml": "^4.0.0", "@types/mime-types": "^2.1.0", diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index 1867b52265..35c9ebfb35 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/test-utils +## 0.2.4 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@0.5.2 + +## 0.2.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@0.5.2-next.0 + ## 0.2.3 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 318db4e0ed..c5fe18d7f7 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": "0.2.3", + "version": "0.2.4", "private": false, "publishConfig": { "access": "public", @@ -30,7 +30,7 @@ }, "dependencies": { "@backstage/config": "^0.1.13", - "@backstage/core-app-api": "^0.5.1", + "@backstage/core-app-api": "^0.5.2", "@backstage/core-plugin-api": "^0.6.0", "@backstage/plugin-permission-common": "^0.4.0", "@backstage/plugin-permission-react": "^0.3.0", @@ -51,7 +51,7 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", "msw": "^0.35.0" diff --git a/plugins/airbrake/CHANGELOG.md b/plugins/airbrake/CHANGELOG.md index 357e32bb05..489559c023 100644 --- a/plugins/airbrake/CHANGELOG.md +++ b/plugins/airbrake/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-airbrake +## 0.1.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + ## 0.1.2-next.0 ### Patch Changes diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index da6d9f68c3..92e142c1a9 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake", - "version": "0.1.2-next.0", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,7 +21,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/plugin-catalog-react": "^0.6.12", "@backstage/theme": "^0.2.14", @@ -36,11 +36,11 @@ }, "devDependencies": { "@types/object-hash": "^2.2.1", - "@backstage/app-defaults": "^0.1.6-next.0", - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/app-defaults": "^0.1.6", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/allure/CHANGELOG.md b/plugins/allure/CHANGELOG.md index 5641aec797..f0fa792278 100644 --- a/plugins/allure/CHANGELOG.md +++ b/plugins/allure/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-allure +## 0.1.13 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + ## 0.1.13-next.0 ### Patch Changes diff --git a/plugins/allure/package.json b/plugins/allure/package.json index cfabf4e57a..4b497bd56e 100644 --- a/plugins/allure/package.json +++ b/plugins/allure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-allure", "description": "A Backstage plugin that integrates with Allure", - "version": "0.1.13-next.0", + "version": "0.1.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,9 +23,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -37,10 +37,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/analytics-module-ga/CHANGELOG.md b/plugins/analytics-module-ga/CHANGELOG.md index 27a5ce04e7..81c61769fb 100644 --- a/plugins/analytics-module-ga/CHANGELOG.md +++ b/plugins/analytics-module-ga/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-analytics-module-ga +## 0.1.8 + +### Patch Changes + +- b40a0ccc4d: Added the ability to capture and set user IDs from Backstage's `identityApi`. For full instructions on how to + set this up, see [the User ID section of its README](https://github.com/backstage/backstage/tree/master/plugins/analytics-module-ga#user-ids) +- Updated dependencies + - @backstage/core-components@0.8.7 + ## 0.1.8-next.0 ### Patch Changes diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index e3f0ec00e8..bbc9ffcd2e 100644 --- a/plugins/analytics-module-ga/package.json +++ b/plugins/analytics-module-ga/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-ga", - "version": "0.1.8-next.0", + "version": "0.1.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,7 +22,7 @@ }, "dependencies": { "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", @@ -35,10 +35,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/apache-airflow/CHANGELOG.md b/plugins/apache-airflow/CHANGELOG.md index 9bca4cfdb7..7407a9f0c9 100644 --- a/plugins/apache-airflow/CHANGELOG.md +++ b/plugins/apache-airflow/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-apache-airflow +## 0.1.5 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + ## 0.1.5-next.0 ### Patch Changes diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index a39dce2910..7b760070ec 100644 --- a/plugins/apache-airflow/package.json +++ b/plugins/apache-airflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apache-airflow", - "version": "0.1.5-next.0", + "version": "0.1.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,7 +20,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -33,10 +33,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index d8af0d3798..cd477a6152 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-api-docs +## 0.7.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + - @backstage/plugin-catalog@0.7.11 + ## 0.7.1-next.0 ### Patch Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index dd149f3133..26f28ae40b 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-api-docs", "description": "A Backstage plugin that helps represent API entities in the frontend", - "version": "0.7.1-next.0", + "version": "0.7.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,10 +32,10 @@ "dependencies": { "@asyncapi/react-component": "1.0.0-next.32", "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog": "^0.7.11-next.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog": "^0.7.11", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -53,10 +53,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index 68a38461fe..b2a8d38636 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-app-backend +## 0.3.23 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6 + +## 0.3.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + ## 0.3.22 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index f65f23a420..361dc07b2c 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.22", + "version": "0.3.23", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,7 +30,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/config-loader": "^0.9.3", "@backstage/config": "^0.1.13", "@backstage/types": "^0.1.1", @@ -47,8 +47,8 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.16-next.0", - "@backstage/cli": "^0.13.1-next.0", + "@backstage/backend-test-utils": "^0.1.16", + "@backstage/cli": "^0.13.1", "@backstage/types": "^0.1.1", "@types/supertest": "^2.0.8", "mock-fs": "^5.1.0", diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index 05836979fd..52c1f3caa3 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,51 @@ # @backstage/plugin-auth-backend +## 0.9.0 + +### Minor Changes + +- cef64b1561: **BREAKING** Added `tokenManager` as a required property for the auth-backend `createRouter` function. This dependency is used to issue server tokens that are used by the `CatalogIdentityClient` when looking up users and their group membership during authentication. + + These changes are **required** to `packages/backend/src/plugins/auth.ts`: + + ```diff + export default async function createPlugin({ + logger, + database, + config, + discovery, + + tokenManager, + }: PluginEnvironment): Promise { + return await createRouter({ + logger, + config, + database, + discovery, + + tokenManager, + }); + } + ``` + + **BREAKING** The `CatalogIdentityClient` constructor now expects a `TokenManager` instead of a `TokenIssuer`. The `TokenManager` interface is used to generate a server token when [resolving a user's identity and membership through the catalog](https://backstage.io/docs/auth/identity-resolver). Using server tokens for these requests allows the auth-backend to bypass authorization checks when permissions are enabled for Backstage. This change will break apps that rely on the user tokens that were previously used by the client. Refer to the ["Backend-to-backend Authentication" tutorial](https://backstage.io/docs/tutorials/backend-to-backend-auth) for more information on server token usage. + +### Patch Changes + +- 9d75a939b6: Fixed a bug where providers that tracked the granted scopes through a cookie would not take failed authentication attempts into account. +- 28a5f9d0b1: chore(deps): bump `passport` from 0.4.1 to 0.5.2 +- 5d09bdd1de: Added custom `callbackUrl` support for multiple providers. `v0.8.0` introduced this change for `github`, and now we're adding the same capability to the following providers: `atlassian, auth0, bitbucket, gitlab, google, microsoft, oauth2, oidc, okta, onelogin`. +- 648606b3ac: Added support for storing static GitHub access tokens in cookies and using them to refresh the Backstage session. +- Updated dependencies + - @backstage/backend-common@0.10.6 + +## 0.9.0-next.1 + +### Patch Changes + +- 9d75a939b6: Fixed a bug where providers that tracked the granted scopes through a cookie would not take failed authentication attempts into account. +- 648606b3ac: Added support for storing static GitHub access tokens in cookies and using them to refresh the Backstage session. +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + ## 0.9.0-next.0 ### Minor Changes diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 7cdc33f0e2..88b75d99b0 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -592,6 +592,7 @@ export type OAuthState = { nonce: string; env: string; origin?: string; + scope?: string; }; // @public @@ -734,6 +735,6 @@ export type WebMessageResponse = // // src/identity/types.d.ts:31:9 - (ae-forgotten-export) The symbol "AnyJWK" needs to be exported by the entry point index.d.ts // src/providers/aws-alb/provider.d.ts:77:5 - (ae-forgotten-export) The symbol "AwsAlbResult" needs to be exported by the entry point index.d.ts -// src/providers/github/provider.d.ts:81:5 - (ae-forgotten-export) The symbol "StateEncoder" needs to be exported by the entry point index.d.ts +// src/providers/github/provider.d.ts:97:5 - (ae-forgotten-export) The symbol "StateEncoder" needs to be exported by the entry point index.d.ts // src/providers/types.d.ts:98:5 - (ae-forgotten-export) The symbol "AuthProviderConfig" needs to be exported by the entry point index.d.ts ``` diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 80ec297ea5..e077444292 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend", "description": "A Backstage backend plugin that handles authentication", - "version": "0.9.0-next.0", + "version": "0.9.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,7 +30,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/catalog-client": "^0.5.5", "@backstage/catalog-model": "^0.9.10", "@backstage/config": "^0.1.13", @@ -73,8 +73,8 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/test-utils": "^0.2.4", "@types/body-parser": "^1.19.0", "@types/cookie-parser": "^1.4.2", "@types/express-session": "^1.17.2", diff --git a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.test.ts b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.test.ts index a85dd49fba..d1057b19a8 100644 --- a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.test.ts +++ b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.test.ts @@ -17,7 +17,7 @@ import express from 'express'; import { THOUSAND_DAYS_MS, TEN_MINUTES_MS, OAuthAdapter } from './OAuthAdapter'; import { encodeState } from './helpers'; -import { OAuthHandlers, OAuthResponse } from './types'; +import { OAuthHandlers, OAuthResponse, OAuthState } from './types'; const mockResponseData = { providerInfo: { @@ -148,6 +148,102 @@ describe('OAuthAdapter', () => { ); }); + it('persists scope through cookie if enabled', async () => { + const handlers = { + start: jest.fn(async (_req: { state: OAuthState }) => ({ + url: '/url', + status: 301, + })), + handler: jest.fn(async () => ({ response: mockResponseData })), + refresh: jest.fn(async () => ({ response: mockResponseData })), + }; + const oauthProvider = new OAuthAdapter(handlers, { + ...oAuthProviderOptions, + disableRefresh: false, + persistScopes: true, + }); + + // First we test the /start request, making sure state is set + const mockStartReq = { + query: { + scope: 'user', + env: 'development', + }, + } as unknown as express.Request; + const mockStartRes = { + cookie: jest.fn().mockReturnThis(), + end: jest.fn().mockReturnThis(), + setHeader: jest.fn().mockReturnThis(), + statusCode: jest.fn().mockReturnThis(), + } as unknown as express.Response; + + await oauthProvider.start(mockStartReq, mockStartRes); + + expect(handlers.start).toHaveBeenCalledTimes(1); + expect(handlers.start).toHaveBeenCalledWith({ + query: { + scope: 'user', + env: 'development', + }, + scope: 'user', + state: { + nonce: expect.any(String), + env: 'development', + origin: undefined, + scope: 'user', + }, + }); + + // Then test the /handler, making sure the granted scope cookie is set + const providedState = handlers.start.mock.calls[0][0].state; + const mockHandleReq = { + cookies: { + 'test-provider-nonce': providedState.nonce, + }, + query: { + state: encodeState(providedState), + }, + } as unknown as express.Request; + const mockHandleRes = { + cookie: jest.fn().mockReturnThis(), + setHeader: jest.fn().mockReturnThis(), + end: jest.fn().mockReturnThis(), + } as unknown as express.Response; + + await oauthProvider.frameHandler(mockHandleReq, mockHandleRes); + expect(mockHandleRes.cookie).toHaveBeenCalledTimes(1); + expect(mockHandleRes.cookie).toHaveBeenCalledWith( + 'test-provider-granted-scope', + 'user', + expect.objectContaining({ + path: '/auth/test-provider', + maxAge: THOUSAND_DAYS_MS, + }), + ); + + // Them make sure scopes are forwarded correctly during refresh + const mockRefreshReq = { + query: { scope: 'ignore-me' }, + cookies: { + 'test-provider-granted-scope': 'user', + 'test-provider-refresh-token': 'refresh-token', + }, + header: jest.fn().mockReturnValue('XMLHttpRequest'), + } as unknown as express.Request; + const mockRefreshRes = { + status: jest.fn().mockReturnThis(), + json: jest.fn().mockReturnThis(), + } as unknown as express.Response; + await oauthProvider.refresh(mockRefreshReq, mockRefreshRes); + expect(handlers.refresh).toHaveBeenCalledTimes(1); + expect(handlers.refresh).toHaveBeenCalledWith( + expect.objectContaining({ + scope: 'user', + refreshToken: 'refresh-token', + }), + ); + }); + it('does not set the refresh cookie if refresh is disabled', async () => { const oauthProvider = new OAuthAdapter(providerInstance, { ...oAuthProviderOptions, diff --git a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts index 564d5c20de..2e2d26db61 100644 --- a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts +++ b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import express from 'express'; +import express, { CookieOptions } from 'express'; import crypto from 'crypto'; import { URL } from 'url'; import { @@ -90,10 +90,20 @@ export class OAuthAdapter implements AuthProviderRouteHandlers { }); } + private readonly baseCookieOptions: CookieOptions; + constructor( private readonly handlers: OAuthHandlers, private readonly options: Options, - ) {} + ) { + this.baseCookieOptions = { + httpOnly: true, + sameSite: 'lax', + secure: this.options.secure, + path: this.options.cookiePath, + domain: this.options.cookieDomain, + }; + } async start(req: express.Request, res: express.Response): Promise { // retrieve scopes from request @@ -105,15 +115,17 @@ export class OAuthAdapter implements AuthProviderRouteHandlers { throw new InputError('No env provided in request query parameters'); } - if (this.options.persistScopes) { - this.setScopesCookie(res, scope); - } - const nonce = crypto.randomBytes(16).toString('base64'); // set a nonce cookie before redirecting to oauth provider this.setNonceCookie(res, nonce); - const state = { nonce, env, origin }; + const state: OAuthState = { nonce, env, origin }; + + // If scopes are persisted then we pass them through the state so that we + // can set the cookie on successful auth + if (this.options.persistScopes) { + state.scope = scope; + } const forwardReq = Object.assign(req, { scope, state }); const { url, status } = await this.handlers.start( @@ -151,12 +163,11 @@ export class OAuthAdapter implements AuthProviderRouteHandlers { const { response, refreshToken } = await this.handlers.handler(req); - if (this.options.persistScopes) { - const grantedScopes = this.getScopesFromCookie( - req, - this.options.providerId, - ); - response.providerInfo.scope = grantedScopes; + // Store the scope that we have been granted for this session. This is useful if + // the provider does not return granted scopes on refresh or if they are normalized. + if (this.options.persistScopes && state.scope) { + this.setGrantedScopeCookie(res, state.scope); + response.providerInfo.scope = state.scope; } if (refreshToken && !this.options.disableRefresh) { @@ -214,8 +225,10 @@ export class OAuthAdapter implements AuthProviderRouteHandlers { throw new InputError('Missing session cookie'); } - const scope = req.query.scope?.toString() ?? ''; - + let scope = req.query.scope?.toString() ?? ''; + if (this.options.persistScopes) { + scope = this.getGrantedScopeFromCookie(req); + } const forwardReq = Object.assign(req, { scope, refreshToken }); // get new access_token @@ -267,27 +280,20 @@ export class OAuthAdapter implements AuthProviderRouteHandlers { private setNonceCookie = (res: express.Response, nonce: string) => { res.cookie(`${this.options.providerId}-nonce`, nonce, { maxAge: TEN_MINUTES_MS, - secure: this.options.secure, - sameSite: 'lax', - domain: this.options.cookieDomain, + ...this.baseCookieOptions, path: `${this.options.cookiePath}/handler`, - httpOnly: true, }); }; - private setScopesCookie = (res: express.Response, scope: string) => { - res.cookie(`${this.options.providerId}-scope`, scope, { - maxAge: TEN_MINUTES_MS, - secure: this.options.secure, - sameSite: 'lax', - domain: this.options.cookieDomain, - path: `${this.options.cookiePath}/handler`, - httpOnly: true, + private setGrantedScopeCookie = (res: express.Response, scope: string) => { + res.cookie(`${this.options.providerId}-granted-scope`, scope, { + maxAge: THOUSAND_DAYS_MS, + ...this.baseCookieOptions, }); }; - private getScopesFromCookie = (req: express.Request, providerId: string) => { - return req.cookies[`${providerId}-scope`]; + private getGrantedScopeFromCookie = (req: express.Request) => { + return req.cookies[`${this.options.providerId}-granted-scope`]; }; private setRefreshTokenCookie = ( @@ -296,22 +302,14 @@ export class OAuthAdapter implements AuthProviderRouteHandlers { ) => { res.cookie(`${this.options.providerId}-refresh-token`, refreshToken, { maxAge: THOUSAND_DAYS_MS, - secure: this.options.secure, - sameSite: 'lax', - domain: this.options.cookieDomain, - path: this.options.cookiePath, - httpOnly: true, + ...this.baseCookieOptions, }); }; private removeRefreshTokenCookie = (res: express.Response) => { res.cookie(`${this.options.providerId}-refresh-token`, '', { maxAge: 0, - secure: this.options.secure, - sameSite: 'lax', - domain: this.options.cookieDomain, - path: this.options.cookiePath, - httpOnly: true, + ...this.baseCookieOptions, }); }; } diff --git a/plugins/auth-backend/src/lib/oauth/types.ts b/plugins/auth-backend/src/lib/oauth/types.ts index 9ddef007a7..6973e99569 100644 --- a/plugins/auth-backend/src/lib/oauth/types.ts +++ b/plugins/auth-backend/src/lib/oauth/types.ts @@ -87,6 +87,7 @@ export type OAuthState = { nonce: string; env: string; origin?: string; + scope?: string; }; export type OAuthStartRequest = express.Request<{}> & { diff --git a/plugins/auth-backend/src/providers/atlassian/provider.ts b/plugins/auth-backend/src/providers/atlassian/provider.ts index 2696fd233f..79bcb5c909 100644 --- a/plugins/auth-backend/src/providers/atlassian/provider.ts +++ b/plugins/auth-backend/src/providers/atlassian/provider.ts @@ -205,7 +205,10 @@ export const createAtlassianProvider = ( const clientId = envConfig.getString('clientId'); const clientSecret = envConfig.getString('clientSecret'); const scopes = envConfig.getString('scopes'); - const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`; + const customCallbackUrl = envConfig.getOptionalString('callbackUrl'); + const callbackUrl = + customCallbackUrl || + `${globalConfig.baseUrl}/${providerId}/handler/frame`; const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, @@ -231,6 +234,7 @@ export const createAtlassianProvider = ( disableRefresh: true, providerId, tokenIssuer, + callbackUrl, }); }); }; diff --git a/plugins/auth-backend/src/providers/auth0/provider.ts b/plugins/auth-backend/src/providers/auth0/provider.ts index 15578117ea..fbd57c0b76 100644 --- a/plugins/auth-backend/src/providers/auth0/provider.ts +++ b/plugins/auth-backend/src/providers/auth0/provider.ts @@ -228,7 +228,10 @@ export const createAuth0Provider = ( const clientId = envConfig.getString('clientId'); const clientSecret = envConfig.getString('clientSecret'); const domain = envConfig.getString('domain'); - const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`; + const customCallbackUrl = envConfig.getOptionalString('callbackUrl'); + const callbackUrl = + customCallbackUrl || + `${globalConfig.baseUrl}/${providerId}/handler/frame`; const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, @@ -259,6 +262,7 @@ export const createAuth0Provider = ( disableRefresh: true, providerId, tokenIssuer, + callbackUrl, }); }); }; diff --git a/plugins/auth-backend/src/providers/bitbucket/provider.ts b/plugins/auth-backend/src/providers/bitbucket/provider.ts index 4d5bdcf6f6..1cc0e60bd8 100644 --- a/plugins/auth-backend/src/providers/bitbucket/provider.ts +++ b/plugins/auth-backend/src/providers/bitbucket/provider.ts @@ -280,7 +280,10 @@ export const createBitbucketProvider = ( OAuthEnvironmentHandler.mapConfig(config, envConfig => { const clientId = envConfig.getString('clientId'); const clientSecret = envConfig.getString('clientSecret'); - const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`; + const customCallbackUrl = envConfig.getOptionalString('callbackUrl'); + const callbackUrl = + customCallbackUrl || + `${globalConfig.baseUrl}/${providerId}/handler/frame`; const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, @@ -309,6 +312,7 @@ export const createBitbucketProvider = ( disableRefresh: false, providerId, tokenIssuer, + callbackUrl, }); }); }; diff --git a/plugins/auth-backend/src/providers/github/provider.test.ts b/plugins/auth-backend/src/providers/github/provider.test.ts index 15eeccc07c..206df52083 100644 --- a/plugins/auth-backend/src/providers/github/provider.test.ts +++ b/plugins/auth-backend/src/providers/github/provider.test.ts @@ -98,6 +98,7 @@ describe('GithubAuthProvider', () => { providerInfo: { accessToken: '19xasczxcm9n7gacn9jdgm19me', scope: 'read:scope', + expiresInSeconds: 3600, }, profile: { email: 'jimmymarkum@gmail.com', @@ -143,6 +144,7 @@ describe('GithubAuthProvider', () => { providerInfo: { accessToken: '19xasczxcm9n7gacn9jdgm19me', scope: 'read:scope', + expiresInSeconds: 3600, }, profile: { displayName: 'Jimmy Markum', @@ -186,6 +188,7 @@ describe('GithubAuthProvider', () => { providerInfo: { accessToken: '19xasczxcm9n7gacn9jdgm19me', scope: 'read:scope', + expiresInSeconds: 3600, }, profile: { displayName: 'jimmymarkum', @@ -230,6 +233,7 @@ describe('GithubAuthProvider', () => { accessToken: 'ajakljsdoiahoawxbrouawucmbawe.awkxjemaneasdxwe.sodijxqeqwexeqwxe', scope: 'read:user', + expiresInSeconds: 3600, }, profile: { displayName: 'Dave Boyle', @@ -316,7 +320,7 @@ describe('GithubAuthProvider', () => { ], }); - const result = await provider.refresh({} as any); + const result = await provider.refresh({ scope: 'actual-scope' } as any); expect(result).toEqual({ response: { @@ -332,11 +336,65 @@ describe('GithubAuthProvider', () => { providerInfo: { accessToken: 'a.b.c', expiresInSeconds: 123, - scope: 'read_user', + scope: 'actual-scope', }, }, refreshToken: 'dont-forget-to-send-refresh', }); + + mockRefreshToken.mockRestore(); + mockUserProfile.mockRestore(); + }); + + it('should use access token as refresh token', async () => { + const mockUserProfile = jest.spyOn( + helpers, + 'executeFetchUserProfileStrategy', + ) as unknown as jest.MockedFunction<() => Promise>; + + mockUserProfile.mockResolvedValueOnce({ + id: 'mockid', + username: 'mockuser', + provider: 'github', + displayName: 'Mocked User', + emails: [ + { + value: 'mockuser@gmail.com', + }, + ], + }); + + const result = await provider.refresh({ + refreshToken: 'access-token.le-token', + scope: 'the-scope', + } as any); + + expect(mockUserProfile).toHaveBeenCalledTimes(1); + expect(mockUserProfile).toHaveBeenCalledWith( + expect.anything(), + 'le-token', + ); + expect(result).toEqual({ + response: { + backstageIdentity: { + id: 'mockuser', + token: 'token-for-user:default/mockuser', + }, + profile: { + displayName: 'Mocked User', + email: 'mockuser@gmail.com', + picture: undefined, + }, + providerInfo: { + accessToken: 'le-token', + expiresInSeconds: 3600, + scope: 'the-scope', + }, + }, + refreshToken: 'access-token.le-token', + }); + + mockUserProfile.mockRestore(); }); }); }); diff --git a/plugins/auth-backend/src/providers/github/provider.ts b/plugins/auth-backend/src/providers/github/provider.ts index 9dc70cf60e..ec7f8cafa6 100644 --- a/plugins/auth-backend/src/providers/github/provider.ts +++ b/plugins/auth-backend/src/providers/github/provider.ts @@ -41,11 +41,15 @@ import { OAuthStartRequest, encodeState, OAuthRefreshRequest, - OAuthResponse, } from '../../lib/oauth'; import { CatalogIdentityClient } from '../../lib/catalog'; import { TokenIssuer } from '../../identity'; +const ACCESS_TOKEN_PREFIX = 'access-token.'; + +// TODO(Rugvip): Auth providers need a way to access this in a less hardcoded way +const BACKSTAGE_SESSION_EXPIRATION = 3600; + type PrivateInfo = { refreshToken?: string; }; @@ -123,31 +127,69 @@ export class GithubAuthProvider implements OAuthHandlers { PrivateInfo >(req, this._strategy); + let refreshToken = privateInfo.refreshToken; + + // If we do not have a real refresh token and we have a non-expiring + // access token, then we use that as our refresh token. + if (!refreshToken && !result.params.expires_in) { + refreshToken = ACCESS_TOKEN_PREFIX + result.accessToken; + } + return { response: await this.handleResult(result), - refreshToken: privateInfo.refreshToken, + refreshToken, }; } async refresh(req: OAuthRefreshRequest) { - const { accessToken, refreshToken, params } = - await executeRefreshTokenStrategy( - this._strategy, - req.refreshToken, - req.scope, - ); - const fullProfile = await executeFetchUserProfileStrategy( - this._strategy, - accessToken, - ); + // We've enable persisting scope in the OAuth provider, so scope here will + // be whatever was stored in the cookie + const { scope, refreshToken } = req; + // This is the OAuth App flow. A non-expiring access token is stored in the + // refresh token cookie. We use that token to fetch the user profile and + // refresh the Backstage session when needed. + if (refreshToken?.startsWith(ACCESS_TOKEN_PREFIX)) { + const accessToken = refreshToken.slice(ACCESS_TOKEN_PREFIX.length); + + const fullProfile = await executeFetchUserProfileStrategy( + this._strategy, + accessToken, + ).catch(error => { + if (error.oauthError?.statusCode === 401) { + throw new Error('Invalid access token'); + } + throw error; + }); + + return { + response: await this.handleResult({ + fullProfile, + params: { scope }, + accessToken, + }), + refreshToken, + }; + } + + // This is the App flow, which is close to a standard OAuth refresh flow. It has a + // pretty long session expiration, and it also ignores the requested scope, instead + // just allowing access to whatever is configured as part of the app installation. + const result = await executeRefreshTokenStrategy( + this._strategy, + refreshToken, + scope, + ); return { response: await this.handleResult({ - fullProfile, - params, - accessToken, + fullProfile: await executeFetchUserProfileStrategy( + this._strategy, + result.accessToken, + ), + params: { ...result.params, scope }, + accessToken: result.accessToken, }), - refreshToken, + refreshToken: result.refreshToken, }; } @@ -160,27 +202,41 @@ export class GithubAuthProvider implements OAuthHandlers { const { profile } = await this.authHandler(result, context); const expiresInStr = result.params.expires_in; - const response: OAuthResponse = { - providerInfo: { - accessToken: result.accessToken, - scope: result.params.scope, - expiresInSeconds: - expiresInStr === undefined ? undefined : Number(expiresInStr), - }, - profile, - }; + let expiresInSeconds = + expiresInStr === undefined ? undefined : Number(expiresInStr); + + let backstageIdentity = undefined; if (this.signInResolver) { - response.backstageIdentity = await this.signInResolver( + backstageIdentity = await this.signInResolver( { result, profile, }, context, ); + + // GitHub sessions last longer than Backstage sessions, so if we're using + // GitHub for sign-in, then we need to expire the sessions earlier + if (expiresInSeconds) { + expiresInSeconds = Math.min( + expiresInSeconds, + BACKSTAGE_SESSION_EXPIRATION, + ); + } else { + expiresInSeconds = BACKSTAGE_SESSION_EXPIRATION; + } } - return response; + return { + backstageIdentity, + providerInfo: { + accessToken: result.accessToken, + scope: result.params.scope, + expiresInSeconds, + }, + profile, + }; } } diff --git a/plugins/auth-backend/src/providers/gitlab/provider.ts b/plugins/auth-backend/src/providers/gitlab/provider.ts index da816f2fd2..6689aba884 100644 --- a/plugins/auth-backend/src/providers/gitlab/provider.ts +++ b/plugins/auth-backend/src/providers/gitlab/provider.ts @@ -236,7 +236,10 @@ export const createGitlabProvider = ( const clientSecret = envConfig.getString('clientSecret'); const audience = envConfig.getOptionalString('audience'); const baseUrl = audience || 'https://gitlab.com'; - const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`; + const customCallbackUrl = envConfig.getOptionalString('callbackUrl'); + const callbackUrl = + customCallbackUrl || + `${globalConfig.baseUrl}/${providerId}/handler/frame`; const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, @@ -272,6 +275,7 @@ export const createGitlabProvider = ( disableRefresh: false, providerId, tokenIssuer, + callbackUrl, }); }); }; diff --git a/plugins/auth-backend/src/providers/google/provider.ts b/plugins/auth-backend/src/providers/google/provider.ts index 13c5093aa5..fbaf8c7462 100644 --- a/plugins/auth-backend/src/providers/google/provider.ts +++ b/plugins/auth-backend/src/providers/google/provider.ts @@ -266,7 +266,10 @@ export const createGoogleProvider = ( OAuthEnvironmentHandler.mapConfig(config, envConfig => { const clientId = envConfig.getString('clientId'); const clientSecret = envConfig.getString('clientSecret'); - const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`; + const customCallbackUrl = envConfig.getOptionalString('callbackUrl'); + const callbackUrl = + customCallbackUrl || + `${globalConfig.baseUrl}/${providerId}/handler/frame`; const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, @@ -304,6 +307,7 @@ export const createGoogleProvider = ( disableRefresh: false, providerId, tokenIssuer, + callbackUrl, }); }); }; diff --git a/plugins/auth-backend/src/providers/microsoft/provider.ts b/plugins/auth-backend/src/providers/microsoft/provider.ts index 9249f643dc..25c940547b 100644 --- a/plugins/auth-backend/src/providers/microsoft/provider.ts +++ b/plugins/auth-backend/src/providers/microsoft/provider.ts @@ -276,7 +276,10 @@ export const createMicrosoftProvider = ( const clientSecret = envConfig.getString('clientSecret'); const tenantId = envConfig.getString('tenantId'); - const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`; + const customCallbackUrl = envConfig.getOptionalString('callbackUrl'); + const callbackUrl = + customCallbackUrl || + `${globalConfig.baseUrl}/${providerId}/handler/frame`; const authorizationUrl = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/authorize`; const tokenUrl = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`; @@ -318,6 +321,7 @@ export const createMicrosoftProvider = ( disableRefresh: false, providerId, tokenIssuer, + callbackUrl, }); }); }; diff --git a/plugins/auth-backend/src/providers/oauth2/provider.ts b/plugins/auth-backend/src/providers/oauth2/provider.ts index 8e69a3ee1d..0906005791 100644 --- a/plugins/auth-backend/src/providers/oauth2/provider.ts +++ b/plugins/auth-backend/src/providers/oauth2/provider.ts @@ -240,7 +240,10 @@ export const createOAuth2Provider = ( OAuthEnvironmentHandler.mapConfig(config, envConfig => { const clientId = envConfig.getString('clientId'); const clientSecret = envConfig.getString('clientSecret'); - const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`; + const customCallbackUrl = envConfig.getOptionalString('callbackUrl'); + const callbackUrl = + customCallbackUrl || + `${globalConfig.baseUrl}/${providerId}/handler/frame`; const authorizationUrl = envConfig.getString('authorizationUrl'); const tokenUrl = envConfig.getString('tokenUrl'); const scope = envConfig.getOptionalString('scope'); @@ -288,6 +291,7 @@ export const createOAuth2Provider = ( disableRefresh, providerId, tokenIssuer, + callbackUrl, }); }); }; diff --git a/plugins/auth-backend/src/providers/oidc/provider.ts b/plugins/auth-backend/src/providers/oidc/provider.ts index fa46294784..e77812e750 100644 --- a/plugins/auth-backend/src/providers/oidc/provider.ts +++ b/plugins/auth-backend/src/providers/oidc/provider.ts @@ -264,7 +264,10 @@ export const createOidcProvider = ( OAuthEnvironmentHandler.mapConfig(config, envConfig => { const clientId = envConfig.getString('clientId'); const clientSecret = envConfig.getString('clientSecret'); - const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`; + const customCallbackUrl = envConfig.getOptionalString('callbackUrl'); + const callbackUrl = + customCallbackUrl || + `${globalConfig.baseUrl}/${providerId}/handler/frame`; const metadataUrl = envConfig.getString('metadataUrl'); const tokenSignedResponseAlg = envConfig.getOptionalString( 'tokenSignedResponseAlg', @@ -313,6 +316,7 @@ export const createOidcProvider = ( disableRefresh: false, providerId, tokenIssuer, + callbackUrl, }); }); }; diff --git a/plugins/auth-backend/src/providers/okta/provider.ts b/plugins/auth-backend/src/providers/okta/provider.ts index def0da694e..0ba7d241d3 100644 --- a/plugins/auth-backend/src/providers/okta/provider.ts +++ b/plugins/auth-backend/src/providers/okta/provider.ts @@ -276,7 +276,10 @@ export const createOktaProvider = ( const clientId = envConfig.getString('clientId'); const clientSecret = envConfig.getString('clientSecret'); const audience = envConfig.getString('audience'); - const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`; + const customCallbackUrl = envConfig.getOptionalString('callbackUrl'); + const callbackUrl = + customCallbackUrl || + `${globalConfig.baseUrl}/${providerId}/handler/frame`; // This is a safe assumption as `passport-okta-oauth` uses the audience // as the base for building the authorization, token, and user info URLs. @@ -322,6 +325,7 @@ export const createOktaProvider = ( disableRefresh: false, providerId, tokenIssuer, + callbackUrl, }); }); }; diff --git a/plugins/auth-backend/src/providers/onelogin/provider.ts b/plugins/auth-backend/src/providers/onelogin/provider.ts index a5ab4f658b..e14e8548a0 100644 --- a/plugins/auth-backend/src/providers/onelogin/provider.ts +++ b/plugins/auth-backend/src/providers/onelogin/provider.ts @@ -227,7 +227,10 @@ export const createOneLoginProvider = ( const clientId = envConfig.getString('clientId'); const clientSecret = envConfig.getString('clientSecret'); const issuer = envConfig.getString('issuer'); - const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`; + const customCallbackUrl = envConfig.getOptionalString('callbackUrl'); + const callbackUrl = + customCallbackUrl || + `${globalConfig.baseUrl}/${providerId}/handler/frame`; const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, @@ -258,6 +261,7 @@ export const createOneLoginProvider = ( disableRefresh: false, providerId, tokenIssuer, + callbackUrl, }); }); }; diff --git a/plugins/azure-devops-backend/CHANGELOG.md b/plugins/azure-devops-backend/CHANGELOG.md index 16b4a0d182..e2aad374b3 100644 --- a/plugins/azure-devops-backend/CHANGELOG.md +++ b/plugins/azure-devops-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-azure-devops-backend +## 0.3.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6 + +## 0.3.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + ## 0.3.1 ### Patch Changes diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index 638857fabb..4125e9be24 100644 --- a/plugins/azure-devops-backend/package.json +++ b/plugins/azure-devops-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops-backend", - "version": "0.3.1", + "version": "0.3.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,7 +20,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/config": "^0.1.13", "@backstage/plugin-azure-devops-common": "^0.2.0", "@types/express": "^4.17.6", @@ -32,7 +32,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@types/supertest": "^2.0.8", "supertest": "^6.1.6", "msw": "^0.35.0" diff --git a/plugins/azure-devops/CHANGELOG.md b/plugins/azure-devops/CHANGELOG.md index 042dad9a9d..8e300e9699 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-azure-devops +## 0.1.13 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + ## 0.1.13-next.0 ### Patch Changes diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index 45d5e46cee..7052dee6d5 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops", - "version": "0.1.13-next.0", + "version": "0.1.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -28,11 +28,11 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/errors": "^0.2.0", "@backstage/plugin-azure-devops-common": "^0.2.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -46,10 +46,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/badges-backend/CHANGELOG.md b/plugins/badges-backend/CHANGELOG.md index 4f54700697..54c46a6f3e 100644 --- a/plugins/badges-backend/CHANGELOG.md +++ b/plugins/badges-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-badges-backend +## 0.1.17 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6 + +## 0.1.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + ## 0.1.16 ### Patch Changes diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index 01c6d4b1fc..f5d533522e 100644 --- a/plugins/badges-backend/package.json +++ b/plugins/badges-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges-backend", "description": "A Backstage backend plugin that generates README badges for your entities", - "version": "0.1.16", + "version": "0.1.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/catalog-client": "^0.5.5", "@backstage/catalog-model": "^0.9.10", "@backstage/config": "^0.1.13", @@ -45,7 +45,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/badges/CHANGELOG.md b/plugins/badges/CHANGELOG.md index fa3b72c00d..e49dc620ee 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-badges +## 0.2.21 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + ## 0.2.21-next.0 ### Patch Changes diff --git a/plugins/badges/package.json b/plugins/badges/package.json index b46f4450bb..c27375b995 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges", "description": "A Backstage plugin that generates README badges for your entities", - "version": "0.2.21-next.0", + "version": "0.2.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -28,10 +28,10 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/errors": "^0.2.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -43,10 +43,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/bazaar-backend/CHANGELOG.md b/plugins/bazaar-backend/CHANGELOG.md index ab73c8ab04..4262b3fe11 100644 --- a/plugins/bazaar-backend/CHANGELOG.md +++ b/plugins/bazaar-backend/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-bazaar-backend +## 0.1.8 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6 + - @backstage/backend-test-utils@0.1.16 + +## 0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + - @backstage/backend-test-utils@0.1.16-next.1 + ## 0.1.8-next.0 ### Patch Changes diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index d3c6cab9cf..a713e61503 100644 --- a/plugins/bazaar-backend/package.json +++ b/plugins/bazaar-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar-backend", - "version": "0.1.8-next.0", + "version": "0.1.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,8 +20,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", - "@backstage/backend-test-utils": "^0.1.16-next.0", + "@backstage/backend-common": "^0.10.6", + "@backstage/backend-test-utils": "^0.1.16", "@backstage/config": "^0.1.13", "@types/express": "^4.17.6", "express": "^4.17.1", @@ -31,7 +31,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0" + "@backstage/cli": "^0.13.1" }, "files": [ "dist", diff --git a/plugins/bazaar/CHANGELOG.md b/plugins/bazaar/CHANGELOG.md index 949910ae40..8fd907c6bd 100644 --- a/plugins/bazaar/CHANGELOG.md +++ b/plugins/bazaar/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-bazaar +## 0.1.12 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + - @backstage/cli@0.13.1 + - @backstage/plugin-catalog@0.7.11 + ## 0.1.12-next.0 ### Patch Changes diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index 9dd3bf5125..111bccced6 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar", - "version": "0.1.12-next.0", + "version": "0.1.12", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,11 +23,11 @@ "dependencies": { "@backstage/catalog-client": "^0.5.5", "@backstage/catalog-model": "^0.9.10", - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/cli": "^0.13.1", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog": "^0.7.11-next.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog": "^0.7.11", + "@backstage/plugin-catalog-react": "^0.6.13", "@date-io/luxon": "2.x", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -44,8 +44,8 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/dev-utils": "^0.2.20-next.0", + "@backstage/cli": "^0.13.1", + "@backstage/dev-utils": "^0.2.20", "@testing-library/jest-dom": "^5.10.1", "cross-fetch": "^3.0.6" }, diff --git a/plugins/bitrise/CHANGELOG.md b/plugins/bitrise/CHANGELOG.md index f91dbbd5b3..e37e17882c 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-bitrise +## 0.1.24 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + ## 0.1.24-next.0 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index ee1a91ba23..6c8dea09b4 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-bitrise", "description": "A Backstage plugin that integrates towards Bitrise", - "version": "0.1.24-next.0", + "version": "0.1.24", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,9 +22,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -40,10 +40,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index c6e97d4906..67e8aeade2 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.3.11 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@0.21.2 + ## 0.3.11-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index 79dbf3335c..cb57a8fbed 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 modules that helps integrate towards LDAP", - "version": "0.3.11-next.0", + "version": "0.3.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,7 +32,7 @@ "@backstage/catalog-model": "^0.9.10", "@backstage/config": "^0.1.13", "@backstage/errors": "^0.2.0", - "@backstage/plugin-catalog-backend": "^0.21.2-next.0", + "@backstage/plugin-catalog-backend": "^0.21.2", "@backstage/types": "^0.1.1", "@types/ldapjs": "^2.2.0", "ldapjs": "^2.2.0", @@ -40,7 +40,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@types/lodash": "^4.14.151" }, "files": [ diff --git a/plugins/catalog-backend-module-msgraph/CHANGELOG.md b/plugins/catalog-backend-module-msgraph/CHANGELOG.md index 4a36db457b..6d8771b609 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.2.14 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@0.21.2 + ## 0.2.14-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index dd387fb05d..795a113144 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-msgraph", "description": "A Backstage catalog backend modules that helps integrate towards Microsoft Graph", - "version": "0.2.14-next.0", + "version": "0.2.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,7 +32,7 @@ "@azure/msal-node": "^1.1.0", "@backstage/catalog-model": "^0.9.10", "@backstage/config": "^0.1.13", - "@backstage/plugin-catalog-backend": "^0.21.2-next.0", + "@backstage/plugin-catalog-backend": "^0.21.2", "@microsoft/microsoft-graph-types": "^2.6.0", "@types/node-fetch": "^2.5.12", "lodash": "^4.17.21", @@ -42,9 +42,9 @@ "qs": "^6.9.4" }, "devDependencies": { - "@backstage/backend-common": "^0.10.5", - "@backstage/cli": "^0.13.1-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/backend-common": "^0.10.6", + "@backstage/cli": "^0.13.1", + "@backstage/test-utils": "^0.2.4", "@types/lodash": "^4.14.151", "msw": "^0.35.0" }, diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 94097a6745..e46d30350f 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-catalog-backend +## 0.21.2 + +### Patch Changes + +- fac5f112b4: chore(deps): bump `prom-client` from 13.2.0 to 14.0.1 +- 5bbffa60be: Pass authorization token to location service inside location api routes +- Updated dependencies + - @backstage/plugin-catalog-common@0.1.2 + - @backstage/backend-common@0.10.6 + - @backstage/plugin-permission-node@0.4.2 + +## 0.21.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@0.1.2-next.0 + - @backstage/backend-common@0.10.6-next.0 + - @backstage/plugin-permission-node@0.4.2-next.1 + ## 0.21.2-next.0 ### Patch Changes diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 95bdb2fcf2..f2f9d91b1b 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": "0.21.2-next.0", + "version": "0.21.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,15 +30,15 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/catalog-client": "^0.5.5", "@backstage/catalog-model": "^0.9.10", "@backstage/config": "^0.1.13", "@backstage/errors": "^0.2.0", "@backstage/integration": "^0.7.2", - "@backstage/plugin-catalog-common": "^0.1.1", + "@backstage/plugin-catalog-common": "^0.1.2", "@backstage/plugin-permission-common": "^0.4.0", - "@backstage/plugin-permission-node": "^0.4.2-next.0", + "@backstage/plugin-permission-node": "^0.4.2", "@backstage/search-common": "^0.2.2", "@backstage/types": "^0.1.1", "@octokit/graphql": "^4.5.8", @@ -65,10 +65,10 @@ "yup": "^0.32.9" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.16-next.0", - "@backstage/cli": "^0.13.1-next.0", + "@backstage/backend-test-utils": "^0.1.16", + "@backstage/cli": "^0.13.1", "@backstage/plugin-permission-common": "^0.4.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/test-utils": "^0.2.4", "@types/core-js": "^2.5.4", "@types/git-url-parse": "^9.0.0", "@types/lodash": "^4.14.151", diff --git a/plugins/catalog-common/CHANGELOG.md b/plugins/catalog-common/CHANGELOG.md index 77bc30964c..a236e55857 100644 --- a/plugins/catalog-common/CHANGELOG.md +++ b/plugins/catalog-common/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-common +## 0.1.2 + +### Patch Changes + +- ba59832aed: Adds new `catalogEntityCreatePermission` which can be imported and used when authoring a permission policy to restrict/grant a user's access to the catalog import plugin. (And the "Register Existing Component" button which navigates there). + +## 0.1.2-next.0 + +### Patch Changes + +- ba59832aed: Adds new `catalogEntityCreatePermission` which can be imported and used when authoring a permission policy to restrict/grant a user's access to the catalog import plugin. (And the "Register Existing Component" button which navigates there). + ## 0.1.1 ### Patch Changes diff --git a/plugins/catalog-common/package.json b/plugins/catalog-common/package.json index 340a4baa8a..b9cf9a20dd 100644 --- a/plugins/catalog-common/package.json +++ b/plugins/catalog-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-common", "description": "Common functionalities for the catalog plugin", - "version": "0.1.1", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,7 +33,7 @@ "@backstage/plugin-permission-common": "^0.4.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0" + "@backstage/cli": "^0.13.1" }, "files": [ "dist" diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index 0da33cddf9..56446575da 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-catalog-graph +## 0.2.9 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + ## 0.2.9-next.0 ### Patch Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 49cce2ae51..10dafe8daa 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graph", - "version": "0.2.9-next.0", + "version": "0.2.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,9 +23,9 @@ "dependencies": { "@backstage/catalog-client": "^0.5.5", "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -42,10 +42,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index 4e4f61b103..affc3e0ee6 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -43,8 +43,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1-next.1", + "@backstage/test-utils": "^0.2.4-next.0", "@graphql-codegen/cli": "^2.3.1", "@graphql-codegen/typescript": "^2.4.2", "@graphql-codegen/typescript-resolvers": "^2.4.3", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 652f39ed61..f3aae8182e 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,47 @@ # @backstage/plugin-catalog-import +## 0.8.0 + +### Minor Changes + +- 2e8764b95f: Make filename, branch name and examples URLs used in catalog import customizable. + + Catalog backend ingestion loop can be already configured to fetch targets with custom catalog filename (other than `catalog-info.yaml`). It's now possible to customize said filename and branch name used in pull requests created by catalog import flow too. This allows organizations to further customize Backstage experience and to better reflect their branding. + + Filename (default: `catalog-info.yaml`) and branch name (default: `backstage-integration`) used in pull requests can be configured in `app-config.yaml` as follows: + + ```yaml + // app-config.yaml + + catalog: + import: + entityFilename: anvil.yaml + pullRequestBranchName: anvil-integration + ``` + + Following React components have also been updated to accept optional props for providing example entity and repository paths: + + ```tsx + + ``` + + ```tsx + + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + - @backstage/integration-react@0.1.20 + ## 0.8.0-next.0 ### Minor Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index cd3323a6b4..0b452aa239 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-import", "description": "A Backstage plugin the helps you import entities into your catalog", - "version": "0.8.0-next.0", + "version": "0.8.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,13 +33,13 @@ "dependencies": { "@backstage/catalog-client": "^0.5.5", "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/config": "^0.1.13", "@backstage/core-plugin-api": "^0.6.0", "@backstage/errors": "^0.2.0", "@backstage/integration": "^0.7.2", - "@backstage/integration-react": "^0.1.20-next.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/integration-react": "^0.1.20", + "@backstage/plugin-catalog-react": "^0.6.13", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -57,10 +57,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index 48cc93e7b1..e38f17b37d 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-catalog-react +## 0.6.13 + +### Patch Changes + +- f7257dff6f: The `` component now accepts a `noTrack` prop, which prevents the `click` event from being captured by the Analytics API. This can be used if tracking is explicitly not warranted, or in order to use custom link tracking in specific situations. +- 300f8cdaee: Fix bug: previously the filter would be set to "all" on page load, even if the + `initiallySelectedFilter` on the `DefaultCatalogPage` was set to something else, + or a different query parameter was supplied. Now, the prop and query parameters + control the filter as expected. Additionally, after this change any filters + which match 0 items will be disabled, and the filter will be reverted to 'all' + if they're set on page load. +- 6acc8f7db7: Add caching to the useEntityPermission hook + + The hook now caches the authorization decision based on the permission + the entity, and returns the cache match value as the default `allowed` value while loading. This helps avoid flicker in UI elements that would be conditionally rendered based on the `allowed` result of this hook. + +- Updated dependencies + - @backstage/core-components@0.8.7 + +## 0.6.13-next.1 + +### Patch Changes + +- f7257dff6f: The `` component now accepts a `noTrack` prop, which prevents the `click` event from being captured by the Analytics API. This can be used if tracking is explicitly not warranted, or in order to use custom link tracking in specific situations. +- 300f8cdaee: Fix bug: previously the filter would be set to "all" on page load, even if the + `initiallySelectedFilter` on the `DefaultCatalogPage` was set to something else, + or a different query parameter was supplied. Now, the prop and query parameters + control the filter as expected. Additionally, after this change any filters + which match 0 items will be disabled, and the filter will be reverted to 'all' + if they're set on page load. +- 6acc8f7db7: Add caching to the useEntityPermission hook + + The hook now caches the authorization decision based on the permission + the entity, and returns the cache match value as the default `allowed` value while loading. This helps avoid flicker in UI elements that would be conditionally rendered based on the `allowed` result of this hook. + +- Updated dependencies + - @backstage/core-components@0.8.7-next.1 + ## 0.6.13-next.0 ### Patch Changes diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 282ddc02ed..9018ea75d7 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": "0.6.13-next.0", + "version": "0.6.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,7 +31,7 @@ "dependencies": { "@backstage/catalog-client": "^0.5.5", "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/errors": "^0.2.0", "@backstage/integration": "^0.7.2", @@ -54,10 +54,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/plugin-catalog-common": "^0.1.1", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/plugin-catalog-common": "^0.1.2", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index 4cf5533dbf..8ccca07609 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-catalog +## 0.7.11 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + - @backstage/plugin-catalog-common@0.1.2 + - @backstage/integration-react@0.1.20 + +## 0.7.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7-next.1 + - @backstage/plugin-catalog-react@0.6.13-next.1 + - @backstage/plugin-catalog-common@0.1.2-next.0 + ## 0.7.11-next.0 ### Patch Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 8d06e50b09..0a3211fcaf 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog", "description": "The Backstage plugin for browsing the Backstage catalog", - "version": "0.7.11-next.0", + "version": "0.7.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,12 +33,12 @@ "dependencies": { "@backstage/catalog-client": "^0.5.5", "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/errors": "^0.2.0", - "@backstage/integration-react": "^0.1.20-next.0", - "@backstage/plugin-catalog-common": "^0.1.1", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/integration-react": "^0.1.20", + "@backstage/plugin-catalog-common": "^0.1.2", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -54,11 +54,11 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", "@backstage/plugin-permission-react": "^0.3.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md index 303114a79c..5ad74a75c4 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-circleci +## 0.2.36 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + ## 0.2.36-next.0 ### Patch Changes diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index cb11885fb4..8fffeffc37 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-circleci", "description": "A Backstage plugin that integrates towards Circle CI", - "version": "0.2.36-next.0", + "version": "0.2.36", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,9 +33,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -52,10 +52,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md index 6f7e0f7562..08c66d50dd 100644 --- a/plugins/cloudbuild/CHANGELOG.md +++ b/plugins/cloudbuild/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-cloudbuild +## 0.2.34 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + ## 0.2.34-next.0 ### Patch Changes diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 808faac15b..6bb299418b 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cloudbuild", "description": "A Backstage plugin that integrates towards Google Cloud Build", - "version": "0.2.34-next.0", + "version": "0.2.34", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,9 +32,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -49,10 +49,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/code-coverage-backend/CHANGELOG.md b/plugins/code-coverage-backend/CHANGELOG.md index 8faa0d789d..def8cca7f0 100644 --- a/plugins/code-coverage-backend/CHANGELOG.md +++ b/plugins/code-coverage-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-code-coverage-backend +## 0.1.21 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6 + +## 0.1.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + ## 0.1.20 ### Patch Changes diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index aa60df0893..e01619671f 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.1.20", + "version": "0.1.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,7 +20,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/catalog-client": "^0.5.5", "@backstage/catalog-model": "^0.9.10", "@backstage/config": "^0.1.13", @@ -36,7 +36,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@types/express-xml-bodyparser": "^0.3.2", "@types/supertest": "^2.0.8", "msw": "^0.35.0", diff --git a/plugins/code-coverage/CHANGELOG.md b/plugins/code-coverage/CHANGELOG.md index eb1a926900..7aef422166 100644 --- a/plugins/code-coverage/CHANGELOG.md +++ b/plugins/code-coverage/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-code-coverage +## 0.1.24 + +### Patch Changes + +- 2ce5e4e0a7: Fixed a bug in the FileExplorer component which made it impossible to navigate upwards to a containing folder by clicking on the folder breadcrumb. +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + +## 0.1.24-next.1 + +### Patch Changes + +- 2ce5e4e0a7: Fixed a bug in the FileExplorer component which made it impossible to navigate upwards to a containing folder by clicking on the folder breadcrumb. +- Updated dependencies + - @backstage/core-components@0.8.7-next.1 + - @backstage/plugin-catalog-react@0.6.13-next.1 + ## 0.1.24-next.0 ### Patch Changes diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 47837e09ba..44e970d54a 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.1.24-next.0", + "version": "0.1.24", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,10 +23,10 @@ "dependencies": { "@backstage/catalog-model": "^0.9.10", "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/errors": "^0.2.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -43,10 +43,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/code-coverage/src/components/FileExplorer/FileExplorer.test.tsx b/plugins/code-coverage/src/components/FileExplorer/FileExplorer.test.tsx index 4163b22ac1..b59b3ad1fd 100644 --- a/plugins/code-coverage/src/components/FileExplorer/FileExplorer.test.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/FileExplorer.test.tsx @@ -13,7 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { groupByPath, buildFileStructure } from './FileExplorer'; +import { + groupByPath, + buildFileStructure, + getObjectsAtPath, +} from './FileExplorer'; const dummyFiles = [ { @@ -207,6 +211,28 @@ const coverageTableRowResults = { path: '', }; +const pathTestLeaf = { + files: [], + coverage: 1, + missing: 3, + tracked: 2, + path: 'file5', +}; + +const dummyFilesPathTest = { + files: [ + ...dummyFiles, + { + ...pathTestLeaf, + filename: 'dir3/dir7/file5', + }, + ], + coverage: 1, + missing: 1, + tracked: 1, + path: '', +}; + describe('groupByPath function', () => { it('should group files by their root directory,as per their filename', () => { expect(groupByPath(dummyFiles)).toStrictEqual(dummyDataGroupedByPath); @@ -220,3 +246,19 @@ describe('buildFileStructure function', () => { ); }); }); + +describe('getObjectsAtPath function', () => { + const structure = buildFileStructure(dummyFilesPathTest); + + it('should return the the dirs/files at the given path', () => { + expect(getObjectsAtPath(structure, ['dir3', 'dir7'])).toStrictEqual([ + pathTestLeaf, + ]); + }); + + it('should return undefined for a nonexistent path', () => { + expect( + getObjectsAtPath(structure, ['dir3', 'doesnt-exist']), + ).toBeUndefined(); + }); +}); diff --git a/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx b/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx index 790de6e00f..3d41a1ff64 100644 --- a/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx @@ -131,6 +131,17 @@ const formatInitialData = (value: any) => { }); }; +export const getObjectsAtPath = ( + curData: CoverageTableRow | undefined, + path: string[], +): CoverageTableRow[] | undefined => { + let data = curData?.files; + for (const fragment of path) { + data = data?.find(d => d.path === fragment)?.files; + } + return data; +}; + export const FileExplorer = () => { const { entity } = useEntity(); const [curData, setCurData] = useState(); @@ -175,14 +186,10 @@ export const FileExplorer = () => { } }; - const moveUpIntoPath = (path: string) => { - const pathArray = path.split('/').filter(p => p.length); - let data = curData?.files; - pathArray.forEach(p => { - data = data?.find(d => d.path === p)?.files; - }); - setCurPath(path); - setTableData(data); + const moveUpIntoPath = (idx: number) => { + const path = curPath.split('/').slice(0, idx + 1); + setCurPath(path.join('/')); + setTableData(getObjectsAtPath(curData, path.slice(1))); }; const columns: TableColumn[] = [ @@ -270,8 +277,8 @@ export const FileExplorer = () => { color: `${idx !== lastPathElementIndex && 'lightblue'}`, cursor: `${idx !== lastPathElementIndex && 'pointer'}`, }} - onKeyDown={() => moveUpIntoPath(pathElement)} - onClick={() => moveUpIntoPath(pathElement)} + onKeyDown={() => moveUpIntoPath(idx)} + onClick={() => moveUpIntoPath(idx)} > {pathElement || 'root'}
diff --git a/plugins/config-schema/CHANGELOG.md b/plugins/config-schema/CHANGELOG.md index 05e694f3eb..9c6ff062a7 100644 --- a/plugins/config-schema/CHANGELOG.md +++ b/plugins/config-schema/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-config-schema +## 0.1.20 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + ## 0.1.20-next.0 ### Patch Changes diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 51705222d2..26a583fa95 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-config-schema", "description": "A Backstage plugin that lets you browse the configuration schema of your app", - "version": "0.1.20-next.0", + "version": "0.1.20", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,7 +22,7 @@ }, "dependencies": { "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/errors": "^0.2.0", "@backstage/theme": "^0.2.14", @@ -38,10 +38,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index 4a068b20d6..93a9bbdb19 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-cost-insights +## 0.11.19 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + ## 0.11.19-next.0 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 48c4916beb..288464129d 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cost-insights", "description": "A Backstage plugin that helps you keep track of your cloud spend", - "version": "0.11.19-next.0", + "version": "0.11.19", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,7 +33,7 @@ "dependencies": { "@backstage/catalog-model": "^0.9.10", "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", @@ -57,10 +57,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/explore-react/package.json b/plugins/explore-react/package.json index 902933b7d3..7bd9edd854 100644 --- a/plugins/explore-react/package.json +++ b/plugins/explore-react/package.json @@ -32,9 +32,9 @@ "@backstage/core-plugin-api": "^0.6.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1-next.1", + "@backstage/dev-utils": "^0.2.20-next.1", + "@backstage/test-utils": "^0.2.4-next.0", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/explore/CHANGELOG.md b/plugins/explore/CHANGELOG.md index 0dc472d3f0..03c200c5e8 100644 --- a/plugins/explore/CHANGELOG.md +++ b/plugins/explore/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-explore +## 0.3.28 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + ## 0.3.28-next.0 ### Patch Changes diff --git a/plugins/explore/package.json b/plugins/explore/package.json index d9c87d1826..424f6abf2f 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-explore", "description": "A Backstage plugin for building an exploration page of your software ecosystem", - "version": "0.3.28-next.0", + "version": "0.3.28", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,9 +32,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/plugin-explore-react": "^0.0.11", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", @@ -50,10 +50,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/firehydrant/CHANGELOG.md b/plugins/firehydrant/CHANGELOG.md index 7af43b2697..c441693df6 100644 --- a/plugins/firehydrant/CHANGELOG.md +++ b/plugins/firehydrant/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-firehydrant +## 0.1.14 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + ## 0.1.14-next.0 ### Patch Changes diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index d9e93dd983..4d1cc6ba44 100644 --- a/plugins/firehydrant/package.json +++ b/plugins/firehydrant/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-firehydrant", "description": "A Backstage plugin that integrates towards FireHydrant", - "version": "0.1.14-next.0", + "version": "0.1.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,9 +22,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -36,10 +36,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md index a65d8a223a..d01d581db8 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-fossa +## 0.2.29 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + ## 0.2.29-next.0 ### Patch Changes diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 05157e9ed7..9ce1008659 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-fossa", "description": "A Backstage plugin that integrates towards FOSSA", - "version": "0.2.29-next.0", + "version": "0.2.29", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,10 +33,10 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/errors": "^0.2.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -50,10 +50,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/gcp-projects/CHANGELOG.md b/plugins/gcp-projects/CHANGELOG.md index 7df85f2a37..77b57867c5 100644 --- a/plugins/gcp-projects/CHANGELOG.md +++ b/plugins/gcp-projects/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-gcp-projects +## 0.3.16 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + ## 0.3.16-next.0 ### Patch Changes diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index d5632e0a13..0df05ae7b1 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gcp-projects", "description": "A Backstage plugin that helps you manage projects in GCP", - "version": "0.3.16-next.0", + "version": "0.3.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", @@ -44,10 +44,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/git-release-manager/CHANGELOG.md b/plugins/git-release-manager/CHANGELOG.md index 5ba514faa9..605f27322e 100644 --- a/plugins/git-release-manager/CHANGELOG.md +++ b/plugins/git-release-manager/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-git-release-manager +## 0.3.10 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + ## 0.3.10-next.0 ### Patch Changes diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 016a66cd29..b2acf96ccf 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.10-next.0", + "version": "0.3.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,7 +21,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/integration": "^0.7.2", "@backstage/theme": "^0.2.14", @@ -40,10 +40,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/git-release-manager/src/features/Features.test.tsx b/plugins/git-release-manager/src/features/Features.test.tsx index 28bd9b6310..8f9e3544f2 100644 --- a/plugins/git-release-manager/src/features/Features.test.tsx +++ b/plugins/git-release-manager/src/features/Features.test.tsx @@ -55,7 +55,7 @@ describe('Features', () => { expect(getByTestId(TEST_IDS.info.info)).toMatchInlineSnapshot(`
{ kind: 'User', metadata: { name: 'calum.leavy', + description: 'Super awesome human', }, spec: { profile: { @@ -73,5 +74,6 @@ describe('UserSummary Test', () => { 'href', '/catalog/default/group/ExampleGroup', ); + expect(rendered.getByText('Super awesome human')).toBeInTheDocument(); }); }); diff --git a/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.tsx b/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.tsx index 298819ed09..0997e0a4d8 100644 --- a/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.tsx +++ b/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.tsx @@ -61,7 +61,7 @@ export const UserProfileCard = ({ } const { - metadata: { name: metaName }, + metadata: { name: metaName, description }, spec: { profile }, } = user; const displayName = profile?.displayName ?? metaName; @@ -71,7 +71,11 @@ export const UserProfileCard = ({ }); return ( - } variant={variant}> + } + subheader={description} + variant={variant} + > diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index fe22454657..4de0112481 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-pagerduty +## 0.3.24 + +### Patch Changes + +- 5a459626bc: Fix change events tab error when change events exist +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + ## 0.3.24-next.0 ### Patch Changes diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 2a57f5b0d5..96b1c6738b 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-pagerduty", "description": "A Backstage plugin that integrates towards PagerDuty", - "version": "0.3.24-next.0", + "version": "0.3.24", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,9 +32,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -49,10 +49,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/permission-backend/CHANGELOG.md b/plugins/permission-backend/CHANGELOG.md index 629a7d5f96..5a2aaa72bf 100644 --- a/plugins/permission-backend/CHANGELOG.md +++ b/plugins/permission-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-permission-backend +## 0.4.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-backend@0.9.0 + - @backstage/backend-common@0.10.6 + - @backstage/plugin-permission-node@0.4.2 + +## 0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-backend@0.9.0-next.1 + - @backstage/backend-common@0.10.6-next.0 + - @backstage/plugin-permission-node@0.4.2-next.1 + ## 0.4.2-next.0 ### Patch Changes diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index aeba1577bf..8c0bdb93c4 100644 --- a/plugins/permission-backend/package.json +++ b/plugins/permission-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-backend", - "version": "0.4.2-next.0", + "version": "0.4.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -19,12 +19,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/config": "^0.1.13", "@backstage/errors": "^0.2.0", - "@backstage/plugin-auth-backend": "^0.9.0-next.0", + "@backstage/plugin-auth-backend": "^0.9.0", "@backstage/plugin-permission-common": "^0.4.0", - "@backstage/plugin-permission-node": "^0.4.2-next.0", + "@backstage/plugin-permission-node": "^0.4.2", "@types/express": "*", "dataloader": "^2.0.0", "express": "^4.17.1", @@ -36,7 +36,7 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@types/lodash": "^4.14.151", "@types/supertest": "^2.0.8", "supertest": "^6.1.6", diff --git a/plugins/permission-node/CHANGELOG.md b/plugins/permission-node/CHANGELOG.md index e1f62551e3..c4690777f6 100644 --- a/plugins/permission-node/CHANGELOG.md +++ b/plugins/permission-node/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-permission-node +## 0.4.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-backend@0.9.0 + - @backstage/backend-common@0.10.6 + +## 0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-backend@0.9.0-next.1 + - @backstage/backend-common@0.10.6-next.0 + ## 0.4.2-next.0 ### Patch Changes diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index 5a0213ef63..a5b6adabc2 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.4.2-next.0", + "version": "0.4.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,10 +29,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/config": "^0.1.13", "@backstage/errors": "^0.2.0", - "@backstage/plugin-auth-backend": "^0.9.0-next.0", + "@backstage/plugin-auth-backend": "^0.9.0", "@backstage/plugin-permission-common": "^0.4.0", "@types/express": "^4.17.6", "express": "^4.17.1", @@ -40,7 +40,7 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@types/supertest": "^2.0.8", "msw": "^0.35.0", "supertest": "^6.1.3" diff --git a/plugins/permission-react/package.json b/plugins/permission-react/package.json index e4ae819247..b1e0350dcc 100644 --- a/plugins/permission-react/package.json +++ b/plugins/permission-react/package.json @@ -32,15 +32,16 @@ "@backstage/plugin-permission-common": "^0.4.0", "cross-fetch": "^3.0.6", "react-router": "6.0.0-beta.0", - "react-use": "^17.2.4" + "react-use": "^17.2.4", + "swr": "^1.1.2" }, "peerDependencies": { "@types/react": "^16.13.1 || ^17.0.0", "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1-next.1", + "@backstage/test-utils": "^0.2.4-next.0", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@types/jest": "^26.0.7" diff --git a/plugins/permission-react/src/hooks/usePermission.test.tsx b/plugins/permission-react/src/hooks/usePermission.test.tsx index 4cf0bc6530..d6c5b2ed33 100644 --- a/plugins/permission-react/src/hooks/usePermission.test.tsx +++ b/plugins/permission-react/src/hooks/usePermission.test.tsx @@ -19,9 +19,8 @@ import { render } from '@testing-library/react'; import { usePermission } from './usePermission'; import { AuthorizeResult } from '@backstage/plugin-permission-common'; import { TestApiProvider } from '@backstage/test-utils'; -import { permissionApiRef } from '../apis'; - -const mockAuthorize = jest.fn(); +import { PermissionApi, permissionApiRef } from '../apis'; +import { SWRConfig } from 'swr'; const permission = { name: 'access.something', @@ -39,49 +38,48 @@ const TestComponent: FC = () => { ); }; -describe('usePermission', () => { - it('Returns loading when permissionApi has not yet responded.', () => { - mockAuthorize.mockReturnValueOnce(new Promise(() => {})); - - const { getByText } = render( - +function renderComponent(mockApi: PermissionApi) { + return render( + new Map() }}> + - , - ); + + , + , + ); +} - expect(mockAuthorize).toHaveBeenCalledWith({ permission }); +describe('usePermission', () => { + const mockPermissionApi = { authorize: jest.fn() }; + + it('Returns loading when permissionApi has not yet responded.', () => { + mockPermissionApi.authorize.mockReturnValueOnce(new Promise(() => {})); + + const { getByText } = renderComponent(mockPermissionApi); + + expect(mockPermissionApi.authorize).toHaveBeenCalledWith({ permission }); expect(getByText('loading')).toBeTruthy(); }); it('Returns allowed when permissionApi allows authorization.', async () => { - mockAuthorize.mockResolvedValueOnce({ result: AuthorizeResult.ALLOW }); + mockPermissionApi.authorize.mockResolvedValueOnce({ + result: AuthorizeResult.ALLOW, + }); - const { findByText } = render( - - - , - ); + const { findByText } = renderComponent(mockPermissionApi); - expect(mockAuthorize).toHaveBeenCalledWith({ permission }); + expect(mockPermissionApi.authorize).toHaveBeenCalledWith({ permission }); expect(await findByText('content')).toBeTruthy(); }); it('Returns not allowed when permissionApi denies authorization.', async () => { - mockAuthorize.mockResolvedValueOnce({ result: AuthorizeResult.DENY }); + mockPermissionApi.authorize.mockResolvedValueOnce({ + result: AuthorizeResult.DENY, + }); - const { findByText } = render( - - - , - ); + const { findByText } = renderComponent(mockPermissionApi); - expect(mockAuthorize).toHaveBeenCalledWith({ permission }); + expect(mockPermissionApi.authorize).toHaveBeenCalledWith({ permission }); await expect(findByText('content')).rejects.toThrowError(); }); }); diff --git a/plugins/permission-react/src/hooks/usePermission.ts b/plugins/permission-react/src/hooks/usePermission.ts index 45136d6697..cc27f82c59 100644 --- a/plugins/permission-react/src/hooks/usePermission.ts +++ b/plugins/permission-react/src/hooks/usePermission.ts @@ -14,13 +14,13 @@ * limitations under the License. */ -import useAsync from 'react-use/lib/useAsync'; import { useApi } from '@backstage/core-plugin-api'; import { permissionApiRef } from '../apis'; import { AuthorizeResult, Permission, } from '@backstage/plugin-permission-common'; +import useSWR from 'swr'; /** @public */ export type AsyncPermissionResult = { @@ -30,9 +30,16 @@ export type AsyncPermissionResult = { }; /** - * React hook utlity for authorization. Given a {@link @backstage/plugin-permission-common#Permission} and an optional - * resourceRef, it will return whether or not access is allowed (for the given resource, if resourceRef is provided). See - * {@link @backstage/plugin-permission-common/PermissionClient#authorize} for more details. + * React hook utility for authorization. Given a + * {@link @backstage/plugin-permission-common#Permission} and an optional + * resourceRef, it will return whether or not access is allowed (for the given + * resource, if resourceRef is provided). See + * {@link @backstage/plugin-permission-common/PermissionClient#authorize} for + * more details. + * + * Note: This hook uses stale-while-revalidate to help avoid flicker in UI + * elements that would be conditionally rendered based on the `allowed` result + * of this hook. * @public */ export const usePermission = ( @@ -40,21 +47,16 @@ export const usePermission = ( resourceRef?: string, ): AsyncPermissionResult => { const permissionApi = useApi(permissionApiRef); - - const { loading, error, value } = useAsync(async () => { - const { result } = await permissionApi.authorize({ - permission, - resourceRef, - }); - + const { data, error } = useSWR({ permission, resourceRef }, async args => { + const { result } = await permissionApi.authorize(args); return result; - }, [permissionApi, permission, resourceRef]); + }); - if (loading) { - return { loading: true, allowed: false }; - } if (error) { return { error, loading: false, allowed: false }; } - return { loading: false, allowed: value === AuthorizeResult.ALLOW }; + if (data === undefined) { + return { loading: true, allowed: false }; + } + return { loading: false, allowed: data === AuthorizeResult.ALLOW }; }; diff --git a/plugins/proxy-backend/CHANGELOG.md b/plugins/proxy-backend/CHANGELOG.md index 7e8cd6803f..4fb4328974 100644 --- a/plugins/proxy-backend/CHANGELOG.md +++ b/plugins/proxy-backend/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-proxy-backend +## 0.2.17 + +### Patch Changes + +- 332d3decb2: Adds a new option `skipInvalidTargets` for the proxy `createRouter` which allows the proxy backend to be started with an invalid proxy configuration. If configured, it will simply skip the failed proxy and mount the other valid proxies. + + To configure it to pass by failing proxies: + + ``` + const router = await createRouter({ + config, + logger, + discovery, + skipInvalidProxies: true, + }); + ``` + + If you would like it to fail if a proxy is configured badly: + + ``` + const router = await createRouter({ + config, + logger, + discovery, + }); + ``` + +- Updated dependencies + - @backstage/backend-common@0.10.6 + +## 0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + ## 0.2.17-next.0 ### Patch Changes diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 031f8e5665..3d7d03794b 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-proxy-backend", "description": "A Backstage backend plugin that helps you set up proxy endpoints in the backend", - "version": "0.2.17-next.0", + "version": "0.2.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,7 +29,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/config": "^0.1.13", "@types/express": "^4.17.6", "express": "^4.17.1", @@ -43,7 +43,7 @@ "yup": "^0.32.9" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@types/http-proxy-middleware": "^0.19.3", "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", diff --git a/plugins/rollbar-backend/CHANGELOG.md b/plugins/rollbar-backend/CHANGELOG.md index d14c5644a8..9f6c657935 100644 --- a/plugins/rollbar-backend/CHANGELOG.md +++ b/plugins/rollbar-backend/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-rollbar-backend +## 0.1.20 + +### Patch Changes + +- 91faf87aaf: chore(deps): bump `camelcase-keys` from 6.2.2 to 7.0.1 +- Updated dependencies + - @backstage/backend-common@0.10.6 + +## 0.1.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + ## 0.1.20-next.0 ### Patch Changes diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index 8972572f1f..81f288c9e8 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-rollbar-backend", "description": "A Backstage backend plugin that integrates towards Rollbar", - "version": "0.1.20-next.0", + "version": "0.1.20", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/config": "^0.1.13", "@types/express": "^4.17.6", "camelcase-keys": "^7.0.1", @@ -48,8 +48,8 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/test-utils": "^0.2.4", "@types/supertest": "^2.0.8", "msw": "^0.36.3", "supertest": "^6.1.3" diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md index 5fc59c3efd..fdb3feb3ea 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-rollbar +## 0.3.25 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + ## 0.3.25-next.0 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 2a4a18979c..35e660a650 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-rollbar", "description": "A Backstage plugin that integrates towards Rollbar", - "version": "0.3.25-next.0", + "version": "0.3.25", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,9 +33,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -50,10 +50,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md index cbc1119062..231538cbc1 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-scaffolder-backend-module-cookiecutter +## 0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@0.15.23 + - @backstage/backend-common@0.10.6 + +## 0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + - @backstage/plugin-scaffolder-backend@0.15.23-next.1 + ## 0.1.10-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index ed267e2846..e7e2d7b469 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.1.10-next.0", + "version": "0.1.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,10 +20,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/errors": "^0.2.0", "@backstage/integration": "^0.7.2", - "@backstage/plugin-scaffolder-backend": "^0.15.23-next.0", + "@backstage/plugin-scaffolder-backend": "^0.15.23", "@backstage/config": "^0.1.13", "@backstage/types": "^0.1.1", "command-exists": "^1.2.9", @@ -32,7 +32,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@types/fs-extra": "^9.0.1", "@types/mock-fs": "^4.13.0", "@types/jest": "^26.0.7", diff --git a/plugins/scaffolder-backend-module-rails/CHANGELOG.md b/plugins/scaffolder-backend-module-rails/CHANGELOG.md index 94e0c5b411..bb78b9e5fd 100644 --- a/plugins/scaffolder-backend-module-rails/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-rails/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-scaffolder-backend-module-rails +## 0.2.5 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@0.15.23 + - @backstage/backend-common@0.10.6 + +## 0.2.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + - @backstage/plugin-scaffolder-backend@0.15.23-next.1 + ## 0.2.5-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index 3e73840fed..36d68bf46d 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.2.5-next.0", + "version": "0.2.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,8 +21,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", - "@backstage/plugin-scaffolder-backend": "^0.15.23-next.0", + "@backstage/backend-common": "^0.10.6", + "@backstage/plugin-scaffolder-backend": "^0.15.23", "@backstage/config": "^0.1.13", "@backstage/errors": "^0.2.0", "@backstage/integration": "^0.7.2", @@ -31,7 +31,7 @@ "fs-extra": "^9.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", "@types/command-exists": "^1.2.0", diff --git a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md index fb6c0bdab8..517cd20ca0 100644 --- a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-scaffolder-backend-module-yeoman +## 0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@0.15.23 + ## 0.1.4-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index 30fcbdc8e5..b43d0c50bb 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.1.4-next.0", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,13 +21,13 @@ }, "dependencies": { "@backstage/config": "^0.1.13", - "@backstage/plugin-scaffolder-backend": "^0.15.23-next.0", + "@backstage/plugin-scaffolder-backend": "^0.15.23", "@backstage/types": "^0.1.1", "winston": "^3.2.1", "yeoman-environment": "^3.6.0" }, "devDependencies": { - "@backstage/backend-common": "^0.10.4", + "@backstage/backend-common": "^0.10.6", "@types/jest": "^26.0.7" }, "files": [ diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index 41582a5f4e..b6061e8a38 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-scaffolder-backend +## 0.15.23 + +### Patch Changes + +- 2e0dbb0e50: Migrate from deprecated package @octokit/rest to octokit +- c95df1631e: Added support for templating secrets into actions input, and also added an extra `token` input argument to all publishers to provide a token that would override the `integrations.config`. + You can find more information over at [Writing Templates](https://backstage.io/docs/features/software-templates/writing-templates#using-the-users-oauth-token) +- Updated dependencies + - @backstage/plugin-catalog-backend@0.21.2 + - @backstage/backend-common@0.10.6 + - @backstage/plugin-scaffolder-backend-module-cookiecutter@0.1.10 + +## 0.15.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + - @backstage/plugin-catalog-backend@0.21.2-next.1 + - @backstage/plugin-scaffolder-backend-module-cookiecutter@0.1.10-next.1 + ## 0.15.23-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index cfe8f5d2b0..5e7b5a428b 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -299,7 +299,12 @@ export class OctokitProvider { githubCredentialsProvider?: GithubCredentialsProvider, ); // Warning: (ae-forgotten-export) The symbol "OctokitIntegration" needs to be exported by the entry point index.d.ts - getOctokit(repoUrl: string): Promise; + getOctokit( + repoUrl: string, + options?: { + token?: string; + }, + ): Promise; } // @public diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 790d6ed273..335d85327a 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": "0.15.23-next.0", + "version": "0.15.23", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,15 +31,15 @@ "build:assets": "node scripts/build-nunjucks.js" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/catalog-client": "^0.5.5", "@backstage/catalog-model": "^0.9.10", "@backstage/config": "^0.1.13", "@backstage/errors": "^0.2.0", "@backstage/integration": "^0.7.2", - "@backstage/plugin-catalog-backend": "^0.21.2-next.0", + "@backstage/plugin-catalog-backend": "^0.21.2", "@backstage/plugin-scaffolder-common": "^0.1.3", - "@backstage/plugin-scaffolder-backend-module-cookiecutter": "^0.1.10-next.0", + "@backstage/plugin-scaffolder-backend-module-cookiecutter": "^0.1.10", "@backstage/types": "^0.1.1", "@gitbeaker/core": "^34.6.0", "@gitbeaker/node": "^35.1.0", @@ -73,8 +73,8 @@ "vm2": "^3.9.5" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/test-utils": "^0.2.4", "@types/command-exists": "^1.2.0", "@types/fs-extra": "^9.0.1", "@types/git-url-parse": "^9.0.0", diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/OctokitProvider.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/OctokitProvider.test.ts index 0d4353c857..e2449917ab 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/OctokitProvider.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/OctokitProvider.test.ts @@ -74,4 +74,15 @@ describe('getOctokit', () => { expect(owner).toBe('owner'); expect(repo).toBe('bob'); }); + + it('should return an octokit client with the passed in token if it is provided', async () => { + const { client, token, owner, repo } = await octokitProvider.getOctokit( + 'github.com?repo=bob&owner=owner', + { token: 'tokenlols2' }, + ); + expect(client).toBeDefined(); + expect(token).toBe('tokenlols2'); + expect(owner).toBe('owner'); + expect(repo).toBe('bob'); + }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/OctokitProvider.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/OctokitProvider.ts index a3eeec4373..3ac66a0023 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/OctokitProvider.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/OctokitProvider.ts @@ -52,7 +52,10 @@ export class OctokitProvider { * * @param repoUrl - Repository URL */ - async getOctokit(repoUrl: string): Promise { + async getOctokit( + repoUrl: string, + options?: { token?: string }, + ): Promise { const { owner, repo, host } = parseRepoUrl(repoUrl, this.integrations); if (!owner) { @@ -65,7 +68,19 @@ export class OctokitProvider { throw new InputError(`No integration for host ${host}`); } - // TODO(blam): Consider changing this API to have owner, repo interface instead of URL as the it's + // Short circuit the internal Github Token provider the token provided + // by the action or the caller. + if (options?.token) { + const client = new Octokit({ + auth: options.token, + baseUrl: integrationConfig.apiBaseUrl, + previews: ['nebula-preview'], + }); + + return { client, token: options.token, owner, repo }; + } + + // TODO(blam): Consider changing this API to have owner, repoo interface instead of URL as the it's // needless to create URL and then parse again the other side. const { token } = await this.githubCredentialsProvider.getCredentials({ url: `https://${host}/${encodeURIComponent(owner)}/${encodeURIComponent( diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubActionsDispatch.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubActionsDispatch.ts index 1f7f0f60b9..0c8b4d4aab 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubActionsDispatch.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubActionsDispatch.ts @@ -37,6 +37,7 @@ export function createGithubActionsDispatchAction(options: { workflowId: string; branchOrTagName: string; workflowInputs?: { [key: string]: string }; + token?: string; }>({ id: 'github:actions:dispatch', description: @@ -68,18 +69,31 @@ export function createGithubActionsDispatchAction(options: { 'Inputs keys and values to send to GitHub Action configured on the workflow file. The maximum number of properties is 10. ', type: 'object', }, + token: { + title: 'Authentication Token', + type: 'string', + description: 'The GITHUB_TOKEN to use for authorization to GitHub', + }, }, }, }, async handler(ctx) { - const { repoUrl, workflowId, branchOrTagName, workflowInputs } = - ctx.input; + const { + repoUrl, + workflowId, + branchOrTagName, + workflowInputs, + token: providedToken, + } = ctx.input; ctx.logger.info( `Dispatching workflow ${workflowId} for repo ${repoUrl} on ${branchOrTagName}`, ); - const { client, owner, repo } = await octokitProvider.getOctokit(repoUrl); + const { client, owner, repo } = await octokitProvider.getOctokit( + repoUrl, + { token: providedToken }, + ); await client.rest.actions.createWorkflowDispatch({ owner, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts index 39e8c3aa70..660c7793f2 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts @@ -47,6 +47,7 @@ export function createGithubWebhookAction(options: { active?: boolean; contentType?: ContentType; insecureSsl?: boolean; + token?: string; }>({ id: 'github:webhook', description: 'Creates webhook for a repository on GitHub.', @@ -107,6 +108,11 @@ export function createGithubWebhookAction(options: { type: 'boolean', description: `Determines whether the SSL certificate of the host for url will be verified when delivering payloads. Default 'false'`, }, + token: { + title: 'Authentication Token', + type: 'string', + description: 'The GITHUB_TOKEN to use for authorization to GitHub', + }, }, }, }, @@ -119,11 +125,15 @@ export function createGithubWebhookAction(options: { active = true, contentType = 'form', insecureSsl = false, + token: providedToken, } = ctx.input; ctx.logger.info(`Creating webhook ${webhookUrl} for repo ${repoUrl}`); - const { client, owner, repo } = await octokitProvider.getOctokit(repoUrl); + const { client, owner, repo } = await octokitProvider.getOctokit( + repoUrl, + { token: providedToken }, + ); try { const insecure_ssl = insecureSsl ? '1' : '0'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts index cee99e1646..9247109121 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts @@ -119,6 +119,32 @@ describe('publish:azure', () => { ).rejects.toThrow(/Unable to create the repository/); }); + it('should not throw if there is a token provided through ctx.input', async () => { + mockGitClient.createRepository.mockImplementation(() => ({ + remoteUrl: 'http://google.com', + })); + + await action.handler({ + ...mockContext, + input: { + repoUrl: 'myazurehostnotoken.com?repo=bob&owner=owner&organization=org', + token: 'lols', + }, + }); + + expect(WebApi).toHaveBeenCalledWith( + 'https://myazurehostnotoken.com/org', + expect.any(Function), + ); + + expect(mockGitClient.createRepository).toHaveBeenCalledWith( + { + name: 'bob', + }, + 'owner', + ); + }); + it('should throw if there is no remoteUrl returned', async () => { mockGitClient.createRepository.mockImplementation(() => ({ remoteUrl: null, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts index 7e394a8d8b..4f67a0e45f 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts @@ -34,6 +34,7 @@ export function createPublishAzureAction(options: { description?: string; defaultBranch?: string; sourcePath?: string; + token?: string; }>({ id: 'publish:azure', description: @@ -57,10 +58,16 @@ export function createPublishAzureAction(options: { description: `Sets the default branch on the repository. The default value is 'master'`, }, sourcePath: { - title: + title: 'Source Path', + description: 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.', type: 'string', }, + token: { + title: 'Authentication Token', + type: 'string', + description: 'The token to use for authorization to Azure', + }, }, }, output: { @@ -98,12 +105,13 @@ export function createPublishAzureAction(options: { `No matching integration configuration for host ${host}, please check your integrations config`, ); } - if (!integrationConfig.config.token) { + + if (!integrationConfig.config.token && !ctx.input.token) { throw new InputError(`No token provided for Azure Integration ${host}`); } - const authHandler = getPersonalAccessTokenHandler( - integrationConfig.config.token, - ); + + const token = ctx.input.token ?? integrationConfig.config.token!; + const authHandler = getPersonalAccessTokenHandler(token); const webApi = new WebApi(`https://${host}/${organization}`, authHandler); const client = await webApi.getGitApi(); @@ -139,7 +147,7 @@ export function createPublishAzureAction(options: { defaultBranch, auth: { username: 'notempty', - password: integrationConfig.config.token, + password: token, }, logger: ctx.logger, commitMessage: config.getOptionalString( diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts index 2678abd9dd..3d14710f3e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts @@ -194,6 +194,45 @@ describe('publish:bitbucket', () => { }); }); + it('should work if the token is provided through ctx.input', async () => { + expect.assertions(2); + server.use( + rest.post( + 'https://notoken.bitbucket.com/rest/api/1.0/projects/project/repos', + (req, res, ctx) => { + expect(req.headers.get('Authorization')).toBe('Bearer lols'); + expect(req.body).toEqual({ public: false, name: 'repo' }); + return res( + ctx.status(201), + ctx.set('Content-Type', 'application/json'), + ctx.json({ + links: { + self: [ + { + href: 'https://bitbucket.mycompany.com/projects/project/repos/repo', + }, + ], + clone: [ + { + name: 'http', + href: 'https://bitbucket.mycompany.com/scm/project/repo', + }, + ], + }, + }), + ); + }, + ), + ); + await action.handler({ + ...mockContext, + input: { + repoUrl: 'notoken.bitbucket.com?project=project&repo=repo', + token: 'lols', + }, + }); + }); + describe('LFS for hosted bitbucket', () => { const repoCreationResponse = { links: { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts index fbfe87b076..8ba8592642 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts @@ -205,6 +205,7 @@ export function createPublishBitbucketAction(options: { repoVisibility: 'private' | 'public'; sourcePath?: string; enableLFS: boolean; + token?: string; }>({ id: 'publish:bitbucket', description: @@ -233,15 +234,22 @@ export function createPublishBitbucketAction(options: { description: `Sets the default branch on the repository. The default value is 'master'`, }, sourcePath: { - title: + title: 'Source Path', + description: 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.', type: 'string', }, enableLFS: { - title: + title: 'Enable LFS?', + description: 'Enable LFS for the repository. Only available for hosted Bitbucket.', type: 'boolean', }, + token: { + title: 'Authentication Token', + type: 'string', + description: 'The token to use for authorization to BitBucket', + }, }, }, output: { @@ -296,7 +304,12 @@ export function createPublishBitbucketAction(options: { ); } - const authorization = getAuthorizationHeader(integrationConfig.config); + const authorization = getAuthorizationHeader( + ctx.input.token + ? { host: integrationConfig.config.host, token: ctx.input.token } + : integrationConfig.config, + ); + const apiBaseUrl = integrationConfig.config.apiBaseUrl; const createMethod = @@ -320,17 +333,28 @@ export function createPublishBitbucketAction(options: { email: config.getOptionalString('scaffolder.defaultAuthor.email'), }; - await initRepoAndPush({ - dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath), - remoteUrl, - auth: { + let auth; + + if (ctx.input.token) { + auth = { + username: 'x-token-auth', + password: ctx.input.token, + }; + } else { + auth = { username: integrationConfig.config.username ? integrationConfig.config.username : 'x-token-auth', password: integrationConfig.config.appPassword ? integrationConfig.config.appPassword : integrationConfig.config.token ?? '', - }, + }; + } + + await initRepoAndPush({ + dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath), + remoteUrl, + auth, defaultBranch, logger: ctx.logger, commitMessage: config.getOptionalString( diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts index 081f9616ac..139fad04d4 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts @@ -52,6 +52,7 @@ export function createPublishGithubAction(options: { requireCodeOwnerReviews?: boolean; repoVisibility: 'private' | 'internal' | 'public'; collaborators: Collaborator[]; + token?: string; topics?: string[]; }>({ id: 'publish:github', @@ -77,7 +78,8 @@ export function createPublishGithubAction(options: { type: 'string', }, requireCodeOwnerReviews: { - title: + title: 'Require CODEOWNER Reviews?', + description: 'Require an approved review in PR including files with a designated Code Owner', type: 'boolean', }, @@ -92,7 +94,8 @@ export function createPublishGithubAction(options: { description: `Sets the default branch on the repository. The default value is 'master'`, }, sourcePath: { - title: + title: 'Source Path', + description: 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.', type: 'string', }, @@ -116,6 +119,11 @@ export function createPublishGithubAction(options: { }, }, }, + token: { + title: 'Authentication Token', + type: 'string', + description: 'The token to use for authorization to GitHub', + }, topics: { title: 'Topics', type: 'array', @@ -149,10 +157,12 @@ export function createPublishGithubAction(options: { defaultBranch = 'master', collaborators, topics, + token: providedToken, } = ctx.input; const { client, token, owner, repo } = await octokitProvider.getOctokit( repoUrl, + { token: providedToken }, ); const user = await client.rest.users.getByUsername({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts index 841d4c7a82..80333c4966 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts @@ -55,6 +55,7 @@ export type GithubPullRequestActionInput = { repoUrl: string; targetPath?: string; sourcePath?: string; + token?: string; }; export type ClientFactoryInput = { @@ -63,6 +64,7 @@ export type ClientFactoryInput = { host: string; owner: string; repo: string; + token?: string; }; export const defaultClientFactory = async ({ @@ -71,13 +73,22 @@ export const defaultClientFactory = async ({ owner, repo, host = 'github.com', + token: providedToken, }: ClientFactoryInput): Promise => { const integrationConfig = integrations.github.byHost(host)?.config; + const OctokitPR = Octokit.plugin(createPullRequest); if (!integrationConfig) { throw new InputError(`No integration for host ${host}`); } + if (providedToken) { + return new OctokitPR({ + auth: providedToken, + baseUrl: integrationConfig.apiBaseUrl, + }); + } + const credentialsProvider = githubCredentialsProvider || SingleInstanceGithubCredentialsProvider.create(integrationConfig); @@ -94,8 +105,6 @@ export const defaultClientFactory = async ({ ); } - const OctokitPR = Octokit.plugin(createPullRequest); - return new OctokitPR({ auth: token, baseUrl: integrationConfig.apiBaseUrl, @@ -151,6 +160,11 @@ export const createPublishGithubPullRequestAction = ({ title: 'Repository Subdirectory', description: 'Subdirectory of repository to apply changes to', }, + token: { + title: 'Authentication Token', + type: 'string', + description: 'The token to use for authorization to GitHub', + }, }, }, output: { @@ -173,6 +187,7 @@ export const createPublishGithubPullRequestAction = ({ description, targetPath, sourcePath, + token: providedToken, } = ctx.input; const { owner, repo, host } = parseRepoUrl(repoUrl, integrations); @@ -189,7 +204,9 @@ export const createPublishGithubPullRequestAction = ({ host, owner, repo, + token: providedToken, }); + const fileRoot = sourcePath ? resolveSafeChildPath(ctx.workspacePath, sourcePath) : ctx.workspacePath; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts index 2cd27da359..a32fea8830 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts @@ -96,6 +96,28 @@ describe('publish:gitlab', () => { ).rejects.toThrow(/No token available for host/); }); + it('should work when there is a token provided through ctx.input', async () => { + mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 }); + mockGitlabClient.Projects.create.mockResolvedValue({ + http_url_to_repo: 'http://mockurl.git', + }); + + await action.handler({ + ...mockContext, + input: { + repoUrl: 'hosted.gitlab.com?repo=bob&owner=owner', + token: 'token', + }, + }); + + expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner'); + expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({ + namespace_id: 1234, + name: 'bob', + visibility: 'private', + }); + }); + it('should call the correct Gitlab APIs when the owner is an organization', async () => { mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 }); mockGitlabClient.Projects.create.mockResolvedValue({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index 5941f52746..a04766f941 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -33,6 +33,7 @@ export function createPublishGitlabAction(options: { defaultBranch?: string; repoVisibility: 'private' | 'internal' | 'public'; sourcePath?: string; + token?: string; }>({ id: 'publish:gitlab', description: @@ -57,10 +58,16 @@ export function createPublishGitlabAction(options: { description: `Sets the default branch on the repository. The default value is 'master'`, }, sourcePath: { - title: + title: 'Source Path', + description: 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.', type: 'string', }, + token: { + title: 'Authentication Token', + type: 'string', + description: 'The token to use for authorization to GitLab', + }, }, }, output: { @@ -100,13 +107,15 @@ export function createPublishGitlabAction(options: { ); } - if (!integrationConfig.config.token) { + if (!integrationConfig.config.token && !ctx.input.token) { throw new InputError(`No token available for host ${host}`); } + const token = ctx.input.token || integrationConfig.config.token!; + const client = new Gitlab({ host: integrationConfig.config.baseUrl, - token: integrationConfig.config.token, + token, }); let { id: targetNamespace } = (await client.Namespaces.show(owner)) as { @@ -140,7 +149,7 @@ export function createPublishGitlabAction(options: { defaultBranch, auth: { username: 'oauth2', - password: integrationConfig.config.token, + password: token, }, logger: ctx.logger, commitMessage: config.getOptionalString( diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts index 2ac369249b..281b72789f 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts @@ -31,6 +31,7 @@ export type GitlabMergeRequestActionInput = { description: string; branchName: string; targetPath: string; + token?: string; }; export const createPublishGitlabMergeRequestAction = (options: { @@ -75,6 +76,11 @@ export const createPublishGitlabMergeRequestAction = (options: { title: 'Repository Subdirectory', description: 'Subdirectory of repository to apply changes to', }, + token: { + title: 'Authentication Token', + type: 'string', + description: 'The token to use for authorization to GitLab', + }, }, }, output: { @@ -107,13 +113,15 @@ export const createPublishGitlabMergeRequestAction = (options: { ); } - if (!integrationConfig.config.token) { + if (!integrationConfig.config.token && !ctx.input.token) { throw new InputError(`No token available for host ${host}`); } + const token = ctx.input.token ?? integrationConfig.config.token!; + const api = new Gitlab({ host: integrationConfig.config.baseUrl, - token: integrationConfig.config.token, + token, }); const fileRoot = ctx.workspacePath; diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts index 161d5b865b..2fc6b99406 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts @@ -497,6 +497,60 @@ describe('DefaultWorkflowRunner', () => { expect.objectContaining({ secrets: { foo: 'bar' } }), ); }); + + it('should be able to template secrets into the input of an action', async () => { + const task = createMockTaskWithSpec( + { + apiVersion: 'scaffolder.backstage.io/v1beta3', + steps: [ + { + id: 'test', + name: 'name', + action: 'jest-mock-action', + input: { + b: '${{ secrets.foo }}', + }, + }, + ], + output: {}, + parameters: {}, + }, + { foo: 'bar' }, + ); + + await runner.execute(task); + + expect(fakeActionHandler).toHaveBeenCalledWith( + expect.objectContaining({ input: { b: 'bar' } }), + ); + }); + + it('does not allow templating of secrets as an output', async () => { + const task = createMockTaskWithSpec( + { + apiVersion: 'scaffolder.backstage.io/v1beta3', + steps: [ + { + id: 'test', + name: 'name', + action: 'jest-mock-action', + input: { + b: '${{ secrets.foo }}', + }, + }, + ], + output: { + b: '${{ secrets.foo }}', + }, + parameters: {}, + }, + { foo: 'bar' }, + ); + + const executedTask = await runner.execute(task); + + expect(executedTask.output.b).toBeUndefined(); + }); }); describe('filters', () => { diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index 5089998834..889e94d000 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -53,6 +53,7 @@ type TemplateContext = { steps: { [stepName: string]: { output: { [outputName: string]: JsonValue } }; }; + secrets?: Record; }; const isValidTaskSpec = (taskSpec: TaskSpec): taskSpec is TaskSpecV1beta3 => { @@ -231,8 +232,14 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { const action = this.options.actionRegistry.get(step.action); const { taskLogger, streamLogger } = createStepLogger({ task, step }); + // Secrets are only passed when templating the input to actions for security reasons const input = - (step.input && this.render(step.input, context, renderTemplate)) ?? + (step.input && + this.render( + step.input, + { ...context, secrets: task.secrets ?? {} }, + renderTemplate, + )) ?? {}; if (action.schema?.input) { diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index eb46870e2b..dfbe114f82 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-scaffolder +## 0.12.1 + +### Patch Changes + +- ba59832aed: Permission the Register Existing Component button +- cee44ad289: Added the ability to collect users `oauth` token from the `RepoUrlPicker` for use in the template manifest +- a681cb9c2f: Make linkTarget configurable for MarkdownContent component +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + - @backstage/plugin-catalog-common@0.1.2 + - @backstage/integration-react@0.1.20 + +## 0.12.1-next.1 + +### Patch Changes + +- ba59832aed: Permission the Register Existing Component button +- Updated dependencies + - @backstage/core-components@0.8.7-next.1 + - @backstage/plugin-catalog-react@0.6.13-next.1 + - @backstage/plugin-catalog-common@0.1.2-next.0 + ## 0.12.1-next.0 ### Patch Changes diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index b77fb5f939..80b5faf201 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -164,6 +164,16 @@ export interface RepoUrlPickerUiOptions { allowedHosts?: string[]; // (undocumented) allowedOwners?: string[]; + // (undocumented) + requestUserCredentials?: { + secretsKey: string; + additionalScopes?: { + github?: string[]; + gitlab?: string[]; + bitbucket?: string[]; + azure?: string[]; + }; + }; } // @public @@ -317,4 +327,9 @@ export const TextValuePicker: ({ idSchema, placeholder, }: FieldProps) => JSX.Element; + +// @public +export const useTemplateSecrets: () => { + setSecret: (input: Record) => void; +}; ``` diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index a85d13f56e..60852e3b93 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": "0.12.1-next.0", + "version": "0.12.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,13 +34,13 @@ "@backstage/catalog-client": "^0.5.5", "@backstage/catalog-model": "^0.9.10", "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/errors": "^0.2.0", "@backstage/integration": "^0.7.2", - "@backstage/integration-react": "^0.1.20-next.0", - "@backstage/plugin-catalog-common": "^0.1.1", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/integration-react": "^0.1.20", + "@backstage/plugin-catalog-common": "^0.1.2", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/plugin-permission-react": "^0.3.0", "@backstage/plugin-scaffolder-common": "^0.1.3", "@backstage/theme": "^0.2.14", @@ -69,11 +69,11 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/plugin-catalog": "^0.7.11-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/plugin-catalog": "^0.7.11", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/scaffolder/src/components/Router.tsx b/plugins/scaffolder/src/components/Router.tsx index e667c676f2..ab79f9dec3 100644 --- a/plugins/scaffolder/src/components/Router.tsx +++ b/plugins/scaffolder/src/components/Router.tsx @@ -21,6 +21,7 @@ import { ScaffolderPage } from './ScaffolderPage'; import { TemplatePage } from './TemplatePage'; import { TaskPage } from './TaskPage'; import { ActionsPage } from './ActionsPage'; +import { SecretsContextProvider } from './secrets/SecretsContext'; import { FieldExtensionOptions, @@ -77,7 +78,11 @@ export const Router = ({ TemplateCardComponent, groups }: RouterProps) => { /> } + element={ + + + + } /> } /> } /> diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx index 8ce7ecf6b3..852ae3d81c 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx @@ -17,12 +17,13 @@ import { JsonObject, JsonValue } from '@backstage/types'; import { LinearProgress } from '@material-ui/core'; import { FormValidation, IChangeEvent } from '@rjsf/core'; import qs from 'qs'; -import React, { useCallback, useState } from 'react'; +import React, { useCallback, useContext, useState } from 'react'; import { generatePath, Navigate, useNavigate } from 'react-router'; import { useParams } from 'react-router-dom'; import useAsync from 'react-use/lib/useAsync'; import { scaffolderApiRef } from '../../api'; import { CustomFieldValidator, FieldExtensionOptions } from '../../extensions'; +import { SecretsContext } from '../secrets/SecretsContext'; import { rootRouteRef } from '../../routes'; import { MultistepJsonForm } from '../MultistepJsonForm'; @@ -115,6 +116,7 @@ export const TemplatePage = ({ customFieldExtensions?: FieldExtensionOptions[]; }) => { const apiHolder = useApiHolder(); + const secretsContext = useContext(SecretsContext); const errorApi = useApi(errorApiRef); const scaffolderApi = useApi(scaffolderApiRef); const { templateName } = useParams(); @@ -135,7 +137,11 @@ export const TemplatePage = ({ ); const handleCreate = async () => { - const id = await scaffolderApi.scaffold(templateName, formState); + const id = await scaffolderApi.scaffold( + templateName, + formState, + secretsContext?.secrets, + ); const formParams = qs.stringify( { formData: formState }, diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx new file mode 100644 index 0000000000..829495cdda --- /dev/null +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx @@ -0,0 +1,177 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React, { useContext } from 'react'; +import { RepoUrlPicker } from './RepoUrlPicker'; +import Form from '@rjsf/core'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { + scmIntegrationsApiRef, + ScmIntegrationsApi, + scmAuthApiRef, + ScmAuthApi, +} from '@backstage/integration-react'; +import { scaffolderApiRef, ScaffolderApi } from '../../../api'; +import { + SecretsContextProvider, + SecretsContext, +} from '../../secrets/SecretsContext'; +import { act, fireEvent } from '@testing-library/react'; + +describe('RepoUrlPicker', () => { + const mockScaffolderApi: Partial = { + getIntegrationsList: async () => [ + { host: 'github.com', type: 'github', title: 'github.com' }, + { host: 'dev.azure.com', type: 'azure', title: 'dev.azure.com' }, + ], + }; + + const mockIntegrationsApi: Partial = { + byHost: () => ({ type: 'github' }), + }; + + const mockScmAuthApi: Partial = { + getCredentials: jest.fn().mockResolvedValue({ token: 'abc123' }), + }; + + describe('happy path rendering', () => { + it('should render the repo url picker with minimal props', async () => { + const onSubmit = jest.fn(); + const { getAllByRole, getByRole } = await renderInTestApp( + + +
+ + , + ); + + const [ownerInput, repoInput] = getAllByRole('textbox'); + const submitButton = getByRole('button'); + + fireEvent.change(ownerInput, { target: { value: 'backstage' } }); + fireEvent.change(repoInput, { target: { value: 'repo123' } }); + + fireEvent.click(submitButton); + + expect(onSubmit).toHaveBeenCalledWith( + expect.objectContaining({ + formData: 'github.com?owner=backstage&repo=repo123', + }), + expect.anything(), + ); + }); + + it('should render properly with allowedHosts', async () => { + const { getByRole } = await renderInTestApp( + + + + + , + ); + + expect( + getByRole('option', { name: 'dev.azure.com' }), + ).toBeInTheDocument(); + }); + }); + + describe('requestUserCredentials', () => { + it('should call the scmAuthApi with the correct params', async () => { + const SecretsComponent = () => { + const value = useContext(SecretsContext); + return
{JSON.stringify(value)}
; + }; + const { getAllByRole, getByTestId } = await renderInTestApp( + + + + + + , + ); + + const [ownerInput, repoInput] = getAllByRole('textbox'); + + await act(async () => { + fireEvent.change(ownerInput, { target: { value: 'backstage' } }); + fireEvent.change(repoInput, { target: { value: 'repo123' } }); + + // need to wait for the debounce to finish + await new Promise(resolve => setTimeout(resolve, 600)); + }); + + expect(mockScmAuthApi.getCredentials).toHaveBeenCalledWith({ + url: 'https://github.com/backstage/repo123', + additionalScope: { + repoWrite: true, + customScopes: { + github: ['workflow:write'], + }, + }, + }); + + const currentSecrets = JSON.parse( + getByTestId('current-secrets').textContent!, + ); + + expect(currentSecrets).toEqual({ + secrets: { testKey: 'abc123' }, + }); + }); + }); +}); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx index 998fa41588..1ccaed4e86 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx @@ -14,7 +14,10 @@ * limitations under the License. */ import { useApi } from '@backstage/core-plugin-api'; -import { scmIntegrationsApiRef } from '@backstage/integration-react'; +import { + scmIntegrationsApiRef, + scmAuthApiRef, +} from '@backstage/integration-react'; import React, { useEffect, useState, useMemo, useCallback } from 'react'; import { GithubRepoPicker } from './GithubRepoPicker'; import { GitlabRepoPicker } from './GitlabRepoPicker'; @@ -24,10 +27,21 @@ import { FieldExtensionComponentProps } from '../../../extensions'; import { RepoUrlPickerHost } from './RepoUrlPickerHost'; import { parseRepoPickerUrl, serializeRepoPickerUrl } from './utils'; import { RepoUrlPickerState } from './types'; +import useDebounce from 'react-use/lib/useDebounce'; +import { useTemplateSecrets } from '../../secrets'; export interface RepoUrlPickerUiOptions { allowedHosts?: string[]; allowedOwners?: string[]; + requestUserCredentials?: { + secretsKey: string; + additionalScopes?: { + github?: string[]; + gitlab?: string[]; + bitbucket?: string[]; + azure?: string[]; + }; + }; } export const RepoUrlPicker = ( @@ -38,7 +52,8 @@ export const RepoUrlPicker = ( parseRepoPickerUrl(formData), ); const integrationApi = useApi(scmIntegrationsApiRef); - + const scmAuthApi = useApi(scmAuthApiRef); + const { setSecret } = useTemplateSecrets(); const allowedHosts = useMemo( () => uiSchema?.['ui:options']?.allowedHosts ?? [], [uiSchema], @@ -66,6 +81,42 @@ export const RepoUrlPicker = ( [setState], ); + useDebounce( + async () => { + const { requestUserCredentials } = uiSchema?.['ui:options'] ?? {}; + + if ( + !requestUserCredentials || + !(state.host && state.owner && state.repoName) + ) { + return; + } + + const [host, owner, repoName] = [ + state.host, + state.owner, + state.repoName, + ].map(encodeURIComponent); + + // user has requested that we use the users credentials + // so lets grab them using the scmAuthApi and pass through + // any additional scopes from the ui:options + const { token } = await scmAuthApi.getCredentials({ + url: `https://${host}/${owner}/${repoName}`, + additionalScope: { + repoWrite: true, + customScopes: requestUserCredentials.additionalScopes, + }, + }); + + // set the secret using the key provided in the the ui:options for use + // in the templating the manifest with ${{ secrets[secretsKey] }} + setSecret({ [requestUserCredentials.secretsKey]: token }); + }, + 500, + [state, uiSchema], + ); + const hostType = (state.host && integrationApi.byHost(state.host)?.type) ?? null; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx index 261429c757..ec09494a1b 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx @@ -37,16 +37,23 @@ export const RepoUrlPickerHost = (props: { }); useEffect(() => { - if (hosts && !host) { - // This is only hear to set the default as the first one in the hosts array - // if the host is not set yet and there is a list of hosts. - onChange(hosts[0]); + // If there is no host chosen currently + if (!host) { + // Set the first of the allowedHosts option if that available + if (hosts?.length) { + onChange(hosts[0]); + // if there's no hosts provided, fallback to using the first integration + } else if (integrations?.length) { + onChange(integrations[0].host); + } } - }, [hosts, host, onChange]); + }, [hosts, host, onChange, integrations]); + // If there are no allowedHosts provided, then show all integrations. Otherwise, only show integrations + // that are provided in the dropdown for the user to choose from. const hostsOptions: SelectItem[] = integrations ? integrations - .filter(i => hosts?.includes(i.host)) + .filter(i => (hosts?.length ? hosts?.includes(i.host) : true)) .map(i => ({ label: i.title, value: i.host })) : [{ label: 'Loading...', value: 'loading' }]; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/utils.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/utils.ts index d1f2302d3e..2f17f0aef7 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/utils.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/utils.ts @@ -44,22 +44,22 @@ export function serializeRepoPickerUrl(data: RepoUrlPickerState) { export function parseRepoPickerUrl( url: string | undefined, ): RepoUrlPickerState { - let host = undefined; - let owner = undefined; - let repoName = undefined; - let organization = undefined; - let workspace = undefined; - let project = undefined; + let host = ''; + let owner = ''; + let repoName = ''; + let organization = ''; + let workspace = ''; + let project = ''; try { if (url) { const parsed = new URL(`https://${url}`); host = parsed.host; - owner = parsed.searchParams.get('owner') || undefined; - repoName = parsed.searchParams.get('repo') || undefined; - organization = parsed.searchParams.get('organization') || undefined; - workspace = parsed.searchParams.get('workspace') || undefined; - project = parsed.searchParams.get('project') || undefined; + owner = parsed.searchParams.get('owner') || ''; + repoName = parsed.searchParams.get('repo') || ''; + organization = parsed.searchParams.get('organization') || ''; + workspace = parsed.searchParams.get('workspace') || ''; + project = parsed.searchParams.get('project') || ''; } } catch { /* ok */ diff --git a/plugins/scaffolder/src/components/secrets/SecretsContext.test.tsx b/plugins/scaffolder/src/components/secrets/SecretsContext.test.tsx new file mode 100644 index 0000000000..37d35c9015 --- /dev/null +++ b/plugins/scaffolder/src/components/secrets/SecretsContext.test.tsx @@ -0,0 +1,43 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React, { useContext } from 'react'; +import { + useTemplateSecrets, + SecretsContextProvider, + SecretsContext, +} from './SecretsContext'; +import { renderHook, act } from '@testing-library/react-hooks'; + +describe('SecretsContext', () => { + it('should allow the setting of secrets in the context', async () => { + const { result } = renderHook( + () => ({ + hook: useTemplateSecrets(), + context: useContext(SecretsContext), + }), + { + wrapper: ({ children }) => ( + {children} + ), + }, + ); + expect(result.current.context?.secrets.foo).toEqual(undefined); + + act(() => result.current.hook.setSecret({ foo: 'bar' })); + + expect(result.current.context?.secrets.foo).toEqual('bar'); + }); +}); diff --git a/plugins/scaffolder/src/components/secrets/SecretsContext.tsx b/plugins/scaffolder/src/components/secrets/SecretsContext.tsx new file mode 100644 index 0000000000..6570f9d901 --- /dev/null +++ b/plugins/scaffolder/src/components/secrets/SecretsContext.tsx @@ -0,0 +1,73 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React, { + useState, + useCallback, + useContext, + createContext, + PropsWithChildren, +} from 'react'; + +type SecretsContextContents = { + secrets: Record; + setSecrets: React.Dispatch>>; +}; + +/** + * The actual context object. + */ +export const SecretsContext = createContext( + undefined, +); + +/** + * The Context Provider that holds the state for the secrets. + * + * @public + */ +export const SecretsContextProvider = ({ children }: PropsWithChildren<{}>) => { + const [secrets, setSecrets] = useState>({}); + + return ( + + {children} + + ); +}; + +/** + * Hook to access the secrets context. + * @public + */ +export const useTemplateSecrets = () => { + const value = useContext(SecretsContext); + if (!value) { + throw new Error( + 'useTemplateSecrets must be used within a SecretsContextProvider', + ); + } + + const { setSecrets } = value; + + const setSecret = useCallback( + (input: Record) => { + setSecrets(currentSecrets => ({ ...currentSecrets, ...input })); + }, + [setSecrets], + ); + + return { setSecret }; +}; diff --git a/plugins/scaffolder/src/components/secrets/index.ts b/plugins/scaffolder/src/components/secrets/index.ts new file mode 100644 index 0000000000..44adb2a00a --- /dev/null +++ b/plugins/scaffolder/src/components/secrets/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { useTemplateSecrets } from './SecretsContext'; diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index 3cf65d7a07..133234e20b 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -56,3 +56,4 @@ export { FavouriteTemplate } from './components/FavouriteTemplate'; export { TemplateList } from './components/TemplateList'; export type { TemplateListProps } from './components/TemplateList'; export { TemplateTypePicker } from './components/TemplateTypePicker'; +export * from './components/secrets'; diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index 714235c947..79408a2e69 100644 --- a/plugins/search-backend-module-elasticsearch/package.json +++ b/plugins/search-backend-module-elasticsearch/package.json @@ -30,8 +30,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-common": "^0.10.5", - "@backstage/cli": "^0.13.1-next.0", + "@backstage/backend-common": "^0.10.6-next.0", + "@backstage/cli": "^0.13.1-next.1", "@elastic/elasticsearch-mock": "^0.3.0" }, "files": [ diff --git a/plugins/search-backend-module-pg/CHANGELOG.md b/plugins/search-backend-module-pg/CHANGELOG.md index 8abeaa10e8..245a4ded3f 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.2.5 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6 + +## 0.2.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + ## 0.2.4 ### Patch Changes diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index 0fa4ca3f8d..51a7933ae3 100644 --- a/plugins/search-backend-module-pg/package.json +++ b/plugins/search-backend-module-pg/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-pg", "description": "A module for the search backend that implements search using PostgreSQL", - "version": "0.2.4", + "version": "0.2.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,15 +20,15 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/search-common": "^0.2.2", "@backstage/plugin-search-backend-node": "^0.4.5", "lodash": "^4.17.21", "knex": "^0.95.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.16-next.0", - "@backstage/cli": "^0.13.1-next.0" + "@backstage/backend-test-utils": "^0.1.16", + "@backstage/cli": "^0.13.1" }, "files": [ "dist", diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index ee65c5528e..fb72994de5 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -26,8 +26,8 @@ "@types/lunr": "^2.3.3" }, "devDependencies": { - "@backstage/backend-common": "^0.10.5", - "@backstage/cli": "^0.13.1-next.0" + "@backstage/backend-common": "^0.10.6-next.0", + "@backstage/cli": "^0.13.1-next.1" }, "files": [ "dist" diff --git a/plugins/search-backend/CHANGELOG.md b/plugins/search-backend/CHANGELOG.md index 342d56af32..46daea6df6 100644 --- a/plugins/search-backend/CHANGELOG.md +++ b/plugins/search-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-search-backend +## 0.4.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-backend@0.9.0 + - @backstage/backend-common@0.10.6 + - @backstage/plugin-permission-node@0.4.2 + +## 0.4.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-backend@0.9.0-next.1 + - @backstage/backend-common@0.10.6-next.0 + - @backstage/plugin-permission-node@0.4.2-next.1 + ## 0.4.1-next.0 ### Patch Changes diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index 02093f07d6..3329115650 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": "0.4.1-next.0", + "version": "0.4.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,13 +20,13 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/config": "^0.1.13", "@backstage/errors": "^0.2.0", "@backstage/search-common": "^0.2.2", - "@backstage/plugin-auth-backend": "^0.9.0-next.0", + "@backstage/plugin-auth-backend": "^0.9.0", "@backstage/plugin-permission-common": "^0.4.0-next.0", - "@backstage/plugin-permission-node": "^0.4.2-next.0", + "@backstage/plugin-permission-node": "^0.4.2", "@backstage/plugin-search-backend-node": "^0.4.5", "@backstage/types": "^0.1.1", "@types/express": "^4.17.6", @@ -40,7 +40,7 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index 5abfb45f0b..f6692413b4 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-search +## 0.6.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + ## 0.6.1-next.0 ### Patch Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index 5c66dab402..6536c9c386 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search", "description": "The Backstage plugin that provides your backstage app with search", - "version": "0.6.1-next.0", + "version": "0.6.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,10 +32,10 @@ "dependencies": { "@backstage/catalog-model": "^0.9.10", "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/errors": "^0.2.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/search-common": "^0.2.2", "@backstage/theme": "^0.2.14", "@backstage/types": "^0.1.1", @@ -52,10 +52,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index ae94faaa19..acccd2dc4c 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-sentry +## 0.3.35 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + ## 0.3.35-next.0 ### Patch Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index 8f7e487f1c..274cc6e1e2 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sentry", "description": "A Backstage plugin that integrates towards Sentry", - "version": "0.3.35-next.0", + "version": "0.3.35", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,9 +33,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -49,10 +49,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/shortcuts/CHANGELOG.md b/plugins/shortcuts/CHANGELOG.md index 0d382afeb3..60c0b9fe84 100644 --- a/plugins/shortcuts/CHANGELOG.md +++ b/plugins/shortcuts/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-shortcuts +## 0.1.21 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + ## 0.1.21-next.0 ### Patch Changes diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index 0ea2c6d367..23e61cda42 100644 --- a/plugins/shortcuts/package.json +++ b/plugins/shortcuts/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-shortcuts", "description": "A Backstage plugin that provides a shortcuts feature to the sidebar", - "version": "0.1.21-next.0", + "version": "0.1.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,7 +21,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/theme": "^0.2.14", "@backstage/types": "^0.1.1", @@ -39,10 +39,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index 116c26a30e..7cbabeda41 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-sonarqube +## 0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + ## 0.2.15-next.0 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index d249074eb1..4d6d83a67a 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sonarqube", "description": "", - "version": "0.2.15-next.0", + "version": "0.2.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,9 +34,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -50,10 +50,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/splunk-on-call/CHANGELOG.md b/plugins/splunk-on-call/CHANGELOG.md index dfde9b7013..90ff0a5bd1 100644 --- a/plugins/splunk-on-call/CHANGELOG.md +++ b/plugins/splunk-on-call/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-splunk-on-call +## 0.3.21 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + ## 0.3.21-next.0 ### Patch Changes diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index 557d486ab2..f3de0d3602 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-splunk-on-call", "description": "A Backstage plugin that integrates towards Splunk On-Call", - "version": "0.3.21-next.0", + "version": "0.3.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,9 +32,9 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -48,10 +48,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/splunk-on-call/src/components/Incident/IncidentListItem.tsx b/plugins/splunk-on-call/src/components/Incident/IncidentListItem.tsx index 570b47483f..4c9975bd06 100644 --- a/plugins/splunk-on-call/src/components/Incident/IncidentListItem.tsx +++ b/plugins/splunk-on-call/src/components/Incident/IncidentListItem.tsx @@ -106,7 +106,7 @@ const IncidentAction = ({ switch (currentPhase) { case 'UNACKED': return ( - + acknowledgeAction({ incidentId, incidentType: 'ACKNOWLEDGEMENT' }) diff --git a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md index 9346b5c402..d136927b9b 100644 --- a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md +++ b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-tech-insights-backend-module-jsonfc +## 0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6 + - @backstage/plugin-tech-insights-node@0.2.1 + +## 0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + - @backstage/plugin-tech-insights-node@0.2.1-next.0 + ## 0.1.6 ### Patch Changes diff --git a/plugins/tech-insights-backend-module-jsonfc/package.json b/plugins/tech-insights-backend-module-jsonfc/package.json index d9ca5449f5..77ce4b3268 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.6", + "version": "0.1.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,11 +31,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/config": "^0.1.13", "@backstage/errors": "^0.2.0", "@backstage/plugin-tech-insights-common": "^0.2.1", - "@backstage/plugin-tech-insights-node": "^0.2.0", + "@backstage/plugin-tech-insights-node": "^0.2.1", "ajv": "^7.0.3", "json-rules-engine": "^6.1.2", "lodash": "^4.17.21", @@ -43,7 +43,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@types/node-cron": "^3.0.1" }, "files": [ diff --git a/plugins/tech-insights-backend/CHANGELOG.md b/plugins/tech-insights-backend/CHANGELOG.md index 7cf31f5b61..a9032f9c98 100644 --- a/plugins/tech-insights-backend/CHANGELOG.md +++ b/plugins/tech-insights-backend/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-tech-insights-backend +## 0.2.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6 + - @backstage/plugin-tech-insights-node@0.2.1 + +## 0.2.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + - @backstage/plugin-tech-insights-node@0.2.1-next.0 + ## 0.2.2 ### Patch Changes diff --git a/plugins/tech-insights-backend/package.json b/plugins/tech-insights-backend/package.json index 80620bd016..d63bb60499 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.2.2", + "version": "0.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,13 +31,13 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/catalog-client": "^0.5.5", "@backstage/catalog-model": "^0.9.10", "@backstage/config": "^0.1.13", "@backstage/errors": "^0.2.0", "@backstage/plugin-tech-insights-common": "^0.2.1", - "@backstage/plugin-tech-insights-node": "^0.2.0", + "@backstage/plugin-tech-insights-node": "^0.2.1", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -51,8 +51,8 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.16-next.0", - "@backstage/cli": "^0.13.1-next.0", + "@backstage/backend-test-utils": "^0.1.16", + "@backstage/cli": "^0.13.1", "@types/supertest": "^2.0.8", "@types/node-cron": "^3.0.0", "@types/semver": "^7.3.8", diff --git a/plugins/tech-insights-node/CHANGELOG.md b/plugins/tech-insights-node/CHANGELOG.md index 502cfdaa9b..4f3ed0d13e 100644 --- a/plugins/tech-insights-node/CHANGELOG.md +++ b/plugins/tech-insights-node/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-tech-insights-node +## 0.2.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6 + +## 0.2.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + ## 0.2.0 ### Minor Changes diff --git a/plugins/tech-insights-node/package.json b/plugins/tech-insights-node/package.json index 405c3cfe03..7ed74ab76d 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.2.0", + "version": "0.2.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,7 +30,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/config": "^0.1.13", "@backstage/plugin-tech-insights-common": "^0.2.1", "@types/luxon": "^2.0.5", @@ -38,7 +38,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0" + "@backstage/cli": "^0.13.1" }, "files": [ "dist" diff --git a/plugins/tech-insights/CHANGELOG.md b/plugins/tech-insights/CHANGELOG.md index 78147429bb..a63a1a8f80 100644 --- a/plugins/tech-insights/CHANGELOG.md +++ b/plugins/tech-insights/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-tech-insights +## 0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + ## 0.1.7-next.0 ### Patch Changes diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index dafbd52ffb..2f0d2f3638 100644 --- a/plugins/tech-insights/package.json +++ b/plugins/tech-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights", - "version": "0.1.7-next.0", + "version": "0.1.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,10 +21,10 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/errors": "^0.2.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/plugin-tech-insights-common": "^0.2.1", "@backstage/theme": "^0.2.14", "@backstage/types": "^0.1.1", @@ -39,10 +39,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/tech-radar/CHANGELOG.md b/plugins/tech-radar/CHANGELOG.md index c224d374f9..b7952b6f12 100644 --- a/plugins/tech-radar/CHANGELOG.md +++ b/plugins/tech-radar/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-tech-radar +## 0.5.4 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + ## 0.5.4-next.0 ### Patch Changes diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index af6390083d..4da9252c6a 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-tech-radar", "description": "A Backstage plugin that lets you display a Tech Radar for your organization", - "version": "0.5.4-next.0", + "version": "0.5.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,7 +31,7 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", @@ -46,10 +46,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index 246d612833..4593b8db5b 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-techdocs-backend +## 0.13.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@0.1.2 + - @backstage/backend-common@0.10.6 + - @backstage/techdocs-common@0.11.6 + +## 0.13.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@0.1.2-next.0 + - @backstage/backend-common@0.10.6-next.0 + - @backstage/techdocs-common@0.11.6-next.0 + ## 0.13.1 ### Patch Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index 7e5fb16472..292b70a61d 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-backend", "description": "The Backstage backend plugin that renders technical documentation for your components", - "version": "0.13.1", + "version": "0.13.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,15 +31,15 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/catalog-client": "^0.5.5", "@backstage/catalog-model": "^0.9.10", "@backstage/config": "^0.1.13", "@backstage/errors": "^0.2.0", "@backstage/integration": "^0.7.2", - "@backstage/plugin-catalog-common": "^0.1.1-next.0", + "@backstage/plugin-catalog-common": "^0.1.2", "@backstage/search-common": "^0.2.2", - "@backstage/techdocs-common": "^0.11.5", + "@backstage/techdocs-common": "^0.11.6", "@types/express": "^4.17.6", "cross-fetch": "^3.0.6", "dockerode": "^3.3.1", @@ -53,8 +53,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/test-utils": "^0.2.4", "@types/dockerode": "^3.3.0", "msw": "^0.35.0", "supertest": "^6.1.3" diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 677746ec49..e0547de64e 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-techdocs +## 0.13.2 + +### Patch Changes + +- 742434a6ba: Fixed a bug where links to files within a TechDocs site that use the `download` attribute would result in a 404 in cases where the TechDocs backend and Backstage frontend application are on the same host. +- 359c31e31d: Added support for documentation using the raw `` tag to point to relative resources like audio or video files. +- 18317a08db: Fixed a bug where copy-to-clipboard buttons were appended to unintended elements. +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + - @backstage/integration-react@0.1.20 + - @backstage/plugin-catalog@0.7.11 + - @backstage/plugin-search@0.6.1 + +## 0.13.2-next.1 + +### Patch Changes + +- 742434a6ba: Fixed a bug where links to files within a TechDocs site that use the `download` attribute would result in a 404 in cases where the TechDocs backend and Backstage frontend application are on the same host. +- Updated dependencies + - @backstage/core-components@0.8.7-next.1 + - @backstage/plugin-catalog-react@0.6.13-next.1 + - @backstage/plugin-catalog@0.7.11-next.1 + ## 0.13.2-next.0 ### Patch Changes diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 3585dd4ced..6e571ec5ac 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs", "description": "The Backstage plugin that renders technical documentation for your components", - "version": "0.13.2-next.0", + "version": "0.13.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,14 +34,14 @@ "dependencies": { "@backstage/catalog-model": "^0.9.10", "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/errors": "^0.2.0", "@backstage/integration": "^0.7.2", - "@backstage/integration-react": "^0.1.20-next.0", - "@backstage/plugin-catalog": "^0.7.11-next.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", - "@backstage/plugin-search": "^0.6.1-next.0", + "@backstage/integration-react": "^0.1.20", + "@backstage/plugin-catalog": "^0.7.11", + "@backstage/plugin-catalog-react": "^0.6.13", + "@backstage/plugin-search": "^0.6.1", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -62,10 +62,10 @@ "react-dom": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/techdocs/src/reader/transformers/copyToClipboard.test.ts b/plugins/techdocs/src/reader/transformers/copyToClipboard.test.ts index 679121d9bd..daa074f6e4 100644 --- a/plugins/techdocs/src/reader/transformers/copyToClipboard.test.ts +++ b/plugins/techdocs/src/reader/transformers/copyToClipboard.test.ts @@ -32,7 +32,7 @@ describe('copyToClipboard', () => { - ${expectedClipboard} +
${expectedClipboard}
`, @@ -46,4 +46,25 @@ describe('copyToClipboard', () => { expect(clipboardSpy).toHaveBeenCalledWith(expectedClipboard); }); + + it('only gets applied to code blocks', async () => { + const expectedClipboard = 'function foo() {return "bar";}'; + const shadowDom = await createTestShadowDom( + ` + + + + ${expectedClipboard} + + + `, + { + preTransformers: [], + postTransformers: [copyToClipboard()], + }, + ); + + const copyButton = shadowDom.querySelector('button'); + expect(copyButton).toBe(null); + }); }); diff --git a/plugins/techdocs/src/reader/transformers/copyToClipboard.ts b/plugins/techdocs/src/reader/transformers/copyToClipboard.ts index 24b46c0b85..d0569c0fd9 100644 --- a/plugins/techdocs/src/reader/transformers/copyToClipboard.ts +++ b/plugins/techdocs/src/reader/transformers/copyToClipboard.ts @@ -22,7 +22,7 @@ import type { Transformer } from './transformer'; */ export const copyToClipboard = (): Transformer => { return dom => { - Array.from(dom.querySelectorAll('code')).forEach(codeElem => { + Array.from(dom.querySelectorAll('pre > code')).forEach(codeElem => { const button = document.createElement('button'); const toBeCopied = codeElem.textContent || ''; button.className = 'md-clipboard md-icon'; diff --git a/plugins/todo-backend/CHANGELOG.md b/plugins/todo-backend/CHANGELOG.md index ddbc5d215a..9e2275dc7b 100644 --- a/plugins/todo-backend/CHANGELOG.md +++ b/plugins/todo-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-todo-backend +## 0.1.20 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6 + +## 0.1.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.6-next.0 + ## 0.1.19 ### Patch Changes diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index d90ebb2f08..456600e0be 100644 --- a/plugins/todo-backend/package.json +++ b/plugins/todo-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo-backend", "description": "A Backstage backend plugin that lets you browse TODO comments in your source code", - "version": "0.1.19", + "version": "0.1.20", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -25,7 +25,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.5", + "@backstage/backend-common": "^0.10.6", "@backstage/catalog-client": "^0.5.5", "@backstage/catalog-model": "^0.9.10", "@backstage/config": "^0.1.13", @@ -39,7 +39,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", + "@backstage/cli": "^0.13.1", "@types/supertest": "^2.0.8", "msw": "^0.35.0", "supertest": "^6.1.3" diff --git a/plugins/todo/CHANGELOG.md b/plugins/todo/CHANGELOG.md index 1d5a7b42cc..e659da3131 100644 --- a/plugins/todo/CHANGELOG.md +++ b/plugins/todo/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-todo +## 0.1.21 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + - @backstage/plugin-catalog-react@0.6.13 + ## 0.1.21-next.0 ### Patch Changes diff --git a/plugins/todo/package.json b/plugins/todo/package.json index 254aa4fdb4..fc9893fcd9 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo", "description": "A Backstage plugin that lets you browse TODO comments in your source code", - "version": "0.1.21-next.0", + "version": "0.1.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -28,10 +28,10 @@ }, "dependencies": { "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/errors": "^0.2.0", - "@backstage/plugin-catalog-react": "^0.6.13-next.0", + "@backstage/plugin-catalog-react": "^0.6.13", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -42,10 +42,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index 8abf24f743..b4438be6ce 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-user-settings +## 0.3.18 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + ## 0.3.18-next.0 ### Patch Changes diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index a4d0e4d46f..4506cdfb75 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-user-settings", "description": "A Backstage plugin that provides a settings page", - "version": "0.3.18-next.0", + "version": "0.3.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/theme": "^0.2.14", "@material-ui/core": "^4.12.2", @@ -44,10 +44,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/xcmetrics/CHANGELOG.md b/plugins/xcmetrics/CHANGELOG.md index f2b15f69dd..652dcca6b9 100644 --- a/plugins/xcmetrics/CHANGELOG.md +++ b/plugins/xcmetrics/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-xcmetrics +## 0.2.17 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.7 + ## 0.2.17-next.0 ### Patch Changes diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index 8e77220dc7..7680c787d5 100644 --- a/plugins/xcmetrics/package.json +++ b/plugins/xcmetrics/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-xcmetrics", "description": "A Backstage plugin that shows XCode build metrics for your components", - "version": "0.2.17-next.0", + "version": "0.2.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,7 +21,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.8.7-next.0", + "@backstage/core-components": "^0.8.7", "@backstage/core-plugin-api": "^0.6.0", "@backstage/errors": "^0.2.0", "@backstage/theme": "^0.2.14", @@ -37,10 +37,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.1-next.0", - "@backstage/core-app-api": "^0.5.1", - "@backstage/dev-utils": "^0.2.20-next.0", - "@backstage/test-utils": "^0.2.3", + "@backstage/cli": "^0.13.1", + "@backstage/core-app-api": "^0.5.2", + "@backstage/dev-utils": "^0.2.20", + "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/scripts/api-extractor.ts b/scripts/api-extractor.ts index bfb8b525fc..dfbd91f76b 100644 --- a/scripts/api-extractor.ts +++ b/scripts/api-extractor.ts @@ -193,7 +193,7 @@ const SKIPPED_PACKAGES = [ join('packages', 'codemods'), join('packages', 'create-app'), join('packages', 'e2e-test'), - join('packages', 'embedded-techdocs-app'), + join('packages', 'techdocs-cli-embedded-app'), join('packages', 'storybook'), join('packages', 'techdocs-cli'), ]; diff --git a/scripts/verify-changesets.js b/scripts/verify-changesets.js index 8d828ee058..9e3064eeac 100755 --- a/scripts/verify-changesets.js +++ b/scripts/verify-changesets.js @@ -26,7 +26,7 @@ const privatePackages = new Set([ 'example-backend', 'e2e-test', 'storybook', - 'embedded-techdocs-app', + 'techdocs-cli-embedded-app', ]); async function main() { diff --git a/storybook/package.json b/storybook/package.json index 13c3c310df..3864e04484 100644 --- a/storybook/package.json +++ b/storybook/package.json @@ -15,12 +15,12 @@ "react-dom": "^17.0.2" }, "devDependencies": { - "@storybook/addon-a11y": "^6.4.17", - "@storybook/addon-actions": "^6.4.17", - "@storybook/addon-links": "^6.4.17", - "@storybook/addon-storysource": "^6.4.17", + "@storybook/addon-a11y": "^6.4.18", + "@storybook/addon-actions": "^6.4.18", + "@storybook/addon-links": "^6.4.18", + "@storybook/addon-storysource": "^6.4.18", "@storybook/addons": "^6.4.14", - "@storybook/react": "^6.4.17", + "@storybook/react": "^6.4.18", "storybook-dark-mode": "^1.0.8" }, "peerDependencies": { diff --git a/storybook/yarn.lock b/storybook/yarn.lock index 17c00cb3a7..284ada1cb2 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -1310,19 +1310,19 @@ resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz#830beaec4b4091a9e9398ac50f865ddea52186b9" integrity sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA== -"@storybook/addon-a11y@^6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-6.4.17.tgz#b7efe7f7a52c81392e06efafc34044db784fd3ce" - integrity sha512-uIgl9vJwY4//7i+JEu47Lgi1wOGOskHQ0+H/S8DPGcEMF2xqK/w3BjgSEWa8NPYfYyxkf/yHvCIsa99b/3phUg== +"@storybook/addon-a11y@^6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-6.4.18.tgz#c61f71cd7b17aff408835ee35e29bf4a0716ece7" + integrity sha512-sqsA5pXXKKDsquSXu5KC8WxQ1gg5ZoNIltWRgmJCEt4a0bkGUzn2iz+uW/gbt4NOVWGPXKvmMBLT/q4Q9gb+og== dependencies: - "@storybook/addons" "6.4.17" - "@storybook/api" "6.4.17" - "@storybook/channels" "6.4.17" - "@storybook/client-logger" "6.4.17" - "@storybook/components" "6.4.17" - "@storybook/core-events" "6.4.17" + "@storybook/addons" "6.4.18" + "@storybook/api" "6.4.18" + "@storybook/channels" "6.4.18" + "@storybook/client-logger" "6.4.18" + "@storybook/components" "6.4.18" + "@storybook/core-events" "6.4.18" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/theming" "6.4.17" + "@storybook/theming" "6.4.18" axe-core "^4.2.0" core-js "^3.8.2" global "^4.4.0" @@ -1332,17 +1332,17 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/addon-actions@^6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.4.17.tgz#93a8190b07f776ba4670cb7021adc81ff7a094ad" - integrity sha512-8TYdgzJMMKvfHvSp8N3Bsj78xGw9lNHTYkh0IE0TGGwRVOEU6xNBkao6ktXzM3gTB+6U6OZn8Y//NCzLsoTUHg== +"@storybook/addon-actions@^6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.4.18.tgz#e997060e1b0af62f9f831301a56a3addfc1f1365" + integrity sha512-qPw5qfbWPmyOdaXxAVAbdVLVVE31gRrkH0ESUps+FXVNypRz1/0lJ6M2VrtOHMrFbGBl94SALdqsHOx6OYZKwg== dependencies: - "@storybook/addons" "6.4.17" - "@storybook/api" "6.4.17" - "@storybook/components" "6.4.17" - "@storybook/core-events" "6.4.17" + "@storybook/addons" "6.4.18" + "@storybook/api" "6.4.18" + "@storybook/components" "6.4.18" + "@storybook/core-events" "6.4.18" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/theming" "6.4.17" + "@storybook/theming" "6.4.18" core-js "^3.8.2" fast-deep-equal "^3.1.3" global "^4.4.0" @@ -1356,16 +1356,16 @@ util-deprecate "^1.0.2" uuid-browser "^3.1.0" -"@storybook/addon-links@^6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-6.4.17.tgz#83675642669c239c8d3ddaacd75348366e280426" - integrity sha512-ytGEe7sfOW10wwc0NIWSGtNgGM8ql8EOg7ZhrgXiRgQE0vD5NXRJi8FWzBdb06/G3cURYwveKR4Ea9mABZEaUw== +"@storybook/addon-links@^6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-6.4.18.tgz#edb61db6c291056f7d3c64566aea436a6796c50a" + integrity sha512-yIbL57+tV1Ei2b7zTGU/T7muBFByTPm/8IN5SA5tSFYRTR9VtFuvBXco6I9Wz9GLN/REyVa4+AoDahokk7+vPQ== dependencies: - "@storybook/addons" "6.4.17" - "@storybook/client-logger" "6.4.17" - "@storybook/core-events" "6.4.17" + "@storybook/addons" "6.4.18" + "@storybook/client-logger" "6.4.18" + "@storybook/core-events" "6.4.18" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/router" "6.4.17" + "@storybook/router" "6.4.18" "@types/qs" "^6.9.5" core-js "^3.8.2" global "^4.4.0" @@ -1374,18 +1374,18 @@ regenerator-runtime "^0.13.7" ts-dedent "^2.0.0" -"@storybook/addon-storysource@^6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/addon-storysource/-/addon-storysource-6.4.17.tgz#b5ca9ab8307de18d8885bcb181a4c867991b5dee" - integrity sha512-LBUyk3JXr9qalQazUsYbV50v9S2aI162y8wprpk1hF5YBZp2gL07+59sYww4riHZ+jZA+2oR5+TcTs8sRFFuXg== +"@storybook/addon-storysource@^6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/addon-storysource/-/addon-storysource-6.4.18.tgz#00f0fb919b6224bfa8379b7c4c66e0b32b443921" + integrity sha512-02hs9dnfJs5lihQ0c/Cv4+lQNmkR0Fd+isEL+oVNcWTE9g0LVSLzC3evzeQCJv0SDzei7T0N+G7pF1P2dmc5PQ== dependencies: - "@storybook/addons" "6.4.17" - "@storybook/api" "6.4.17" - "@storybook/client-logger" "6.4.17" - "@storybook/components" "6.4.17" - "@storybook/router" "6.4.17" - "@storybook/source-loader" "6.4.17" - "@storybook/theming" "6.4.17" + "@storybook/addons" "6.4.18" + "@storybook/api" "6.4.18" + "@storybook/client-logger" "6.4.18" + "@storybook/components" "6.4.18" + "@storybook/router" "6.4.18" + "@storybook/source-loader" "6.4.18" + "@storybook/theming" "6.4.18" core-js "^3.8.2" estraverse "^5.2.0" loader-utils "^2.0.0" @@ -1394,35 +1394,35 @@ react-syntax-highlighter "^13.5.3" regenerator-runtime "^0.13.7" -"@storybook/addons@6.4.17", "@storybook/addons@^6.4.14": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/addons/-/addons-6.4.17.tgz#d040db3ddcf72fd9e7df8b8fce2a6dc88578c87e" - integrity sha512-C/hji0Bc7+tssGqaD0JYd/Pz0GM46xbRpdgHSVLInYdhJrb5a9IG6INCbcB8CXeReDKWJCLAaj2+z79Wa96bFQ== +"@storybook/addons@6.4.18", "@storybook/addons@^6.4.14": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/addons/-/addons-6.4.18.tgz#fc92a4a608680f2e182a5e896ed382792f6b774e" + integrity sha512-fd3S79P4jJCYZNA2JxA1Xnkj0UlHGQ4Vg72aroWy4OQFlgGQor1LgPfM6RaJ9rh/4k4BXYPXsS7wzI0UWKG3Lw== dependencies: - "@storybook/api" "6.4.17" - "@storybook/channels" "6.4.17" - "@storybook/client-logger" "6.4.17" - "@storybook/core-events" "6.4.17" + "@storybook/api" "6.4.18" + "@storybook/channels" "6.4.18" + "@storybook/client-logger" "6.4.18" + "@storybook/core-events" "6.4.18" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/router" "6.4.17" - "@storybook/theming" "6.4.17" + "@storybook/router" "6.4.18" + "@storybook/theming" "6.4.18" "@types/webpack-env" "^1.16.0" core-js "^3.8.2" global "^4.4.0" regenerator-runtime "^0.13.7" -"@storybook/api@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/api/-/api-6.4.17.tgz#82c3d756c85a65ecd8a3c3d9ce890e581175003a" - integrity sha512-O0ssHVy40t4QD5CNdNESbJo7uZd86UWYrHCFjgeC2gmxrMgBD+ajO34N4HoQFC/F+/84om2/z8RYAGKu/WpoTA== +"@storybook/api@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/api/-/api-6.4.18.tgz#92da2b69aeec712419bec9bab5c8434ff1776e97" + integrity sha512-tSbsHKklBysuSmw4T+cKzMj6mQh/42m9F8+2iJns2XG/IUKpMAzFg/9dlgCTW+ay6dJwsR79JGIc9ccIe4SMgQ== dependencies: - "@storybook/channels" "6.4.17" - "@storybook/client-logger" "6.4.17" - "@storybook/core-events" "6.4.17" + "@storybook/channels" "6.4.18" + "@storybook/client-logger" "6.4.18" + "@storybook/core-events" "6.4.18" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/router" "6.4.17" + "@storybook/router" "6.4.18" "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.4.17" + "@storybook/theming" "6.4.18" core-js "^3.8.2" fast-deep-equal "^3.1.3" global "^4.4.0" @@ -1434,10 +1434,10 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/builder-webpack4@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/builder-webpack4/-/builder-webpack4-6.4.17.tgz#ad71aaa0a271941e2efe114d5bf7bc8feaa13dcf" - integrity sha512-jE1JehWj5gjLwafGuvV1OyBFVVhBCvv6ESc3QPm+jrsf4ZyB9xliTsnPt3bDggQhWpTEbxgGw7IkVc83ss4AOw== +"@storybook/builder-webpack4@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/builder-webpack4/-/builder-webpack4-6.4.18.tgz#8bae72b9e982d35a5a9f2b7f9af9d85a9c2dc966" + integrity sha512-N/OGjTnc7CpVoDnfoI49uMjAIpGqh2lWHFYNIWaUoG1DNnTt1nCc49hw9awjFc5KgaYOwJmVg1SYYE8Afssu+Q== dependencies: "@babel/core" "^7.12.10" "@babel/plugin-proposal-class-properties" "^7.12.1" @@ -1460,22 +1460,22 @@ "@babel/preset-env" "^7.12.11" "@babel/preset-react" "^7.12.10" "@babel/preset-typescript" "^7.12.7" - "@storybook/addons" "6.4.17" - "@storybook/api" "6.4.17" - "@storybook/channel-postmessage" "6.4.17" - "@storybook/channels" "6.4.17" - "@storybook/client-api" "6.4.17" - "@storybook/client-logger" "6.4.17" - "@storybook/components" "6.4.17" - "@storybook/core-common" "6.4.17" - "@storybook/core-events" "6.4.17" - "@storybook/node-logger" "6.4.17" - "@storybook/preview-web" "6.4.17" - "@storybook/router" "6.4.17" + "@storybook/addons" "6.4.18" + "@storybook/api" "6.4.18" + "@storybook/channel-postmessage" "6.4.18" + "@storybook/channels" "6.4.18" + "@storybook/client-api" "6.4.18" + "@storybook/client-logger" "6.4.18" + "@storybook/components" "6.4.18" + "@storybook/core-common" "6.4.18" + "@storybook/core-events" "6.4.18" + "@storybook/node-logger" "6.4.18" + "@storybook/preview-web" "6.4.18" + "@storybook/router" "6.4.18" "@storybook/semver" "^7.3.2" - "@storybook/store" "6.4.17" - "@storybook/theming" "6.4.17" - "@storybook/ui" "6.4.17" + "@storybook/store" "6.4.18" + "@storybook/theming" "6.4.18" + "@storybook/ui" "6.4.18" "@types/node" "^14.0.10" "@types/webpack" "^4.41.26" autoprefixer "^9.8.6" @@ -1509,51 +1509,51 @@ webpack-hot-middleware "^2.25.1" webpack-virtual-modules "^0.2.2" -"@storybook/channel-postmessage@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.4.17.tgz#9f439bee440479bfe8f86092701b3b63afc5195a" - integrity sha512-IaVkO/w7bn95Psm1iROlSsc/DHh9RiA7F151VLFD9VTh55qiIfeRssfBXIg3ueGUWm0K+Y9J1jQbcqJoEniMtw== +"@storybook/channel-postmessage@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.4.18.tgz#24547fe7cee599969fd62df22142ba7046099a8e" + integrity sha512-SKapUREPkqzKoBMpOJrZddE9PCR8CJkPTcDpjDqcRsTvToRWsux3pvzmuW4iGYnHNh+GQml7Rz9x85WfMIpfyQ== dependencies: - "@storybook/channels" "6.4.17" - "@storybook/client-logger" "6.4.17" - "@storybook/core-events" "6.4.17" + "@storybook/channels" "6.4.18" + "@storybook/client-logger" "6.4.18" + "@storybook/core-events" "6.4.18" core-js "^3.8.2" global "^4.4.0" qs "^6.10.0" telejson "^5.3.2" -"@storybook/channel-websocket@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/channel-websocket/-/channel-websocket-6.4.17.tgz#780cc68bb3a31069196b35a232013764cc2320a3" - integrity sha512-HtApo/3upDvxSl6VU04F/JznMIltUHeyEqaQNlkqJbQ1VQEHky/M/XJZWT4I/b+nGMXCt0+z0P0ikZ6VZKzFsw== +"@storybook/channel-websocket@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/channel-websocket/-/channel-websocket-6.4.18.tgz#cf3a03e88b983c2953cb76a40a964806790567c4" + integrity sha512-ROqNZAFB1gP9u8dmlM4KxykXHsd1ifunBgFY3ncQKeRi2Oh30OMVB2ZhNdoIF8i8X5ZBwSpId1o6nQhL2e/EJA== dependencies: - "@storybook/channels" "6.4.17" - "@storybook/client-logger" "6.4.17" + "@storybook/channels" "6.4.18" + "@storybook/client-logger" "6.4.18" core-js "^3.8.2" global "^4.4.0" telejson "^5.3.2" -"@storybook/channels@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/channels/-/channels-6.4.17.tgz#95d05745a96b6059cea26d45aacca3967c401e26" - integrity sha512-C6ON1olkkHc+FaDerkwL1yYGDL1xtFP+eMlm42ZaO06sIT9qv9EkJZ3GU/PNLTeXYMX4OsZl9kjz2whD4rN7gg== +"@storybook/channels@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/channels/-/channels-6.4.18.tgz#2907aca0039b5eb9ae305112f14c488c2621c2f6" + integrity sha512-Bh4l7VKKR2ImLbZ9XgL/DzT3lFv9+SLiCu1ozfpBZGHUCOLyHRnkG/h8wYvRkF9s3tpNwOtaCaqD1vkkZfr3uw== dependencies: core-js "^3.8.2" ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/client-api@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.4.17.tgz#34476732eb4a698e7dcc774a21feca4529581889" - integrity sha512-qK8Bvsr2KzndAu8RxbBrieNUCltO/ynwtAohJ/29hAg/duf94CZjN0HkuTpQmd4lDip11d9o4Fz5UBWC0zMyOw== +"@storybook/client-api@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.4.18.tgz#61c7c90f3f099e4d3bcc36576d2adbe2e5ef6eee" + integrity sha512-ua2Q692Fz2b3q5M/Qzjixg2LArwrcHGBmht06bNw/jrRfyFeTUHOhh5BT7LxSEetUgHATH/Y1GW40xza9rXFNw== dependencies: - "@storybook/addons" "6.4.17" - "@storybook/channel-postmessage" "6.4.17" - "@storybook/channels" "6.4.17" - "@storybook/client-logger" "6.4.17" - "@storybook/core-events" "6.4.17" + "@storybook/addons" "6.4.18" + "@storybook/channel-postmessage" "6.4.18" + "@storybook/channels" "6.4.18" + "@storybook/client-logger" "6.4.18" + "@storybook/core-events" "6.4.18" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/store" "6.4.17" + "@storybook/store" "6.4.18" "@types/qs" "^6.9.5" "@types/webpack-env" "^1.16.0" core-js "^3.8.2" @@ -1568,23 +1568,23 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/client-logger@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.4.17.tgz#50652859592c489b671f010455b8ce85d21a1b3d" - integrity sha512-awKBTOWHXHBxAIl8a/Zy/BitIw49A+0RnhPGuf8aFAw2Ym/vKR4bI8lRHVPtlR6RIHFp5rC1g32HmCQfKE22Fw== +"@storybook/client-logger@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.4.18.tgz#4ad8ea7d67b17e5db8f15cffcc2f984df3479462" + integrity sha512-ciBaASMaB2ZPksbuyDbp3++5SZxbhcihEpl+RQcAVV8g+TUyBZKIcHt8HNHicTczz5my1EydZovMh1IkSBMICA== dependencies: core-js "^3.8.2" global "^4.4.0" -"@storybook/components@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/components/-/components-6.4.17.tgz#5be383682d9538c35c96463723cb17740f105fb6" - integrity sha512-R6imELCWlHWQiprYMeeXLKgUQK4m698G/jvkc1xUxAThpTxwgROTcpw5qnJA0k+wltjGn4t6MBWKHhheGZc6Hg== +"@storybook/components@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/components/-/components-6.4.18.tgz#1f3eba9ab69a09b9468af0126d6e7ab040655ca4" + integrity sha512-LAPKYWgB6S10Vzt0IWa1Ihf9EAuQOGxlqehTuxYLOwMOKbto8iEbGRse/XaQfxdZf/RbmOL4u+7nVRROWgOEjg== dependencies: "@popperjs/core" "^2.6.0" - "@storybook/client-logger" "6.4.17" + "@storybook/client-logger" "6.4.18" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/theming" "6.4.17" + "@storybook/theming" "6.4.18" "@types/color-convert" "^2.0.0" "@types/overlayscrollbars" "^1.12.0" "@types/react-syntax-highlighter" "11.0.5" @@ -1606,21 +1606,21 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/core-client@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/core-client/-/core-client-6.4.17.tgz#baff9629a0723f9485d608c00357d45921a78a0d" - integrity sha512-uXO+DW5XI6fWLtQIBIBlBFeYGsy2qZEe3lxxXwBHwIjsDq53/1CmhEPuzC3jAsy5ddeKC2yEEHUdy3d3wkusIQ== +"@storybook/core-client@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/core-client/-/core-client-6.4.18.tgz#7f2feb961864dcf6de501a94a41900fd36b43657" + integrity sha512-F9CqW31Mr9Qde90uqPorpkiS+P7UteKYmdHlV0o0czeWaL+MEhpY+3pRJuRIIjX5C7Vc89TvljMqs37Khakmdg== dependencies: - "@storybook/addons" "6.4.17" - "@storybook/channel-postmessage" "6.4.17" - "@storybook/channel-websocket" "6.4.17" - "@storybook/client-api" "6.4.17" - "@storybook/client-logger" "6.4.17" - "@storybook/core-events" "6.4.17" + "@storybook/addons" "6.4.18" + "@storybook/channel-postmessage" "6.4.18" + "@storybook/channel-websocket" "6.4.18" + "@storybook/client-api" "6.4.18" + "@storybook/client-logger" "6.4.18" + "@storybook/core-events" "6.4.18" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/preview-web" "6.4.17" - "@storybook/store" "6.4.17" - "@storybook/ui" "6.4.17" + "@storybook/preview-web" "6.4.18" + "@storybook/store" "6.4.18" + "@storybook/ui" "6.4.18" airbnb-js-shims "^2.2.1" ansi-to-html "^0.6.11" core-js "^3.8.2" @@ -1632,10 +1632,10 @@ unfetch "^4.2.0" util-deprecate "^1.0.2" -"@storybook/core-common@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.4.17.tgz#bd2b14cfd1473f5f31f40c747afb62ea4a4ada6e" - integrity sha512-aOSG5Yvd8eoZsjvVlk7sS8iRXWT/dleHoHPXtKmHJnGcIZ1dcgr4wZqoOvL8dGhNNoU4Wx9dkJepqHD0+E/UgA== +"@storybook/core-common@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.4.18.tgz#0688a0a4a80cdbc161966c5a7ff49e755d64bbab" + integrity sha512-y4e43trNyQ3/v0Wpi240on7yVooUQvJBhJxOGEfcxAMRtcDa0ZCxHO4vAFX3k3voQOSmiXItXfJ1eGo/K+u0Fw== dependencies: "@babel/core" "^7.12.10" "@babel/plugin-proposal-class-properties" "^7.12.1" @@ -1658,7 +1658,7 @@ "@babel/preset-react" "^7.12.10" "@babel/preset-typescript" "^7.12.7" "@babel/register" "^7.12.1" - "@storybook/node-logger" "6.4.17" + "@storybook/node-logger" "6.4.18" "@storybook/semver" "^7.3.2" "@types/node" "^14.0.10" "@types/pretty-hrtime" "^1.0.0" @@ -1687,29 +1687,29 @@ util-deprecate "^1.0.2" webpack "4" -"@storybook/core-events@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.4.17.tgz#ad70c883673a2060f1c7c4aa8f5926fc14119f4a" - integrity sha512-k6wNjQLZZ8A/rt4gLz0M4ebTORKYYz2B9hZ3LvPJftNVqv+bTFAV4KVks6bBlvbJWpJ+eCPEyfeSP9Np2QIFMQ== +"@storybook/core-events@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.4.18.tgz#630a19425eb387c6134f29b967c30458c65f7ea8" + integrity sha512-lCT3l0rFs6CuVpD8+mwmj1lUTomGErySTxi0KmVd2AWQj8kJL90EfS0jHSU5JIXScDvuwXDXLLmvMfqNU+zHdg== dependencies: core-js "^3.8.2" -"@storybook/core-server@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/core-server/-/core-server-6.4.17.tgz#16f31635565c19248a45a793a7c2150597f3a4cc" - integrity sha512-wXYF4VD2EJ/6uFK+wAo/TgUyfD/lfMzzbAw2gBZAjYp7y7Zwj3svGqUfkFuPQG0/E9gmQfEmlyhTPPZImBFeBg== +"@storybook/core-server@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/core-server/-/core-server-6.4.18.tgz#520935f7f330a734488e733ad4cf15a9556679b5" + integrity sha512-7e2QUtD8/TE14P9X/xsBDMBbNVi/etTtMKKhsG2TG25daRz+6qadbM9tNP0YwvIDk452cNYJkjflV48mf5+ZEA== dependencies: "@discoveryjs/json-ext" "^0.5.3" - "@storybook/builder-webpack4" "6.4.17" - "@storybook/core-client" "6.4.17" - "@storybook/core-common" "6.4.17" - "@storybook/core-events" "6.4.17" + "@storybook/builder-webpack4" "6.4.18" + "@storybook/core-client" "6.4.18" + "@storybook/core-common" "6.4.18" + "@storybook/core-events" "6.4.18" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/csf-tools" "6.4.17" - "@storybook/manager-webpack4" "6.4.17" - "@storybook/node-logger" "6.4.17" + "@storybook/csf-tools" "6.4.18" + "@storybook/manager-webpack4" "6.4.18" + "@storybook/node-logger" "6.4.18" "@storybook/semver" "^7.3.2" - "@storybook/store" "6.4.17" + "@storybook/store" "6.4.18" "@types/node" "^14.0.10" "@types/node-fetch" "^2.5.7" "@types/pretty-hrtime" "^1.0.0" @@ -1742,18 +1742,18 @@ webpack "4" ws "^8.2.3" -"@storybook/core@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/core/-/core-6.4.17.tgz#61892e2eb484a44fc9d69515c3068b1f64173327" - integrity sha512-wquJcEebw9kXJ7pThcmEsDNK0ykd3ir0uL5tkBzPGNIj7dozpzy24Fo9JSr0rNWHNtE7JczdIAQTcumowLTDig== +"@storybook/core@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/core/-/core-6.4.18.tgz#56f7bb0f20dbcfa205d860022b7bf30bf42fd472" + integrity sha512-7DTMAEXiBIwd1jgalbsZiXCiS2Be9MKKsr6GQdf3WaBm0WYV067oN9jcUY5IgNtJX06arT4Ykp+CGG/TR+sLlw== dependencies: - "@storybook/core-client" "6.4.17" - "@storybook/core-server" "6.4.17" + "@storybook/core-client" "6.4.18" + "@storybook/core-server" "6.4.18" -"@storybook/csf-tools@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-6.4.17.tgz#e7d2b9de95317d706657c294d7beee1d7b307ec4" - integrity sha512-GnaO1dX4wTvMKBthbbHLHcrDTXwZ7PooZmT1fTCeokzaobZzyv1cUtF1hlPQa3zA75kRE5AznJ0jmBVhHe0/9Q== +"@storybook/csf-tools@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-6.4.18.tgz#cdd40b543f9bea79c1481c236868b8ea04af6bd7" + integrity sha512-KtwxKrkndEyvyAiBliI6m4yMFMvnyI4fOjU8t1qCit/0gjutOF5JxmmZ+H8FSI5dIyibEOzQmzHe0MyStAjCEQ== dependencies: "@babel/core" "^7.12.10" "@babel/generator" "^7.12.11" @@ -1780,20 +1780,20 @@ dependencies: lodash "^4.17.15" -"@storybook/manager-webpack4@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/manager-webpack4/-/manager-webpack4-6.4.17.tgz#8fc6d5dba0587446defe78ced67b7033886c4c47" - integrity sha512-ekHudBR8FVSE475YQZZs9sqwou7YqFv03hNVOcvIJ36cZBgMbSkG8q50cK4uru2xCOedTK15SKIoFZQQ77cmQQ== +"@storybook/manager-webpack4@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/manager-webpack4/-/manager-webpack4-6.4.18.tgz#5317c917dbdaf4cf8721647551a785eb13c04146" + integrity sha512-6oX1KrIJBoY4vdZiMftJNusv+Bm8pegVjdJ+aZcbr/41x7ufP3tu5UKebEXDH0UURXtLw0ffl+OgojewGdpC1Q== dependencies: "@babel/core" "^7.12.10" "@babel/plugin-transform-template-literals" "^7.12.1" "@babel/preset-react" "^7.12.10" - "@storybook/addons" "6.4.17" - "@storybook/core-client" "6.4.17" - "@storybook/core-common" "6.4.17" - "@storybook/node-logger" "6.4.17" - "@storybook/theming" "6.4.17" - "@storybook/ui" "6.4.17" + "@storybook/addons" "6.4.18" + "@storybook/core-client" "6.4.18" + "@storybook/core-common" "6.4.18" + "@storybook/node-logger" "6.4.18" + "@storybook/theming" "6.4.18" + "@storybook/ui" "6.4.18" "@types/node" "^14.0.10" "@types/webpack" "^4.41.26" babel-loader "^8.0.0" @@ -1822,10 +1822,10 @@ webpack-dev-middleware "^3.7.3" webpack-virtual-modules "^0.2.2" -"@storybook/node-logger@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.4.17.tgz#14fe3091b2030413c2f43f0de3e9408b27591d9c" - integrity sha512-gymFKjmOdi9fAJCaM4C8I/5Go4hPsOAcVNixpjAQYsvNQQZ1Yjm2zcSdD+QOuLJ36NTxgOFxT4ESbC2AfSjyqA== +"@storybook/node-logger@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.4.18.tgz#8759761ba7526b2fa03a1a08fe82d6d892d7a072" + integrity sha512-wY1qt4XOXtJJdQ+DrO3RijtiwVFqWuWetvCY4RV4lge5yk0FP5Q+MTpmjazYodAvGPUIP0LK9bvEDLwXa0JUfw== dependencies: "@types/npmlog" "^4.1.2" chalk "^4.1.0" @@ -1833,17 +1833,17 @@ npmlog "^5.0.1" pretty-hrtime "^1.0.3" -"@storybook/preview-web@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/preview-web/-/preview-web-6.4.17.tgz#d29bbfa8f66428ef5e2202c4c364c1892d8cbf7b" - integrity sha512-fJIE/LO7I09w334AH71ojRpIiHLQrBUidkZlIQbjEmHn/GZBTePlf3CevrERA12FbCLoUbeS5nadk2dEg6YnUw== +"@storybook/preview-web@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/preview-web/-/preview-web-6.4.18.tgz#47c908bf27d2089ccf3296c376a6f5b1e8674b5a" + integrity sha512-0x64uLdGhIOk9hIuRKTHFdP7+iEHyjAOi5U4jtwqFfDtG4n4zxEGSsUWij7pTR2rAYf7g2NWIbAM7qb1AqqcLQ== dependencies: - "@storybook/addons" "6.4.17" - "@storybook/channel-postmessage" "6.4.17" - "@storybook/client-logger" "6.4.17" - "@storybook/core-events" "6.4.17" + "@storybook/addons" "6.4.18" + "@storybook/channel-postmessage" "6.4.18" + "@storybook/client-logger" "6.4.18" + "@storybook/core-events" "6.4.18" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/store" "6.4.17" + "@storybook/store" "6.4.18" ansi-to-html "^0.6.11" core-js "^3.8.2" global "^4.4.0" @@ -1868,22 +1868,22 @@ react-docgen-typescript "^2.0.0" tslib "^2.0.0" -"@storybook/react@^6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/react/-/react-6.4.17.tgz#c12f22c3365d4213c662bf1e26520e72c68b0c33" - integrity sha512-hAMEyMcWC5fEdzXOYr0S9/QHclXbbJpl7Vl9dd56wxbHx4FFwcJ7R5hroLntPsHXU+rGTF9/EqehmEa/Jd0l4w== +"@storybook/react@^6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/react/-/react-6.4.18.tgz#22624af56a9873c6616b5dc6a1e30c968bac95d2" + integrity sha512-dKxwsvJEGTm/aNIJSJMI4MImsI4EhmBa42FtwVvtFkrokuMf2CsmTJsaaAh+1or9SKGTiFuGsYDGhX5joE3XUQ== dependencies: "@babel/preset-flow" "^7.12.1" "@babel/preset-react" "^7.12.10" "@pmmmwh/react-refresh-webpack-plugin" "^0.5.1" - "@storybook/addons" "6.4.17" - "@storybook/core" "6.4.17" - "@storybook/core-common" "6.4.17" + "@storybook/addons" "6.4.18" + "@storybook/core" "6.4.18" + "@storybook/core-common" "6.4.18" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/node-logger" "6.4.17" + "@storybook/node-logger" "6.4.18" "@storybook/react-docgen-typescript-plugin" "1.0.2-canary.253f8c1.0" "@storybook/semver" "^7.3.2" - "@storybook/store" "6.4.17" + "@storybook/store" "6.4.18" "@types/webpack-env" "^1.16.0" babel-plugin-add-react-displayname "^0.0.5" babel-plugin-named-asset-import "^0.3.1" @@ -1898,12 +1898,12 @@ ts-dedent "^2.0.0" webpack "4" -"@storybook/router@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/router/-/router-6.4.17.tgz#d53c4f9a4ccaa21a7bbe8d875a1a81c9dba2a6f2" - integrity sha512-GLhzth83BB2BbUkM/+ld2JITIbDQtzFLs/CnZZQKq6aR93Kou6VK2epHnIwrPyWbP6rsGavR/8L/UWeBdwwTrQ== +"@storybook/router@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/router/-/router-6.4.18.tgz#8803dd78277f8602d6c11dae56f6229474dfa54c" + integrity sha512-itvSWHhG1X/NV1sMlwP1qKtF0HfiIaAHImr0LwQ2K2F6/CI11W68dJAs4WBUdwzA0+H0Joyu/2a/6mCQHcee1A== dependencies: - "@storybook/client-logger" "6.4.17" + "@storybook/client-logger" "6.4.18" core-js "^3.8.2" fast-deep-equal "^3.1.3" global "^4.4.0" @@ -1923,13 +1923,13 @@ core-js "^3.6.5" find-up "^4.1.0" -"@storybook/source-loader@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/source-loader/-/source-loader-6.4.17.tgz#d17e73f88f8c2a714fe129bf66ad692b4d4e0c97" - integrity sha512-OAETI21mL/jwmb9e/JtFDIsLWoOOWOAIm3Cj89XHQz/5VkYljZxdh2icb6xDHR8PtEaXj4+sBWQUG3L+a/a9QQ== +"@storybook/source-loader@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/source-loader/-/source-loader-6.4.18.tgz#205423e56f7da752d64a0695f2b22ed94378e5d0" + integrity sha512-sjKvngCCYDbBwjjFTjAXO6VsAzKkjy+UctseeULXxEN3cKIsz/R3y7MrrN9yBrwyYcn0k3pqa9d9e3gE+Jv2Tw== dependencies: - "@storybook/addons" "6.4.17" - "@storybook/client-logger" "6.4.17" + "@storybook/addons" "6.4.18" + "@storybook/client-logger" "6.4.18" "@storybook/csf" "0.0.2--canary.87bc651.0" core-js "^3.8.2" estraverse "^5.2.0" @@ -1939,14 +1939,14 @@ prettier ">=2.2.1 <=2.3.0" regenerator-runtime "^0.13.7" -"@storybook/store@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/store/-/store-6.4.17.tgz#a68b687628b82f8ca0ef2c74f5d65f5a30e94f86" - integrity sha512-0rWk8u7gtzBOp5NvuIrL6abBHaDxax7e+yBPvU9tR0GZ7X0ALhOhJFRIo+lW9sZTUrcuSinOJ8Acyb0ZvnYCkg== +"@storybook/store@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/store/-/store-6.4.18.tgz#3b693c9d5555d5cfc04e2318e104746d9d55ad66" + integrity sha512-Vl5oCs/9fP1gUgfgMHTBsnYbwAAoaR93/bzDBeOHI3eo5x9uzzJtA4zcRmEiKahR/wgwGacpWy90JrIX469PDQ== dependencies: - "@storybook/addons" "6.4.17" - "@storybook/client-logger" "6.4.17" - "@storybook/core-events" "6.4.17" + "@storybook/addons" "6.4.18" + "@storybook/client-logger" "6.4.18" + "@storybook/core-events" "6.4.18" "@storybook/csf" "0.0.2--canary.87bc651.0" core-js "^3.8.2" fast-deep-equal "^3.1.3" @@ -1960,15 +1960,15 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/theming@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/theming/-/theming-6.4.17.tgz#f0a03d2d3239638ac171e97a8f089ee2656a8287" - integrity sha512-7+U72/VdhoMb00q1URMzdTW3OYHJogro2i2hScgKR+ndL4/dtSmetJ/1z9PuoFxLxHgdLKcwMAV0fZAjEYlhCA== +"@storybook/theming@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/theming/-/theming-6.4.18.tgz#05365cc1d3dab5d71b80a82928fc5188106a0ed6" + integrity sha512-1o0w2eP+8sXUesdtXpZR4Yvayp1h3xvK7l9+wuHh+1uCy+EvD5UI9d1HvU5kt5fw7XAJJcInaVAmyAbpwct0TQ== dependencies: "@emotion/core" "^10.1.1" "@emotion/is-prop-valid" "^0.8.6" "@emotion/styled" "^10.0.27" - "@storybook/client-logger" "6.4.17" + "@storybook/client-logger" "6.4.18" core-js "^3.8.2" deep-object-diff "^1.1.0" emotion-theming "^10.0.27" @@ -1978,21 +1978,21 @@ resolve-from "^5.0.0" ts-dedent "^2.0.0" -"@storybook/ui@6.4.17": - version "6.4.17" - resolved "https://registry.npmjs.org/@storybook/ui/-/ui-6.4.17.tgz#926aa1dbb4d3f9a28afe6edd6a0e5cb667be8e19" - integrity sha512-vBYV8PmvhYgMjjTRLtOHIisGqr1nfajAgOC+wfYvGLbF0npVEt5PfDieG1LTRc1OaItWLpKKJcByqSfL/y9Qow== +"@storybook/ui@6.4.18": + version "6.4.18" + resolved "https://registry.npmjs.org/@storybook/ui/-/ui-6.4.18.tgz#3ceaf6b317f8f2c1d7d1cdc49daaac7eaf10af6b" + integrity sha512-f2ckcLvEyA9CRcu6W2I2CyEbUnU4j3h5Nz0N40YZ2uRMVNQY2xPywAFZVySZIJAaum/5phDfnOD0Feap/Q6zVQ== dependencies: "@emotion/core" "^10.1.1" - "@storybook/addons" "6.4.17" - "@storybook/api" "6.4.17" - "@storybook/channels" "6.4.17" - "@storybook/client-logger" "6.4.17" - "@storybook/components" "6.4.17" - "@storybook/core-events" "6.4.17" - "@storybook/router" "6.4.17" + "@storybook/addons" "6.4.18" + "@storybook/api" "6.4.18" + "@storybook/channels" "6.4.18" + "@storybook/client-logger" "6.4.18" + "@storybook/components" "6.4.18" + "@storybook/core-events" "6.4.18" + "@storybook/router" "6.4.18" "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.4.17" + "@storybook/theming" "6.4.18" copy-to-clipboard "^3.3.1" core-js "^3.8.2" core-js-pure "^3.8.2" diff --git a/yarn.lock b/yarn.lock index 70a00d7cd6..792a2ecf15 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1366,49 +1366,6 @@ "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" -"@backstage/core-components@*", "@backstage/core-components@^0.8.0", "@backstage/core-components@^0.8.5", "@backstage/core-components@^0.8.6": - version "0.8.6" - resolved "https://registry.npmjs.org/@backstage/core-components/-/core-components-0.8.6.tgz#ad365c2d8ee99ec1280c1212b7de14a922dd6f34" - integrity sha512-dPbsENsqd6NBqg1ZcwZdOBdK4XxjkDP78ANE5Opcx1Kas+LpvFEPSSrK9AYkbZS4SK71vbreAmk/ovCLpj5Odg== - dependencies: - "@backstage/config" "^0.1.13" - "@backstage/core-plugin-api" "^0.6.0" - "@backstage/errors" "^0.2.0" - "@backstage/theme" "^0.2.14" - "@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.57" - "@types/react-sparklines" "^1.7.0" - "@types/react-text-truncate" "^0.14.0" - ansi-regex "^5.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" - history "^5.0.0" - immer "^9.0.1" - lodash "^4.17.21" - pluralize "^8.0.0" - prop-types "^15.7.2" - qs "^6.9.4" - rc-progress "3.2.4" - react-helmet "6.1.0" - react-hook-form "^7.12.2" - react-markdown "^8.0.0" - react-router "6.0.0-beta.0" - react-router-dom "6.0.0-beta.0" - react-sparklines "^1.7.0" - react-syntax-highlighter "^15.4.5" - react-text-truncate "^0.17.0" - react-use "^17.2.4" - react-virtualized-auto-sizer "^1.0.6" - react-window "^1.8.6" - remark-gfm "^3.0.1" - zen-observable "^0.8.15" - zod "^3.11.6" - "@backstage/core-plugin-api@^0.4.0": version "0.4.1" resolved "https://registry.npmjs.org/@backstage/core-plugin-api/-/core-plugin-api-0.4.1.tgz#c0a13504bdfa61ae3d0db96934cd6c32a7574446" @@ -1425,69 +1382,6 @@ react-use "^17.2.4" zen-observable "^0.8.15" -"@backstage/integration-react@^0.1.10", "@backstage/integration-react@^0.1.19": - version "0.1.19" - resolved "https://registry.npmjs.org/@backstage/integration-react/-/integration-react-0.1.19.tgz#99ac8bfb3f2bd0758fab04157660d7d34f4231a4" - integrity sha512-sYPERl63XJwmlsQ981BeCnqZjD1WsTU39x1lNIdO+EAOpy3LHe9qO5T4wSNLZgJvaliK1KuKf3w4ClU+qcDYvg== - dependencies: - "@backstage/config" "^0.1.13" - "@backstage/core-components" "^0.8.5" - "@backstage/core-plugin-api" "^0.6.0" - "@backstage/integration" "^0.7.2" - "@backstage/theme" "^0.2.14" - "@material-ui/core" "^4.12.2" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "4.0.0-alpha.57" - react-use "^17.2.4" - -"@backstage/plugin-catalog-react@^0.6.12", "@backstage/plugin-catalog-react@^0.6.5": - version "0.6.12" - resolved "https://registry.npmjs.org/@backstage/plugin-catalog-react/-/plugin-catalog-react-0.6.12.tgz#df6e9017ff6ad2e87395af11a277aadd95aef58b" - integrity sha512-0ezerRaR5dbYfoXvsxguUDqAhBxlblPl3uvzHhRDfUcV1r9L+UjKIlRB2tjC8rVtzAh7ob486viKAe6wKnbB5g== - dependencies: - "@backstage/catalog-client" "^0.5.5" - "@backstage/catalog-model" "^0.9.10" - "@backstage/core-components" "^0.8.5" - "@backstage/core-plugin-api" "^0.6.0" - "@backstage/errors" "^0.2.0" - "@backstage/integration" "^0.7.2" - "@backstage/plugin-permission-common" "^0.4.0" - "@backstage/plugin-permission-react" "^0.3.0" - "@backstage/types" "^0.1.1" - "@backstage/version-bridge" "^0.1.1" - "@material-ui/core" "^4.12.2" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "4.0.0-alpha.57" - jwt-decode "^3.1.0" - lodash "^4.17.21" - qs "^6.9.4" - react-router "6.0.0-beta.0" - react-use "^17.2.4" - zen-observable "^0.8.15" - -"@backstage/plugin-catalog@*": - version "0.7.10" - resolved "https://registry.npmjs.org/@backstage/plugin-catalog/-/plugin-catalog-0.7.10.tgz#0d434a91b61ed98d143a42d472c2ffdfff0fd64f" - integrity sha512-lNvoDL3GGoXtnfFCFnCrvtX7c13LHPuzpS7FWroKcg/3K/AoshUTr8OXQJht56djszzE02ne9r91VIBlYJ1DaQ== - dependencies: - "@backstage/catalog-client" "^0.5.5" - "@backstage/catalog-model" "^0.9.10" - "@backstage/core-components" "^0.8.6" - "@backstage/core-plugin-api" "^0.6.0" - "@backstage/errors" "^0.2.0" - "@backstage/integration-react" "^0.1.19" - "@backstage/plugin-catalog-common" "^0.1.1" - "@backstage/plugin-catalog-react" "^0.6.12" - "@backstage/theme" "^0.2.14" - "@material-ui/core" "^4.12.2" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "4.0.0-alpha.57" - history "^5.0.0" - lodash "^4.17.21" - react-helmet "6.1.0" - react-router "6.0.0-beta.0" - react-use "^17.2.4" - "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -1498,17 +1392,17 @@ resolved "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-5.0.2.tgz#b23080fa35520e993a8a37a0f5bca26aa4650a48" integrity sha512-NBEJlHWrhQucLhZGHtSxM2loSaNUMajC7KOYJLyfcdW/6goVoff2HoYI3bz8YCDN0wKGbxtUL0gx2dvHpvnWlw== -"@changesets/apply-release-plan@^5.0.1": - version "5.0.1" - resolved "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-5.0.1.tgz#ed3e30550f787ef1b72f0a51e29a54d244123109" - integrity sha512-ltYLM/PPoL1Un9hnNCbUac25FWonJvIZ/9C3O4UyZ/k4rir9FGvH6KLtMOiPEAJWnXmaHeRDr06MzohuXOnmvw== +"@changesets/apply-release-plan@^5.0.4": + version "5.0.4" + resolved "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-5.0.4.tgz#fefffecf73b59dbee7ae905b3c6a2e64c489f0cb" + integrity sha512-czayDIrgC8qBnqwClvh9nxjCMem+XZG7xtfdYwq3dxpzA30qGppcI0i088VYug5RCFR+l1N+HUvkujSZuBK65w== dependencies: "@babel/runtime" "^7.10.4" - "@changesets/config" "^1.6.1" + "@changesets/config" "^1.6.4" "@changesets/get-version-range-type" "^0.3.2" - "@changesets/git" "^1.1.2" - "@changesets/types" "^4.0.1" - "@manypkg/get-packages" "^1.0.1" + "@changesets/git" "^1.3.0" + "@changesets/types" "^4.0.2" + "@manypkg/get-packages" "^1.1.3" detect-indent "^6.0.0" fs-extra "^7.0.1" lodash.startcase "^4.4.0" @@ -1517,45 +1411,45 @@ resolve-from "^5.0.0" semver "^5.4.1" -"@changesets/assemble-release-plan@^5.0.1": - version "5.0.1" - resolved "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-5.0.1.tgz#80e9b750705677eb2d6356c581ed9c2e97fd68e7" - integrity sha512-KQqafvScTFQ/4Q2LpLmDYhU47LWvIGcgVS8tzKU8fBvRdKuLGQXe42VYbwVM0cHIkFd/b6YFn+H2QMdKC2MjIQ== +"@changesets/assemble-release-plan@^5.0.5": + version "5.0.5" + resolved "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-5.0.5.tgz#60e4adc9bf458dd6ec38dee78d8f1bbeddfe3936" + integrity sha512-ejCVSM4I1jgaNi30we3/qltj2NQtS68w7C3H8Gvb6ZOvbIpAW/Tr0uMmPgRj4Vzkez5+fx0If02AvOdssz1btA== dependencies: "@babel/runtime" "^7.10.4" "@changesets/errors" "^0.1.4" - "@changesets/get-dependents-graph" "^1.2.2" - "@changesets/types" "^4.0.1" - "@manypkg/get-packages" "^1.0.1" + "@changesets/get-dependents-graph" "^1.3.0" + "@changesets/types" "^4.0.2" + "@manypkg/get-packages" "^1.1.3" semver "^5.4.1" "@changesets/cli@^2.14.0": - version "2.17.0" - resolved "https://registry.npmjs.org/@changesets/cli/-/cli-2.17.0.tgz#cc7ff4f64d029ddd6d87020a012c8cf8c7adde58" - integrity sha512-UyraYwYst1lTjef+8i80XQ6SqsLaGwi4Sgn9YuDf2xdHA9m+5qQXshHvHVjaTdPTA09rqMBk9yeO7vmAqF4+vQ== + version "2.20.0" + resolved "https://registry.npmjs.org/@changesets/cli/-/cli-2.20.0.tgz#f24dbd38bd4bc47bf083e59b6bb9cbf531465808" + integrity sha512-IUYSgZKtS+wXPD5hxfnCfZ1JWCbBI0CRrhxpkgVKcXDwpxiRU8stCwuSuVj14kiYlThuH2zL0/ZuGvhF4r28Gg== dependencies: "@babel/runtime" "^7.10.4" - "@changesets/apply-release-plan" "^5.0.1" - "@changesets/assemble-release-plan" "^5.0.1" - "@changesets/config" "^1.6.1" + "@changesets/apply-release-plan" "^5.0.4" + "@changesets/assemble-release-plan" "^5.0.5" + "@changesets/config" "^1.6.4" "@changesets/errors" "^0.1.4" - "@changesets/get-dependents-graph" "^1.2.2" - "@changesets/get-release-plan" "^3.0.1" - "@changesets/git" "^1.1.2" + "@changesets/get-dependents-graph" "^1.3.0" + "@changesets/get-release-plan" "^3.0.5" + "@changesets/git" "^1.3.0" "@changesets/logger" "^0.0.5" - "@changesets/pre" "^1.0.7" - "@changesets/read" "^0.5.0" - "@changesets/types" "^4.0.1" - "@changesets/write" "^0.1.5" - "@manypkg/get-packages" "^1.0.1" + "@changesets/pre" "^1.0.9" + "@changesets/read" "^0.5.3" + "@changesets/types" "^4.0.2" + "@changesets/write" "^0.1.6" + "@manypkg/get-packages" "^1.1.3" + "@types/is-ci" "^3.0.0" "@types/semver" "^6.0.0" - boxen "^1.3.0" chalk "^2.1.0" enquirer "^2.3.0" external-editor "^3.1.0" fs-extra "^7.0.1" human-id "^1.0.2" - is-ci "^2.0.0" + is-ci "^3.0.1" meow "^6.0.0" outdent "^0.5.0" p-limit "^2.2.0" @@ -1565,16 +1459,16 @@ term-size "^2.1.0" tty-table "^2.8.10" -"@changesets/config@^1.6.1": - version "1.6.1" - resolved "https://registry.npmjs.org/@changesets/config/-/config-1.6.1.tgz#e9b1636fd56a74411c493c924e6ffa07d7d26091" - integrity sha512-aQTo6ODvhsvnSFszMP1YbJyAi1DtE1Pes9rL+G+KYJiAOA6k5RzbiKOarjo+ZkKXpX0G3CBAbOO8jXOX4xG7cQ== +"@changesets/config@^1.6.4": + version "1.6.4" + resolved "https://registry.npmjs.org/@changesets/config/-/config-1.6.4.tgz#c904c84f067b49c09b378618b751089dd29ed0b7" + integrity sha512-WWa8eR8GzS/p2atLc/+5UEDn7fsRCZ+/sShLkB/3efVbTkSTB1PwoKwQRXLYXM1DY289T7UnJT4HLZA3Gcreww== dependencies: "@changesets/errors" "^0.1.4" - "@changesets/get-dependents-graph" "^1.2.2" + "@changesets/get-dependents-graph" "^1.3.0" "@changesets/logger" "^0.0.5" - "@changesets/types" "^4.0.1" - "@manypkg/get-packages" "^1.0.1" + "@changesets/types" "^4.0.2" + "@manypkg/get-packages" "^1.1.3" fs-extra "^7.0.1" micromatch "^4.0.2" @@ -1585,44 +1479,44 @@ dependencies: extendable-error "^0.1.5" -"@changesets/get-dependents-graph@^1.2.2": - version "1.2.2" - resolved "https://registry.npmjs.org/@changesets/get-dependents-graph/-/get-dependents-graph-1.2.2.tgz#7a2238f3d1a023de83d37b727a0da15826e88d73" - integrity sha512-3zJRw6TcexmOrmIZNOXpIRsZtqtrdmlzbqp4+V0VgnBvTxz16rqCS9VBsBqFYeJDWFj3soOlHUMeTwLghr18DA== +"@changesets/get-dependents-graph@^1.3.0": + version "1.3.0" + resolved "https://registry.npmjs.org/@changesets/get-dependents-graph/-/get-dependents-graph-1.3.0.tgz#892bbb63406911baac1f77a31303620492d466ec" + integrity sha512-4VHQWEluWySPgDdkL94YNxrEjDb9nwNFw515sWDmVrlfpQN5qaP1hdaotrp4mJm4ky85t4cTlrWSP+CTY7IDbw== dependencies: - "@changesets/types" "^4.0.1" - "@manypkg/get-packages" "^1.0.1" + "@changesets/types" "^4.0.2" + "@manypkg/get-packages" "^1.1.3" chalk "^2.1.0" fs-extra "^7.0.1" semver "^5.4.1" -"@changesets/get-release-plan@^3.0.1": - version "3.0.1" - resolved "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-3.0.1.tgz#c98a34321eac9e4187098893ff8dadb6f90ad89c" - integrity sha512-HTZeEPvLlcWMWKxLrzQNLQWKDDN1lUKvaOV+hl/yBhgtyJECljJJzd3IRaKqCSWMrYKNaaEcmunTtZ4oaeoK9w== +"@changesets/get-release-plan@^3.0.5": + version "3.0.5" + resolved "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-3.0.5.tgz#c05cff031bba737c8dd236afe97e77b007ee44a3" + integrity sha512-67td3LA1RTJpY5Q+wJaTTRtAjZ2suAhDfj3VRjFv0gCgUPXs8rNx17n9UPbegPTQjeTS1r7hVRVifycmT0fQtA== dependencies: "@babel/runtime" "^7.10.4" - "@changesets/assemble-release-plan" "^5.0.1" - "@changesets/config" "^1.6.1" - "@changesets/pre" "^1.0.7" - "@changesets/read" "^0.5.0" - "@changesets/types" "^4.0.1" - "@manypkg/get-packages" "^1.0.1" + "@changesets/assemble-release-plan" "^5.0.5" + "@changesets/config" "^1.6.4" + "@changesets/pre" "^1.0.9" + "@changesets/read" "^0.5.3" + "@changesets/types" "^4.0.2" + "@manypkg/get-packages" "^1.1.3" "@changesets/get-version-range-type@^0.3.2": version "0.3.2" resolved "https://registry.npmjs.org/@changesets/get-version-range-type/-/get-version-range-type-0.3.2.tgz#8131a99035edd11aa7a44c341cbb05e668618c67" integrity sha512-SVqwYs5pULYjYT4op21F2pVbcrca4qA/bAA3FmFXKMN7Y+HcO8sbZUTx3TAy2VXulP2FACd1aC7f2nTuqSPbqg== -"@changesets/git@^1.1.2": - version "1.1.2" - resolved "https://registry.npmjs.org/@changesets/git/-/git-1.1.2.tgz#248d4418bcb2d4f198852409cfcbd06a1fcb0424" - integrity sha512-dfza8elsIwcYVa4fFzLaPs4+AkoCFiW3sfzkkC7WR+rG9j+zZh7CelzVpnoiAbEI2QOzeCbZKMoLSvBPgHhB1g== +"@changesets/git@^1.3.0": + version "1.3.0" + resolved "https://registry.npmjs.org/@changesets/git/-/git-1.3.0.tgz#7f62e1983552efecb738054db5178eef77f41241" + integrity sha512-Ydj4lWX33d2PCDaTXOMSbyTjgk1go1V6EyXjKTmOV7nB/qvgKdDZLSt+AexKWKp3Ac2FTrtVnl9G5gMNVYNmuQ== dependencies: "@babel/runtime" "^7.10.4" "@changesets/errors" "^0.1.4" - "@changesets/types" "^4.0.1" - "@manypkg/get-packages" "^1.0.1" + "@changesets/types" "^4.0.2" + "@manypkg/get-packages" "^1.1.3" is-subdir "^1.1.1" spawndamnit "^2.0.0" @@ -1633,51 +1527,51 @@ dependencies: chalk "^2.1.0" -"@changesets/parse@^0.3.9": - version "0.3.9" - resolved "https://registry.npmjs.org/@changesets/parse/-/parse-0.3.9.tgz#c518792b05f15ab418d58dc1cea81601556e845e" - integrity sha512-XoTEkMpvRRVxSlhvOaK4YSFM+RZhYFTksxRh7ieNkb6pMxkpq8MOYSi/07BuqkODn4dJEMOoSy3RzL99P6FyqA== +"@changesets/parse@^0.3.11": + version "0.3.11" + resolved "https://registry.npmjs.org/@changesets/parse/-/parse-0.3.11.tgz#b53485f36152e6e9a097b56fc46cafb6705ce2b5" + integrity sha512-w5/X8KijcCrvv5lHimXIBR9o35c78niiBoesBjBUlWeifwPz0DHc/lzVYJKRkA5w0BGqft6T/9hKI68GaYj5wA== dependencies: - "@changesets/types" "^4.0.1" + "@changesets/types" "^4.0.2" js-yaml "^3.13.1" -"@changesets/pre@^1.0.7": - version "1.0.7" - resolved "https://registry.npmjs.org/@changesets/pre/-/pre-1.0.7.tgz#caf6430c90b8ac6d58c9cd90a19558ab06b19b88" - integrity sha512-oUU6EL4z0AIyCv/EscQFxxJsQfc9/AcSpqAGbdZrLXwshUWTXsJHMWlE3/+iSIyQ+I+/xtxbBxnqDUpUU3TOOg== +"@changesets/pre@^1.0.9": + version "1.0.9" + resolved "https://registry.npmjs.org/@changesets/pre/-/pre-1.0.9.tgz#f1a0efea42733c25ef4a782377b2ac61023bd1b7" + integrity sha512-F3+qMun89KlynecBD15fEpwGT/KxbYb3WGeut6w1xhZb0u7V/jdcPy9b+kJ2xmBqFZLn1WteWIP96IjxS57H7A== dependencies: "@babel/runtime" "^7.10.4" "@changesets/errors" "^0.1.4" - "@changesets/types" "^4.0.1" - "@manypkg/get-packages" "^1.0.1" + "@changesets/types" "^4.0.2" + "@manypkg/get-packages" "^1.1.3" fs-extra "^7.0.1" -"@changesets/read@^0.5.0": - version "0.5.0" - resolved "https://registry.npmjs.org/@changesets/read/-/read-0.5.0.tgz#52f7a10f6baebf97172e62035ee8345652c5a1c0" - integrity sha512-A2OJ+vgfvbUaLx2yKyHH+tapa+DUd2NtpFpVuxjUqv0zirjqju20z1bziqaqpIQSf/rXPuoc09vp5w4VakraHg== +"@changesets/read@^0.5.3": + version "0.5.3" + resolved "https://registry.npmjs.org/@changesets/read/-/read-0.5.3.tgz#5afb14ee0e806751c255e94fe8742843a9b12487" + integrity sha512-zoj5NjNR4AhiGXz6aHTxsBLojChHgDOSbz6VfAVxMKX7tF7UhyNYptG2VEbSjxeamNKABx6k1pkM2IyVVlOcbQ== dependencies: "@babel/runtime" "^7.10.4" - "@changesets/git" "^1.1.2" + "@changesets/git" "^1.3.0" "@changesets/logger" "^0.0.5" - "@changesets/parse" "^0.3.9" - "@changesets/types" "^4.0.1" + "@changesets/parse" "^0.3.11" + "@changesets/types" "^4.0.2" chalk "^2.1.0" fs-extra "^7.0.1" p-filter "^2.1.0" -"@changesets/types@^4.0.1": - version "4.0.1" - resolved "https://registry.npmjs.org/@changesets/types/-/types-4.0.1.tgz#85cf3cc32baff0691112d9d15fc21fbe022c9f0a" - integrity sha512-zVfv752D8K2tjyFmxU/vnntQ+dPu+9NupOSguA/2Zuym4tVxRh0ylArgKZ1bOAi2eXfGlZMxJU/kj7uCSI15RQ== +"@changesets/types@^4.0.1", "@changesets/types@^4.0.2": + version "4.0.2" + resolved "https://registry.npmjs.org/@changesets/types/-/types-4.0.2.tgz#d20e1e45bdc96a97cc509c655e708b53a9292465" + integrity sha512-OeDaB7D+WVy/ErymPzFm58IeGvz4DOl+oedyZETfnkfMezF/Uhrm1Ub6MHrO5LcAaQTW+ptDmr0fmaVyoTxgHw== -"@changesets/write@^0.1.5": - version "0.1.5" - resolved "https://registry.npmjs.org/@changesets/write/-/write-0.1.5.tgz#97574d95c8e48c3bbb1173802672f9a64d1b7fef" - integrity sha512-AYVSCH7on/Cyzo/8lVfqlsXmyKl3JhbNu9yHApdLPhHAzv5wqoHiZlMDkmd+AA67SRqzK2lDs4BcIojK+uWeIA== +"@changesets/write@^0.1.6": + version "0.1.6" + resolved "https://registry.npmjs.org/@changesets/write/-/write-0.1.6.tgz#798d882bada93f391902a854a17965f3b80a5201" + integrity sha512-JWE2gJs9eHhorxqembkf43fllKlCz+sp1TJKSheaWfhWILMHPdfa/xQG4+sMZkISo1qZ+IlJyiBLha6iGGjXyA== dependencies: "@babel/runtime" "^7.10.4" - "@changesets/types" "^4.0.1" + "@changesets/types" "^4.0.2" fs-extra "^7.0.1" human-id "^1.0.2" prettier "^1.19.1" @@ -3583,17 +3477,6 @@ find-up "^4.1.0" fs-extra "^8.1.0" -"@manypkg/get-packages@^1.0.1": - version "1.1.1" - resolved "https://registry.npmjs.org/@manypkg/get-packages/-/get-packages-1.1.1.tgz#7c7e72d0061ab2e61d2ce4da58ce91290a60ac8d" - integrity sha512-J6VClfQSVgR6958eIDTGjfdCrELy1eT+SHeoSMomnvRQVktZMnEA5edIr5ovRFNw5y+Bk/jyoevPzGYod96mhw== - dependencies: - "@babel/runtime" "^7.5.5" - "@manypkg/find-root" "^1.1.0" - fs-extra "^8.1.0" - globby "^11.0.0" - read-yaml-file "^1.1.0" - "@manypkg/get-packages@^1.1.3": version "1.1.3" resolved "https://registry.npmjs.org/@manypkg/get-packages/-/get-packages-1.1.3.tgz#e184db9bba792fa4693de4658cfb1463ac2c9c47" @@ -4543,13 +4426,13 @@ react-use "^17.2.4" "@roadiehq/backstage-plugin-travis-ci@^1.3.2": - version "1.3.3" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-travis-ci/-/backstage-plugin-travis-ci-1.3.3.tgz#317c9280d8dd404794ad5aa057ce457bfd459706" - integrity sha512-f5RhuG681iwiRa9/WvwhV4pI0KHv6oAHlgOXG3/pbOcONN9w9RaQIITgTyc6hpm9MzAkFQWV8qc3yPFcojza+A== + version "1.3.6" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-travis-ci/-/backstage-plugin-travis-ci-1.3.6.tgz#6f45a42bdf39aa6baab56f0c4400990238df1625" + integrity sha512-th+2GaOjkPArDUbTBuhhCz/6WL4gcrVRVAsDHzuSrrJqNtsz6kXdBIHhR/58En16BZ2bnHhRzY87uiUDLjAntA== dependencies: "@backstage/catalog-model" "^0.9.7" "@backstage/core-components" "^0.8.0" - "@backstage/core-plugin-api" "^0.4.0" + "@backstage/core-plugin-api" "^0.6.0" "@backstage/plugin-catalog-react" "^0.6.5" "@backstage/theme" "^0.2.9" "@material-ui/core" "^4.11.3" @@ -5177,15 +5060,7 @@ dependencies: "@babel/types" "^7.3.0" -"@types/body-parser@*", "@types/body-parser@^1.19.0": - version "1.19.1" - resolved "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz#0c0174c42a7d017b818303d4b5d969cb0b75929c" - integrity sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg== - dependencies: - "@types/connect" "*" - "@types/node" "*" - -"@types/body-parser@1.19.2": +"@types/body-parser@*", "@types/body-parser@1.19.2", "@types/body-parser@^1.19.0": version "1.19.2" resolved "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== @@ -5415,17 +5290,10 @@ "@types/docker-modem" "*" "@types/node" "*" -"@types/dompurify@^2.1.0": - version "2.3.1" - resolved "https://registry.npmjs.org/@types/dompurify/-/dompurify-2.3.1.tgz#2934adcd31c4e6b02676f9c22f9756e5091c04dd" - integrity sha512-YJth9qa0V/E6/XPH1Jq4BC8uCMmO8V1fKWn8PCvuZcAhMn7q0ez9LW6naQT04UZzjFfAPhyRMZmI2a2rbMlEFA== - dependencies: - "@types/trusted-types" "*" - -"@types/dompurify@^2.2.2": - version "2.2.3" - resolved "https://registry.npmjs.org/@types/dompurify/-/dompurify-2.2.3.tgz#6e89677a07902ac1b6821c345f34bd85da239b08" - integrity sha512-CLtc2mZK8+axmrz1JqtpklO/Kvn38arGc8o1l3UVopZaXXuer9ONdZwJ/9f226GrhRLtUmLr9WrvZsRSNpS8og== +"@types/dompurify@^2.1.0", "@types/dompurify@^2.2.2": + version "2.3.3" + resolved "https://registry.npmjs.org/@types/dompurify/-/dompurify-2.3.3.tgz#c24c92f698f77ed9cc9d9fa7888f90cf2bfaa23f" + integrity sha512-nnVQSgRVuZ/843oAfhA25eRSNzUFcBPk/LOiw5gm8mD9/X7CNcbRkQu/OsjCewO8+VIYfPxUnXvPEVGenw14+w== dependencies: "@types/trusted-types" "*" @@ -5501,17 +5369,7 @@ "@types/express" "*" "@types/xml2js" "*" -"@types/express@*", "@types/express@^4.17.6": - version "4.17.12" - resolved "https://registry.npmjs.org/@types/express/-/express-4.17.12.tgz#4bc1bf3cd0cfe6d3f6f2853648b40db7d54de350" - integrity sha512-pTYas6FrP15B1Oa0bkN5tQMNqOcVXa9j4FTFtO8DWI9kppKib+6NJtfTOOLcwxuuYvcX2+dVG6et1SxW/Kc17Q== - dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.18" - "@types/qs" "*" - "@types/serve-static" "*" - -"@types/express@4.17.13": +"@types/express@*", "@types/express@4.17.13", "@types/express@^4.17.6": version "4.17.13" resolved "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== @@ -5639,6 +5497,13 @@ "@types/through" "*" rxjs "^7.2.0" +"@types/is-ci@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@types/is-ci/-/is-ci-3.0.0.tgz#7e8910af6857601315592436f030aaa3ed9783c3" + integrity sha512-Q0Op0hdWbYd1iahB+IFNQcWXFq4O0Q5MwQP7uN0souuQ4rPg1vEYcnIOfr1gY+M+6rc8FGoRaBO1mOOvL29sEQ== + dependencies: + ci-info "^3.1.0" + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.1" resolved "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" @@ -5928,9 +5793,9 @@ "@types/passport-oauth2" "*" "@types/passport-google-oauth20@^2.0.3": - version "2.0.7" - resolved "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.7.tgz#0d97b7a886a0c0d2158682145cd949b29f8efe86" - integrity sha512-0HPVSqDmOWk5fRLb+bqGal+6iWsERiEco/Mli77yy5NEy22IfkoRoqZTSZ8UtXDWY9DCZlpS1Jqq56iWx2torw== + version "2.0.11" + resolved "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.11.tgz#271ec71de3030a3e1c004b24e633e4b298ccba97" + integrity sha512-9XMT1GfwhZL7UQEiCepLef55RNPHkbrCtsU7rsWPTEOsmu5qVIW8nSemtB4p+P24CuOhA+IKkv8LsPThYghGww== dependencies: "@types/express" "*" "@types/passport" "*" @@ -6474,9 +6339,9 @@ integrity sha512-qRyuv+P/1t1JK1rA+elmK1MmCL1BapEzKKfbEhDBV/LMMse4lmhZ/XbgETI39JveDJRpLjmToOI6uFtMW/WR2g== "@types/zen-observable@^0.8.0", "@types/zen-observable@^0.8.2": - version "0.8.2" - resolved "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.2.tgz#808c9fa7e4517274ed555fa158f2de4b4f468e71" - integrity sha512-HrCIVMLjE1MOozVoD86622S7aunluLb2PJdPfb3nYiEtohm8mIB/vyv0Fd37AdeMFrTUQXEunw78YloMA3Qilg== + version "0.8.3" + resolved "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.3.tgz#781d360c282436494b32fe7d9f7f8e64b3118aa3" + integrity sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw== "@typescript-eslint/eslint-plugin@^5.9.0": version "5.9.0" @@ -6936,13 +6801,6 @@ anafanafo@2.0.0: dependencies: char-width-table-consumer "^1.0.0" -ansi-align@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" - integrity sha1-w2rsy6VjuJzrVW82kPCx2eNUf38= - dependencies: - string-width "^2.0.0" - ansi-align@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" @@ -7947,19 +7805,6 @@ bottleneck@^2.15.3: resolved "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz#5df0b90f59fd47656ebe63c78a98419205cadd91" integrity sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw== -boxen@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" - integrity sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw== - dependencies: - ansi-align "^2.0.0" - camelcase "^4.0.0" - chalk "^2.0.1" - cli-boxes "^1.0.0" - string-width "^2.0.0" - term-size "^1.2.0" - widest-line "^2.0.0" - boxen@^4.2.0: version "4.2.0" resolved "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64" @@ -8352,11 +8197,6 @@ camelcase@^3.0.0: resolved "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= -camelcase@^4.0.0: - version "4.1.0" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= - camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" @@ -8429,7 +8269,7 @@ chainsaw@~0.1.0: dependencies: traverse ">=0.3.0 <0.4" -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -8601,10 +8441,10 @@ ci-info@^2.0.0: resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== -ci-info@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.1.1.tgz#9a32fcefdf7bcdb6f0a7e1c0f8098ec57897b80a" - integrity sha512-kdRWLBIJwdsYJWYJFtAFFYxybguqeF91qpZaggjG5Nf8QKdizFG2hjqvaTXbxFIcYbSaD74KpAXv6BSm17DHEQ== +ci-info@^3.1.0, ci-info@^3.2.0: + version "3.3.0" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz#b4ed1fb6818dea4803a55c623041f9165d2066b2" + integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" @@ -8658,11 +8498,6 @@ clean-stack@^2.0.0: resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== -cli-boxes@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" - integrity sha1-T6kXw+WclKAEzWH47lCdplFocUM= - cli-boxes@^2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" @@ -9532,7 +9367,7 @@ cross-fetch@^3.0.4, cross-fetch@^3.0.6, cross-fetch@^3.1.3, cross-fetch@^3.1.4: dependencies: node-fetch "2.6.7" -cross-spawn@^5.0.1, cross-spawn@^5.1.0: +cross-spawn@^5.1.0: version "5.1.0" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= @@ -10829,30 +10664,6 @@ elliptic@^6.0.0: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" -"embedded-techdocs-app@file:packages/embedded-techdocs-app": - version "0.2.62-next.0" - dependencies: - "@backstage/app-defaults" "^0.1.6-next.0" - "@backstage/catalog-model" "^0.9.10" - "@backstage/cli" "^0.13.1-next.0" - "@backstage/config" "^0.1.13" - "@backstage/core-app-api" "^0.5.1" - "@backstage/core-components" "^0.8.7-next.0" - "@backstage/core-plugin-api" "^0.6.0" - "@backstage/integration-react" "^0.1.20-next.0" - "@backstage/plugin-catalog" "^0.7.11-next.0" - "@backstage/plugin-techdocs" "^0.13.2-next.0" - "@backstage/test-utils" "^0.2.3" - "@backstage/theme" "^0.2.14" - "@material-ui/core" "^4.11.0" - "@material-ui/icons" "^4.9.1" - history "^5.0.0" - react "^17.0.2" - react-dom "^17.0.2" - react-router "6.0.0-beta.0" - react-router-dom "6.0.0-beta.0" - react-use "^17.2.4" - emittery@^0.7.1: version "0.7.1" resolved "https://registry.npmjs.org/emittery/-/emittery-0.7.1.tgz#c02375a927a40948c0345cc903072597f5270451" @@ -11627,52 +11438,54 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: safe-buffer "^5.1.1" "example-app@file:packages/app": - version "0.2.63-next.0" + version "0.2.63" dependencies: - "@backstage/app-defaults" "^0.1.6-next.0" + "@backstage/app-defaults" "^0.1.6" "@backstage/catalog-model" "^0.9.10" - "@backstage/cli" "^0.13.1-next.0" - "@backstage/core-app-api" "^0.5.1" - "@backstage/core-components" "^0.8.7-next.0" + "@backstage/cli" "^0.13.1" + "@backstage/core-app-api" "^0.5.2" + "@backstage/core-components" "^0.8.7" "@backstage/core-plugin-api" "^0.6.0" - "@backstage/integration-react" "^0.1.20-next.0" - "@backstage/plugin-airbrake" "^0.1.2-next.0" - "@backstage/plugin-apache-airflow" "^0.1.5-next.0" - "@backstage/plugin-api-docs" "^0.7.1-next.0" - "@backstage/plugin-azure-devops" "^0.1.13-next.0" - "@backstage/plugin-badges" "^0.2.21-next.0" - "@backstage/plugin-catalog" "^0.7.11-next.0" - "@backstage/plugin-catalog-graph" "^0.2.9-next.0" - "@backstage/plugin-catalog-import" "^0.8.0-next.0" - "@backstage/plugin-catalog-react" "^0.6.13-next.0" - "@backstage/plugin-circleci" "^0.2.36-next.0" - "@backstage/plugin-cloudbuild" "^0.2.34-next.0" - "@backstage/plugin-code-coverage" "^0.1.24-next.0" - "@backstage/plugin-cost-insights" "^0.11.19-next.0" - "@backstage/plugin-explore" "^0.3.28-next.0" - "@backstage/plugin-gcp-projects" "^0.3.16-next.0" - "@backstage/plugin-github-actions" "^0.4.34-next.0" - "@backstage/plugin-gocd" "^0.1.3-next.0" - "@backstage/plugin-graphiql" "^0.2.29-next.0" - "@backstage/plugin-home" "^0.4.13-next.0" - "@backstage/plugin-jenkins" "^0.5.19-next.0" - "@backstage/plugin-kafka" "^0.2.27-next.0" - "@backstage/plugin-kubernetes" "^0.5.6-next.0" - "@backstage/plugin-lighthouse" "^0.2.36-next.0" - "@backstage/plugin-newrelic" "^0.3.15-next.0" - "@backstage/plugin-newrelic-dashboard" "^0.1.5-next.0" - "@backstage/plugin-org" "^0.4.1-next.0" - "@backstage/plugin-pagerduty" "0.3.24-next.0" - "@backstage/plugin-rollbar" "^0.3.25-next.0" - "@backstage/plugin-scaffolder" "^0.12.1-next.0" - "@backstage/plugin-search" "^0.6.1-next.0" - "@backstage/plugin-sentry" "^0.3.35-next.0" - "@backstage/plugin-shortcuts" "^0.1.21-next.0" - "@backstage/plugin-tech-insights" "^0.1.7-next.0" - "@backstage/plugin-tech-radar" "^0.5.4-next.0" - "@backstage/plugin-techdocs" "^0.13.2-next.0" - "@backstage/plugin-todo" "^0.1.21-next.0" - "@backstage/plugin-user-settings" "^0.3.18-next.0" + "@backstage/integration-react" "^0.1.20" + "@backstage/plugin-airbrake" "^0.1.2" + "@backstage/plugin-apache-airflow" "^0.1.5" + "@backstage/plugin-api-docs" "^0.7.1" + "@backstage/plugin-azure-devops" "^0.1.13" + "@backstage/plugin-badges" "^0.2.21" + "@backstage/plugin-catalog" "^0.7.11" + "@backstage/plugin-catalog-common" "^0.1.2" + "@backstage/plugin-catalog-graph" "^0.2.9" + "@backstage/plugin-catalog-import" "^0.8.0" + "@backstage/plugin-catalog-react" "^0.6.13" + "@backstage/plugin-circleci" "^0.2.36" + "@backstage/plugin-cloudbuild" "^0.2.34" + "@backstage/plugin-code-coverage" "^0.1.24" + "@backstage/plugin-cost-insights" "^0.11.19" + "@backstage/plugin-explore" "^0.3.28" + "@backstage/plugin-gcp-projects" "^0.3.16" + "@backstage/plugin-github-actions" "^0.4.34" + "@backstage/plugin-gocd" "^0.1.3" + "@backstage/plugin-graphiql" "^0.2.29" + "@backstage/plugin-home" "^0.4.13" + "@backstage/plugin-jenkins" "^0.5.19" + "@backstage/plugin-kafka" "^0.2.27" + "@backstage/plugin-kubernetes" "^0.5.6" + "@backstage/plugin-lighthouse" "^0.2.36" + "@backstage/plugin-newrelic" "^0.3.15" + "@backstage/plugin-newrelic-dashboard" "^0.1.5" + "@backstage/plugin-org" "^0.4.1" + "@backstage/plugin-pagerduty" "0.3.24" + "@backstage/plugin-permission-react" "^0.3.0" + "@backstage/plugin-rollbar" "^0.3.25" + "@backstage/plugin-scaffolder" "^0.12.1" + "@backstage/plugin-search" "^0.6.1" + "@backstage/plugin-sentry" "^0.3.35" + "@backstage/plugin-shortcuts" "^0.1.21" + "@backstage/plugin-tech-insights" "^0.1.7" + "@backstage/plugin-tech-radar" "^0.5.4" + "@backstage/plugin-techdocs" "^0.13.2" + "@backstage/plugin-todo" "^0.1.21" + "@backstage/plugin-user-settings" "^0.3.18" "@backstage/search-common" "^0.2.2" "@backstage/theme" "^0.2.14" "@material-ui/core" "^4.12.2" @@ -11743,19 +11556,6 @@ execa@5.1.1, execa@^5.0.0, execa@^5.1.1: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - execa@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" @@ -12699,11 +12499,6 @@ get-stdin@^8.0.0: resolved "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53" integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg== -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= - get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -13149,9 +12944,9 @@ graphql-sse@^1.0.1: integrity sha512-y2mVBN2KwNrzxX2KBncQ6kzc6JWvecxuBernrl0j65hsr6MAS3+Yn8PTFSOgRmtolxugepxveyZVQEuaNEbw3w== graphql-tag@^2.11.0: - version "2.12.4" - resolved "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.4.tgz#d34066688a4f09e72d6f4663c74211e9b4b7c4bf" - integrity sha512-VV1U4O+9x99EkNpNmCUV5RZwq6MnK4+pGbRYWG+lA/m3uo7TSqJF81OkcOP148gFP6fzdl7JWYBrwWVTS9jXww== + version "2.12.6" + resolved "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1" + integrity sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg== dependencies: tslib "^2.1.0" @@ -13762,9 +13557,9 @@ ignore@^5.1.4, ignore@^5.1.8, ignore@^5.2.0: integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== immer@^9.0.1, immer@^9.0.7: - version "9.0.7" - resolved "https://registry.npmjs.org/immer/-/immer-9.0.7.tgz#b6156bd7db55db7abc73fd2fdadf4e579a701075" - integrity sha512-KGllzpbamZDvOIxnmJ0jI840g7Oikx58lBPWV0hUh7dtAyZpFqqrBZdKka5GlTwMTZ1Tjc/bKKW4VSFAt6BqMA== + version "9.0.12" + resolved "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz#2d33ddf3ee1d247deab9d707ca472c8c942a0f20" + integrity sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA== immutable@^3.x.x: version "3.8.2" @@ -13919,7 +13714,7 @@ inline-style-prefixer@^6.0.0: dependencies: css-in-js-utils "^2.0.0" -inquirer@^7.0.4, inquirer@^7.3.3: +inquirer@^7.3.3: version "7.3.3" resolved "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== @@ -13938,27 +13733,7 @@ inquirer@^7.0.4, inquirer@^7.3.3: strip-ansi "^6.0.0" through "^2.3.6" -inquirer@^8.0.0: - version "8.1.5" - resolved "https://registry.npmjs.org/inquirer/-/inquirer-8.1.5.tgz#2dc5159203c826d654915b5fe6990fd17f54a150" - integrity sha512-G6/9xUqmt/r+UvufSyrPpt84NYwhKZ9jLsgMbQzlx804XErNupor8WQdBnBRrXmBfTPpuwf1sV+ss2ovjgdXIg== - dependencies: - ansi-escapes "^4.2.1" - chalk "^4.1.1" - cli-cursor "^3.1.0" - cli-width "^3.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.21" - mute-stream "0.0.8" - ora "^5.4.1" - run-async "^2.4.0" - rxjs "^7.2.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - through "^2.3.6" - -inquirer@^8.1.1, inquirer@^8.2.0: +inquirer@^8.0.0, inquirer@^8.1.1, inquirer@^8.2.0: version "8.2.0" resolved "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz#f44f008dd344bbfc4b30031f45d984e034a3ac3a" integrity sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ== @@ -14151,12 +13926,12 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-ci@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/is-ci/-/is-ci-3.0.0.tgz#c7e7be3c9d8eef7d0fa144390bd1e4b88dc4c994" - integrity sha512-kDXyttuLeslKAHYL/K28F2YkM3x5jvFPEw3yXbRptXydjD9rpLEz+C5K5iutY9ZiUu6AP41JdvRQwF4Iqs4ZCQ== +is-ci@^3.0.0, is-ci@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867" + integrity sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ== dependencies: - ci-info "^3.1.1" + ci-info "^3.2.0" is-core-module@^2.1.0, is-core-module@^2.2.0: version "2.8.0" @@ -15811,9 +15586,9 @@ keyv@^3.0.0: json-buffer "3.0.0" keyv@^4.0.0, keyv@^4.0.3: - version "4.0.5" - resolved "https://registry.npmjs.org/keyv/-/keyv-4.0.5.tgz#bb12b467aba372fab2a44d4420c00d3c4ebd484c" - integrity sha512-531pkGLqV3BMg0eDqqJFI0R1mkK1Nm5xIP2mM6keP5P8WfFtCkg2IOwplTUmlGoTgIg9yQYZ/kdihhz89XH3vA== + version "4.1.0" + resolved "https://registry.npmjs.org/keyv/-/keyv-4.1.0.tgz#8ab5ca4ae6a34e05c629531d9a7f871575af0d5b" + integrity sha512-YsY3wr6HabE11/sscee+3nZ03XjvkrPWGouAmJFBdZoK92wiOlJCzI5/sDEIKdJhdhHO144ei45U9gXfbu14Uw== dependencies: json-buffer "3.0.1" @@ -21183,13 +20958,13 @@ replace-ext@^1.0.0: integrity sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw== replace-in-file@^6.0.0: - version "6.1.0" - resolved "https://registry.npmjs.org/replace-in-file/-/replace-in-file-6.1.0.tgz#9f9ddd7bb70d6ad231d2ad692e1b646e73d06647" - integrity sha512-URzjyF3nucvejuY13HFd7O+Q6tFJRLKGHLYVvSh+LiZj3gFXzSYGnIkQflnJJulCAI2/RTZaZkpOtdVdW0EhQA== + version "6.3.2" + resolved "https://registry.npmjs.org/replace-in-file/-/replace-in-file-6.3.2.tgz#0f19835137177c89932f45df319f3539a019484f" + integrity sha512-Dbt5pXKvFVPL3WAaEB3ZX+95yP0CeAtIPJDwYzHbPP5EAHn+0UoegH/Wg3HKflU9dYBH8UnBC2NvY3P+9EZtTg== dependencies: - chalk "^4.0.0" - glob "^7.1.6" - yargs "^15.3.1" + chalk "^4.1.2" + glob "^7.2.0" + yargs "^17.2.1" replaceall@^0.1.6: version "0.1.6" @@ -21558,14 +21333,7 @@ rxjs@^6.3.3, rxjs@^6.4.0, rxjs@^6.6.0, rxjs@^6.6.3: dependencies: tslib "^1.9.0" -rxjs@^7.1.0, rxjs@^7.2.0: - version "7.3.0" - resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.3.0.tgz#39fe4f3461dc1e50be1475b2b85a0a88c1e938c6" - integrity sha512-p2yuGIg9S1epc3vrjKf6iVb3RCaAYjYskkO+jHIaV0IjOPlJop4UnodOoFb2xeNwlguqLYvGw1b1McillYb5Gw== - dependencies: - tslib "~2.1.0" - -rxjs@^7.5.1: +rxjs@^7.1.0, rxjs@^7.2.0, rxjs@^7.5.1: version "7.5.2" resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.5.2.tgz#11e4a3a1dfad85dbf7fb6e33cbba17668497490b" integrity sha512-PwDt186XaL3QN5qXj/H9DGyHhP3/RYYgZZwqBv9Tv8rsAaiwFH1IsJJlcgD37J7UW5a6O67qX0KWKS3/pu0m4w== @@ -21997,9 +21765,9 @@ simple-concat@^1.0.0: integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== simple-get@^3.0.2, simple-get@^3.0.3: - version "3.1.0" - resolved "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3" - integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA== + version "3.1.1" + resolved "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz#cc7ba77cfbe761036fbfce3d021af25fc5584d55" + integrity sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA== dependencies: decompress-response "^4.2.0" once "^1.3.1" @@ -22633,7 +22401,7 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2", string-width@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -22650,16 +22418,7 @@ string-width@^3.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: - version "4.2.0" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" - -string-width@^4.2.3: +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -23085,6 +22844,11 @@ swap-case@^2.0.2: dependencies: tslib "^2.0.3" +swr@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/swr/-/swr-1.1.2.tgz#9f3de2541931fccf03c48f322f1fc935a7551612" + integrity sha512-UsM0eo5T+kRPyWFZtWRx2XR5qzohs/LS4lDC0GCyLpCYFmsfTk28UCVDbOE9+KtoXY4FnwHYiF+ZYEU3hnJ1lQ== + symbol-observable@1.2.0, symbol-observable@^1.0.4, symbol-observable@^1.1.0, symbol-observable@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" @@ -23198,6 +22962,30 @@ tdigest@^0.1.1: dependencies: bintrees "1.0.1" +"techdocs-cli-embedded-app@file:packages/techdocs-cli-embedded-app": + version "0.2.62" + dependencies: + "@backstage/app-defaults" "^0.1.6" + "@backstage/catalog-model" "^0.9.10" + "@backstage/cli" "^0.13.1" + "@backstage/config" "^0.1.13" + "@backstage/core-app-api" "^0.5.2" + "@backstage/core-components" "^0.8.7" + "@backstage/core-plugin-api" "^0.6.0" + "@backstage/integration-react" "^0.1.20" + "@backstage/plugin-catalog" "^0.7.11" + "@backstage/plugin-techdocs" "^0.13.2" + "@backstage/test-utils" "^0.2.4" + "@backstage/theme" "^0.2.14" + "@material-ui/core" "^4.11.0" + "@material-ui/icons" "^4.9.1" + history "^5.0.0" + react "^17.0.2" + react-dom "^17.0.2" + react-router "6.0.0-beta.0" + react-router-dom "6.0.0-beta.0" + react-use "^17.2.4" + teeny-request@^7.0.0: version "7.0.1" resolved "https://registry.npmjs.org/teeny-request/-/teeny-request-7.0.1.tgz#bdd41fdffea5f8fbc0d29392cb47bec4f66b2b4c" @@ -23232,13 +23020,6 @@ temp@^0.8.4: dependencies: rimraf "~2.6.2" -term-size@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" - integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk= - dependencies: - execa "^0.7.0" - term-size@^2.1.0: version "2.2.0" resolved "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz#1f16adedfe9bdc18800e1776821734086fcc6753" @@ -23693,12 +23474,7 @@ tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@~2.3.0: - version "2.3.0" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" - integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== - -tslib@^2.3.0: +tslib@^2, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@~2.3.0: version "2.3.1" resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== @@ -24842,13 +24618,6 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.2 || 2" -widest-line@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" - integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== - dependencies: - string-width "^2.1.1" - widest-line@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" @@ -25207,10 +24976,10 @@ yargs@^16.1.1, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.0.0, yargs@^17.0.1, yargs@^17.1.1, yargs@^17.3.0: - version "17.3.0" - resolved "https://registry.npmjs.org/yargs/-/yargs-17.3.0.tgz#295c4ffd0eef148ef3e48f7a2e0f58d0e4f26b1c" - integrity sha512-GQl1pWyDoGptFPJx9b9L6kmR33TGusZvXIZUT+BOz9f7X2L94oeAskFYLEg/FkhV06zZPBYLvLZRWeYId29lew== +yargs@^17.0.0, yargs@^17.0.1, yargs@^17.1.1, yargs@^17.2.1, yargs@^17.3.0: + version "17.3.1" + resolved "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz#da56b28f32e2fd45aefb402ed9c26f42be4c07b9" + integrity sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA== dependencies: cliui "^7.0.2" escalade "^3.1.1"