diff --git a/.changeset/afraid-flies-try.md b/.changeset/afraid-flies-try.md new file mode 100644 index 0000000000..15d2e3942c --- /dev/null +++ b/.changeset/afraid-flies-try.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-cost-insights': patch +--- + +Move cost-insights data specific API types (non react) into an @backstage/plugin-cost-insights-common +isomorphic package. This allows these types to be shared in any backend packages or other cost-insight +modules. diff --git a/.changeset/blue-monkeys-explain.md b/.changeset/blue-monkeys-explain.md new file mode 100644 index 0000000000..69382ff11d --- /dev/null +++ b/.changeset/blue-monkeys-explain.md @@ -0,0 +1,6 @@ +--- +'@backstage/create-app': patch +--- + +Adds the ability to define the Backstage app name using a `BACKSTAGE_APP_NAME` +environment variable when running `create-app`. diff --git a/.changeset/bright-balloons-hide.md b/.changeset/bright-balloons-hide.md new file mode 100644 index 0000000000..5163e72dc1 --- /dev/null +++ b/.changeset/bright-balloons-hide.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Change BackstageIconLinkVertical style to use pallette instead of explicit color diff --git a/.changeset/cool-toys-flow.md b/.changeset/cool-toys-flow.md new file mode 100644 index 0000000000..799bf3ace4 --- /dev/null +++ b/.changeset/cool-toys-flow.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': minor +--- + +Add `transformLinkUri` and `transformImageUri` to `MarkdownContent` diff --git a/.changeset/create-app-1656408352.md b/.changeset/create-app-1656408352.md new file mode 100644 index 0000000000..b50d431d4b --- /dev/null +++ b/.changeset/create-app-1656408352.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Bumped create-app version. diff --git a/.changeset/cuddly-flowers-provide.md b/.changeset/cuddly-flowers-provide.md new file mode 100644 index 0000000000..729ac96cda --- /dev/null +++ b/.changeset/cuddly-flowers-provide.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-fossa': patch +--- + +Allow configuration of base URL for Fossa links diff --git a/.changeset/eight-suits-fail.md b/.changeset/eight-suits-fail.md new file mode 100644 index 0000000000..742154da91 --- /dev/null +++ b/.changeset/eight-suits-fail.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-kubernetes-backend': patch +'@backstage/plugin-kubernetes-common': patch +--- + +Fixed the lack of `limitranges` as part of the Default Objects to fetch from the kubernetes api diff --git a/.changeset/eighty-windows-brush.md b/.changeset/eighty-windows-brush.md new file mode 100644 index 0000000000..753b53fbb4 --- /dev/null +++ b/.changeset/eighty-windows-brush.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-tech-insights-backend': minor +--- + +Allow FactRetrieverRegistry to be injected into buildTechInsightsContext so that we can override default registry implementation. diff --git a/.changeset/five-fireants-run.md b/.changeset/five-fireants-run.md new file mode 100644 index 0000000000..589d46cc81 --- /dev/null +++ b/.changeset/five-fireants-run.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Fix the EntityLayout header style so that EntityContextMenu button can display in correct shape when user hover on it diff --git a/.changeset/forty-seals-complain.md b/.changeset/forty-seals-complain.md new file mode 100644 index 0000000000..b2435b2d3a --- /dev/null +++ b/.changeset/forty-seals-complain.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Improve error messaging when passing in malformed auth diff --git a/.changeset/great-roses-pump.md b/.changeset/great-roses-pump.md index 16a49bd464..0e15d186d4 100644 --- a/.changeset/great-roses-pump.md +++ b/.changeset/great-roses-pump.md @@ -4,7 +4,7 @@ Previously, the color of the Entity Context Menu (in the Entity Page Header) was hardcoded as `white`. -This was an issue for themes that use a header with a white background. By default, the color of the icon is now `theme.palette.bursts.fontColor`. +This was an issue for themes that use a header with a white background. By default, the color of the icon is now `theme.page.fontColor`. It can now also be overridden in the theme, which is only necessary if the header title, subtitle and three-dots icon need to have different colors. For example: diff --git a/.changeset/hot-rice-sin.md b/.changeset/hot-rice-sin.md new file mode 100644 index 0000000000..5a3d6fdb7a --- /dev/null +++ b/.changeset/hot-rice-sin.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': minor +--- + +Add `allowedRepos` `ui:option` to `RepoUrlPicker` component, and move `repoName` field to own component diff --git a/.changeset/light-hornets-eat.md b/.changeset/light-hornets-eat.md new file mode 100644 index 0000000000..795e51fb67 --- /dev/null +++ b/.changeset/light-hornets-eat.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-cost-insights-common': minor +--- + +Introduces a new isomorphic @backstage/plugin-cost-insight-common package to contain shared types across all other cost insights packages and modules. diff --git a/.changeset/little-geckos-end.md b/.changeset/little-geckos-end.md new file mode 100644 index 0000000000..328095aa44 --- /dev/null +++ b/.changeset/little-geckos-end.md @@ -0,0 +1,18 @@ +--- +'@backstage/plugin-kubernetes-backend': minor +--- + +Add new endpoints to Kubernetes backend plugin + +BREAKING: Kubernetes backend plugin now depends on CatalogApi + +```typescript +// Create new CatalogClient +const catalogApi = new CatalogClient({ discoveryApi: env.discovery }); +const { router } = await KubernetesBuilder.createBuilder({ + logger: env.logger, + config: env.config, + // Inject it into createBuilder params + catalogApi, +}).build(); +``` diff --git a/.changeset/long-bananas-rescue.md b/.changeset/long-bananas-rescue.md new file mode 100644 index 0000000000..d990fd67c6 --- /dev/null +++ b/.changeset/long-bananas-rescue.md @@ -0,0 +1,91 @@ +--- +'@backstage/plugin-catalog-backend-module-msgraph': minor +--- + +Align `msgraph` plugin's entity provider config with other providers. **Deprecated** entity processor as well as previous config. + +You will see warning at the log output until you migrate to the new setup. +All deprecated parts will be removed eventually after giving some time to migrate. + +Please find information on how to migrate your current setup to the new one below. + +**Migration Guide:** + +There were two different way on how to use the msgraph plugin: processor or provider. + +Previous registration for the processor: + +```typescript +// packages/backend/src/plugins/catalog.ts +builder.addProcessor( + MicrosoftGraphOrgReaderProcessor.fromConfig(env.config, { + logger: env.logger, + // [...] + }), +); +``` + +Previous registration when using the provider: + +```typescript +// packages/backend/src/plugins/catalog.ts +builder.addEntityProvider( + MicrosoftGraphOrgEntityProvider.fromConfig(env.config, { + id: 'https://graph.microsoft.com/v1.0', + target: 'https://graph.microsoft.com/v1.0', + logger: env.logger, + schedule: env.scheduler.createScheduledTaskRunner({ + frequency: { minutes: 30 }, + timeout: { minutes: 3 }, + }), + // [...] + }), +); +``` + +Previous configuration as used for both: + +```yaml +# app-config.yaml +catalog: + processors: + microsoftGraphOrg: + providers: + - target: https://graph.microsoft.com/v1.0 + # [...] +``` + +**Replacement:** + +Please check https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-msgraph/README.md for the complete documentation of all configuration options (config as well as registration of the provider). + +```yaml +# app-config.yaml +catalog: + providers: + microsoftGraphOrg: + # In case you used the deprecated configuration with the entity provider + # using the value of `target` will keep the same location key for all + providerId: # some stable ID which will be used as part of the location key for all ingested data + target: https://graph.microsoft.com/v1.0 + # [...] +``` + +```typescript +// packages/backend/src/plugins/catalog.ts +builder.addEntityProvider( + MicrosoftGraphOrgEntityProvider.fromConfig(env.config, { + logger: env.logger, + schedule: env.scheduler.createScheduledTaskRunner({ + frequency: { minutes: 30 }, + timeout: { minutes: 3 }, + }), + // [...] + }), +); +``` + +In case you've used multiple entity providers before +**and** you had different transformers for each of them +you can provide these directly at the one `fromConfig` call +by passing a Record with the provider ID as key. diff --git a/.changeset/many-vans-thank.md b/.changeset/many-vans-thank.md new file mode 100644 index 0000000000..16f8c8a69b --- /dev/null +++ b/.changeset/many-vans-thank.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-jenkins': patch +'@backstage/plugin-jenkins-backend': patch +--- + +feature: added support for multiple branches to the `JenkinsApi` diff --git a/.changeset/metal-windows-share.md b/.changeset/metal-windows-share.md new file mode 100644 index 0000000000..b4443a620f --- /dev/null +++ b/.changeset/metal-windows-share.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-search-backend-module-pg': patch +--- + +**DEPRECATED**: `PgSearchEngine` static `from` has been deprecated and will be removed in a future release. Use static `fromConfig` method to instantiate. + +Added support for highlighting matched terms in search result data diff --git a/.changeset/moody-crabs-march.md b/.changeset/moody-crabs-march.md new file mode 100644 index 0000000000..b5ddf12ffa --- /dev/null +++ b/.changeset/moody-crabs-march.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-vault': patch +'@backstage/plugin-vault-backend': patch +--- + +Added a path notion in addition to secret name to allow to differentiate secrets in sub-paths diff --git a/.changeset/ninety-coats-learn.md b/.changeset/ninety-coats-learn.md new file mode 100644 index 0000000000..9d6945e9c0 --- /dev/null +++ b/.changeset/ninety-coats-learn.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Fix relative `sub-paths` by concatenating the app's base path with them. diff --git a/.changeset/old-onions-hear.md b/.changeset/old-onions-hear.md new file mode 100644 index 0000000000..82dcc09190 --- /dev/null +++ b/.changeset/old-onions-hear.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': minor +--- + +Update GitLab Merge Request Action to allow source branch to be deleted diff --git a/.changeset/plenty-clouds-guess.md b/.changeset/plenty-clouds-guess.md new file mode 100644 index 0000000000..cc56bd604d --- /dev/null +++ b/.changeset/plenty-clouds-guess.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +Added an option for the auth backend router to select the algorithm for the JWT token signing keys diff --git a/.changeset/polite-lions-sell.md b/.changeset/polite-lions-sell.md new file mode 100644 index 0000000000..07b5fcbd77 --- /dev/null +++ b/.changeset/polite-lions-sell.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +Auth provider now also export createAuthProviderIntegration diff --git a/.changeset/pre.json b/.changeset/pre.json index 6ea515cda8..7b30cba7ba 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -157,39 +157,100 @@ "@backstage/plugin-vault": "0.1.0", "@backstage/plugin-vault-backend": "0.1.0", "@backstage/plugin-xcmetrics": "0.2.26", - "@backstage/plugin-api-docs-module-protoc-gen-doc": "0.0.0" + "@backstage/plugin-api-docs-module-protoc-gen-doc": "0.0.0", + "@backstage/plugin-catalog-backend-module-openapi": "0.0.0", + "@backstage/plugin-cost-insights-common": "0.0.0" }, "changesets": [ + "afraid-flies-try", "beige-horses-scream", + "blue-monkeys-explain", "breezy-poems-grab", "breezy-seas-exist", + "bright-balloons-hide", + "calm-experts-buy", "chilled-mirrors-grab", + "cool-toys-flow", + "create-app-1656408352", "curly-candles-battle", "curvy-weeks-matter", + "eight-suits-fail", + "eighty-windows-brush", "eleven-mice-collect", + "five-fireants-run", + "forty-seals-complain", "great-roses-pump", + "green-actors-argue", + "happy-boxes-melt", + "hot-rice-sin", "large-kangaroos-poke", + "lemon-goats-obey", + "light-hornets-eat", + "long-bananas-rescue", + "many-vans-thank", + "metal-singers-matter", + "metal-windows-share", "modern-ducks-lay", + "moody-crabs-march", "nasty-zoos-cross", "nervous-humans-sip", + "old-onions-hear", + "plenty-clouds-guess", "polite-eagles-invite", + "polite-lions-sell", + "popular-pots-yell", + "pretty-masks-live", + "proud-toys-return", "purple-beans-march", + "quiet-pens-notice", "red-games-decide", + "renovate-149779d", + "renovate-2ae4dda", + "renovate-4b5ff24", + "renovate-7438bff", + "renovate-833a91b", "renovate-9454dab", "rude-llamas-lie", + "search-boats-double", + "search-lightning-cult", + "search-turtles-itch", + "serious-houses-watch", + "serious-zebras-joke", "shaggy-melons-drive", + "sharp-numbers-taste", "sharp-planes-turn", + "shiny-seahorses-do", + "shiny-turkeys-doubt", + "short-deers-remember", "short-olives-train", + "shy-cameras-develop", + "silent-coats-brake", + "silly-geese-design", + "silver-needles-unite", + "smart-elephants-knock", "smooth-sheep-hide", + "strange-tables-flash", "strange-trains-collect", + "strong-lies-explain", "sweet-plants-sparkle", "tame-guests-wave", + "techdocs-eyes-sit", "techdocs-gorgeous-plants-sniff", + "techdocs-sheep-talk", + "techdocs-sixty-mugs-hug", "techdocs-the-whole-pulse", + "thick-cats-kiss", "thick-radios-drive", + "thirty-rivers-watch", + "tricky-ravens-visit", + "twelve-candles-jump", + "two-crews-accept", "unlucky-stingrays-juggle", "weak-bananas-deliver", + "weak-jeans-cry", + "weak-llamas-repeat", "wet-dolphins-act", - "wicked-icons-grin" + "wicked-icons-grin", + "wicked-ladybugs-argue" ] } diff --git a/.changeset/proud-toys-return.md b/.changeset/proud-toys-return.md new file mode 100644 index 0000000000..f93e6ef4a8 --- /dev/null +++ b/.changeset/proud-toys-return.md @@ -0,0 +1,5 @@ +--- +'@backstage/catalog-model': minor +--- + +Introduced `GroupDefaultParentEntityPolicy` to set a default group entity parent. diff --git a/.changeset/renovate-0546761.md b/.changeset/renovate-0546761.md new file mode 100644 index 0000000000..ed7b8b19a3 --- /dev/null +++ b/.changeset/renovate-0546761.md @@ -0,0 +1,103 @@ +--- +'@backstage/backend-common': patch +'@backstage/backend-test-utils': patch +'@backstage/catalog-client': patch +'@backstage/cli': patch +'@backstage/config-loader': patch +'@backstage/core-app-api': patch +'@backstage/core-components': patch +'@backstage/core-plugin-api': patch +'@backstage/integration-react': patch +'@backstage/integration': patch +'@backstage/release-manifests': patch +'@backstage/test-utils': patch +'@backstage/plugin-adr-backend': patch +'@backstage/plugin-adr': patch +'@backstage/plugin-airbrake-backend': patch +'@backstage/plugin-airbrake': patch +'@backstage/plugin-allure': patch +'@backstage/plugin-analytics-module-ga': patch +'@backstage/plugin-apache-airflow': patch +'@backstage/plugin-api-docs': patch +'@backstage/plugin-app-backend': patch +'@backstage/plugin-auth-backend': patch +'@backstage/plugin-auth-node': patch +'@backstage/plugin-azure-devops-backend': patch +'@backstage/plugin-azure-devops': patch +'@backstage/plugin-badges': patch +'@backstage/plugin-bitbucket-cloud-common': patch +'@backstage/plugin-bitrise': patch +'@backstage/plugin-catalog-backend-module-azure': patch +'@backstage/plugin-catalog-backend-module-bitbucket-cloud': patch +'@backstage/plugin-catalog-backend-module-bitbucket': patch +'@backstage/plugin-catalog-backend-module-gerrit': patch +'@backstage/plugin-catalog-backend-module-github': patch +'@backstage/plugin-catalog-backend-module-gitlab': patch +'@backstage/plugin-catalog-backend-module-msgraph': patch +'@backstage/plugin-catalog-backend': patch +'@backstage/plugin-catalog-graphql': patch +'@backstage/plugin-catalog-import': patch +'@backstage/plugin-circleci': patch +'@backstage/plugin-cloudbuild': patch +'@backstage/plugin-code-climate': patch +'@backstage/plugin-code-coverage-backend': patch +'@backstage/plugin-code-coverage': patch +'@backstage/plugin-codescene': patch +'@backstage/plugin-config-schema': patch +'@backstage/plugin-cost-insights': patch +'@backstage/plugin-dynatrace': patch +'@backstage/plugin-explore-react': patch +'@backstage/plugin-explore': patch +'@backstage/plugin-firehydrant': patch +'@backstage/plugin-fossa': patch +'@backstage/plugin-gcalendar': patch +'@backstage/plugin-gcp-projects': patch +'@backstage/plugin-git-release-manager': patch +'@backstage/plugin-github-actions': patch +'@backstage/plugin-github-deployments': patch +'@backstage/plugin-github-pull-requests-board': patch +'@backstage/plugin-gitops-profiles': patch +'@backstage/plugin-gocd': patch +'@backstage/plugin-graphiql': patch +'@backstage/plugin-graphql-backend': patch +'@backstage/plugin-home': patch +'@backstage/plugin-ilert': patch +'@backstage/plugin-jenkins-backend': patch +'@backstage/plugin-jenkins': patch +'@backstage/plugin-kafka': patch +'@backstage/plugin-kubernetes': patch +'@backstage/plugin-lighthouse': patch +'@backstage/plugin-newrelic': patch +'@backstage/plugin-org': patch +'@backstage/plugin-pagerduty': patch +'@backstage/plugin-periskop-backend': patch +'@backstage/plugin-periskop': patch +'@backstage/plugin-permission-backend': patch +'@backstage/plugin-permission-common': patch +'@backstage/plugin-permission-node': patch +'@backstage/plugin-rollbar-backend': patch +'@backstage/plugin-rollbar': patch +'@backstage/plugin-scaffolder-backend-module-cookiecutter': patch +'@backstage/plugin-scaffolder-backend': patch +'@backstage/plugin-scaffolder': patch +'@backstage/plugin-search': patch +'@backstage/plugin-sentry': patch +'@backstage/plugin-shortcuts': patch +'@backstage/plugin-sonarqube': patch +'@backstage/plugin-splunk-on-call': patch +'@backstage/plugin-stack-overflow': patch +'@backstage/plugin-tech-insights': patch +'@backstage/plugin-tech-radar': patch +'@backstage/plugin-techdocs-addons-test-utils': patch +'@backstage/plugin-techdocs-backend': patch +'@backstage/plugin-techdocs-module-addons-contrib': patch +'@backstage/plugin-techdocs': patch +'@backstage/plugin-todo-backend': patch +'@backstage/plugin-todo': patch +'@backstage/plugin-user-settings': patch +'@backstage/plugin-vault-backend': patch +'@backstage/plugin-vault': patch +'@backstage/plugin-xcmetrics': patch +--- + +Updated dependency `msw` to `^0.43.0`. diff --git a/.changeset/renovate-149779d.md b/.changeset/renovate-149779d.md new file mode 100644 index 0000000000..58d764485e --- /dev/null +++ b/.changeset/renovate-149779d.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kafka-backend': patch +--- + +Updated dependency `kafkajs` to `^2.0.0`. diff --git a/.changeset/renovate-2ae4dda.md b/.changeset/renovate-2ae4dda.md new file mode 100644 index 0000000000..2cedbcb9d7 --- /dev/null +++ b/.changeset/renovate-2ae4dda.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-openapi': patch +--- + +Updated dependency `openapi-types` to `^12.0.0`. diff --git a/.changeset/renovate-7438bff.md b/.changeset/renovate-7438bff.md new file mode 100644 index 0000000000..43a4ac5016 --- /dev/null +++ b/.changeset/renovate-7438bff.md @@ -0,0 +1,16 @@ +--- +'@backstage/backend-common': patch +'@backstage/backend-tasks': patch +'@backstage/backend-test-utils': patch +'@backstage/plugin-app-backend': patch +'@backstage/plugin-auth-backend': patch +'@backstage/plugin-bazaar-backend': patch +'@backstage/plugin-catalog-backend': patch +'@backstage/plugin-code-coverage-backend': patch +'@backstage/plugin-scaffolder-backend': patch +'@backstage/plugin-search-backend-module-pg': patch +'@backstage/plugin-tech-insights-backend': patch +'@backstage/plugin-techdocs-backend': patch +--- + +Updated dependency `knex` to `^2.0.0`. diff --git a/.changeset/renovate-833a91b.md b/.changeset/renovate-833a91b.md new file mode 100644 index 0000000000..15e23ec5ff --- /dev/null +++ b/.changeset/renovate-833a91b.md @@ -0,0 +1,7 @@ +--- +'@backstage/core-components': patch +'@backstage/plugin-codescene': patch +'@backstage/plugin-sonarqube': patch +--- + +Updated dependency `rc-progress` to `3.4.0`. diff --git a/.changeset/renovate-913f3dc.md b/.changeset/renovate-913f3dc.md new file mode 100644 index 0000000000..edb2f95356 --- /dev/null +++ b/.changeset/renovate-913f3dc.md @@ -0,0 +1,5 @@ +--- +'@backstage/config-loader': patch +--- + +Updated dependency `typescript-json-schema` to `^0.54.0`. diff --git a/.changeset/renovate-cbb545a.md b/.changeset/renovate-cbb545a.md new file mode 100644 index 0000000000..be423e8252 --- /dev/null +++ b/.changeset/renovate-cbb545a.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': patch +--- + +Updated dependency `@asyncapi/react-component` to `1.0.0-next.39`. diff --git a/.changeset/search-boats-double.md b/.changeset/search-boats-double.md new file mode 100644 index 0000000000..92fd372cb8 --- /dev/null +++ b/.changeset/search-boats-double.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-react': patch +--- + +Fix search pagination to reset page cursor also when a term is cleared. diff --git a/.changeset/search-lightning-cult.md b/.changeset/search-lightning-cult.md new file mode 100644 index 0000000000..79cd256e77 --- /dev/null +++ b/.changeset/search-lightning-cult.md @@ -0,0 +1,24 @@ +--- +'@backstage/plugin-search-backend-module-elasticsearch': minor +--- + +**BREAKING**: In order to remain interoperable with all currently supported +deployments of Elasticsearch, this package will now conditionally use either +the `@elastic/elasticsearch` or `@opensearch-project/opensearch` client when +communicating with your deployed cluster. + +If you do not rely on types exported from this package, or if you do not make +use of the `createElasticSearchClientOptions` or `newClient` methods on the +`ElasticSearchSearchEngine` class, then upgrading to this version should not +require any further action on your part. Everything will continue to work as it +always has. + +If you _do_ rely on either of the above methods or any underlying types, some +changes may be needed to your custom code. A type guard is now exported by this +package (`isOpenSearchCompatible(options)`), which you may use to help clarify +which client options are compatible with which client constructors. + +If you are using this package with the `search.elasticsearch.provider` set to +`aws`, and you are making use of the `newClient` method in particular, you may +wish to start using the `@opensearch-project/opensearch` client in your custom +code. diff --git a/.changeset/serious-houses-watch.md b/.changeset/serious-houses-watch.md new file mode 100644 index 0000000000..63d5253bcb --- /dev/null +++ b/.changeset/serious-houses-watch.md @@ -0,0 +1,7 @@ +--- +'@backstage/theme': patch +--- + +**DEPRECATED**: The `bursts` object from `BackstagePaletteAdditions` has been depreciated and will be removed in a future release + +The `genPageTheme` function now includes an optional options object with an optional `fontColor` which defaults to white if not provided. diff --git a/.changeset/shiny-seahorses-do.md b/.changeset/shiny-seahorses-do.md new file mode 100644 index 0000000000..06892900bf --- /dev/null +++ b/.changeset/shiny-seahorses-do.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-badges-backend': patch +--- + +Add missing installation instructions diff --git a/.changeset/short-deers-remember.md b/.changeset/short-deers-remember.md new file mode 100644 index 0000000000..7579e7773b --- /dev/null +++ b/.changeset/short-deers-remember.md @@ -0,0 +1,21 @@ +--- +'@backstage/backend-common': patch +'@backstage/integration': patch +'@backstage/plugin-adr': patch +'@backstage/plugin-catalog-backend': patch +'@backstage/plugin-catalog-import': patch +'@backstage/plugin-scaffolder': patch +'@backstage/plugin-scaffolder-backend': patch +'@backstage/plugin-techdocs': patch +'@backstage/plugin-techdocs-module-addons-contrib': patch +'@backstage/plugin-techdocs-node': patch +--- + +Upgrade git-url-parse to 12.0.0. + +Motivation for upgrade is transitively upgrading parse-url which is vulnerable +to several CVEs detected by Snyk. + +- SNYK-JS-PARSEURL-2935944 +- SNYK-JS-PARSEURL-2935947 +- SNYK-JS-PARSEURL-2936249 diff --git a/.changeset/silly-geese-design.md b/.changeset/silly-geese-design.md new file mode 100644 index 0000000000..d4f8de2510 --- /dev/null +++ b/.changeset/silly-geese-design.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-api-docs': patch +'@backstage/plugin-catalog': minor +--- + +Add hidden title column to catalog and API table to enable filtering by title. diff --git a/.changeset/silver-needles-unite.md b/.changeset/silver-needles-unite.md new file mode 100644 index 0000000000..b5fed7e615 --- /dev/null +++ b/.changeset/silver-needles-unite.md @@ -0,0 +1,26 @@ +--- +'@backstage/plugin-home': patch +--- + +Added support for customizing the time format used in the `HeaderWorldClock` component + +Here's an example of how this can be used in the `HomePage.tsx` found in `\packages\app\src\components\home` to change the clock to be in the 24hr time format: + +```diff ++const timeFormat: Intl.DateTimeFormatOptions = { ++ hour: '2-digit', ++ minute: '2-digit', ++ hour12: false, ++}; + +export const homePage = ( + +
} pageTitleOverride="Home"> ++ +
+ + + + + +``` diff --git a/.changeset/small-shoes-hide.md b/.changeset/small-shoes-hide.md new file mode 100644 index 0000000000..b1f95e9f2d --- /dev/null +++ b/.changeset/small-shoes-hide.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend-node': patch +--- + +Exports `MissingIndexError` that can be used by the search engines for better error handling when missing index. diff --git a/.changeset/smart-elephants-knock.md b/.changeset/smart-elephants-knock.md new file mode 100644 index 0000000000..7aed10a71e --- /dev/null +++ b/.changeset/smart-elephants-knock.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +The `test` command now ensures that all IO is flushed before exiting when printing `--help`. diff --git a/.changeset/techdocs-sixty-mugs-hug.md b/.changeset/techdocs-sixty-mugs-hug.md new file mode 100644 index 0000000000..a1a9e815a1 --- /dev/null +++ b/.changeset/techdocs-sixty-mugs-hug.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Fix: When docs are shown in an entity page under the docs tab the sidebars start overlapping with the header and tabs in the page when you scroll the documentation content. diff --git a/.changeset/ten-cobras-wash.md b/.changeset/ten-cobras-wash.md new file mode 100644 index 0000000000..81915d958d --- /dev/null +++ b/.changeset/ten-cobras-wash.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': minor +--- + +Allowed post method on /refresh path diff --git a/.changeset/tender-chicken-learn.md b/.changeset/tender-chicken-learn.md new file mode 100644 index 0000000000..bd95c5545f --- /dev/null +++ b/.changeset/tender-chicken-learn.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend': patch +--- + +If error is `MissingIndexError` we return a 400 response with a more clear error message. diff --git a/.changeset/tender-terms-flash.md b/.changeset/tender-terms-flash.md new file mode 100644 index 0000000000..ca5fdb3799 --- /dev/null +++ b/.changeset/tender-terms-flash.md @@ -0,0 +1,5 @@ +--- +'@backstage/integration': patch +--- + +Avoid double encoding of the file path in `getBitbucketServerDownloadUrl` diff --git a/.changeset/thick-cats-kiss.md b/.changeset/thick-cats-kiss.md new file mode 100644 index 0000000000..8817115ec3 --- /dev/null +++ b/.changeset/thick-cats-kiss.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Adding ability to customize the "unregister entity" menu item in the entity context menu on the entity page with options 'visible','hidden','disabled'.With this three new options, one can hide the "unregister entity" menu item from the list, disable or keep it enabled. + +The boolean input for "unregister entity" will be deprecated later in favour of the above three options. diff --git a/.changeset/thirty-rivers-watch.md b/.changeset/thirty-rivers-watch.md new file mode 100644 index 0000000000..d92343f365 --- /dev/null +++ b/.changeset/thirty-rivers-watch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': minor +--- + +Added two new scaffolder actions: `github:repo:create` and `github:repo:push` diff --git a/.changeset/tricky-ravens-visit.md b/.changeset/tricky-ravens-visit.md new file mode 100644 index 0000000000..8500c9b64e --- /dev/null +++ b/.changeset/tricky-ravens-visit.md @@ -0,0 +1,6 @@ +--- +'@backstage/core-components': patch +'@backstage/plugin-catalog': patch +--- + +Updated to remove usage of the `bursts` object in the theme palette diff --git a/.changeset/two-owls-cry.md b/.changeset/two-owls-cry.md new file mode 100644 index 0000000000..ca371781a1 --- /dev/null +++ b/.changeset/two-owls-cry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend-module-elasticsearch': patch +--- + +Throws `MissingIndexError` when no index of type exist. diff --git a/.changeset/weak-jeans-cry.md b/.changeset/weak-jeans-cry.md new file mode 100644 index 0000000000..79f419e3db --- /dev/null +++ b/.changeset/weak-jeans-cry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Add `allowArbitraryValues` to `ui:options` in `OwnedEntityPicker`, similar to `allowArbitraryValues` in `EntityPicker` diff --git a/.changeset/wicked-ladybugs-argue.md b/.changeset/wicked-ladybugs-argue.md new file mode 100644 index 0000000000..9a36cf17cb --- /dev/null +++ b/.changeset/wicked-ladybugs-argue.md @@ -0,0 +1,43 @@ +--- +'@backstage/plugin-catalog': patch +'@backstage/plugin-catalog-react': patch +--- + +Added new `EntityProcessingStatusPicker` that will filter for entities with orphans and/or errors. + +If you are using the default Catalog page this picker will be added automatically. For those who have customized their Catalog page you'll need to add this manually by doing something like this: + +```diff +... +import { + CatalogFilterLayout, + EntityTypePicker, + UserListPicker, + EntityTagPicker ++ EntityProcessingStatusPicker, +} from '@backstage/plugin-catalog-react'; +... +export const CustomCatalogPage = ({ + columns, + actions, + initiallySelectedFilter = 'owned', +}: CatalogPageProps) => { + return ( + ... + + + + + + ... +}; +``` diff --git a/.github/workflows/automate_merge_renovate_prs.yaml b/.github/workflows/automate_merge_renovate_prs.yaml deleted file mode 100644 index 8de488cf05..0000000000 --- a/.github/workflows/automate_merge_renovate_prs.yaml +++ /dev/null @@ -1,85 +0,0 @@ -name: Automate Merge Renovate PRs - -on: - workflow_dispatch: - schedule: - - cron: '*/10 * * * *' - -jobs: - diff: - runs-on: ubuntu-latest - steps: - - uses: actions/github-script@v6 - with: - script: | - const owner = "backstage"; - const repo = "backstage"; - const query = `{ - repository(owner: "backstage", name: "backstage") { - pullRequests(labels: ["dependencies"], last: 10, states: [OPEN]) { - nodes { - title - author { - login - } - number - mergeable - files(first: 1) { - nodes { - path - } - } - changedFiles - commits(last: 1) { - nodes { - commit { - statusCheckRollup { - state - } - } - } - } - reviewDecision - reviews(first: 10) { - nodes { - author { - login - } - } - } - } - } - } - }`; - - const date = new Date(); - if (date.getDay() === 2) { - console.log("Skipping auto merge because Tuesday is release day"); - return; - } - - const r = await github.graphql(query); - const mergable = r.repository.pullRequests.nodes.filter( - (pr) => - pr.author.login === "renovate" && - pr.mergeable === "MERGEABLE" && - pr.changedFiles === 1 && - pr.files.nodes[0].path.split("/").slice(-1)[0] === "yarn.lock" && - pr.commits.nodes[0].commit.statusCheckRollup.state === "SUCCESS" && - pr.reviewDecision === "APPROVED" - ); - - if (mergable.length === 0) { - console.log("no mergable PRs"); - return; - } - - for (const pr of mergable) { - console.log(`Merging #${pr.number} - ${pr.title}`); - await github.rest.pulls.merge({ - owner, - repo, - pull_number: pr.number, - }); - await new Promise((r) => setTimeout(r, 2000)); - } diff --git a/.github/workflows/automate_review-labels-scheduled.yaml b/.github/workflows/automate_review-labels-scheduled.yaml deleted file mode 100644 index 3ba13cfd17..0000000000 --- a/.github/workflows/automate_review-labels-scheduled.yaml +++ /dev/null @@ -1,31 +0,0 @@ -# on a review from someone in the reviewers group, remove the awaiting-review label and add the awaiting-author label -name: Automate review labels - scheduled -on: - schedule: - - cron: '* * * * *' - -jobs: - label: - runs-on: ubuntu-latest - steps: - - name: Get Token - id: get_workflow_token - uses: peter-murray/workflow-application-token-action@v1 - with: - application_id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} - application_private_key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} - organization: backstage - - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: 14 - - run: npm install codeowners - - - uses: actions/github-script@v6 - id: fix-labels - with: - github-token: ${{ steps.get_workflow_token.outputs.token }} - script: | - const script = require('./scripts/goalie-labels.js') - await script({github, context, core}) diff --git a/.github/workflows/automate_review-labels.yaml b/.github/workflows/automate_review-labels.yaml deleted file mode 100644 index cae71f6aaa..0000000000 --- a/.github/workflows/automate_review-labels.yaml +++ /dev/null @@ -1,84 +0,0 @@ -# When the target of the PR changes, open, re-open or sync, then re-add the label. - -name: Automate review labels -on: - pull_request_target: - types: - - opened - - closed - - synchronize - -permissions: - issues: write - pull-requests: write - -jobs: - label: - runs-on: ubuntu-latest - steps: - # THESE SCRIPTS SHOULD BE INLINED AND NOT IN REPO - # DUE TO THE TOKEN PERMISSIONS THAT ARE GIVEN - # TO THE WORKFLOW. THIS SCRIPT WILL AND SHOULD - # RUN FROM THE BASE REPO ALL TIMES. - - uses: actions/github-script@v6 - id: fix-labels - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - if (['opened', 'synchronize'].includes('${{ github.event.action }}')) { - // if it's the author, always add awaiting-review label - const isAuthor = context.payload.pull_request.user.login === context.actor - if (isAuthor) { - await github.rest.issues.addLabels({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - labels: ['awaiting-review'] - }); - } - } - - if ('${{ github.event.action}}' === 'closed') { - await github.rest.issues.removeLabel({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - labels: 'awaiting-review' - }).catch((e) => { - console.log(e) - }); - } - - - name: Add PRs to review board - uses: actions/github-script@v6 - if: github.event.action == 'opened' || github.event.action == 'reopened' - env: - PROJECT_ID: PN_kwDOBFKqdc02LQ - with: - github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} - script: | - const prLookup = await github.graphql(` - query($owner: String!, $repo: String!, $number: Int!){ - repository(owner: $owner, name: $repo) { - pullRequest(number: $number) { - id - } - } - } - `, context.issue); - - await github.graphql(` - mutation($projectId: ID!, $contentId: ID!) { - addProjectNextItem(input: { - projectId: $projectId, - contentId: $contentId, - }) { - projectNextItem { - id - } - } - } - `, { - projectId: process.env.PROJECT_ID, - contentId: prLookup.repository.pullRequest.id - }) diff --git a/.github/workflows/automate_stale.yml b/.github/workflows/automate_stale.yml index f9c655fc4a..8978048c89 100644 --- a/.github/workflows/automate_stale.yml +++ b/.github/workflows/automate_stale.yml @@ -25,6 +25,6 @@ jobs: If you are the author and the PR has been closed, feel free to re-open the PR and continue the contribution! days-before-pr-stale: 7 days-before-pr-close: 5 - exempt-pr-labels: reviewer-approved,awaiting-review,will-fix + exempt-pr-labels: reviewer-approved,will-fix stale-pr-label: stale operations-per-run: 100 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0718c8a8b9..e38df375b6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,9 +9,116 @@ concurrency: cancel-in-progress: true jobs: + # This step only runs yarn install to make sure that an exact match is available + # in the cache. The two following verify and tests jobs then always install from cache. + install: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [14.x, 16.x] + + env: + CI: true + NODE_OPTIONS: --max-old-space-size=4096 + + steps: + - uses: actions/checkout@v3 + + - name: use node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + registry-url: https://registry.npmjs.org/ # Needed for auth + + - name: yarn install + uses: backstage/actions/yarn-install@v0.5.0 + with: + cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} + + # The verify jobs runs all the verification that doesn't require a + # diff towards master, since it takes some time to fetch that. verify: runs-on: ubuntu-latest + needs: install + + strategy: + matrix: + node-version: [14.x, 16.x] + + env: + CI: true + NODE_OPTIONS: --max-old-space-size=4096 + + steps: + - uses: actions/checkout@v3 + + - name: use node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + registry-url: https://registry.npmjs.org/ # Needed for auth + + - name: yarn install + uses: backstage/actions/yarn-install@v0.5.0 + with: + cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} + + - name: verify changesets + run: node scripts/verify-changesets.js + + - name: verify local dependency ranges + run: node scripts/verify-local-dependencies.js + + - name: validate config + run: yarn backstage-cli config:check --lax + + - name: type checking and declarations + run: yarn tsc:full + + - name: prettier + run: yarn prettier:check + + # We need to generate the API references as well, so that we can verify the doc links + - name: check api reports and generate API reference + run: yarn build:api-reports:only --ci --docs + + - name: verify api reference + run: node scripts/verify-api-reference.js + + - name: verify doc links + run: node scripts/verify-links.js + + - name: build all packages + run: yarn backstage-cli repo build --all + + - name: verify type dependencies + run: yarn lint:type-deps + + - name: verify plugin template + run: yarn lerna -- run diff -- --check + + - name: ensure clean working directory + run: | + if files=$(git ls-files --exclude-standard --others --modified) && [[ -z "$files" ]]; then + exit 0 + else + echo "" + echo "Working directory has been modified:" + echo "" + git status --short + echo "" + exit 1 + fi + + # The test job runs all tests as well as any verification step that + # requires a diff towards master. + test: + runs-on: ubuntu-latest + + needs: install + strategy: matrix: node-version: [14.x, 16.x] @@ -64,93 +171,28 @@ jobs: - name: fetch branch master run: git fetch origin master - # Beginning of yarn setup, keep in sync between all workflows. - # TODO(Rugvip): move this to composite action once all features we use are supported - name: use node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - # Cache every node_modules folder inside the monorepo - - name: cache all node_modules - id: cache-modules - uses: actions/cache@v3 - with: - path: '**/node_modules' - # We use both yarn.lock and package.json as cache keys to ensure that - # changes to local monorepo packages bust the cache. - key: ${{ runner.os }}-v${{ matrix.node-version }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }} - - # If we get a cache hit for node_modules, there's no need to bring in the global - # yarn cache or run yarn install, as all dependencies will be installed already. - - - name: find location of global yarn cache - id: yarn-cache - if: steps.cache-modules.outputs.cache-hit != 'true' - run: echo "::set-output name=dir::$(yarn cache dir)" - - - name: cache global yarn cache - uses: actions/cache@v3 - if: steps.cache-modules.outputs.cache-hit != 'true' - with: - path: ${{ steps.yarn-cache.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - name: yarn install - if: steps.cache-modules.outputs.cache-hit != 'true' - run: yarn install --frozen-lockfile - # End of yarn setup + uses: backstage/actions/yarn-install@v0.5.0 + with: + cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: check for yarn.lock changes id: yarn-lock run: git diff --quiet origin/master HEAD -- yarn.lock continue-on-error: true - - name: prettier - run: yarn prettier:check - - name: lock run: yarn lock:check - - name: validate config - run: yarn backstage-cli config:check --lax - - name: lint run: yarn backstage-cli repo lint --since origin/master - - name: type checking and declarations - run: yarn tsc:full - - # We need to generate the API references as well, so that we can verify the doc links - - name: check api reports and generate API reference - run: yarn build:api-reports:only --ci --docs - - - name: verify api reference - run: node scripts/verify-api-reference.js - - - name: verify changesets - run: node scripts/verify-changesets.js - - - name: verify doc links - run: node scripts/verify-links.js - - - name: verify local dependency ranges - run: node scripts/verify-local-dependencies.js - - - name: build changed packages - if: ${{ steps.yarn-lock.outcome == 'success' }} - run: yarn backstage-cli repo build --all --since origin/master - - - name: build all packages - if: ${{ steps.yarn-lock.outcome == 'failure' }} - run: yarn backstage-cli repo build --all - - - name: verify type dependencies - run: yarn lint:type-deps - - name: test changed packages if: ${{ steps.yarn-lock.outcome == 'success' }} run: yarn lerna -- run test --since origin/master -- --coverage --runInBand @@ -173,9 +215,6 @@ jobs: BACKSTAGE_TEST_DATABASE_POSTGRES9_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres9.ports[5432] }} BACKSTAGE_TEST_DATABASE_MYSQL8_CONNECTION_STRING: mysql://root:root@localhost:${{ job.services.mysql8.ports[3306] }}/ignored - - name: verify plugin template - run: yarn lerna -- run diff -- --check - - name: ensure clean working directory run: | if files=$(git ls-files --exclude-standard --others --modified) && [[ -z "$files" ]]; then diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml new file mode 100644 index 0000000000..5b5c8b63c8 --- /dev/null +++ b/.github/workflows/cron.yml @@ -0,0 +1,15 @@ +name: Cron +on: + workflow_dispatch: + schedule: + - cron: '*/5 * * * *' + +jobs: + cron: + runs-on: ubuntu-latest + steps: + - uses: backstage/actions/cron@v0.5.0 + with: + app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} + private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} + installation-id: ${{ secrets.BACKSTAGE_GOALIE_INSTALLATION_ID }} diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml new file mode 100644 index 0000000000..6cb97d1a9e --- /dev/null +++ b/.github/workflows/deploy_docker-image.yml @@ -0,0 +1,89 @@ +name: Build and push Docker Hub image +on: + repository_dispatch: + types: [release-published] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: checkout + uses: actions/checkout@v2 + with: + path: backstage + ref: v${{ github.event.client_payload.version }} + + - name: setup-node + uses: actions/setup-node@v1 + with: + node-version: 16.x + registry-url: https://registry.npmjs.org/ + + # Beginning of yarn setup, keep in sync between all workflows. + # TODO(Rugvip): move this to composite action once all features we use are supported + - name: use node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + registry-url: https://registry.npmjs.org/ # Needed for auth + + # Cache every node_modules folder inside the monorepo + - name: cache all node_modules + id: cache-modules + uses: actions/cache@v2 + with: + path: '**/node_modules' + # We use both yarn.lock and package.json as cache keys to ensure that + # changes to local monorepo packages bust the cache. + key: ${{ runner.os }}-v${{ matrix.node-version }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }} + + # If we get a cache hit for node_modules, there's no need to bring in the global + # yarn cache or run yarn install, as all dependencies will be installed already. + + - name: find location of global yarn cache + id: yarn-cache + if: steps.cache-modules.outputs.cache-hit != 'true' + run: echo "::set-output name=dir::$(yarn cache dir)" + + - name: cache global yarn cache + uses: actions/cache@v2 + if: steps.cache-modules.outputs.cache-hit != 'true' + with: + path: ${{ steps.yarn-cache.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + - name: yarn install + if: steps.cache-modules.outputs.cache-hit != 'true' + run: yarn install --frozen-lockfile + # End of yarn setup + + - name: create-app + run: npx @backstage/create-app + env: + BACKSTAGE_APP_NAME: example-app + + - name: yarn build + run: yarn build + working-directory: ./example-app + + - name: Login to GitHub Container Registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Build and push + uses: docker/build-push-action@v2 + with: + context: './example-app' + file: ./example-app/packages/backend/Dockerfile + push: true + tags: | + ghcr.io/${{ github.repository_owner }}/backstage:latest + ghcr.io/${{ github.repository_owner }}/backstage:${{ github.event.client_payload.version }} diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml index d0f8dc1e79..ffada71523 100644 --- a/.github/workflows/deploy_microsite.yml +++ b/.github/workflows/deploy_microsite.yml @@ -55,7 +55,7 @@ jobs: run: ls microsite/build/backstage && ls microsite/build/backstage/storybook - name: Deploy both microsite and storybook to gh-pages - uses: JamesIves/github-pages-deploy-action@v4.3.3 + uses: JamesIves/github-pages-deploy-action@v4.3.4 with: branch: gh-pages folder: microsite/build/backstage diff --git a/.github/workflows/deploy_nightly.yml b/.github/workflows/deploy_nightly.yml index c90894bce4..427a7139a0 100644 --- a/.github/workflows/deploy_nightly.yml +++ b/.github/workflows/deploy_nightly.yml @@ -20,33 +20,15 @@ jobs: steps: - uses: actions/checkout@v3 - # Beginning of yarn setup, keep in sync between all workflows, see ci.yml - name: use node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - - name: cache all node_modules - id: cache-modules - uses: actions/cache@v3 - with: - path: '**/node_modules' - key: ${{ runner.os }}-v${{ matrix.node-version }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }} - - name: find location of global yarn cache - id: yarn-cache - if: steps.cache-modules.outputs.cache-hit != 'true' - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: cache global yarn cache - uses: actions/cache@v3 - if: steps.cache-modules.outputs.cache-hit != 'true' - with: - path: ${{ steps.yarn-cache.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - name: yarn install - run: yarn install --frozen-lockfile - # End of yarn setup + uses: backstage/actions/yarn-install@v0.5.0 + with: + cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} # No verification done here, only build & publish. If the master branch # is broken we will see that from those builds, but we still want to push nightly diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index b63507df0c..30d4bf9ee2 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -61,33 +61,15 @@ jobs: steps: - uses: actions/checkout@v3 - # Beginning of yarn setup, keep in sync between all workflows, see ci.yml - name: use node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - - name: cache all node_modules - id: cache-modules - uses: actions/cache@v3 - with: - path: '**/node_modules' - key: ${{ runner.os }}-v${{ matrix.node-version }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }} - - name: find location of global yarn cache - id: yarn-cache - if: steps.cache-modules.outputs.cache-hit != 'true' - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: cache global yarn cache - uses: actions/cache@v3 - if: steps.cache-modules.outputs.cache-hit != 'true' - with: - path: ${{ steps.yarn-cache.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - name: yarn install - run: yarn install --frozen-lockfile - # End of yarn setup + uses: backstage/actions/yarn-install@v0.5.0 + with: + cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: Fetch previous commit for release check run: git fetch origin '${{ github.event.before }}' @@ -157,33 +139,15 @@ jobs: steps: - uses: actions/checkout@v3 - # Beginning of yarn setup, keep in sync between all workflows, see ci.yml - name: use node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - - name: cache all node_modules - id: cache-modules - uses: actions/cache@v3 - with: - path: '**/node_modules' - key: ${{ runner.os }}-v${{ matrix.node-version }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }} - - name: find location of global yarn cache - id: yarn-cache - if: steps.cache-modules.outputs.cache-hit != 'true' - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: cache global yarn cache - uses: actions/cache@v3 - if: steps.cache-modules.outputs.cache-hit != 'true' - with: - path: ${{ steps.yarn-cache.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - name: yarn install - run: yarn install --frozen-lockfile - # End of yarn setup + uses: backstage/actions/yarn-install@v0.5.0 + with: + cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: build type declarations run: yarn tsc:full @@ -209,7 +173,7 @@ jobs: # Grabs the version in the root package.json and creates a tag on GitHub - name: Create a release tag id: create_tag - run: node scripts/create-release-tag.js --dispatch-workflows + run: node scripts/create-release-tag.js env: GITHUB_TOKEN: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} @@ -219,6 +183,13 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} + - name: Dispatch repository event + uses: peter-evans/repository-dispatch@v2 + with: + token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} + event-type: release-published + client-payload: '{"version": "${{ steps.create_tag.outputs.version }}"}' + # Notify everyone about this great new release :D - name: Discord notification uses: Ilshidur/action-discord@0.3.2 diff --git a/.github/workflows/issue.yaml b/.github/workflows/issue.yaml new file mode 100644 index 0000000000..bc0dd15617 --- /dev/null +++ b/.github/workflows/issue.yaml @@ -0,0 +1,13 @@ +name: Issue +on: + issues: + types: [opened] + +jobs: + sync: + runs-on: ubuntu-latest + + if: github.repository == 'backstage/backstage' + steps: + - name: Issue sync + uses: backstage/actions/issue-sync@v0.5.0 diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml new file mode 100644 index 0000000000..c8fe3e2d69 --- /dev/null +++ b/.github/workflows/pr.yaml @@ -0,0 +1,32 @@ +name: PR +on: + pull_request_target: + types: + - opened + - synchronize + - reopened + - closed + issue_comment: + types: + - created + pull_request_review_comment: + types: + - created + +jobs: + sync: + runs-on: ubuntu-latest + + # Avoid running on issue comments + if: github.repository == 'backstage/backstage' && ( github.event.pull_request || github.event.issue.pull_request ) + steps: + - name: PR sync + uses: backstage/actions/pr-sync@v0.5.0 + with: + github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} + app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} + private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} + installation-id: ${{ secrets.BACKSTAGE_GOALIE_INSTALLATION_ID }} + project-id: PVT_kwDOBFKqdc02LQ + excluded-users: ${{ secrets.OOO_USERS }} + owning-teams: '@backstage/techdocs' diff --git a/.github/workflows/sync_approve_renovate_pr.yaml b/.github/workflows/sync_approve_renovate_pr.yaml deleted file mode 100644 index 2d25bea223..0000000000 --- a/.github/workflows/sync_approve_renovate_pr.yaml +++ /dev/null @@ -1,37 +0,0 @@ -name: Approve renovate lock file changes -on: - pull_request_target: - paths: - - '.github/workflows/sync_renovate-changesets.yml' - - '**/yarn.lock' - -jobs: - generate-changeset: - runs-on: ubuntu-latest - if: github.actor == 'renovate[bot]' && github.repository == 'backstage/backstage' - steps: - - name: Approve - uses: actions/github-script@v6 - with: - github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} - script: | - const owner = 'backstage'; - const repo = 'backstage'; - - const r = await github.rest.pulls.listFiles({ - owner, - repo, - pull_number: context.issue.number, - }); - - if (r.data.some((f) => f.filename.split('/').slice(-1)[0] !== 'yarn.lock')) { - console.log('skipping approval since some files are not yarn.lock'); - return; - } - - await github.rest.pulls.createReview({ - owner, - repo, - pull_number: context.issue.number, - event: 'APPROVE' - }) diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml index b6fce0e68d..0d3add5f12 100644 --- a/.github/workflows/sync_code-formatting.yml +++ b/.github/workflows/sync_code-formatting.yml @@ -14,33 +14,15 @@ jobs: # Fetch changes to previous commit - required for 'only_changed' in Prettier action fetch-depth: 0 - # Beginning of yarn setup, keep in sync between all workflows, see ci.yml - name: use node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - - name: cache all node_modules - id: cache-modules - uses: actions/cache@v3 - with: - path: '**/node_modules' - key: ${{ runner.os }}-v${{ matrix.node-version }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }} - - name: find location of global yarn cache - id: yarn-cache - if: steps.cache-modules.outputs.cache-hit != 'true' - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: cache global yarn cache - uses: actions/cache@v3 - if: steps.cache-modules.outputs.cache-hit != 'true' - with: - path: ${{ steps.yarn-cache.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - name: yarn install - run: yarn install --frozen-lockfile - # End of yarn setup + uses: backstage/actions/yarn-install@v0.5.0 + with: + cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: Run Prettier on ADOPTERS.md uses: creyD/prettier_action@v4.2 diff --git a/.github/workflows/sync_issue-labels.yml b/.github/workflows/sync_issue-labels.yml deleted file mode 100644 index 91b5f79f5d..0000000000 --- a/.github/workflows/sync_issue-labels.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Sync Issue Labels -on: - issues: - types: [opened] -jobs: - label-issue: - runs-on: ubuntu-latest - if: github.repository == 'backstage/backstage' - steps: - - name: View context attributes - uses: actions/github-script@v6 - with: - script: | - const keywords = { - 'techdocs|tech-docs|tech docs': 'docs-like-code', - 'search': 'search', - 'catalog': 'catalog', - 'scaffolder': 'scaffolder', - }; - - const labels = Object.entries(keywords) - .map(([regexp, label]) => { - if (new RegExp(regexp, 'gi').test(context.payload.issue.title)) { - return label; - } - }) - .filter(Boolean); - - if(!labels.length) { - return; - } - - github.rest.issues.addLabels({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - labels - }); diff --git a/.github/workflows/sync_release-manifest.yml b/.github/workflows/sync_release-manifest.yml index 816a3e632f..8cf6991aaf 100644 --- a/.github/workflows/sync_release-manifest.yml +++ b/.github/workflows/sync_release-manifest.yml @@ -1,10 +1,7 @@ name: Sync Release Manifest on: - workflow_dispatch: - inputs: - version: - description: Version number, without any 'v' prefix - required: true + repository_dispatch: + types: [release-published] jobs: create-new-version: @@ -23,7 +20,7 @@ jobs: with: path: backstage # 'v' prefix is added here for the tag, we keep it out of the manifest logic - ref: v${{ github.event.inputs.version }} + ref: v${{ github.event.client_payload.version }} # Checkout backstage/versions into /backstage/versions, which is where store the output - name: Checkout versions @@ -44,10 +41,10 @@ jobs: cd backstage mkdir -p scripts wget -O scripts/assemble-manifest.js https://raw.githubusercontent.com/backstage/backstage/master/scripts/assemble-manifest.js - node scripts/assemble-manifest.js ${{ github.event.inputs.version }} + node scripts/assemble-manifest.js ${{ github.event.client_payload.version }} cd versions git add . - git commit -am "${{ github.event.inputs.version }}" + git commit -am "${{ github.event.client_payload.version }}" git push - name: Dispatch update-helper update diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml index e45a36c8e8..9d0726e915 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -16,33 +16,15 @@ jobs: steps: - uses: actions/checkout@v3 - # Beginning of yarn setup, keep in sync between all workflows, see ci.yml - name: use node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - - name: cache all node_modules - id: cache-modules - uses: actions/cache@v3 - with: - path: '**/node_modules' - key: ${{ runner.os }}-v${{ matrix.node-version }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }} - - name: find location of global yarn cache - id: yarn-cache - if: steps.cache-modules.outputs.cache-hit != 'true' - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: cache global yarn cache - uses: actions/cache@v3 - if: steps.cache-modules.outputs.cache-hit != 'true' - with: - path: ${{ steps.yarn-cache.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - name: yarn install - run: yarn install --frozen-lockfile - # End of yarn setup + uses: backstage/actions/yarn-install@v0.5.0 + with: + cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: Create Snyk report uses: snyk/actions/node@master diff --git a/.github/workflows/verify_dco.yaml b/.github/workflows/verify_dco.yaml deleted file mode 100644 index 2094327d23..0000000000 --- a/.github/workflows/verify_dco.yaml +++ /dev/null @@ -1,65 +0,0 @@ -name: Verify DCO -on: - schedule: - - cron: '*/15 * * * *' - -jobs: - dco-helper: - runs-on: ubuntu-latest - steps: - - name: Verify DCO status for open pull requests - uses: actions/github-script@v6 - with: - script: | - const owner = "backstage"; - const repo = "backstage"; - const pulls = await github.paginate(github.rest.pulls.list, { - state: "open", - owner, - repo, - }); - - for (const pull of pulls) { - // Pick out the PRs that have the DCO check - const checks = await github.rest.checks.listForRef({ - owner, - repo, - ref: pull.head.sha, - check_name: "DCO", - status: "completed", - }); - // Skip if there are no checks - if (!checks.data.check_runs.length) { - continue; - } - // Skip if the conclusion is not action_required - if (checks.data.check_runs[0].conclusion !== "action_required") { - console.log(`No checks found for PR #${pull.number}, skipping`); - continue; - } - - const comments = await github.paginate(github.rest.issues.listComments, { - owner, - repo, - issue_number: pull.number, - }); - if (comments.find((c) => - c.user.login === "github-actions[bot]" && - c.body.includes("") - ) - ) { - console.log(`already commented on PR #${pull.number}, skipping`); - continue; - } - console.log(`creating comment on PR #${pull.number}`); - const body = ` - Thanks for the contribution! - All commits need to be DCO signed before they are reviewed. Please refer to the the [DCO section in CONTRIBUTING.md](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md#developer-certificate-of-origin) or the [DCO](${checks.data.check_runs[0].html_url}) status for more info. - `; - await github.rest.issues.createComment({ - repo, - owner, - issue_number: pull.number, - body, - }); - } diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml index 884d8bf172..126670b67f 100644 --- a/.github/workflows/verify_e2e-linux.yml +++ b/.github/workflows/verify_e2e-linux.yml @@ -40,35 +40,15 @@ jobs: steps: - uses: actions/checkout@v3 - # Beginning of yarn setup, keep in sync between all workflows, see ci.yml - name: use node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - - name: cache all node_modules - id: cache-modules - uses: actions/cache@v3 - with: - path: '**/node_modules' - key: ${{ runner.os }}-v${{ matrix.node-version }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }} - - name: find location of global yarn cache - id: yarn-cache - if: steps.cache-modules.outputs.cache-hit != 'true' - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: setup chrome - uses: browser-actions/setup-chrome@latest - - name: cache global yarn cache - uses: actions/cache@v3 - if: steps.cache-modules.outputs.cache-hit != 'true' - with: - path: ${{ steps.yarn-cache.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - name: yarn install - run: yarn install --frozen-lockfile - # End of yarn setup + uses: backstage/actions/yarn-install@v0.5.0 + with: + cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - run: yarn tsc - run: yarn backstage-cli repo build diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml index a13aa3ae71..89679b530a 100644 --- a/.github/workflows/verify_storybook.yml +++ b/.github/workflows/verify_storybook.yml @@ -17,44 +17,30 @@ on: jobs: chromatic: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [ubuntu-latest] + node-version: [16.x] + steps: - uses: actions/checkout@v3 with: fetch-depth: 0 # Required to retrieve git history - # Beginning of yarn setup, keep in sync between all workflows, see ci.yml - name: use node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - - name: cache all node_modules - id: cache-modules - uses: actions/cache@v3 + - name: yarn install + uses: backstage/actions/yarn-install@v0.5.0 with: - path: '**/node_modules' - key: ${{ runner.os }}-v${{ matrix.node-version }}-node_modules-${{ hashFiles('yarn.lock', '**/package.json') }} - - name: find location of global yarn cache - id: yarn-cache - if: steps.cache-modules.outputs.cache-hit != 'true' - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: cache global yarn cache - uses: actions/cache@v3 - if: steps.cache-modules.outputs.cache-hit != 'true' - with: - path: ${{ steps.yarn-cache.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - - name: top-level install - run: yarn install --frozen-lockfile - + cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: storybook yarn install run: yarn install --frozen-lockfile working-directory: storybook - # End of yarn setup - run: yarn build-storybook diff --git a/.github/workflows/verify_windows.yml b/.github/workflows/verify_windows.yml index bb8aa9e5aa..e286d42c7e 100644 --- a/.github/workflows/verify_windows.yml +++ b/.github/workflows/verify_windows.yml @@ -26,25 +26,15 @@ jobs: steps: - uses: actions/checkout@v3 - # Beginning of yarn setup, keep in sync between all workflows, see ci.yml - name: use node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - - name: find location of global yarn cache - id: yarn-cache - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: cache global yarn cache - uses: actions/cache@v3 - with: - path: ${{ steps.yarn-cache.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- + + # Windows file operation slowness means there's no point caching this - name: yarn install run: yarn install --frozen-lockfile - # End of yarn setup - name: lint run: yarn backstage-cli repo lint diff --git a/.prettierignore b/.prettierignore index 393c35fdbe..8f1fae0456 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,6 +5,7 @@ coverage *.hbs templates api-report.md +cli-report.md plugins/scaffolder-backend/sample-templates .vscode dist-types diff --git a/ADOPTERS.md b/ADOPTERS.md index e8d2aeed8b..1cb0577c44 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -1,6 +1,8 @@ # Adopters -_If you're using Backstage in your organization, please try to add your company name to this list. This really helps the project to gain momentum and credibility. It's a small contribution back to the project with a big impact._ +_If you're using Backstage in your organization, please try to add your company name to this list. It really helps the project to gain momentum and credibility. It's a small contribution back to the project with a big impact._ +_You can do this by using the [Adopter form](https://form.typeform.com/to/zcOaKikB) or by editing this file after following the [CONTRIBUTING.md](./CONTRIBUTING.md)._ + | Organization | Contact | Description of Use | |-----------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -36,7 +38,7 @@ _If you're using Backstage in your organization, please try to add your company | [PagerDuty](https://www.pagerduty.com/) | [Mark Shaw](https://github.com/markshawtoronto) | Developer portal, initially focused on software templates and tech-docs. | | [MoonShiner](https://moonshiner.at) | [Fabian Hippmann](https://github.com/FabianHippmann) | Developer portal - helps us keep track of our customer projects, onboard new developers & improve our development process 🌕🚀🧑‍🚀 | | [FundApps](https://www.fundapps.co/) | [Elliot Greenwood](https://github.com/egnwd) | Developer Portal - A place for us to keep track of our projects and documentation for all services and processes | -| [DAZN](https://dazn.com/) | [Lou Bichard](https://twitter.com/loujaybee), [Marco Crivellaro](https://github.com/crivetechie), [Alex Hollerith](mailto:alex.hollerith@dazn.com), [Kamil Wolny](https://github.com/mrwolny) | Ingesting all of DAZN's repos for the catalog, migrating our internal platform apps (pull request boards, release information, inner source marketplace etc) to Backstage plugins (where applicable). | +| [DAZN](https://dazn.com/) | [David Rubio Vidal](https://github.com/davidrv87), [Marco Crivellaro](https://github.com/crivetechie), [Alex Hollerith](mailto:alex.hollerith@dazn.com), [Kamil Wolny](https://github.com/mrwolny) | Ingesting all of DAZN's repos for the catalog, migrating our internal platform apps (pull request boards, release information, inner source marketplace etc) to Backstage plugins (where applicable). | | [HelloFresh](https://www.hellofresh.de/) | [@iammuho](https://github.com/iammuho), [@ElenaForester](https://github.com/ElenaForester), [@diegomarangoni](https://github.com/diegomarangoni) | Our developer portal at HelloFresh - Spread across an organisation of 500+ engineers globally. | | [FactSet](https://www.factset.com/) | [@kuangp](https://github.com/kuangp) | Developer portal to provide discoverability to all internal components, APIs, documentation, and scaffold templates with integrations to our internal infrastructure tools. | | [Workrise](https://www.workrise.com/) | [Michael Rode](https://github.com/michaelrode) | Developer portal, main gateway to our infrastructure, documentation and internal tooling. | @@ -176,7 +178,7 @@ _If you're using Backstage in your organization, please try to add your company | [idwall](https://idwall.co) | [Rodrigo Catão Araujo](mailto:rodrigo@idwall.co) | Developer Portal for internal engineers to access service catalog, documentation, observability, infrastructure and internal tooling. | | [Jaguar Land Rover](https://www.jaguarlandrover.com) | [Josh Walker](mailto:jwalke18@jaguarlandrover.com) | Users can request a Gitlab user, which creates a commit with the Terraform code. | | [Glovo](http://glovoapp.com/) | [Yaser Toutah](mailto:yaser.toutah@glovoapp.com) | Developer Portal to improve our Developer Experience, identify ownership and track metadata for our services and tools. It's our Service Catalog. In addition to that, we use it for Service Creation, and much more. | -| [Dixa](https://dixa.com) | [Jens Møller](mailto:jsc@dixa.com) | We are in early stages, but using it to get overview of our repositories and ownership of these. We want among many things to use it for compliance and easier access to key metrics for our repos. | +| [Dixa](https://dixa.com) | [Jens Møller](https://github.com/jensamoller) | We are in early stages, but using it to get overview of our repositories and ownership of these. We want among many things to use it for compliance and easier access to key metrics for our repos. | | [Notino](https://notino.com) | [Jan Remunda](mailto:jan.remunda@notino.com) | Backstage is our developer portal. We use it as service catalog and for technical documentation. | | [Polarpoint](https://polarpoint.io/) | [Surj Bains](https://github.com/polarpoint-io) | We are using Backstage as our Developer portal as well as for hosting our DevOps portal for software catalog. | | [Niche](https://niche.com) | [Zach Romitz](mailto:zach.romitz@niche.com) | We are using the Software Catalog, Software Templates, API documentation, and Techdocs to try and centralize service information. | @@ -184,3 +186,7 @@ _If you're using Backstage in your organization, please try to add your company | [Funding Circle](https://www.fundingcircle.com/) | [Ariel Pacciaroni](https://github.com/arielpacciaroni) | We are building the internal developer portal using Backstage project and centralizing all services information at one place. The portal helps us track down repositories ownership as well as direct access to key information on every component. | | [Clarivate](https://www.clarivate.com) | [Gabriele Carteni](mailto:gabriele.carteni@clarivate.com) | We are building our Developer Portal using Backstage to have a better control over our software ecosystem, integrate SDLC tools and promote best practices | | [Cho Tot](https://www.chotot.com) | [Chotot Team](mailto:sre@chotot.vn) | Internal developer portal, service catalog with CI/CD tools. | +| [William Hill](https://www.williamhillgroup.com/) | [Pat Mills](mailto:pat.mills@williamhill.com), [Nathan Flynn](mailto:nflynn@williamhill.co.uk), and [Nishkarsh Raj](mailto:nishkarsh.raj@williamhill.co.uk) | William Hill are leveraging Backstage to build our Engineering Portal. Our mission is to centralize the software catalog inventory to enable service discoverability, reduce the onboarding time for new Engineers, provide a single pane of glass to accelerate Developer Productivity and Save Engineers time. Our aspiration is to create an InnerSource community focussed on organization-wide patterns that are re-usable and can be self-served with the Scaffolder. | +| [Vodafone NewZealand Limited](https://vodafone.co.nz) | [Ankit Gupta](mailto:ankit.gupta@vodafone.nz), [DevOps COE](mailto:devopstooling@vodafone.nz) | Vodafone NZ are leveraging Backstage to build centralised and self service Engineering Portal. Our mission is to standardised Pipeline templates across the Engineering teams, One shop stop to create the pipelines and repository with a template approach which reduces creation part from days to minutes and no wait time for developers. A unified view for Azure DevOps pipeline, Azure Repo pull requests, Deployment status from Azure RedHat Openshift-ArgoCD and SonarQube Security and code quality scans report on a single pan to provide a streamlined view for all microservices across the app stack. | +| [Coamo](http://www.coamo.com.br) | [@holiiveira](https://github.com/holiiveira), [@gpxlnx](https://github.com/gpxlnx) | We're starting to use it as the main tool of a DevOps platform. Our goal is to provide software templates, centralize our software catalog enabling efficient service discovery, and make it easy to manage the entire software ecosystem in one place. + | diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eb60bc48e0..1afbf072fc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -58,9 +58,9 @@ If you are proposing a feature: - Remember that this is a volunteer-driven project, and that contributions are welcome :) -### Add your company to ADOPTERS +### Add your company to `ADOPTERS` -Have you started using Backstage? Adding your company to [ADOPTERS](ADOPTERS.md) really helps the project. +Have you started using Backstage? Adding your company to [ADOPTERS](ADOPTERS.md) really helps the project, you can do this by filling out this [Adopter form](https://form.typeform.com/to/zcOaKikB). ## Get Started! diff --git a/app-config.yaml b/app-config.yaml index a56a3df9d1..9a3206026e 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -234,16 +234,6 @@ catalog: # dn: ou=access,ou=groups,ou=example,dc=example,dc=net # options: # filter: (&(objectClass=some-group-class)(!(groupType=email))) - microsoftGraphOrg: - ### Example for how to add your Microsoft Graph tenant - #providers: - # - target: https://graph.microsoft.com/v1.0 - # authority: https://login.microsoftonline.com - # tenantId: ${MICROSOFT_GRAPH_TENANT_ID} - # clientId: ${MICROSOFT_GRAPH_CLIENT_ID} - # clientSecret: ${MICROSOFT_GRAPH_CLIENT_SECRET_TOKEN} - # userFilter: accountEnabled eq true and userType eq 'member' - # groupFilter: securityEnabled eq false and mailEnabled eq true and groupTypes/any(c:c+eq+'Unified') locations: # Add a location here to ingest it, for example from a URL: diff --git a/cypress/yarn.lock b/cypress/yarn.lock index 1ccce4ea24..991d2d8562 100644 --- a/cypress/yarn.lock +++ b/cypress/yarn.lock @@ -304,9 +304,9 @@ cross-spawn@^7.0.0: which "^2.0.1" cypress@^10.0.0: - version "10.2.0" - resolved "https://registry.npmjs.org/cypress/-/cypress-10.2.0.tgz#ca078abfceb13be2a33cbba6e0e80ded770f542a" - integrity sha512-+i9lY5ENlfi2mJwsggzR+XASOIgMd7S/Gd3/13NCpv596n3YSplMAueBTIxNLcxDpTcIksp+9pM3UaDrJDpFqA== + version "10.3.0" + resolved "https://registry.npmjs.org/cypress/-/cypress-10.3.0.tgz#fae8d32f0822fcfb938e79c7c31ef344794336ae" + integrity sha512-txkQWKzvBVnWdCuKs5Xc08gjpO89W2Dom2wpZgT9zWZT5jXxqPIxqP/NC1YArtkpmp3fN5HW8aDjYBizHLUFvg== dependencies: "@cypress/request" "^2.88.10" "@cypress/xvfb" "^1.2.4" diff --git a/docs/auth/add-auth-provider.md b/docs/auth/add-auth-provider.md index eb8973bec1..01c18f04cd 100644 --- a/docs/auth/add-auth-provider.md +++ b/docs/auth/add-auth-provider.md @@ -350,6 +350,7 @@ router.get('/auth/providerA/handler/frame'); router.post('/auth/providerA/handler/frame'); router.post('/auth/providerA/logout'); router.get('/auth/providerA/refresh'); // if supported +router.post('/auth/providerA/refresh'); // if supported ``` As you can see each endpoint is prefixed with both `/auth` and its provider diff --git a/docs/features/search/search-engines.md b/docs/features/search/search-engines.md index 9bb8b8c343..ecd8a85109 100644 --- a/docs/features/search/search-engines.md +++ b/docs/features/search/search-engines.md @@ -59,10 +59,38 @@ configured and make the following changes to your backend: // Initialize a connection to a search engine. const searchEngine = (await PgSearchEngine.supported(env.database)) - ? await PgSearchEngine.from({ database: env.database }) + ? await PgSearchEngine.fromConfig(env.config, { database: env.database }) : new LunrSearchEngine({ logger: env.logger }); ``` +## Optional Configuration + +The following is an example of the optional configuration that can be applied when using Postgres as the search backend. Currently this is mostly for just the highlight feature: + +```yaml +search: + pg: + highlightOptions: + useHighlight: true # Used to enable to disable the highlight feature. The default value is true + maxWord: 35 # Used to set the longest headlines to output. The default value is 35. + minWord: 15 # Used to set the shortest headlines to output. The default value is 15. + shortWord: 3 # Words of this length or less will be dropped at the start and end of a headline, unless they are query terms. The default value of three (3) eliminates common English articles. + highlightAll: false # If true the whole document will be used as the headline, ignoring the preceding three parameters. The default is false. + maxFragments: 0 # Maximum number of text fragments to display. The default value of zero selects a non-fragment-based headline generation method. A value greater than zero selects fragment-based headline generation (see the linked documentation above for more details). + fragmentDelimiter: ' ... ' # Delimiter string used to concatenate fragments. Defaults to " ... ". +``` + +**Note:** the highlight search term feature uses `ts_headline` which has been known to potentially impact performance. You only need this minimal config to disable it should you have issues: + +```yaml +search: + pg: + highlightOptions: + useHighlight: false +``` + +The Postgres documentation on [Highlighting Results](https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-HEADLINE) has more details. + ## ElasticSearch Backstage supports ElasticSearch search engine connections, indexing and @@ -80,15 +108,16 @@ const searchEngine = await ElasticSearchSearchEngine.initialize({ const indexBuilder = new IndexBuilder({ logger: env.logger, searchEngine }); ``` -For the engine to be available, your backend package needs a dependency into +For the engine to be available, your backend package needs a dependency on package `@backstage/plugin-search-backend-module-elasticsearch`. ElasticSearch needs some additional configuration before it is ready to use within your instance. The configuration options are documented in the [configuration schema definition file.](https://github.com/backstage/backstage/blob/master/plugins/search-backend-module-elasticsearch/config.d.ts) -The underlying functionality is using official ElasticSearch client version 7.x, -meaning that ElasticSearch version 7 is the only one confirmed to be supported. +The underlying functionality uses either the official ElasticSearch client +version 7.x (meaning that ElasticSearch version 7 is the only one confirmed to +be supported), or the OpenSearch client, when the `aws` provider is configured. Should you need to create your own bespoke search experiences that require more than just a query translator (such as faceted search or Relay pagination), you @@ -97,9 +126,19 @@ search clients. The version of the client need not be the same as one used internally by the elastic search engine plugin. For example: ```typescript -import { Client } from '@elastic/elastic-search'; +import { isOpenSearchCompatible } from '@backstage/plugin-search-backend-module-elasticsearch'; +import { Client as ElasticClient } from '@elastic/elastic-search'; +import { Client as OpenSearchClient } from '@opensearch-project/opensearch'; -const client = searchEngine.newClient(options => new Client(options)); +const client = searchEngine.newClient(options => { + // In reality, you would only import / instantiate one of the following, but + // for illustrative purposes, here are both: + if (isOpenSearchCompatible(options)) { + return new OpenSearchClient(options); + } else { + return new ElasticClient(options); + } +}); ``` #### Set custom index template diff --git a/docs/features/software-catalog/configuration.md b/docs/features/software-catalog/configuration.md index 849823a59e..5abd266099 100644 --- a/docs/features/software-catalog/configuration.md +++ b/docs/features/software-catalog/configuration.md @@ -106,8 +106,7 @@ with [Static Location Configuration](#static-location-configuration) or a discovery processor like [GitHub Discovery](../../integrations/github/discovery.md). To enforce usage of processors to locate entities we can configure the catalog into `readonly` mode. -This configuration disables the mutating backend catalog APIs and disallows -users from registering new entities at run-time. +This configuration disables registering and deleting locations with the catalog APIs. ```yaml catalog: @@ -117,6 +116,8 @@ catalog: > **Note that any plugin relying on the catalog API for creating, updating and > deleting entities will not work in this mode.** +Deleting an entity by UUID, `DELETE /entities/by-uid/:uid`, is allowed when using this mode. It may be rediscovered as noted in [explicit deletion](life-of-an-entity.md#explicit-deletion). + A common use case for this configuration is when organizations have a remote source that should be mirrored into Backstage. To make Backstage a mirror of this remote source, users cannot also register new entities with e.g. the diff --git a/docs/features/software-templates/adding-templates.md b/docs/features/software-templates/adding-templates.md index db765fc7ee..e8176a688b 100644 --- a/docs/features/software-templates/adding-templates.md +++ b/docs/features/software-templates/adding-templates.md @@ -86,6 +86,13 @@ contains more information about the required fields. Once we have a `template.yaml` ready, we can then add it to the software catalog for use by the scaffolder. +> Note: When you add or modify a template, you will need to refresh the location entity. +> Otherwise, Backstage won't display the template in the available templates, +> or it will keep showing the old template. You can refresh the location instance by +> going into `Catalog` web page, choosing `Locations` instead of `Components`, and selecting the correct location entity. +> From there, you can click on the refresh icon representing "Scheduled entity refresh" action. +> Afterwards, you should see your template updated. + You can add the template files to the catalog through [static location configuration](../software-catalog/configuration.md#static-location-configuration), for example: @@ -97,6 +104,8 @@ catalog: target: https://github.com/backstage/software-templates/blob/main/scaffolder-templates/react-ssr-template/template.yaml rules: - allow: [Template] + - type: file + target: template.yaml # Backstage will expect the file to be in packages/backend/template.yaml ``` Or you can add the template using the `catalog-import` plugin, which unless diff --git a/docs/features/software-templates/writing-custom-actions.md b/docs/features/software-templates/writing-custom-actions.md index 8e698e1a05..a9e1d297f3 100644 --- a/docs/features/software-templates/writing-custom-actions.md +++ b/docs/features/software-templates/writing-custom-actions.md @@ -9,8 +9,9 @@ by writing custom actions which can be used along side our [built-in actions](./builtin-actions.md). > Note: When adding custom actions, the actions array will **replace the -> built-in actions too**. To ensure you can continue to include the builtin -> actions, see below to include them during registration of your action. +> built-in actions too**. Meaning, you will no longer be able to use them. +> If you want to continue using the builtin actions, include them in the actions +> array when registering your custom actions, as seen below. ## Writing your Custom Action @@ -122,27 +123,32 @@ will set the available actions that the scaffolder has access to. ```ts import { createBuiltinActions } from '@backstage/plugin-scaffolder-backend'; import { ScmIntegrations } from '@backstage/integration'; +import { createNewFileAction } from './actions/custom'; -const integrations = ScmIntegrations.fromConfig(env.config); +export default async function createPlugin( + env: PluginEnvironment, +): Promise { + const catalogClient = new CatalogClient({ discoveryApi: env.discovery }); + const integrations = ScmIntegrations.fromConfig(env.config); -const builtInActions = createBuiltinActions({ - containerRunner, - integrations, - catalogClient, - config: env.config, - reader: env.reader, -}); + const builtInActions = createBuiltinActions({ + integrations, + catalogClient, + config: env.config, + reader: env.reader, + }); -const actions = [...builtInActions, createNewFileAction()]; -return await createRouter({ - containerRunner, - catalogClient, - actions, - logger: env.logger, - config: env.config, - database: env.database, - reader: env.reader, -}); + const actions = [...builtInActions, createNewFileAction()]; + + return createRouter({ + actions, + catalogClient: catalogClient, + logger: env.logger, + config: env.config, + database: env.database, + reader: env.reader, + }); +} ``` ## List of custom action packages diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index ff9962d8d4..81367b19c5 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -320,6 +320,30 @@ The `allowedHosts` part should be set to where you wish to enable this template to publish to. And it can be any host that is listed in your `integrations` config in `app-config.yaml`. +Besides specifying `allowedHosts` you can also restrict the template to publish to +repositories owned by specific users/groups/namespaces by setting the `allowedOwners` +option. With the `allowedRepos` option you are able to narrow it down further to a +specific set of repository names. A full example could look like this: + +```yaml +- title: Choose a location + required: + - repoUrl + properties: + repoUrl: + title: Repository Location + type: string + ui:field: RepoUrlPicker + ui:options: + allowedHosts: + - github.com + allowedOwners: + - backstage + - someGithubUser + allowedRepos: + - backstage +``` + 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) @@ -485,6 +509,64 @@ the value of `firstName` from the parameters). This is great for passing the values from the form into different steps and reusing these input variables. These template strings preserve the type of the parameter. +The `${{ parameters.firstName }}` pattern will work only in the template file. +If you want to start using values provided from the UI in your code, you will have to use +the `${{ values.firstName }}` pattern. Additionally, you have to pass +the parameters from the UI to the input of the `fetch:template` step. + +```yaml +apiVersion: scaffolder.backstage.io/v1beta3 +kind: Template +metadata: + name: v1beta3-demo + title: Test Action + description: scaffolder v1beta3 template demo +spec: + owner: backstage/techdocs-core + type: service + parameters: + - title: Fill in some steps + required: + - name + properties: + name: + title: Name + type: string + description: Unique name of your project + urlParameter: + title: URL endpoint + type: string + description: URL endpoint at which the component can be reached + default: 'https://www.example.com' + enabledDB: + title: Enable Database + type: boolean + default: false + ... + steps: + - id: fetch-base + name: Fetch Base + action: fetch:template + input: + url: ./template + values: + name: ${{ parameters.name }} + url: ${{ parameters.urlParameter }} + enabledDB: ${{ parameters.enabledDB }} +``` + +Afterwards, if you are using the builtin templating action, you can start using +the variables in your code. You can use also any other templating functions from +[Nunjucks](https://mozilla.github.io/nunjucks/templating.html#tags) as well. + +```bash +#!/bin/bash +echo "Hi my name is ${{ values.name }}, and you can fine me at ${{ values.url }}!" +{% if values.enabledDB %} +echo "You have enabled your database!" +{% endif %} +``` + As you can see above in the `Outputs` section, `actions` and `steps` can also output things. You can grab that output using `steps.$stepId.output.$property`. diff --git a/docs/features/techdocs/addons.md b/docs/features/techdocs/addons.md index 831729d093..fe1058b2ca 100644 --- a/docs/features/techdocs/addons.md +++ b/docs/features/techdocs/addons.md @@ -52,6 +52,8 @@ Addons are rendered in the order in which they are registered. ## Installing and using Addons +To start using Addons you need to add the `@backstage/plugin-techdocs-module-addons-contrib` package to your app. You can do that by running this command from the root of your project: `yarn add --cwd packages/app @backstage/plugin-techdocs-module-addons-contrib` + Addons can be installed and configured in much the same way as extensions for other Backstage plugins: by adding them underneath an extension registry component (``) under the route representing the TechDocs Reader @@ -74,6 +76,18 @@ import { ReportIssue } from '@backstage/plugin-techdocs-module-addons-contrib'; ; ``` +If you are using a custom [TechDocs reader page](./how-to-guides.md#how-to-customize-the-techdocs-reader-page) your setup will be very similar, here's an example: + +```ts +}> + + + {/* Other addons can be added here. */} + + {techDocsPage} // This is your custom TechDocs reader page + +``` + The process for configuring Addons on the documentation tab on the entity page is very similar; instead of adding the `` registry under a ``, you'd add it as a child of ``: diff --git a/docs/features/techdocs/configuration.md b/docs/features/techdocs/configuration.md index 9440d9a824..8a54d76ed0 100644 --- a/docs/features/techdocs/configuration.md +++ b/docs/features/techdocs/configuration.md @@ -160,7 +160,8 @@ techdocs: # techdocs.cache is optional, and is only recommended when you've configured # an external techdocs.publisher.type above. Also requires backend.cache to - # be configured with a valid cache store. + # be configured with a valid cache store. Configure techdocs.cache.ttl to + # enable caching of techdocs assets. cache: # Represents the number of milliseconds a statically built asset should # stay cached. Cache invalidation is handled automatically by the frontend, diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index 8c2f6bc865..d560b97eae 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -21,7 +21,7 @@ guide to do a repository-based installation. ### Prerequisites -- Access to a Linux-based operating system, such as Linux, MacOS or +- Access to a Unix-based operating system, such as Linux, MacOS or [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/) - An account with elevated rights to install the dependencies - `curl` or `wget` installed diff --git a/docs/overview/architecture-overview.md b/docs/overview/architecture-overview.md index 382399e603..3c9417268b 100644 --- a/docs/overview/architecture-overview.md +++ b/docs/overview/architecture-overview.md @@ -341,7 +341,8 @@ separate Docker images. The backend container can be built by running the following command: ```bash -yarn run docker-build +yarn run build +yarn run build-image ``` This will create a container called `example-backend`. diff --git a/docs/overview/roadmap.md b/docs/overview/roadmap.md index 727000728f..df242ed172 100644 --- a/docs/overview/roadmap.md +++ b/docs/overview/roadmap.md @@ -15,9 +15,9 @@ work"](#future-work). With "next" we mean features planned for release within the ongoing quarter from April through June 2022. With "future" we mean features on the radar, but not yet scheduled. -| [What's next](#whats-next) | [Future work](#future-work) | -| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -| [Ease of onboarding](#ease-of-onboarding)
[Backstage Search 1.0](#search-1.0)
[TechDocs Addon Framework](#techdocs-addon-framework)
[Backend Services (initial)](#backend-services-initial)
[Backstage Security Audit](#backstage-security-audit)
[SIGs for contributors](#sigs-for-contributors) | Security Plan (and Strategy)
Composable Homepage 1.0
GraphQL
Telemetry
Improved UX design | +| [What's next](#whats-next) | [Future work](#future-work) | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | +| [Backstage Search 1.0](#search-1.0)
[Backend Services (MVP)](#backend-services-mvp)
[Backstage Security Audit](#backstage-security-audit)
[Backstage Threat Model](#backstage-threat-model)
[TechDocs Addon Framework](#techdocs-addon-framework)
[Software Catalog pagination](#software-catalog-pagination)
[More SIGs](#more-sigs) | Ease of onboarding
Composable Homepage 1.0
Creator experience
GraphQL
Telemetry | The long-term roadmap (12 - 36 months) is not detailed in the public roadmap. Third-party contributions are also not currently included in the roadmap. Let us @@ -30,47 +30,22 @@ The feature set below is planned for the ongoing quarter, and grouped by theme. The list order doesn't necessarily reflect priority, and the development/release cycle will vary based on maintainer schedules. -### Ease of onboarding - -A faster (with less development) and easier setup of a proof-of-concept -deployment, as part of the onboarding experience, has been a common and loud -suggestion from new adopters as well as analysts looking at Backstage. - -With this initiative we plan to start facing this important topic with the most -commonly used and challenging tasks. More in particular we plan to reduce the -effort required to go from zero to production in installing and customizing -Backstage, as well as reducing the effort required to populate the Software -Catalog. - -More iterations will be required in the following quarters, but this will be a -good improvement in the onboarding experience, especially for the benefit of new -adopters. - ### Backstage Search 1.0 Fix the few remaining issues to get Backstage Search platform up to 1.0. For more information, see the [Backstage Search documentation and roadmap page](https://backstage.io/docs/features/search/search-overview). -### TechDocs Addon Framework - -Addons are TechDocs features that are added on top of the base docs-like-code experience. An example would be a feature that showed comments on the page. We plan to add an Addon framework and open source a selection of the Addons that we use internally at Spotify. We encourage the Backstage community to add further Addons. - -For more information about the TechDocs Addon Framework, see the documentation page [here](https://backstage.io/docs/features/techdocs/addons) - -For general information about TechDocs including roadmap, see [here](https://backstage.io/docs/features/techdocs/techdocs-overview). - -### Backend Services (initial) +### Backend Services (MVP) To better scale and maintain the Backstage instances, a backend services system is planned to be introduced as part of the software architecture. This layer of backend services will help in decoupling the various modules (e.g. Catalog and Scaffolder) from the frontend experience. -In this quarter we plan to start designing the new architecture, together with -the first experimentation and development of the software components. +After the experimentation and design happened in the past quarter, soon we plan to release a first version to start providing the first benefits to adopters and developers. ### Backstage Security Audit -This is the continuation of the initiative started in the previous quarter. This +This is the continuation of the initiative started in the previous quarters. This quarter will see the publication of the report describing the outcome of the audit, together the first fixes and the development of some of the changes required to address the vulnerabilities. @@ -84,12 +59,34 @@ initiative. This initiative is done together with, and with the support of, the [Cloud Native Computing Foundation (CNCF)](https://www.cncf.io/). -### SIGs for contributors +### Backstage Threat Model -The request to better coordinate the increasing number of contributions coming -from the various adopters' developers is loud and clear. We think that the -community is mature enough to start launching the SIGs (Special Interest Groups) -following the successful model of Kubernetes. +This is another (relevant) initiative planned to make Backstage a secure product for the adopters. The goals of this initiative are: + +1. Understand where security investment and attention is needed. +2. Guide the upcoming security audit. +3. Communicate expectations to Backstage adopters and inform and attract security researchers. + +The planned artifacts are: + +- Concise high level threat model that will be included as part of the Backstage security documentation. +- Granular threat model created in conjunction with the security audit to inform further security investment areas for Backstage. + +### TechDocs Addon Framework + +Addons are TechDocs features that are added on top of the base docs-like-code experience. An example would be a feature that showed comments on the page. We plan to add an Addon framework and open source a selection of the Addons that we use internally at Spotify. We encourage the Backstage community to add further Addons. + +For more information about the TechDocs Addon Framework, see the documentation page [here](https://backstage.io/docs/features/techdocs/addons). + +For general information about TechDocs including roadmap, see [here](https://backstage.io/docs/features/techdocs/techdocs-overview). + +### Software Catalog pagination + +Today adopters with a big catalog (with several thousands of software components) might not have an ideal end-user experience when viewing the `/catalog` page. The issue is related to how the entities are fetched by the frontend. In order to provide a better end-user experience the pagination of the catalog’s entities needs to be enforced. Some experimentation is already completed but in this quarter we plan to continue, and hopefully complete, this relevant enhancement. + +### More SIGs + +In the last quarter we launched the [Catalog SIG (Special Interest Group)](https://github.com/backstage/community/tree/main/sigs/sig-catalog) to better coordinate the increasing number of contributions to the project. We think that this is the proper path to follow to engage more with the contributors. For this reason we will launch other SIGs dedicated to the most interesting topics for the community. ## Future work @@ -97,18 +94,17 @@ The following feature list doesn't represent a commitment to develop, and the list order doesn't reflect any priority or importance, but these features are on the maintainers' radar, with clear interest expressed by the community. -- **Security Plan (and Strategy):** The purpose of the Security Strategy is to - move another step along the path to maturing the platform, setting the - expectations of any adopters from a security standpoint. +- **Ease of onboarding:** A faster (with less development) and easier setup of + Backstage and the most relevant/adopted plugins. - **Composable Homepage 1.0:** Driving this to 1.0 by adding some composable components. +- **Creator experience:** Provide a better Backstage user experience through + visual guidelines and templates, especially navigation across plug-ins and + portal functionalities. - **[GraphQL](https://graphql.org/) support:** Introduce the ability to query Backstage backend services with a standard query language for APIs. - **Telemetry:** To efficiently generate logging and metrics in such a way that adopters can get insights so that Backstage can be monitored and improved. -- **Improved UX design:** Provide a better Backstage user experience through - visual guidelines and templates, especially navigation across plug-ins and - portal functionalities. ## How to influence the roadmap diff --git a/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md b/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md index e818557402..a76518b202 100644 --- a/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md +++ b/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md @@ -160,12 +160,12 @@ Create a new `plugins/todo-list-backend/src/conditionExports.ts` file and add th ```typescript import { TODO_LIST_RESOURCE_TYPE } from '@internal/plugin-todo-list-common'; import { createConditionExports } from '@backstage/plugin-permission-node'; -import { permissionRules } from './service/rules'; +import { rules } from './service/rules'; const { conditions, createConditionalDecision } = createConditionExports({ - pluginId: 'catalog', - resourceType: RESOURCE_TYPE_CATALOG_ENTITY, - rules: permissionRules, + pluginId: 'todolist', + resourceType: TODO_LIST_RESOURCE_TYPE, + rules, }); export const todoListConditions = conditions; @@ -173,7 +173,12 @@ export const todoListConditions = conditions; export const createTodoListConditionalDecision = createConditionalDecision; ``` -Make sure `todoListConditions` and `createTodoListConditionalDecision` are exported from the `todo-list-backend` package. +Make sure `todoListConditions` and `createTodoListConditionalDecision` are exported from the `todo-list-backend` package by editing `plugins/todo-list-backend/src/index.ts`: + +```diff + export * from './service/router'; ++ export * from './conditionExports'; +``` ## Test the authorized update endpoint diff --git a/docs/releases/v1.4.0-next.1-changelog.md b/docs/releases/v1.4.0-next.1-changelog.md new file mode 100644 index 0000000000..0780178d4d --- /dev/null +++ b/docs/releases/v1.4.0-next.1-changelog.md @@ -0,0 +1,1474 @@ +# Release v1.4.0-next.1 + +## @backstage/cli@0.18.0-next.1 + +### Minor Changes + +- 96a82d9791: **BREAKING**: Removed the following deprecated package commands: + + - `app:build` - Use `package build` instead + - `app:serve` - Use `package start` instead + - `backend:build` - Use `package build` instead + - `backend:bundle` - Use `package build` instead + - `backend:dev` - Use `package start` instead + - `plugin:build` - Use `package build` instead + - `plugin:serve` - Use `package start` instead + - `build` - Use `package build` instead + - `lint` - Use `package lint` instead + - `prepack` - Use `package prepack` instead + - `postpack` - Use `package postpack` instead + + In order to replace these you need to have [migrated to using package roles](https://backstage.io/docs/tutorials/package-role-migration). + +### Patch Changes + +- 86640214f0: Upgrade `@rollup/plugin-node-resolve` to `^13.0.6` +- e661242844: Updated dependency `run-script-webpack-plugin` to `^0.1.0`. +- Updated dependencies + - @backstage/errors@1.1.0-next.0 + - @backstage/config-loader@1.1.3-next.0 + +## @backstage/errors@1.1.0-next.0 + +### Minor Changes + +- 6d61b44466: The `ResponseError.fromResponse` now accepts a more narrow response type, in order to avoid incompatibilities between different fetch implementations. + + The `response` property of `ResponseError` has also been narrowed to a new `ConsumedResponse` type that omits all the properties for consuming the body of the response. This is not considered a breaking change as it was always an error to try to consume the body of the response. + +## @backstage/plugin-apache-airflow@0.2.0-next.1 + +### Minor Changes + +- 01f976ea72: Exposed DagTableComponent as standalone component + added a prop to get only select DAGs instead of the full list + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + +## @backstage/plugin-auth-backend@0.15.0-next.1 + +### Minor Changes + +- 9d4040777e: **BREAKING**: Removed all directly exported auth provider factories, option types, and sign-in resolvers. For example: `AwsAlbProviderOptions`, `bitbucketUserIdSignInResolver`, `createGithubProvider`. These are all still accessible via the `providers` export. For example, use `providers.github.create()` rather than `createGithubProvider()`, and `providers.bitbucket.resolvers.userIdMatchingUserEntityAnnotation()` rather than `bitbucketUserIdSignInResolver`. + + **BREAKING**: Removed the exported `AuthProviderFactoryOptions` type as well as the deprecated option fields of the `AuthProviderFactory` callback. This includes the `tokenManager`, `tokenIssuer`, `discovery`, and `catalogApi` fields. Existing usage of these should be replaced with the new utilities in the `resolverContext` field. The deprecated `TokenIssuer` type is now also removed, since it is no longer used. + + **BREAKING**: Removed `getEntityClaims`, use `getDefaultOwnershipEntityRefs` instead. + + **DEPRECATION**: Deprecated `AtlassianAuthProvider` as it was unintentionally exported. + +### Patch Changes + +- f2cf79d62e: Added an option for the auth backend router to select the algorithm for the JWT token signing keys +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/plugin-auth-node@0.2.3-next.1 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.0-next.0 + +### Minor Changes + +- 67503d159e: Add basic OpenAPI \\$ref support. + + For more information see [here](https://github.com/backstage/backstage/tree/master/plugins/catalog-backend-module-openapi). + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/integration@1.2.2-next.1 + +## @backstage/plugin-search-backend-module-elasticsearch@0.2.0-next.1 + +### Minor Changes + +- c5af773757: **BREAKING**: In order to remain interoperable with all currently supported + deployments of Elasticsearch, this package will now conditionally use either + the `@elastic/elasticsearch` or `@opensearch-project/opensearch` client when + communicating with your deployed cluster. + + If you do not rely on types exported from this package, or if you do not make + use of the `createElasticSearchClientOptions` or `newClient` methods on the + `ElasticSearchSearchEngine` class, then upgrading to this version should not + require any further action on your part. Everything will continue to work as it + always has. + + If you _do_ rely on either of the above methods or any underlying types, some + changes may be needed to your custom code. A type guard is now exported by this + package (`isOpenSearchCompatible(options)`), which you may use to help clarify + which client options are compatible with which client constructors. + + If you are using this package with the `search.elasticsearch.provider` set to + `aws`, and you are making use of the `newClient` method in particular, you may + wish to start using the `@opensearch-project/opensearch` client in your custom + code. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-node@0.6.3-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + +## @backstage/plugin-techdocs-backend@1.2.0-next.1 + +### Minor Changes + +- 860765ff45: Added local publishing target directory `config`: `techdocs.publisher.local.publishDirectory` + +### Patch Changes + +- 726577958f: Add sample headings on the documented component homepage. +- Updated dependencies + - @backstage/plugin-techdocs-node@1.2.0-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + - @backstage/plugin-catalog-common@1.0.4-next.0 + - @backstage/plugin-permission-common@0.6.3-next.0 + - @backstage/plugin-search-common@0.3.6-next.0 + +## @backstage/plugin-techdocs-node@1.2.0-next.1 + +### Minor Changes + +- 860765ff45: Added local publishing target directory `config`: `techdocs.publisher.local.publishDirectory` + +### Patch Changes + +- a5d73da942: Fix the flag parsing for `legacyCopyReadmeMdToIndexMd` in `techdocs-cli generate` command, and decouple it's logic from the `techdocs-ref` flag. +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/integration@1.2.2-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + +## @backstage/app-defaults@1.0.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-permission-react@0.4.3-next.0 + +## @backstage/backend-common@0.14.1-next.1 + +### Patch Changes + +- 0fc57887e8: Improve plural handling in logging output for secrets +- Updated dependencies + - @backstage/errors@1.1.0-next.0 + - @backstage/integration@1.2.2-next.1 + - @backstage/config-loader@1.1.3-next.0 + +## @backstage/backend-tasks@0.3.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + +## @backstage/backend-test-utils@0.1.26-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.18.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + +## @backstage/catalog-client@1.0.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + +## @backstage/catalog-model@1.1.0-next.1 + +### Patch Changes + +- f1dcc6f3c6: Added type predicates for all entity types, e.g. isUserEntity +- Updated dependencies + - @backstage/errors@1.1.0-next.0 + +## @backstage/config-loader@1.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.1.0-next.0 + +## @backstage/core-components@0.9.6-next.1 + +### Patch Changes + +- 3c440ea77e: Change BackstageIconLinkVertical style to use pallette instead of explicit color +- 7e115d42f9: Support displaying subtitle text in `SidebarSubmenuItem` +- Updated dependencies + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + +## @backstage/create-app@0.4.29-next.1 + +### Patch Changes + +- Bumped create-app version. + +## @backstage/dev-utils@1.0.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/app-defaults@1.0.4-next.1 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/test-utils@1.1.2-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/integration@1.2.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.1.0-next.0 + +## @backstage/integration-react@1.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/integration@1.2.2-next.1 + +## @techdocs/cli@1.1.3-next.1 + +### Patch Changes + +- a5d73da942: Fix the flag parsing for `legacyCopyReadmeMdToIndexMd` in `techdocs-cli generate` command, and decouple it's logic from the `techdocs-ref` flag. +- Updated dependencies + - @backstage/plugin-techdocs-node@1.2.0-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + +## @backstage/test-utils@1.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-permission-common@0.6.3-next.0 + - @backstage/plugin-permission-react@0.4.3-next.0 + +## @backstage/theme@0.2.16-next.0 + +### Patch Changes + +- 4c09c09102: Adds optional `htmlFontSize` property and also sets typography design tokens for h5 and h6 in base theme. + +## @backstage/plugin-adr@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/plugin-adr-common@0.1.2-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + - @backstage/plugin-search-react@0.2.2-next.1 + +## @backstage/plugin-adr-backend@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + - @backstage/plugin-adr-common@0.1.2-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + +## @backstage/plugin-adr-common@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/integration@1.2.2-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + +## @backstage/plugin-airbrake@0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/dev-utils@1.0.4-next.1 + - @backstage/test-utils@1.1.2-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-allure@0.1.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-analytics-module-ga@0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + +## @backstage/plugin-api-docs@0.8.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/plugin-catalog@1.3.1-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-app-backend@0.3.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/config-loader@1.1.3-next.0 + +## @backstage/plugin-auth-node@0.2.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + +## @backstage/plugin-azure-devops@0.1.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-badges@0.2.31-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-badges-backend@0.1.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/catalog-client@1.0.4-next.1 + +## @backstage/plugin-bazaar@0.1.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/cli@0.18.0-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/plugin-catalog@1.3.1-next.1 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-bitrise@0.1.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-catalog@1.3.1-next.1 + +### Patch Changes + +- f1dcc6f3c6: Use entity type predicates from catalog-model +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/plugin-catalog-common@1.0.4-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + - @backstage/plugin-search-react@0.2.2-next.1 + +## @backstage/plugin-catalog-backend@1.2.1-next.1 + +### Patch Changes + +- f1dcc6f3c6: Use entity type predicates from catalog-model +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + - @backstage/plugin-catalog-common@1.0.4-next.0 + - @backstage/plugin-permission-common@0.6.3-next.0 + - @backstage/plugin-permission-node@0.6.3-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + +## @backstage/plugin-catalog-backend-module-aws@0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/backend-tasks@0.3.3-next.1 + - @backstage/integration@1.2.2-next.1 + +## @backstage/plugin-catalog-backend-module-azure@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/backend-tasks@0.3.3-next.1 + - @backstage/integration@1.2.2-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/integration@1.2.2-next.1 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/backend-tasks@0.3.3-next.1 + - @backstage/integration@1.2.2-next.1 + +## @backstage/plugin-catalog-backend-module-github@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/backend-tasks@0.3.3-next.1 + - @backstage/integration@1.2.2-next.1 + +## @backstage/plugin-catalog-backend-module-gitlab@0.1.5-next.1 + +### Patch Changes + +- 49ff472c0b: Add the possibility in the `GitlabDiscoveryEntityProvider` to scan the whole project instead of concrete groups. For that, use a configuration like this one, where the group parameter is omitted (not mandatory anymore): + + ```yaml + catalog: + providers: + gitlab: + yourProviderId: + host: gitlab-host # Identifies one of the hosts set up in the integrations + branch: main # Optional. Uses `master` as default + entityFilename: catalog-info.yaml # Optional. Defaults to `catalog-info.yaml` + ``` + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/backend-tasks@0.3.3-next.1 + - @backstage/integration@1.2.2-next.1 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.1-next.1 + +### Patch Changes + +- fbfbff6bf7: Add possibility to resolve relations by RDN, in addition to UUID and DN +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/backend-tasks@0.3.3-next.1 + +## @backstage/plugin-catalog-common@1.0.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.6.3-next.0 + - @backstage/plugin-search-common@0.3.6-next.0 + +## @backstage/plugin-catalog-graph@0.2.19-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-catalog-import@0.8.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-catalog-react@1.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + - @backstage/plugin-catalog-common@1.0.4-next.0 + - @backstage/plugin-permission-common@0.6.3-next.0 + - @backstage/plugin-permission-react@0.4.3-next.0 + +## @backstage/plugin-circleci@0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-cloudbuild@0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-code-climate@0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-code-coverage@0.1.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-code-coverage-backend@0.1.32-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + +## @backstage/plugin-codescene@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + +## @backstage/plugin-config-schema@0.1.30-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + +## @backstage/plugin-cost-insights@0.11.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + +## @backstage/plugin-dynatrace@0.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + +## @backstage/plugin-explore@0.3.38-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-firehydrant@0.1.24-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-fossa@0.2.39-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-gcalendar@0.3.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + +## @backstage/plugin-gcp-projects@0.3.26-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + +## @backstage/plugin-git-release-manager@0.3.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/integration@1.2.2-next.1 + +## @backstage/plugin-github-actions@0.5.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/integration@1.2.2-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-github-deployments@0.1.38-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/integration@1.2.2-next.1 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-github-pull-requests-board@0.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/integration@1.2.2-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-gitops-profiles@0.3.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + +## @backstage/plugin-gocd@0.1.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-graphiql@0.2.39-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + +## @backstage/plugin-home@0.4.23-next.1 + +### Patch Changes + +- a46e317a75: Added support for customizing the time format used in the `HeaderWorldClock` component + + Here's an example of how this can be used in the `HomePage.tsx` found in `\packages\app\src\components\home` to change the clock to be in the 24hr time format: + + ```diff + +const timeFormat: Intl.DateTimeFormatOptions = { + + hour: '2-digit', + + minute: '2-digit', + + hour12: false, + +}; + + export const homePage = ( + +
} pageTitleOverride="Home"> + + +
+ + + + + + ``` + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/plugin-stack-overflow@0.1.3-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-ilert@0.1.33-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-jenkins@0.7.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + - @backstage/plugin-jenkins-common@0.1.6-next.0 + +## @backstage/plugin-jenkins-backend@0.1.24-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/plugin-auth-node@0.2.3-next.1 + - @backstage/plugin-jenkins-common@0.1.6-next.0 + - @backstage/plugin-permission-common@0.6.3-next.0 + +## @backstage/plugin-jenkins-common@0.1.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.4-next.0 + - @backstage/plugin-permission-common@0.6.3-next.0 + +## @backstage/plugin-kafka@0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-kafka-backend@0.2.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + +## @backstage/plugin-kubernetes@0.6.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-kubernetes-backend@0.7.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + +## @backstage/plugin-lighthouse@0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-newrelic@0.3.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + +## @backstage/plugin-newrelic-dashboard@0.1.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-org@0.5.7-next.1 + +### Patch Changes + +- 1e984b11fc: Render namespaces for teams with subtitles in `MyGroupsSidebarItem` +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-pagerduty@0.5.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-periskop@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-permission-backend@0.5.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-auth-node@0.2.3-next.1 + - @backstage/plugin-permission-common@0.6.3-next.0 + - @backstage/plugin-permission-node@0.6.3-next.1 + +## @backstage/plugin-permission-common@0.6.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.1.0-next.0 + +## @backstage/plugin-permission-node@0.6.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-auth-node@0.2.3-next.1 + - @backstage/plugin-permission-common@0.6.3-next.0 + +## @backstage/plugin-permission-react@0.4.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.6.3-next.0 + +## @backstage/plugin-rollbar@0.4.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-scaffolder@1.4.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/plugin-catalog-common@1.0.4-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + - @backstage/plugin-permission-react@0.4.3-next.0 + +## @backstage/plugin-scaffolder-backend@1.4.0-next.1 + +### Patch Changes + +- 801d606909: Improve error messaging when passing in malformed auth +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.4.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/integration@1.2.2-next.1 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.4.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/integration@1.2.2-next.1 + +## @backstage/plugin-search@0.9.1-next.1 + +### Patch Changes + +- 509c4092f0: To allow people to use a global search context in the search modal, the code for the search modal has been changed to only create a local search context if there is no parent context already defined. + + If you want to continue using a local context even if you define a global one, you will have to wrap the modal in a new local context manually: + + ```tsx + + + + ``` + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + - @backstage/plugin-search-react@0.2.2-next.1 + +## @backstage/plugin-search-backend@0.5.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-auth-node@0.2.3-next.1 + - @backstage/plugin-permission-common@0.6.3-next.0 + - @backstage/plugin-permission-node@0.6.3-next.1 + - @backstage/plugin-search-backend-node@0.6.3-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + +## @backstage/plugin-search-backend-module-pg@0.3.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/plugin-search-backend-node@0.6.3-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + +## @backstage/plugin-search-backend-node@0.6.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/backend-tasks@0.3.3-next.1 + - @backstage/plugin-permission-common@0.6.3-next.0 + - @backstage/plugin-search-common@0.3.6-next.0 + +## @backstage/plugin-search-common@0.3.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.6.3-next.0 + +## @backstage/plugin-search-react@0.2.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-search-common@0.3.6-next.0 + +## @backstage/plugin-sentry@0.3.45-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-shortcuts@0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + +## @backstage/plugin-sonarqube@0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-splunk-on-call@0.3.31-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-stack-overflow@0.1.3-next.1 + +### Patch Changes + +- 52b4f796e3: app-config is now picked up properly. +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/plugin-home@0.4.23-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-search-common@0.3.6-next.0 + +## @backstage/plugin-stack-overflow-backend@0.1.3-next.0 + +### Patch Changes + +- 52b4f796e3: app-config is now picked up properly. +- Updated dependencies + - @backstage/plugin-search-common@0.3.6-next.0 + +## @backstage/plugin-tech-insights@0.2.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-tech-insights-backend@0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/backend-tasks@0.3.3-next.1 + - @backstage/catalog-client@1.0.4-next.1 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + +## @backstage/plugin-tech-radar@0.5.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + +## @backstage/plugin-techdocs@1.2.1-next.1 + +### Patch Changes + +- 726577958f: Remove the 60% factor from the font size calculation of headers to use the exact size defined in BackstageTheme. +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/integration@1.2.2-next.1 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + - @backstage/plugin-search-react@0.2.2-next.1 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/plugin-catalog@1.3.1-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-techdocs@1.2.1-next.1 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/test-utils@1.1.2-next.1 + - @backstage/plugin-search-react@0.2.2-next.1 + +## @backstage/plugin-techdocs-module-addons-contrib@1.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/integration@1.2.2-next.1 + - @backstage/integration-react@1.1.2-next.1 + +## @backstage/plugin-todo@0.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-todo-backend@0.1.31-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + +## @backstage/plugin-user-settings@0.4.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + +## @backstage/plugin-vault@0.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + +## @backstage/plugin-vault-backend@0.2.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/backend-tasks@0.3.3-next.1 + - @backstage/backend-test-utils@0.1.26-next.1 + +## @backstage/plugin-xcmetrics@0.2.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + +## example-app@0.2.73-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/cli@0.18.0-next.1 + - @backstage/plugin-apache-airflow@0.2.0-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/plugin-search@0.9.1-next.1 + - @backstage/plugin-org@0.5.7-next.1 + - @backstage/plugin-catalog@1.3.1-next.1 + - @backstage/plugin-home@0.4.23-next.1 + - @backstage/plugin-stack-overflow@0.1.3-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-techdocs@1.2.1-next.1 + - @backstage/app-defaults@1.0.4-next.1 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/plugin-airbrake@0.3.7-next.1 + - @backstage/plugin-api-docs@0.8.7-next.1 + - @backstage/plugin-azure-devops@0.1.23-next.1 + - @backstage/plugin-badges@0.2.31-next.1 + - @backstage/plugin-catalog-common@1.0.4-next.0 + - @backstage/plugin-catalog-graph@0.2.19-next.1 + - @backstage/plugin-catalog-import@0.8.10-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + - @backstage/plugin-circleci@0.3.7-next.1 + - @backstage/plugin-cloudbuild@0.3.7-next.1 + - @backstage/plugin-code-coverage@0.1.34-next.1 + - @backstage/plugin-cost-insights@0.11.29-next.1 + - @backstage/plugin-dynatrace@0.1.1-next.1 + - @backstage/plugin-explore@0.3.38-next.1 + - @backstage/plugin-gcalendar@0.3.3-next.1 + - @backstage/plugin-gcp-projects@0.3.26-next.1 + - @backstage/plugin-github-actions@0.5.7-next.1 + - @backstage/plugin-gocd@0.1.13-next.1 + - @backstage/plugin-graphiql@0.2.39-next.1 + - @backstage/plugin-jenkins@0.7.6-next.1 + - @backstage/plugin-kafka@0.3.7-next.1 + - @backstage/plugin-kubernetes@0.6.7-next.1 + - @backstage/plugin-lighthouse@0.3.7-next.1 + - @backstage/plugin-newrelic@0.3.25-next.1 + - @backstage/plugin-newrelic-dashboard@0.1.15-next.1 + - @backstage/plugin-pagerduty@0.5.0-next.1 + - @backstage/plugin-permission-react@0.4.3-next.0 + - @backstage/plugin-rollbar@0.4.7-next.1 + - @backstage/plugin-scaffolder@1.4.0-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + - @backstage/plugin-sentry@0.3.45-next.1 + - @backstage/plugin-shortcuts@0.2.8-next.1 + - @backstage/plugin-tech-insights@0.2.3-next.1 + - @backstage/plugin-tech-radar@0.5.14-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.2-next.1 + - @backstage/plugin-todo@0.2.9-next.1 + - @backstage/plugin-user-settings@0.4.6-next.1 + - @backstage/plugin-search-react@0.2.2-next.1 + +## example-backend@0.2.73-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.4.0-next.1 + - @backstage/plugin-auth-backend@0.15.0-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/plugin-search-backend-module-elasticsearch@0.2.0-next.1 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/plugin-techdocs-backend@1.2.0-next.1 + - example-app@0.2.73-next.1 + - @backstage/backend-tasks@0.3.3-next.1 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + - @backstage/plugin-app-backend@0.3.34-next.1 + - @backstage/plugin-auth-node@0.2.3-next.1 + - @backstage/plugin-badges-backend@0.1.28-next.1 + - @backstage/plugin-code-coverage-backend@0.1.32-next.1 + - @backstage/plugin-jenkins-backend@0.1.24-next.1 + - @backstage/plugin-kafka-backend@0.2.27-next.1 + - @backstage/plugin-kubernetes-backend@0.7.0-next.1 + - @backstage/plugin-permission-backend@0.5.9-next.1 + - @backstage/plugin-permission-common@0.6.3-next.0 + - @backstage/plugin-permission-node@0.6.3-next.1 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.2-next.1 + - @backstage/plugin-search-backend@0.5.4-next.1 + - @backstage/plugin-search-backend-module-pg@0.3.5-next.1 + - @backstage/plugin-search-backend-node@0.6.3-next.1 + - @backstage/plugin-tech-insights-backend@0.4.2-next.1 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.18-next.1 + - @backstage/plugin-todo-backend@0.1.31-next.1 + +## techdocs-cli-embedded-app@0.2.72-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/cli@0.18.0-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/plugin-catalog@1.3.1-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-techdocs@1.2.1-next.1 + - @backstage/app-defaults@1.0.4-next.1 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/test-utils@1.1.2-next.1 + +## @internal/plugin-todo-list@1.0.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + +## @internal/plugin-todo-list-backend@1.0.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-auth-node@0.2.3-next.1 + +## @internal/plugin-todo-list-common@1.0.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.6.3-next.0 diff --git a/docs/releases/v1.4.0-next.2-changelog.md b/docs/releases/v1.4.0-next.2-changelog.md new file mode 100644 index 0000000000..fe00c648dd --- /dev/null +++ b/docs/releases/v1.4.0-next.2-changelog.md @@ -0,0 +1,1308 @@ +# Release v1.4.0-next.2 + +## @backstage/catalog-model@1.1.0-next.2 + +### Minor Changes + +- 4cc81372f8: Introduced `GroupDefaultParentEntityPolicy` to set a default group entity parent. + +## @backstage/core-components@0.10.0-next.2 + +### Minor Changes + +- 32204fa794: Add `transformLinkUri` and `transformImageUri` to `MarkdownContent` + +### Patch Changes + +- b4b711bcc2: Fix the EntityLayout header style so that EntityContextMenu button can display in correct shape when user hover on it +- 15201b1032: Updated dependency `rc-progress` to `3.4.0`. +- 385389d23c: Updated to remove usage of the `bursts` object in the theme palette +- Updated dependencies + - @backstage/theme@0.2.16-next.1 + +## @backstage/plugin-catalog@1.4.0-next.2 + +### Minor Changes + +- a274fe38b9: Add hidden title column to catalog and API table to enable filtering by title. + +### Patch Changes + +- 258057a4b9: Adding ability to customize the "unregister entity" menu item in the entity context menu on the entity page with options 'visible','hidden','disabled'.With this three new options, one can hide the "unregister entity" menu item from the list, disable or keep it enabled. + + The boolean input for "unregister entity" will be deprecated later in favour of the above three options. + +- 385389d23c: Updated to remove usage of the `bursts` object in the theme palette + +- be26d95141: Added new `EntityProcessingStatusPicker` that will filter for entities with orphans and/or errors. + + If you are using the default Catalog page this picker will be added automatically. For those who have customized their Catalog page you'll need to add this manually by doing something like this: + + ```diff + ... + import { + CatalogFilterLayout, + EntityTypePicker, + UserListPicker, + EntityTagPicker + + EntityProcessingStatusPicker, + } from '@backstage/plugin-catalog-react'; + ... + export const CustomCatalogPage = ({ + columns, + actions, + initiallySelectedFilter = 'owned', + }: CatalogPageProps) => { + return ( + ... + + + + + + ... + }; + ``` + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/plugin-search-react@0.2.2-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/integration-react@1.1.2-next.2 + +## @backstage/plugin-catalog-backend-module-msgraph@0.4.0-next.1 + +### Minor Changes + +- a145672f0f: Align `msgraph` plugin's entity provider config with other providers. **Deprecated** entity processor as well as previous config. + + You will see warning at the log output until you migrate to the new setup. + All deprecated parts will be removed eventually after giving some time to migrate. + + Please find information on how to migrate your current setup to the new one below. + + **Migration Guide:** + + There were two different way on how to use the msgraph plugin: processor or provider. + + Previous registration for the processor: + + ```typescript + // packages/backend/src/plugins/catalog.ts + builder.addProcessor( + MicrosoftGraphOrgReaderProcessor.fromConfig(env.config, { + logger: env.logger, + // [...] + }), + ); + ``` + + Previous registration when using the provider: + + ```typescript + // packages/backend/src/plugins/catalog.ts + builder.addEntityProvider( + MicrosoftGraphOrgEntityProvider.fromConfig(env.config, { + id: 'https://graph.microsoft.com/v1.0', + target: 'https://graph.microsoft.com/v1.0', + logger: env.logger, + schedule: env.scheduler.createScheduledTaskRunner({ + frequency: { minutes: 30 }, + timeout: { minutes: 3 }, + }), + // [...] + }), + ); + ``` + + Previous configuration as used for both: + + ```yaml + # app-config.yaml + catalog: + processors: + microsoftGraphOrg: + providers: + - target: https://graph.microsoft.com/v1.0 + # [...] + ``` + + **Replacement:** + + Please check for the complete documentation of all configuration options (config as well as registration of the provider). + + ```yaml + # app-config.yaml + catalog: + providers: + microsoftGraphOrg: + # In case you used the deprecated configuration with the entity provider + # using the value of `target` will keep the same location key for all + providerId: # some stable ID which will be used as part of the location key for all ingested data + target: https://graph.microsoft.com/v1.0 + # [...] + ``` + + ```typescript + // packages/backend/src/plugins/catalog.ts + builder.addEntityProvider( + MicrosoftGraphOrgEntityProvider.fromConfig(env.config, { + logger: env.logger, + schedule: env.scheduler.createScheduledTaskRunner({ + frequency: { minutes: 30 }, + timeout: { minutes: 3 }, + }), + // [...] + }), + ); + ``` + + In case you've used multiple entity providers before + **and** you had different transformers for each of them + you can provide these directly at the one `fromConfig` call + by passing a Record with the provider ID as key. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-tasks@0.3.3-next.2 + - @backstage/plugin-catalog-backend@1.2.1-next.2 + +## @backstage/plugin-cost-insights-common@0.1.0-next.0 + +### Minor Changes + +- 81dd5ea989: Introduces a new isomorphic @backstage/plugin-cost-insight-common package to contain shared types across all other cost insights packages and modules. + +## @backstage/plugin-scaffolder@1.4.0-next.2 + +### Minor Changes + +- d8eb82f447: Add `allowedRepos` `ui:option` to `RepoUrlPicker` component, and move `repoName` field to own component + +### Patch Changes + +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +- 14146703e5: Add `allowArbitraryValues` to `ui:options` in `OwnedEntityPicker`, similar to `allowArbitraryValues` in `EntityPicker` + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/integration@1.2.2-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/integration-react@1.1.2-next.2 + +## @backstage/plugin-scaffolder-backend@1.4.0-next.2 + +### Minor Changes + +- 4baf8a4ece: Update GitLab Merge Request Action to allow source branch to be deleted +- 2db07887cb: Added two new scaffolder actions: `github:repo:create` and `github:repo:push` + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. + +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + - @backstage/plugin-catalog-backend@1.2.1-next.2 + - @backstage/integration@1.2.2-next.2 + +## @backstage/plugin-tech-insights-backend@0.5.0-next.2 + +### Minor Changes + +- 818fa28d71: Allow FactRetrieverRegistry to be injected into buildTechInsightsContext so that we can override default registry implementation. + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + - @backstage/backend-tasks@0.3.3-next.2 + +## @backstage/app-defaults@1.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## @backstage/backend-common@0.14.1-next.2 + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. + +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +- Updated dependencies + - @backstage/integration@1.2.2-next.2 + +## @backstage/backend-tasks@0.3.3-next.2 + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- Updated dependencies + - @backstage/backend-common@0.14.1-next.2 + +## @backstage/backend-test-utils@0.1.26-next.2 + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- Updated dependencies + - @backstage/backend-common@0.14.1-next.2 + - @backstage/cli@0.18.0-next.2 + +## @backstage/cli@0.18.0-next.2 + +### Patch Changes + +- f6b6fb7165: The `test` command now ensures that all IO is flushed before exiting when printing `--help`. + +## @backstage/create-app@0.4.29-next.2 + +### Patch Changes + +- f281ad17c0: Adds the ability to define the Backstage app name using a `BACKSTAGE_APP_NAME` + environment variable when running `create-app`. + +## @backstage/dev-utils@1.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/app-defaults@1.0.4-next.2 + - @backstage/integration-react@1.1.2-next.2 + +## @backstage/integration@1.2.2-next.2 + +### Patch Changes + +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +## @backstage/integration-react@1.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/integration@1.2.2-next.2 + +## @backstage/theme@0.2.16-next.1 + +### Patch Changes + +- ff4f56eb49: **DEPRECATED**: The `bursts` object from `BackstagePaletteAdditions` has been depreciated and will be removed in a future release + + The `genPageTheme` function now includes an optional options object with an optional `fontColor` which defaults to white if not provided. + +## @backstage/plugin-adr@0.1.2-next.2 + +### Patch Changes + +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/plugin-search-react@0.2.2-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/integration-react@1.1.2-next.2 + +## @backstage/plugin-airbrake@0.3.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/dev-utils@1.0.4-next.2 + +## @backstage/plugin-allure@0.1.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-analytics-module-ga@0.1.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## @backstage/plugin-apache-airflow@0.2.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + +## @backstage/plugin-api-docs@0.8.7-next.2 + +### Patch Changes + +- a274fe38b9: Add hidden title column to catalog and API table to enable filtering by title. +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog@1.4.0-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-app-backend@0.3.34-next.2 + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- Updated dependencies + - @backstage/backend-common@0.14.1-next.2 + +## @backstage/plugin-auth-backend@0.15.0-next.2 + +### Patch Changes + +- 8e03db907a: Auth provider now also export createAuthProviderIntegration +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + +## @backstage/plugin-azure-devops@0.1.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-badges@0.2.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-badges-backend@0.1.28-next.2 + +### Patch Changes + +- 58fd5ee9d5: Add missing installation instructions +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + +## @backstage/plugin-bazaar@0.1.22-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/plugin-catalog@1.4.0-next.2 + - @backstage/cli@0.18.0-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-bazaar-backend@0.1.18-next.1 + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- Updated dependencies + - @backstage/backend-common@0.14.1-next.2 + - @backstage/backend-test-utils@0.1.26-next.2 + +## @backstage/plugin-bitrise@0.1.34-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-catalog-backend@1.2.1-next.2 + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. + +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + - @backstage/integration@1.2.2-next.2 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.0-next.1 + +### Patch Changes + +- 4881dc4c84: Updated dependency `openapi-types` to `^12.0.0`. +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + - @backstage/plugin-catalog-backend@1.2.1-next.2 + - @backstage/integration@1.2.2-next.2 + +## @backstage/plugin-catalog-graph@0.2.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-catalog-import@0.8.10-next.2 + +### Patch Changes + +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/integration@1.2.2-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/integration-react@1.1.2-next.2 + +## @backstage/plugin-catalog-react@1.1.2-next.2 + +### Patch Changes + +- be26d95141: Added new `EntityProcessingStatusPicker` that will filter for entities with orphans and/or errors. + + If you are using the default Catalog page this picker will be added automatically. For those who have customized their Catalog page you'll need to add this manually by doing something like this: + + ```diff + ... + import { + CatalogFilterLayout, + EntityTypePicker, + UserListPicker, + EntityTagPicker + + EntityProcessingStatusPicker, + } from '@backstage/plugin-catalog-react'; + ... + export const CustomCatalogPage = ({ + columns, + actions, + initiallySelectedFilter = 'owned', + }: CatalogPageProps) => { + return ( + ... + + + + + + ... + }; + ``` + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/integration@1.2.2-next.2 + +## @backstage/plugin-circleci@0.3.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-cloudbuild@0.3.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-code-climate@0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-code-coverage@0.1.34-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-code-coverage-backend@0.1.32-next.2 + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + - @backstage/integration@1.2.2-next.2 + +## @backstage/plugin-codescene@0.1.2-next.2 + +### Patch Changes + +- 15201b1032: Updated dependency `rc-progress` to `3.4.0`. +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## @backstage/plugin-config-schema@0.1.30-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## @backstage/plugin-cost-insights@0.11.29-next.2 + +### Patch Changes + +- 3e032a5de2: Move cost-insights data specific API types (non react) into an @backstage/plugin-cost-insights-common + isomorphic package. This allows these types to be shared in any backend packages or other cost-insight + modules. +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/plugin-cost-insights-common@0.1.0-next.0 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## @backstage/plugin-dynatrace@0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## @backstage/plugin-explore@0.3.38-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-firehydrant@0.1.24-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-fossa@0.2.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-gcalendar@0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## @backstage/plugin-gcp-projects@0.3.26-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## @backstage/plugin-git-release-manager@0.3.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/integration@1.2.2-next.2 + +## @backstage/plugin-github-actions@0.5.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/integration@1.2.2-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-github-deployments@0.1.38-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/integration@1.2.2-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/integration-react@1.1.2-next.2 + +## @backstage/plugin-github-pull-requests-board@0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/integration@1.2.2-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-gitops-profiles@0.3.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## @backstage/plugin-gocd@0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-graphiql@0.2.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## @backstage/plugin-home@0.4.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/plugin-stack-overflow@0.1.3-next.2 + +## @backstage/plugin-ilert@0.1.33-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-jenkins@0.7.6-next.2 + +### Patch Changes + +- 8747824221: feature: added support for multiple branches to the `JenkinsApi` +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-jenkins-backend@0.1.24-next.2 + +### Patch Changes + +- 8747824221: feature: added support for multiple branches to the `JenkinsApi` +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + +## @backstage/plugin-kafka@0.3.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-kafka-backend@0.2.27-next.2 + +### Patch Changes + +- 8751667541: Updated dependency `kafkajs` to `^2.0.0`. +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + +## @backstage/plugin-kubernetes@0.6.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/plugin-kubernetes-common@0.4.0-next.1 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-kubernetes-backend@0.7.0-next.2 + +### Patch Changes + +- 60e5f9fe68: Fixed the lack of `limitranges` as part of the Default Objects to fetch from the kubernetes api +- Updated dependencies + - @backstage/plugin-kubernetes-common@0.4.0-next.1 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + +## @backstage/plugin-kubernetes-common@0.4.0-next.1 + +### Patch Changes + +- 60e5f9fe68: Fixed the lack of `limitranges` as part of the Default Objects to fetch from the kubernetes api +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + +## @backstage/plugin-lighthouse@0.3.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-newrelic@0.3.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## @backstage/plugin-newrelic-dashboard@0.1.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-org@0.5.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-pagerduty@0.5.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-periskop@0.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-rollbar@0.4.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-search@0.9.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/plugin-search-react@0.2.2-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-search-backend-module-pg@0.3.5-next.2 + +### Patch Changes + +- 423e3d8e95: **DEPRECATED**: `PgSearchEngine` static `from` has been deprecated and will be removed in a future release. Use static `fromConfig` method to instantiate. + + Added support for highlighting matched terms in search result data + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.2 + +## @backstage/plugin-search-react@0.2.2-next.2 + +### Patch Changes + +- 60408ca9d4: Fix search pagination to reset page cursor also when a term is cleared. +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## @backstage/plugin-sentry@0.3.45-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-shortcuts@0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## @backstage/plugin-sonarqube@0.3.7-next.2 + +### Patch Changes + +- 15201b1032: Updated dependency `rc-progress` to `3.4.0`. +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-splunk-on-call@0.3.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-stack-overflow@0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-home@0.4.23-next.2 + +## @backstage/plugin-tech-insights@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-tech-radar@0.5.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## @backstage/plugin-techdocs@1.2.1-next.2 + +### Patch Changes + +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +- 7739141ab2: Fix: When docs are shown in an entity page under the docs tab the sidebars start overlapping with the header and tabs in the page when you scroll the documentation content. + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/plugin-search-react@0.2.2-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/integration@1.2.2-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/integration-react@1.1.2-next.2 + - @backstage/plugin-techdocs-react@1.0.2-next.1 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/plugin-search-react@0.2.2-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-techdocs@1.2.1-next.2 + - @backstage/plugin-catalog@1.4.0-next.2 + - @backstage/integration-react@1.1.2-next.2 + - @backstage/plugin-techdocs-react@1.0.2-next.1 + +## @backstage/plugin-techdocs-backend@1.2.0-next.2 + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + - @backstage/integration@1.2.2-next.2 + - @backstage/plugin-techdocs-node@1.2.0-next.2 + +## @backstage/plugin-techdocs-module-addons-contrib@1.0.2-next.2 + +### Patch Changes + +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/integration@1.2.2-next.2 + - @backstage/integration-react@1.1.2-next.2 + - @backstage/plugin-techdocs-react@1.0.2-next.1 + +## @backstage/plugin-techdocs-node@1.2.0-next.2 + +### Patch Changes + +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + - @backstage/integration@1.2.2-next.2 + +## @backstage/plugin-techdocs-react@1.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + +## @backstage/plugin-todo@0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-user-settings@0.4.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## @backstage/plugin-vault@0.1.1-next.2 + +### Patch Changes + +- 7ee4abdcc9: Added a path notion in addition to secret name to allow to differentiate secrets in sub-paths +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## @backstage/plugin-vault-backend@0.2.0-next.2 + +### Patch Changes + +- 7ee4abdcc9: Added a path notion in addition to secret name to allow to differentiate secrets in sub-paths +- Updated dependencies + - @backstage/backend-common@0.14.1-next.2 + - @backstage/backend-tasks@0.3.3-next.2 + - @backstage/backend-test-utils@0.1.26-next.2 + +## @backstage/plugin-xcmetrics@0.2.27-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## example-app@0.2.73-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-cost-insights@0.11.29-next.2 + - @backstage/core-components@0.10.0-next.2 + - @backstage/plugin-scaffolder@1.4.0-next.2 + - @backstage/plugin-jenkins@0.7.6-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/plugin-search-react@0.2.2-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-import@0.8.10-next.2 + - @backstage/plugin-techdocs@1.2.1-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.2-next.2 + - @backstage/plugin-api-docs@0.8.7-next.2 + - @backstage/plugin-catalog@1.4.0-next.2 + - @backstage/cli@0.18.0-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/app-defaults@1.0.4-next.2 + - @backstage/integration-react@1.1.2-next.2 + - @backstage/plugin-airbrake@0.3.7-next.2 + - @backstage/plugin-apache-airflow@0.2.0-next.2 + - @backstage/plugin-azure-devops@0.1.23-next.2 + - @backstage/plugin-badges@0.2.31-next.2 + - @backstage/plugin-catalog-graph@0.2.19-next.2 + - @backstage/plugin-circleci@0.3.7-next.2 + - @backstage/plugin-cloudbuild@0.3.7-next.2 + - @backstage/plugin-code-coverage@0.1.34-next.2 + - @backstage/plugin-dynatrace@0.1.1-next.2 + - @backstage/plugin-explore@0.3.38-next.2 + - @backstage/plugin-gcalendar@0.3.3-next.2 + - @backstage/plugin-gcp-projects@0.3.26-next.2 + - @backstage/plugin-github-actions@0.5.7-next.2 + - @backstage/plugin-gocd@0.1.13-next.2 + - @backstage/plugin-graphiql@0.2.39-next.2 + - @backstage/plugin-home@0.4.23-next.2 + - @backstage/plugin-kafka@0.3.7-next.2 + - @backstage/plugin-kubernetes@0.6.7-next.2 + - @backstage/plugin-lighthouse@0.3.7-next.2 + - @backstage/plugin-newrelic@0.3.25-next.2 + - @backstage/plugin-newrelic-dashboard@0.1.15-next.2 + - @backstage/plugin-org@0.5.7-next.2 + - @backstage/plugin-pagerduty@0.5.0-next.2 + - @backstage/plugin-rollbar@0.4.7-next.2 + - @backstage/plugin-search@0.9.1-next.2 + - @backstage/plugin-sentry@0.3.45-next.2 + - @backstage/plugin-shortcuts@0.2.8-next.2 + - @backstage/plugin-stack-overflow@0.1.3-next.2 + - @backstage/plugin-tech-insights@0.2.3-next.2 + - @backstage/plugin-tech-radar@0.5.14-next.2 + - @backstage/plugin-techdocs-react@1.0.2-next.1 + - @backstage/plugin-todo@0.2.9-next.2 + - @backstage/plugin-user-settings@0.4.6-next.2 + +## example-backend@0.2.73-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-kubernetes-backend@0.7.0-next.2 + - @backstage/plugin-tech-insights-backend@0.5.0-next.2 + - @backstage/plugin-jenkins-backend@0.1.24-next.2 + - @backstage/plugin-search-backend-module-pg@0.3.5-next.2 + - @backstage/plugin-scaffolder-backend@1.4.0-next.2 + - @backstage/plugin-auth-backend@0.15.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/plugin-kafka-backend@0.2.27-next.2 + - @backstage/backend-common@0.14.1-next.2 + - @backstage/backend-tasks@0.3.3-next.2 + - @backstage/plugin-app-backend@0.3.34-next.2 + - @backstage/plugin-catalog-backend@1.2.1-next.2 + - @backstage/plugin-code-coverage-backend@0.1.32-next.2 + - @backstage/plugin-techdocs-backend@1.2.0-next.2 + - @backstage/plugin-badges-backend@0.1.28-next.2 + - @backstage/integration@1.2.2-next.2 + - example-app@0.2.73-next.2 + +## techdocs-cli-embedded-app@0.2.72-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-techdocs@1.2.1-next.2 + - @backstage/plugin-catalog@1.4.0-next.2 + - @backstage/cli@0.18.0-next.2 + - @backstage/app-defaults@1.0.4-next.2 + - @backstage/integration-react@1.1.2-next.2 + - @backstage/plugin-techdocs-react@1.0.2-next.1 + +## @internal/plugin-todo-list@1.0.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 diff --git a/microsite/data/on-demand/20211117-01.yaml b/microsite/data/on-demand/20211117-1.yaml similarity index 100% rename from microsite/data/on-demand/20211117-01.yaml rename to microsite/data/on-demand/20211117-1.yaml diff --git a/microsite/data/on-demand/20211118-01.yaml b/microsite/data/on-demand/20211118-1.yaml similarity index 100% rename from microsite/data/on-demand/20211118-01.yaml rename to microsite/data/on-demand/20211118-1.yaml diff --git a/microsite/data/on-demand/20211215-01.yaml b/microsite/data/on-demand/20211215-1.yaml similarity index 100% rename from microsite/data/on-demand/20211215-01.yaml rename to microsite/data/on-demand/20211215-1.yaml diff --git a/microsite/data/on-demand/20211216-01.yaml b/microsite/data/on-demand/20211216-1.yaml similarity index 100% rename from microsite/data/on-demand/20211216-01.yaml rename to microsite/data/on-demand/20211216-1.yaml diff --git a/microsite/data/on-demand/20220216-01.yaml b/microsite/data/on-demand/20220216-1.yaml similarity index 100% rename from microsite/data/on-demand/20220216-01.yaml rename to microsite/data/on-demand/20220216-1.yaml diff --git a/microsite/data/on-demand/20220223-01.yaml b/microsite/data/on-demand/20220223-1.yaml similarity index 100% rename from microsite/data/on-demand/20220223-01.yaml rename to microsite/data/on-demand/20220223-1.yaml diff --git a/microsite/data/on-demand/20220518-01.yaml b/microsite/data/on-demand/20220518-1.yaml similarity index 100% rename from microsite/data/on-demand/20220518-01.yaml rename to microsite/data/on-demand/20220518-1.yaml diff --git a/microsite/data/on-demand/20220525.yaml b/microsite/data/on-demand/20220525-1.yaml similarity index 100% rename from microsite/data/on-demand/20220525.yaml rename to microsite/data/on-demand/20220525-1.yaml diff --git a/microsite/data/on-demand/20220615-01.yaml b/microsite/data/on-demand/20220615-1.yaml similarity index 97% rename from microsite/data/on-demand/20220615-01.yaml rename to microsite/data/on-demand/20220615-1.yaml index 8ac660a71c..fb296dd6ce 100644 --- a/microsite/data/on-demand/20220615-01.yaml +++ b/microsite/data/on-demand/20220615-1.yaml @@ -1,7 +1,7 @@ --- title: Adopters Community Sessions date: June 15, 2022 -category: Upcoming +category: Meetup description: Adopters Community Session ✨. It's the monthly meetup where we all come together to listen to the latest maintainer updates, learn from each other about adopting, share exciting new demos or discuss any relevant topic like developer effectiveness, developer experience, developer portals, etc. youtubeUrl: https://youtu.be/aKZnjnE5Wy8 youtubeImgUrl: https://backstage.io/img/b-sessions.png diff --git a/microsite/data/on-demand/20220622-1.yaml b/microsite/data/on-demand/20220622-1.yaml index 0bbd53525a..27634609cb 100644 --- a/microsite/data/on-demand/20220622-1.yaml +++ b/microsite/data/on-demand/20220622-1.yaml @@ -1,9 +1,9 @@ --- title: Contributor Community Sessions date: June 22, 2022 -category: Upcoming +category: Meetup description: Join the maintainers and contributors for the Contributor Community Sessions -youtubeUrl: https://youtu.be/aKZnjnE5Wy8 +youtubeUrl: https://youtu.be/E-jWqWXBxUY youtubeImgUrl: https://backstage.io/img/b-sessions.png rsvpUrl: https://calendar.google.com/calendar/embed?src=c_qup9gbhn9sqpuao6trttd8mk5s@group.calendar.google.com eventUrl: https://github.com/backstage/community/issues/49 diff --git a/microsite/data/on-demand/20220720-1.yaml b/microsite/data/on-demand/20220720-1.yaml new file mode 100644 index 0000000000..a1f51859f4 --- /dev/null +++ b/microsite/data/on-demand/20220720-1.yaml @@ -0,0 +1,9 @@ +--- +title: Adopters Community Sessions +date: July 20, 2022 +category: Upcoming +description: Adopters Community Session ✨. It's the monthly meetup where we all come together to listen to the latest maintainer updates, learn from each other about adopting, share exciting new demos or discuss any relevant topic like developer effectiveness, developer experience, developer portals, etc. +youtubeUrl: https://youtu.be/4VFNlPxWcx8 +youtubeImgUrl: https://backstage.io/img/b-sessions.png +rsvpUrl: https://calendar.google.com/calendar/embed?src=c_qup9gbhn9sqpuao6trttd8mk5s@group.calendar.google.com +eventUrl: https://github.com/backstage/community/issues/52 diff --git a/microsite/data/on-demand/20220727-1.yaml b/microsite/data/on-demand/20220727-1.yaml new file mode 100644 index 0000000000..5f7712596f --- /dev/null +++ b/microsite/data/on-demand/20220727-1.yaml @@ -0,0 +1,9 @@ +--- +title: Contributor Community Sessions +date: July 27, 2022 +category: Upcoming +description: Join the maintainers and contributors for the Contributor Community Sessions +youtubeUrl: https://youtu.be/4VFNlPxWcx8 +youtubeImgUrl: https://backstage.io/img/b-sessions.png +rsvpUrl: https://calendar.google.com/calendar/embed?src=c_qup9gbhn9sqpuao6trttd8mk5s@group.calendar.google.com +eventUrl: https://github.com/backstage/community/issues/52 diff --git a/microsite/pages/en/community.js b/microsite/pages/en/community.js index 26366b25df..3d79c82f93 100644 --- a/microsite/pages/en/community.js +++ b/microsite/pages/en/community.js @@ -8,6 +8,30 @@ const React = require('react'); const Components = require(`${process.cwd()}/core/Components.js`); const Block = Components.Block; +const BulletLine = Components.BulletLine; + +const PARTNERS = [ + { + name: 'Frontside Software', + url: 'https://frontside.com/backstage/', + logo: 'img/partner-logo-frontside.png', + }, + { + name: 'Roadie', + url: 'https://roadie.io/', + logo: 'img/partner-logo-roadie.png', + }, + { + name: 'ThoughtWorks', + url: 'https://www.thoughtworks.com', + logo: 'img/partner-logo-thoughtworks.png', + }, + { + name: 'VMWare', + url: 'https://www.vmware.com', + logo: 'img/partner-logo-vmware.png', + }, +]; const Background = props => { const { config: siteConfig } = props; @@ -17,14 +41,11 @@ const Background = props => { - Backstage Community - - + Backstage Community - What's the use of having fun if you can't share it? Exactly. Join - the vibrant community around the Backstage project. Be it on - GitHub, social media, Discord... You'll find a welcoming - environment. To ensure this, we follow the{' '} + Join the vibrant community around Backstage through social media + and different meetups. To ensure that you have a welcoming + environment, we follow{' '} {' '} CNCF Code of Conduct @@ -32,110 +53,110 @@ const Background = props => { in everything we do. - + - Main community channels -
- Chat and get support on our{' '} -
Discord -
- Get into contributing with the{' '} - - Good First Issues - -
- Subscribe to the{' '} - - Community newsletter - -
- Join the{' '} - - Twitter community - -
+ + Get started in our community! + +
- - - - Backstage Community Sessions - - Missed a meetup? Wondering when the next one is coming up? We've - got you covered! Check out our all-new Meetups page. - - Meetups - - - Adopter Community Sessions - - Backstage Community Sessions is the monthly meetup where we all - come together to listen to the latest maintainer updates, learn - from each other about adopting, share exciting new demos or - discuss any relevant topic like developer effectiveness, developer - experience, developer portals, etc. Have something to share, or a - burning question? Add it to the{' '} - issue. - - - - Contributor Community Sessions - - Discuss all things contributing, diving deep under the hood of - Backstage (Backstage of Backstage? Backerstage?). An open - discussion with maintainers and contributors of Backstage. If you - like Backstage, this is your favorite Zoom meeting of the month, - guaranteed! Have something to share, or a burning question? Add it - to the{' '} - issue. - + + + + Offical Backstage initiatives + + Stay tuned to the latest developments + + + + + Community sessions + + Maintainers and adopters meet monthly to share updates, demos, + and ideas. Yep, all sessions are recorded! + + + Join a session + + + + + Newsletter + + The official monthly Backstage newsletter. Don't miss the latest + news from your favorite project! + + + Subscribe + + + + + Contributor Spotlight + + A recognition for valuable community work. Nominate contributing + members for their efforts! We'll put them in the spotlight ❤️ + + Nominate now + + - - - - - Backstage official Newsletter + + + + Community initiatives - + + Open Mic Meetup - The official monthly Backstage newsletter. Containing the latest - news from your favorite project. - - - Subscribe - - - - - - - - - Spotlight - - A recognition for valuable community work, the{' '} - Contributor Spotlight. Nominate contributing members for - their efforts! We'll put them in the spotlight ❤️. -
-
- Nominate now -
- - Open Mic Meetup - - A monthly casual get together of Backstage users sharing their - experiences and helping each other. Hosted by{' '} + A casual get together of Backstage users sharing their experiences + and helping each other. Hosted by{' '} Roadie.io and{' '} Frontside Software. -
Learn more
- - Backstage Weekly + + Backstage Weekly Newsletter A weekly newsletter with news, updates and things community from your friends at Roadie.io. @@ -146,6 +167,23 @@ const Background = props => {
+ + + + + Commercial Partners + + {PARTNERS.map(partner => ( + + + + {partner.name} + + + + ))} + + ); }; diff --git a/microsite/pages/en/live.js b/microsite/pages/en/live.js index 062af419fc..f2ebd4bb1d 100644 --- a/microsite/pages/en/live.js +++ b/microsite/pages/en/live.js @@ -34,7 +34,7 @@ const Background = props => { diff --git a/microsite/static/img/partner-logo-frontside.png b/microsite/static/img/partner-logo-frontside.png new file mode 100644 index 0000000000..c8cad6bce1 Binary files /dev/null and b/microsite/static/img/partner-logo-frontside.png differ diff --git a/microsite/static/img/partner-logo-roadie.png b/microsite/static/img/partner-logo-roadie.png new file mode 100644 index 0000000000..41b169f55b Binary files /dev/null and b/microsite/static/img/partner-logo-roadie.png differ diff --git a/microsite/static/img/partner-logo-thoughtworks.png b/microsite/static/img/partner-logo-thoughtworks.png new file mode 100644 index 0000000000..53c3bc2a9e Binary files /dev/null and b/microsite/static/img/partner-logo-thoughtworks.png differ diff --git a/microsite/static/img/partner-logo-vmware.png b/microsite/static/img/partner-logo-vmware.png new file mode 100644 index 0000000000..049975ca15 Binary files /dev/null and b/microsite/static/img/partner-logo-vmware.png differ diff --git a/package.json b/package.json index 823db687d3..9f219cfa11 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@types/react": "^17", "@types/react-dom": "^17" }, - "version": "1.4.0-next.0", + "version": "1.4.0-next.2", "dependencies": { "@manypkg/get-packages": "^1.1.3", "@microsoft/api-documenter": "^7.17.11", diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index 929e53e248..2786d4a5e4 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/app-defaults +## 1.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## 1.0.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-permission-react@0.4.3-next.0 + ## 1.0.4-next.0 ### Patch Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index 92de05204d..e67af42404 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/app-defaults", "description": "Provides the default wiring of a Backstage App", - "version": "1.0.4-next.0", + "version": "1.0.4-next.2", "private": false, "publishConfig": { "access": "public", @@ -33,11 +33,11 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-permission-react": "^0.4.2", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-permission-react": "^0.4.3-next.0", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "react-router-dom": "6.0.0-beta.0" @@ -46,8 +46,8 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/cli": "^0.18.0-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@types/jest": "^26.0.7", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 119200eca6..0f28d87448 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,117 @@ # example-app +## 0.2.73-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-cost-insights@0.11.29-next.2 + - @backstage/core-components@0.10.0-next.2 + - @backstage/plugin-scaffolder@1.4.0-next.2 + - @backstage/plugin-jenkins@0.7.6-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/plugin-search-react@0.2.2-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-import@0.8.10-next.2 + - @backstage/plugin-techdocs@1.2.1-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.2-next.2 + - @backstage/plugin-api-docs@0.8.7-next.2 + - @backstage/plugin-catalog@1.4.0-next.2 + - @backstage/cli@0.18.0-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/app-defaults@1.0.4-next.2 + - @backstage/integration-react@1.1.2-next.2 + - @backstage/plugin-airbrake@0.3.7-next.2 + - @backstage/plugin-apache-airflow@0.2.0-next.2 + - @backstage/plugin-azure-devops@0.1.23-next.2 + - @backstage/plugin-badges@0.2.31-next.2 + - @backstage/plugin-catalog-graph@0.2.19-next.2 + - @backstage/plugin-circleci@0.3.7-next.2 + - @backstage/plugin-cloudbuild@0.3.7-next.2 + - @backstage/plugin-code-coverage@0.1.34-next.2 + - @backstage/plugin-dynatrace@0.1.1-next.2 + - @backstage/plugin-explore@0.3.38-next.2 + - @backstage/plugin-gcalendar@0.3.3-next.2 + - @backstage/plugin-gcp-projects@0.3.26-next.2 + - @backstage/plugin-github-actions@0.5.7-next.2 + - @backstage/plugin-gocd@0.1.13-next.2 + - @backstage/plugin-graphiql@0.2.39-next.2 + - @backstage/plugin-home@0.4.23-next.2 + - @backstage/plugin-kafka@0.3.7-next.2 + - @backstage/plugin-kubernetes@0.6.7-next.2 + - @backstage/plugin-lighthouse@0.3.7-next.2 + - @backstage/plugin-newrelic@0.3.25-next.2 + - @backstage/plugin-newrelic-dashboard@0.1.15-next.2 + - @backstage/plugin-org@0.5.7-next.2 + - @backstage/plugin-pagerduty@0.5.0-next.2 + - @backstage/plugin-rollbar@0.4.7-next.2 + - @backstage/plugin-search@0.9.1-next.2 + - @backstage/plugin-sentry@0.3.45-next.2 + - @backstage/plugin-shortcuts@0.2.8-next.2 + - @backstage/plugin-stack-overflow@0.1.3-next.2 + - @backstage/plugin-tech-insights@0.2.3-next.2 + - @backstage/plugin-tech-radar@0.5.14-next.2 + - @backstage/plugin-techdocs-react@1.0.2-next.1 + - @backstage/plugin-todo@0.2.9-next.2 + - @backstage/plugin-user-settings@0.4.6-next.2 + +## 0.2.73-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/cli@0.18.0-next.1 + - @backstage/plugin-apache-airflow@0.2.0-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/plugin-search@0.9.1-next.1 + - @backstage/plugin-org@0.5.7-next.1 + - @backstage/plugin-catalog@1.3.1-next.1 + - @backstage/plugin-home@0.4.23-next.1 + - @backstage/plugin-stack-overflow@0.1.3-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-techdocs@1.2.1-next.1 + - @backstage/app-defaults@1.0.4-next.1 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/plugin-airbrake@0.3.7-next.1 + - @backstage/plugin-api-docs@0.8.7-next.1 + - @backstage/plugin-azure-devops@0.1.23-next.1 + - @backstage/plugin-badges@0.2.31-next.1 + - @backstage/plugin-catalog-common@1.0.4-next.0 + - @backstage/plugin-catalog-graph@0.2.19-next.1 + - @backstage/plugin-catalog-import@0.8.10-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + - @backstage/plugin-circleci@0.3.7-next.1 + - @backstage/plugin-cloudbuild@0.3.7-next.1 + - @backstage/plugin-code-coverage@0.1.34-next.1 + - @backstage/plugin-cost-insights@0.11.29-next.1 + - @backstage/plugin-dynatrace@0.1.1-next.1 + - @backstage/plugin-explore@0.3.38-next.1 + - @backstage/plugin-gcalendar@0.3.3-next.1 + - @backstage/plugin-gcp-projects@0.3.26-next.1 + - @backstage/plugin-github-actions@0.5.7-next.1 + - @backstage/plugin-gocd@0.1.13-next.1 + - @backstage/plugin-graphiql@0.2.39-next.1 + - @backstage/plugin-jenkins@0.7.6-next.1 + - @backstage/plugin-kafka@0.3.7-next.1 + - @backstage/plugin-kubernetes@0.6.7-next.1 + - @backstage/plugin-lighthouse@0.3.7-next.1 + - @backstage/plugin-newrelic@0.3.25-next.1 + - @backstage/plugin-newrelic-dashboard@0.1.15-next.1 + - @backstage/plugin-pagerduty@0.5.0-next.1 + - @backstage/plugin-permission-react@0.4.3-next.0 + - @backstage/plugin-rollbar@0.4.7-next.1 + - @backstage/plugin-scaffolder@1.4.0-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + - @backstage/plugin-sentry@0.3.45-next.1 + - @backstage/plugin-shortcuts@0.2.8-next.1 + - @backstage/plugin-tech-insights@0.2.3-next.1 + - @backstage/plugin-tech-radar@0.5.14-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.2-next.1 + - @backstage/plugin-todo@0.2.9-next.1 + - @backstage/plugin-user-settings@0.4.6-next.1 + - @backstage/plugin-search-react@0.2.2-next.1 + ## 0.2.73-next.0 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 9c43f03f49..c114d79250 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,67 +1,67 @@ { "name": "example-app", - "version": "0.2.73-next.0", + "version": "0.2.73-next.2", "private": true, "backstage": { "role": "frontend" }, "bundled": true, "dependencies": { - "@backstage/app-defaults": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/cli": "^0.17.3-next.0", + "@backstage/app-defaults": "^1.0.4-next.2", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/cli": "^0.18.0-next.2", "@backstage/config": "^1.0.1", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/integration-react": "^1.1.2-next.0", - "@backstage/plugin-airbrake": "^0.3.7-next.0", - "@backstage/plugin-api-docs": "^0.8.7-next.0", - "@backstage/plugin-azure-devops": "^0.1.23-next.0", - "@backstage/plugin-apache-airflow": "^0.1.15-next.0", - "@backstage/plugin-badges": "^0.2.31-next.0", - "@backstage/plugin-catalog": "^1.3.1-next.0", - "@backstage/plugin-catalog-common": "^1.0.3", - "@backstage/plugin-catalog-graph": "^0.2.19-next.0", - "@backstage/plugin-catalog-import": "^0.8.10-next.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/plugin-circleci": "^0.3.7-next.0", - "@backstage/plugin-cloudbuild": "^0.3.7-next.0", - "@backstage/plugin-code-coverage": "^0.1.34-next.0", - "@backstage/plugin-cost-insights": "^0.11.29-next.0", - "@backstage/plugin-dynatrace": "^0.1.1-next.0", - "@backstage/plugin-explore": "^0.3.38-next.0", - "@backstage/plugin-gcalendar": "^0.3.3-next.0", - "@backstage/plugin-gcp-projects": "^0.3.26-next.0", - "@backstage/plugin-github-actions": "^0.5.7-next.0", - "@backstage/plugin-gocd": "^0.1.13-next.0", - "@backstage/plugin-graphiql": "^0.2.39-next.0", - "@backstage/plugin-home": "^0.4.23-next.0", - "@backstage/plugin-jenkins": "^0.7.6-next.0", - "@backstage/plugin-kafka": "^0.3.7-next.0", - "@backstage/plugin-kubernetes": "^0.6.7-next.0", - "@backstage/plugin-lighthouse": "^0.3.7-next.0", - "@backstage/plugin-newrelic": "^0.3.25-next.0", - "@backstage/plugin-newrelic-dashboard": "^0.1.15-next.0", - "@backstage/plugin-org": "^0.5.7-next.0", - "@backstage/plugin-pagerduty": "0.5.0-next.0", - "@backstage/plugin-permission-react": "^0.4.2", - "@backstage/plugin-rollbar": "^0.4.7-next.0", - "@backstage/plugin-scaffolder": "^1.4.0-next.0", - "@backstage/plugin-search": "^0.9.1-next.0", - "@backstage/plugin-search-react": "^0.2.2-next.0", - "@backstage/plugin-search-common": "^0.3.5", - "@backstage/plugin-sentry": "^0.3.45-next.0", - "@backstage/plugin-shortcuts": "^0.2.8-next.0", - "@backstage/plugin-stack-overflow": "^0.1.3-next.0", - "@backstage/plugin-tech-radar": "^0.5.14-next.0", - "@backstage/plugin-techdocs": "^1.2.1-next.0", - "@backstage/plugin-techdocs-react": "^1.0.2-next.0", - "@backstage/plugin-techdocs-module-addons-contrib": "^1.0.2-next.0", - "@backstage/plugin-todo": "^0.2.9-next.0", - "@backstage/plugin-user-settings": "^0.4.6-next.0", - "@backstage/plugin-tech-insights": "^0.2.3-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/integration-react": "^1.1.2-next.2", + "@backstage/plugin-airbrake": "^0.3.7-next.2", + "@backstage/plugin-api-docs": "^0.8.7-next.2", + "@backstage/plugin-azure-devops": "^0.1.23-next.2", + "@backstage/plugin-apache-airflow": "^0.2.0-next.2", + "@backstage/plugin-badges": "^0.2.31-next.2", + "@backstage/plugin-catalog": "^1.4.0-next.2", + "@backstage/plugin-catalog-common": "^1.0.4-next.0", + "@backstage/plugin-catalog-graph": "^0.2.19-next.2", + "@backstage/plugin-catalog-import": "^0.8.10-next.2", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/plugin-circleci": "^0.3.7-next.2", + "@backstage/plugin-cloudbuild": "^0.3.7-next.2", + "@backstage/plugin-code-coverage": "^0.1.34-next.2", + "@backstage/plugin-cost-insights": "^0.11.29-next.2", + "@backstage/plugin-dynatrace": "^0.1.1-next.2", + "@backstage/plugin-explore": "^0.3.38-next.2", + "@backstage/plugin-gcalendar": "^0.3.3-next.2", + "@backstage/plugin-gcp-projects": "^0.3.26-next.2", + "@backstage/plugin-github-actions": "^0.5.7-next.2", + "@backstage/plugin-gocd": "^0.1.13-next.2", + "@backstage/plugin-graphiql": "^0.2.39-next.2", + "@backstage/plugin-home": "^0.4.23-next.2", + "@backstage/plugin-jenkins": "^0.7.6-next.2", + "@backstage/plugin-kafka": "^0.3.7-next.2", + "@backstage/plugin-kubernetes": "^0.6.7-next.2", + "@backstage/plugin-lighthouse": "^0.3.7-next.2", + "@backstage/plugin-newrelic": "^0.3.25-next.2", + "@backstage/plugin-newrelic-dashboard": "^0.1.15-next.2", + "@backstage/plugin-org": "^0.5.7-next.2", + "@backstage/plugin-pagerduty": "0.5.0-next.2", + "@backstage/plugin-permission-react": "^0.4.3-next.0", + "@backstage/plugin-rollbar": "^0.4.7-next.2", + "@backstage/plugin-scaffolder": "^1.4.0-next.2", + "@backstage/plugin-search": "^0.9.1-next.2", + "@backstage/plugin-search-react": "^0.2.2-next.2", + "@backstage/plugin-search-common": "^0.3.6-next.0", + "@backstage/plugin-sentry": "^0.3.45-next.2", + "@backstage/plugin-shortcuts": "^0.2.8-next.2", + "@backstage/plugin-stack-overflow": "^0.1.3-next.2", + "@backstage/plugin-tech-radar": "^0.5.14-next.2", + "@backstage/plugin-techdocs": "^1.2.1-next.2", + "@backstage/plugin-techdocs-react": "^1.0.2-next.1", + "@backstage/plugin-techdocs-module-addons-contrib": "^1.0.2-next.2", + "@backstage/plugin-todo": "^0.2.9-next.2", + "@backstage/plugin-user-settings": "^0.4.6-next.2", + "@backstage/plugin-tech-insights": "^0.2.3-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -81,7 +81,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/test-utils": "^1.1.2-next.1", "@rjsf/core": "^3.2.1", "@testing-library/cypress": "^8.0.2", "@testing-library/jest-dom": "^5.10.1", diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 1958aabd2e..155dc071ff 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -167,7 +167,12 @@ const EntityLayoutWrapper = (props: { children?: ReactNode }) => { return ( <> - + {props.children}
} pageTitleOverride="Home"> - +
diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index 92b3271ec0..a052e37fe7 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/backend-common +## 0.14.1-next.2 + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +- Updated dependencies + - @backstage/integration@1.2.2-next.2 + +## 0.14.1-next.1 + +### Patch Changes + +- 0fc57887e8: Improve plural handling in logging output for secrets +- Updated dependencies + - @backstage/errors@1.1.0-next.0 + - @backstage/integration@1.2.2-next.1 + - @backstage/config-loader@1.1.3-next.0 + ## 0.14.1-next.0 ### Patch Changes diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 9c459373ff..422465ee6f 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-common", "description": "Common functionality library for Backstage backends", - "version": "0.14.1-next.0", + "version": "0.14.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -36,9 +36,9 @@ "dependencies": { "@backstage/cli-common": "^0.1.9", "@backstage/config": "^1.0.1", - "@backstage/config-loader": "^1.1.2", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", + "@backstage/config-loader": "^1.1.3-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.2", "@backstage/types": "^1.0.0", "@google-cloud/storage": "^6.0.0", "@manypkg/get-packages": "^1.1.3", @@ -58,14 +58,14 @@ "express": "^4.17.1", "express-promise-router": "^4.1.0", "fs-extra": "10.1.0", - "git-url-parse": "^11.6.0", + "git-url-parse": "^12.0.0", "helmet": "^5.0.2", "isomorphic-git": "^1.8.0", "jose": "^4.6.0", "keyv": "^4.0.3", "keyv-memcache": "^1.2.5", "@keyv/redis": "^2.2.3", - "knex": "^1.0.2", + "knex": "^2.0.0", "lodash": "^4.17.21", "logform": "^2.3.2", "luxon": "^2.3.1", @@ -91,8 +91,8 @@ } }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.26-next.0", - "@backstage/cli": "^0.17.3-next.0", + "@backstage/backend-test-utils": "^0.1.26-next.2", + "@backstage/cli": "^0.18.0-next.2", "@types/archiver": "^5.1.0", "@types/base64-stream": "^1.0.2", "@types/compression": "^1.7.0", @@ -112,7 +112,7 @@ "better-sqlite3": "^7.5.0", "http-errors": "^2.0.0", "mock-fs": "^5.1.0", - "msw": "^0.42.0", + "msw": "^0.43.0", "mysql2": "^2.2.5", "recursive-readdir": "^2.2.2", "supertest": "^6.1.3" diff --git a/packages/backend-common/src/database/DatabaseManager.ts b/packages/backend-common/src/database/DatabaseManager.ts index 503945e594..004e7d13cd 100644 --- a/packages/backend-common/src/database/DatabaseManager.ts +++ b/packages/backend-common/src/database/DatabaseManager.ts @@ -251,7 +251,7 @@ export class DatabaseManager { // include base connection if client type has not been overridden ...(overridden ? {} : baseConnection), ...connection, - }; + } as Partial; } /** diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md index b73abb2d5a..782088ff84 100644 --- a/packages/backend-tasks/CHANGELOG.md +++ b/packages/backend-tasks/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/backend-tasks +## 0.3.3-next.2 + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- Updated dependencies + - @backstage/backend-common@0.14.1-next.2 + +## 0.3.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + ## 0.3.3-next.0 ### Patch Changes diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index f99baea1d5..91b94d4d1c 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.3.3-next.0", + "version": "0.3.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -33,13 +33,13 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", + "@backstage/backend-common": "^0.14.1-next.2", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", + "@backstage/errors": "^1.1.0-next.0", "@backstage/types": "^1.0.0", "@types/luxon": "^2.0.4", "cron": "^2.0.0", - "knex": "^1.0.2", + "knex": "^2.0.0", "lodash": "^4.17.21", "luxon": "^2.0.2", "node-abort-controller": "^3.0.1", @@ -48,8 +48,8 @@ "zod": "^3.9.5" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.26-next.0", - "@backstage/cli": "^0.17.3-next.0", + "@backstage/backend-test-utils": "^0.1.26-next.2", + "@backstage/cli": "^0.18.0-next.2", "@types/cron": "^2.0.0", "wait-for-expect": "^3.0.2" }, diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index a9da9b0a3c..e0bb57a3f0 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/backend-test-utils +## 0.1.26-next.2 + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- Updated dependencies + - @backstage/backend-common@0.14.1-next.2 + - @backstage/cli@0.18.0-next.2 + +## 0.1.26-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.18.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + ## 0.1.26-next.0 ### Patch Changes diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 56aa23bfd8..53953ba85e 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.26-next.0", + "version": "0.1.26-next.2", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -34,19 +34,19 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/cli": "^0.17.3-next.0", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/cli": "^0.18.0-next.2", "@backstage/config": "^1.0.1", "better-sqlite3": "^7.5.0", - "knex": "^1.0.2", - "msw": "^0.42.0", + "knex": "^2.0.0", + "msw": "^0.43.0", "mysql2": "^2.2.5", "pg": "^8.3.0", "testcontainers": "^8.1.2", "uuid": "^8.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0" + "@backstage/cli": "^0.18.0-next.2" }, "files": [ "dist" diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index 3dfde23cae..02eac85805 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,62 @@ # example-backend +## 0.2.73-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-kubernetes-backend@0.7.0-next.2 + - @backstage/plugin-tech-insights-backend@0.5.0-next.2 + - @backstage/plugin-jenkins-backend@0.1.24-next.2 + - @backstage/plugin-search-backend-module-pg@0.3.5-next.2 + - @backstage/plugin-scaffolder-backend@1.4.0-next.2 + - @backstage/plugin-auth-backend@0.15.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/plugin-kafka-backend@0.2.27-next.2 + - @backstage/backend-common@0.14.1-next.2 + - @backstage/backend-tasks@0.3.3-next.2 + - @backstage/plugin-app-backend@0.3.34-next.2 + - @backstage/plugin-catalog-backend@1.2.1-next.2 + - @backstage/plugin-code-coverage-backend@0.1.32-next.2 + - @backstage/plugin-techdocs-backend@1.2.0-next.2 + - @backstage/plugin-badges-backend@0.1.28-next.2 + - @backstage/integration@1.2.2-next.2 + - example-app@0.2.73-next.2 + +## 0.2.73-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.4.0-next.1 + - @backstage/plugin-auth-backend@0.15.0-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/plugin-search-backend-module-elasticsearch@0.2.0-next.1 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/plugin-techdocs-backend@1.2.0-next.1 + - example-app@0.2.73-next.1 + - @backstage/backend-tasks@0.3.3-next.1 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + - @backstage/plugin-app-backend@0.3.34-next.1 + - @backstage/plugin-auth-node@0.2.3-next.1 + - @backstage/plugin-badges-backend@0.1.28-next.1 + - @backstage/plugin-code-coverage-backend@0.1.32-next.1 + - @backstage/plugin-jenkins-backend@0.1.24-next.1 + - @backstage/plugin-kafka-backend@0.2.27-next.1 + - @backstage/plugin-kubernetes-backend@0.7.0-next.1 + - @backstage/plugin-permission-backend@0.5.9-next.1 + - @backstage/plugin-permission-common@0.6.3-next.0 + - @backstage/plugin-permission-node@0.6.3-next.1 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.2-next.1 + - @backstage/plugin-search-backend@0.5.4-next.1 + - @backstage/plugin-search-backend-module-pg@0.3.5-next.1 + - @backstage/plugin-search-backend-node@0.6.3-next.1 + - @backstage/plugin-tech-insights-backend@0.4.2-next.1 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.18-next.1 + - @backstage/plugin-todo-backend@0.1.31-next.1 + ## 0.2.73-next.0 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index 0023a169bf..df6fe5ec3b 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.73-next.0", + "version": "0.2.73-next.2", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", @@ -26,39 +26,39 @@ "build-image": "docker build ../.. -f Dockerfile --tag example-backend" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/backend-tasks": "^0.3.3-next.0", - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/backend-tasks": "^0.3.3-next.2", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/plugin-app-backend": "^0.3.34-next.0", - "@backstage/plugin-auth-backend": "^0.14.2-next.0", - "@backstage/plugin-auth-node": "^0.2.3-next.0", + "@backstage/integration": "^1.2.2-next.2", + "@backstage/plugin-app-backend": "^0.3.34-next.2", + "@backstage/plugin-auth-backend": "^0.15.0-next.2", + "@backstage/plugin-auth-node": "^0.2.3-next.1", "@backstage/plugin-azure-devops-backend": "^0.3.13-next.0", - "@backstage/plugin-badges-backend": "^0.1.28-next.0", - "@backstage/plugin-catalog-backend": "^1.2.1-next.0", - "@backstage/plugin-code-coverage-backend": "^0.1.32-next.0", + "@backstage/plugin-badges-backend": "^0.1.28-next.2", + "@backstage/plugin-catalog-backend": "^1.2.1-next.2", + "@backstage/plugin-code-coverage-backend": "^0.1.32-next.2", "@backstage/plugin-graphql-backend": "^0.1.24-next.0", - "@backstage/plugin-jenkins-backend": "^0.1.24-next.0", - "@backstage/plugin-kubernetes-backend": "^0.7.0-next.0", - "@backstage/plugin-kafka-backend": "^0.2.27-next.0", - "@backstage/plugin-permission-backend": "^0.5.9-next.0", - "@backstage/plugin-permission-common": "^0.6.2", - "@backstage/plugin-permission-node": "^0.6.3-next.0", + "@backstage/plugin-jenkins-backend": "^0.1.24-next.2", + "@backstage/plugin-kubernetes-backend": "^0.7.0-next.2", + "@backstage/plugin-kafka-backend": "^0.2.27-next.2", + "@backstage/plugin-permission-backend": "^0.5.9-next.1", + "@backstage/plugin-permission-common": "^0.6.3-next.0", + "@backstage/plugin-permission-node": "^0.6.3-next.1", "@backstage/plugin-proxy-backend": "^0.2.28-next.0", "@backstage/plugin-rollbar-backend": "^0.1.31-next.0", - "@backstage/plugin-scaffolder-backend": "^1.4.0-next.0", - "@backstage/plugin-scaffolder-backend-module-rails": "^0.4.2-next.0", - "@backstage/plugin-search-backend": "^0.5.4-next.0", - "@backstage/plugin-search-backend-node": "^0.6.3-next.0", - "@backstage/plugin-search-backend-module-elasticsearch": "^0.1.6-next.0", - "@backstage/plugin-search-backend-module-pg": "^0.3.5-next.0", - "@backstage/plugin-techdocs-backend": "^1.1.3-next.0", - "@backstage/plugin-tech-insights-backend": "^0.4.2-next.0", + "@backstage/plugin-scaffolder-backend": "^1.4.0-next.2", + "@backstage/plugin-scaffolder-backend-module-rails": "^0.4.2-next.1", + "@backstage/plugin-search-backend": "^0.5.4-next.1", + "@backstage/plugin-search-backend-node": "^0.6.3-next.1", + "@backstage/plugin-search-backend-module-elasticsearch": "^0.2.0-next.1", + "@backstage/plugin-search-backend-module-pg": "^0.3.5-next.2", + "@backstage/plugin-techdocs-backend": "^1.2.0-next.2", + "@backstage/plugin-tech-insights-backend": "^0.5.0-next.2", "@backstage/plugin-tech-insights-node": "^0.3.2-next.0", - "@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.18-next.0", - "@backstage/plugin-todo-backend": "^0.1.31-next.0", + "@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.18-next.1", + "@backstage/plugin-todo-backend": "^0.1.31-next.1", "@gitbeaker/node": "^35.1.0", "@octokit/rest": "^18.5.3", "better-sqlite3": "^7.5.0", @@ -75,7 +75,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@types/dockerode": "^3.3.0", "@types/express": "^4.17.6", "@types/express-serve-static-core": "^4.17.5", diff --git a/packages/backend/src/plugins/kubernetes.ts b/packages/backend/src/plugins/kubernetes.ts index 376569a959..b089b20405 100644 --- a/packages/backend/src/plugins/kubernetes.ts +++ b/packages/backend/src/plugins/kubernetes.ts @@ -17,14 +17,17 @@ import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend'; import { Router } from 'express'; import { PluginEnvironment } from '../types'; +import { CatalogClient } from '@backstage/catalog-client'; export default async function createPlugin( env: PluginEnvironment, ): Promise { + const catalogApi = new CatalogClient({ discoveryApi: env.discovery }); const { router } = await KubernetesBuilder.createBuilder({ logger: env.logger, config: env.config, discovery: env.discovery, + catalogApi, }).build(); return router; } diff --git a/packages/backend/src/plugins/search.ts b/packages/backend/src/plugins/search.ts index a0ea83ab61..c478ecdd05 100644 --- a/packages/backend/src/plugins/search.ts +++ b/packages/backend/src/plugins/search.ts @@ -39,7 +39,9 @@ async function createSearchEngine( } if (await PgSearchEngine.supported(env.database)) { - return await PgSearchEngine.from({ database: env.database }); + return await PgSearchEngine.fromConfig(env.config, { + database: env.database, + }); } return new LunrSearchEngine({ logger: env.logger }); diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index 8ea70b67be..0b0d29b940 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/catalog-client +## 1.0.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + ## 1.0.4-next.0 ### Patch Changes diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index 893b057e37..3fbf662615 100644 --- a/packages/catalog-client/package.json +++ b/packages/catalog-client/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-client", "description": "An isomorphic client for the catalog backend", - "version": "1.0.4-next.0", + "version": "1.0.4-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,14 +33,14 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/errors": "^1.0.0", + "@backstage/catalog-model": "^1.1.0-next.1", + "@backstage/errors": "^1.1.0-next.0", "cross-fetch": "^3.1.5" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/jest": "^26.0.7", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md index 6501c32409..910fc92cd2 100644 --- a/packages/catalog-model/CHANGELOG.md +++ b/packages/catalog-model/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/catalog-model +## 1.1.0-next.2 + +### Minor Changes + +- 4cc81372f8: Introduced `GroupDefaultParentEntityPolicy` to set a default group entity parent. + +## 1.1.0-next.1 + +### Patch Changes + +- f1dcc6f3c6: Added type predicates for all entity types, e.g. isUserEntity +- Updated dependencies + - @backstage/errors@1.1.0-next.0 + ## 1.1.0-next.0 ### Minor Changes diff --git a/packages/catalog-model/api-report.md b/packages/catalog-model/api-report.md index 1538a1273b..b7456bb2f8 100644 --- a/packages/catalog-model/api-report.md +++ b/packages/catalog-model/api-report.md @@ -241,6 +241,13 @@ export function getEntitySourceLocation(entity: Entity): { target: string; }; +// @public +export class GroupDefaultParentEntityPolicy implements EntityPolicy { + constructor(parentEntityRef: string); + // (undocumented) + enforce(entity: Entity): Promise; +} + // @public interface GroupEntityV1alpha1 extends Entity { // (undocumented) diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index ba2521b927..a58fdcf4d5 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-model", "description": "Types and validators that help describe the model of a Backstage Catalog", - "version": "1.1.0-next.0", + "version": "1.1.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,7 +35,7 @@ }, "dependencies": { "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", + "@backstage/errors": "^1.1.0-next.0", "@backstage/types": "^1.0.0", "ajv": "^8.10.0", "json-schema": "^0.4.0", @@ -43,7 +43,7 @@ "uuid": "^8.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@types/jest": "^26.0.7", "@types/json-schema": "^7.0.5", "@types/lodash": "^4.14.151", diff --git a/packages/catalog-model/src/entity/policies/GroupDefaultParentEntityPolicy.test.ts b/packages/catalog-model/src/entity/policies/GroupDefaultParentEntityPolicy.test.ts new file mode 100644 index 0000000000..d5eb6145c2 --- /dev/null +++ b/packages/catalog-model/src/entity/policies/GroupDefaultParentEntityPolicy.test.ts @@ -0,0 +1,71 @@ +/* + * 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 { UserEntity, GroupEntity } from '../../kinds'; +import { GroupDefaultParentEntityPolicy } from './GroupDefaultParentEntityPolicy'; + +describe('GroupDefaultParentEntityPolicy', () => { + it('should ignore non-group entities', async () => { + const p = new GroupDefaultParentEntityPolicy('name'); + const u: UserEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { name: 'n' }, + spec: { profile: {}, memberOf: ['c'] }, + }; + const result = await p.enforce(u); + expect(result).toEqual({ + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { name: 'n' }, + spec: { profile: {}, memberOf: ['c'] }, + }); + }); + + it('should parent group entities', async () => { + const p = new GroupDefaultParentEntityPolicy('name'); + const g: GroupEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { name: 'n' }, + spec: { type: 'foo', children: [] }, + }; + const result = await p.enforce(g); + expect(result).toEqual({ + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { name: 'n' }, + spec: { type: 'foo', parent: 'group:default/name', children: [] }, + }); + }); + + it('should not replace existing parents', async () => { + const p = new GroupDefaultParentEntityPolicy('namespace/name'); + const g: GroupEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { name: 'n' }, + spec: { type: 'foo', parent: 'group:something/else', children: [] }, + }; + const result = await p.enforce(g); + expect(result).toEqual({ + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { name: 'n' }, + spec: { type: 'foo', parent: 'group:something/else', children: [] }, + }); + }); +}); diff --git a/packages/catalog-model/src/entity/policies/GroupDefaultParentEntityPolicy.ts b/packages/catalog-model/src/entity/policies/GroupDefaultParentEntityPolicy.ts new file mode 100644 index 0000000000..8eb0aef757 --- /dev/null +++ b/packages/catalog-model/src/entity/policies/GroupDefaultParentEntityPolicy.ts @@ -0,0 +1,68 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity } from '../Entity'; +import { GroupEntity } from '../../kinds'; +import { EntityPolicy } from './types'; +import { DEFAULT_NAMESPACE } from '../constants'; +import { parseEntityRef, stringifyEntityRef } from '../ref'; + +/** + * DefaultParentPolicy is an EntityPolicy that updates group entities + * with a parent of last resort. This ensures that, while we preserve + * any existing group hierarchies, we can guarantee that there is a + * single global root of the group hierarchy. + * + * @public + */ +export class GroupDefaultParentEntityPolicy implements EntityPolicy { + private readonly parentRef: string; + + constructor(parentEntityRef: string) { + const { kind, namespace, name } = parseEntityRef(parentEntityRef, { + defaultKind: 'Group', + defaultNamespace: DEFAULT_NAMESPACE, + }); + + if (kind.toLocaleUpperCase('en-US') !== 'GROUP') { + throw new TypeError('group parent must be a group'); + } + + this.parentRef = stringifyEntityRef({ + kind: kind, + namespace: namespace, + name: name, + }); + } + + async enforce(entity: Entity): Promise { + if (entity.kind !== 'Group') { + return entity; + } + + const group = entity as GroupEntity; + if (group.spec.parent) { + return group; + } + + // Avoid making the parent entity it's own parent. + if (stringifyEntityRef(group) !== this.parentRef) { + group.spec.parent = this.parentRef; + } + + return group; + } +} diff --git a/packages/catalog-model/src/entity/policies/index.ts b/packages/catalog-model/src/entity/policies/index.ts index ae14007d80..d5740c0955 100644 --- a/packages/catalog-model/src/entity/policies/index.ts +++ b/packages/catalog-model/src/entity/policies/index.ts @@ -15,6 +15,7 @@ */ export { DefaultNamespaceEntityPolicy } from './DefaultNamespaceEntityPolicy'; +export { GroupDefaultParentEntityPolicy } from './GroupDefaultParentEntityPolicy'; export { FieldFormatEntityPolicy } from './FieldFormatEntityPolicy'; export { NoForeignRootFieldsEntityPolicy } from './NoForeignRootFieldsEntityPolicy'; export { SchemaValidEntityPolicy } from './SchemaValidEntityPolicy'; diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index dbceb46db1..b4dbb1cdc5 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/cli +## 0.18.0-next.2 + +### Patch Changes + +- f6b6fb7165: The `test` command now ensures that all IO is flushed before exiting when printing `--help`. + +## 0.18.0-next.1 + +### Minor Changes + +- 96a82d9791: **BREAKING**: Removed the following deprecated package commands: + + - `app:build` - Use `package build` instead + - `app:serve` - Use `package start` instead + - `backend:build` - Use `package build` instead + - `backend:bundle` - Use `package build` instead + - `backend:dev` - Use `package start` instead + - `plugin:build` - Use `package build` instead + - `plugin:serve` - Use `package start` instead + - `build` - Use `package build` instead + - `lint` - Use `package lint` instead + - `prepack` - Use `package prepack` instead + - `postpack` - Use `package postpack` instead + + In order to replace these you need to have [migrated to using package roles](https://backstage.io/docs/tutorials/package-role-migration). + +### Patch Changes + +- 86640214f0: Upgrade `@rollup/plugin-node-resolve` to `^13.0.6` +- e661242844: Updated dependency `run-script-webpack-plugin` to `^0.1.0`. +- Updated dependencies + - @backstage/errors@1.1.0-next.0 + - @backstage/config-loader@1.1.3-next.0 + ## 0.17.3-next.0 ### Patch Changes diff --git a/packages/cli/cli-report.md b/packages/cli/cli-report.md new file mode 100644 index 0000000000..8c678d885e --- /dev/null +++ b/packages/cli/cli-report.md @@ -0,0 +1,563 @@ +## CLI Report file for "@backstage/cli" + +> Do not edit this file. It is a report generated by `yarn build:api-reports` + +### `backstage-cli` + +``` +Usage: backstage-cli [options] [command] + +Options: + -V, --version + -h, --help + +Commands: + create [options] + create-plugin [options] + plugin:diff [options] + test + config:docs [options] + config:print [options] + config:check [options] + config:schema [options] + repo [command] + package [command] + migrate [command] + versions:bump [options] + versions:check [options] + clean + build-workspace [packages...] + create-github-app + info + help [command] +``` + +### `backstage-cli build-workspace` + +``` +Usage: backstage-cli build-workspace [options] [packages...] + +Options: + -h, --help +``` + +### `backstage-cli clean` + +``` +Usage: backstage-cli clean [options] + +Options: + -h, --help +``` + +### `backstage-cli config:check` + +``` +Usage: backstage-cli config:check [options] + +Options: + --package + --lax + --frontend + --deprecated + --config + -h, --help +``` + +### `backstage-cli config:docs` + +``` +Usage: backstage-cli config:docs [options] + +Options: + --package + -h, --help +``` + +### `backstage-cli config:print` + +``` +Usage: backstage-cli config:print [options] + +Options: + --package + --lax + --frontend + --with-secrets + --format + --config + -h, --help +``` + +### `backstage-cli config:schema` + +``` +Usage: backstage-cli config:schema [options] + +Options: + --package + --format + -h, --help +``` + +### `backstage-cli create` + +``` +Usage: backstage-cli create [options] + +Options: + --select + --option = + --scope + --npm-registry + --no-private + -h, --help +``` + +### `backstage-cli create-github-app` + +``` +Usage: backstage-cli create-github-app [options] + +Options: + -h, --help +``` + +### `backstage-cli create-plugin` + +``` +Usage: backstage-cli create-plugin [options] + +Options: + --backend + --scope + --npm-registry + --no-private + -h, --help +``` + +### `backstage-cli info` + +``` +Usage: backstage-cli info [options] + +Options: + -h, --help +``` + +### `backstage-cli migrate` + +``` +Usage: backstage-cli migrate [options] [command] [command] + +Options: + -h, --help + +Commands: + package-roles + package-scripts + package-lint-configs + help [command] +``` + +### `backstage-cli migrate package-lint-configs` + +``` +Usage: backstage-cli migrate package-lint-configs [options] + +Options: + -h, --help +``` + +### `backstage-cli migrate package-roles` + +``` +Usage: backstage-cli migrate package-roles [options] + +Options: + -h, --help +``` + +### `backstage-cli migrate package-scripts` + +``` +Usage: backstage-cli migrate package-scripts [options] + +Options: + -h, --help +``` + +### `backstage-cli package` + +``` +Usage: backstage-cli package [options] [command] [command] + +Options: + -h, --help + +Commands: + start [options] + build [options] + lint [options] [directories...] + test + clean + prepack + postpack + help [command] +``` + +### `backstage-cli package build` + +``` +Usage: backstage-cli package build [options] + +Options: + --role + --minify + --experimental-type-build + --skip-build-dependencies + --stats + --config + -h, --help +``` + +### `backstage-cli package clean` + +``` +Usage: backstage-cli package clean [options] + +Options: + -h, --help +``` + +### `backstage-cli package lint` + +``` +Usage: backstage-cli package lint [options] [directories...] + +Options: + --format + --fix + -h, --help +``` + +### `backstage-cli package postpack` + +``` +Usage: backstage-cli package postpack [options] + +Options: + -h, --help +``` + +### `backstage-cli package prepack` + +``` +Usage: backstage-cli package prepack [options] + +Options: + -h, --help +``` + +### `backstage-cli package start` + +``` +Usage: backstage-cli package start [options] + +Options: + --config + --role + --check + --inspect + --inspect-brk + -h, --help +``` + +### `backstage-cli package test` + +``` +Usage: backstage-cli [--config=] [TestPathPattern] + +Options: + -h, --help + -v, --version + --all + --automock + -b, --bail + --cache + --cacheDirectory + --changedFilesWithAncestor + --changedSince + --ci + --clearCache + --clearMocks + --collectCoverage + --collectCoverageFrom + --collectCoverageOnlyFrom + --color + --colors + -c, --config + --coverage + --coverageDirectory + --coveragePathIgnorePatterns + --coverageProvider + --coverageReporters + --coverageThreshold + --debug + --detectLeaks + --detectOpenHandles + --env + --errorOnDeprecated + -e, --expand + --filter + --findRelatedTests + --forceExit + --globalSetup + --globalTeardown + --globals + --haste + --init + --injectGlobals + --json + --lastCommit + --listTests + --logHeapUsage + --maxConcurrency + -w, --maxWorkers + --moduleDirectories + --moduleFileExtensions + --moduleNameMapper + --modulePathIgnorePatterns + --modulePaths + --noStackTrace + --notify + --notifyMode + -o, --onlyChanged + -f, --onlyFailures + --outputFile + --passWithNoTests + --preset + --prettierPath + --projects + --reporters + --resetMocks + --resetModules + --resolver + --restoreMocks + --rootDir + --roots + -i, --runInBand + --runTestsByPath + --runner + --selectProjects + --setupFiles + --setupFilesAfterEnv + --showConfig + --silent + --skipFilter + --snapshotSerializers + --testEnvironment + --testEnvironmentOptions + --testFailureExitCode + --testLocationInResults + --testMatch + -t, --testNamePattern + --testPathIgnorePatterns + --testPathPattern + --testRegex + --testResultsProcessor + --testRunner + --testSequencer + --testTimeout + --testURL + --timers + --transform + --transformIgnorePatterns + --unmockedModulePathPatterns + -u, --updateSnapshot + --useStderr + --verbose + --watch + --watchAll + --watchPathIgnorePatterns + --watchman +``` + +### `backstage-cli plugin:diff` + +``` +Usage: backstage-cli plugin:diff [options] + +Options: + --check + --yes + -h, --help +``` + +### `backstage-cli repo` + +``` +Usage: backstage-cli repo [options] [command] [command] + +Options: + -h, --help + +Commands: + build [options] + lint [options] + help [command] +``` + +### `backstage-cli repo build` + +``` +Usage: backstage-cli repo build [options] + +Options: + --all + --since + -h, --help +``` + +### `backstage-cli repo lint` + +``` +Usage: backstage-cli repo lint [options] + +Options: + --format + --since + --fix + -h, --help +``` + +### `backstage-cli test` + +``` +Usage: backstage-cli [--config=] [TestPathPattern] + +Options: + -h, --help + -v, --version + --all + --automock + -b, --bail + --cache + --cacheDirectory + --changedFilesWithAncestor + --changedSince + --ci + --clearCache + --clearMocks + --collectCoverage + --collectCoverageFrom + --collectCoverageOnlyFrom + --color + --colors + -c, --config + --coverage + --coverageDirectory + --coveragePathIgnorePatterns + --coverageProvider + --coverageReporters + --coverageThreshold + --debug + --detectLeaks + --detectOpenHandles + --env + --errorOnDeprecated + -e, --expand + --filter + --findRelatedTests + --forceExit + --globalSetup + --globalTeardown + --globals + --haste + --init + --injectGlobals + --json + --lastCommit + --listTests + --logHeapUsage + --maxConcurrency + -w, --maxWorkers + --moduleDirectories + --moduleFileExtensions + --moduleNameMapper + --modulePathIgnorePatterns + --modulePaths + --noStackTrace + --notify + --notifyMode + -o, --onlyChanged + -f, --onlyFailures + --outputFile + --passWithNoTests + --preset + --prettierPath + --projects + --reporters + --resetMocks + --resetModules + --resolver + --restoreMocks + --rootDir + --roots + -i, --runInBand + --runTestsByPath + --runner + --selectProjects + --setupFiles + --setupFilesAfterEnv + --showConfig + --silent + --skipFilter + --snapshotSerializers + --testEnvironment + --testEnvironmentOptions + --testFailureExitCode + --testLocationInResults + --testMatch + -t, --testNamePattern + --testPathIgnorePatterns + --testPathPattern + --testRegex + --testResultsProcessor + --testRunner + --testSequencer + --testTimeout + --testURL + --timers + --transform + --transformIgnorePatterns + --unmockedModulePathPatterns + -u, --updateSnapshot + --useStderr + --verbose + --watch + --watchAll + --watchPathIgnorePatterns + --watchman +``` + +### `backstage-cli versions:bump` + +``` +Usage: backstage-cli versions:bump [options] + +Options: + --pattern + --release + -h, --help +``` + +### `backstage-cli versions:check` + +``` +Usage: backstage-cli versions:check [options] + +Options: + --fix + -h, --help +``` diff --git a/packages/cli/package.json b/packages/cli/package.json index 42e8953d1e..aead136ec6 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.17.3-next.0", + "version": "0.18.0-next.2", "private": false, "publishConfig": { "access": "public" @@ -33,8 +33,8 @@ "dependencies": { "@backstage/cli-common": "^0.1.9", "@backstage/config": "^1.0.1", - "@backstage/config-loader": "^1.1.2", - "@backstage/errors": "^1.0.0", + "@backstage/config-loader": "^1.1.3-next.0", + "@backstage/errors": "^1.1.0-next.0", "@backstage/release-manifests": "^0.0.4", "@backstage/types": "^1.0.0", "@hot-loader/react-dom-v16": "npm:@hot-loader/react-dom@^16.0.2", @@ -126,14 +126,14 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/backend-common": "^0.14.1-next.0", + "@backstage/backend-common": "^0.14.1-next.2", "@backstage/config": "^1.0.1", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", + "@backstage/theme": "^0.2.16-next.1", "@types/diff": "^5.0.0", "@types/express": "^4.17.6", "@types/fs-extra": "^9.0.1", @@ -152,7 +152,7 @@ "@types/yarnpkg__lockfile": "^1.1.4", "del": "^6.0.0", "mock-fs": "^5.1.0", - "msw": "^0.42.0", + "msw": "^0.43.0", "nodemon": "^2.0.2", "ts-node": "^10.0.0" }, diff --git a/packages/cli/src/commands/test.ts b/packages/cli/src/commands/test.ts index f1bfcc356b..88769aec1a 100644 --- a/packages/cli/src/commands/test.ts +++ b/packages/cli/src/commands/test.ts @@ -78,6 +78,10 @@ export default async (_opts: OptionValues, cmd: Command) => { process.env.TZ = 'UTC'; } + if (args.includes('--help')) { + (process.stdout as any)._handle.setBlocking(true); + } + // eslint-disable-next-line jest/no-jest-import await require('jest').run(args); }; diff --git a/packages/cli/templates/default-backend-plugin/package.json.hbs b/packages/cli/templates/default-backend-plugin/package.json.hbs index 2416fd75cb..4e8ee254b9 100644 --- a/packages/cli/templates/default-backend-plugin/package.json.hbs +++ b/packages/cli/templates/default-backend-plugin/package.json.hbs @@ -41,7 +41,7 @@ "@backstage/cli": "{{versionQuery '@backstage/cli'}}", "@types/supertest": "{{versionQuery '@types/supertest' '2.0.8'}}", "supertest": "{{versionQuery 'supertest' '4.0.2'}}", - "msw": "{{versionQuery 'msw' '0.42.0'}}" + "msw": "{{versionQuery 'msw' '0.43.0'}}" }, "files": [ "dist" diff --git a/packages/cli/templates/default-plugin/package.json.hbs b/packages/cli/templates/default-plugin/package.json.hbs index 34a0548b29..490f18d474 100644 --- a/packages/cli/templates/default-plugin/package.json.hbs +++ b/packages/cli/templates/default-plugin/package.json.hbs @@ -49,7 +49,7 @@ "@testing-library/user-event": "{{versionQuery '@testing-library/user-event' '14.0.0'}}", "@types/jest": "{{versionQuery '@types/jest' '26.0.7'}}", "@types/node": "{{versionQuery '@types/node' '16.11.26'}}", - "msw": "{{versionQuery 'msw' '0.42.0'}}", + "msw": "{{versionQuery 'msw' '0.43.0'}}", "cross-fetch": "{{versionQuery 'cross-fetch' '3.1.5'}}" }, "files": [ diff --git a/packages/codemods/cli-report.md b/packages/codemods/cli-report.md new file mode 100644 index 0000000000..57d2198141 --- /dev/null +++ b/packages/codemods/cli-report.md @@ -0,0 +1,61 @@ +## CLI Report file for "@backstage/codemods" + +> Do not edit this file. It is a report generated by `yarn build:api-reports` + +### `backstage-codemods` + +``` +Usage: backstage-codemods [options] [command] + +Options: + -V, --version + -h, --help + +Commands: + apply [target-dirs...] + list + help [command] +``` + +### `backstage-codemods apply` + +``` +Usage: backstage-codemods apply [options] [command] [target-dirs...] + +Options: + -h, --help + +Commands: + core-imports [options] [target-dirs...] + extension-names [options] [target-dirs...] + help [command] +``` + +### `backstage-codemods apply core-imports` + +``` +Usage: backstage-codemods apply core-imports [options] [target-dirs...] + +Options: + -d, --dry + -h, --help +``` + +### `backstage-codemods apply extension-names` + +``` +Usage: backstage-codemods apply extension-names [options] [target-dirs...] + +Options: + -d, --dry + -h, --help +``` + +### `backstage-codemods list` + +``` +Usage: backstage-codemods list [options] + +Options: + -h, --help +``` diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md index d9228aa091..af297b1112 100644 --- a/packages/config-loader/CHANGELOG.md +++ b/packages/config-loader/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/config-loader +## 1.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.1.0-next.0 + ## 1.1.2 ### Patch Changes diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index 3448b336b7..3ca4b1455f 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config-loader", "description": "Config loading functionality used by Backstage backend, and CLI", - "version": "1.1.2", + "version": "1.1.3-next.0", "private": false, "publishConfig": { "access": "public", @@ -36,7 +36,7 @@ "dependencies": { "@backstage/cli-common": "^0.1.9", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", + "@backstage/errors": "^1.1.0-next.0", "@backstage/types": "^1.0.0", "@types/json-schema": "^7.0.6", "ajv": "^8.10.0", @@ -46,7 +46,7 @@ "json-schema-merge-allof": "^0.8.1", "json-schema-traverse": "^1.0.0", "node-fetch": "^2.6.7", - "typescript-json-schema": "^0.53.0", + "typescript-json-schema": "^0.54.0", "yaml": "^1.9.2", "yup": "^0.32.9" }, @@ -57,7 +57,7 @@ "@types/node": "^16.11.26", "@types/yup": "^0.29.13", "mock-fs": "^5.1.0", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index be95a344fa..e7d530417a 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -49,8 +49,8 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/cli": "^0.18.0-next.1", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", @@ -59,7 +59,7 @@ "@types/node": "^16.11.26", "@types/zen-observable": "^0.8.0", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index ccccade63d..46a44394b3 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/core-components +## 0.10.0-next.2 + +### Minor Changes + +- 32204fa794: Add `transformLinkUri` and `transformImageUri` to `MarkdownContent` + +### Patch Changes + +- b4b711bcc2: Fix the EntityLayout header style so that EntityContextMenu button can display in correct shape when user hover on it +- 15201b1032: Updated dependency `rc-progress` to `3.4.0`. +- 385389d23c: Updated to remove usage of the `bursts` object in the theme palette +- Updated dependencies + - @backstage/theme@0.2.16-next.1 + +## 0.9.6-next.1 + +### Patch Changes + +- 3c440ea77e: Change BackstageIconLinkVertical style to use pallette instead of explicit color +- 7e115d42f9: Support displaying subtitle text in `SidebarSubmenuItem` +- Updated dependencies + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + ## 0.9.6-next.0 ### Patch Changes diff --git a/packages/core-components/package.json b/packages/core-components/package.json index f4b4f55089..0d27c6419d 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.9.6-next.0", + "version": "0.10.0-next.2", "private": false, "publishConfig": { "access": "public", @@ -35,8 +35,8 @@ "dependencies": { "@backstage/config": "^1.0.1", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/theme": "^0.2.16-next.1", "@backstage/version-bridge": "^1.0.1", "@material-table/core": "^3.1.0", "@material-ui/core": "^4.12.2", @@ -56,7 +56,7 @@ "pluralize": "^8.0.0", "prop-types": "^15.7.2", "qs": "^6.9.4", - "rc-progress": "3.3.3", + "rc-progress": "3.4.0", "react-helmet": "6.1.0", "react-hook-form": "^7.12.2", "react-markdown": "^8.0.0", @@ -80,8 +80,8 @@ }, "devDependencies": { "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/cli": "^0.17.3-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/cli": "^0.18.0-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", @@ -101,7 +101,7 @@ "@types/react-window": "^1.8.5", "@types/zen-observable": "^0.8.0", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/packages/core-components/src/components/HeaderIconLinkRow/IconLinkVertical.tsx b/packages/core-components/src/components/HeaderIconLinkRow/IconLinkVertical.tsx index 2816603f7f..dda2782c45 100644 --- a/packages/core-components/src/components/HeaderIconLinkRow/IconLinkVertical.tsx +++ b/packages/core-components/src/components/HeaderIconLinkRow/IconLinkVertical.tsx @@ -47,7 +47,7 @@ const useIconStyles = makeStyles( textAlign: 'center', }, disabled: { - color: 'gray', + color: theme.palette.text.secondary, cursor: 'default', }, primary: { diff --git a/packages/core-components/src/components/Link/Link.test.tsx b/packages/core-components/src/components/Link/Link.test.tsx index 8c6ed54d76..5cfeaa4869 100644 --- a/packages/core-components/src/components/Link/Link.test.tsx +++ b/packages/core-components/src/components/Link/Link.test.tsx @@ -21,9 +21,11 @@ import { TestApiProvider, wrapInTestApp, } from '@backstage/test-utils'; -import { analyticsApiRef } from '@backstage/core-plugin-api'; -import { isExternalUri, Link } from './Link'; +import { analyticsApiRef, configApiRef } from '@backstage/core-plugin-api'; +import { isExternalUri, Link, useResolvedPath } from './Link'; import { Route, Routes } from 'react-router'; +import { renderHook, WrapperComponent } from '@testing-library/react-hooks'; +import { ConfigReader } from '@backstage/config'; describe('', () => { it('navigates using react-router', async () => { @@ -103,6 +105,58 @@ describe('', () => { }); }); + describe('resolves a sub-path correctly', () => { + it('when it starts with base path', async () => { + const testString = 'This is test string'; + const linkText = 'Navigate!'; + const configApi = new ConfigReader({ + app: { baseUrl: 'http://localhost:3000/example' }, + }); + + const { getByText } = render( + wrapInTestApp( + + + {linkText} + {testString}

} /> +
+
, + ), + ); + + expect(() => getByText(testString)).toThrow(); + fireEvent.click(getByText(linkText)); + await waitFor(() => { + expect(getByText(testString)).toBeInTheDocument(); + }); + }); + + it('when it does not start with base path', async () => { + const testString = 'This is test string'; + const linkText = 'Navigate!'; + const configApi = new ConfigReader({ + app: { baseUrl: 'http://localhost:3000/example' }, + }); + + const { getByText } = render( + wrapInTestApp( + + + {linkText} + {testString}

} /> +
+
, + ), + ); + + expect(() => getByText(testString)).toThrow(); + fireEvent.click(getByText(linkText)); + await waitFor(() => { + expect(getByText(testString)).toBeInTheDocument(); + }); + }); + }); + describe('isExternalUri', () => { it.each([ [true, 'http://'], @@ -128,4 +182,45 @@ describe('', () => { expect(isExternalUri(uri)).toBe(expected); }); }); + + describe('useResolvedPath', () => { + const wrapper: WrapperComponent<{}> = ({ children }) => { + const configApi = new ConfigReader({ + app: { baseUrl: 'http://localhost:3000/example' }, + }); + return ( + + {children} + + ); + }; + + describe('concatenate base path', () => { + it('when uri is internal and does not start with base path', () => { + const path = '/catalog/default/component/artist-lookup'; + const { result } = renderHook(() => useResolvedPath(path), { + wrapper, + }); + expect(result.current).toBe('/example'.concat(path)); + }); + }); + + describe('does not concatenate base path', () => { + it('when uri is external', () => { + const path = 'https://stackoverflow.com/questions/1/example'; + const { result } = renderHook(() => useResolvedPath(path), { + wrapper, + }); + expect(result.current).toBe(path); + }); + + it('when uri already starts with base path', () => { + const path = '/example/catalog/default/component/artist-lookup'; + const { result } = renderHook(() => useResolvedPath(path), { + wrapper, + }); + expect(result.current).toBe(path); + }); + }); + }); }); diff --git a/packages/core-components/src/components/Link/Link.tsx b/packages/core-components/src/components/Link/Link.tsx index 5809990b92..22b203d157 100644 --- a/packages/core-components/src/components/Link/Link.tsx +++ b/packages/core-components/src/components/Link/Link.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { useAnalytics } from '@backstage/core-plugin-api'; +import { configApiRef, useAnalytics, useApi } from '@backstage/core-plugin-api'; import classnames from 'classnames'; import MaterialLink, { LinkProps as MaterialLinkProps, @@ -25,6 +25,7 @@ import { Link as RouterLink, LinkProps as RouterLinkProps, } from 'react-router-dom'; +import { trimEnd } from 'lodash'; const useStyles = makeStyles( { @@ -52,6 +53,45 @@ export type LinkProps = MaterialLinkProps & noTrack?: boolean; }; +/** + * Returns the app base url that could be empty if the Config API is not properly implemented. + * The only cases there would be no Config API are in tests and in storybook stories, and in those cases, it's unlikely that callers would rely on this subpath behavior. + */ +const useBaseUrl = () => { + try { + const config = useApi(configApiRef); + return config.getOptionalString('app.baseUrl'); + } catch { + return undefined; + } +}; + +/** + * Get the app base path from the configured app baseUrl. + * The returned path does not have a trailing slash. + */ +const useBasePath = () => { + // baseUrl can be specified as just a path + const base = 'http://dummy.dev'; + const url = useBaseUrl() ?? '/'; + const { pathname } = new URL(url, base); + return trimEnd(pathname, '/'); +}; + +export const useResolvedPath = (uri: LinkProps['to']) => { + let resolvedPath = String(uri); + + const basePath = useBasePath(); + const external = isExternalUri(resolvedPath); + const startsWithBasePath = resolvedPath.startsWith(basePath); + + if (!external && !startsWithBasePath) { + resolvedPath = basePath.concat(resolvedPath); + } + + return resolvedPath; +}; + /** * Given a react node, try to retrieve its text content. */ @@ -84,7 +124,7 @@ export const Link = React.forwardRef( ({ onClick, noTrack, ...props }, ref) => { const classes = useStyles(); const analytics = useAnalytics(); - const to = String(props.to); + const to = useResolvedPath(props.to); const linkText = getNodeText(props.children) || to; const external = isExternalUri(to); const newWindow = external && !!/^https?:/.exec(to); @@ -99,11 +139,11 @@ export const Link = React.forwardRef( return external ? ( // External links {props.children} @@ -112,10 +152,11 @@ export const Link = React.forwardRef( ) : ( // Interact with React Router for internal links ); }, diff --git a/packages/core-components/src/components/MarkdownContent/MarkdownContent.test.tsx b/packages/core-components/src/components/MarkdownContent/MarkdownContent.test.tsx index 2e1550078f..9c08b83c40 100644 --- a/packages/core-components/src/components/MarkdownContent/MarkdownContent.test.tsx +++ b/packages/core-components/src/components/MarkdownContent/MarkdownContent.test.tsx @@ -62,4 +62,42 @@ describe('', () => { expect(fp2).toBeInTheDocument(); expect(rendered.getByText(');', { selector: 'span' })).toBeInTheDocument(); }); + + it('render MarkdownContent component with transformed link', async () => { + const rendered = await renderWithEffects( + wrapInTestApp( + { + return `${href}-modified`; + }} + />, + ), + ); + const fp1 = rendered.getByText('Title', { + selector: 'a', + }); + expect(fp1).toBeInTheDocument(); + expect(fp1.getAttribute('href')).toEqual( + 'https://backstage.io/link-modified', + ); + }); + + it('render MarkdownContent component with transformed image', async () => { + const rendered = await renderWithEffects( + wrapInTestApp( + { + return `https://example.com/blog/assets/6/header.png`; + }} + />, + ), + ); + const fp1 = rendered.getByAltText('Image'); + expect(fp1).toBeInTheDocument(); + expect(fp1.getAttribute('src')).toEqual( + 'https://example.com/blog/assets/6/header.png', + ); + }); }); diff --git a/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx b/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx index df4ad56776..0e5aedda90 100644 --- a/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx +++ b/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx @@ -68,6 +68,8 @@ type Props = { content: string; dialect?: 'gfm' | 'common-mark'; linkTarget?: Options['linkTarget']; + transformLinkUri?: (href: string) => string; + transformImageUri?: (href: string) => string; }; const components: Options['components'] = { @@ -91,7 +93,13 @@ const components: Options['components'] = { * If you just want to render to plain [CommonMark](https://commonmark.org/), set the dialect to `'common-mark'` */ export function MarkdownContent(props: Props) { - const { content, dialect = 'gfm', linkTarget } = props; + const { + content, + dialect = 'gfm', + linkTarget, + transformLinkUri, + transformImageUri, + } = props; const classes = useStyles(); return ( ); } diff --git a/packages/core-components/src/layout/Header/Header.tsx b/packages/core-components/src/layout/Header/Header.tsx index bb4d19b949..1badb4eb98 100644 --- a/packages/core-components/src/layout/Header/Header.tsx +++ b/packages/core-components/src/layout/Header/Header.tsx @@ -63,15 +63,16 @@ const useStyles = makeStyles( }, rightItemsBox: { width: 'auto', + alignItems: 'center', }, title: { - color: theme.palette.bursts.fontColor, + color: theme.page.fontColor, wordBreak: 'break-word', fontSize: theme.typography.h3.fontSize, marginBottom: 0, }, subtitle: { - color: theme.palette.bursts.fontColor, + color: theme.page.fontColor, opacity: 0.8, display: 'inline-block', // prevents margin collapse of adjacent siblings marginTop: theme.spacing(1), @@ -82,10 +83,10 @@ const useStyles = makeStyles( fontSize: 11, opacity: 0.8, marginBottom: theme.spacing(1), - color: theme.palette.bursts.fontColor, + color: theme.page.fontColor, }, breadcrumb: { - color: theme.palette.bursts.fontColor, + color: theme.page.fontColor, }, breadcrumbType: { fontSize: 'inherit', diff --git a/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx b/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx index a34d773ce3..d9443ffc9a 100644 --- a/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx +++ b/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx @@ -27,7 +27,7 @@ const styles = (theme: BackstageTheme) => root: { color: theme.palette.common.white, padding: theme.spacing(2, 2, 3), - backgroundImage: theme.palette.bursts.gradient.linear, + backgroundImage: theme.getPageTheme({ themeId: 'card' }).backgroundImage, backgroundPosition: 0, backgroundSize: 'inherit', }, diff --git a/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx b/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx index b51e3cbc0d..c85e6d11f2 100644 --- a/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx +++ b/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx @@ -85,14 +85,14 @@ const useStyles = makeStyles( overlayHeader: { display: 'flex', - color: theme.palette.bursts.fontColor, + color: theme.palette.text.primary, alignItems: 'center', justifyContent: 'space-between', padding: theme.spacing(2, 3), }, overlayHeaderClose: { - color: theme.palette.bursts.fontColor, + color: theme.palette.text.primary, }, marginMobileSidebar: props => ({ diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index 5f468dba51..37b69d74f7 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -46,9 +46,9 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", @@ -58,7 +58,7 @@ "@types/prop-types": "^15.7.3", "@types/zen-observable": "^0.8.0", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 77d36048ba..7f2fa483f0 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/create-app +## 0.4.29-next.2 + +### Patch Changes + +- f281ad17c0: Adds the ability to define the Backstage app name using a `BACKSTAGE_APP_NAME` + environment variable when running `create-app`. + +## 0.4.29-next.1 + +### Patch Changes + +- Bumped create-app version. + ## 0.4.29-next.0 ### Patch Changes diff --git a/packages/create-app/cli-report.md b/packages/create-app/cli-report.md new file mode 100644 index 0000000000..1244432c6a --- /dev/null +++ b/packages/create-app/cli-report.md @@ -0,0 +1,15 @@ +## CLI Report file for "@backstage/create-app" + +> Do not edit this file. It is a report generated by `yarn build:api-reports` + +### `backstage-create-app` + +``` +Usage: backstage-create-app [options] + +Options: + -V, --version + --path [directory] + --skip-install + -h, --help +``` diff --git a/packages/create-app/package.json b/packages/create-app/package.json index d67e7c6f54..1fc0d17285 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.29-next.0", + "version": "0.4.29-next.2", "private": false, "publishConfig": { "access": "public" diff --git a/packages/create-app/src/createApp.ts b/packages/create-app/src/createApp.ts index 824d1d967e..7cf589e5f8 100644 --- a/packages/create-app/src/createApp.ts +++ b/packages/create-app/src/createApp.ts @@ -49,6 +49,14 @@ export default async (opts: OptionValues): Promise => { } return true; }, + when: (a: Answers) => { + const envName = process.env.BACKSTAGE_APP_NAME; + if (envName) { + a.name = envName; + return false; + } + return true; + }, }, ]); diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index 26aa5ce212..b748970b06 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/dev-utils +## 1.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/app-defaults@1.0.4-next.2 + - @backstage/integration-react@1.1.2-next.2 + +## 1.0.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/app-defaults@1.0.4-next.1 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/test-utils@1.1.2-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 1.0.4-next.0 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 8835aea7c6..8d19bf9cb3 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/dev-utils", "description": "Utilities for developing Backstage plugins.", - "version": "1.0.4-next.0", + "version": "1.0.4-next.2", "private": false, "publishConfig": { "access": "public", @@ -33,15 +33,15 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/app-defaults": "^1.0.4-next.0", + "@backstage/app-defaults": "^1.0.4-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/integration-react": "^1.1.2-next.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/test-utils": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/integration-react": "^1.1.2-next.2", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/test-utils": "^1.1.2-next.1", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@testing-library/jest-dom": "^5.10.1", @@ -59,7 +59,7 @@ "react-dom": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@types/jest": "^26.0.7", "@types/node": "^16.0.0" }, diff --git a/packages/e2e-test/cli-report.md b/packages/e2e-test/cli-report.md new file mode 100644 index 0000000000..3a3912b8fc --- /dev/null +++ b/packages/e2e-test/cli-report.md @@ -0,0 +1,26 @@ +## CLI Report file for "e2e-test" + +> Do not edit this file. It is a report generated by `yarn build:api-reports` + +### `e2e-test` + +``` +Usage: e2e-test [options] [command] + +Options: + -V, --version + -h, --help + +Commands: + run + help [command] +``` + +### `e2e-test run` + +``` +Usage: e2e-test run [options] + +Options: + -h, --help +``` diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index 2de60f4db8..333ac09b23 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -30,7 +30,7 @@ }, "devDependencies": { "@backstage/cli-common": "^0.1.9-next.0", - "@backstage/errors": "^1.0.0", + "@backstage/errors": "^1.1.0-next.0", "@types/fs-extra": "^9.0.1", "@types/node": "^16.11.26", "@types/puppeteer": "^5.4.4", @@ -40,7 +40,7 @@ "fs-extra": "10.1.0", "handlebars": "^4.7.3", "pgtools": "^0.3.0", - "puppeteer": "^14.0.0", + "puppeteer": "^15.0.0", "tree-kill": "^1.2.2", "ts-node": "^10.0.0" }, diff --git a/packages/errors/CHANGELOG.md b/packages/errors/CHANGELOG.md index 20f938370b..b7d912f5ab 100644 --- a/packages/errors/CHANGELOG.md +++ b/packages/errors/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/errors +## 1.1.0-next.0 + +### Minor Changes + +- 6d61b44466: The `ResponseError.fromResponse` now accepts a more narrow response type, in order to avoid incompatibilities between different fetch implementations. + + The `response` property of `ResponseError` has also been narrowed to a new `ConsumedResponse` type that omits all the properties for consuming the body of the response. This is not considered a breaking change as it was always an error to try to consume the body of the response. + ## 1.0.0 ### Major Changes diff --git a/packages/errors/package.json b/packages/errors/package.json index 849c451e84..01f1137eeb 100644 --- a/packages/errors/package.json +++ b/packages/errors/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/errors", "description": "Common utilities for error handling within Backstage", - "version": "1.0.0", + "version": "1.1.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -38,7 +38,7 @@ "serialize-error": "^8.0.1" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/jest": "^26.0.7" }, "files": [ diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index 30326e1205..644d6f7cc4 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/integration-react +## 1.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/integration@1.2.2-next.2 + +## 1.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/integration@1.2.2-next.1 + ## 1.1.2-next.0 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index ea87dfc724..bf0a3e471c 100644 --- a/packages/integration-react/package.json +++ b/packages/integration-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration-react", "description": "Frontend package for managing integrations towards external systems", - "version": "1.1.2-next.0", + "version": "1.1.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -25,10 +25,10 @@ }, "dependencies": { "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/integration": "^1.2.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -38,15 +38,15 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/cli": "^0.18.0-next.2", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", - "msw": "^0.42.0", + "msw": "^0.43.0", "cross-fetch": "^3.1.5" }, "files": [ diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md index 9a9b679b19..bf352f168f 100644 --- a/packages/integration/CHANGELOG.md +++ b/packages/integration/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/integration +## 1.2.2-next.2 + +### Patch Changes + +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +## 1.2.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.1.0-next.0 + ## 1.2.2-next.0 ### Patch Changes diff --git a/packages/integration/package.json b/packages/integration/package.json index f103d63bbb..532797aee8 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration", "description": "Helpers for managing integrations towards external systems", - "version": "1.2.2-next.0", + "version": "1.2.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,21 +34,21 @@ }, "dependencies": { "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", + "@backstage/errors": "^1.1.0-next.0", "cross-fetch": "^3.1.5", - "git-url-parse": "^11.6.0", + "git-url-parse": "^12.0.0", "@octokit/rest": "^18.5.3", "@octokit/auth-app": "^3.4.0", "luxon": "^2.0.2", "lodash": "^4.17.21" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", - "@backstage/config-loader": "^1.1.2", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/cli": "^0.18.0-next.2", + "@backstage/config-loader": "^1.1.3-next.0", + "@backstage/test-utils": "^1.1.2-next.1", "@types/jest": "^26.0.7", "@types/luxon": "^2.0.4", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/packages/integration/src/bitbucketServer/core.test.ts b/packages/integration/src/bitbucketServer/core.test.ts index 1c8f5d259c..076a2c7a4f 100644 --- a/packages/integration/src/bitbucketServer/core.test.ts +++ b/packages/integration/src/bitbucketServer/core.test.ts @@ -108,6 +108,20 @@ describe('bitbucketServer core', () => { ); }); + it('does not double encode the filepath', async () => { + const config: BitbucketServerIntegrationConfig = { + host: 'bitbucket.mycompany.net', + apiBaseUrl: 'https://api.bitbucket.mycompany.net/rest/api/1.0', + }; + const result = await getBitbucketServerDownloadUrl( + 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/%2Fdocs?at=some-branch', + config, + ); + expect(result).toEqual( + 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/archive?format=tgz&at=some-branch&prefix=backstage-mock&path=%2Fdocs', + ); + }); + it('do not add path param if no path is specified for Bitbucket Server', async () => { const defaultBranchResponse = { displayId: 'main', diff --git a/packages/integration/src/bitbucketServer/core.ts b/packages/integration/src/bitbucketServer/core.ts index 80dbc0443f..0c57b0d3ed 100644 --- a/packages/integration/src/bitbucketServer/core.ts +++ b/packages/integration/src/bitbucketServer/core.ts @@ -83,7 +83,9 @@ export async function getBitbucketServerDownloadUrl( // path will limit the downloaded content // /docs will only download the docs folder and everything below it // /docs/index.md will download the docs folder and everything below it - const path = filepath ? `&path=${encodeURIComponent(filepath)}` : ''; + const path = filepath + ? `&path=${encodeURIComponent(decodeURIComponent(filepath))}` + : ''; return `${config.apiBaseUrl}/projects/${project}/repos/${repoName}/archive?format=tgz&at=${branch}&prefix=${project}-${repoName}${path}`; } diff --git a/packages/release-manifests/package.json b/packages/release-manifests/package.json index 822c3c1a52..3309b1b9f1 100644 --- a/packages/release-manifests/package.json +++ b/packages/release-manifests/package.json @@ -37,7 +37,7 @@ }, "devDependencies": { "@backstage/test-utils": "^1.1.2-next.0", - "msw": "^0.42.0", + "msw": "^0.43.0", "@types/jest": "^26.0.7", "@types/node": "^16.0.0" }, diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md index b6ce6d4a97..af9f0ad09c 100644 --- a/packages/techdocs-cli-embedded-app/CHANGELOG.md +++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md @@ -1,5 +1,35 @@ # techdocs-cli-embedded-app +## 0.2.72-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-techdocs@1.2.1-next.2 + - @backstage/plugin-catalog@1.4.0-next.2 + - @backstage/cli@0.18.0-next.2 + - @backstage/app-defaults@1.0.4-next.2 + - @backstage/integration-react@1.1.2-next.2 + - @backstage/plugin-techdocs-react@1.0.2-next.1 + +## 0.2.72-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/cli@0.18.0-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/plugin-catalog@1.3.1-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-techdocs@1.2.1-next.1 + - @backstage/app-defaults@1.0.4-next.1 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/test-utils@1.1.2-next.1 + ## 0.2.72-next.0 ### Patch Changes diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index 959be03e52..60389b6596 100644 --- a/packages/techdocs-cli-embedded-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -1,25 +1,25 @@ { "name": "techdocs-cli-embedded-app", - "version": "0.2.72-next.0", + "version": "0.2.72-next.2", "private": true, "backstage": { "role": "frontend" }, "bundled": true, "dependencies": { - "@backstage/app-defaults": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/cli": "^0.17.3-next.0", + "@backstage/app-defaults": "^1.0.4-next.2", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/cli": "^0.18.0-next.2", "@backstage/config": "^1.0.1", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/integration-react": "^1.1.2-next.0", - "@backstage/plugin-catalog": "^1.3.1-next.0", - "@backstage/plugin-techdocs": "^1.2.1-next.0", - "@backstage/plugin-techdocs-react": "^1.0.2-next.0", - "@backstage/test-utils": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/integration-react": "^1.1.2-next.2", + "@backstage/plugin-catalog": "^1.4.0-next.2", + "@backstage/plugin-techdocs": "^1.2.1-next.2", + "@backstage/plugin-techdocs-react": "^1.0.2-next.1", + "@backstage/test-utils": "^1.1.2-next.1", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "history": "^5.0.0", @@ -30,7 +30,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index aa1870d5da..3e66248276 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,5 +1,15 @@ # @techdocs/cli +## 1.1.3-next.1 + +### Patch Changes + +- a5d73da942: Fix the flag parsing for `legacyCopyReadmeMdToIndexMd` in `techdocs-cli generate` command, and decouple it's logic from the `techdocs-ref` flag. +- Updated dependencies + - @backstage/plugin-techdocs-node@1.2.0-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + ## 1.1.3-next.0 ### Patch Changes diff --git a/packages/techdocs-cli/cli-report.md b/packages/techdocs-cli/cli-report.md new file mode 100644 index 0000000000..64b5e9c090 --- /dev/null +++ b/packages/techdocs-cli/cli-report.md @@ -0,0 +1,117 @@ +## CLI Report file for "@techdocs/cli" + +> Do not edit this file. It is a report generated by `yarn build:api-reports` + +### `techdocs-cli` + +``` +Usage: techdocs-cli [options] [command] + +Options: + -V, --version + -h, --help + +Commands: + generate|build [options] + migrate [options] + publish [options] + serve:mkdocs [options] + serve [options] + help [command] +``` + +### `techdocs-cli generate` + +``` +Usage: techdocs-cli generate|build [options] + +Options: + --source-dir + --output-dir + --docker-image + --no-pull + --no-docker + --techdocs-ref + --etag + -v --verbose + --omitTechdocsCoreMkdocsPlugin + --legacyCopyReadmeMdToIndexMd + -h, --help +``` + +### `techdocs-cli migrate` + +``` +Usage: techdocs-cli migrate [options] + +Options: + --publisher-type + --storage-name + --azureAccountName + --azureAccountKey + --awsRoleArn + --awsEndpoint + --awsS3ForcePathStyle + --awsBucketRootPath + --osCredentialId + --osSecret + --osAuthUrl + --osSwiftUrl + --removeOriginal + --concurrency + -v --verbose + -h, --help +``` + +### `techdocs-cli publish` + +``` +Usage: techdocs-cli publish [options] + +Options: + --publisher-type + --storage-name + --entity + --legacyUseCaseSensitiveTripletPaths + --azureAccountName + --azureAccountKey + --awsRoleArn + --awsEndpoint + --awsS3sse + --awsS3ForcePathStyle + --osCredentialId + --osSecret + --osAuthUrl + --osSwiftUrl + --gcsBucketRootPath + --directory + -h, --help +``` + +### `techdocs-cli serve` + +``` +Usage: techdocs-cli serve [options] + +Options: + -i, --docker-image + --docker-entrypoint + --no-docker + --mkdocs-port + -v --verbose + -h, --help +``` + +### `techdocs-cli serve:mkdocs` + +``` +Usage: techdocs-cli serve:mkdocs [options] + +Options: + -i, --docker-image + --docker-entrypoint + --no-docker + -p, --port + -v --verbose + -h, --help +``` diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index 7f556a8dd7..00e254d10f 100644 --- a/packages/techdocs-cli/package.json +++ b/packages/techdocs-cli/package.json @@ -1,7 +1,7 @@ { "name": "@techdocs/cli", "description": "Utility CLI for managing TechDocs sites in Backstage.", - "version": "1.1.3-next.0", + "version": "1.1.3-next.1", "private": false, "publishConfig": { "access": "public" @@ -37,7 +37,7 @@ "techdocs-cli": "bin/techdocs-cli" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/commander": "^2.12.2", "@types/fs-extra": "^9.0.6", "@types/http-proxy": "^1.17.4", @@ -62,11 +62,11 @@ "ext": "ts" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.1", + "@backstage/catalog-model": "^1.1.0-next.1", "@backstage/cli-common": "^0.1.9", "@backstage/config": "^1.0.1", - "@backstage/plugin-techdocs-node": "^1.1.3-next.0", + "@backstage/plugin-techdocs-node": "^1.2.0-next.1", "@types/dockerode": "^3.3.0", "commander": "^9.1.0", "dockerode": "^3.3.1", diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index 56bcd3ec62..adbb3cd7ac 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/test-utils +## 1.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-permission-common@0.6.3-next.0 + - @backstage/plugin-permission-react@0.4.3-next.0 + ## 1.1.2-next.0 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 17886b76ce..0918dcaaac 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/test-utils", "description": "Utilities to test Backstage plugins and apps.", - "version": "1.1.2-next.0", + "version": "1.1.2-next.1", "private": false, "publishConfig": { "access": "public", @@ -36,9 +36,9 @@ "@backstage/config": "^1.0.1", "@backstage/core-app-api": "^1.0.4-next.0", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-permission-common": "^0.6.2", - "@backstage/plugin-permission-react": "^0.4.2", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-permission-common": "^0.6.3-next.0", + "@backstage/plugin-permission-react": "^0.4.3-next.0", + "@backstage/theme": "^0.2.16-next.0", "@backstage/types": "^1.0.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.11.2", @@ -55,10 +55,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/packages/theme/CHANGELOG.md b/packages/theme/CHANGELOG.md index 5c3e8cf5d6..93b79b0721 100644 --- a/packages/theme/CHANGELOG.md +++ b/packages/theme/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/theme +## 0.2.16-next.1 + +### Patch Changes + +- ff4f56eb49: **DEPRECATED**: The `bursts` object from `BackstagePaletteAdditions` has been depreciated and will be removed in a future release + + The `genPageTheme` function now includes an optional options object with an optional `fontColor` which defaults to white if not provided. + +## 0.2.16-next.0 + +### Patch Changes + +- 4c09c09102: Adds optional `htmlFontSize` property and also sets typography design tokens for h5 and h6 in base theme. + ## 0.2.15 ### Patch Changes diff --git a/packages/theme/api-report.md b/packages/theme/api-report.md index 772e868635..92958c9c7e 100644 --- a/packages/theme/api-report.md +++ b/packages/theme/api-report.md @@ -116,7 +116,13 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides; export const darkTheme: BackstageTheme; // @public -export function genPageTheme(colors: string[], shape: string): PageTheme; +export function genPageTheme(props: { + colors: string[]; + shape: string; + options?: { + fontColor?: string; + }; +}): PageTheme; // @public export const lightTheme: BackstageTheme; @@ -126,6 +132,7 @@ export type PageTheme = { colors: string[]; shape: string; backgroundImage: string; + fontColor: string; }; // @public diff --git a/packages/theme/package.json b/packages/theme/package.json index 0e4d26fbea..4cbd4d2205 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/theme", "description": "material-ui theme for use with Backstage.", - "version": "0.2.15", + "version": "0.2.16-next.1", "private": false, "publishConfig": { "access": "public", @@ -36,7 +36,7 @@ "@material-ui/core": "^4.12.2" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0" + "@backstage/cli": "^0.18.0-next.2" }, "files": [ "dist" diff --git a/packages/theme/src/pageTheme.ts b/packages/theme/src/pageTheme.ts index ae81dc8534..5b5eb24be9 100644 --- a/packages/theme/src/pageTheme.ts +++ b/packages/theme/src/pageTheme.ts @@ -52,6 +52,7 @@ export const colorVariants: Record = { eveningSea: ['#00FFF2', '#035355'], teal: ['#005B4B'], pinkSea: ['#C8077A', '#C2297D'], + greens: ['#4BB8A5', '#187656'], }; /** @@ -63,12 +64,25 @@ export const colorVariants: Record = { * As the background shapes and colors are decorative, we place them onto the * page as a css background-image instead of an html element of its own. */ -export function genPageTheme(colors: string[], shape: string): PageTheme { +export function genPageTheme(props: { + colors: string[]; + shape: string; + options?: { + fontColor?: string; + }; +}): PageTheme { + const { colors, shape, options } = props; const gradientColors = colors.length === 1 ? [colors[0], colors[0]] : colors; const gradient = `linear-gradient(90deg, ${gradientColors.join(', ')})`; const backgroundImage = `${shape}, ${gradient}`; + const fontColor = options?.fontColor ?? '#FFFFFF'; - return { colors, shape, backgroundImage }; + return { + colors: colors, + shape: shape, + backgroundImage: backgroundImage, + fontColor: fontColor, + }; } /** @@ -77,13 +91,20 @@ export function genPageTheme(colors: string[], shape: string): PageTheme { * @public */ export const pageTheme: Record = { - home: genPageTheme(colorVariants.teal, shapes.wave), - documentation: genPageTheme(colorVariants.pinkSea, shapes.wave2), - tool: genPageTheme(colorVariants.purpleSky, shapes.round), - service: genPageTheme(colorVariants.marineBlue, shapes.wave), - website: genPageTheme(colorVariants.veryBlue, shapes.wave), - library: genPageTheme(colorVariants.rubyRed, shapes.wave), - other: genPageTheme(colorVariants.darkGrey, shapes.wave), - app: genPageTheme(colorVariants.toastyOrange, shapes.wave), - apis: genPageTheme(colorVariants.teal, shapes.wave2), + home: genPageTheme({ colors: colorVariants.teal, shape: shapes.wave }), + documentation: genPageTheme({ + colors: colorVariants.pinkSea, + shape: shapes.wave2, + }), + tool: genPageTheme({ colors: colorVariants.purpleSky, shape: shapes.round }), + service: genPageTheme({ + colors: colorVariants.marineBlue, + shape: shapes.wave, + }), + website: genPageTheme({ colors: colorVariants.veryBlue, shape: shapes.wave }), + library: genPageTheme({ colors: colorVariants.rubyRed, shape: shapes.wave }), + other: genPageTheme({ colors: colorVariants.darkGrey, shape: shapes.wave }), + app: genPageTheme({ colors: colorVariants.toastyOrange, shape: shapes.wave }), + apis: genPageTheme({ colors: colorVariants.teal, shape: shapes.wave2 }), + card: genPageTheme({ colors: colorVariants.greens, shape: shapes.wave }), }; diff --git a/packages/theme/src/types.ts b/packages/theme/src/types.ts index b921154005..96b7c54f9b 100644 --- a/packages/theme/src/types.ts +++ b/packages/theme/src/types.ts @@ -63,6 +63,9 @@ export type BackstagePaletteAdditions = { tabbar: { indicator: string; }; + /** + * @deprecated The entire `bursts` section will be removed in a future release + */ bursts: { fontColor: string; slackChannelText: string; @@ -161,4 +164,5 @@ export type PageTheme = { colors: string[]; shape: string; backgroundImage: string; + fontColor: string; }; diff --git a/packages/types/package.json b/packages/types/package.json index 9d26ee25e7..d1410631bd 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -34,7 +34,7 @@ }, "dependencies": {}, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/zen-observable": "^0.8.0", "zen-observable": "^0.8.15" }, diff --git a/packages/version-bridge/package.json b/packages/version-bridge/package.json index 357350bef7..4b9ce2ed11 100644 --- a/packages/version-bridge/package.json +++ b/packages/version-bridge/package.json @@ -37,7 +37,7 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0" diff --git a/plugins/adr-backend/CHANGELOG.md b/plugins/adr-backend/CHANGELOG.md index 8262032252..15a0519010 100644 --- a/plugins/adr-backend/CHANGELOG.md +++ b/plugins/adr-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-adr-backend +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + - @backstage/plugin-adr-common@0.1.2-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + ## 0.1.2-next.0 ### Patch Changes diff --git a/plugins/adr-backend/package.json b/plugins/adr-backend/package.json index 7ed696a650..be04a712cc 100644 --- a/plugins/adr-backend/package.json +++ b/plugins/adr-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr-backend", - "version": "0.1.2-next.0", + "version": "0.1.2-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,14 +29,14 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.1", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/catalog-model": "^1.1.0-next.1", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/plugin-adr-common": "^0.1.2-next.0", - "@backstage/plugin-search-common": "^0.3.5", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.1", + "@backstage/plugin-adr-common": "^0.1.2-next.1", + "@backstage/plugin-search-common": "^0.3.6-next.0", "luxon": "^2.0.2", "marked": "^4.0.14", "winston": "^3.2.1", @@ -44,11 +44,11 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/marked": "^4.0.0", "@types/supertest": "^2.0.8", "supertest": "^6.1.3", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/adr-common/CHANGELOG.md b/plugins/adr-common/CHANGELOG.md index 07bbac4e8e..e07697118c 100644 --- a/plugins/adr-common/CHANGELOG.md +++ b/plugins/adr-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-adr-common +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/integration@1.2.2-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + ## 0.1.2-next.0 ### Patch Changes diff --git a/plugins/adr-common/package.json b/plugins/adr-common/package.json index fee09a03e1..a0567fb5b8 100644 --- a/plugins/adr-common/package.json +++ b/plugins/adr-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-adr-common", "description": "Common functionalities for the adr plugin", - "version": "0.1.2-next.0", + "version": "0.1.2-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,12 +30,12 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/plugin-search-common": "^0.3.5" + "@backstage/catalog-model": "^1.1.0-next.1", + "@backstage/integration": "^1.2.2-next.1", + "@backstage/plugin-search-common": "^0.3.6-next.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0" + "@backstage/cli": "^0.18.0-next.1" }, "files": [ "dist" diff --git a/plugins/adr/CHANGELOG.md b/plugins/adr/CHANGELOG.md index 7d0e47a5f1..efad1034a8 100644 --- a/plugins/adr/CHANGELOG.md +++ b/plugins/adr/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-adr +## 0.1.2-next.2 + +### Patch Changes + +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/plugin-search-react@0.2.2-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/integration-react@1.1.2-next.2 + +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/plugin-adr-common@0.1.2-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + - @backstage/plugin-search-react@0.2.2-next.1 + ## 0.1.2-next.0 ### Patch Changes diff --git a/plugins/adr/package.json b/plugins/adr/package.json index 4bff140277..80d24e7223 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr", - "version": "0.1.2-next.0", + "version": "0.1.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,18 +22,18 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/integration-react": "^1.1.2-next.0", - "@backstage/plugin-adr-common": "^0.1.2-next.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/plugin-search-common": "^0.3.5", - "@backstage/plugin-search-react": "^0.2.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/integration-react": "^1.1.2-next.2", + "@backstage/plugin-adr-common": "^0.1.2-next.1", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/plugin-search-common": "^0.3.6-next.0", + "@backstage/plugin-search-react": "^0.2.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", - "git-url-parse": "^11.6.0", + "git-url-parse": "^12.0.0", "octokit": "^1.7.1", "react-markdown": "^8.0.0", "react-router-dom": "6.0.0-beta.0", @@ -44,10 +44,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", @@ -55,7 +55,7 @@ "@types/jest": "*", "@types/node": "*", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/airbrake-backend/package.json b/plugins/airbrake-backend/package.json index 979137cbff..900161364c 100644 --- a/plugins/airbrake-backend/package.json +++ b/plugins/airbrake-backend/package.json @@ -22,7 +22,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", + "@backstage/backend-common": "^0.14.1-next.1", "@backstage/config": "^1.0.1", "@types/express": "*", "express": "^4.17.1", @@ -33,11 +33,11 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/http-proxy-middleware": "^0.19.3", "@types/supertest": "^2.0.8", "supertest": "^6.1.6", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/airbrake/CHANGELOG.md b/plugins/airbrake/CHANGELOG.md index b1a86b6e22..0be1badd9e 100644 --- a/plugins/airbrake/CHANGELOG.md +++ b/plugins/airbrake/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-airbrake +## 0.3.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/dev-utils@1.0.4-next.2 + +## 0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/dev-utils@1.0.4-next.1 + - @backstage/test-utils@1.1.2-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.3.7-next.0 ### Patch Changes diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index 755e99c522..2f93d533cc 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake", - "version": "0.3.7-next.0", + "version": "0.3.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,13 +23,13 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/test-utils": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/test-utils": "^1.1.2-next.1", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -40,10 +40,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/app-defaults": "^1.0.4-next.0", - "@backstage/cli": "^0.17.3-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/app-defaults": "^1.0.4-next.2", + "@backstage/cli": "^0.18.0-next.2", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", @@ -51,7 +51,7 @@ "@types/node": "^16.11.26", "@types/object-hash": "^2.2.1", "cross-fetch": "^3.1.5", - "msw": "^0.42.0", + "msw": "^0.43.0", "react-router": "6.0.0-beta.0" }, "files": [ diff --git a/plugins/allure/CHANGELOG.md b/plugins/allure/CHANGELOG.md index 06f84b5f42..8f09da737c 100644 --- a/plugins/allure/CHANGELOG.md +++ b/plugins/allure/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-allure +## 0.1.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.1.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.1.23-next.0 ### Patch Changes diff --git a/plugins/allure/package.json b/plugins/allure/package.json index 2499a70f28..c98b8b7d63 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.23-next.0", + "version": "0.1.23-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -25,11 +25,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -40,17 +40,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/analytics-module-ga/CHANGELOG.md b/plugins/analytics-module-ga/CHANGELOG.md index d9fe0e6c0d..edbc67981a 100644 --- a/plugins/analytics-module-ga/CHANGELOG.md +++ b/plugins/analytics-module-ga/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-analytics-module-ga +## 0.1.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## 0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + ## 0.1.18-next.0 ### Patch Changes diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index 0b137d5a44..23532af5fa 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.18-next.0", + "version": "0.1.18-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -25,9 +25,9 @@ }, "dependencies": { "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/theme": "^0.2.15", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -38,17 +38,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/apache-airflow/CHANGELOG.md b/plugins/apache-airflow/CHANGELOG.md index 73c1c2ae18..920dcf5686 100644 --- a/plugins/apache-airflow/CHANGELOG.md +++ b/plugins/apache-airflow/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-apache-airflow +## 0.2.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + +## 0.2.0-next.1 + +### Minor Changes + +- 01f976ea72: Exposed DagTableComponent as standalone component + added a prop to get only select DAGs instead of the full list + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + ## 0.1.15-next.0 ### Patch Changes diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index 63f444075e..657ecc7ad6 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.15-next.0", + "version": "0.2.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,7 +23,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -36,16 +36,16 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/api-docs-module-protoc-gen-doc/package.json b/plugins/api-docs-module-protoc-gen-doc/package.json index 2ce03b5803..00409845d0 100644 --- a/plugins/api-docs-module-protoc-gen-doc/package.json +++ b/plugins/api-docs-module-protoc-gen-doc/package.json @@ -37,7 +37,7 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@testing-library/jest-dom": "^5.16.4", "@types/react": "^16.13.1 || ^17.0.0" }, diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index f5998235ca..6b2e54f018 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-api-docs +## 0.8.7-next.2 + +### Patch Changes + +- a274fe38b9: Add hidden title column to catalog and API table to enable filtering by title. +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog@1.4.0-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.8.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/plugin-catalog@1.3.1-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.8.7-next.0 ### Patch Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 9db7530f84..b6d54ab952 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.8.7-next.0", + "version": "0.8.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,13 +33,13 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@asyncapi/react-component": "1.0.0-next.38", - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@asyncapi/react-component": "1.0.0-next.39", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog": "^1.3.1-next.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-catalog": "^1.4.0-next.2", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@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.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", @@ -68,7 +68,7 @@ "@types/node": "^16.11.26", "@types/swagger-ui-react": "^4.1.1", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.tsx b/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.tsx index 9fc6b2c3c2..b0acd3567c 100644 --- a/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.tsx +++ b/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.tsx @@ -40,6 +40,7 @@ import React from 'react'; import { registerComponentRouteRef } from '../../routes'; const defaultColumns: TableColumn[] = [ + CatalogTable.columns.createTitleColumn({ hidden: true }), CatalogTable.columns.createNameColumn({ defaultKind: 'API' }), CatalogTable.columns.createSystemColumn(), CatalogTable.columns.createOwnerColumn(), diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index aa3baa77da..0282527437 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-app-backend +## 0.3.34-next.2 + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- Updated dependencies + - @backstage/backend-common@0.14.1-next.2 + +## 0.3.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/config-loader@1.1.3-next.0 + ## 0.3.34-next.0 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index 173b15c80c..b25a162f4a 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.34-next.0", + "version": "0.3.34-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,8 +33,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/config-loader": "^1.1.2", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/config-loader": "^1.1.3-next.0", "@backstage/config": "^1.0.1", "@backstage/types": "^1.0.0", "@types/express": "^4.17.6", @@ -43,19 +43,19 @@ "express-promise-router": "^4.1.0", "fs-extra": "10.1.0", "helmet": "^5.0.2", - "knex": "^1.0.2", + "knex": "^2.0.0", "lodash": "^4.17.21", "luxon": "^2.0.2", "winston": "^3.2.1", "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.26-next.0", - "@backstage/cli": "^0.17.3-next.0", + "@backstage/backend-test-utils": "^0.1.26-next.2", + "@backstage/cli": "^0.18.0-next.2", "@backstage/types": "^1.0.0", "@types/supertest": "^2.0.8", "mock-fs": "^5.1.0", - "msw": "^0.42.0", + "msw": "^0.43.0", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index 00c8669c4d..8e6e79d97e 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-auth-backend +## 0.15.0-next.2 + +### Patch Changes + +- 8e03db907a: Auth provider now also export createAuthProviderIntegration +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + +## 0.15.0-next.1 + +### Minor Changes + +- 9d4040777e: **BREAKING**: Removed all directly exported auth provider factories, option types, and sign-in resolvers. For example: `AwsAlbProviderOptions`, `bitbucketUserIdSignInResolver`, `createGithubProvider`. These are all still accessible via the `providers` export. For example, use `providers.github.create()` rather than `createGithubProvider()`, and `providers.bitbucket.resolvers.userIdMatchingUserEntityAnnotation()` rather than `bitbucketUserIdSignInResolver`. + + **BREAKING**: Removed the exported `AuthProviderFactoryOptions` type as well as the deprecated option fields of the `AuthProviderFactory` callback. This includes the `tokenManager`, `tokenIssuer`, `discovery`, and `catalogApi` fields. Existing usage of these should be replaced with the new utilities in the `resolverContext` field. The deprecated `TokenIssuer` type is now also removed, since it is no longer used. + + **BREAKING**: Removed `getEntityClaims`, use `getDefaultOwnershipEntityRefs` instead. + + **DEPRECATION**: Deprecated `AtlassianAuthProvider` as it was unintentionally exported. + +### Patch Changes + +- f2cf79d62e: Added an option for the auth backend router to select the algorithm for the JWT token signing keys +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/plugin-auth-node@0.2.3-next.1 + ## 0.14.2-next.0 ### Patch Changes diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 9e567cc6ab..8c9ec14c9e 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -181,6 +181,22 @@ export type CookieConfigurer = (ctx: { secure: boolean; }; +// Warning: (ae-missing-release-tag) "createAuthProviderIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function createAuthProviderIntegration< + TCreateOptions extends unknown[], + TResolvers extends { + [name in string]: (...args: any[]) => SignInResolver; + }, +>(config: { + create: (...args: TCreateOptions) => AuthProviderFactory; + resolvers?: TResolvers; +}): Readonly<{ + create: (...args: TCreateOptions) => AuthProviderFactory; + resolvers: Readonly; +}>; + // Warning: (ae-missing-release-tag) "createOriginFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -650,6 +666,8 @@ export interface RouterOptions { // (undocumented) providerFactories?: ProviderFactories; // (undocumented) + tokenFactoryAlgorithm?: string; + // (undocumented) tokenManager: TokenManager; } diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index c1fe319e3c..d6b027e6ea 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.14.2-next.0", + "version": "0.15.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,12 +33,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/plugin-auth-node": "^0.2.3-next.0", - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/plugin-auth-node": "^0.2.3-next.1", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", + "@backstage/errors": "^1.1.0-next.0", "@backstage/types": "^1.0.0", "@google-cloud/firestore": "^5.0.2", "@types/express": "^4.17.6", @@ -53,7 +53,7 @@ "google-auth-library": "^8.0.0", "jose": "^4.6.0", "jwt-decode": "^3.1.0", - "knex": "^1.0.2", + "knex": "^2.0.0", "lodash": "^4.17.21", "luxon": "^2.0.2", "minimatch": "^5.0.0", @@ -76,8 +76,8 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.26-next.0", - "@backstage/cli": "^0.17.3-next.0", + "@backstage/backend-test-utils": "^0.1.26-next.2", + "@backstage/cli": "^0.18.0-next.2", "@types/body-parser": "^1.19.0", "@types/cookie-parser": "^1.4.2", "@types/express-session": "^1.17.2", @@ -88,7 +88,7 @@ "@types/passport-saml": "^1.1.3", "@types/passport-strategy": "^0.2.35", "@types/xml2js": "^0.4.7", - "msw": "^0.42.0", + "msw": "^0.43.0", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/auth-backend/src/providers/index.ts b/plugins/auth-backend/src/providers/index.ts index de410a9407..41ee44beae 100644 --- a/plugins/auth-backend/src/providers/index.ts +++ b/plugins/auth-backend/src/providers/index.ts @@ -28,6 +28,8 @@ export type { GcpIapResult, GcpIapTokenInfo } from './gcp-iap'; export { providers, defaultAuthProviderFactories } from './providers'; +export { createAuthProviderIntegration } from './createAuthProviderIntegration'; + export type { AuthProviderConfig, AuthProviderRouteHandlers, diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts index 50577ece53..e4fa5eeea4 100644 --- a/plugins/auth-backend/src/service/router.ts +++ b/plugins/auth-backend/src/service/router.ts @@ -44,6 +44,7 @@ export interface RouterOptions { config: Config; discovery: PluginEndpointDiscovery; tokenManager: TokenManager; + tokenFactoryAlgorithm?: string; providerFactories?: ProviderFactories; } @@ -56,6 +57,7 @@ export async function createRouter( discovery, database, tokenManager, + tokenFactoryAlgorithm, providerFactories, } = options; const router = Router(); @@ -71,6 +73,7 @@ export async function createRouter( keyStore, keyDurationSeconds, logger: logger.child({ component: 'token-factory' }), + algorithm: tokenFactoryAlgorithm, }); const catalogApi = new CatalogClient({ discoveryApi: discovery }); @@ -137,6 +140,7 @@ export async function createRouter( } if (provider.refresh) { r.get('/refresh', provider.refresh.bind(provider)); + r.post('/refresh', provider.refresh.bind(provider)); } router.use(`/${providerId}`, r); diff --git a/plugins/auth-node/CHANGELOG.md b/plugins/auth-node/CHANGELOG.md index 68fef0b00d..43bf44ac8e 100644 --- a/plugins/auth-node/CHANGELOG.md +++ b/plugins/auth-node/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-auth-node +## 0.2.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + ## 0.2.3-next.0 ### Patch Changes diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index bac48aa559..011aade178 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-node", - "version": "0.2.3-next.0", + "version": "0.2.3-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,17 +23,17 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", + "@backstage/backend-common": "^0.14.1-next.1", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", + "@backstage/errors": "^1.1.0-next.0", "jose": "^4.6.0", "node-fetch": "^2.6.7", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "lodash": "^4.17.21", - "msw": "^0.42.0", + "msw": "^0.43.0", "uuid": "^8.0.0" }, "files": [ diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index d0fd5eaf80..cff9eaf07e 100644 --- a/plugins/azure-devops-backend/package.json +++ b/plugins/azure-devops-backend/package.json @@ -23,7 +23,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", + "@backstage/backend-common": "^0.14.1-next.1", "@backstage/config": "^1.0.1", "@backstage/plugin-azure-devops-common": "^0.2.3", "@types/express": "^4.17.6", @@ -35,10 +35,10 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/supertest": "^2.0.8", "supertest": "^6.1.6", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/azure-devops-common/package.json b/plugins/azure-devops-common/package.json index 2e39961ca8..f0f137ac52 100644 --- a/plugins/azure-devops-common/package.json +++ b/plugins/azure-devops-common/package.json @@ -32,7 +32,7 @@ "clean": "backstage-cli package clean" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0" + "@backstage/cli": "^0.18.0-next.1" }, "files": [ "dist" diff --git a/plugins/azure-devops/CHANGELOG.md b/plugins/azure-devops/CHANGELOG.md index 297dc81883..79a58574f3 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-azure-devops +## 0.1.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.1.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.1.23-next.0 ### Patch Changes diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index 5375737866..6ab9760f66 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.23-next.0", + "version": "0.1.23-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,13 +30,13 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", + "@backstage/errors": "^1.1.0-next.0", "@backstage/plugin-azure-devops-common": "^0.2.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -49,17 +49,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/badges-backend/CHANGELOG.md b/plugins/badges-backend/CHANGELOG.md index 6f69cf8662..779625184e 100644 --- a/plugins/badges-backend/CHANGELOG.md +++ b/plugins/badges-backend/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-badges-backend +## 0.1.28-next.2 + +### Patch Changes + +- 58fd5ee9d5: Add missing installation instructions +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + +## 0.1.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/catalog-client@1.0.4-next.1 + ## 0.1.28-next.0 ### Patch Changes diff --git a/plugins/badges-backend/README.md b/plugins/badges-backend/README.md index bdbfac3fa5..63e43c6692 100644 --- a/plugins/badges-backend/README.md +++ b/plugins/badges-backend/README.md @@ -11,8 +11,14 @@ endpoint. ## Installation -Install the `@backstage/plugin-badges-backend` package in your backend package, -and then integrate the plugin using the following default setup for +Install the `@backstage/plugin-badges-backend` package in your backend package: + +```bash +# From your Backstage root directory +yarn add --cwd packages/backend @backstage/plugin-badges-backend +``` + +Add the plugin using the following default setup for `src/plugins/badges.ts`: ```ts @@ -39,6 +45,34 @@ the badges-backend `createRouter()` to forward to the default badge builder. To customize the available badges, provide a custom set of badge factories. See further down for an example of a custom badge factories function. +Finally, you have to make the following changes in `src/index.ts`: + +```ts +// 1. import the plugin +import badges from './plugins/badges'; + +... + +const config = await loadBackendConfig({ + argv: process.argv, + logger: rootLogger, +}); +const createEnv = makeCreateEnv(config); + + ... + // 2. Create a PluginEnvironment for the Badges plugin + const badgesEnv = useHotMemoize(module, () => createEnv('badges')); + + ... + + const apiRouter = Router(); + ... + // 3. Register the badges plugin in the router + apiRouter.use('/badges', await badges(badgesEnv)); + ... + apiRouter.use(notFoundHandler()); +``` + ## Badge builder Badges are created by classes implementing the `BadgeBuilder` type. The default diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index b7a727c3b0..1e0bc62b15 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.28-next.0", + "version": "0.1.28-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,11 +34,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", + "@backstage/errors": "^1.1.0-next.0", "@types/express": "^4.17.6", "badge-maker": "^3.3.0", "cors": "^2.8.5", @@ -48,7 +48,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/badges/CHANGELOG.md b/plugins/badges/CHANGELOG.md index 0d789f0f3d..b6fc662c3a 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-badges +## 0.2.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.2.31-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.2.31-next.0 ### Patch Changes diff --git a/plugins/badges/package.json b/plugins/badges/package.json index c12aedee98..6972ba80ae 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.31-next.0", + "version": "0.2.31-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,12 +30,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -46,17 +46,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/bazaar-backend/CHANGELOG.md b/plugins/bazaar-backend/CHANGELOG.md index cfc222eb55..81358cfc7f 100644 --- a/plugins/bazaar-backend/CHANGELOG.md +++ b/plugins/bazaar-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-bazaar-backend +## 0.1.18-next.1 + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- Updated dependencies + - @backstage/backend-common@0.14.1-next.2 + - @backstage/backend-test-utils@0.1.26-next.2 + ## 0.1.18-next.0 ### Patch Changes diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index c0769fe5b8..351535e544 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.18-next.0", + "version": "0.1.18-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,18 +23,18 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/backend-test-utils": "^0.1.26-next.0", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/backend-test-utils": "^0.1.26-next.2", "@backstage/config": "^1.0.1", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", - "knex": "^1.0.2", + "knex": "^2.0.0", "winston": "^3.2.1", "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0" + "@backstage/cli": "^0.18.0-next.2" }, "files": [ "dist", diff --git a/plugins/bazaar/CHANGELOG.md b/plugins/bazaar/CHANGELOG.md index 577b50f11e..e70e0db58b 100644 --- a/plugins/bazaar/CHANGELOG.md +++ b/plugins/bazaar/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-bazaar +## 0.1.22-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/plugin-catalog@1.4.0-next.2 + - @backstage/cli@0.18.0-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.1.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/cli@0.18.0-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/plugin-catalog@1.3.1-next.1 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.1.22-next.0 ### Patch Changes diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index 5f16d8a9bc..aa44986a79 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar", - "version": "0.1.22-next.0", + "version": "0.1.22-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,13 +24,13 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/cli": "^0.17.3-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/cli": "^0.18.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog": "^1.3.1-next.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", + "@backstage/plugin-catalog": "^1.4.0-next.2", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", "@date-io/luxon": "1.x", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -47,8 +47,8 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", + "@backstage/cli": "^0.18.0-next.2", + "@backstage/dev-utils": "^1.0.4-next.2", "@testing-library/jest-dom": "^5.10.1", "cross-fetch": "^3.1.5" }, diff --git a/plugins/bitbucket-cloud-common/package.json b/plugins/bitbucket-cloud-common/package.json index 46ec37791c..d5a686a1cd 100644 --- a/plugins/bitbucket-cloud-common/package.json +++ b/plugins/bitbucket-cloud-common/package.json @@ -28,13 +28,13 @@ "update-models": "yarn refresh-schema && yarn generate-models && yarn reduce-models" }, "dependencies": { - "@backstage/integration": "^1.2.2-next.0", + "@backstage/integration": "^1.2.2-next.1", "cross-fetch": "^3.1.5" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@openapitools/openapi-generator-cli": "^2.4.26", - "msw": "^0.42.0", + "msw": "^0.43.0", "ts-morph": "^15.0.0" }, "files": [ diff --git a/plugins/bitrise/CHANGELOG.md b/plugins/bitrise/CHANGELOG.md index 86662fdeba..9058f5c15a 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-bitrise +## 0.1.34-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.1.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.1.34-next.0 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index a42a513fbf..07ac2ca46e 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.34-next.0", + "version": "0.1.34-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,11 +24,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -43,17 +43,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "@types/recharts": "^1.8.15", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/catalog-backend-module-aws/CHANGELOG.md b/plugins/catalog-backend-module-aws/CHANGELOG.md index 28bd008062..2f200dd9b1 100644 --- a/plugins/catalog-backend-module-aws/CHANGELOG.md +++ b/plugins/catalog-backend-module-aws/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-aws +## 0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/backend-tasks@0.3.3-next.1 + - @backstage/integration@1.2.2-next.1 + ## 0.1.7-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 1a825a397d..c768bbe9e4 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-aws", "description": "A Backstage catalog backend module that helps integrate towards AWS", - "version": "0.1.7-next.0", + "version": "0.1.7-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,13 +33,13 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/backend-tasks": "^0.3.3-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.1", + "@backstage/backend-tasks": "^0.3.3-next.1", + "@backstage/catalog-model": "^1.1.0-next.1", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/plugin-catalog-backend": "^1.2.1-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.1", + "@backstage/plugin-catalog-backend": "^1.2.1-next.1", "@backstage/types": "^1.0.0", "aws-sdk": "^2.840.0", "lodash": "^4.17.21", @@ -48,7 +48,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/lodash": "^4.14.151", "aws-sdk-mock": "^5.2.1", "yaml": "^1.9.2" diff --git a/plugins/catalog-backend-module-azure/CHANGELOG.md b/plugins/catalog-backend-module-azure/CHANGELOG.md index b39064e4e5..f9c2eeb6ce 100644 --- a/plugins/catalog-backend-module-azure/CHANGELOG.md +++ b/plugins/catalog-backend-module-azure/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-azure +## 0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/backend-tasks@0.3.3-next.1 + - @backstage/integration@1.2.2-next.1 + ## 0.1.5-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index 3e244dc913..6256a01a72 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-azure", "description": "A Backstage catalog backend module that helps integrate towards Azure", - "version": "0.1.5-next.0", + "version": "0.1.5-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,23 +33,23 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/backend-tasks": "^0.3.3-next.0", + "@backstage/backend-common": "^0.14.1-next.1", + "@backstage/catalog-model": "^1.1.0-next.1", + "@backstage/backend-tasks": "^0.3.3-next.1", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/plugin-catalog-backend": "^1.2.1-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.1", + "@backstage/plugin-catalog-backend": "^1.2.1-next.1", "@backstage/types": "^1.0.0", "lodash": "^4.17.21", - "msw": "^0.42.0", + "msw": "^0.43.0", "uuid": "^8.0.0", "node-fetch": "^2.6.7", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.26-next.0", - "@backstage/cli": "^0.17.3-next.0", + "@backstage/backend-test-utils": "^0.1.26-next.1", + "@backstage/cli": "^0.18.0-next.1", "@types/lodash": "^4.14.151" }, "files": [ diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index d55e8d9c8f..b272cb8c29 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -33,19 +33,19 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-tasks": "^0.3.3-next.0", + "@backstage/backend-tasks": "^0.3.3-next.1", "@backstage/config": "^1.0.1", - "@backstage/integration": "^1.2.2-next.0", + "@backstage/integration": "^1.2.2-next.1", "@backstage/plugin-bitbucket-cloud-common": "^0.1.1-next.0", - "@backstage/plugin-catalog-backend": "^1.2.1-next.0", + "@backstage/plugin-catalog-backend": "^1.2.1-next.1", "uuid": "^8.0.0", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/backend-test-utils": "^0.1.26-next.0", - "@backstage/cli": "^0.17.3-next.0", - "msw": "^0.42.0" + "@backstage/backend-common": "^0.14.1-next.1", + "@backstage/backend-test-utils": "^0.1.26-next.1", + "@backstage/cli": "^0.18.0-next.1", + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md index 225e2cda88..a920827973 100644 --- a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-catalog-backend-module-bitbucket +## 0.2.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/integration@1.2.2-next.1 + ## 0.2.1-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket/package.json b/plugins/catalog-backend-module-bitbucket/package.json index d7df9542a6..4eb2a85e0e 100644 --- a/plugins/catalog-backend-module-bitbucket/package.json +++ b/plugins/catalog-backend-module-bitbucket/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket", - "version": "0.2.1-next.0", + "version": "0.2.1-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,22 +33,22 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.1", + "@backstage/catalog-model": "^1.1.0-next.1", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.1", "@backstage/plugin-bitbucket-cloud-common": "^0.1.1-next.0", - "@backstage/plugin-catalog-backend": "^1.2.1-next.0", + "@backstage/plugin-catalog-backend": "^1.2.1-next.1", "@backstage/types": "^1.0.0", "lodash": "^4.17.21", - "msw": "^0.42.0", + "msw": "^0.43.0", "node-fetch": "^2.6.7", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.26-next.0", - "@backstage/cli": "^0.17.3-next.0", + "@backstage/backend-test-utils": "^0.1.26-next.1", + "@backstage/cli": "^0.18.0-next.1", "@types/lodash": "^4.14.151" }, "files": [ diff --git a/plugins/catalog-backend-module-gerrit/CHANGELOG.md b/plugins/catalog-backend-module-gerrit/CHANGELOG.md index 483ff47997..c55973d568 100644 --- a/plugins/catalog-backend-module-gerrit/CHANGELOG.md +++ b/plugins/catalog-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-gerrit +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/backend-tasks@0.3.3-next.1 + - @backstage/integration@1.2.2-next.1 + ## 0.1.2-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index 0668a2858b..6c4bd63659 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gerrit", - "version": "0.1.2-next.0", + "version": "0.1.2-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -28,22 +28,22 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/backend-tasks": "^0.3.3-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.1", + "@backstage/backend-tasks": "^0.3.3-next.1", + "@backstage/catalog-model": "^1.1.0-next.1", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/plugin-catalog-backend": "^1.2.1-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.1", + "@backstage/plugin-catalog-backend": "^1.2.1-next.1", "fs-extra": "10.1.0", - "msw": "^0.42.0", + "msw": "^0.43.0", "node-fetch": "^2.6.7", "uuid": "^8.0.0", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.26-next.0", - "@backstage/cli": "^0.17.3-next.0", + "@backstage/backend-test-utils": "^0.1.26-next.1", + "@backstage/cli": "^0.18.0-next.1", "@types/fs-extra": "^9.0.1" }, "files": [ diff --git a/plugins/catalog-backend-module-github/CHANGELOG.md b/plugins/catalog-backend-module-github/CHANGELOG.md index b97a043aba..42aa26afdf 100644 --- a/plugins/catalog-backend-module-github/CHANGELOG.md +++ b/plugins/catalog-backend-module-github/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-github +## 0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/backend-tasks@0.3.3-next.1 + - @backstage/integration@1.2.2-next.1 + ## 0.1.5-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index c3adbbf212..eae503c507 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-github", "description": "A Backstage catalog backend module that helps integrate towards GitHub", - "version": "0.1.5-next.0", + "version": "0.1.5-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,24 +33,24 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/backend-tasks": "^0.3.3-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.1", + "@backstage/backend-tasks": "^0.3.3-next.1", + "@backstage/catalog-model": "^1.1.0-next.1", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/plugin-catalog-backend": "^1.2.1-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.1", + "@backstage/plugin-catalog-backend": "^1.2.1-next.1", "@backstage/types": "^1.0.0", "@octokit/graphql": "^4.5.8", "lodash": "^4.17.21", - "msw": "^0.42.0", + "msw": "^0.43.0", "node-fetch": "^2.6.7", "uuid": "^8.0.0", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.26-next.0", - "@backstage/cli": "^0.17.3-next.0", + "@backstage/backend-test-utils": "^0.1.26-next.1", + "@backstage/cli": "^0.18.0-next.1", "@types/lodash": "^4.14.151" }, "files": [ diff --git a/plugins/catalog-backend-module-gitlab/CHANGELOG.md b/plugins/catalog-backend-module-gitlab/CHANGELOG.md index 343b2b9d7b..95fa6ddbda 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.1.5-next.1 + +### Patch Changes + +- 49ff472c0b: Add the possibility in the `GitlabDiscoveryEntityProvider` to scan the whole project instead of concrete groups. For that, use a configuration like this one, where the group parameter is omitted (not mandatory anymore): + + ```yaml + catalog: + providers: + gitlab: + yourProviderId: + host: gitlab-host # Identifies one of the hosts set up in the integrations + branch: main # Optional. Uses `master` as default + entityFilename: catalog-info.yaml # Optional. Defaults to `catalog-info.yaml` + ``` + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/backend-tasks@0.3.3-next.1 + - @backstage/integration@1.2.2-next.1 + ## 0.1.5-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index 8d39a8dc05..47f48af481 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab", "description": "A Backstage catalog backend module that helps integrate towards GitLab", - "version": "0.1.5-next.0", + "version": "0.1.5-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,23 +33,23 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/backend-tasks": "^0.3.3-next.0", + "@backstage/backend-common": "^0.14.1-next.1", + "@backstage/catalog-model": "^1.1.0-next.1", + "@backstage/backend-tasks": "^0.3.3-next.1", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/plugin-catalog-backend": "^1.2.1-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.1", + "@backstage/plugin-catalog-backend": "^1.2.1-next.1", "@backstage/types": "^1.0.0", "lodash": "^4.17.21", - "msw": "^0.42.0", + "msw": "^0.43.0", "node-fetch": "^2.6.7", "winston": "^3.2.1", "uuid": "^8.0.0" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.26-next.0", - "@backstage/cli": "^0.17.3-next.0", + "@backstage/backend-test-utils": "^0.1.26-next.1", + "@backstage/cli": "^0.18.0-next.1", "@types/lodash": "^4.14.151", "@types/uuid": "^8.0.0" }, diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index 3afb99dc79..e906e40631 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.5.1-next.1 + +### Patch Changes + +- fbfbff6bf7: Add possibility to resolve relations by RDN, in addition to UUID and DN +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/backend-tasks@0.3.3-next.1 + ## 0.5.1-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index a8c28018f2..7232ea24c3 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-ldap", "description": "A Backstage catalog backend module that helps integrate towards LDAP", - "version": "0.5.1-next.0", + "version": "0.5.1-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,11 +33,11 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-tasks": "^0.3.3-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-tasks": "^0.3.3-next.1", + "@backstage/catalog-model": "^1.1.0-next.1", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-backend": "^1.2.1-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-catalog-backend": "^1.2.1-next.1", "@backstage/types": "^1.0.0", "@types/ldapjs": "^2.2.0", "ldapjs": "^2.2.0", @@ -46,7 +46,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.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 d50e93edcc..a86663d6d1 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,104 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.4.0-next.1 + +### Minor Changes + +- a145672f0f: Align `msgraph` plugin's entity provider config with other providers. **Deprecated** entity processor as well as previous config. + + You will see warning at the log output until you migrate to the new setup. + All deprecated parts will be removed eventually after giving some time to migrate. + + Please find information on how to migrate your current setup to the new one below. + + **Migration Guide:** + + There were two different way on how to use the msgraph plugin: processor or provider. + + Previous registration for the processor: + + ```typescript + // packages/backend/src/plugins/catalog.ts + builder.addProcessor( + MicrosoftGraphOrgReaderProcessor.fromConfig(env.config, { + logger: env.logger, + // [...] + }), + ); + ``` + + Previous registration when using the provider: + + ```typescript + // packages/backend/src/plugins/catalog.ts + builder.addEntityProvider( + MicrosoftGraphOrgEntityProvider.fromConfig(env.config, { + id: 'https://graph.microsoft.com/v1.0', + target: 'https://graph.microsoft.com/v1.0', + logger: env.logger, + schedule: env.scheduler.createScheduledTaskRunner({ + frequency: { minutes: 30 }, + timeout: { minutes: 3 }, + }), + // [...] + }), + ); + ``` + + Previous configuration as used for both: + + ```yaml + # app-config.yaml + catalog: + processors: + microsoftGraphOrg: + providers: + - target: https://graph.microsoft.com/v1.0 + # [...] + ``` + + **Replacement:** + + Please check https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-msgraph/README.md for the complete documentation of all configuration options (config as well as registration of the provider). + + ```yaml + # app-config.yaml + catalog: + providers: + microsoftGraphOrg: + # In case you used the deprecated configuration with the entity provider + # using the value of `target` will keep the same location key for all + providerId: # some stable ID which will be used as part of the location key for all ingested data + target: https://graph.microsoft.com/v1.0 + # [...] + ``` + + ```typescript + // packages/backend/src/plugins/catalog.ts + builder.addEntityProvider( + MicrosoftGraphOrgEntityProvider.fromConfig(env.config, { + logger: env.logger, + schedule: env.scheduler.createScheduledTaskRunner({ + frequency: { minutes: 30 }, + timeout: { minutes: 3 }, + }), + // [...] + }), + ); + ``` + + In case you've used multiple entity providers before + **and** you had different transformers for each of them + you can provide these directly at the one `fromConfig` call + by passing a Record with the provider ID as key. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-tasks@0.3.3-next.2 + - @backstage/plugin-catalog-backend@1.2.1-next.2 + ## 0.3.4-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-msgraph/README.md b/plugins/catalog-backend-module-msgraph/README.md index e6429152e4..6132d5abc6 100644 --- a/plugins/catalog-backend-module-msgraph/README.md +++ b/plugins/catalog-backend-module-msgraph/README.md @@ -1,85 +1,86 @@ # Catalog Backend Module for Microsoft Graph -This is an extension module to the `plugin-catalog-backend` plugin, providing a -`MicrosoftGraphOrgReaderProcessor` and a `MicrosoftGraphOrgEntityProvider` that -can be used to ingest organization data from the Microsoft Graph API. This -processor is useful if you want to import users and groups from Azure Active -Directory or Office 365. +This is an extension module to the `plugin-catalog-backend` plugin, providing a `MicrosoftGraphOrgEntityProvider` +that can be used to ingest organization data from the Microsoft Graph API. +This provider is useful if you want to import users and groups from Azure Active Directory or Office 365. ## Getting Started -First you need to decide whether you want to use an [entity provider or a processor](https://backstage.io/docs/features/software-catalog/life-of-an-entity#stitching) to ingest the organization data. -If you want groups and users deleted from the source to be automatically deleted -from Backstage, choose the entity provider. - 1. Create or use an existing App registration in the [Microsoft Azure Portal](https://portal.azure.com/). The App registration requires at least the API permissions `Group.Read.All`, `GroupMember.Read.All`, `User.Read` and `User.Read.All` for Microsoft Graph (if you still run into errors about insufficient privileges, add `Team.ReadBasic.All` and `TeamMember.Read.All` too). -2. Configure the processor or entity provider: +2. Configure the entity provider: ```yaml # app-config.yaml catalog: - processors: + providers: microsoftGraphOrg: - providers: - - target: https://graph.microsoft.com/v1.0 - authority: https://login.microsoftonline.com - # If you don't know you tenantId, you can use Microsoft Graph Explorer - # to query it - tenantId: ${MICROSOFT_GRAPH_TENANT_ID} - # Client Id and Secret can be created under Certificates & secrets in - # the App registration in the Microsoft Azure Portal. - clientId: ${MICROSOFT_GRAPH_CLIENT_ID} - clientSecret: ${MICROSOFT_GRAPH_CLIENT_SECRET_TOKEN} - # Optional mode for querying which defaults to "basic". - # By default, the Microsoft Graph API only provides the basic feature set - # for querying. Certain features are limited to advanced querying capabilities. - # (See https://docs.microsoft.com/en-us/graph/aad-advanced-queries) - queryMode: basic # basic | advanced + providerId: + target: https://graph.microsoft.com/v1.0 + authority: https://login.microsoftonline.com + # If you don't know you tenantId, you can use Microsoft Graph Explorer + # to query it + tenantId: ${MICROSOFT_GRAPH_TENANT_ID} + # Client Id and Secret can be created under Certificates & secrets in + # the App registration in the Microsoft Azure Portal. + clientId: ${MICROSOFT_GRAPH_CLIENT_ID} + clientSecret: ${MICROSOFT_GRAPH_CLIENT_SECRET_TOKEN} + # Optional mode for querying which defaults to "basic". + # By default, the Microsoft Graph API only provides the basic feature set + # for querying. Certain features are limited to advanced querying capabilities. + # (See https://docs.microsoft.com/en-us/graph/aad-advanced-queries) + queryMode: basic # basic | advanced + # Optional configuration block + user: # Optional parameter to include the expanded resource or collection referenced # by a single relationship (navigation property) in your results. # Only one relationship can be expanded in a single request. # See https://docs.microsoft.com/en-us/graph/query-parameters#expand-parameter # Can be combined with userGroupMember[...] instead of userFilter. - userExpand: manager + expand: manager # Optional filter for user, see Microsoft Graph API for the syntax # See https://docs.microsoft.com/en-us/graph/api/resources/user?view=graph-rest-1.0#properties # and for the syntax https://docs.microsoft.com/en-us/graph/query-parameters#filter-parameter # This and userGroupMemberFilter are mutually exclusive, only one can be specified - userFilter: accountEnabled eq true and userType eq 'member' + filter: accountEnabled eq true and userType eq 'member' + # Optional configuration block + userGroupMember: # Optional filter for users, use group membership to get users. # (Filtered groups and fetch their members.) # This and userFilter are mutually exclusive, only one can be specified # See https://docs.microsoft.com/en-us/graph/search-query-parameter - userGroupMemberFilter: "displayName eq 'Backstage Users'" + filter: "displayName eq 'Backstage Users'" + # Optional search for users, use group membership to get users. + # (Search for groups and fetch their members.) + # This and userFilter are mutually exclusive, only one can be specified + search: '"description:One" AND ("displayName:Video" OR "displayName:Drive")' + # Optional configuration block + group: # Optional parameter to include the expanded resource or collection referenced # by a single relationship (navigation property) in your results. # Only one relationship can be expanded in a single request. # See https://docs.microsoft.com/en-us/graph/query-parameters#expand-parameter # Can be combined with userGroupMember[...] instead of userFilter. - groupExpand: member - # Optional search for users, use group membership to get users. - # (Search for groups and fetch their members.) - # This and userFilter are mutually exclusive, only one can be specified - userGroupMemberSearch: '"description:One" AND ("displayName:Video" OR "displayName:Drive")' + expand: member # Optional filter for group, see Microsoft Graph API for the syntax # See https://docs.microsoft.com/en-us/graph/api/resources/group?view=graph-rest-1.0#properties - groupFilter: securityEnabled eq false and mailEnabled eq true and groupTypes/any(c:c+eq+'Unified') + filter: securityEnabled eq false and mailEnabled eq true and groupTypes/any(c:c+eq+'Unified') # Optional search for groups, see Microsoft Graph API for the syntax # See https://docs.microsoft.com/en-us/graph/search-query-parameter - groupSearch: '"description:One" AND ("displayName:Video" OR "displayName:Drive")' - # Optional select for groups, this will allow you work with schemaExtensions in order to add extra information to your groups that can be used on you custom groupTransformers + search: '"description:One" AND ("displayName:Video" OR "displayName:Drive")' + # Optional select for groups, this will allow you work with schemaExtensions + # in order to add extra information to your groups that can be used on you custom groupTransformers # See https://docs.microsoft.com/en-us/graph/api/resources/schemaextension?view=graph-rest-1.0 - groupSelect: ['id', 'displayName', 'description'] + select: ['id', 'displayName', 'description'] ``` -`userFilter` and `userGroupMemberFilter` are mutually exclusive, only one can be provided. If both are provided, an error will be thrown. +`user.filter` and `userGroupMember.filter` are mutually exclusive, only one can be provided. If both are provided, an error will be thrown. -By default, all users are loaded. If you want to filter users based on their attributes, use `userFilter`. `userGroupMemberFilter` can be used if you want to load users based on their group membership. +By default, all users are loaded. If you want to filter users based on their attributes, use `user.filter`. `userGroupMember.filter` can be used if you want to load users based on their group membership. 3. The package is not installed by default, therefore you have to add a dependency to `@backstage/plugin-catalog-backend-module-msgraph` to your @@ -90,15 +91,12 @@ By default, all users are loaded. If you want to filter users based on their att yarn add --cwd packages/backend @backstage/plugin-catalog-backend-module-msgraph ``` -### Using the Entity Provider - 4. The `MicrosoftGraphOrgEntityProvider` is not registered by default, so you have to register it in the catalog plugin. Pass the target to reference a provider from the configuration. ```diff // packages/backend/src/plugins/catalog.ts -+import { Duration } from 'luxon'; +import { MicrosoftGraphOrgEntityProvider } from '@backstage/plugin-catalog-backend-module-msgraph'; export default async function createPlugin( @@ -106,53 +104,21 @@ yarn add --cwd packages/backend @backstage/plugin-catalog-backend-module-msgraph ): Promise { const builder = await CatalogBuilder.create(env); -+ // The target parameter below needs to match one of the providers' target -+ // value specified in your app-config (see above). + builder.addEntityProvider( + MicrosoftGraphOrgEntityProvider.fromConfig(env.config, { -+ id: 'production', -+ target: 'https://graph.microsoft.com/v1.0', + logger: env.logger, + schedule: env.scheduler.createScheduledTaskRunner({ -+ frequency: Duration.fromObject({ minutes: 5 }), -+ timeout: Duration.fromObject({ minutes: 3 }), ++ frequency: { minutes: 5 }, ++ timeout: { minutes: 3 }, + }), + }), + ); ``` -### Using the Processor - -4. The `MicrosoftGraphOrgReaderProcessor` is not registered by default, so you - have to register it in the catalog plugin: - -```typescript -// packages/backend/src/plugins/catalog.ts -builder.addProcessor( - MicrosoftGraphOrgReaderProcessor.fromConfig(env.config, { - logger: env.logger, - }), -); -``` - -5. Add a location that ingests from Microsoft Graph: - -```yaml -# app-config.yaml -catalog: - locations: - - type: microsoft-graph-org - target: https://graph.microsoft.com/v1.0 - rules: - - allow: [Group, User] - … -``` - ## Customize the Processor or Entity Provider -In case you want to customize the ingested entities, both the `MicrosoftGraphOrgReaderProcessor` -and the `MicrosoftGraphOrgEntityProvider` allows to pass transformers for users, -groups and the organization. +In case you want to customize the ingested entities, the `MicrosoftGraphOrgEntityProvider` +allows to pass transformers for users, groups and the organization. 1. Create a transformer: @@ -179,13 +145,17 @@ export async function myGroupTransformer( } ``` -2. Configure the processor with the transformer: +2. Add the transformer: -```ts -builder.addProcessor( - MicrosoftGraphOrgReaderProcessor.fromConfig(env.config, { - logger: env.logger, - groupTransformer: myGroupTransformer, - }), -); +```diff + builder.addEntityProvider( + MicrosoftGraphOrgEntityProvider.fromConfig(env.config, { + logger: env.logger, + schedule: env.scheduler.createScheduledTaskRunner({ + frequency: { minutes: 5 }, + timeout: { minutes: 3 }, + }), ++ groupTransformer: myGroupTransformer, + }), + ); ``` diff --git a/plugins/catalog-backend-module-msgraph/api-report.md b/plugins/catalog-backend-module-msgraph/api-report.md index 31a22b0bc4..a4083b1d9e 100644 --- a/plugins/catalog-backend-module-msgraph/api-report.md +++ b/plugins/catalog-backend-module-msgraph/api-report.md @@ -125,14 +125,14 @@ export class MicrosoftGraphOrgEntityProvider implements EntityProvider { static fromConfig( configRoot: Config, options: MicrosoftGraphOrgEntityProviderOptions, - ): MicrosoftGraphOrgEntityProvider; + ): MicrosoftGraphOrgEntityProvider[]; // (undocumented) getProviderName(): string; read(options?: { logger?: Logger }): Promise; } -// @public -export interface MicrosoftGraphOrgEntityProviderOptions { +// @public @deprecated +export interface MicrosoftGraphOrgEntityProviderLegacyOptions { groupTransformer?: GroupTransformer; id: string; logger: Logger; @@ -143,6 +143,19 @@ export interface MicrosoftGraphOrgEntityProviderOptions { } // @public +export type MicrosoftGraphOrgEntityProviderOptions = + | MicrosoftGraphOrgEntityProviderLegacyOptions + | { + logger: Logger; + schedule: 'manual' | TaskRunner; + userTransformer?: UserTransformer | Record; + groupTransformer?: GroupTransformer | Record; + organizationTransformer?: + | OrganizationTransformer + | Record; + }; + +// @public @deprecated export class MicrosoftGraphOrgReaderProcessor implements CatalogProcessor { constructor(options: { providers: MicrosoftGraphProviderConfig[]; @@ -173,6 +186,7 @@ export class MicrosoftGraphOrgReaderProcessor implements CatalogProcessor { // @public export type MicrosoftGraphProviderConfig = { + id: string; target: string; authority?: string; tenantId: string; @@ -206,7 +220,7 @@ export type OrganizationTransformer = ( organization: MicrosoftGraph.Organization, ) => Promise; -// @public +// @public @deprecated export function readMicrosoftGraphConfig( config: Config, ): MicrosoftGraphProviderConfig[]; diff --git a/plugins/catalog-backend-module-msgraph/config.d.ts b/plugins/catalog-backend-module-msgraph/config.d.ts index cf00713e72..564ccbb10a 100644 --- a/plugins/catalog-backend-module-msgraph/config.d.ts +++ b/plugins/catalog-backend-module-msgraph/config.d.ts @@ -25,6 +25,7 @@ export interface Config { processors?: { /** * MicrosoftGraphOrgReaderProcessor configuration + * @deprecated Use `catalog.providers.microsoftGraphOrg` instead. */ microsoftGraphOrg?: { /** @@ -102,5 +103,173 @@ export interface Config { }>; }; }; + /** + * List of provider-specific options and attributes + */ + providers?: { + /** + * MicrosoftGraphOrgEntityProvider configuration. + */ + microsoftGraphOrg?: + | { + /** + * The prefix of the target that this matches on, e.g. + * "https://graph.microsoft.com/v1.0", with no trailing slash. + */ + target: string; + /** + * The auth authority used. + * + * Default value "https://login.microsoftonline.com" + */ + authority?: string; + /** + * The tenant whose org data we are interested in. + */ + tenantId: string; + /** + * The OAuth client ID to use for authenticating requests. + */ + clientId: string; + /** + * The OAuth client secret to use for authenticating requests. + * + * @visibility secret + */ + clientSecret: string; + + user?: { + /** + * The "expand" argument to apply to users. + * + * E.g. "manager". + */ + expand?: string; + /** + * The filter to apply to extract users. + * + * E.g. "accountEnabled eq true and userType eq 'member'" + */ + filter?: string; + }; + + group?: { + /** + * The "expand" argument to apply to groups. + * + * E.g. "member". + */ + expand?: string; + /** + * The filter to apply to extract groups. + * + * E.g. "securityEnabled eq false and mailEnabled eq true" + */ + filter?: string; + /** + * The search criteria to apply to extract users by groups memberships. + * + * E.g. "\"displayName:-team\"" would only match groups which contain '-team' + */ + search?: string; + /** + * The fields to be fetched on query. + * + * E.g. ["id", "displayName", "description"] + */ + select?: string[]; + }; + + userGroupMember?: { + /** + * The filter to apply to extract users by groups memberships. + * + * E.g. "displayName eq 'Backstage Users'" + */ + filter?: string; + /** + * The search criteria to apply to extract groups. + * + * E.g. "\"displayName:-team\"" would only match groups which contain '-team' + */ + search?: string; + }; + } + | Record< + string, + { + /** + * The prefix of the target that this matches on, e.g. + * "https://graph.microsoft.com/v1.0", with no trailing slash. + */ + target: string; + /** + * The auth authority used. + * + * Default value "https://login.microsoftonline.com" + */ + authority?: string; + /** + * The tenant whose org data we are interested in. + */ + tenantId: string; + /** + * The OAuth client ID to use for authenticating requests. + */ + clientId: string; + /** + * The OAuth client secret to use for authenticating requests. + * + * @visibility secret + */ + clientSecret: string; + + user?: { + /** + * The filter to apply to extract users. + * + * E.g. "accountEnabled eq true and userType eq 'member'" + */ + filter?: string; + }; + + group?: { + /** + * The filter to apply to extract groups. + * + * E.g. "securityEnabled eq false and mailEnabled eq true" + */ + filter?: string; + /** + * The search criteria to apply to extract users by groups memberships. + * + * E.g. "\"displayName:-team\"" would only match groups which contain '-team' + */ + search?: string; + /** + * The fields to be fetched on query. + * + * E.g. ["id", "displayName", "description"] + */ + select?: string[]; + }; + + userGroupMember?: { + /** + * The filter to apply to extract users by groups memberships. + * + * E.g. "displayName eq 'Backstage Users'" + */ + filter?: string; + /** + * The search criteria to apply to extract groups. + * + * E.g. "\"displayName:-team\"" would only match groups which contain '-team' + */ + search?: string; + }; + } + >; + }; }; } diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index e2e75af446..921d198b8b 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-msgraph", "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph", - "version": "0.3.4-next.0", + "version": "0.4.0-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,10 +34,10 @@ }, "dependencies": { "@azure/msal-node": "^1.1.0", - "@backstage/backend-tasks": "^0.3.3-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-tasks": "^0.3.3-next.2", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/plugin-catalog-backend": "^1.2.1-next.0", + "@backstage/plugin-catalog-backend": "^1.2.1-next.2", "@microsoft/microsoft-graph-types": "^2.6.0", "@types/node-fetch": "^2.5.12", "lodash": "^4.17.21", @@ -48,11 +48,11 @@ "qs": "^6.9.4" }, "devDependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/backend-test-utils": "^0.1.26-next.0", - "@backstage/cli": "^0.17.3-next.0", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/backend-test-utils": "^0.1.26-next.2", + "@backstage/cli": "^0.18.0-next.2", "@types/lodash": "^4.14.151", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts index e310fa544f..8239090249 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts @@ -15,13 +15,14 @@ */ import { ConfigReader } from '@backstage/config'; -import { readMicrosoftGraphConfig } from './config'; +import { readMicrosoftGraphConfig, readProviderConfigs } from './config'; describe('readMicrosoftGraphConfig', () => { it('applies all of the defaults', () => { const config = { providers: [ { + id: 'target', target: 'target', tenantId: 'tenantId', clientId: 'clientId', @@ -32,6 +33,7 @@ describe('readMicrosoftGraphConfig', () => { const actual = readMicrosoftGraphConfig(new ConfigReader(config)); const expected = [ { + id: 'target', target: 'target', tenantId: 'tenantId', clientId: 'clientId', @@ -48,6 +50,7 @@ describe('readMicrosoftGraphConfig', () => { const config = { providers: [ { + id: 'target', target: 'target', tenantId: 'tenantId', clientId: 'clientId', @@ -64,6 +67,7 @@ describe('readMicrosoftGraphConfig', () => { const actual = readMicrosoftGraphConfig(new ConfigReader(config)); const expected = [ { + id: 'target', target: 'target', tenantId: 'tenantId', clientId: 'clientId', @@ -83,6 +87,7 @@ describe('readMicrosoftGraphConfig', () => { const config = { providers: [ { + id: 'target', target: 'target', tenantId: 'tenantId', clientId: 'clientId', @@ -100,6 +105,7 @@ describe('readMicrosoftGraphConfig', () => { const config = { providers: [ { + id: 'target', target: 'target', tenantId: 'tenantId', clientId: 'clientId', @@ -113,3 +119,128 @@ describe('readMicrosoftGraphConfig', () => { expect(() => readMicrosoftGraphConfig(new ConfigReader(config))).toThrow(); }); }); + +describe('readProviderConfigs', () => { + it('applies all of the defaults', () => { + const config = { + catalog: { + providers: { + microsoftGraphOrg: { + customProviderId: { + target: 'target', + tenantId: 'tenantId', + clientId: 'clientId', + clientSecret: 'clientSecret', + }, + }, + }, + }, + }; + const actual = readProviderConfigs(new ConfigReader(config)); + const expected = [ + { + id: 'customProviderId', + target: 'target', + tenantId: 'tenantId', + clientId: 'clientId', + clientSecret: 'clientSecret', + authority: 'https://login.microsoftonline.com', + }, + ]; + expect(actual).toEqual(expected); + }); + + it('reads all the values', () => { + const config = { + catalog: { + providers: { + microsoftGraphOrg: { + customProviderId: { + target: 'target', + tenantId: 'tenantId', + clientId: 'clientId', + clientSecret: 'clientSecret', + authority: 'https://login.example.com/', + user: { + expand: 'manager', + filter: 'accountEnabled eq true', + }, + group: { + expand: 'member', + filter: 'securityEnabled eq false', + select: ['id', 'displayName', 'description'], + }, + }, + }, + }, + }, + }; + const actual = readProviderConfigs(new ConfigReader(config)); + const expected = [ + { + id: 'customProviderId', + target: 'target', + tenantId: 'tenantId', + clientId: 'clientId', + clientSecret: 'clientSecret', + authority: 'https://login.example.com', + userExpand: 'manager', + userFilter: 'accountEnabled eq true', + groupExpand: 'member', + groupSelect: ['id', 'displayName', 'description'], + groupFilter: 'securityEnabled eq false', + }, + ]; + expect(actual).toEqual(expected); + }); + + it('should fail if both userFilter and userGroupMemberFilter are set', () => { + const config = { + catalog: { + providers: { + microsoftGraphOrg: { + customProviderId: { + target: 'target', + tenantId: 'tenantId', + clientId: 'clientId', + clientSecret: 'clientSecret', + authority: 'https://login.example.com/', + user: { + filter: 'accountEnabled eq true', + }, + userGroupMember: { + filter: 'any', + }, + }, + }, + }, + }, + }; + expect(() => readProviderConfigs(new ConfigReader(config))).toThrow(); + }); + + it('should fail if both userFilter and userGroupMemberSearch are set', () => { + const config = { + catalog: { + providers: { + microsoftGraphOrg: { + customProviderId: { + target: 'target', + tenantId: 'tenantId', + clientId: 'clientId', + clientSecret: 'clientSecret', + authority: 'https://login.example.com/', + user: { + filter: 'accountEnabled eq true', + }, + userGroupMember: { + search: 'any', + }, + }, + }, + }, + }, + }; + expect(() => readProviderConfigs(new ConfigReader(config))).toThrow(); + }); +}); diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts index aa2f2d6ee2..30e3a9a4d2 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts @@ -17,12 +17,21 @@ import { Config } from '@backstage/config'; import { trimEnd } from 'lodash'; +const DEFAULT_AUTHORITY = 'https://login.microsoftonline.com'; +const DEFAULT_PROVIDER_ID = 'default'; +const DEFAULT_TARGET = 'https://graph.microsoft.com/v1.0'; + /** * The configuration parameters for a single Microsoft Graph provider. * * @public */ export type MicrosoftGraphProviderConfig = { + /** + * Identifier of the provider which will be used i.e. at the location key for ingested entities. + */ + id: string; + /** * The prefix of the target that this matches on, e.g. * "https://graph.microsoft.com/v1.0", with no trailing slash. @@ -55,7 +64,7 @@ export type MicrosoftGraphProviderConfig = { /** * The "expand" argument to apply to users. * - * E.g. "manager" + * E.g. "manager". */ userExpand?: string; /** @@ -73,7 +82,7 @@ export type MicrosoftGraphProviderConfig = { /** * The "expand" argument to apply to groups. * - * E.g. "member" + * E.g. "member". */ groupExpand?: string; /** @@ -113,6 +122,7 @@ export type MicrosoftGraphProviderConfig = { * @param config - The root of the msgraph config hierarchy * * @public + * @deprecated Replaced by not exported `readProviderConfigs` and kept for backwards compatibility only. */ export function readMicrosoftGraphConfig( config: Config, @@ -125,7 +135,7 @@ export function readMicrosoftGraphConfig( const authority = providerConfig.getOptionalString('authority') ? trimEnd(providerConfig.getOptionalString('authority'), '/') - : 'https://login.microsoftonline.com'; + : DEFAULT_AUTHORITY; const tenantId = providerConfig.getString('tenantId'); const clientId = providerConfig.getString('clientId'); const clientSecret = providerConfig.getString('clientSecret'); @@ -164,6 +174,7 @@ export function readMicrosoftGraphConfig( } providers.push({ + id: target, target, authority, tenantId, @@ -183,3 +194,86 @@ export function readMicrosoftGraphConfig( return providers; } + +export function readProviderConfigs( + config: Config, +): MicrosoftGraphProviderConfig[] { + const providersConfig = config.getOptionalConfig( + 'catalog.providers.microsoftGraphOrg', + ); + if (!providersConfig) { + return []; + } + + if (providersConfig.has('clientId')) { + // simple/single config variant + return [readProviderConfig(DEFAULT_PROVIDER_ID, providersConfig)]; + } + + return providersConfig.keys().map(id => { + const providerConfig = providersConfig.getConfig(id); + + return readProviderConfig(id, providerConfig); + }); +} + +export function readProviderConfig( + id: string, + config: Config, +): MicrosoftGraphProviderConfig { + const target = trimEnd( + config.getOptionalString('target') ?? DEFAULT_TARGET, + '/', + ); + const authority = trimEnd( + config.getOptionalString('authority') ?? DEFAULT_AUTHORITY, + '/', + ); + + const clientId = config.getString('clientId'); + const clientSecret = config.getString('clientSecret'); + const tenantId = config.getString('tenantId'); + + const userExpand = config.getOptionalString('user.expand'); + const userFilter = config.getOptionalString('user.filter'); + + const groupExpand = config.getOptionalString('group.expand'); + const groupFilter = config.getOptionalString('group.filter'); + const groupSearch = config.getOptionalString('group.search'); + const groupSelect = config.getOptionalStringArray('group.select'); + + const userGroupMemberFilter = config.getOptionalString( + 'userGroupMember.filter', + ); + const userGroupMemberSearch = config.getOptionalString( + 'userGroupMember.search', + ); + + if (userFilter && userGroupMemberFilter) { + throw new Error( + `userFilter and userGroupMemberFilter are mutually exclusive, only one can be specified.`, + ); + } + if (userFilter && userGroupMemberSearch) { + throw new Error( + `userGroupMemberSearch cannot be specified when userFilter is defined.`, + ); + } + + return { + id, + target, + authority, + clientId, + clientSecret, + tenantId, + userExpand, + userFilter, + groupExpand, + groupFilter, + groupSearch, + groupSelect, + userGroupMemberFilter, + userGroupMemberSearch, + }; +} diff --git a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.test.ts b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.test.ts index 456afda550..26b4f80765 100644 --- a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.test.ts @@ -14,6 +14,7 @@ * limitations under the License. */ import { getVoidLogger } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; import { ANNOTATION_LOCATION, ANNOTATION_ORIGIN_LOCATION, @@ -78,19 +79,30 @@ describe('MicrosoftGraphOrgEntityProvider', () => { ], }); + const config = { + catalog: { + providers: { + microsoftGraphOrg: { + customProviderId: { + target: 'target', + tenantId: 'tenantId', + clientId: 'clientId', + clientSecret: 'clientSecret', + }, + }, + }, + }, + }; const entityProviderConnection: EntityProviderConnection = { applyMutation: jest.fn(), }; - const provider = new MicrosoftGraphOrgEntityProvider({ - id: 'test', - logger: getVoidLogger(), - provider: { - target: 'https://example.com', - tenantId: 'tenant', - clientId: 'clientid', - clientSecret: 'clientsecret', + const provider = MicrosoftGraphOrgEntityProvider.fromConfig( + new ConfigReader(config), + { + logger: getVoidLogger(), + schedule: 'manual', }, - }); + )[0]; provider.connect(entityProviderConnection); @@ -104,8 +116,10 @@ describe('MicrosoftGraphOrgEntityProvider', () => { kind: 'User', metadata: { annotations: { - 'backstage.io/managed-by-location': 'msgraph:test/u1', - 'backstage.io/managed-by-origin-location': 'msgraph:test/u1', + 'backstage.io/managed-by-location': + 'msgraph:customProviderId/u1', + 'backstage.io/managed-by-origin-location': + 'msgraph:customProviderId/u1', }, name: 'u1', }, @@ -113,7 +127,7 @@ describe('MicrosoftGraphOrgEntityProvider', () => { memberOf: [], }, }, - locationKey: 'msgraph-org-provider:test', + locationKey: 'msgraph-org-provider:customProviderId', }, { entity: { @@ -121,8 +135,10 @@ describe('MicrosoftGraphOrgEntityProvider', () => { kind: 'Group', metadata: { annotations: { - 'backstage.io/managed-by-location': 'msgraph:test/g1', - 'backstage.io/managed-by-origin-location': 'msgraph:test/g1', + 'backstage.io/managed-by-location': + 'msgraph:customProviderId/g1', + 'backstage.io/managed-by-origin-location': + 'msgraph:customProviderId/g1', }, name: 'g1', }, @@ -131,7 +147,7 @@ describe('MicrosoftGraphOrgEntityProvider', () => { type: 'team', }, }, - locationKey: 'msgraph-org-provider:test', + locationKey: 'msgraph-org-provider:customProviderId', }, ], type: 'full', diff --git a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.ts b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.ts index d96faf8e03..4a52ddc665 100644 --- a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.ts +++ b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.ts @@ -40,13 +40,64 @@ import { readMicrosoftGraphOrg, UserTransformer, } from '../microsoftGraph'; +import { readProviderConfigs } from '../microsoftGraph/config'; /** * Options for {@link MicrosoftGraphOrgEntityProvider}. * * @public */ -export interface MicrosoftGraphOrgEntityProviderOptions { +export type MicrosoftGraphOrgEntityProviderOptions = + | MicrosoftGraphOrgEntityProviderLegacyOptions + | { + /** + * The logger to use. + */ + logger: Logger; + + /** + * The refresh schedule to use. + * + * @remarks + * + * If you pass in 'manual', you are responsible for calling the `read` method + * manually at some interval. + * + * But more commonly you will pass in the result of + * {@link @backstage/backend-tasks#PluginTaskScheduler.createScheduledTaskRunner} + * to enable automatic scheduling of tasks. + */ + schedule: 'manual' | TaskRunner; + + /** + * The function that transforms a user entry in msgraph to an entity. + * Optionally, you can pass separate transformers per provider ID. + */ + userTransformer?: UserTransformer | Record; + + /** + * The function that transforms a group entry in msgraph to an entity. + * Optionally, you can pass separate transformers per provider ID. + */ + groupTransformer?: GroupTransformer | Record; + + /** + * The function that transforms an organization entry in msgraph to an entity. + * Optionally, you can pass separate transformers per provider ID. + */ + organizationTransformer?: + | OrganizationTransformer + | Record; + }; + +/** + * Legacy options for {@link MicrosoftGraphOrgEntityProvider} + * based on `catalog.processors.microsoftGraphOrg`. + * + * @public + * @deprecated This interface exists for backwards compatibility only and will be removed in the future. + */ +export interface MicrosoftGraphOrgEntityProviderLegacyOptions { /** * A unique, stable identifier for this provider. * @@ -57,7 +108,7 @@ export interface MicrosoftGraphOrgEntityProviderOptions { /** * The target that this provider should consume. * - * Should exactly match the "target" field of one of the providers + * Should exactly match the "target" field of one of the provider * configuration entries. */ target: string; @@ -110,7 +161,58 @@ export class MicrosoftGraphOrgEntityProvider implements EntityProvider { static fromConfig( configRoot: Config, options: MicrosoftGraphOrgEntityProviderOptions, - ) { + ): MicrosoftGraphOrgEntityProvider[] { + if ('id' in options) { + return [ + MicrosoftGraphOrgEntityProvider.fromLegacyConfig(configRoot, options), + ]; + } + + function getTransformer( + id: string, + transformers?: T | Record, + ): T | undefined { + if (['undefined', 'function'].includes(typeof transformers)) { + return transformers as T; + } + + return (transformers as Record)[id]; + } + + return readProviderConfigs(configRoot).map(providerConfig => { + const provider = new MicrosoftGraphOrgEntityProvider({ + id: providerConfig.id, + provider: providerConfig, + logger: options.logger, + userTransformer: getTransformer( + providerConfig.id, + options.userTransformer, + ), + groupTransformer: getTransformer( + providerConfig.id, + options.groupTransformer, + ), + organizationTransformer: getTransformer( + providerConfig.id, + options.organizationTransformer, + ), + }); + provider.schedule(options.schedule); + + return provider; + }); + } + + /** + * @deprecated Exists for backwards compatibility only and will be removed in the future. + */ + private static fromLegacyConfig( + configRoot: Config, + options: MicrosoftGraphOrgEntityProviderLegacyOptions, + ): MicrosoftGraphOrgEntityProvider { + options.logger.warn( + 'Deprecated msgraph config "catalog.processors.microsoftGraphOrg" used. Use "catalog.providers.microsoftGraphOrg" instead. More info at https://github.com/backstage/backstage/blob/master/.changeset/long-bananas-rescue.md', + ); const config = configRoot.getOptionalConfig( 'catalog.processors.microsoftGraphOrg', ); diff --git a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.test.ts b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.test.ts index 8236dc52e1..bcf76e9482 100644 --- a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.test.ts @@ -38,6 +38,7 @@ describe('MicrosoftGraphOrgReaderProcessor', () => { processor = new MicrosoftGraphOrgReaderProcessor({ providers: [ { + id: 'https://example.com', target: 'https://example.com', tenantId: 'tenant', clientId: 'clientid', diff --git a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts index 5d0e6b2ec7..decd84ec1f 100644 --- a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts +++ b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts @@ -33,9 +33,10 @@ import { } from '../microsoftGraph'; /** - * Extracts teams and users out of a the Microsoft Graph API. + * Extracts teams and users out of the Microsoft Graph API. * * @public + * @deprecated Use the MicrosoftGraphOrgEntityProvider instead. */ export class MicrosoftGraphOrgReaderProcessor implements CatalogProcessor { private readonly providers: MicrosoftGraphProviderConfig[]; @@ -67,6 +68,9 @@ export class MicrosoftGraphOrgReaderProcessor implements CatalogProcessor { groupTransformer?: GroupTransformer; organizationTransformer?: OrganizationTransformer; }) { + options.logger.warn( + 'MicrosoftGraphOrgReaderProcessor is deprecated. Please use MicrosoftGraphOrgEntityProvider instead. More info at https://github.com/backstage/backstage/blob/master/.changeset/long-bananas-rescue.md', + ); this.providers = options.providers; this.logger = options.logger; this.userTransformer = options.userTransformer; diff --git a/plugins/catalog-backend-module-msgraph/src/processors/index.ts b/plugins/catalog-backend-module-msgraph/src/processors/index.ts index 7bc3559c8b..7e74ca1d8b 100644 --- a/plugins/catalog-backend-module-msgraph/src/processors/index.ts +++ b/plugins/catalog-backend-module-msgraph/src/processors/index.ts @@ -15,5 +15,8 @@ */ export { MicrosoftGraphOrgEntityProvider } from './MicrosoftGraphOrgEntityProvider'; -export type { MicrosoftGraphOrgEntityProviderOptions } from './MicrosoftGraphOrgEntityProvider'; +export type { + MicrosoftGraphOrgEntityProviderOptions, + MicrosoftGraphOrgEntityProviderLegacyOptions, +} from './MicrosoftGraphOrgEntityProvider'; export { MicrosoftGraphOrgReaderProcessor } from './MicrosoftGraphOrgReaderProcessor'; diff --git a/plugins/catalog-backend-module-openapi/CHANGELOG.md b/plugins/catalog-backend-module-openapi/CHANGELOG.md new file mode 100644 index 0000000000..657238efda --- /dev/null +++ b/plugins/catalog-backend-module-openapi/CHANGELOG.md @@ -0,0 +1,28 @@ +# @backstage/plugin-catalog-backend-module-openapi + +## 0.1.0-next.1 + +### Patch Changes + +- 4881dc4c84: Updated dependency `openapi-types` to `^12.0.0`. +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + - @backstage/plugin-catalog-backend@1.2.1-next.2 + - @backstage/integration@1.2.2-next.2 + +## 0.1.0-next.0 + +### Minor Changes + +- 67503d159e: Add basic OpenAPI \$ref support. + + For more information see [here](https://github.com/backstage/backstage/tree/master/plugins/catalog-backend-module-openapi). + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/integration@1.2.2-next.1 diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index 1c99618ff8..0b9c24369c 100644 --- a/plugins/catalog-backend-module-openapi/package.json +++ b/plugins/catalog-backend-module-openapi/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-openapi", "description": "A Backstage catalog backend module that helps with OpenAPI specifications", - "version": "0.0.0", + "version": "0.1.0-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,18 +34,18 @@ }, "dependencies": { "@apidevtools/swagger-parser": "^10.1.0", - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/plugin-catalog-backend": "^1.2.1-next.0", + "@backstage/integration": "^1.2.2-next.2", + "@backstage/plugin-catalog-backend": "^1.2.1-next.2", "winston": "^3.2.1", "yaml": "^2.1.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.26-next.0", - "@backstage/cli": "^0.17.3-next.0", - "openapi-types": "^11.0.1" + "@backstage/backend-test-utils": "^0.1.26-next.2", + "@backstage/cli": "^0.18.0-next.2", + "openapi-types": "^12.0.0" }, "files": [ "dist" diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 84f80243fd..a228308681 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-catalog-backend +## 1.2.1-next.2 + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + - @backstage/integration@1.2.2-next.2 + +## 1.2.1-next.1 + +### Patch Changes + +- f1dcc6f3c6: Use entity type predicates from catalog-model +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + - @backstage/plugin-catalog-common@1.0.4-next.0 + - @backstage/plugin-permission-common@0.6.3-next.0 + - @backstage/plugin-permission-node@0.6.3-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + ## 1.2.1-next.0 ### Patch Changes diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 61a8e68412..ebed76ca90 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend", "description": "The Backstage backend plugin that provides the Backstage catalog", - "version": "1.2.1-next.0", + "version": "1.2.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,17 +34,17 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/plugin-catalog-common": "^1.0.3", - "@backstage/plugin-permission-common": "^0.6.2", - "@backstage/plugin-permission-node": "^0.6.3-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.2", + "@backstage/plugin-catalog-common": "^1.0.4-next.0", + "@backstage/plugin-permission-common": "^0.6.3-next.0", + "@backstage/plugin-permission-node": "^0.6.3-next.1", "@backstage/plugin-scaffolder-common": "^1.1.2-next.0", - "@backstage/plugin-search-common": "^0.3.5", + "@backstage/plugin-search-common": "^0.3.6-next.0", "@backstage/types": "^1.0.0", "@types/express": "^4.17.6", "codeowners-utils": "^1.0.2", @@ -53,9 +53,9 @@ "express-promise-router": "^4.1.0", "fast-json-stable-stringify": "^2.1.0", "fs-extra": "10.1.0", - "git-url-parse": "^11.6.0", + "git-url-parse": "^12.0.0", "glob": "^7.1.6", - "knex": "^1.0.2", + "knex": "^2.0.0", "lodash": "^4.17.21", "luxon": "^2.0.2", "node-fetch": "^2.6.7", @@ -68,17 +68,17 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.26-next.0", - "@backstage/cli": "^0.17.3-next.0", - "@backstage/plugin-permission-common": "^0.6.2", - "@backstage/plugin-search-backend-node": "0.6.3-next.0", + "@backstage/backend-test-utils": "^0.1.26-next.2", + "@backstage/cli": "^0.18.0-next.2", + "@backstage/plugin-permission-common": "^0.6.3-next.0", + "@backstage/plugin-search-backend-node": "0.6.3-next.1", "@types/core-js": "^2.5.4", "@types/git-url-parse": "^9.0.0", "@types/lodash": "^4.14.151", "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", "better-sqlite3": "^7.5.0", - "msw": "^0.42.0", + "msw": "^0.43.0", "supertest": "^6.1.3", "wait-for-expect": "^3.0.2", "luxon": "^2.0.2" diff --git a/plugins/catalog-common/CHANGELOG.md b/plugins/catalog-common/CHANGELOG.md index 72002894c4..7fa70e5859 100644 --- a/plugins/catalog-common/CHANGELOG.md +++ b/plugins/catalog-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-catalog-common +## 1.0.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.6.3-next.0 + - @backstage/plugin-search-common@0.3.6-next.0 + ## 1.0.3 ### Patch Changes diff --git a/plugins/catalog-common/package.json b/plugins/catalog-common/package.json index 3adb442c3e..82c0d72855 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": "1.0.3", + "version": "1.0.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,11 +34,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/plugin-permission-common": "^0.6.2", - "@backstage/plugin-search-common": "^0.3.5" + "@backstage/plugin-permission-common": "^0.6.3-next.0", + "@backstage/plugin-search-common": "^0.3.6-next.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0" + "@backstage/cli": "^0.18.0-next.1" }, "files": [ "dist", diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index 5ce0a2d31b..f497b35628 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-catalog-graph +## 0.2.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.2.19-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.2.19-next.0 ### Patch Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 786f284628..c61d388f0b 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.19-next.0", + "version": "0.2.19-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,12 +24,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -45,11 +45,11 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/plugin-catalog": "^1.3.1-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/plugin-catalog": "^1.4.0-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@backstage/types": "^1.0.0", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index 411ae5ec17..81b31ffe51 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -34,7 +34,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/catalog-model": "^1.1.0-next.1", "@backstage/config": "^1.0.1", "@backstage/types": "^1.0.0", "apollo-server": "^3.0.0", @@ -46,14 +46,14 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/cli": "^0.18.0-next.1", + "@backstage/test-utils": "^1.1.2-next.1", "@graphql-codegen/cli": "^2.3.1", "@graphql-codegen/graphql-modules-preset": "^2.3.2", "@graphql-codegen/typescript": "^2.4.2", "@graphql-codegen/typescript-resolvers": "^2.4.3", "@graphql-tools/schema": "^8.3.1", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 1240ab1fc4..7de1bd72d0 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-catalog-import +## 0.8.10-next.2 + +### Patch Changes + +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/integration@1.2.2-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/integration-react@1.1.2-next.2 + +## 0.8.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.8.10-next.0 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 527faad4b3..042e85f792 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.10-next.0", + "version": "0.8.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,20 +34,20 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/integration-react": "^1.1.2-next.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.2", + "@backstage/integration-react": "^1.1.2-next.2", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "@octokit/rest": "^18.5.3", - "git-url-parse": "^11.6.0", + "git-url-parse": "^12.0.0", "js-base64": "^3.6.0", "lodash": "^4.17.21", "react-hook-form": "^7.12.2", @@ -60,17 +60,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index 8b396ca878..0df99a1bb9 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,69 @@ # @backstage/plugin-catalog-react +## 1.1.2-next.2 + +### Patch Changes + +- be26d95141: Added new `EntityProcessingStatusPicker` that will filter for entities with orphans and/or errors. + + If you are using the default Catalog page this picker will be added automatically. For those who have customized their Catalog page you'll need to add this manually by doing something like this: + + ```diff + ... + import { + CatalogFilterLayout, + EntityTypePicker, + UserListPicker, + EntityTagPicker + + EntityProcessingStatusPicker, + } from '@backstage/plugin-catalog-react'; + ... + export const CustomCatalogPage = ({ + columns, + actions, + initiallySelectedFilter = 'owned', + }: CatalogPageProps) => { + return ( + ... + + + + + + ... + }; + ``` + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/integration@1.2.2-next.2 + +## 1.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + - @backstage/plugin-catalog-common@1.0.4-next.0 + - @backstage/plugin-permission-common@0.6.3-next.0 + - @backstage/plugin-permission-react@0.4.3-next.0 + ## 1.1.2-next.0 ### Patch Changes diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md index 285ecafd70..5232c49150 100644 --- a/plugins/catalog-react/api-report.md +++ b/plugins/catalog-react/api-report.md @@ -78,6 +78,7 @@ export type CatalogReactComponentsNameToClassKey = { CatalogReactEntitySearchBar: CatalogReactEntitySearchBarClassKey; CatalogReactEntityTagPicker: CatalogReactEntityTagPickerClassKey; CatalogReactEntityOwnerPicker: CatalogReactEntityOwnerPickerClassKey; + CatalogReactEntityProcessingStatusPicker: CatalogReactEntityProcessingStatusPickerClassKey; }; // @public (undocumented) @@ -86,6 +87,9 @@ export type CatalogReactEntityLifecyclePickerClassKey = 'input'; // @public (undocumented) export type CatalogReactEntityOwnerPickerClassKey = 'input'; +// @public (undocumented) +export type CatalogReactEntityProcessingStatusPickerClassKey = 'input'; + // @public (undocumented) export type CatalogReactEntitySearchBarClassKey = 'searchToolbar' | 'input'; @@ -137,8 +141,19 @@ export type DefaultEntityFilters = { lifecycles?: EntityLifecycleFilter; tags?: EntityTagFilter; text?: EntityTextFilter; + orphan?: EntityOrphanFilter; + error?: EntityErrorFilter; }; +// @public +export class EntityErrorFilter implements EntityFilter { + constructor(value: boolean); + // (undocumented) + filterEntity(entity: Entity): boolean; + // (undocumented) + readonly value: boolean; +} + // @public (undocumented) export type EntityFilter = { getCatalogFilters?: () => Record< @@ -222,6 +237,15 @@ export type EntityLoadingStatus = { refresh?: VoidFunction; }; +// @public +export class EntityOrphanFilter implements EntityFilter { + constructor(value: boolean); + // (undocumented) + filterEntity(entity: Entity): boolean; + // (undocumented) + readonly value: boolean; +} + // @public export class EntityOwnerFilter implements EntityFilter { constructor(values: string[]); @@ -236,6 +260,9 @@ export class EntityOwnerFilter implements EntityFilter { // @public (undocumented) export const EntityOwnerPicker: () => JSX.Element | null; +// @public (undocumented) +export const EntityProcessingStatusPicker: () => JSX.Element; + // @public export const EntityProvider: (props: EntityProviderProps) => JSX.Element; diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index a525a0af50..3f3ee5f402 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-react", "description": "A frontend library that helps other Backstage plugins interact with the catalog", - "version": "1.1.2-next.0", + "version": "1.1.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,16 +34,16 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/plugin-catalog-common": "^1.0.3", - "@backstage/plugin-permission-common": "^0.6.2", - "@backstage/plugin-permission-react": "^0.4.2", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.2", + "@backstage/plugin-catalog-common": "^1.0.4-next.0", + "@backstage/plugin-permission-common": "^0.6.3-next.0", + "@backstage/plugin-permission-react": "^0.4.3-next.0", + "@backstage/theme": "^0.2.16-next.1", "@backstage/types": "^1.0.0", "@backstage/version-bridge": "^1.0.1", "@material-ui/core": "^4.12.2", @@ -63,11 +63,11 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/plugin-catalog-common": "^1.0.3", + "@backstage/plugin-catalog-common": "^1.0.4-next.0", "@backstage/plugin-scaffolder-common": "^1.1.2-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.test.tsx b/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.test.tsx new file mode 100644 index 0000000000..8e90e04148 --- /dev/null +++ b/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.test.tsx @@ -0,0 +1,152 @@ +/* + * 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 { Entity } from '@backstage/catalog-model'; +import { fireEvent, render } from '@testing-library/react'; +import React from 'react'; +import { EntityErrorFilter, EntityOrphanFilter } from '../../filters'; +import { MockEntityListContextProvider } from '../../testUtils/providers'; +import { EntityProcessingStatusPicker } from './EntityProcessingStatusPicker'; + +const orphanAnnotation: Record = {}; +orphanAnnotation['backstage.io/orphan'] = 'true'; + +const sampleEntities: Entity[] = [ + { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'valid-component', + }, + }, + { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'orphan-component', + annotations: orphanAnnotation, + }, + }, + { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'error-component', + tags: ['Invalid Tag'], + }, + }, +]; + +describe('', () => { + it('renders all processing status options', () => { + const rendered = render( + + + , + ); + expect(rendered.getByText('Processing Status')).toBeInTheDocument(); + + fireEvent.click(rendered.getByTestId('processing-status-picker-expand')); + expect(rendered.getByText('Is Orphan')).toBeInTheDocument(); + expect(rendered.getByText('Has Error')).toBeInTheDocument(); + }); + + it('adds orphan to orphan filter', () => { + const updateFilters = jest.fn(); + const rendered = render( + + + , + ); + + fireEvent.click(rendered.getByTestId('processing-status-picker-expand')); + fireEvent.click(rendered.getByText('Is Orphan')); + expect(updateFilters).toHaveBeenCalledWith({ + orphan: new EntityOrphanFilter(true), + }); + }); + + it('adds error to error filter', () => { + const updateFilters = jest.fn(); + const rendered = render( + + + , + ); + + fireEvent.click(rendered.getByTestId('processing-status-picker-expand')); + fireEvent.click(rendered.getByText('Has Error')); + expect(updateFilters).toHaveBeenCalledWith({ + error: new EntityErrorFilter(true), + }); + }); + + it('remove orphan from orphan filter', () => { + const updateFilters = jest.fn(); + const rendered = render( + + + , + ); + + fireEvent.click(rendered.getByTestId('processing-status-picker-expand')); + fireEvent.click(rendered.getByText('Is Orphan')); + expect(updateFilters).toHaveBeenCalledWith({ + orphan: undefined, + }); + }); + + it('remove error from error filter', () => { + const updateFilters = jest.fn(); + const rendered = render( + + + , + ); + + fireEvent.click(rendered.getByTestId('processing-status-picker-expand')); + fireEvent.click(rendered.getByText('Has Error')); + expect(updateFilters).toHaveBeenCalledWith({ + error: undefined, + }); + }); +}); diff --git a/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.tsx b/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.tsx new file mode 100644 index 0000000000..3fe3b60e25 --- /dev/null +++ b/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.tsx @@ -0,0 +1,111 @@ +/* + * 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 { EntityErrorFilter, EntityOrphanFilter } from '../../filters'; +import { + Box, + Checkbox, + FormControlLabel, + makeStyles, + TextField, + Typography, +} from '@material-ui/core'; +import CheckBoxIcon from '@material-ui/icons/CheckBox'; +import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import React, { useState } from 'react'; +import { useEntityList } from '../../hooks'; +import { Autocomplete } from '@material-ui/lab'; + +/** @public */ +export type CatalogReactEntityProcessingStatusPickerClassKey = 'input'; + +const useStyles = makeStyles( + { + input: {}, + }, + { + name: 'CatalogReactEntityProcessingStatusPickerPicker', + }, +); + +const icon = ; +const checkedIcon = ; + +/** @public */ +export const EntityProcessingStatusPicker = () => { + const classes = useStyles(); + const { updateFilters } = useEntityList(); + + const [selectedAdvancedItems, setSelectedAdvancedItems] = useState( + [], + ); + + function orphanChange(value: boolean) { + updateFilters({ + orphan: value ? new EntityOrphanFilter(value) : undefined, + }); + } + + function errorChange(value: boolean) { + updateFilters({ + error: value ? new EntityErrorFilter(value) : undefined, + }); + } + + const availableAdvancedItems = ['Is Orphan', 'Has Error']; + + return ( + + + Processing Status + { + setSelectedAdvancedItems(value); + orphanChange(value.includes('Is Orphan')); + errorChange(value.includes('Has Error')); + }} + renderOption={(option, { selected }) => ( + + } + label={option} + /> + )} + size="small" + popupIcon={ + + } + renderInput={params => ( + + )} + /> + + + ); +}; diff --git a/plugins/catalog-react/src/components/EntityProcessingStatusPicker/index.ts b/plugins/catalog-react/src/components/EntityProcessingStatusPicker/index.ts new file mode 100644 index 0000000000..55daeaecc0 --- /dev/null +++ b/plugins/catalog-react/src/components/EntityProcessingStatusPicker/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { EntityProcessingStatusPicker as EntityProcessingStatusPicker } from './EntityProcessingStatusPicker'; +export type { CatalogReactEntityProcessingStatusPickerClassKey } from './EntityProcessingStatusPicker'; diff --git a/plugins/catalog-react/src/components/index.ts b/plugins/catalog-react/src/components/index.ts index 7a26a72bf9..c604306ead 100644 --- a/plugins/catalog-react/src/components/index.ts +++ b/plugins/catalog-react/src/components/index.ts @@ -27,3 +27,4 @@ export * from './FavoriteEntity'; export * from './InspectEntityDialog'; export * from './UnregisterEntityDialog'; export * from './UserListPicker'; +export * from './EntityProcessingStatusPicker'; diff --git a/plugins/catalog-react/src/filters.test.ts b/plugins/catalog-react/src/filters.test.ts index ba31e21122..c2c92e033e 100644 --- a/plugins/catalog-react/src/filters.test.ts +++ b/plugins/catalog-react/src/filters.test.ts @@ -14,9 +14,13 @@ * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; +import { AlphaEntity, Entity } from '@backstage/catalog-model'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; -import { EntityTextFilter } from './filters'; +import { + EntityErrorFilter, + EntityOrphanFilter, + EntityTextFilter, +} from './filters'; const entities: Entity[] = [ { @@ -91,3 +95,50 @@ describe('EntityTextFilter', () => { expect(filter.filterEntity(entities[1])).toBeTruthy(); }); }); + +describe('EntityOrphanFilter', () => { + const orphanAnnotation: Record = {}; + orphanAnnotation['backstage.io/orphan'] = 'true'; + + const orphan: Entity = { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'orphaned-service', + annotations: orphanAnnotation, + }, + }; + + it('should find orphans', () => { + const filter = new EntityOrphanFilter(true); + expect(filter.filterEntity(orphan)).toBeTruthy(); + expect(filter.filterEntity(entities[1])).toBeFalsy(); + }); +}); + +describe('EntityErrorFilter', () => { + const error: AlphaEntity = { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'service-with-error', + tags: ['Invalid Tag'], + }, + status: { + items: [ + { + type: 'invalid-tag', + level: 'error', + message: 'Tag is not valid', + error: undefined, + }, + ], + }, + }; + + it('should find errors', () => { + const filter = new EntityErrorFilter(true); + expect(filter.filterEntity(error)).toBeTruthy(); + expect(filter.filterEntity(entities[1])).toBeFalsy(); + }); +}); diff --git a/plugins/catalog-react/src/filters.ts b/plugins/catalog-react/src/filters.ts index 9fb057a01c..a828015f0e 100644 --- a/plugins/catalog-react/src/filters.ts +++ b/plugins/catalog-react/src/filters.ts @@ -14,7 +14,11 @@ * limitations under the License. */ -import { Entity, RELATION_OWNED_BY } from '@backstage/catalog-model'; +import { + AlphaEntity, + Entity, + RELATION_OWNED_BY, +} from '@backstage/catalog-model'; import { humanizeEntityRef } from './components/EntityRefLink'; import { EntityFilter, UserListFilterKind } from './types'; import { getEntityRelations } from './utils'; @@ -159,3 +163,28 @@ export class UserListFilter implements EntityFilter { return this.value; } } + +/** + * Filters entities based if it is an orphan or not. + * @public + */ +export class EntityOrphanFilter implements EntityFilter { + constructor(readonly value: boolean) {} + filterEntity(entity: Entity): boolean { + const orphan = entity.metadata.annotations?.['backstage.io/orphan']; + return orphan !== undefined && this.value.toString() === orphan; + } +} + +/** + * Filters entities based on if it has errors or not. + * @public + */ +export class EntityErrorFilter implements EntityFilter { + constructor(readonly value: boolean) {} + filterEntity(entity: Entity): boolean { + const error = + ((entity as AlphaEntity)?.status?.items?.length as number) > 0; + return error !== undefined && this.value === error; + } +} diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx index ccac475ae8..089701d8b4 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx @@ -31,8 +31,10 @@ import useDebounce from 'react-use/lib/useDebounce'; import useMountedState from 'react-use/lib/useMountedState'; import { catalogApiRef } from '../api'; import { + EntityErrorFilter, EntityKindFilter, EntityLifecycleFilter, + EntityOrphanFilter, EntityOwnerFilter, EntityTagFilter, EntityTextFilter, @@ -52,6 +54,8 @@ export type DefaultEntityFilters = { lifecycles?: EntityLifecycleFilter; tags?: EntityTagFilter; text?: EntityTextFilter; + orphan?: EntityOrphanFilter; + error?: EntityErrorFilter; }; /** @public */ diff --git a/plugins/catalog-react/src/overridableComponents.ts b/plugins/catalog-react/src/overridableComponents.ts index 1e654988e4..c3b392fcfe 100644 --- a/plugins/catalog-react/src/overridableComponents.ts +++ b/plugins/catalog-react/src/overridableComponents.ts @@ -22,6 +22,7 @@ import { CatalogReactEntitySearchBarClassKey, CatalogReactEntityTagPickerClassKey, CatalogReactEntityOwnerPickerClassKey, + CatalogReactEntityProcessingStatusPickerClassKey, } from './components'; /** @public */ @@ -31,6 +32,7 @@ export type CatalogReactComponentsNameToClassKey = { CatalogReactEntitySearchBar: CatalogReactEntitySearchBarClassKey; CatalogReactEntityTagPicker: CatalogReactEntityTagPickerClassKey; CatalogReactEntityOwnerPicker: CatalogReactEntityOwnerPickerClassKey; + CatalogReactEntityProcessingStatusPicker: CatalogReactEntityProcessingStatusPickerClassKey; }; /** @public */ diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index cc64ccd3ee..5e00cd2661 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,82 @@ # @backstage/plugin-catalog +## 1.4.0-next.2 + +### Minor Changes + +- a274fe38b9: Add hidden title column to catalog and API table to enable filtering by title. + +### Patch Changes + +- 258057a4b9: Adding ability to customize the "unregister entity" menu item in the entity context menu on the entity page with options 'visible','hidden','disabled'.With this three new options, one can hide the "unregister entity" menu item from the list, disable or keep it enabled. + + The boolean input for "unregister entity" will be deprecated later in favour of the above three options. + +- 385389d23c: Updated to remove usage of the `bursts` object in the theme palette +- be26d95141: Added new `EntityProcessingStatusPicker` that will filter for entities with orphans and/or errors. + + If you are using the default Catalog page this picker will be added automatically. For those who have customized their Catalog page you'll need to add this manually by doing something like this: + + ```diff + ... + import { + CatalogFilterLayout, + EntityTypePicker, + UserListPicker, + EntityTagPicker + + EntityProcessingStatusPicker, + } from '@backstage/plugin-catalog-react'; + ... + export const CustomCatalogPage = ({ + columns, + actions, + initiallySelectedFilter = 'owned', + }: CatalogPageProps) => { + return ( + ... + + + + + + ... + }; + ``` + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/plugin-search-react@0.2.2-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/integration-react@1.1.2-next.2 + +## 1.3.1-next.1 + +### Patch Changes + +- f1dcc6f3c6: Use entity type predicates from catalog-model +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/plugin-catalog-common@1.0.4-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + - @backstage/plugin-search-react@0.2.2-next.1 + ## 1.3.1-next.0 ### Patch Changes diff --git a/plugins/catalog/api-report.md b/plugins/catalog/api-report.md index 0d2d611412..bfdf62bdb0 100644 --- a/plugins/catalog/api-report.md +++ b/plugins/catalog/api-report.md @@ -136,6 +136,13 @@ export const CatalogTable: { createSpecLifecycleColumn(): TableColumn; createMetadataDescriptionColumn(): TableColumn; createTagsColumn(): TableColumn; + createTitleColumn( + options?: + | { + hidden?: boolean | undefined; + } + | undefined, + ): TableColumn; }>; }; @@ -259,10 +266,10 @@ export interface EntityLayoutProps { children?: React_2.ReactNode; // (undocumented) NotFoundComponent?: React_2.ReactNode; - // Warning: (ae-forgotten-export) The symbol "contextMenuOptions" needs to be exported by the entry point index.d.ts + // Warning: (ae-forgotten-export) The symbol "EntityContextMenuOptions" needs to be exported by the entry point index.d.ts // // (undocumented) - UNSTABLE_contextMenuOptions?: contextMenuOptions; + UNSTABLE_contextMenuOptions?: EntityContextMenuOptions; // Warning: (ae-forgotten-export) The symbol "ExtraContextMenuItem" needs to be exported by the entry point index.d.ts // // (undocumented) diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 786083356a..a294e64d29 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog", "description": "The Backstage plugin for browsing the Backstage catalog", - "version": "1.3.1-next.0", + "version": "1.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,17 +34,17 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/integration-react": "^1.1.2-next.0", - "@backstage/plugin-catalog-common": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/plugin-search-common": "^0.3.5", - "@backstage/plugin-search-react": "^0.2.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration-react": "^1.1.2-next.2", + "@backstage/plugin-catalog-common": "^1.0.4-next.0", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/plugin-search-common": "^0.3.6-next.0", + "@backstage/plugin-search-react": "^0.2.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@backstage/types": "^1.0.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -61,11 +61,11 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/plugin-permission-react": "^0.4.2", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/plugin-permission-react": "^0.4.3-next.0", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx index 5250dcec0d..51ef12ac74 100644 --- a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx @@ -28,6 +28,7 @@ import { CatalogFilterLayout, EntityLifecyclePicker, EntityListProvider, + EntityProcessingStatusPicker, EntityOwnerPicker, EntityTagPicker, EntityTypePicker, @@ -84,6 +85,7 @@ export function DefaultCatalogPage(props: DefaultCatalogPageProps) { + { const defaultColumns: TableColumn[] = useMemo(() => { return [ + columnFactories.createTitleColumn({ hidden: true }), columnFactories.createNameColumn({ defaultKind: filters.kind?.value }), ...createEntitySpecificColumns(), columnFactories.createMetadataDescriptionColumn(), diff --git a/plugins/catalog/src/components/CatalogTable/columns.tsx b/plugins/catalog/src/components/CatalogTable/columns.tsx index 0fb91d4f3f..d8b52e276e 100644 --- a/plugins/catalog/src/components/CatalogTable/columns.tsx +++ b/plugins/catalog/src/components/CatalogTable/columns.tsx @@ -131,4 +131,14 @@ export const columnFactories = Object.freeze({ ), }; }, + createTitleColumn(options?: { + hidden?: boolean; + }): TableColumn { + return { + title: 'Title', + field: 'entity.metadata.title', + hidden: options?.hidden, + searchable: true, + }; + }, }); diff --git a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx index eb920aaa20..0e981bb1fc 100644 --- a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx +++ b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx @@ -42,7 +42,6 @@ function render(children: React.ReactNode) { describe('ComponentContextMenu', () => { it('should call onUnregisterEntity on button click', async () => { const mockCallback = jest.fn(); - await render( { expect(mockCallback).toBeCalled(); }); + it('check Unregister entity button is disabled', async () => { + const mockCallback = jest.fn(); + + const { getByText } = await render( + {}} + />, + ); + + const button = await screen.findByTestId('menu-button'); + expect(button).toBeInTheDocument(); + fireEvent.click(button); + + const unregister = await screen.getByText('Unregister entity'); + expect(unregister).toBeInTheDocument(); + + const unregisterSpanItem = getByText(/Unregister entity/); + const unregisterMenuListItem = + unregisterSpanItem?.parentElement?.parentElement; + expect(unregisterMenuListItem).toHaveAttribute('aria-disabled'); + }); + it('should call onInspectEntity on button click', async () => { const mockCallback = jest.fn(); diff --git a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx index db50eeab84..41610ed13c 100644 --- a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx +++ b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx @@ -24,7 +24,6 @@ import { Popover, } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; -import CancelIcon from '@material-ui/icons/Cancel'; import BugReportIcon from '@material-ui/icons/BugReport'; import MoreVert from '@material-ui/icons/MoreVert'; import React, { useState } from 'react'; @@ -32,6 +31,7 @@ import { IconComponent } from '@backstage/core-plugin-api'; import { useEntityPermission } from '@backstage/plugin-catalog-react'; import { catalogEntityDeletePermission } from '@backstage/plugin-catalog-common'; import { BackstageTheme } from '@backstage/theme'; +import { UnregisterEntity, UnregisterEntityOptions } from './UnregisterEntity'; /** @public */ export type EntityContextMenuClassKey = 'button'; @@ -40,7 +40,7 @@ const useStyles = makeStyles( (theme: BackstageTheme) => { return { button: { - color: theme.palette.bursts.fontColor, + color: theme.page.fontColor, }, }; }, @@ -55,14 +55,9 @@ interface ExtraContextMenuItem { onClick: () => void; } -// unstable context menu option, eg: disable the unregister entity menu -interface contextMenuOptions { - disableUnregister: boolean; -} - interface EntityContextMenuProps { UNSTABLE_extraContextMenuItems?: ExtraContextMenuItem[]; - UNSTABLE_contextMenuOptions?: contextMenuOptions; + UNSTABLE_contextMenuOptions?: UnregisterEntityOptions; onUnregisterEntity: () => void; onInspectEntity: () => void; } @@ -79,6 +74,7 @@ export function EntityContextMenu(props: EntityContextMenuProps) { const unregisterPermission = useEntityPermission( catalogEntityDeletePermission, ); + const isAllowed = unregisterPermission.allowed; const onOpen = (event: React.SyntheticEvent) => { setAnchorEl(event.currentTarget); @@ -106,11 +102,6 @@ export function EntityContextMenu(props: EntityContextMenuProps) { , ]; - const disableUnregister = - (!unregisterPermission.allowed || - UNSTABLE_contextMenuOptions?.disableUnregister) ?? - false; - return ( <> {extraItems} - { - onClose(); - onUnregisterEntity(); - }} - disabled={disableUnregister} - > - - - - - + { onClose(); diff --git a/plugins/catalog/src/components/EntityContextMenu/UnregisterEntity.test.tsx b/plugins/catalog/src/components/EntityContextMenu/UnregisterEntity.test.tsx new file mode 100644 index 0000000000..70b75c7bae --- /dev/null +++ b/plugins/catalog/src/components/EntityContextMenu/UnregisterEntity.test.tsx @@ -0,0 +1,80 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { EntityProvider } from '@backstage/plugin-catalog-react'; +import { permissionApiRef } from '@backstage/plugin-permission-react'; +import { + MockPermissionApi, + renderInTestApp, + TestApiProvider, +} from '@backstage/test-utils'; +import { fireEvent, screen } from '@testing-library/react'; +import * as React from 'react'; +import { UnregisterEntity } from './UnregisterEntity'; + +const mockPermissionApi = new MockPermissionApi(); + +function render(children: React.ReactNode) { + return renderInTestApp( + + + , + ); +} + +describe('ComponentContextMenu', () => { + it('should call onUnregisterEntity on button click', async () => { + const mockCallback = jest.fn(); + await render( + {}} + />, + ); + + const unregister = await screen.findByText('Unregister entity'); + expect(unregister).toBeInTheDocument(); + fireEvent.click(unregister); + + expect(mockCallback).toBeCalled(); + }); + + it('check Unregister entity button is disabled', async () => { + const mockCallback = jest.fn(); + + const { getByText } = await render( + {}} + />, + ); + + const unregister = await screen.getByText('Unregister entity'); + expect(unregister).toBeInTheDocument(); + + const unregisterSpanItem = getByText(/Unregister entity/); + const unregisterMenuListItem = + unregisterSpanItem?.parentElement?.parentElement; + expect(unregisterMenuListItem).toHaveAttribute('aria-disabled'); + }); +}); diff --git a/plugins/catalog/src/components/EntityContextMenu/UnregisterEntity.tsx b/plugins/catalog/src/components/EntityContextMenu/UnregisterEntity.tsx new file mode 100644 index 0000000000..05044bf935 --- /dev/null +++ b/plugins/catalog/src/components/EntityContextMenu/UnregisterEntity.tsx @@ -0,0 +1,72 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { ListItemIcon, ListItemText, MenuItem } from '@material-ui/core'; +import CancelIcon from '@material-ui/icons/Cancel'; + +type VisibleType = 'visible' | 'hidden' | 'disable'; + +export type UnregisterEntityOptions = { + disableUnregister: boolean | VisibleType; +}; + +interface UnregisterEntityProps { + unregisterEntityOptions?: UnregisterEntityOptions; + isUnregisterAllowed: boolean; + onUnregisterEntity: () => void; + onClose: () => void; +} + +export function UnregisterEntity(props: UnregisterEntityProps) { + const { + unregisterEntityOptions, + isUnregisterAllowed, + onUnregisterEntity, + onClose, + } = props; + + const isBoolean = + typeof unregisterEntityOptions?.disableUnregister === 'boolean'; + + const isDisabled = + (!isUnregisterAllowed || + (isBoolean + ? !!unregisterEntityOptions?.disableUnregister + : unregisterEntityOptions?.disableUnregister === 'disable')) ?? + false; + + let unregisterButton = <>; + + if (unregisterEntityOptions?.disableUnregister !== 'hidden') { + unregisterButton = ( + { + onClose(); + onUnregisterEntity(); + }} + disabled={isDisabled} + > + + + + + + ); + } + + return <>{unregisterButton}; +} diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx index 693137fe21..2295034905 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx @@ -142,15 +142,18 @@ interface ExtraContextMenuItem { onClick: () => void; } +type VisibleType = 'visible' | 'hidden' | 'disable'; + +// NOTE(blam): Intentionally not exported at this point, since it's part of // unstable context menu option, eg: disable the unregister entity menu -interface contextMenuOptions { - disableUnregister: boolean; +interface EntityContextMenuOptions { + disableUnregister: boolean | VisibleType; } /** @public */ export interface EntityLayoutProps { UNSTABLE_extraContextMenuItems?: ExtraContextMenuItem[]; - UNSTABLE_contextMenuOptions?: contextMenuOptions; + UNSTABLE_contextMenuOptions?: EntityContextMenuOptions; children?: React.ReactNode; NotFoundComponent?: React.ReactNode; } diff --git a/plugins/cicd-statistics-module-gitlab/package.json b/plugins/cicd-statistics-module-gitlab/package.json index 3f6d9d6731..749c77d1c5 100644 --- a/plugins/cicd-statistics-module-gitlab/package.json +++ b/plugins/cicd-statistics-module-gitlab/package.json @@ -35,10 +35,10 @@ "luxon": "^2.0.2", "p-limit": "^4.0.0", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/catalog-model": "^1.1.0-next.0" + "@backstage/catalog-model": "^1.1.0-next.1" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0" + "@backstage/cli": "^0.18.0-next.1" }, "files": [ "dist" diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md index 1c1b551102..4df5655c52 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-circleci +## 0.3.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.3.7-next.0 ### Patch Changes diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 789c6f5668..c17569db13 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-circleci", "description": "A Backstage plugin that integrates towards Circle CI", - "version": "0.3.7-next.0", + "version": "0.3.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,11 +35,11 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -55,10 +55,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", @@ -66,7 +66,7 @@ "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md index d31721fee7..94b16aafdd 100644 --- a/plugins/cloudbuild/CHANGELOG.md +++ b/plugins/cloudbuild/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-cloudbuild +## 0.3.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.3.7-next.0 ### Patch Changes diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index b95a6253cc..2348693d58 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cloudbuild", "description": "A Backstage plugin that integrates towards Google Cloud Build", - "version": "0.3.7-next.0", + "version": "0.3.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,11 +34,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -52,17 +52,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/code-climate/CHANGELOG.md b/plugins/code-climate/CHANGELOG.md index 407aacb6e2..cd2e824758 100644 --- a/plugins/code-climate/CHANGELOG.md +++ b/plugins/code-climate/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-code-climate +## 0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.1.7-next.0 ### Patch Changes diff --git a/plugins/code-climate/package.json b/plugins/code-climate/package.json index 2bb8e7aaf2..40c0861f17 100644 --- a/plugins/code-climate/package.json +++ b/plugins/code-climate/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-code-climate", - "version": "0.1.7-next.0", + "version": "0.1.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,11 +23,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -40,9 +40,9 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/cli": "^0.18.0-next.2", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", @@ -51,7 +51,7 @@ "@types/luxon": "^2.0.9", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/code-coverage-backend/CHANGELOG.md b/plugins/code-coverage-backend/CHANGELOG.md index b354cd364a..6fccd225cb 100644 --- a/plugins/code-coverage-backend/CHANGELOG.md +++ b/plugins/code-coverage-backend/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-code-coverage-backend +## 0.1.32-next.2 + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + - @backstage/integration@1.2.2-next.2 + +## 0.1.32-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + ## 0.1.32-next.0 ### Patch Changes diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index 78b57974b9..017b96122e 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.32-next.0", + "version": "0.1.32-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,26 +23,26 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.2", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", "express-xml-bodyparser": "^0.3.0", - "knex": "^1.0.2", + "knex": "^2.0.0", "uuid": "^8.3.2", "winston": "^3.2.1", "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@types/express-xml-bodyparser": "^0.3.2", "@types/supertest": "^2.0.8", - "msw": "^0.42.0", + "msw": "^0.43.0", "supertest": "^6.1.6", "xml2js": "^0.4.23" }, diff --git a/plugins/code-coverage/CHANGELOG.md b/plugins/code-coverage/CHANGELOG.md index 90fef2528b..b2b64aa993 100644 --- a/plugins/code-coverage/CHANGELOG.md +++ b/plugins/code-coverage/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-code-coverage +## 0.1.34-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.1.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.1.34-next.0 ### Patch Changes diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 793fc61ee0..68cd7d7990 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.34-next.0", + "version": "0.1.34-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,13 +24,13 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -46,10 +46,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", @@ -58,7 +58,7 @@ "@types/node": "^16.11.26", "@types/recharts": "^1.8.15", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/codescene/CHANGELOG.md b/plugins/codescene/CHANGELOG.md index 17a14cd3a9..e3f98725c3 100644 --- a/plugins/codescene/CHANGELOG.md +++ b/plugins/codescene/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-codescene +## 0.1.2-next.2 + +### Patch Changes + +- 15201b1032: Updated dependency `rc-progress` to `3.4.0`. +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + ## 0.1.2-next.0 ### Patch Changes diff --git a/plugins/codescene/package.json b/plugins/codescene/package.json index 41190404cb..85f7096f69 100644 --- a/plugins/codescene/package.json +++ b/plugins/codescene/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-codescene", - "version": "0.1.2-next.0", + "version": "0.1.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,14 +23,14 @@ }, "dependencies": { "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.9.10", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "^4.0.0-alpha.57", - "rc-progress": "3.3.3", + "rc-progress": "3.4.0", "react-router-dom": "6.0.0-beta.0", "react-use": "^17.2.4" }, @@ -38,16 +38,16 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "*", "@types/node": "*", - "msw": "^0.42.0", + "msw": "^0.43.0", "cross-fetch": "^3.1.5" }, "files": [ diff --git a/plugins/config-schema/CHANGELOG.md b/plugins/config-schema/CHANGELOG.md index 3943ec30c5..b6a43ed858 100644 --- a/plugins/config-schema/CHANGELOG.md +++ b/plugins/config-schema/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-config-schema +## 0.1.30-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## 0.1.30-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + ## 0.1.30-next.0 ### Patch Changes diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index d806bf6d70..c33e7adac3 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.30-next.0", + "version": "0.1.30-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -25,10 +25,10 @@ }, "dependencies": { "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/theme": "^0.2.16-next.1", "@backstage/types": "^1.0.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -41,17 +41,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/cost-insights-common/.eslintrc.js b/plugins/cost-insights-common/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/cost-insights-common/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/cost-insights-common/CHANGELOG.md b/plugins/cost-insights-common/CHANGELOG.md new file mode 100644 index 0000000000..0a55b342fc --- /dev/null +++ b/plugins/cost-insights-common/CHANGELOG.md @@ -0,0 +1,7 @@ +# @backstage/plugin-cost-insights-common + +## 0.1.0-next.0 + +### Minor Changes + +- 81dd5ea989: Introduces a new isomorphic @backstage/plugin-cost-insight-common package to contain shared types across all other cost insights packages and modules. diff --git a/plugins/cost-insights-common/README.md b/plugins/cost-insights-common/README.md new file mode 100644 index 0000000000..5140701987 --- /dev/null +++ b/plugins/cost-insights-common/README.md @@ -0,0 +1,8 @@ +# Cost Insights Common + +Shared isomorphic code for the cost-insights plugin. + +## Links + +- [Frontend part of the plugin](https://github.com/backstage/backstage/tree/master/plugins/cost-insights) +- [The Backstage homepage](https://backstage.io) diff --git a/plugins/cost-insights-common/api-report.md b/plugins/cost-insights-common/api-report.md new file mode 100644 index 0000000000..a5f7045854 --- /dev/null +++ b/plugins/cost-insights-common/api-report.md @@ -0,0 +1,92 @@ +## API Report File for "@backstage/plugin-cost-insights-common" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +// @public (undocumented) +export interface ChangeStatistic { + amount: number; + ratio?: number; +} + +// @public (undocumented) +export interface Cost { + // (undocumented) + aggregation: DateAggregation[]; + // (undocumented) + change?: ChangeStatistic; + // (undocumented) + groupedCosts?: Record; + // (undocumented) + id: string; + // (undocumented) + trendline?: Trendline; +} + +// @public (undocumented) +export type DateAggregation = { + date: string; + amount: number; +}; + +// @public +export interface Entity { + // (undocumented) + aggregation: [number, number]; + // (undocumented) + change: ChangeStatistic; + // (undocumented) + entities: Record; + // (undocumented) + id: Maybe; +} + +// @public (undocumented) +export type Group = { + id: string; +}; + +// @public (undocumented) +export type Maybe = T | null; + +// @public (undocumented) +export type Metric = { + kind: string; + name: string; + default: boolean; +}; + +// @public (undocumented) +export interface MetricData { + // (undocumented) + aggregation: DateAggregation[]; + // (undocumented) + change: ChangeStatistic; + // (undocumented) + format: 'number' | 'currency'; + // (undocumented) + id: string; +} + +// @public (undocumented) +export interface Product { + // (undocumented) + kind: string; + // (undocumented) + name: string; +} + +// @public (undocumented) +export interface Project { + // (undocumented) + id: string; + // (undocumented) + name?: string; +} + +// @public (undocumented) +export type Trendline = { + slope: number; + intercept: number; +}; +``` diff --git a/plugins/cost-insights-common/package.json b/plugins/cost-insights-common/package.json new file mode 100644 index 0000000000..2918462e09 --- /dev/null +++ b/plugins/cost-insights-common/package.json @@ -0,0 +1,42 @@ +{ + "name": "@backstage/plugin-cost-insights-common", + "description": "Common functionalities for the cost-insights plugin", + "version": "0.1.0-next.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "private": false, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "module": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "common-library" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/cost-insights-common" + }, + "keywords": [ + "backstage" + ], + "scripts": { + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" + }, + "dependencies": {}, + "devDependencies": { + "@backstage/cli": "^0.18.0-next.2" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/cost-insights-common/src/index.ts b/plugins/cost-insights-common/src/index.ts new file mode 100644 index 0000000000..c3c76ccf17 --- /dev/null +++ b/plugins/cost-insights-common/src/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Provides shared objects useful for interacting with the cost-insights plugin. + * + * @packageDocumentation + */ + +export * from './types'; diff --git a/plugins/cost-insights-common/src/setupTests.ts b/plugins/cost-insights-common/src/setupTests.ts new file mode 100644 index 0000000000..813cdeaae3 --- /dev/null +++ b/plugins/cost-insights-common/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export {}; diff --git a/plugins/cost-insights-common/src/types/ChangeStatistic.ts b/plugins/cost-insights-common/src/types/ChangeStatistic.ts new file mode 100644 index 0000000000..8d64fb47f9 --- /dev/null +++ b/plugins/cost-insights-common/src/types/ChangeStatistic.ts @@ -0,0 +1,32 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @public + */ +export interface ChangeStatistic { + /** + * The ratio of change from one duration to another, expressed as: (newSum - oldSum) / oldSum + * If a ratio cannot be calculated - such as when a new or old sum is zero, + * the ratio can be omitted and where applicable, ∞ or -∞ will display based on amount. + */ + ratio?: number; + + /** + * The actual USD change between time periods (can be negative if costs decreased) + */ + amount: number; +} diff --git a/plugins/cost-insights/src/types/Cost.ts b/plugins/cost-insights-common/src/types/Cost.ts similarity index 97% rename from plugins/cost-insights/src/types/Cost.ts rename to plugins/cost-insights-common/src/types/Cost.ts index 2ae4755bc7..90ccbe17c0 100644 --- a/plugins/cost-insights/src/types/Cost.ts +++ b/plugins/cost-insights-common/src/types/Cost.ts @@ -18,6 +18,9 @@ import { DateAggregation } from './DateAggregation'; import { ChangeStatistic } from './ChangeStatistic'; import { Trendline } from './Trendline'; +/** + * @public + */ export interface Cost { id: string; aggregation: DateAggregation[]; diff --git a/plugins/cost-insights/src/types/DateAggregation.ts b/plugins/cost-insights-common/src/types/DateAggregation.ts similarity index 85% rename from plugins/cost-insights/src/types/DateAggregation.ts rename to plugins/cost-insights-common/src/types/DateAggregation.ts index 72a2514006..edc867a7bf 100644 --- a/plugins/cost-insights/src/types/DateAggregation.ts +++ b/plugins/cost-insights-common/src/types/DateAggregation.ts @@ -14,7 +14,15 @@ * limitations under the License. */ +/** + * @public + */ export type DateAggregation = { - date: string; // YYYY-MM-DD + /** + * The date aggregation as string. + * @example YYYY-MM-DD + */ + date: string; + amount: number; }; diff --git a/plugins/cost-insights-common/src/types/Entity.ts b/plugins/cost-insights-common/src/types/Entity.ts new file mode 100644 index 0000000000..9a6d6746aa --- /dev/null +++ b/plugins/cost-insights-common/src/types/Entity.ts @@ -0,0 +1,124 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeStatistic } from './ChangeStatistic'; +import { Maybe } from './Maybe'; + +/** + * + * An entity is a tree-like structure that represents any unique + * product or service that generates cost over a fixed period of time. + * An entity could be atomic or composite. An atomic entity is indivisible + * and cannot be broken into sub-entities. + * + * A composite entity is divided into sub-entities that account for portions + * of the total cost **over the same time period**. The root entity is + * expected to only have _one_ Record consisting of the sub-entities to display + * in the product panel (keyed by the entity type, such as "service" for + * compute entities). + * + * The root sub-entities may have multiple breakdowns - for example, a + * breakdown of an entity cost by SKU vs deployment environment. The sum + * aggregated cost of each keyed breakdown should equal the sub-entity's cost. + * + * Entities with null ids are considered "unlabeled" - costs without attribution. + * If an entity is a composite, it may only have one (1) null child but may have any number of + * null grandchildren. + * + * @public + * + * @example + * Here's an example composite entity: + * ``` + * const compositeEntity = { + * id: 'product', + * aggregation: [0, 200], + * change: { + * ratio: 2000, + * amount: 200 + * }, + * entities: { + * service: [ + * { + * id: 'service-a', + * aggregation: [0, 100], + * change: { + * ratio: 100, + * amount: 100 + * }, + * entities: {} + * }, + * { + * id: 'service-b', + * aggregation: [0, 100], + * change: { + * ratio: 100, + * amount: 100 + * }, + * entities: { + * SKU: [ + * { + * id: 'service-b-sku-a', + * aggregation: [0, 25], + * change: { + * ratio: 25, + * amount: 25 + * }, + * entities: {} + * }, + * { + * id: null, // Unlabeled cost for service-b + * aggregation: [0, 75], + * change: { + * ratio: 75, + * amount: 75 + * }, + * entities: {} + * }, + * ], + * deployment: [ + * { + * id: 'service-b-env-a', + * aggregation: [0, 50], + * change: { + * ratio: 50, + * amount: 50 + * }, + * entities: {} + * }, + * { + * id: 'service-b-env-b', + * aggregation: [0, 50], + * change: { + * ratio: 50, + * amount: 50 + * }, + * entities: {} + * }, + * ] + * } + * }, + * ] + * } + * } + * ``` + */ +export interface Entity { + id: Maybe; + aggregation: [number, number]; + entities: Record; + change: ChangeStatistic; +} diff --git a/plugins/cost-insights/src/types/Group.ts b/plugins/cost-insights-common/src/types/Group.ts similarity index 97% rename from plugins/cost-insights/src/types/Group.ts rename to plugins/cost-insights-common/src/types/Group.ts index 8e0c768924..b34cac083f 100644 --- a/plugins/cost-insights/src/types/Group.ts +++ b/plugins/cost-insights-common/src/types/Group.ts @@ -14,6 +14,9 @@ * limitations under the License. */ +/** + * @public + */ export type Group = { id: string; }; diff --git a/plugins/cost-insights/src/types/Maybe.ts b/plugins/cost-insights-common/src/types/Maybe.ts similarity index 97% rename from plugins/cost-insights/src/types/Maybe.ts rename to plugins/cost-insights-common/src/types/Maybe.ts index 461c31f6a5..824c64c334 100644 --- a/plugins/cost-insights/src/types/Maybe.ts +++ b/plugins/cost-insights-common/src/types/Maybe.ts @@ -14,4 +14,7 @@ * limitations under the License. */ +/** + * @public + */ export type Maybe = T | null; diff --git a/plugins/cost-insights/src/types/Metric.ts b/plugins/cost-insights-common/src/types/Metric.ts similarity index 97% rename from plugins/cost-insights/src/types/Metric.ts rename to plugins/cost-insights-common/src/types/Metric.ts index 107513b80d..901d40f106 100644 --- a/plugins/cost-insights/src/types/Metric.ts +++ b/plugins/cost-insights-common/src/types/Metric.ts @@ -14,6 +14,9 @@ * limitations under the License. */ +/** + * @public + */ export type Metric = { kind: string; name: string; diff --git a/plugins/cost-insights/src/types/MetricData.ts b/plugins/cost-insights-common/src/types/MetricData.ts similarity index 97% rename from plugins/cost-insights/src/types/MetricData.ts rename to plugins/cost-insights-common/src/types/MetricData.ts index 225da185f8..56742e76e9 100644 --- a/plugins/cost-insights/src/types/MetricData.ts +++ b/plugins/cost-insights-common/src/types/MetricData.ts @@ -17,6 +17,9 @@ import { DateAggregation } from './DateAggregation'; import { ChangeStatistic } from './ChangeStatistic'; +/** + * @public + */ export interface MetricData { id: string; format: 'number' | 'currency'; diff --git a/plugins/cost-insights/src/types/Product.ts b/plugins/cost-insights-common/src/types/Product.ts similarity index 97% rename from plugins/cost-insights/src/types/Product.ts rename to plugins/cost-insights-common/src/types/Product.ts index 9920841223..7ed49c18da 100644 --- a/plugins/cost-insights/src/types/Product.ts +++ b/plugins/cost-insights-common/src/types/Product.ts @@ -14,6 +14,9 @@ * limitations under the License. */ +/** + * @public + */ export interface Product { kind: string; name: string; diff --git a/plugins/cost-insights/src/types/Project.ts b/plugins/cost-insights-common/src/types/Project.ts similarity index 97% rename from plugins/cost-insights/src/types/Project.ts rename to plugins/cost-insights-common/src/types/Project.ts index c12a3f1fa2..6cad92ed46 100644 --- a/plugins/cost-insights/src/types/Project.ts +++ b/plugins/cost-insights-common/src/types/Project.ts @@ -14,6 +14,9 @@ * limitations under the License. */ +/** + * @public + */ export interface Project { id: string; name?: string; diff --git a/plugins/cost-insights/src/types/Trendline.ts b/plugins/cost-insights-common/src/types/Trendline.ts similarity index 97% rename from plugins/cost-insights/src/types/Trendline.ts rename to plugins/cost-insights-common/src/types/Trendline.ts index 64405678f1..3a7e372880 100644 --- a/plugins/cost-insights/src/types/Trendline.ts +++ b/plugins/cost-insights-common/src/types/Trendline.ts @@ -13,6 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +/** + * @public + */ export type Trendline = { slope: number; intercept: number; diff --git a/plugins/cost-insights-common/src/types/index.ts b/plugins/cost-insights-common/src/types/index.ts new file mode 100644 index 0000000000..86e7af33aa --- /dev/null +++ b/plugins/cost-insights-common/src/types/index.ts @@ -0,0 +1,27 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './ChangeStatistic'; +export * from './Cost'; +export * from './DateAggregation'; +export * from './Entity'; +export * from './Group'; +export * from './Maybe'; +export * from './MetricData'; +export * from './Metric'; +export * from './Product'; +export * from './Project'; +export * from './Trendline'; diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index 1c51ec6050..a5824d1cc9 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-cost-insights +## 0.11.29-next.2 + +### Patch Changes + +- 3e032a5de2: Move cost-insights data specific API types (non react) into an @backstage/plugin-cost-insights-common + isomorphic package. This allows these types to be shared in any backend packages or other cost-insight + modules. +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/plugin-cost-insights-common@0.1.0-next.0 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## 0.11.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + ## 0.11.29-next.0 ### Patch Changes diff --git a/plugins/cost-insights/api-report.md b/plugins/cost-insights/api-report.md index 75e1315502..5a9024de5a 100644 --- a/plugins/cost-insights/api-report.md +++ b/plugins/cost-insights/api-report.md @@ -9,9 +9,12 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePalette } from '@backstage/theme'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { BackstageTheme } from '@backstage/theme'; +import { ChangeStatistic as ChangeStatistic_2 } from '@backstage/plugin-cost-insights-common'; +import * as common from '@backstage/plugin-cost-insights-common'; import { ContentRenderer } from 'recharts'; import { Dispatch } from 'react'; import { ForwardRefExoticComponent } from 'react'; +import { Maybe as Maybe_2 } from '@backstage/plugin-cost-insights-common'; import { PaletteOptions } from '@material-ui/core/styles/createPalette'; import { PropsWithChildren } from 'react'; import { ReactNode } from 'react'; @@ -32,9 +35,9 @@ export type Alert = { status?: AlertStatus; url?: string; buttonText?: string; - SnoozeForm?: Maybe; - AcceptForm?: Maybe; - DismissForm?: Maybe; + SnoozeForm?: Maybe_2; + AcceptForm?: Maybe_2; + DismissForm?: Maybe_2; onSnoozed?(options: AlertOptions): Promise; onAccepted?(options: AlertOptions): Promise; onDismissed?(options: AlertOptions): Promise; @@ -55,9 +58,9 @@ export interface AlertCost { // @public (undocumented) export interface AlertDismissFormData { // (undocumented) - feedback: Maybe; + feedback: Maybe_2; // (undocumented) - other: Maybe; + other: Maybe_2; // (undocumented) reason: AlertDismissReason; } @@ -271,13 +274,8 @@ export type BarChartTooltipProps = { // Warning: (ae-missing-release-tag) "ChangeStatistic" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // -// @public (undocumented) -export interface ChangeStatistic { - // (undocumented) - amount: number; - // (undocumented) - ratio?: number; -} +// @public @deprecated (undocumented) +export type ChangeStatistic = common.ChangeStatistic; // Warning: (ae-missing-release-tag) "ChangeThreshold" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -289,8 +287,6 @@ export enum ChangeThreshold { upper = 0.05, } -// Warning: (ae-missing-release-tag) "ChartData" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type ChartData = { date: number; @@ -301,19 +297,8 @@ export type ChartData = { // Warning: (ae-missing-release-tag) "Cost" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // -// @public (undocumented) -export interface Cost { - // (undocumented) - aggregation: DateAggregation[]; - // (undocumented) - change?: ChangeStatistic; - // (undocumented) - groupedCosts?: Record; - // (undocumented) - id: string; - // (undocumented) - trendline?: Trendline; -} +// @public @deprecated (undocumented) +export type Cost = common.Cost; // Warning: (ae-missing-release-tag) "CostGrowth" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -423,8 +408,6 @@ export interface CostInsightsThemeOptions extends PaletteOptions { palette: CostInsightsPaletteOptions; } -// Warning: (ae-missing-release-tag) "Currency" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export interface Currency { // (undocumented) @@ -467,19 +450,14 @@ export enum DataKey { // Warning: (ae-missing-release-tag) "DateAggregation" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // -// @public (undocumented) -export type DateAggregation = { - date: string; - amount: number; -}; +// @public @deprecated (undocumented) +export type DateAggregation = common.DateAggregation; // Warning: (ae-missing-release-tag) "DEFAULT_DATE_FORMAT" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export const DEFAULT_DATE_FORMAT = 'yyyy-LL-dd'; -// Warning: (ae-missing-release-tag) "Duration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export enum Duration { // (undocumented) @@ -499,17 +477,8 @@ export const EngineerThreshold = 0.5; // Warning: (ae-missing-release-tag) "Entity" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // -// @public (undocumented) -export interface Entity { - // (undocumented) - aggregation: [number, number]; - // (undocumented) - change: ChangeStatistic; - // (undocumented) - entities: Record; - // (undocumented) - id: Maybe; -} +// @public @deprecated (undocumented) +export type Entity = common.Entity; // Warning: (ae-missing-release-tag) "ExampleCostInsightsClient" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -535,10 +504,8 @@ export class ExampleCostInsightsClient implements CostInsightsApi { // Warning: (ae-missing-release-tag) "Group" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // -// @public (undocumented) -export type Group = { - id: string; -}; +// @public @deprecated (undocumented) +export type Group = common.Group; // Warning: (ae-missing-release-tag) "GrowthType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -604,31 +571,18 @@ export type Loading = Record; // Warning: (ae-missing-release-tag) "Maybe" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // -// @public (undocumented) -export type Maybe = T | null; +// @public @deprecated (undocumented) +export type Maybe = common.Maybe; // Warning: (ae-missing-release-tag) "Metric" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // -// @public (undocumented) -export type Metric = { - kind: string; - name: string; - default: boolean; -}; +// @public @deprecated (undocumented) +export type Metric = common.Metric; // Warning: (ae-missing-release-tag) "MetricData" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // -// @public (undocumented) -export interface MetricData { - // (undocumented) - aggregation: DateAggregation[]; - // (undocumented) - change: ChangeStatistic; - // (undocumented) - format: 'number' | 'currency'; - // (undocumented) - id: string; -} +// @public @deprecated (undocumented) +export type MetricData = common.MetricData; // Warning: (ae-forgotten-export) The symbol "MockConfigProviderProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "MockConfigProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -648,32 +602,23 @@ export const MockCurrencyProvider: ({ ...context }: MockCurrencyProviderProps) => JSX.Element; -// Warning: (ae-missing-release-tag) "PageFilters" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export interface PageFilters { // (undocumented) duration: Duration; // (undocumented) - group: Maybe; + group: Maybe_2; // (undocumented) metric: string | null; // (undocumented) - project: Maybe; + project: Maybe_2; } // Warning: (ae-missing-release-tag) "Product" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // -// @public (undocumented) -export interface Product { - // (undocumented) - kind: string; - // (undocumented) - name: string; -} +// @public @deprecated (undocumented) +export type Product = common.Product; -// Warning: (ae-missing-release-tag) "ProductFilters" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type ProductFilters = Array; @@ -687,8 +632,6 @@ export type ProductInsightsOptions = { project: Maybe; }; -// Warning: (ae-missing-release-tag) "ProductPeriod" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export interface ProductPeriod { // (undocumented) @@ -699,13 +642,8 @@ export interface ProductPeriod { // Warning: (ae-missing-release-tag) "Project" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // -// @public (undocumented) -export interface Project { - // (undocumented) - id: string; - // (undocumented) - name?: string; -} +// @public @deprecated (undocumented) +export type Project = common.Project; // Warning: (ae-missing-release-tag) "ProjectGrowthAlert" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -731,7 +669,7 @@ export interface ProjectGrowthData { // (undocumented) aggregation: [number, number]; // (undocumented) - change: ChangeStatistic; + change: ChangeStatistic_2; // (undocumented) periodEnd: string; // (undocumented) @@ -749,7 +687,7 @@ export interface ResourceData { // (undocumented) current: number; // (undocumented) - name: Maybe; + name: Maybe_2; // (undocumented) previous: number; } @@ -765,11 +703,8 @@ export type TooltipItem = { // Warning: (ae-missing-release-tag) "Trendline" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // -// @public (undocumented) -export type Trendline = { - slope: number; - intercept: number; -}; +// @public @deprecated (undocumented) +export type Trendline = common.Trendline; // Warning: (ae-missing-release-tag) "UnlabeledDataflowAlert" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // diff --git a/plugins/cost-insights/contrib/aws-cost-explorer-api.md b/plugins/cost-insights/contrib/aws-cost-explorer-api.md index caa7b72e10..1e3f4e9de6 100644 --- a/plugins/cost-insights/contrib/aws-cost-explorer-api.md +++ b/plugins/cost-insights/contrib/aws-cost-explorer-api.md @@ -77,7 +77,7 @@ We can use the data provided by the Cost Explorer API to implement CostInsightsA ### 1. [getGroupDailyCost](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/api/CostInsightsApi.ts#L93) -The `getGroupDailyCost` method is expected to return daily cost aggregations for a given group and interval time frame as a [`Cost`](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/types/Cost.ts). +The `getGroupDailyCost` method is expected to return daily cost aggregations for a given group and interval time frame as a [`Cost`](https://github.com/backstage/backstage/blob/master/plugins/cost-insights-common/src/types/Cost.ts). #### Total Daily cost @@ -208,13 +208,13 @@ Sample `groupedCosts` based on the response: ### 2. [getProjectDailyCost](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/api/CostInsightsApi.ts#L111) -The `getProjectDailyCost` method is expected to return daily cost aggregations for a given billing entity and interval time frame as a [`Cost`](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/types/Cost.ts). +The `getProjectDailyCost` method is expected to return daily cost aggregations for a given billing entity and interval time frame as a [`Cost`](https://github.com/backstage/backstage/blob/master/plugins/cost-insights-common/src/types/Cost.ts). This should be similar to the `getGroupDailyCost` method implementation, but with an updated `LINKED_ACCOUNT` filter to get narrower cost data for a lower-level linked account. ### 3. [getProductInsights](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/api/CostInsightsApi.ts#L111) -The `getProductInsights` method is expected to return cost aggregations for a particular cloud product and interval time frame as an [`Entity`](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/types/Entity.ts). +The `getProductInsights` method is expected to return cost aggregations for a particular cloud product and interval time frame as an [`Entity`](https://github.com/backstage/backstage/blob/master/plugins/cost-insights-common/src/types/Entity.ts). #### Cloud product cost by resource diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 6ea67d5425..beb28546b6 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.29-next.0", + "version": "0.11.29-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,11 +34,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-cost-insights-common": "^0.1.0-next.0", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -60,10 +61,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", @@ -75,7 +76,7 @@ "@types/yup": "^0.29.13", "canvas": "^2.6.1", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/cost-insights/src/types/Alert.ts b/plugins/cost-insights/src/types/Alert.ts index 2f220be0e6..483b9a654d 100644 --- a/plugins/cost-insights/src/types/Alert.ts +++ b/plugins/cost-insights/src/types/Alert.ts @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { ForwardRefExoticComponent, RefAttributes } from 'react'; -import { ChangeStatistic } from './ChangeStatistic'; +import { ChangeStatistic, Maybe } from '@backstage/plugin-cost-insights-common'; import { Duration } from './Duration'; -import { Maybe } from './Maybe'; /** * Generic alert type with required fields for display. The `element` field will be rendered in diff --git a/plugins/cost-insights/src/types/ChangeStatistic.ts b/plugins/cost-insights/src/types/ChangeStatistic.ts index 6e85335a67..8264b23c8d 100644 --- a/plugins/cost-insights/src/types/ChangeStatistic.ts +++ b/plugins/cost-insights/src/types/ChangeStatistic.ts @@ -14,15 +14,6 @@ * limitations under the License. */ -export interface ChangeStatistic { - // The ratio of change from one duration to another, expressed as: (newSum - oldSum) / oldSum - // If a ratio cannot be calculated - such as when a new or old sum is zero, - // the ratio can be omitted and where applicable, ∞ or -∞ will display based on amount. - ratio?: number; - // The actual USD change between time periods (can be negative if costs decreased) - amount: number; -} - export const EngineerThreshold = 0.5; export enum ChangeThreshold { diff --git a/plugins/cost-insights/src/types/ChartData.tsx b/plugins/cost-insights/src/types/ChartData.ts similarity index 97% rename from plugins/cost-insights/src/types/ChartData.tsx rename to plugins/cost-insights/src/types/ChartData.ts index 9de8af496d..f4ae204a22 100644 --- a/plugins/cost-insights/src/types/ChartData.tsx +++ b/plugins/cost-insights/src/types/ChartData.ts @@ -14,6 +14,9 @@ * limitations under the License. */ +/** + * @public + */ export type ChartData = { date: number; trend: number; diff --git a/plugins/cost-insights/src/types/Currency.ts b/plugins/cost-insights/src/types/Currency.ts index 5cc5756dfc..4bd1490a69 100644 --- a/plugins/cost-insights/src/types/Currency.ts +++ b/plugins/cost-insights/src/types/Currency.ts @@ -14,6 +14,9 @@ * limitations under the License. */ +/** + * @public + */ export interface Currency { kind: string | null; label: string; @@ -21,10 +24,3 @@ export interface Currency { prefix?: string; rate?: number; } - -export enum CurrencyType { - USD = 'USD', - CarbonOffsetTons = 'CARBON_OFFSET_TONS', - Beers = 'BEERS', - IceCream = 'PINTS_OF_ICE_CREAM', -} diff --git a/plugins/cost-insights/src/types/CurrencyType.ts b/plugins/cost-insights/src/types/CurrencyType.ts new file mode 100644 index 0000000000..0316e8f90e --- /dev/null +++ b/plugins/cost-insights/src/types/CurrencyType.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export enum CurrencyType { + USD = 'USD', + CarbonOffsetTons = 'CARBON_OFFSET_TONS', + Beers = 'BEERS', + IceCream = 'PINTS_OF_ICE_CREAM', +} diff --git a/plugins/cost-insights/src/types/DateFormat.ts b/plugins/cost-insights/src/types/DateFormat.ts new file mode 100644 index 0000000000..c5d9c83f6e --- /dev/null +++ b/plugins/cost-insights/src/types/DateFormat.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const DEFAULT_DATE_FORMAT = 'yyyy-LL-dd'; diff --git a/plugins/cost-insights/src/types/Duration.ts b/plugins/cost-insights/src/types/Duration.ts index 94297ac00a..dbb226df24 100644 --- a/plugins/cost-insights/src/types/Duration.ts +++ b/plugins/cost-insights/src/types/Duration.ts @@ -19,6 +19,8 @@ * 'last completed quarter', and P30D/P90D to be '[month|quarter] relative to today'. So if * it's September 15, P3M represents costs for Q2 and P30D represents August 16 - * September 15. + * + * @public */ export enum Duration { P7D = 'P7D', @@ -26,5 +28,3 @@ export enum Duration { P90D = 'P90D', P3M = 'P3M', } - -export const DEFAULT_DATE_FORMAT = 'yyyy-LL-dd'; diff --git a/plugins/cost-insights/src/types/Entity.ts b/plugins/cost-insights/src/types/Entity.ts deleted file mode 100644 index ccfea6667e..0000000000 --- a/plugins/cost-insights/src/types/Entity.ts +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { ChangeStatistic } from './ChangeStatistic'; -import { Maybe } from './Maybe'; - -export interface Entity { - id: Maybe; - aggregation: [number, number]; - entities: Record; - change: ChangeStatistic; -} - -/* - An entity is a tree-like structure that represents any unique - product or service that generates cost over a fixed period of time. - An entity could be atomic or composite. An atomic entity is indivisible - and cannot be broken into sub-entities. - - A composite entity is divided into sub-entities that account for portions - of the total cost **over the same time period**. The root entity is - expected to only have _one_ Record consisting of the sub-entities to display - in the product panel (keyed by the entity type, such as "service" for - compute entities). - - The root sub-entities may have multiple breakdowns - for example, a - breakdown of an entity cost by SKU vs deployment environment. The sum - aggregated cost of each keyed breakdown should equal the sub-entity's cost. - - Entities with null ids are considered "unlabeled" - costs without attribution. - If an entity is a composite, it may only have one (1) null child but may have any number of - null grandchildren. - - { - id: 'product', - aggregation: [0, 200], - change: { - ratio: 2000, - amount: 200 - }, - entities: { - service: [ - { - id: 'service-a', - aggregation: [0, 100], - change: { - ratio: 100, - amount: 100 - }, - entities: {} - }, - { - id: 'service-b', - aggregation: [0, 100], - change: { - ratio: 100, - amount: 100 - }, - entities: { - SKU: [ - { - id: 'service-b-sku-a', - aggregation: [0, 25], - change: { - ratio: 25, - amount: 25 - }, - entities: {} - }, - { - id: null, // Unlabeled cost for service-b - aggregation: [0, 75], - change: { - ratio: 75, - amount: 75 - }, - entities: {} - }, - ], - deployment: [ - { - id: 'service-b-env-a', - aggregation: [0, 50], - change: { - ratio: 50, - amount: 50 - }, - entities: {} - }, - { - id: 'service-b-env-b', - aggregation: [0, 50], - change: { - ratio: 50, - amount: 50 - }, - entities: {} - }, - ] - } - }, - ] - } - } -*/ diff --git a/plugins/cost-insights/src/types/Filters.ts b/plugins/cost-insights/src/types/Filters.ts index 6beef5cacc..d307243ad0 100644 --- a/plugins/cost-insights/src/types/Filters.ts +++ b/plugins/cost-insights/src/types/Filters.ts @@ -14,9 +14,12 @@ * limitations under the License. */ -import { Maybe } from './Maybe'; +import { Maybe } from '@backstage/plugin-cost-insights-common'; import { Duration } from './Duration'; +/** + * @public + */ export interface PageFilters { group: Maybe; project: Maybe; @@ -24,8 +27,14 @@ export interface PageFilters { metric: string | null; } +/** + * @public + */ export type ProductFilters = Array; +/** + * @public + */ export interface ProductPeriod { duration: Duration; productType: string; diff --git a/plugins/cost-insights/src/types/index.ts b/plugins/cost-insights/src/types/index.ts index 5f090cc7eb..b836914e73 100644 --- a/plugins/cost-insights/src/types/index.ts +++ b/plugins/cost-insights/src/types/index.ts @@ -14,22 +14,66 @@ * limitations under the License. */ +// TODO: Split some of these up into `@backstage/plugin-cost-insights-react` for presentation types +// and `@backstage/plugin-cost-insights-common` for data transfer object types. export * from './Alert'; export * from './ChangeStatistic'; export * from './ChartData'; -export * from './Cost'; -export * from './DateAggregation'; -export * from './Duration'; export * from './Currency'; -export * from './Entity'; -export * from './Icon'; +export * from './CurrencyType'; +export * from './DateFormat'; +export * from './Duration'; export * from './Filters'; -export * from './Group'; +export * from './Icon'; export * from './Loading'; -export * from './Maybe'; -export * from './MetricData'; -export * from './Metric'; -export * from './Product'; -export * from './Project'; export * from './Theme'; -export * from './Trendline'; + +/** + * Deprecated types moved to `@backstage/plugin-cost-insights-common` + */ +import * as common from '@backstage/plugin-cost-insights-common'; + +/** + * @deprecated use the same type from `@backstage/plugin-cost-insights-common` instead + */ +export type ChangeStatistic = common.ChangeStatistic; +/** + * @deprecated use the same type from `@backstage/plugin-cost-insights-common` instead + */ +export type Cost = common.Cost; +/** + * @deprecated use the same type from `@backstage/plugin-cost-insights-common` instead + */ +export type DateAggregation = common.DateAggregation; +/** + * @deprecated use the same type from `@backstage/plugin-cost-insights-common` instead + */ +export type Entity = common.Entity; +/** + * @deprecated use the same type from `@backstage/plugin-cost-insights-common` instead + */ +export type Group = common.Group; +/** + * @deprecated use the same type from `@backstage/plugin-cost-insights-common` instead + */ +export type Maybe = common.Maybe; +/** + * @deprecated use the same type from `@backstage/plugin-cost-insights-common` instead + */ +export type Metric = common.Metric; +/** + * @deprecated use the same type from `@backstage/plugin-cost-insights-common` instead + */ +export type MetricData = common.MetricData; +/** + * @deprecated use the same type from `@backstage/plugin-cost-insights-common` instead + */ +export type Product = common.Product; +/** + * @deprecated use the same type from `@backstage/plugin-cost-insights-common` instead + */ +export type Project = common.Project; +/** + * @deprecated use the same type from `@backstage/plugin-cost-insights-common` instead + */ +export type Trendline = common.Trendline; diff --git a/plugins/dynatrace/CHANGELOG.md b/plugins/dynatrace/CHANGELOG.md index a7a17ce678..ffe12d4991 100644 --- a/plugins/dynatrace/CHANGELOG.md +++ b/plugins/dynatrace/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-dynatrace +## 0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## 0.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + ## 0.1.1-next.0 ### Patch Changes diff --git a/plugins/dynatrace/package.json b/plugins/dynatrace/package.json index 018d3fdb19..0bf3c2f26c 100644 --- a/plugins/dynatrace/package.json +++ b/plugins/dynatrace/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-dynatrace", - "version": "0.1.1-next.0", + "version": "0.1.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,10 +22,10 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/theme": "^0.2.15", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -37,10 +37,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", @@ -48,7 +48,7 @@ "@types/node": "*", "cross-fetch": "^3.1.5", "express": "^4.18.1", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/example-todo-list-backend/CHANGELOG.md b/plugins/example-todo-list-backend/CHANGELOG.md index 17b2afc9ec..4609c6c4ea 100644 --- a/plugins/example-todo-list-backend/CHANGELOG.md +++ b/plugins/example-todo-list-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @internal/plugin-todo-list-backend +## 1.0.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-auth-node@0.2.3-next.1 + ## 1.0.3-next.0 ### Patch Changes diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index de8a1638ad..67fc049267 100644 --- a/plugins/example-todo-list-backend/package.json +++ b/plugins/example-todo-list-backend/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list-backend", - "version": "1.0.3-next.0", + "version": "1.0.3-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,10 +23,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", + "@backstage/backend-common": "^0.14.1-next.1", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-auth-node": "^0.2.3-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-auth-node": "^0.2.3-next.1", "@types/express": "^4.17.6", "cross-fetch": "^3.1.5", "express": "^4.17.1", @@ -36,10 +36,10 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", - "msw": "^0.42.0", + "msw": "^0.43.0", "supertest": "^6.1.6" }, "files": [ diff --git a/plugins/example-todo-list-common/CHANGELOG.md b/plugins/example-todo-list-common/CHANGELOG.md index 564b1f57eb..ba6a7bcf3d 100644 --- a/plugins/example-todo-list-common/CHANGELOG.md +++ b/plugins/example-todo-list-common/CHANGELOG.md @@ -1,5 +1,12 @@ # @internal/plugin-todo-list-common +## 1.0.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.6.3-next.0 + ## 1.0.2 ### Patch Changes diff --git a/plugins/example-todo-list-common/package.json b/plugins/example-todo-list-common/package.json index fce0a05714..b06328608a 100644 --- a/plugins/example-todo-list-common/package.json +++ b/plugins/example-todo-list-common/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list-common", - "version": "1.0.2", + "version": "1.0.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,15 +23,15 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/plugin-permission-common": "^0.6.2" + "@backstage/plugin-permission-common": "^0.6.3-next.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.1", + "@backstage/test-utils": "^1.1.2-next.1", "@types/node": "^16.11.26", - "msw": "^0.42.0", + "msw": "^0.43.0", "cross-fetch": "^3.1.5" }, "files": [ diff --git a/plugins/example-todo-list/CHANGELOG.md b/plugins/example-todo-list/CHANGELOG.md index f33b659b7e..e73d0d6474 100644 --- a/plugins/example-todo-list/CHANGELOG.md +++ b/plugins/example-todo-list/CHANGELOG.md @@ -1,5 +1,21 @@ # @internal/plugin-todo-list +## 1.0.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## 1.0.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + ## 1.0.3-next.0 ### Patch Changes diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index 7764d7c2cb..3531995880 100644 --- a/plugins/example-todo-list/package.json +++ b/plugins/example-todo-list/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list", - "version": "1.0.3-next.0", + "version": "1.0.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,9 +24,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/theme": "^0.2.15", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -36,16 +36,16 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/explore-react/package.json b/plugins/explore-react/package.json index 021365d056..b23867d8a7 100644 --- a/plugins/explore-react/package.json +++ b/plugins/explore-react/package.json @@ -36,16 +36,16 @@ "@backstage/core-plugin-api": "^1.0.3" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/cli": "^0.18.0-next.1", + "@backstage/dev-utils": "^1.0.4-next.1", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/explore/CHANGELOG.md b/plugins/explore/CHANGELOG.md index 895dd9b0ab..ecb1209c85 100644 --- a/plugins/explore/CHANGELOG.md +++ b/plugins/explore/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-explore +## 0.3.38-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.3.38-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.3.38-next.0 ### Patch Changes diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 4290cf668c..729aee7322 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.38-next.0", + "version": "0.3.38-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,12 +34,12 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", "@backstage/plugin-explore-react": "^0.0.18", - "@backstage/theme": "^0.2.15", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -53,17 +53,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/firehydrant/CHANGELOG.md b/plugins/firehydrant/CHANGELOG.md index 6b02c041dc..c03b08e828 100644 --- a/plugins/firehydrant/CHANGELOG.md +++ b/plugins/firehydrant/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-firehydrant +## 0.1.24-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.1.24-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.1.24-next.0 ### Patch Changes diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index 2574e28871..2690fbcb1d 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.24-next.0", + "version": "0.1.24-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -25,10 +25,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -39,17 +39,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md index e3710b1d3e..99d6445627 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-fossa +## 0.2.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.2.39-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.2.39-next.0 ### Patch Changes diff --git a/plugins/fossa/README.md b/plugins/fossa/README.md index 898c9d0475..10ccba5ba7 100644 --- a/plugins/fossa/README.md +++ b/plugins/fossa/README.md @@ -43,9 +43,12 @@ proxy: headers: Authorization: token ${FOSSA_API_TOKEN} -# if you have a fossa organization, configure your id here fossa: + # if you have a fossa organization, configure your id here organizationId: + # if you have a self-managed fossa instance, + # configure the baseUrl to use for links to the fossa page here + externalLinkBaseUrl: ``` 4. Get an api-token and provide `FOSSA_AUTH_HEADER` as env variable (https://app.fossa.com/account/settings/integrations/api_tokens) diff --git a/plugins/fossa/config.d.ts b/plugins/fossa/config.d.ts index 72d844c4e9..26a2823097 100644 --- a/plugins/fossa/config.d.ts +++ b/plugins/fossa/config.d.ts @@ -20,6 +20,12 @@ export interface Config { * The organization id in fossa. * @visibility frontend */ - organizationId: string; + organizationId?: string; + + /** + * The base url to use for external links (from Backstage to Fossa). + * @visibility frontend + */ + externalLinkBaseUrl?: string; }; } diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index c286f8fd82..223a246151 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.39-next.0", + "version": "0.2.39-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,12 +35,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -53,16 +53,16 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/fossa/src/api/FossaClient.test.ts b/plugins/fossa/src/api/FossaClient.test.ts index 65b0fc1d53..0e2dc81e1f 100644 --- a/plugins/fossa/src/api/FossaClient.test.ts +++ b/plugins/fossa/src/api/FossaClient.test.ts @@ -175,6 +175,58 @@ describe('FossaClient', () => { expect(summary).toBeUndefined(); }); + it('should allow custom external link base url', async () => { + client = new FossaClient({ + discoveryApi, + identityApi, + organizationId: '8736', + externalLinkBaseUrl: 'https://custom.fossa.com', // overrides the default app.fossa.com + }); + server.use( + rest.get(`${mockBaseUrl}/fossa/projects`, (req, res, ctx) => { + const expectedQuery = + 'count=1000&page=0&sort=title%2B&organizationId=8736&title=our-service'; + if (req.url.searchParams.toString() !== expectedQuery) { + return res( + ctx.status(500), + ctx.body( + `${req.url.searchParams.toString()} !== ${expectedQuery}`, + ), + ); + } + + return res( + ctx.json([ + { + locator: 'custom+8736/our-service', + title: 'our-service', + default_branch: 'develop', + revisions: [ + { + updatedAt: '2020-01-01T00:00:00Z', + dependency_count: 160, + unresolved_licensing_issue_count: 5, + unresolved_issue_count: 100, + }, + ], + }, + ]), + ); + }), + ); + + const summary = await client.getFindingSummary('our-service'); + + expect(summary).toEqual({ + timestamp: '2020-01-01T00:00:00Z', + issueCount: 5, + dependencyCount: 160, + projectDefaultBranch: 'develop', + projectUrl: + 'https://custom.fossa.com/projects/custom%2B8736%2Four-service', + } as FindingSummary); + }); + it('should handle 404 status', async () => { server.use( rest.get(`${mockBaseUrl}/fossa/projects`, (_req, res, ctx) => { diff --git a/plugins/fossa/src/api/FossaClient.ts b/plugins/fossa/src/api/FossaClient.ts index 66b44de21e..8b4b4b02e5 100644 --- a/plugins/fossa/src/api/FossaClient.ts +++ b/plugins/fossa/src/api/FossaClient.ts @@ -36,20 +36,24 @@ export class FossaClient implements FossaApi { discoveryApi: DiscoveryApi; identityApi: IdentityApi; organizationId?: string; + externalLinkBaseUrl: string; private readonly limit = pLimit(5); constructor({ discoveryApi, identityApi, organizationId, + externalLinkBaseUrl = 'https://app.fossa.com', }: { discoveryApi: DiscoveryApi; identityApi: IdentityApi; organizationId?: string; + externalLinkBaseUrl?: string; }) { this.discoveryApi = discoveryApi; this.identityApi = identityApi; this.organizationId = organizationId; + this.externalLinkBaseUrl = externalLinkBaseUrl; } private async callApi( @@ -104,9 +108,9 @@ export class FossaClient implements FossaApi { revision.unresolved_issue_count, dependencyCount: revision.dependency_count, projectDefaultBranch: project.default_branch, - projectUrl: `https://app.fossa.com/projects/${encodeURIComponent( - project.locator, - )}`, + projectUrl: `${ + this.externalLinkBaseUrl + }/projects/${encodeURIComponent(project.locator)}`, }, }; } diff --git a/plugins/fossa/src/plugin.ts b/plugins/fossa/src/plugin.ts index a586d6d8a6..954ecedc81 100644 --- a/plugins/fossa/src/plugin.ts +++ b/plugins/fossa/src/plugin.ts @@ -39,6 +39,9 @@ export const fossaPlugin = createPlugin({ discoveryApi, identityApi, organizationId: configApi.getOptionalString('fossa.organizationId'), + externalLinkBaseUrl: configApi.getOptionalString( + 'fossa.externalLinkBaseUrl', + ), }), }), ], diff --git a/plugins/gcalendar/CHANGELOG.md b/plugins/gcalendar/CHANGELOG.md index 7c6db3657b..12e37176a7 100644 --- a/plugins/gcalendar/CHANGELOG.md +++ b/plugins/gcalendar/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-gcalendar +## 0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## 0.3.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + ## 0.3.3-next.0 ### Patch Changes diff --git a/plugins/gcalendar/package.json b/plugins/gcalendar/package.json index 77dfc8af18..3024c80e26 100644 --- a/plugins/gcalendar/package.json +++ b/plugins/gcalendar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gcalendar", - "version": "0.3.3-next.0", + "version": "0.3.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,10 +22,10 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -43,10 +43,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", @@ -55,7 +55,7 @@ "@types/node": "^16.11.26", "@types/sanitize-html": "^2.6.2", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/gcp-projects/CHANGELOG.md b/plugins/gcp-projects/CHANGELOG.md index 4420fb00cc..f2bedb646f 100644 --- a/plugins/gcp-projects/CHANGELOG.md +++ b/plugins/gcp-projects/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-gcp-projects +## 0.3.26-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## 0.3.26-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + ## 0.3.26-next.0 ### Patch Changes diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index fa1aa611bd..c3809ffaac 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.26-next.0", + "version": "0.3.26-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,9 +34,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/theme": "^0.2.15", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -47,17 +47,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/git-release-manager/CHANGELOG.md b/plugins/git-release-manager/CHANGELOG.md index c4a44de3c8..e617ca7342 100644 --- a/plugins/git-release-manager/CHANGELOG.md +++ b/plugins/git-release-manager/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-git-release-manager +## 0.3.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/integration@1.2.2-next.2 + +## 0.3.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/integration@1.2.2-next.1 + ## 0.3.20-next.0 ### Patch Changes diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 2d6bf1ec73..28bfa001a0 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.20-next.0", + "version": "0.3.20-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,10 +24,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/integration": "^1.2.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -43,10 +43,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", @@ -55,7 +55,7 @@ "@types/node": "^16.11.26", "@types/recharts": "^1.8.15", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index 01e47f8e49..de2a693116 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-github-actions +## 0.5.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/integration@1.2.2-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.5.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/integration@1.2.2-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.5.7-next.0 ### Patch Changes diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 16122a2d12..eefc7c1f4c 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-actions", "description": "A Backstage plugin that integrates towards GitHub Actions", - "version": "0.5.7-next.0", + "version": "0.5.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -36,12 +36,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/integration": "^1.2.2-next.2", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -55,17 +55,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md index 1ba6a113a5..cd0542d5cf 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-github-deployments +## 0.1.38-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/integration@1.2.2-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/integration-react@1.1.2-next.2 + +## 0.1.38-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/integration@1.2.2-next.1 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.1.38-next.0 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index dd537c4b21..cbfc076a9b 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-deployments", "description": "A Backstage plugin that integrates towards GitHub Deployments", - "version": "0.1.38-next.0", + "version": "0.1.38-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,14 +24,14 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/integration-react": "^1.1.2-next.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.2", + "@backstage/integration-react": "^1.1.2-next.2", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -43,17 +43,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/github-pull-requests-board/CHANGELOG.md b/plugins/github-pull-requests-board/CHANGELOG.md index 483329f784..91faf82d07 100644 --- a/plugins/github-pull-requests-board/CHANGELOG.md +++ b/plugins/github-pull-requests-board/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-github-pull-requests-board +## 0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/integration@1.2.2-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/integration@1.2.2-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.1.1-next.0 ### Patch Changes diff --git a/plugins/github-pull-requests-board/package.json b/plugins/github-pull-requests-board/package.json index 6f12e656ca..c167cc8d88 100644 --- a/plugins/github-pull-requests-board/package.json +++ b/plugins/github-pull-requests-board/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-pull-requests-board", "description": "A Backstage plugin that allows you to see all open Pull Requests for all the repositories owned by your team", - "version": "0.1.1-next.0", + "version": "0.1.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,12 +35,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/integration": "^1.2.2-next.2", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -49,16 +49,16 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/cli": "^0.18.0-next.2", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "peerDependencies": { "@types/react": "^16.13.1 || ^17.0.0", diff --git a/plugins/gitops-profiles/CHANGELOG.md b/plugins/gitops-profiles/CHANGELOG.md index 611f5dab40..0c47ffc99f 100644 --- a/plugins/gitops-profiles/CHANGELOG.md +++ b/plugins/gitops-profiles/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-gitops-profiles +## 0.3.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## 0.3.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + ## 0.3.25-next.0 ### Patch Changes diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index 3246b5edb7..3b48f5a6a1 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gitops-profiles", "description": "A Backstage plugin that helps you manage GitOps profiles", - "version": "0.3.25-next.0", + "version": "0.3.25-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,9 +35,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/theme": "^0.2.15", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -48,17 +48,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/gocd/CHANGELOG.md b/plugins/gocd/CHANGELOG.md index 9c37f08aad..692a789447 100644 --- a/plugins/gocd/CHANGELOG.md +++ b/plugins/gocd/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-gocd +## 0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.1.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.1.13-next.0 ### Patch Changes diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index 25af6a6d4d..a7d968d3c7 100644 --- a/plugins/gocd/package.json +++ b/plugins/gocd/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gocd", "description": "A Backstage plugin that integrates towards GoCD", - "version": "0.1.13-next.0", + "version": "0.1.13-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,12 +31,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -49,10 +49,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", @@ -61,7 +61,7 @@ "@types/luxon": "^2.0.4", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/graphiql/CHANGELOG.md b/plugins/graphiql/CHANGELOG.md index 8fb1c85078..c034cef2b5 100644 --- a/plugins/graphiql/CHANGELOG.md +++ b/plugins/graphiql/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-graphiql +## 0.2.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## 0.2.39-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + ## 0.2.39-next.0 ### Patch Changes diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 9d933da2e1..0b124ecbc9 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphiql", "description": "Backstage plugin for browsing GraphQL APIs", - "version": "0.2.39-next.0", + "version": "0.2.39-next.2", "private": false, "publishConfig": { "access": "public", @@ -34,9 +34,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/theme": "^0.2.15", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -49,10 +49,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", @@ -60,7 +60,7 @@ "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0", + "msw": "^0.43.0", "react-router-dom": "6.0.0-beta.0" }, "files": [ diff --git a/plugins/graphql-backend/package.json b/plugins/graphql-backend/package.json index 6293b17f4f..0664f5a44d 100644 --- a/plugins/graphql-backend/package.json +++ b/plugins/graphql-backend/package.json @@ -34,7 +34,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", + "@backstage/backend-common": "^0.14.1-next.1", "@backstage/config": "^1.0.1", "@backstage/plugin-catalog-graphql": "^0.3.11-next.0", "@graphql-tools/schema": "^8.3.1", @@ -51,9 +51,9 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/supertest": "^2.0.8", - "msw": "^0.42.0", + "msw": "^0.43.0", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/home/CHANGELOG.md b/plugins/home/CHANGELOG.md index a5069b9352..bb2e5d7405 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,50 @@ # @backstage/plugin-home +## 0.4.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/plugin-stack-overflow@0.1.3-next.2 + +## 0.4.23-next.1 + +### Patch Changes + +- a46e317a75: Added support for customizing the time format used in the `HeaderWorldClock` component + + Here's an example of how this can be used in the `HomePage.tsx` found in `\packages\app\src\components\home` to change the clock to be in the 24hr time format: + + ```diff + +const timeFormat: Intl.DateTimeFormatOptions = { + + hour: '2-digit', + + minute: '2-digit', + + hour12: false, + +}; + + export const homePage = ( + +
} pageTitleOverride="Home"> + + +
+ + + + + + ``` + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/plugin-stack-overflow@0.1.3-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.4.23-next.0 ### Patch Changes diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index a65f8cda5c..452b3e1685 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -59,9 +59,10 @@ export function createCardExtension(options: { name?: string; }): Extension<(props: CardExtensionProps) => JSX.Element>; -// @public (undocumented) +// @public export const HeaderWorldClock: (props: { clockConfigs: ClockConfig[]; + customTimeFormat?: Intl.DateTimeFormatOptions | undefined; }) => JSX.Element | null; // @public diff --git a/plugins/home/package.json b/plugins/home/package.json index c3ec2f3a51..4800ba1842 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-home", "description": "A Backstage plugin that helps you build a home page", - "version": "0.4.23-next.0", + "version": "0.4.23-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,13 +34,13 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/plugin-stack-overflow": "^0.1.3-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/plugin-stack-overflow": "^0.1.3-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -53,17 +53,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/home/src/components/index.ts b/plugins/home/src/components/index.ts index 1408853f5f..aae0cbe26d 100644 --- a/plugins/home/src/components/index.ts +++ b/plugins/home/src/components/index.ts @@ -16,5 +16,3 @@ export { HomepageCompositionRoot } from './HomepageCompositionRoot'; export { SettingsModal } from './SettingsModal'; -export { HeaderWorldClock } from './HeaderWorldClock'; -export type { ClockConfig } from './HeaderWorldClock'; diff --git a/plugins/home/src/homePageComponents/HeaderWorldClock/HeaderWorldClock.stories.tsx b/plugins/home/src/homePageComponents/HeaderWorldClock/HeaderWorldClock.stories.tsx new file mode 100644 index 0000000000..706dfa06ce --- /dev/null +++ b/plugins/home/src/homePageComponents/HeaderWorldClock/HeaderWorldClock.stories.tsx @@ -0,0 +1,97 @@ +/* + * 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 { Header } from '@backstage/core-components'; +import { wrapInTestApp } from '@backstage/test-utils'; +import React, { ComponentType } from 'react'; +import { ClockConfig, HeaderWorldClock } from './HeaderWorldClock'; + +export default { + title: 'Plugins/Home/Components/HeaderWorldClock', + decorators: [(Story: ComponentType<{}>) => wrapInTestApp()], +}; + +export const Default = () => { + const clockConfigs: ClockConfig[] = [ + { + label: 'NYC', + timeZone: 'America/New_York', + }, + { + label: 'UTC', + timeZone: 'UTC', + }, + { + label: 'STO', + timeZone: 'Europe/Stockholm', + }, + { + label: 'TYO', + timeZone: 'Asia/Tokyo', + }, + ]; + + const timeFormat: Intl.DateTimeFormatOptions = { + hour: '2-digit', + minute: '2-digit', + hour12: true, + }; + + return ( +
+ +
+ ); +}; + +export const TwentyFourHourClocks = () => { + const clockConfigs: ClockConfig[] = [ + { + label: 'NYC', + timeZone: 'America/New_York', + }, + { + label: 'UTC', + timeZone: 'UTC', + }, + { + label: 'STO', + timeZone: 'Europe/Stockholm', + }, + { + label: 'TYO', + timeZone: 'Asia/Tokyo', + }, + ]; + + const timeFormat: Intl.DateTimeFormatOptions = { + hour: '2-digit', + minute: '2-digit', + hour12: false, + }; + + return ( +
+ +
+ ); +}; diff --git a/plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.test.tsx b/plugins/home/src/homePageComponents/HeaderWorldClock/HeaderWorldClock.test.tsx similarity index 77% rename from plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.test.tsx rename to plugins/home/src/homePageComponents/HeaderWorldClock/HeaderWorldClock.test.tsx index 9dbfceac81..db92fbb89f 100644 --- a/plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.test.tsx +++ b/plugins/home/src/homePageComponents/HeaderWorldClock/HeaderWorldClock.test.tsx @@ -86,3 +86,33 @@ describe('HeaderWorldClock with invalid Time Zone', () => { expect(rendered.getByText('GMT')).toBeInTheDocument(); }); }); + +describe('HeaderWorldClock with custom Time Format', () => { + it('uses 24hr clock from custom Time Format', async () => { + jest.useFakeTimers().setSystemTime(new Date('2022-06-28T09:10:13.502Z')); + + const clockConfigs: ClockConfig[] = [ + { + label: 'UTC', + timeZone: 'UTC', + }, + ]; + + const timeFormat: Intl.DateTimeFormatOptions = { + hour: '2-digit', + minute: '2-digit', + hour12: false, + }; + + const rendered = await renderInTestApp( + + + , + ); + + expect(rendered.getByText('09:10')).toBeInTheDocument(); + }); +}); diff --git a/plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.tsx b/plugins/home/src/homePageComponents/HeaderWorldClock/HeaderWorldClock.tsx similarity index 63% rename from plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.tsx rename to plugins/home/src/homePageComponents/HeaderWorldClock/HeaderWorldClock.tsx index 7e3065cc7a..6672fe6a22 100644 --- a/plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.tsx +++ b/plugins/home/src/homePageComponents/HeaderWorldClock/HeaderWorldClock.tsx @@ -32,7 +32,10 @@ export type ClockConfig = { timeZone: string; }; -function getTimes(clockConfigs: ClockConfig[]) { +function getTimes( + clockConfigs: ClockConfig[], + customTimeFormat?: Intl.DateTimeFormatOptions, +) { const d = new Date(); const lang = window.navigator.language; @@ -47,7 +50,7 @@ function getTimes(clockConfigs: ClockConfig[]) { const options: Intl.DateTimeFormatOptions = { timeZone: clockConfig.timeZone, - ...timeFormat, + ...(customTimeFormat ?? timeFormat), }; try { @@ -68,24 +71,57 @@ function getTimes(clockConfigs: ClockConfig[]) { return clocks; } -/** @public */ -export const HeaderWorldClock = (props: { clockConfigs: ClockConfig[] }) => { - const { clockConfigs } = props; +/** + * A component to display a configurable list of clocks for various time zones. + * + * @example + * Here's a simple example: + * ``` + * // This will give you a clock for the time zone that Stockholm is in + * // you can add more than one but keep in mind space may be limited + * const clockConfigs: ClockConfig[] = [ + * { + * label: 'STO', + * timeZone: 'Europe/Stockholm', + * }, + * ]; + * + * // Setting hour12 to false will make all the clocks show in the 24hr format + * const timeFormat: Intl.DateTimeFormatOptions = { + * hour: '2-digit', + * minute: '2-digit', + * hour12: false, + * }; + * + * // Here is the component in use: + * + * ``` + * + * @public + */ +export const HeaderWorldClock = (props: { + clockConfigs: ClockConfig[]; + customTimeFormat?: Intl.DateTimeFormatOptions; +}) => { + const { clockConfigs, customTimeFormat } = props; const defaultTimes: TimeObj[] = []; const [clocks, setTimes] = React.useState(defaultTimes); React.useEffect(() => { - setTimes(getTimes(clockConfigs)); + setTimes(getTimes(clockConfigs, customTimeFormat)); const intervalId = setInterval(() => { - setTimes(getTimes(clockConfigs)); + setTimes(getTimes(clockConfigs, customTimeFormat)); }, 1000); return () => { clearInterval(intervalId); }; - }, [clockConfigs]); + }, [clockConfigs, customTimeFormat]); if (clocks.length !== 0) { return ( diff --git a/plugins/home/src/components/HeaderWorldClock/index.ts b/plugins/home/src/homePageComponents/HeaderWorldClock/index.ts similarity index 100% rename from plugins/home/src/components/HeaderWorldClock/index.ts rename to plugins/home/src/homePageComponents/HeaderWorldClock/index.ts diff --git a/plugins/home/src/homePageComponents/index.ts b/plugins/home/src/homePageComponents/index.ts index 4d2802fb98..d318226dbd 100644 --- a/plugins/home/src/homePageComponents/index.ts +++ b/plugins/home/src/homePageComponents/index.ts @@ -16,3 +16,4 @@ export * from './CompanyLogo'; export * from './Toolkit'; +export type { ClockConfig } from './HeaderWorldClock'; diff --git a/plugins/home/src/index.ts b/plugins/home/src/index.ts index 8f137d589b..1776b5aa9c 100644 --- a/plugins/home/src/index.ts +++ b/plugins/home/src/index.ts @@ -31,9 +31,10 @@ export { ComponentTabs, ComponentTab, WelcomeTitle, + HeaderWorldClock, } from './plugin'; -export { SettingsModal, HeaderWorldClock } from './components'; +export { SettingsModal } from './components'; export * from './assets'; -export type { ClockConfig } from './components'; +export type { ClockConfig } from './homePageComponents'; export { createCardExtension } from './extensions'; export type { ComponentRenderer } from './extensions'; diff --git a/plugins/home/src/plugin.ts b/plugins/home/src/plugin.ts index 93110faffb..9b221ad8dc 100644 --- a/plugins/home/src/plugin.ts +++ b/plugins/home/src/plugin.ts @@ -136,3 +136,20 @@ export const HomePageStarredEntities = homePlugin.provide( components: () => import('./homePageComponents/StarredEntities'), }), ); + +/** + * A component to display a configurable list of clocks for various time zones. + * + * @public + */ +export const HeaderWorldClock = homePlugin.provide( + createComponentExtension({ + name: 'HeaderWorldClock', + component: { + lazy: () => + import('./homePageComponents/HeaderWorldClock').then( + m => m.HeaderWorldClock, + ), + }, + }), +); diff --git a/plugins/ilert/CHANGELOG.md b/plugins/ilert/CHANGELOG.md index f6845ac116..f24f1ede11 100644 --- a/plugins/ilert/CHANGELOG.md +++ b/plugins/ilert/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-ilert +## 0.1.33-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.1.33-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.1.33-next.0 ### Patch Changes diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index 69a1728b76..c844d5bd7e 100644 --- a/plugins/ilert/package.json +++ b/plugins/ilert/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-ilert", "description": "A Backstage plugin that integrates towards iLert", - "version": "0.1.33-next.0", + "version": "0.1.33-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,12 +24,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@date-io/luxon": "1.x", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -43,17 +43,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/jenkins-backend/CHANGELOG.md b/plugins/jenkins-backend/CHANGELOG.md index ff91e37269..c96b147b18 100644 --- a/plugins/jenkins-backend/CHANGELOG.md +++ b/plugins/jenkins-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-jenkins-backend +## 0.1.24-next.2 + +### Patch Changes + +- 8747824221: feature: added support for multiple branches to the `JenkinsApi` +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + +## 0.1.24-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/plugin-auth-node@0.2.3-next.1 + - @backstage/plugin-jenkins-common@0.1.6-next.0 + - @backstage/plugin-permission-common@0.6.3-next.0 + ## 0.1.24-next.0 ### Patch Changes diff --git a/plugins/jenkins-backend/package.json b/plugins/jenkins-backend/package.json index ac78d61831..bc24160dcf 100644 --- a/plugins/jenkins-backend/package.json +++ b/plugins/jenkins-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-jenkins-backend", "description": "A Backstage backend plugin that integrates towards Jenkins", - "version": "0.1.24-next.0", + "version": "0.1.24-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -25,26 +25,27 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-auth-node": "^0.2.3-next.0", - "@backstage/plugin-jenkins-common": "^0.1.5", - "@backstage/plugin-permission-common": "^0.6.2", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-auth-node": "^0.2.3-next.1", + "@backstage/plugin-jenkins-common": "^0.1.6-next.0", + "@backstage/plugin-permission-common": "^0.6.3-next.0", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", "jenkins": "^0.28.1", + "promise-any-polyfill": "^1.0.1", "winston": "^3.2.1", "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@types/jenkins": "^0.23.1", "@types/supertest": "^2.0.8", - "msw": "^0.42.0", + "msw": "^0.43.0", "supertest": "^6.1.6" }, "files": [ diff --git a/plugins/jenkins-backend/src/service/jenkinsApi.test.ts b/plugins/jenkins-backend/src/service/jenkinsApi.test.ts index 29da414470..bada5e1c29 100644 --- a/plugins/jenkins-backend/src/service/jenkinsApi.test.ts +++ b/plugins/jenkins-backend/src/service/jenkinsApi.test.ts @@ -118,10 +118,9 @@ describe('JenkinsApi', () => { it('standard github layout', async () => { mockedJenkinsClient.job.get.mockResolvedValueOnce(project); - const result = await jenkinsApi.getProjects( - jenkinsInfo, + const result = await jenkinsApi.getProjects(jenkinsInfo, [ 'testBranchName', - ); + ]); expect(mockedJenkins).toHaveBeenCalledWith({ baseUrl: jenkinsInfo.baseUrl, @@ -134,6 +133,35 @@ describe('JenkinsApi', () => { }); expect(result).toHaveLength(1); }); + + it('supports multiple branches', async () => { + mockedJenkinsClient.job.get.mockResolvedValue(project); + + const result = await jenkinsApi.getProjects(jenkinsInfo, [ + 'foo', + 'bar', + 'catpants', + ]); + + expect(mockedJenkins).toHaveBeenCalledWith({ + baseUrl: jenkinsInfo.baseUrl, + headers: jenkinsInfo.headers, + promisify: true, + }); + expect(mockedJenkinsClient.job.get).toBeCalledWith({ + name: `${jenkinsInfo.jobFullName}/foo`, + tree: expect.anything(), + }); + expect(mockedJenkinsClient.job.get).toBeCalledWith({ + name: `${jenkinsInfo.jobFullName}/bar`, + tree: expect.anything(), + }); + expect(mockedJenkinsClient.job.get).toBeCalledWith({ + name: `${jenkinsInfo.jobFullName}/catpants`, + tree: expect.anything(), + }); + expect(result).toHaveLength(1); + }); }); describe('augmented', () => { const projectWithScmActions: JenkinsProject = { diff --git a/plugins/jenkins-backend/src/service/jenkinsApi.ts b/plugins/jenkins-backend/src/service/jenkinsApi.ts index 8069f57692..ae2fa0f7b5 100644 --- a/plugins/jenkins-backend/src/service/jenkinsApi.ts +++ b/plugins/jenkins-backend/src/service/jenkinsApi.ts @@ -30,6 +30,12 @@ import { import { jenkinsExecutePermission } from '@backstage/plugin-jenkins-common'; import { NotAllowedError } from '@backstage/errors'; +if (!Promise.any) { + (async () => { + await import('promise-any-polyfill'); + })(); +} + export class JenkinsApiImpl { private static readonly lastBuildTreeSpec = `lastBuild[ number, @@ -70,18 +76,21 @@ export class JenkinsApiImpl { * Get a list of projects for the given JenkinsInfo. * @see ../../../jenkins/src/api/JenkinsApi.ts#getProjects */ - async getProjects(jenkinsInfo: JenkinsInfo, branch?: string) { + async getProjects(jenkinsInfo: JenkinsInfo, branches?: string[]) { const client = await JenkinsApiImpl.getClient(jenkinsInfo); const projects: BackstageProject[] = []; - if (branch) { - // we have been asked to filter to a single branch. + if (branches) { // Assume jenkinsInfo.jobFullName is a folder which contains one job per branch. // TODO: extract a strategy interface for this - const job = await client.job.get({ - name: `${jenkinsInfo.jobFullName}/${branch}`, - tree: JenkinsApiImpl.jobTreeSpec.replace(/\s/g, ''), - }); + const job = await Promise.any( + branches.map(branch => + client.job.get({ + name: `${jenkinsInfo.jobFullName}/${branch}`, + tree: JenkinsApiImpl.jobTreeSpec.replace(/\s/g, ''), + }), + ), + ); projects.push(this.augmentProject(job)); } else { // We aren't filtering diff --git a/plugins/jenkins-backend/src/service/router.ts b/plugins/jenkins-backend/src/service/router.ts index 2c9e268165..b4c06314e1 100644 --- a/plugins/jenkins-backend/src/service/router.ts +++ b/plugins/jenkins-backend/src/service/router.ts @@ -64,12 +64,12 @@ export async function createRouter( request.header('authorization'), ); const branch = request.query.branch; - let branchStr: string | undefined; + let branches: string[] | undefined; if (branch === undefined) { - branchStr = undefined; + branches = undefined; } else if (typeof branch === 'string') { - branchStr = branch; + branches = branch.split(/,/g); } else { // this was passed in as something weird -> 400 // https://evanhahn.com/gotchas-with-express-query-parsing-and-how-to-avoid-them/ @@ -88,7 +88,7 @@ export async function createRouter( }, backstageToken: token, }); - const projects = await jenkinsApi.getProjects(jenkinsInfo, branchStr); + const projects = await jenkinsApi.getProjects(jenkinsInfo, branches); response.json({ projects: projects, diff --git a/plugins/jenkins-common/CHANGELOG.md b/plugins/jenkins-common/CHANGELOG.md index 53cf222e5a..ea0afcde79 100644 --- a/plugins/jenkins-common/CHANGELOG.md +++ b/plugins/jenkins-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-jenkins-common +## 0.1.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.4-next.0 + - @backstage/plugin-permission-common@0.6.3-next.0 + ## 0.1.5 ### Patch Changes diff --git a/plugins/jenkins-common/package.json b/plugins/jenkins-common/package.json index 78d9cf2532..d6520cd085 100644 --- a/plugins/jenkins-common/package.json +++ b/plugins/jenkins-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-jenkins-common", - "version": "0.1.5", + "version": "0.1.6-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,11 +22,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/plugin-catalog-common": "^1.0.3", - "@backstage/plugin-permission-common": "^0.6.2" + "@backstage/plugin-catalog-common": "^1.0.4-next.0", + "@backstage/plugin-permission-common": "^0.6.3-next.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0" + "@backstage/cli": "^0.18.0-next.1" }, "files": [ "dist" diff --git a/plugins/jenkins/CHANGELOG.md b/plugins/jenkins/CHANGELOG.md index 4519ba9e78..a55f8a3d4b 100644 --- a/plugins/jenkins/CHANGELOG.md +++ b/plugins/jenkins/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-jenkins +## 0.7.6-next.2 + +### Patch Changes + +- 8747824221: feature: added support for multiple branches to the `JenkinsApi` +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.7.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + - @backstage/plugin-jenkins-common@0.1.6-next.0 + ## 0.7.6-next.0 ### Patch Changes diff --git a/plugins/jenkins/README.md b/plugins/jenkins/README.md index 80e39d2095..2a0ec451c8 100644 --- a/plugins/jenkins/README.md +++ b/plugins/jenkins/README.md @@ -19,7 +19,7 @@ yarn add --cwd packages/app @backstage/plugin-jenkins 3. Add the `EntityJenkinsContent` extension to the `CI/CD` page and `EntityLatestJenkinsRunCard` to the `overview` page in the app (or wherever you'd prefer): -Note that if you configured a custom JenkinsInfoProvider in step 2, you may need a custom isJenkinsAvailable. +Note that if you configured a custom JenkinsInfoProvider in step 2, you may need a custom isJenkinsAvailable. Also if you're transitioning to a new default branch name, you can pass multiple branch names as a comma-separated list and it will check for each branch name. ```tsx // In packages/app/src/components/catalog/EntityPage.tsx @@ -38,7 +38,10 @@ const serviceEntityPage = ( - + {/* ... */} diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index 586fcf04dd..e70aea32f4 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-jenkins", "description": "A Backstage plugin that integrates towards Jenkins", - "version": "0.7.6-next.0", + "version": "0.7.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,13 +35,13 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/plugin-jenkins-common": "^0.1.5", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/plugin-jenkins-common": "^0.1.6-next.0", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -54,10 +54,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", @@ -65,7 +65,7 @@ "@types/node": "^16.11.26", "@types/testing-library__jest-dom": "^5.9.1", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/kafka-backend/CHANGELOG.md b/plugins/kafka-backend/CHANGELOG.md index 9a912b07ef..5a35d5a504 100644 --- a/plugins/kafka-backend/CHANGELOG.md +++ b/plugins/kafka-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-kafka-backend +## 0.2.27-next.2 + +### Patch Changes + +- 8751667541: Updated dependency `kafkajs` to `^2.0.0`. +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + +## 0.2.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + ## 0.2.27-next.0 ### Patch Changes diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index b78c297586..5a666ee6df 100644 --- a/plugins/kafka-backend/package.json +++ b/plugins/kafka-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kafka-backend", "description": "A Backstage backend plugin that integrates towards Kafka", - "version": "0.2.27-next.0", + "version": "0.2.27-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,19 +35,19 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", + "@backstage/errors": "^1.1.0-next.0", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", - "kafkajs": "^1.16.0-beta.6", + "kafkajs": "^2.0.0", "lodash": "^4.17.21", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@types/jest-when": "^3.5.0", "@types/lodash": "^4.14.151", "jest-when": "^3.1.0", diff --git a/plugins/kafka/CHANGELOG.md b/plugins/kafka/CHANGELOG.md index 06d84866f6..7f5db4402c 100644 --- a/plugins/kafka/CHANGELOG.md +++ b/plugins/kafka/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-kafka +## 0.3.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.3.7-next.0 ### Patch Changes diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index 18dfdc05fc..522cefb94f 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kafka", "description": "A Backstage plugin that integrates towards Kafka", - "version": "0.3.7-next.0", + "version": "0.3.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,11 +24,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -39,10 +39,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", @@ -51,7 +51,7 @@ "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", "jest-when": "^3.1.0", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index a3747e47aa..b11a5b045f 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-kubernetes-backend +## 0.7.0-next.2 + +### Patch Changes + +- 60e5f9fe68: Fixed the lack of `limitranges` as part of the Default Objects to fetch from the kubernetes api +- Updated dependencies + - @backstage/plugin-kubernetes-common@0.4.0-next.1 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + +## 0.7.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + ## 0.7.0-next.0 ### Minor Changes diff --git a/plugins/kubernetes-backend/api-report.md b/plugins/kubernetes-backend/api-report.md index 9aa1827a71..489098a91e 100644 --- a/plugins/kubernetes-backend/api-report.md +++ b/plugins/kubernetes-backend/api-report.md @@ -3,6 +3,7 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { CatalogApi } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; import { Duration } from 'luxon'; import { Entity } from '@backstage/catalog-model'; @@ -109,6 +110,7 @@ export class KubernetesBuilder { protected buildRouter( objectsProvider: KubernetesObjectsProvider, clusterSupplier: KubernetesClustersSupplier, + catalogApi: CatalogApi, ): express.Router; // (undocumented) protected buildServiceLocator( @@ -156,6 +158,8 @@ export interface KubernetesClustersSupplier { // @alpha (undocumented) export interface KubernetesEnvironment { + // (undocumented) + catalogApi: CatalogApi; // (undocumented) config: Config; // (undocumented) @@ -217,6 +221,7 @@ export type KubernetesObjectTypes = | 'services' | 'configmaps' | 'deployments' + | 'limitranges' | 'replicasets' | 'horizontalpodautoscalers' | 'jobs' @@ -270,6 +275,8 @@ export interface ObjectToFetch { // @alpha (undocumented) export interface RouterOptions { + // (undocumented) + catalogApi: CatalogApi; // (undocumented) clusterSupplier?: KubernetesClustersSupplier; // (undocumented) diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index c528dfa25e..002575e25d 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-backend", "description": "A Backstage backend plugin that integrates towards Kubernetes", - "version": "0.7.0-next.0", + "version": "0.7.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -36,12 +36,13 @@ }, "dependencies": { "@azure/identity": "^2.0.4", - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", "@backstage/core-plugin-api": "^1.0.3-next.0", - "@backstage/errors": "^1.0.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-auth-node": "^0.2.3-next.1", "@backstage/plugin-kubernetes-common": "^0.4.0-next.0", "@google-cloud/container": "^4.0.0", "@kubernetes/client-node": "^0.16.0", @@ -63,7 +64,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@types/aws4": "^1.5.1", "aws-sdk-mock": "^5.2.1", "supertest": "^6.1.3" diff --git a/plugins/kubernetes-backend/src/routes/resourceRoutes.test.ts b/plugins/kubernetes-backend/src/routes/resourceRoutes.test.ts new file mode 100644 index 0000000000..57e6514a96 --- /dev/null +++ b/plugins/kubernetes-backend/src/routes/resourceRoutes.test.ts @@ -0,0 +1,545 @@ +/* + * 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 { errorHandler } from '@backstage/backend-common'; +import express from 'express'; +import request from 'supertest'; +import Router from 'express-promise-router'; +import { addResourceRoutesToRouter } from './resourcesRoutes'; +import { Entity } from '@backstage/catalog-model'; + +describe('resourcesRoutes', () => { + let app: express.Express; + + beforeAll(() => { + app = express(); + app.use(express.json()); + const router = Router(); + addResourceRoutesToRouter( + router, + { + getEntityByRef: jest.fn().mockImplementation(entityRef => { + if (entityRef.name === 'noentity') { + return Promise.resolve(undefined); + } + return Promise.resolve({ + kind: entityRef.kind, + metadata: { + name: entityRef.name, + namespace: entityRef.namespace, + }, + } as Entity); + }), + } as any, + { + getKubernetesObjectsByEntity: jest.fn().mockImplementation(args => { + if (args.entity.metadata.name === 'inject500') { + return Promise.reject(new Error('some internal error')); + } + + return Promise.resolve({ + items: [ + { + clusterOne: { + pods: [ + { + metadata: { + name: 'pod1', + }, + }, + ], + }, + }, + ], + }); + }), + getCustomResourcesByEntity: jest.fn().mockImplementation(args => { + if (args.entity.metadata.name === 'inject500') { + return Promise.reject(new Error('some internal error')); + } + + return Promise.resolve({ + items: [ + { + clusterOne: { + pods: [ + { + metadata: { + name: 'pod1', + }, + }, + ], + }, + }, + ], + }); + }), + } as any, + ); + app.use('/', router); + app.use(errorHandler()); + }); + + describe('POST /resources/workloads/query', () => { + // eslint-disable-next-line jest/expect-expect + it('200 happy path', async () => { + await request(app) + .post('/resources/workloads/query') + .send({ + entityRef: 'kind:namespacec/someComponent', + auth: { + google: 'something', + }, + }) + .set('Content-Type', 'application/json') + .set('Authorization', 'Bearer Zm9vYmFy') + .expect(200, { + items: [ + { + clusterOne: { + pods: [ + { + metadata: { + name: 'pod1', + }, + }, + ], + }, + }, + ], + }); + }); + // eslint-disable-next-line jest/expect-expect + it('400 when missing entity ref', async () => { + await request(app) + .post('/resources/workloads/query') + .send({ + auth: { + google: 'something', + }, + }) + .set('Content-Type', 'application/json') + .set('Authorization', 'Bearer Zm9vYmFy') + .expect(400, { + error: { name: 'InputError', message: 'entity is a required field' }, + request: { + method: 'POST', + url: '/resources/workloads/query', + }, + response: { statusCode: 400 }, + }); + }); + // eslint-disable-next-line jest/expect-expect + it('400 when bad entity ref', async () => { + await request(app) + .post('/resources/workloads/query') + .send({ + entityRef: 'ffff', + auth: { + google: 'something', + }, + }) + .set('Content-Type', 'application/json') + .set('Authorization', 'Bearer Zm9vYmFy') + .expect(400, { + error: { + name: 'InputError', + message: + 'Invalid entity ref, Error: Entity reference "ffff" had missing or empty kind (e.g. did not start with "component:" or similar)', + }, + request: { + method: 'POST', + url: '/resources/workloads/query', + }, + response: { statusCode: 400 }, + }); + }); + // eslint-disable-next-line jest/expect-expect + it('400 when no entity in catalog', async () => { + await request(app) + .post('/resources/workloads/query') + .send({ + entityRef: 'noentity:noentity', + auth: { + google: 'something', + }, + }) + .set('Content-Type', 'application/json') + .set('Authorization', 'Bearer Zm9vYmFy') + .expect(400, { + error: { + name: 'InputError', + message: 'Entity ref missing, noentity:default/noentity', + }, + request: { + method: 'POST', + url: '/resources/workloads/query', + }, + response: { statusCode: 400 }, + }); + }); + // eslint-disable-next-line jest/expect-expect + it('401 when no Auth header', async () => { + await request(app) + .post('/resources/workloads/query') + .send({ + entityRef: 'component:someComponent', + auth: { + google: 'something', + }, + }) + .set('Content-Type', 'application/json') + .expect(401, { + error: { name: 'AuthenticationError', message: 'No Backstage token' }, + request: { + method: 'POST', + url: '/resources/workloads/query', + }, + response: { statusCode: 401 }, + }); + }); + // eslint-disable-next-line jest/expect-expect + it('401 when invalid Auth header', async () => { + await request(app) + .post('/resources/workloads/query') + .send({ + entityRef: 'component:someComponent', + auth: { + google: 'something', + }, + }) + .set('Content-Type', 'application/json') + .set('Authorization', 'ffffff') + .expect(401, { + error: { name: 'AuthenticationError', message: 'No Backstage token' }, + request: { + method: 'POST', + url: '/resources/workloads/query', + }, + response: { statusCode: 401 }, + }); + }); + // eslint-disable-next-line jest/expect-expect + it('500 handle gracefully', async () => { + await request(app) + .post('/resources/workloads/query') + .send({ + entityRef: 'inject500:inject500/inject500', + auth: { + google: 'something', + }, + }) + .set('Content-Type', 'application/json') + .set('Authorization', 'Bearer Zm9vYmFy') + .expect(500, { + error: { + name: 'Error', + message: 'some internal error', + level: 'error', + service: 'backstage', + }, + request: { method: 'POST', url: '/resources/workloads/query' }, + response: { statusCode: 500 }, + }); + }); + }); + describe('POST /resources/custom/query', () => { + // eslint-disable-next-line jest/expect-expect + it('200 happy path', async () => { + await request(app) + .post('/resources/custom/query') + .send({ + entityRef: 'component:someComponent', + auth: { + google: 'something', + }, + customResources: [ + { + group: 'someGroup', + apiVersion: 'someApiVersion', + plural: 'somePlural', + }, + ], + }) + .set('Content-Type', 'application/json') + .set('Authorization', 'Bearer Zm9vYmFy') + .expect(200, { + items: [ + { + clusterOne: { + pods: [ + { + metadata: { + name: 'pod1', + }, + }, + ], + }, + }, + ], + }); + }); + // eslint-disable-next-line jest/expect-expect + it('400 when missing custom resources', async () => { + await request(app) + .post('/resources/custom/query') + .send({ + entityRef: 'component:someComponent', + auth: { + google: 'something', + }, + }) + .set('Content-Type', 'application/json') + .set('Authorization', 'Bearer Zm9vYmFy') + .expect(400, { + error: { + name: 'InputError', + message: 'customResources is a required field', + }, + request: { + method: 'POST', + url: '/resources/custom/query', + }, + response: { statusCode: 400 }, + }); + }); + // eslint-disable-next-line jest/expect-expect + it('400 when custom resources not array', async () => { + await request(app) + .post('/resources/custom/query') + .send({ + entityRef: 'component:someComponent', + auth: { + google: 'something', + }, + customResources: 'somestring', + }) + .set('Content-Type', 'application/json') + .set('Authorization', 'Bearer Zm9vYmFy') + .expect(400, { + error: { + name: 'InputError', + message: 'customResources must be an array', + }, + request: { + method: 'POST', + url: '/resources/custom/query', + }, + response: { statusCode: 400 }, + }); + }); + // eslint-disable-next-line jest/expect-expect + it('400 when custom resources empty', async () => { + await request(app) + .post('/resources/custom/query') + .send({ + entityRef: 'component:someComponent', + auth: { + google: 'something', + }, + customResources: [], + }) + .set('Content-Type', 'application/json') + .set('Authorization', 'Bearer Zm9vYmFy') + .expect(400, { + error: { + name: 'InputError', + message: 'at least 1 customResource is required', + }, + request: { + method: 'POST', + url: '/resources/custom/query', + }, + response: { statusCode: 400 }, + }); + }); + // eslint-disable-next-line jest/expect-expect + it('400 when missing entity ref', async () => { + await request(app) + .post('/resources/custom/query') + .send({ + auth: { + google: 'something', + }, + customResources: [ + { + group: 'someGroup', + apiVersion: 'someApiVersion', + plural: 'somePlural', + }, + ], + }) + .set('Content-Type', 'application/json') + .set('Authorization', 'Bearer Zm9vYmFy') + .expect(400, { + error: { name: 'InputError', message: 'entity is a required field' }, + request: { + method: 'POST', + url: '/resources/custom/query', + }, + response: { statusCode: 400 }, + }); + }); + // eslint-disable-next-line jest/expect-expect + it('400 when bad entity ref', async () => { + await request(app) + .post('/resources/custom/query') + .send({ + entityRef: 'ffff', + auth: { + google: 'something', + }, + customResources: [ + { + group: 'someGroup', + apiVersion: 'someApiVersion', + plural: 'somePlural', + }, + ], + }) + .set('Content-Type', 'application/json') + .set('Authorization', 'Bearer Zm9vYmFy') + .expect(400, { + error: { + name: 'InputError', + message: + 'Invalid entity ref, Error: Entity reference "ffff" had missing or empty kind (e.g. did not start with "component:" or similar)', + }, + request: { + method: 'POST', + url: '/resources/custom/query', + }, + response: { statusCode: 400 }, + }); + }); + // eslint-disable-next-line jest/expect-expect + it('400 when no entity in catalog', async () => { + await request(app) + .post('/resources/custom/query') + .send({ + entityRef: 'noentity:noentity', + auth: { + google: 'something', + }, + customResources: [ + { + group: 'someGroup', + apiVersion: 'someApiVersion', + plural: 'somePlural', + }, + ], + }) + .set('Content-Type', 'application/json') + .set('Authorization', 'Bearer Zm9vYmFy') + .expect(400, { + error: { + name: 'InputError', + message: 'Entity ref missing, noentity:default/noentity', + }, + request: { + method: 'POST', + url: '/resources/custom/query', + }, + response: { statusCode: 400 }, + }); + }); + // eslint-disable-next-line jest/expect-expect + it('401 when no Auth header', async () => { + await request(app) + .post('/resources/custom/query') + .send({ + entityRef: 'component:someComponent', + auth: { + google: 'something', + }, + customResources: [ + { + group: 'someGroup', + apiVersion: 'someApiVersion', + plural: 'somePlural', + }, + ], + }) + .set('Content-Type', 'application/json') + .expect(401, { + error: { name: 'AuthenticationError', message: 'No Backstage token' }, + request: { + method: 'POST', + url: '/resources/custom/query', + }, + response: { statusCode: 401 }, + }); + }); + // eslint-disable-next-line jest/expect-expect + it('401 when invalid Auth header', async () => { + await request(app) + .post('/resources/custom/query') + .send({ + entityRef: 'component:someComponent', + auth: { + google: 'something', + }, + customResources: [ + { + group: 'someGroup', + apiVersion: 'someApiVersion', + plural: 'somePlural', + }, + ], + }) + .set('Content-Type', 'application/json') + .set('Authorization', 'ffffff') + .expect(401, { + error: { name: 'AuthenticationError', message: 'No Backstage token' }, + request: { + method: 'POST', + url: '/resources/custom/query', + }, + response: { statusCode: 401 }, + }); + }); + // eslint-disable-next-line jest/expect-expect + it('500 handle gracefully', async () => { + await request(app) + .post('/resources/custom/query') + .send({ + entityRef: 'inject500:inject500/inject500', + auth: { + google: 'something', + }, + customResources: [ + { + group: 'someGroup', + apiVersion: 'someApiVersion', + plural: 'somePlural', + }, + ], + }) + .set('Content-Type', 'application/json') + .set('Authorization', 'Bearer Zm9vYmFy') + .expect(500, { + error: { + name: 'Error', + message: 'some internal error', + level: 'error', + service: 'backstage', + }, + request: { method: 'POST', url: '/resources/custom/query' }, + response: { statusCode: 500 }, + }); + }); + }); +}); diff --git a/plugins/kubernetes-backend/src/routes/resourcesRoutes.ts b/plugins/kubernetes-backend/src/routes/resourcesRoutes.ts new file mode 100644 index 0000000000..2b2a48f707 --- /dev/null +++ b/plugins/kubernetes-backend/src/routes/resourcesRoutes.ts @@ -0,0 +1,94 @@ +/* + * 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 { + CompoundEntityRef, + parseEntityRef, + stringifyEntityRef, +} from '@backstage/catalog-model'; +import { CatalogApi } from '@backstage/catalog-client'; +import { InputError, AuthenticationError } from '@backstage/errors'; +import express, { Request } from 'express'; +import { KubernetesObjectsProvider } from '../types/types'; +import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node'; + +export const addResourceRoutesToRouter = ( + router: express.Router, + catalogApi: CatalogApi, + objectsProvider: KubernetesObjectsProvider, +) => { + const getEntityByReq = async (req: Request) => { + const rawEntityRef = req.body.entityRef; + if (rawEntityRef && typeof rawEntityRef !== 'string') { + throw new InputError(`entity query must be a string`); + } else if (!rawEntityRef) { + throw new InputError('entity is a required field'); + } + let entityRef: CompoundEntityRef | undefined = undefined; + + try { + entityRef = parseEntityRef(rawEntityRef); + } catch (error) { + throw new InputError(`Invalid entity ref, ${error}`); + } + + const token = getBearerTokenFromAuthorizationHeader( + req.headers.authorization, + ); + + if (!token) { + throw new AuthenticationError('No Backstage token'); + } + + const entity = await catalogApi.getEntityByRef(entityRef, { + token: token, + }); + + if (!entity) { + throw new InputError( + `Entity ref missing, ${stringifyEntityRef(entityRef)}`, + ); + } + return entity; + }; + + router.post('/resources/workloads/query', async (req, res) => { + const entity = await getEntityByReq(req); + const response = await objectsProvider.getKubernetesObjectsByEntity({ + entity, + auth: req.body.auth, + }); + res.json(response); + }); + + router.post('/resources/custom/query', async (req, res) => { + const entity = await getEntityByReq(req); + + if (!req.body.customResources) { + throw new InputError('customResources is a required field'); + } else if (!Array.isArray(req.body.customResources)) { + throw new InputError('customResources must be an array'); + } else if (req.body.customResources.length === 0) { + throw new InputError('at least 1 customResource is required'); + } + + const response = await objectsProvider.getCustomResourcesByEntity({ + entity, + customResources: req.body.customResources, + auth: req.body.auth, + }); + res.json(response); + }); +}; diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts index 2e42ba91d1..c39a72808f 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts @@ -34,11 +34,13 @@ import { import { KubernetesBuilder } from './KubernetesBuilder'; import { KubernetesFanOutHandler } from './KubernetesFanOutHandler'; import { PodStatus } from '@kubernetes/client-node'; +import { CatalogApi } from '@backstage/catalog-client'; describe('KubernetesBuilder', () => { let app: express.Express; let kubernetesFanOutHandler: jest.Mocked; let config: Config; + let catalogApi: CatalogApi; beforeAll(async () => { const logger = getVoidLogger(); @@ -80,6 +82,7 @@ describe('KubernetesBuilder', () => { config, logger, discovery, + catalogApi, }) .setObjectsProvider(kubernetesFanOutHandler) .setClusterSupplier(clusterSupplier) @@ -256,6 +259,7 @@ describe('KubernetesBuilder', () => { logger, config, discovery, + catalogApi, }) .setClusterSupplier(clusterSupplier) .setServiceLocator(serviceLocator) diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts index 50ecfab4bc..4d7eb3d6f4 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts @@ -38,6 +38,8 @@ import { } from './KubernetesFanOutHandler'; import { KubernetesClientBasedFetcher } from './KubernetesFetcher'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; +import { addResourceRoutesToRouter } from '../routes/resourcesRoutes'; +import { CatalogApi } from '@backstage/catalog-client'; /** * @@ -47,6 +49,7 @@ export interface KubernetesEnvironment { logger: Logger; config: Config; discovery: PluginEndpointDiscovery; + catalogApi: CatalogApi; } /** @@ -121,7 +124,11 @@ export class KubernetesBuilder { objectTypesToFetch: this.getObjectTypesToFetch(), }); - const router = this.buildRouter(objectsProvider, clusterSupplier); + const router = this.buildRouter( + objectsProvider, + clusterSupplier, + this.env.catalogApi, + ); return { clusterSupplier, @@ -232,11 +239,13 @@ export class KubernetesBuilder { protected buildRouter( objectsProvider: KubernetesObjectsProvider, clusterSupplier: KubernetesClustersSupplier, + catalogApi: CatalogApi, ): express.Router { const logger = this.env.logger; const router = Router(); router.use(express.json()); + // @deprecated router.post('/services/:serviceId', async (req, res) => { const serviceId = req.params.serviceId; const requestBody: ObjectsByEntityRequest = req.body; @@ -265,6 +274,9 @@ export class KubernetesBuilder { })), }); }); + + addResourceRoutesToRouter(router, catalogApi, objectsProvider); + return router; } diff --git a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts index ac2ffaf2ed..67748e1506 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts @@ -70,6 +70,12 @@ export const DEFAULT_OBJECTS: ObjectToFetch[] = [ plural: 'configmaps', objectType: 'configmaps', }, + { + group: '', + apiVersion: 'v1', + plural: 'limitranges', + objectType: 'limitranges', + }, { group: 'apps', apiVersion: 'v1', diff --git a/plugins/kubernetes-backend/src/service/router.ts b/plugins/kubernetes-backend/src/service/router.ts index 95814a79a3..ab27a75a18 100644 --- a/plugins/kubernetes-backend/src/service/router.ts +++ b/plugins/kubernetes-backend/src/service/router.ts @@ -20,6 +20,7 @@ import { KubernetesClustersSupplier } from '../types/types'; import express from 'express'; import { KubernetesBuilder } from './KubernetesBuilder'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; +import { CatalogApi } from '@backstage/catalog-client'; /** * @@ -28,6 +29,7 @@ import { PluginEndpointDiscovery } from '@backstage/backend-common'; export interface RouterOptions { logger: Logger; config: Config; + catalogApi: CatalogApi; clusterSupplier?: KubernetesClustersSupplier; discovery: PluginEndpointDiscovery; } diff --git a/plugins/kubernetes-backend/src/service/standaloneApplication.ts b/plugins/kubernetes-backend/src/service/standaloneApplication.ts index 5c14c22b1d..8234f89d48 100644 --- a/plugins/kubernetes-backend/src/service/standaloneApplication.ts +++ b/plugins/kubernetes-backend/src/service/standaloneApplication.ts @@ -27,6 +27,7 @@ import helmet from 'helmet'; import { Logger } from 'winston'; import { createRouter } from './router'; import { ConfigReader } from '@backstage/config'; +import { CatalogClient } from '@backstage/catalog-client'; export interface ApplicationOptions { enableCors: boolean; @@ -42,6 +43,10 @@ export async function createStandaloneApplication( const app = express(); + const catalogApi = new CatalogClient({ + discoveryApi: SingleHostDiscovery.fromConfig(config), + }); + app.use(helmet()); if (enableCors) { app.use(cors()); @@ -49,7 +54,7 @@ export async function createStandaloneApplication( app.use(compression()); app.use(express.json()); app.use(requestLoggingHandler()); - app.use('/', await createRouter({ logger, config, discovery })); + app.use('/', await createRouter({ logger, config, discovery, catalogApi })); app.use(notFoundHandler()); app.use(errorHandler()); diff --git a/plugins/kubernetes-backend/src/types/types.ts b/plugins/kubernetes-backend/src/types/types.ts index 6302a49fa5..0826c4158c 100644 --- a/plugins/kubernetes-backend/src/types/types.ts +++ b/plugins/kubernetes-backend/src/types/types.ts @@ -101,6 +101,7 @@ export type KubernetesObjectTypes = | 'services' | 'configmaps' | 'deployments' + | 'limitranges' | 'replicasets' | 'horizontalpodautoscalers' | 'jobs' diff --git a/plugins/kubernetes-common/CHANGELOG.md b/plugins/kubernetes-common/CHANGELOG.md index 560f700be0..dd1feff82e 100644 --- a/plugins/kubernetes-common/CHANGELOG.md +++ b/plugins/kubernetes-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-kubernetes-common +## 0.4.0-next.1 + +### Patch Changes + +- 60e5f9fe68: Fixed the lack of `limitranges` as part of the Default Objects to fetch from the kubernetes api +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + ## 0.4.0-next.0 ### Minor Changes diff --git a/plugins/kubernetes-common/api-report.md b/plugins/kubernetes-common/api-report.md index d59db7422f..2ca33d1a97 100644 --- a/plugins/kubernetes-common/api-report.md +++ b/plugins/kubernetes-common/api-report.md @@ -11,6 +11,7 @@ import { V1Deployment } from '@kubernetes/client-node'; import { V1HorizontalPodAutoscaler } from '@kubernetes/client-node'; import { V1Ingress } from '@kubernetes/client-node'; import { V1Job } from '@kubernetes/client-node'; +import { V1LimitRange } from '@kubernetes/client-node'; import { V1Pod } from '@kubernetes/client-node'; import { V1ReplicaSet } from '@kubernetes/client-node'; import { V1Service } from '@kubernetes/client-node'; @@ -131,6 +132,7 @@ export type FetchResponse = | ServiceFetchResponse | ConfigMapFetchResponse | DeploymentFetchResponse + | LimitRangeFetchReponse | ReplicaSetsFetchResponse | HorizontalPodAutoscalersFetchResponse | JobsFetchResponse @@ -212,6 +214,16 @@ export interface KubernetesRequestBody { entity: Entity; } +// Warning: (ae-missing-release-tag) "LimitRangeFetchReponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface LimitRangeFetchReponse { + // (undocumented) + resources: Array; + // (undocumented) + type: 'limitranges'; +} + // Warning: (ae-missing-release-tag) "ObjectsByEntityResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index 6b576f79ca..9e3ff7299e 100644 --- a/plugins/kubernetes-common/package.json +++ b/plugins/kubernetes-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-common", "description": "Common functionalities for kubernetes, to be shared between kubernetes and kubernetes-backend plugin", - "version": "0.4.0-next.0", + "version": "0.4.0-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -38,11 +38,11 @@ "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", "@kubernetes/client-node": "^0.16.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0" + "@backstage/cli": "^0.18.0-next.2" }, "jest": { "roots": [ diff --git a/plugins/kubernetes-common/src/types.ts b/plugins/kubernetes-common/src/types.ts index 68fbe09301..9b8b790c79 100644 --- a/plugins/kubernetes-common/src/types.ts +++ b/plugins/kubernetes-common/src/types.ts @@ -22,6 +22,7 @@ import { V1HorizontalPodAutoscaler, V1Ingress, V1Job, + V1LimitRange, V1Pod, V1ReplicaSet, V1Service, @@ -97,6 +98,7 @@ export type FetchResponse = | ServiceFetchResponse | ConfigMapFetchResponse | DeploymentFetchResponse + | LimitRangeFetchReponse | ReplicaSetsFetchResponse | HorizontalPodAutoscalersFetchResponse | JobsFetchResponse @@ -130,6 +132,11 @@ export interface ReplicaSetsFetchResponse { resources: Array; } +export interface LimitRangeFetchReponse { + type: 'limitranges'; + resources: Array; +} + export interface HorizontalPodAutoscalersFetchResponse { type: 'horizontalpodautoscalers'; resources: Array; diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index 3765441a95..dc44dffad4 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-kubernetes +## 0.6.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/plugin-kubernetes-common@0.4.0-next.1 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.6.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.6.7-next.0 ### Patch Changes diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 1bc3b47f3c..0bb8ac0324 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes", "description": "A Backstage plugin that integrates towards Kubernetes", - "version": "0.6.7-next.0", + "version": "0.6.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,13 +34,13 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/plugin-kubernetes-common": "^0.4.0-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/plugin-kubernetes-common": "^0.4.0-next.1", + "@backstage/theme": "^0.2.16-next.1", "@kubernetes/client-node": "^0.16.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -57,10 +57,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", @@ -68,7 +68,7 @@ "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md index f3dc92b790..ded56ce2da 100644 --- a/plugins/lighthouse/CHANGELOG.md +++ b/plugins/lighthouse/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-lighthouse +## 0.3.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.3.7-next.0 ### Patch Changes diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index 2dc5aa5f04..ea95636060 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse", "description": "A Backstage plugin that integrates towards Lighthouse", - "version": "0.3.7-next.0", + "version": "0.3.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,12 +35,12 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -51,10 +51,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", @@ -63,7 +63,7 @@ "@types/node": "^16.11.26", "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/newrelic-dashboard/CHANGELOG.md b/plugins/newrelic-dashboard/CHANGELOG.md index b10750b453..ce7fb18e5c 100644 --- a/plugins/newrelic-dashboard/CHANGELOG.md +++ b/plugins/newrelic-dashboard/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-newrelic-dashboard +## 0.1.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.1.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.1.15-next.0 ### Patch Changes diff --git a/plugins/newrelic-dashboard/package.json b/plugins/newrelic-dashboard/package.json index 969853a9dc..a0a21fcf9c 100644 --- a/plugins/newrelic-dashboard/package.json +++ b/plugins/newrelic-dashboard/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-newrelic-dashboard", - "version": "0.1.15-next.0", + "version": "0.1.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,19 +23,19 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", "@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" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", + "@backstage/cli": "^0.18.0-next.2", + "@backstage/dev-utils": "^1.0.4-next.2", "@testing-library/jest-dom": "^5.10.1", "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5" diff --git a/plugins/newrelic/CHANGELOG.md b/plugins/newrelic/CHANGELOG.md index 7753c672c8..f3ff482fd8 100644 --- a/plugins/newrelic/CHANGELOG.md +++ b/plugins/newrelic/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-newrelic +## 0.3.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## 0.3.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + ## 0.3.25-next.0 ### Patch Changes diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 7c67d63436..61b49060a4 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-newrelic", "description": "A Backstage plugin that integrates towards New Relic", - "version": "0.3.25-next.0", + "version": "0.3.25-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,9 +35,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/theme": "^0.2.15", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -47,17 +47,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index 0432f9ef45..f21231dc81 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-org +## 0.5.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.5.7-next.1 + +### Patch Changes + +- 1e984b11fc: Render namespaces for teams with subtitles in `MyGroupsSidebarItem` +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.5.7-next.0 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index 33d9f6da7f..9bc58b26bf 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-org", "description": "A Backstage plugin that helps you create entity pages for your organization", - "version": "0.5.7-next.0", + "version": "0.5.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,11 +29,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -48,18 +48,18 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/cli": "^0.17.3-next.0", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.stories.tsx b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.stories.tsx index c07815f39e..fc050feb2a 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.stories.tsx +++ b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.stories.tsx @@ -110,14 +110,14 @@ const monochromeTheme = (outer: BackstageTheme) => ...outer, defaultPageTheme: 'home', pageTheme: { - home: genPageTheme(['#444'], shapes.wave2), - documentation: genPageTheme(['#474747'], shapes.wave2), - tool: genPageTheme(['#222'], shapes.wave2), - service: genPageTheme(['#aaa'], shapes.wave2), - website: genPageTheme(['#0e0e0e'], shapes.wave2), - library: genPageTheme(['#9d9d9d'], shapes.wave2), - other: genPageTheme(['#aaa'], shapes.wave2), - app: genPageTheme(['#666'], shapes.wave2), + home: genPageTheme({ colors: ['#444'], shape: shapes.wave2 }), + documentation: genPageTheme({ colors: ['#474747'], shape: shapes.wave2 }), + tool: genPageTheme({ colors: ['#222'], shape: shapes.wave2 }), + service: genPageTheme({ colors: ['#aaa'], shape: shapes.wave2 }), + website: genPageTheme({ colors: ['#0e0e0e'], shape: shapes.wave2 }), + library: genPageTheme({ colors: ['#9d9d9d'], shape: shapes.wave2 }), + other: genPageTheme({ colors: ['#aaa'], shape: shapes.wave2 }), + app: genPageTheme({ colors: ['#666'], shape: shapes.wave2 }), }, }); diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index 5222d06b45..929a4a3ed8 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-pagerduty +## 0.5.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.5.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.5.0-next.0 ### Minor Changes diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 0c81aba5ad..b638bbd573 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-pagerduty", "description": "A Backstage plugin that integrates towards PagerDuty", - "version": "0.5.0-next.0", + "version": "0.5.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,12 +34,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -53,17 +53,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/periskop-backend/package.json b/plugins/periskop-backend/package.json index bc27a76e81..03be1e44ec 100644 --- a/plugins/periskop-backend/package.json +++ b/plugins/periskop-backend/package.json @@ -24,7 +24,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", + "@backstage/backend-common": "^0.14.1-next.1", "@backstage/config": "^1.0.1", "@types/express": "*", "cross-fetch": "^3.0.6", @@ -35,9 +35,9 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/supertest": "^2.0.8", - "msw": "^0.42.0", + "msw": "^0.43.0", "supertest": "^6.1.6" }, "files": [ diff --git a/plugins/periskop/CHANGELOG.md b/plugins/periskop/CHANGELOG.md index eb82d4cbac..db6854741f 100644 --- a/plugins/periskop/CHANGELOG.md +++ b/plugins/periskop/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-periskop +## 0.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.1.5-next.0 ### Patch Changes diff --git a/plugins/periskop/package.json b/plugins/periskop/package.json index b5c72b52fe..a9c538d957 100644 --- a/plugins/periskop/package.json +++ b/plugins/periskop/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop", - "version": "0.1.5-next.0", + "version": "0.1.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -25,12 +25,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -42,10 +42,10 @@ "react-dom": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", @@ -53,7 +53,7 @@ "@types/luxon": "^2.0.4", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/permission-backend/CHANGELOG.md b/plugins/permission-backend/CHANGELOG.md index 3c86015f00..e2b2cedb19 100644 --- a/plugins/permission-backend/CHANGELOG.md +++ b/plugins/permission-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-permission-backend +## 0.5.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-auth-node@0.2.3-next.1 + - @backstage/plugin-permission-common@0.6.3-next.0 + - @backstage/plugin-permission-node@0.6.3-next.1 + ## 0.5.9-next.0 ### Patch Changes diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index 69762f67de..4df852d255 100644 --- a/plugins/permission-backend/package.json +++ b/plugins/permission-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-backend", - "version": "0.5.9-next.0", + "version": "0.5.9-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,12 +22,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", + "@backstage/backend-common": "^0.14.1-next.1", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-auth-node": "^0.2.3-next.0", - "@backstage/plugin-permission-common": "^0.6.2", - "@backstage/plugin-permission-node": "^0.6.3-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-auth-node": "^0.2.3-next.1", + "@backstage/plugin-permission-common": "^0.6.3-next.0", + "@backstage/plugin-permission-node": "^0.6.3-next.1", "@types/express": "*", "dataloader": "^2.0.0", "express": "^4.17.1", @@ -39,11 +39,11 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/lodash": "^4.14.151", "@types/supertest": "^2.0.8", "supertest": "^6.1.6", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/permission-common/CHANGELOG.md b/plugins/permission-common/CHANGELOG.md index b578c1e8fb..769887f86e 100644 --- a/plugins/permission-common/CHANGELOG.md +++ b/plugins/permission-common/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-permission-common +## 0.6.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.1.0-next.0 + ## 0.6.2 ### Patch Changes diff --git a/plugins/permission-common/package.json b/plugins/permission-common/package.json index 3988bc0ded..b811b63438 100644 --- a/plugins/permission-common/package.json +++ b/plugins/permission-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-permission-common", "description": "Isomorphic types and client for Backstage permissions and authorization", - "version": "0.6.2", + "version": "0.6.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -42,14 +42,14 @@ }, "dependencies": { "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", + "@backstage/errors": "^1.1.0-next.0", "cross-fetch": "^3.1.5", "uuid": "^8.0.0", "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/jest": "^26.0.7", - "msw": "^0.42.0" + "msw": "^0.43.0" } } diff --git a/plugins/permission-node/CHANGELOG.md b/plugins/permission-node/CHANGELOG.md index 190dfbdbb5..d412a981eb 100644 --- a/plugins/permission-node/CHANGELOG.md +++ b/plugins/permission-node/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-permission-node +## 0.6.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-auth-node@0.2.3-next.1 + - @backstage/plugin-permission-common@0.6.3-next.0 + ## 0.6.3-next.0 ### Patch Changes diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index b6ef506197..a0bc4585b0 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.6.3-next.0", + "version": "0.6.3-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,20 +33,20 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", + "@backstage/backend-common": "^0.14.1-next.1", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-auth-node": "^0.2.3-next.0", - "@backstage/plugin-permission-common": "^0.6.2", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-auth-node": "^0.2.3-next.1", + "@backstage/plugin-permission-common": "^0.6.3-next.0", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/supertest": "^2.0.8", - "msw": "^0.42.0", + "msw": "^0.43.0", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/permission-react/CHANGELOG.md b/plugins/permission-react/CHANGELOG.md index cd991549bd..aa6f06a45c 100644 --- a/plugins/permission-react/CHANGELOG.md +++ b/plugins/permission-react/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-permission-react +## 0.4.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.6.3-next.0 + ## 0.4.2 ### Patch Changes diff --git a/plugins/permission-react/package.json b/plugins/permission-react/package.json index 98f1200881..f0dcc88de0 100644 --- a/plugins/permission-react/package.json +++ b/plugins/permission-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-react", - "version": "0.4.2", + "version": "0.4.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,7 +33,7 @@ "dependencies": { "@backstage/config": "^1.0.1", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-permission-common": "^0.6.2", + "@backstage/plugin-permission-common": "^0.6.3-next.0", "cross-fetch": "^3.1.5", "react-router": "6.0.0-beta.0", "react-use": "^17.2.4", @@ -44,8 +44,8 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/cli": "^0.18.0-next.1", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@types/jest": "^26.0.7" diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 12a265516b..7eba901c54 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -32,7 +32,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", + "@backstage/backend-common": "^0.14.1-next.1", "@backstage/config": "^1.0.1", "@types/express": "^4.17.6", "express": "^4.17.1", @@ -46,7 +46,7 @@ "yup": "^0.32.9" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/http-proxy-middleware": "^0.19.3", "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index bcea34e3c4..8f8be07621 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -34,7 +34,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", + "@backstage/backend-common": "^0.14.1-next.1", "@backstage/config": "^1.0.1", "@types/express": "^4.17.6", "camelcase-keys": "^7.0.1", @@ -50,10 +50,10 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.26-next.0", - "@backstage/cli": "^0.17.3-next.0", + "@backstage/backend-test-utils": "^0.1.26-next.1", + "@backstage/cli": "^0.18.0-next.1", "@types/supertest": "^2.0.8", - "msw": "^0.42.0", + "msw": "^0.43.0", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md index 67288eb5f0..367b7a07f3 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-rollbar +## 0.4.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.4.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.4.7-next.0 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index c75896f622..1ba43e05bc 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-rollbar", "description": "A Backstage plugin that integrates towards Rollbar", - "version": "0.4.7-next.0", + "version": "0.4.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,11 +35,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -53,10 +53,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", @@ -65,7 +65,7 @@ "@types/node": "^16.11.26", "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md index 199920e449..2bf18ee3a8 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-scaffolder-backend-module-cookiecutter +## 0.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.4.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/integration@1.2.2-next.1 + ## 0.2.9-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index b6e7a04b64..f953bac5cd 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/package.json +++ b/plugins/scaffolder-backend-module-cookiecutter/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-cookiecutter", "description": "A module for the scaffolder backend that lets you template projects using cookiecutter", - "version": "0.2.9-next.0", + "version": "0.2.9-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,10 +23,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/plugin-scaffolder-backend": "^1.4.0-next.0", + "@backstage/backend-common": "^0.14.1-next.1", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.1", + "@backstage/plugin-scaffolder-backend": "^1.4.0-next.1", "@backstage/config": "^1.0.1", "@backstage/types": "^1.0.0", "command-exists": "^1.2.9", @@ -35,13 +35,13 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/fs-extra": "^9.0.1", "@types/mock-fs": "^4.13.0", "@types/jest": "^26.0.7", "@types/command-exists": "^1.2.0", "mock-fs": "^5.1.0", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/scaffolder-backend-module-rails/CHANGELOG.md b/plugins/scaffolder-backend-module-rails/CHANGELOG.md index d5967d3c5f..1a1d249fd3 100644 --- a/plugins/scaffolder-backend-module-rails/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-rails/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-scaffolder-backend-module-rails +## 0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.4.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/integration@1.2.2-next.1 + ## 0.4.2-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index 2223c4787e..e42f34b762 100644 --- a/plugins/scaffolder-backend-module-rails/package.json +++ b/plugins/scaffolder-backend-module-rails/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-rails", "description": "A module for the scaffolder backend that lets you template projects using Rails", - "version": "0.4.2-next.0", + "version": "0.4.2-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,17 +24,17 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/plugin-scaffolder-backend": "^1.4.0-next.0", + "@backstage/backend-common": "^0.14.1-next.1", + "@backstage/plugin-scaffolder-backend": "^1.4.0-next.1", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.1", "@backstage/types": "^1.0.0", "command-exists": "^1.2.9", "fs-extra": "^10.0.1" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "@types/command-exists": "^1.2.0", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index ba7ffe278c..ed97db5617 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,43 @@ # @backstage/plugin-scaffolder-backend +## 1.4.0-next.2 + +### Minor Changes + +- 4baf8a4ece: Update GitLab Merge Request Action to allow source branch to be deleted +- 2db07887cb: Added two new scaffolder actions: `github:repo:create` and `github:repo:push` + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + - @backstage/plugin-catalog-backend@1.2.1-next.2 + - @backstage/integration@1.2.2-next.2 + +## 1.4.0-next.1 + +### Patch Changes + +- 801d606909: Improve error messaging when passing in malformed auth +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-catalog-backend@1.2.1-next.1 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + ## 1.4.0-next.0 ### Minor Changes diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 707b8e62ba..8d302e69f6 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -168,6 +168,62 @@ export type CreateGithubPullRequestClientFactoryInput = { token?: string; }; +// @public +export function createGithubRepoCreateAction(options: { + integrations: ScmIntegrationRegistry; + githubCredentialsProvider?: GithubCredentialsProvider; +}): TemplateAction<{ + repoUrl: string; + description?: string | undefined; + access?: string | undefined; + deleteBranchOnMerge?: boolean | undefined; + gitAuthorName?: string | undefined; + gitAuthorEmail?: string | undefined; + allowRebaseMerge?: boolean | undefined; + allowSquashMerge?: boolean | undefined; + allowMergeCommit?: boolean | undefined; + requireCodeOwnerReviews?: boolean | undefined; + requiredStatusCheckContexts?: string[] | undefined; + repoVisibility?: 'internal' | 'private' | 'public' | undefined; + collaborators?: + | ( + | { + user: string; + access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; + } + | { + team: string; + access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; + } + | { + username: string; + access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; + } + )[] + | undefined; + token?: string | undefined; + topics?: string[] | undefined; +}>; + +// @public +export function createGithubRepoPushAction(options: { + integrations: ScmIntegrationRegistry; + config: Config; + githubCredentialsProvider?: GithubCredentialsProvider; +}): TemplateAction<{ + repoUrl: string; + description?: string | undefined; + defaultBranch?: string | undefined; + protectDefaultBranch?: boolean | undefined; + gitCommitMessage?: string | undefined; + gitAuthorName?: string | undefined; + gitAuthorEmail?: string | undefined; + requireCodeOwnerReviews?: boolean | undefined; + requiredStatusCheckContexts?: string[] | undefined; + sourcePath?: string | undefined; + token?: string | undefined; +}>; + // @public export function createGithubWebhookAction(options: { integrations: ScmIntegrationRegistry; @@ -345,6 +401,7 @@ export const createPublishGitlabMergeRequestAction: (options: { targetPath: string; token?: string | undefined; projectid?: string | undefined; + removeSourceBranch?: boolean | undefined; }>; // @public diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index dba891bfa2..a70e60f714 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend", "description": "The Backstage backend plugin that helps you create new things", - "version": "1.4.0-next.0", + "version": "1.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,13 +34,13 @@ "build:assets": "node scripts/build-nunjucks.js" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/plugin-catalog-backend": "^1.2.1-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.2", + "@backstage/plugin-catalog-backend": "^1.2.1-next.2", "@backstage/plugin-scaffolder-common": "^1.1.2-next.0", "@backstage/types": "^1.0.0", "@gitbeaker/core": "^35.6.0", @@ -54,12 +54,12 @@ "express": "^4.17.1", "express-promise-router": "^4.1.0", "fs-extra": "10.1.0", - "git-url-parse": "^11.6.0", + "git-url-parse": "^12.0.0", "globby": "^11.0.0", "isbinaryfile": "^5.0.0", "isomorphic-git": "^1.8.0", "jsonschema": "^1.2.6", - "knex": "^1.0.2", + "knex": "^2.0.0", "lodash": "^4.17.21", "luxon": "^2.0.2", "morgan": "^1.10.0", @@ -76,8 +76,8 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.26-next.0", - "@backstage/cli": "^0.17.3-next.0", + "@backstage/backend-test-utils": "^0.1.26-next.2", + "@backstage/cli": "^0.18.0-next.2", "@types/command-exists": "^1.2.0", "@types/fs-extra": "^9.0.1", "@types/git-url-parse": "^9.0.0", @@ -88,7 +88,7 @@ "esbuild": "^0.14.1", "jest-when": "^3.1.0", "mock-fs": "^5.1.0", - "msw": "^0.42.0", + "msw": "^0.43.0", "supertest": "^6.1.3", "yaml": "^1.10.0" }, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts index 2ffbc09ce5..91f1e180d0 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts @@ -15,25 +15,34 @@ */ import { UrlReader } from '@backstage/backend-common'; -import { JsonObject } from '@backstage/types'; import { CatalogApi } from '@backstage/catalog-client'; -import { - GithubCredentialsProvider, - ScmIntegrations, - DefaultGithubCredentialsProvider, -} from '@backstage/integration'; import { Config } from '@backstage/config'; import { - createCatalogWriteAction, + DefaultGithubCredentialsProvider, + GithubCredentialsProvider, + ScmIntegrations, +} from '@backstage/integration'; +import { JsonObject } from '@backstage/types'; +import { createCatalogRegisterAction, + createCatalogWriteAction, } from './catalog'; +import { TemplateFilter } from '../../../lib'; +import { TemplateAction } from '../types'; import { createDebugLogAction } from './debug'; import { createFetchPlainAction, createFetchTemplateAction } from './fetch'; import { createFilesystemDeleteAction, createFilesystemRenameAction, } from './filesystem'; +import { + createGithubActionsDispatchAction, + createGithubIssuesLabelAction, + createGithubRepoCreateAction, + createGithubRepoPushAction, + createGithubWebhookAction, +} from './github'; import { createPublishAzureAction, createPublishBitbucketAction, @@ -45,13 +54,6 @@ import { createPublishGitlabAction, createPublishGitlabMergeRequestAction, } from './publish'; -import { - createGithubActionsDispatchAction, - createGithubWebhookAction, - createGithubIssuesLabelAction, -} from './github'; -import { TemplateFilter } from '../../../lib'; -import { TemplateAction } from '../types'; /** * The options passed to {@link createBuiltinActions} @@ -165,6 +167,15 @@ export const createBuiltinActions = ( integrations, githubCredentialsProvider, }), + createGithubRepoCreateAction({ + integrations, + githubCredentialsProvider, + }), + createGithubRepoPushAction({ + integrations, + config, + githubCredentialsProvider, + }), ]; return actions as TemplateAction[]; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.test.ts new file mode 100644 index 0000000000..0e7e907917 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.test.ts @@ -0,0 +1,416 @@ +/* + * 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 { TemplateAction } from '../../types'; + +jest.mock('../helpers'); + +import { getVoidLogger } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { + DefaultGithubCredentialsProvider, + GithubCredentialsProvider, + ScmIntegrations, +} from '@backstage/integration'; +import { when } from 'jest-when'; +import { PassThrough } from 'stream'; +import { createGithubRepoCreateAction } from './githubRepoCreate'; + +const mockOctokit = { + rest: { + users: { + getByUsername: jest.fn(), + }, + repos: { + addCollaborator: jest.fn(), + createInOrg: jest.fn(), + createForAuthenticatedUser: jest.fn(), + replaceAllTopics: jest.fn(), + }, + teams: { + addOrUpdateRepoPermissionsInOrg: jest.fn(), + }, + }, +}; +jest.mock('octokit', () => ({ + Octokit: class { + constructor() { + return mockOctokit; + } + }, +})); + +describe('github:repo:create', () => { + const config = new ConfigReader({ + integrations: { + github: [ + { host: 'github.com', token: 'tokenlols' }, + { host: 'ghe.github.com' }, + ], + }, + }); + + const integrations = ScmIntegrations.fromConfig(config); + let githubCredentialsProvider: GithubCredentialsProvider; + let action: TemplateAction; + + const mockContext = { + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + description: 'description', + repoVisibility: 'private' as const, + access: 'owner/blam', + }, + workspacePath: 'lol', + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + + beforeEach(() => { + jest.resetAllMocks(); + githubCredentialsProvider = + DefaultGithubCredentialsProvider.fromIntegrations(integrations); + action = createGithubRepoCreateAction({ + integrations, + githubCredentialsProvider, + }); + }); + + it('should call the githubApis with the correct values for createInOrg', async () => { + mockOctokit.rest.users.getByUsername.mockResolvedValue({ + data: { type: 'Organization' }, + }); + + mockOctokit.rest.repos.createInOrg.mockResolvedValue({ data: {} }); + + await action.handler(mockContext); + expect(mockOctokit.rest.repos.createInOrg).toHaveBeenCalledWith({ + description: 'description', + name: 'repo', + org: 'owner', + private: true, + delete_branch_on_merge: false, + allow_squash_merge: true, + allow_merge_commit: true, + allow_rebase_merge: true, + visibility: 'private', + }); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + repoVisibility: 'public', + }, + }); + expect(mockOctokit.rest.repos.createInOrg).toHaveBeenCalledWith({ + description: 'description', + name: 'repo', + org: 'owner', + private: false, + delete_branch_on_merge: false, + allow_squash_merge: true, + allow_merge_commit: true, + allow_rebase_merge: true, + visibility: 'public', + }); + }); + + it('should call the githubApis with the correct values for createForAuthenticatedUser', async () => { + mockOctokit.rest.users.getByUsername.mockResolvedValue({ + data: { type: 'User' }, + }); + + mockOctokit.rest.repos.createForAuthenticatedUser.mockResolvedValue({ + data: {}, + }); + + await action.handler(mockContext); + expect( + mockOctokit.rest.repos.createForAuthenticatedUser, + ).toHaveBeenCalledWith({ + description: 'description', + name: 'repo', + private: true, + delete_branch_on_merge: false, + allow_squash_merge: true, + allow_merge_commit: true, + allow_rebase_merge: true, + }); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + repoVisibility: 'public', + }, + }); + expect( + mockOctokit.rest.repos.createForAuthenticatedUser, + ).toHaveBeenCalledWith({ + description: 'description', + name: 'repo', + private: false, + delete_branch_on_merge: false, + allow_squash_merge: true, + allow_merge_commit: true, + allow_rebase_merge: true, + }); + }); + + it('should add access for the team when it starts with the owner', async () => { + mockOctokit.rest.users.getByUsername.mockResolvedValue({ + data: { type: 'User' }, + }); + + mockOctokit.rest.repos.createForAuthenticatedUser.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + await action.handler(mockContext); + + expect( + mockOctokit.rest.teams.addOrUpdateRepoPermissionsInOrg, + ).toHaveBeenCalledWith({ + org: 'owner', + team_slug: 'blam', + owner: 'owner', + repo: 'repo', + permission: 'admin', + }); + }); + + it('should add outside collaborators when provided', async () => { + mockOctokit.rest.users.getByUsername.mockResolvedValue({ + data: { type: 'User' }, + }); + + mockOctokit.rest.repos.createForAuthenticatedUser.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + access: 'outsidecollaborator', + }, + }); + + expect(mockOctokit.rest.repos.addCollaborator).toHaveBeenCalledWith({ + username: 'outsidecollaborator', + owner: 'owner', + repo: 'repo', + permission: 'admin', + }); + }); + + it('should add multiple collaborators when provided', async () => { + mockOctokit.rest.users.getByUsername.mockResolvedValue({ + data: { type: 'User' }, + }); + + mockOctokit.rest.repos.createForAuthenticatedUser.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + collaborators: [ + { + access: 'pull', + user: 'robot-1', + }, + { + access: 'push', + team: 'robot-2', + }, + ], + }, + }); + + const commonProperties = { + owner: 'owner', + repo: 'repo', + }; + + expect(mockOctokit.rest.repos.addCollaborator).toHaveBeenCalledWith({ + ...commonProperties, + username: 'robot-1', + permission: 'pull', + }); + + expect( + mockOctokit.rest.teams.addOrUpdateRepoPermissionsInOrg, + ).toHaveBeenCalledWith({ + ...commonProperties, + org: 'owner', + team_slug: 'robot-2', + permission: 'push', + }); + }); + + it('should ignore failures when adding multiple collaborators', async () => { + mockOctokit.rest.users.getByUsername.mockResolvedValue({ + data: { type: 'User' }, + }); + + mockOctokit.rest.repos.createForAuthenticatedUser.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + when(mockOctokit.rest.teams.addOrUpdateRepoPermissionsInOrg) + .calledWith({ + org: 'owner', + owner: 'owner', + repo: 'repo', + team_slug: 'robot-1', + permission: 'pull', + }) + .mockRejectedValueOnce(new Error('Something bad happened') as never); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + collaborators: [ + { + access: 'pull', + team: 'robot-1', + }, + { + access: 'push', + team: 'robot-2', + }, + ], + }, + }); + + expect( + mockOctokit.rest.teams.addOrUpdateRepoPermissionsInOrg.mock.calls[2], + ).toEqual([ + { + org: 'owner', + owner: 'owner', + repo: 'repo', + team_slug: 'robot-2', + permission: 'push', + }, + ]); + }); + + it('should add topics when provided', async () => { + mockOctokit.rest.users.getByUsername.mockResolvedValue({ + data: { type: 'User' }, + }); + + mockOctokit.rest.repos.createForAuthenticatedUser.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + mockOctokit.rest.repos.replaceAllTopics.mockResolvedValue({ + data: { + names: ['node.js'], + }, + }); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + topics: ['node.js'], + }, + }); + + expect(mockOctokit.rest.repos.replaceAllTopics).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + names: ['node.js'], + }); + }); + + it('should lowercase topics when provided', async () => { + mockOctokit.rest.users.getByUsername.mockResolvedValue({ + data: { type: 'User' }, + }); + + mockOctokit.rest.repos.createForAuthenticatedUser.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + mockOctokit.rest.repos.replaceAllTopics.mockResolvedValue({ + data: { + names: ['backstage'], + }, + }); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + topics: ['BACKSTAGE'], + }, + }); + + expect(mockOctokit.rest.repos.replaceAllTopics).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + names: ['backstage'], + }); + }); + + it('should call output with the remoteUrl', async () => { + mockOctokit.rest.users.getByUsername.mockResolvedValue({ + data: { type: 'User' }, + }); + + mockOctokit.rest.repos.createForAuthenticatedUser.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + await action.handler(mockContext); + + expect(mockContext.output).toHaveBeenCalledWith( + 'remoteUrl', + 'https://github.com/clone/url.git', + ); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.ts new file mode 100644 index 0000000000..1e92d91a64 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.ts @@ -0,0 +1,151 @@ +/* + * 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 { InputError } from '@backstage/errors'; +import { + GithubCredentialsProvider, + ScmIntegrationRegistry, +} from '@backstage/integration'; +import { Octokit } from 'octokit'; +import { createTemplateAction } from '../../createTemplateAction'; +import { parseRepoUrl } from '../publish/util'; +import { + createGithubRepoWithCollaboratorsAndTopics, + getOctokitOptions, +} from './helpers'; +import * as inputProps from './inputProperties'; +import * as outputProps from './outputProperties'; + +/** + * Creates a new action that initializes a git repository + * + * @public + */ +export function createGithubRepoCreateAction(options: { + integrations: ScmIntegrationRegistry; + githubCredentialsProvider?: GithubCredentialsProvider; +}) { + const { integrations, githubCredentialsProvider } = options; + + return createTemplateAction<{ + repoUrl: string; + description?: string; + access?: string; + deleteBranchOnMerge?: boolean; + gitAuthorName?: string; + gitAuthorEmail?: string; + allowRebaseMerge?: boolean; + allowSquashMerge?: boolean; + allowMergeCommit?: boolean; + requireCodeOwnerReviews?: boolean; + requiredStatusCheckContexts?: string[]; + repoVisibility?: 'private' | 'internal' | 'public'; + collaborators?: Array< + | { + user: string; + access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; + } + | { + team: string; + access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; + } + | { + /** @deprecated This field is deprecated in favor of team */ + username: string; + access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; + } + >; + token?: string; + topics?: string[]; + }>({ + id: 'github:repo:create', + description: 'Creates a GitHub repository.', + schema: { + input: { + type: 'object', + required: ['repoUrl'], + properties: { + repoUrl: inputProps.repoUrl, + description: inputProps.description, + access: inputProps.access, + requireCodeOwnerReviews: inputProps.requireCodeOwnerReviews, + requiredStatusCheckContexts: inputProps.requiredStatusCheckContexts, + repoVisibility: inputProps.repoVisibility, + deleteBranchOnMerge: inputProps.deleteBranchOnMerge, + allowMergeCommit: inputProps.allowMergeCommit, + allowSquashMerge: inputProps.allowSquashMerge, + allowRebaseMerge: inputProps.allowRebaseMerge, + collaborators: inputProps.collaborators, + token: inputProps.token, + topics: inputProps.topics, + }, + }, + output: { + type: 'object', + properties: { + remoteUrl: outputProps.remoteUrl, + repoContentsUrl: outputProps.repoContentsUrl, + }, + }, + }, + async handler(ctx) { + const { + repoUrl, + description, + access, + repoVisibility = 'private', + deleteBranchOnMerge = false, + allowMergeCommit = true, + allowSquashMerge = true, + allowRebaseMerge = true, + collaborators, + topics, + token: providedToken, + } = ctx.input; + + const octokitOptions = await getOctokitOptions({ + integrations, + credentialsProvider: githubCredentialsProvider, + token: providedToken, + repoUrl: repoUrl, + }); + const client = new Octokit(octokitOptions); + + const { owner, repo } = parseRepoUrl(repoUrl, integrations); + + if (!owner) { + throw new InputError('Invalid repository owner provided in repoUrl'); + } + + const newRepo = await createGithubRepoWithCollaboratorsAndTopics( + client, + repo, + owner, + repoVisibility, + description, + deleteBranchOnMerge, + allowMergeCommit, + allowSquashMerge, + allowRebaseMerge, + access, + collaborators, + topics, + ctx.logger, + ); + + ctx.output('remoteUrl', newRepo.clone_url); + }, + }); +} diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoPush.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoPush.test.ts new file mode 100644 index 0000000000..f23e3dde9f --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoPush.test.ts @@ -0,0 +1,400 @@ +/* + * 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 { TemplateAction } from '../../types'; + +jest.mock('../helpers'); + +import { getVoidLogger } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { + DefaultGithubCredentialsProvider, + GithubCredentialsProvider, + ScmIntegrations, +} from '@backstage/integration'; +import { PassThrough } from 'stream'; +import { + enableBranchProtectionOnDefaultRepoBranch, + initRepoAndPush, +} from '../helpers'; +import { createGithubRepoPushAction } from './githubRepoPush'; + +const mockOctokit = { + rest: { + repos: { + get: jest.fn(), + }, + }, +}; +jest.mock('octokit', () => ({ + Octokit: class { + constructor() { + return mockOctokit; + } + }, +})); + +describe('github:repo:push', () => { + const config = new ConfigReader({ + integrations: { + github: [ + { host: 'github.com', token: 'tokenlols' }, + { host: 'ghe.github.com' }, + ], + }, + }); + + const integrations = ScmIntegrations.fromConfig(config); + let githubCredentialsProvider: GithubCredentialsProvider; + let action: TemplateAction; + + const mockContext = { + input: { + repoUrl: 'github.com?repo=repository&owner=owner', + description: 'description', + repoVisibility: 'private' as const, + access: 'owner/blam', + }, + workspacePath: 'lol', + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + + beforeEach(() => { + jest.resetAllMocks(); + githubCredentialsProvider = + DefaultGithubCredentialsProvider.fromIntegrations(integrations); + action = createGithubRepoPushAction({ + integrations, + config, + githubCredentialsProvider, + }); + }); + + it('should call initRepoAndPush with the correct values', async () => { + mockOctokit.rest.repos.get.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + await action.handler(mockContext); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContext.workspacePath, + remoteUrl: 'https://github.com/clone/url.git', + defaultBranch: 'master', + auth: { username: 'x-access-token', password: 'tokenlols' }, + logger: mockContext.logger, + commitMessage: 'initial commit', + gitAuthorInfo: {}, + }); + }); + + it('should call initRepoAndPush with the correct defaultBranch main', async () => { + mockOctokit.rest.repos.get.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + defaultBranch: 'main', + }, + }); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContext.workspacePath, + remoteUrl: 'https://github.com/clone/url.git', + defaultBranch: 'main', + auth: { username: 'x-access-token', password: 'tokenlols' }, + logger: mockContext.logger, + commitMessage: 'initial commit', + gitAuthorInfo: {}, + }); + }); + + it('should call initRepoAndPush with the configured defaultAuthor', async () => { + const customAuthorConfig = new ConfigReader({ + integrations: { + github: [ + { host: 'github.com', token: 'tokenlols' }, + { host: 'ghe.github.com' }, + ], + }, + scaffolder: { + defaultAuthor: { + name: 'Test', + email: 'example@example.com', + }, + }, + }); + + const customAuthorIntegrations = + ScmIntegrations.fromConfig(customAuthorConfig); + const customAuthorAction = createGithubRepoPushAction({ + integrations: customAuthorIntegrations, + config: customAuthorConfig, + githubCredentialsProvider, + }); + + mockOctokit.rest.repos.get.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + await customAuthorAction.handler(mockContext); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContext.workspacePath, + remoteUrl: 'https://github.com/clone/url.git', + defaultBranch: 'master', + auth: { username: 'x-access-token', password: 'tokenlols' }, + logger: mockContext.logger, + commitMessage: 'initial commit', + gitAuthorInfo: { name: 'Test', email: 'example@example.com' }, + }); + }); + + it('should call initRepoAndPush with the configured defaultCommitMessage', async () => { + const customAuthorConfig = new ConfigReader({ + integrations: { + github: [ + { host: 'github.com', token: 'tokenlols' }, + { host: 'ghe.github.com' }, + ], + }, + scaffolder: { + defaultCommitMessage: 'Test commit message', + }, + }); + + const customAuthorIntegrations = + ScmIntegrations.fromConfig(customAuthorConfig); + const customAuthorAction = createGithubRepoPushAction({ + integrations: customAuthorIntegrations, + config: customAuthorConfig, + githubCredentialsProvider, + }); + + mockOctokit.rest.repos.get.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + await customAuthorAction.handler(mockContext); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContext.workspacePath, + remoteUrl: 'https://github.com/clone/url.git', + defaultBranch: 'master', + auth: { username: 'x-access-token', password: 'tokenlols' }, + logger: mockContext.logger, + commitMessage: 'initial commit', + gitAuthorInfo: { email: undefined, name: undefined }, + }); + }); + + it('should call output with the remoteUrl and the repoContentsUrl', async () => { + mockOctokit.rest.repos.get.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + await action.handler(mockContext); + + expect(mockContext.output).toHaveBeenCalledWith( + 'remoteUrl', + 'https://github.com/clone/url.git', + ); + expect(mockContext.output).toHaveBeenCalledWith( + 'repoContentsUrl', + 'https://github.com/html/url/blob/master', + ); + }); + + it('should use main as default branch', async () => { + mockOctokit.rest.repos.get.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + defaultBranch: 'main', + }, + }); + + expect(mockContext.output).toHaveBeenCalledWith( + 'remoteUrl', + 'https://github.com/clone/url.git', + ); + expect(mockContext.output).toHaveBeenCalledWith( + 'repoContentsUrl', + 'https://github.com/html/url/blob/main', + ); + }); + + it('should call enableBranchProtectionOnDefaultRepoBranch with the correct values of requireCodeOwnerReviews', async () => { + mockOctokit.rest.repos.get.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + await action.handler(mockContext); + + expect(enableBranchProtectionOnDefaultRepoBranch).toHaveBeenCalledWith({ + owner: 'owner', + client: mockOctokit, + repoName: 'repository', + logger: mockContext.logger, + defaultBranch: 'master', + requireCodeOwnerReviews: false, + requiredStatusCheckContexts: [], + }); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + requireCodeOwnerReviews: true, + }, + }); + + expect(enableBranchProtectionOnDefaultRepoBranch).toHaveBeenCalledWith({ + owner: 'owner', + client: mockOctokit, + repoName: 'repository', + logger: mockContext.logger, + defaultBranch: 'master', + requireCodeOwnerReviews: true, + requiredStatusCheckContexts: [], + }); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + requireCodeOwnerReviews: false, + }, + }); + + expect(enableBranchProtectionOnDefaultRepoBranch).toHaveBeenCalledWith({ + owner: 'owner', + client: mockOctokit, + repoName: 'repository', + logger: mockContext.logger, + defaultBranch: 'master', + requireCodeOwnerReviews: false, + requiredStatusCheckContexts: [], + }); + }); + + it('should call enableBranchProtectionOnDefaultRepoBranch with the correct values of requiredStatusCheckContexts', async () => { + mockOctokit.rest.repos.get.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + await action.handler(mockContext); + + expect(enableBranchProtectionOnDefaultRepoBranch).toHaveBeenCalledWith({ + owner: 'owner', + client: mockOctokit, + repoName: 'repository', + logger: mockContext.logger, + defaultBranch: 'master', + requireCodeOwnerReviews: false, + requiredStatusCheckContexts: [], + }); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + requiredStatusCheckContexts: ['statusCheck'], + }, + }); + + expect(enableBranchProtectionOnDefaultRepoBranch).toHaveBeenCalledWith({ + owner: 'owner', + client: mockOctokit, + repoName: 'repository', + logger: mockContext.logger, + defaultBranch: 'master', + requireCodeOwnerReviews: false, + requiredStatusCheckContexts: ['statusCheck'], + }); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + requiredStatusCheckContexts: [], + }, + }); + + expect(enableBranchProtectionOnDefaultRepoBranch).toHaveBeenCalledWith({ + owner: 'owner', + client: mockOctokit, + repoName: 'repository', + logger: mockContext.logger, + defaultBranch: 'master', + requireCodeOwnerReviews: false, + requiredStatusCheckContexts: [], + }); + }); + + it('should not call enableBranchProtectionOnDefaultRepoBranch with protectDefaultBranch disabled', async () => { + mockOctokit.rest.repos.get.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + protectDefaultBranch: false, + }, + }); + + expect(enableBranchProtectionOnDefaultRepoBranch).not.toHaveBeenCalled(); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoPush.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoPush.ts new file mode 100644 index 0000000000..942ebe578d --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoPush.ts @@ -0,0 +1,139 @@ +/* + * 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 { Config } from '@backstage/config'; +import { InputError } from '@backstage/errors'; +import { + GithubCredentialsProvider, + ScmIntegrationRegistry, +} from '@backstage/integration'; +import { Octokit } from 'octokit'; +import { createTemplateAction } from '../../createTemplateAction'; +import { parseRepoUrl } from '../publish/util'; +import { getOctokitOptions, initRepoPushAndProtect } from './helpers'; +import * as inputProps from './inputProperties'; +import * as outputProps from './outputProperties'; + +/** + * Creates a new action that initializes a git repository of the content in the workspace + * and publishes it to GitHub. + * + * @public + */ +export function createGithubRepoPushAction(options: { + integrations: ScmIntegrationRegistry; + config: Config; + githubCredentialsProvider?: GithubCredentialsProvider; +}) { + const { integrations, config, githubCredentialsProvider } = options; + + return createTemplateAction<{ + repoUrl: string; + description?: string; + defaultBranch?: string; + protectDefaultBranch?: boolean; + gitCommitMessage?: string; + gitAuthorName?: string; + gitAuthorEmail?: string; + requireCodeOwnerReviews?: boolean; + requiredStatusCheckContexts?: string[]; + sourcePath?: string; + token?: string; + }>({ + id: 'github:repo:push', + description: + 'Initializes a git repository of contents in workspace and publishes it to GitHub.', + schema: { + input: { + type: 'object', + required: ['repoUrl'], + properties: { + repoUrl: inputProps.repoUrl, + requireCodeOwnerReviews: inputProps.requireCodeOwnerReviews, + requiredStatusCheckContexts: inputProps.requiredStatusCheckContexts, + defaultBranch: inputProps.defaultBranch, + protectDefaultBranch: inputProps.protectDefaultBranch, + gitCommitMessage: inputProps.gitCommitMessage, + gitAuthorName: inputProps.gitAuthorName, + gitAuthorEmail: inputProps.gitAuthorEmail, + sourcePath: inputProps.sourcePath, + token: inputProps.token, + }, + }, + output: { + type: 'object', + properties: { + remoteUrl: outputProps.remoteUrl, + repoContentsUrl: outputProps.repoContentsUrl, + }, + }, + }, + async handler(ctx) { + const { + repoUrl, + defaultBranch = 'master', + protectDefaultBranch = true, + gitCommitMessage = 'initial commit', + gitAuthorName, + gitAuthorEmail, + requireCodeOwnerReviews = false, + requiredStatusCheckContexts = [], + token: providedToken, + } = ctx.input; + + const { owner, repo } = parseRepoUrl(repoUrl, integrations); + + if (!owner) { + throw new InputError('Invalid repository owner provided in repoUrl'); + } + + const octokitOptions = await getOctokitOptions({ + integrations, + credentialsProvider: githubCredentialsProvider, + token: providedToken, + repoUrl, + }); + + const client = new Octokit(octokitOptions); + + const targetRepo = await client.rest.repos.get({ owner, repo }); + + const remoteUrl = targetRepo.data.clone_url; + const repoContentsUrl = `${targetRepo.data.html_url}/blob/${defaultBranch}`; + + await initRepoPushAndProtect( + remoteUrl, + octokitOptions.auth, + ctx.workspacePath, + ctx.input.sourcePath, + defaultBranch, + protectDefaultBranch, + owner, + client, + repo, + requireCodeOwnerReviews, + requiredStatusCheckContexts, + config, + ctx.logger, + gitCommitMessage, + gitAuthorName, + gitAuthorEmail, + ); + + ctx.output('remoteUrl', remoteUrl); + ctx.output('repoContentsUrl', repoContentsUrl); + }, + }); +} diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts index 29997e5843..c8f508e4c0 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts @@ -13,14 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { InputError } from '@backstage/errors'; +import { Config } from '@backstage/config'; +import { assertError, InputError } from '@backstage/errors'; import { DefaultGithubCredentialsProvider, GithubCredentialsProvider, ScmIntegrationRegistry, } from '@backstage/integration'; import { OctokitOptions } from '@octokit/core/dist-types/types'; -import { parseRepoUrl } from '../publish/util'; +import { Octokit } from 'octokit'; +import { Logger } from 'winston'; +import { + enableBranchProtectionOnDefaultRepoBranch, + initRepoAndPush, +} from '../helpers'; +import { getRepoSourceDirectory, parseRepoUrl } from '../publish/util'; const DEFAULT_TIMEOUT_MS = 60_000; @@ -83,3 +90,213 @@ export async function getOctokitOptions(options: { previews: ['nebula-preview'], }; } + +export async function createGithubRepoWithCollaboratorsAndTopics( + client: Octokit, + repo: string, + owner: string, + repoVisibility: 'private' | 'internal' | 'public', + description: string | undefined, + deleteBranchOnMerge: boolean, + allowMergeCommit: boolean, + allowSquashMerge: boolean, + allowRebaseMerge: boolean, + access: string | undefined, + collaborators: + | ( + | { + user: string; + access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; + } + | { + team: string; + access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; + } + | { + /** @deprecated This field is deprecated in favor of team */ + username: string; + access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; + } + )[] + | undefined, + topics: string[] | undefined, + logger: Logger, +) { + const user = await client.rest.users.getByUsername({ + username: owner, + }); + + const repoCreationPromise = + user.data.type === 'Organization' + ? client.rest.repos.createInOrg({ + name: repo, + org: owner, + private: repoVisibility === 'private', + visibility: repoVisibility, + description: description, + delete_branch_on_merge: deleteBranchOnMerge, + allow_merge_commit: allowMergeCommit, + allow_squash_merge: allowSquashMerge, + allow_rebase_merge: allowRebaseMerge, + }) + : client.rest.repos.createForAuthenticatedUser({ + name: repo, + private: repoVisibility === 'private', + description: description, + delete_branch_on_merge: deleteBranchOnMerge, + allow_merge_commit: allowMergeCommit, + allow_squash_merge: allowSquashMerge, + allow_rebase_merge: allowRebaseMerge, + }); + + let newRepo; + + try { + newRepo = (await repoCreationPromise).data; + } catch (e) { + assertError(e); + if (e.message === 'Resource not accessible by integration') { + logger.warn( + `The GitHub app or token provided may not have the required permissions to create the ${user.data.type} repository ${owner}/${repo}.`, + ); + } + throw new Error( + `Failed to create the ${user.data.type} repository ${owner}/${repo}, ${e.message}`, + ); + } + + if (access?.startsWith(`${owner}/`)) { + const [, team] = access.split('/'); + await client.rest.teams.addOrUpdateRepoPermissionsInOrg({ + org: owner, + team_slug: team, + owner, + repo, + permission: 'admin', + }); + // No need to add access if it's the person who owns the personal account + } else if (access && access !== owner) { + await client.rest.repos.addCollaborator({ + owner, + repo, + username: access, + permission: 'admin', + }); + } + + if (collaborators) { + for (const collaborator of collaborators) { + try { + if ('user' in collaborator) { + await client.rest.repos.addCollaborator({ + owner, + repo, + username: collaborator.user, + permission: collaborator.access, + }); + } else if ('team' in collaborator) { + await client.rest.teams.addOrUpdateRepoPermissionsInOrg({ + org: owner, + team_slug: collaborator.team, + owner, + repo, + permission: collaborator.access, + }); + } + } catch (e) { + assertError(e); + const name = extractCollaboratorName(collaborator); + logger.warn( + `Skipping ${collaborator.access} access for ${name}, ${e.message}`, + ); + } + } + } + + if (topics) { + try { + await client.rest.repos.replaceAllTopics({ + owner, + repo, + names: topics.map(t => t.toLowerCase()), + }); + } catch (e) { + assertError(e); + logger.warn(`Skipping topics ${topics.join(' ')}, ${e.message}`); + } + } + + return newRepo; +} + +export async function initRepoPushAndProtect( + remoteUrl: string, + password: string, + workspacePath: string, + sourcePath: string | undefined, + defaultBranch: string, + protectDefaultBranch: boolean, + owner: string, + client: Octokit, + repo: string, + requireCodeOwnerReviews: boolean, + requiredStatusCheckContexts: string[], + config: Config, + logger: any, + gitCommitMessage?: string, + gitAuthorName?: string, + gitAuthorEmail?: string, +) { + const gitAuthorInfo = { + name: gitAuthorName + ? gitAuthorName + : config.getOptionalString('scaffolder.defaultAuthor.name'), + email: gitAuthorEmail + ? gitAuthorEmail + : config.getOptionalString('scaffolder.defaultAuthor.email'), + }; + + const commitMessage = gitCommitMessage + ? gitCommitMessage + : config.getOptionalString('scaffolder.defaultCommitMessage'); + + await initRepoAndPush({ + dir: getRepoSourceDirectory(workspacePath, sourcePath), + remoteUrl, + defaultBranch, + auth: { + username: 'x-access-token', + password, + }, + logger, + commitMessage, + gitAuthorInfo, + }); + + if (protectDefaultBranch) { + try { + await enableBranchProtectionOnDefaultRepoBranch({ + owner, + client, + repoName: repo, + logger, + defaultBranch, + requireCodeOwnerReviews, + requiredStatusCheckContexts, + }); + } catch (e) { + assertError(e); + logger.warn( + `Skipping: default branch protection on '${repo}', ${e.message}`, + ); + } + } +} + +function extractCollaboratorName( + collaborator: { user: string } | { team: string } | { username: string }, +) { + if ('username' in collaborator) return collaborator.username; + if ('user' in collaborator) return collaborator.user; + return collaborator.team; +} diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/index.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/index.ts index c5788afc3a..6746aef37e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/index.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/index.ts @@ -15,5 +15,7 @@ */ export { createGithubActionsDispatchAction } from './githubActionsDispatch'; -export { createGithubWebhookAction } from './githubWebhook'; export { createGithubIssuesLabelAction } from './githubIssuesLabel'; +export { createGithubRepoCreateAction } from './githubRepoCreate'; +export { createGithubRepoPushAction } from './githubRepoPush'; +export { createGithubWebhookAction } from './githubWebhook'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/inputProperties.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/inputProperties.ts new file mode 100644 index 0000000000..0aad402f1f --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/inputProperties.ts @@ -0,0 +1,161 @@ +/* + * 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. + */ + +const repoUrl = { + title: 'Repository Location', + description: `Accepts the format 'github.com?repo=reponame&owner=owner' where 'reponame' is the new repository name and 'owner' is an organization or username`, + type: 'string', +}; +const description = { + title: 'Repository Description', + type: 'string', +}; +const access = { + title: 'Repository Access', + description: `Sets an admin collaborator on the repository. Can either be a user reference different from 'owner' in 'repoUrl' or team reference, eg. 'org/team-name'`, + type: 'string', +}; +const requireCodeOwnerReviews = { + title: 'Require CODEOWNER Reviews?', + description: + 'Require an approved review in PR including files with a designated Code Owner', + type: 'boolean', +}; +const requiredStatusCheckContexts = { + title: 'Required Status Check Contexts', + description: + 'The list of status checks to require in order to merge into this branch', + type: 'array', + items: { + type: 'string', + }, +}; +const repoVisibility = { + title: 'Repository Visibility', + type: 'string', + enum: ['private', 'public', 'internal'], +}; +const deleteBranchOnMerge = { + title: 'Delete Branch On Merge', + type: 'boolean', + description: `Delete the branch after merging the PR. The default value is 'false'`, +}; +const gitAuthorName = { + title: 'Default Author Name', + type: 'string', + description: `Sets the default author name for the commit. The default value is 'Scaffolder'`, +}; +const gitAuthorEmail = { + title: 'Default Author Email', + type: 'string', + description: `Sets the default author email for the commit.`, +}; +const allowMergeCommit = { + title: 'Allow Merge Commits', + type: 'boolean', + description: `Allow merge commits. The default value is 'true'`, +}; +const allowSquashMerge = { + title: 'Allow Squash Merges', + type: 'boolean', + description: `Allow squash merges. The default value is 'true'`, +}; +const allowRebaseMerge = { + title: 'Allow Rebase Merges', + type: 'boolean', + description: `Allow rebase merges. The default value is 'true'`, +}; +const collaborators = { + title: 'Collaborators', + description: 'Provide additional users or teams with permissions', + type: 'array', + items: { + type: 'object', + additionalProperties: false, + required: ['access'], + properties: { + access: { + type: 'string', + description: 'The type of access for the user', + enum: ['push', 'pull', 'admin', 'maintain', 'triage'], + }, + user: { + type: 'string', + description: + 'The name of the user that will be added as a collaborator', + }, + team: { + type: 'string', + description: + 'The name of the team that will be added as a collaborator', + }, + }, + oneOf: [{ required: ['user'] }, { required: ['team'] }], + }, +}; +const token = { + title: 'Authentication Token', + type: 'string', + description: 'The token to use for authorization to GitHub', +}; +const topics = { + title: 'Topics', + type: 'array', + items: { + type: 'string', + }, +}; +const defaultBranch = { + title: 'Default Branch', + type: 'string', + description: `Sets the default branch on the repository. The default value is 'master'`, +}; +const protectDefaultBranch = { + title: 'Protect Default Branch', + type: 'boolean', + description: `Protect the default branch after creating the repository. The default value is 'true'`, +}; +const gitCommitMessage = { + title: 'Git Commit Message', + type: 'string', + description: `Sets the commit message on the repository. The default value is 'initial commit'`, +}; +const sourcePath = { + 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', +}; + +export { access }; +export { allowMergeCommit }; +export { allowRebaseMerge }; +export { allowSquashMerge }; +export { collaborators }; +export { defaultBranch }; +export { deleteBranchOnMerge }; +export { description }; +export { gitAuthorEmail }; +export { gitAuthorName }; +export { gitCommitMessage }; +export { protectDefaultBranch }; +export { repoUrl }; +export { repoVisibility }; +export { requireCodeOwnerReviews }; +export { requiredStatusCheckContexts }; +export { sourcePath }; +export { token }; +export { topics }; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/outputProperties.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/outputProperties.ts new file mode 100644 index 0000000000..d5d6eb108f --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/outputProperties.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. + */ + +const remoteUrl = { + title: 'A URL to the repository with the provider', + type: 'string', +}; +const repoContentsUrl = { + title: 'A URL to the root of the repository', + type: 'string', +}; + +export { remoteUrl }; +export { repoContentsUrl }; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts index 529a504cba..8753d44041 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts @@ -14,12 +14,13 @@ * limitations under the License. */ -import { SpawnOptionsWithoutStdio, spawn } from 'child_process'; +import { Git } from '@backstage/backend-common'; +import { Config } from '@backstage/config'; +import { assertError } from '@backstage/errors'; +import { spawn, SpawnOptionsWithoutStdio } from 'child_process'; +import { Octokit } from 'octokit'; import { PassThrough, Writable } from 'stream'; import { Logger } from 'winston'; -import { Git } from '@backstage/backend-common'; -import { Octokit } from 'octokit'; -import { assertError } from '@backstage/errors'; /** @public */ export type RunCommandOptions = { @@ -200,3 +201,12 @@ export const enableBranchProtectionOnDefaultRepoBranch = async ({ await tryOnce(); } }; + +export function getGitCommitMessage( + gitCommitMessage: string | undefined, + config: Config, +): string | undefined { + return gitCommitMessage + ? gitCommitMessage + : config.getOptionalString('scaffolder.defaultCommitMessage'); +} diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts index ff20d1014b..036c5d66ee 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts @@ -18,20 +18,20 @@ import { TemplateAction } from '../../types'; jest.mock('../helpers'); -import { createPublishGithubAction } from './github'; +import { getVoidLogger } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; import { - ScmIntegrations, DefaultGithubCredentialsProvider, GithubCredentialsProvider, + ScmIntegrations, } from '@backstage/integration'; -import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; +import { when } from 'jest-when'; import { PassThrough } from 'stream'; import { enableBranchProtectionOnDefaultRepoBranch, initRepoAndPush, } from '../helpers'; -import { when } from 'jest-when'; +import { createPublishGithubAction } from './github'; const mockOctokit = { rest: { @@ -609,7 +609,7 @@ describe('publish:github', () => { mockOctokit.rest.repos.createForAuthenticatedUser.mockResolvedValue({ data: { - name: 'repository', + name: 'repo', }, }); @@ -618,7 +618,7 @@ describe('publish:github', () => { expect(enableBranchProtectionOnDefaultRepoBranch).toHaveBeenCalledWith({ owner: 'owner', client: mockOctokit, - repoName: 'repository', + repoName: 'repo', logger: mockContext.logger, defaultBranch: 'master', requireCodeOwnerReviews: false, @@ -636,7 +636,7 @@ describe('publish:github', () => { expect(enableBranchProtectionOnDefaultRepoBranch).toHaveBeenCalledWith({ owner: 'owner', client: mockOctokit, - repoName: 'repository', + repoName: 'repo', logger: mockContext.logger, defaultBranch: 'master', requireCodeOwnerReviews: true, @@ -654,7 +654,7 @@ describe('publish:github', () => { expect(enableBranchProtectionOnDefaultRepoBranch).toHaveBeenCalledWith({ owner: 'owner', client: mockOctokit, - repoName: 'repository', + repoName: 'repo', logger: mockContext.logger, defaultBranch: 'master', requireCodeOwnerReviews: false, @@ -669,7 +669,7 @@ describe('publish:github', () => { mockOctokit.rest.repos.createForAuthenticatedUser.mockResolvedValue({ data: { - name: 'repository', + name: 'repo', }, }); @@ -678,7 +678,7 @@ describe('publish:github', () => { expect(enableBranchProtectionOnDefaultRepoBranch).toHaveBeenCalledWith({ owner: 'owner', client: mockOctokit, - repoName: 'repository', + repoName: 'repo', logger: mockContext.logger, defaultBranch: 'master', requireCodeOwnerReviews: false, @@ -696,7 +696,7 @@ describe('publish:github', () => { expect(enableBranchProtectionOnDefaultRepoBranch).toHaveBeenCalledWith({ owner: 'owner', client: mockOctokit, - repoName: 'repository', + repoName: 'repo', logger: mockContext.logger, defaultBranch: 'master', requireCodeOwnerReviews: false, @@ -714,7 +714,7 @@ describe('publish:github', () => { expect(enableBranchProtectionOnDefaultRepoBranch).toHaveBeenCalledWith({ owner: 'owner', client: mockOctokit, - repoName: 'repository', + repoName: 'repo', logger: mockContext.logger, defaultBranch: 'master', requireCodeOwnerReviews: false, @@ -729,7 +729,7 @@ describe('publish:github', () => { mockOctokit.rest.repos.createForAuthenticatedUser.mockResolvedValue({ data: { - name: 'repository', + name: 'repo', }, }); 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 d9a7112fc9..0815a2cd00 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts @@ -13,21 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { Config } from '@backstage/config'; +import { InputError } from '@backstage/errors'; import { GithubCredentialsProvider, ScmIntegrationRegistry, } from '@backstage/integration'; -import { - enableBranchProtectionOnDefaultRepoBranch, - initRepoAndPush, -} from '../helpers'; -import { getRepoSourceDirectory, parseRepoUrl } from './util'; -import { createTemplateAction } from '../../createTemplateAction'; -import { Config } from '@backstage/config'; -import { assertError, InputError } from '@backstage/errors'; -import { getOctokitOptions } from '../github/helpers'; import { Octokit } from 'octokit'; - +import { createTemplateAction } from '../../createTemplateAction'; +import { + createGithubRepoWithCollaboratorsAndTopics, + getOctokitOptions, + initRepoPushAndProtect, +} from '../github/helpers'; +import * as inputProps from '../github/inputProperties'; +import * as outputProps from '../github/outputProperties'; +import { parseRepoUrl } from './util'; /** * Creates a new action that initializes a git repository of the content in the workspace * and publishes it to GitHub. @@ -84,153 +85,32 @@ export function createPublishGithubAction(options: { type: 'object', required: ['repoUrl'], properties: { - repoUrl: { - title: 'Repository Location', - description: `Accepts the format 'github.com?repo=reponame&owner=owner' where 'reponame' is the new repository name and 'owner' is an organization or username`, - type: 'string', - }, - description: { - title: 'Repository Description', - type: 'string', - }, - access: { - title: 'Repository Access', - description: `Sets an admin collaborator on the repository. Can either be a user reference different from 'owner' in 'repoUrl' or team reference, eg. 'org/team-name'`, - type: 'string', - }, - requireCodeOwnerReviews: { - title: 'Require CODEOWNER Reviews?', - description: - 'Require an approved review in PR including files with a designated Code Owner', - type: 'boolean', - }, - requiredStatusCheckContexts: { - title: 'Required Status Check Contexts', - description: - 'The list of status checks to require in order to merge into this branch', - type: 'array', - items: { - type: 'string', - }, - }, - repoVisibility: { - title: 'Repository Visibility', - type: 'string', - enum: ['private', 'public', 'internal'], - }, - defaultBranch: { - title: 'Default Branch', - type: 'string', - description: `Sets the default branch on the repository. The default value is 'master'`, - }, - protectDefaultBranch: { - title: 'Protect Default Branch', - type: 'boolean', - description: `Protect the default branch after creating the repository. The default value is 'true'`, - }, - deleteBranchOnMerge: { - title: 'Delete Branch On Merge', - type: 'boolean', - description: `Delete the branch after merging the PR. The default value is 'false'`, - }, - gitCommitMessage: { - title: 'Git Commit Message', - type: 'string', - description: `Sets the commit message on the repository. The default value is 'initial commit'`, - }, - gitAuthorName: { - title: 'Default Author Name', - type: 'string', - description: `Sets the default author name for the commit. The default value is 'Scaffolder'`, - }, - gitAuthorEmail: { - title: 'Default Author Email', - type: 'string', - description: `Sets the default author email for the commit.`, - }, - allowMergeCommit: { - title: 'Allow Merge Commits', - type: 'boolean', - description: `Allow merge commits. The default value is 'true'`, - }, - allowSquashMerge: { - title: 'Allow Squash Merges', - type: 'boolean', - description: `Allow squash merges. The default value is 'true'`, - }, - allowRebaseMerge: { - title: 'Allow Rebase Merges', - type: 'boolean', - description: `Allow rebase merges. The default value is 'true'`, - }, - sourcePath: { - 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', - }, - collaborators: { - title: 'Collaborators', - description: 'Provide additional users or teams with permissions', - type: 'array', - items: { - type: 'object', - additionalProperties: false, - required: ['access'], - properties: { - access: { - type: 'string', - description: 'The type of access for the user', - enum: ['push', 'pull', 'admin', 'maintain', 'triage'], - }, - user: { - type: 'string', - description: - 'The name of the user that will be added as a collaborator', - }, - username: { - type: 'string', - description: - 'Deprecated. Use the `team` or `user` field instead.', - }, - team: { - type: 'string', - description: - 'The name of the team that will be added as a collaborator', - }, - }, - oneOf: [ - { required: ['user'] }, - { required: ['username'] }, - { required: ['team'] }, - ], - }, - }, - token: { - title: 'Authentication Token', - type: 'string', - description: 'The token to use for authorization to GitHub', - }, - topics: { - title: 'Topics', - type: 'array', - items: { - type: 'string', - }, - }, + repoUrl: inputProps.repoUrl, + description: inputProps.description, + access: inputProps.access, + requireCodeOwnerReviews: inputProps.requireCodeOwnerReviews, + requiredStatusCheckContexts: inputProps.requiredStatusCheckContexts, + repoVisibility: inputProps.repoVisibility, + defaultBranch: inputProps.defaultBranch, + protectDefaultBranch: inputProps.protectDefaultBranch, + deleteBranchOnMerge: inputProps.deleteBranchOnMerge, + gitCommitMessage: inputProps.gitCommitMessage, + gitAuthorName: inputProps.gitAuthorName, + gitAuthorEmail: inputProps.gitAuthorEmail, + allowMergeCommit: inputProps.allowMergeCommit, + allowSquashMerge: inputProps.allowSquashMerge, + allowRebaseMerge: inputProps.allowRebaseMerge, + sourcePath: inputProps.sourcePath, + collaborators: inputProps.collaborators, + token: inputProps.token, + topics: inputProps.topics, }, }, output: { type: 'object', properties: { - remoteUrl: { - title: 'A URL to the repository with the provider', - type: 'string', - }, - repoContentsUrl: { - title: 'A URL to the root of the repository', - type: 'string', - }, + remoteUrl: outputProps.remoteUrl, + repoContentsUrl: outputProps.repoContentsUrl, }, }, }, @@ -256,192 +136,60 @@ export function createPublishGithubAction(options: { token: providedToken, } = ctx.input; + const octokitOptions = await getOctokitOptions({ + integrations, + credentialsProvider: githubCredentialsProvider, + token: providedToken, + repoUrl: repoUrl, + }); + const client = new Octokit(octokitOptions); + const { owner, repo } = parseRepoUrl(repoUrl, integrations); if (!owner) { throw new InputError('Invalid repository owner provided in repoUrl'); } - const octokitOptions = await getOctokitOptions({ - integrations, - credentialsProvider: githubCredentialsProvider, - token: providedToken, - repoUrl, - }); - - const client = new Octokit(octokitOptions); - - const user = await client.rest.users.getByUsername({ - username: owner, - }); - - const repoCreationPromise = - user.data.type === 'Organization' - ? client.rest.repos.createInOrg({ - name: repo, - org: owner, - private: repoVisibility === 'private', - visibility: repoVisibility, - description: description, - delete_branch_on_merge: deleteBranchOnMerge, - allow_merge_commit: allowMergeCommit, - allow_squash_merge: allowSquashMerge, - allow_rebase_merge: allowRebaseMerge, - }) - : client.rest.repos.createForAuthenticatedUser({ - name: repo, - private: repoVisibility === 'private', - description: description, - delete_branch_on_merge: deleteBranchOnMerge, - allow_merge_commit: allowMergeCommit, - allow_squash_merge: allowSquashMerge, - allow_rebase_merge: allowRebaseMerge, - }); - - let newRepo; - - try { - newRepo = (await repoCreationPromise).data; - } catch (e) { - assertError(e); - if (e.message === 'Resource not accessible by integration') { - ctx.logger.warn( - `The GitHub app or token provided may not have the required permissions to create the ${user.data.type} repository ${owner}/${repo}.`, - ); - } - throw new Error( - `Failed to create the ${user.data.type} repository ${owner}/${repo}, ${e.message}`, - ); - } - - if (access?.startsWith(`${owner}/`)) { - const [, team] = access.split('/'); - await client.rest.teams.addOrUpdateRepoPermissionsInOrg({ - org: owner, - team_slug: team, - owner, - repo, - permission: 'admin', - }); - // No need to add access if it's the person who owns the personal account - } else if (access && access !== owner) { - await client.rest.repos.addCollaborator({ - owner, - repo, - username: access, - permission: 'admin', - }); - } - - if (collaborators) { - for (const collaborator of collaborators) { - try { - if ('user' in collaborator) { - await client.rest.repos.addCollaborator({ - owner, - repo, - username: collaborator.user, - permission: collaborator.access, - }); - } else if ('username' in collaborator) { - ctx.logger.warn( - 'The field `username` is deprecated in favor of `team` and will be removed in the future.', - ); - await client.rest.teams.addOrUpdateRepoPermissionsInOrg({ - org: owner, - team_slug: collaborator.username, - owner, - repo, - permission: collaborator.access, - }); - } else if ('team' in collaborator) { - await client.rest.teams.addOrUpdateRepoPermissionsInOrg({ - org: owner, - team_slug: collaborator.team, - owner, - repo, - permission: collaborator.access, - }); - } - } catch (e) { - assertError(e); - const name = extractCollaboratorName(collaborator); - ctx.logger.warn( - `Skipping ${collaborator.access} access for ${name}, ${e.message}`, - ); - } - } - } - - if (topics) { - try { - await client.rest.repos.replaceAllTopics({ - owner, - repo, - names: topics.map(t => t.toLowerCase()), - }); - } catch (e) { - assertError(e); - ctx.logger.warn(`Skipping topics ${topics.join(' ')}, ${e.message}`); - } - } + const newRepo = await createGithubRepoWithCollaboratorsAndTopics( + client, + repo, + owner, + repoVisibility, + description, + deleteBranchOnMerge, + allowMergeCommit, + allowSquashMerge, + allowRebaseMerge, + access, + collaborators, + topics, + ctx.logger, + ); const remoteUrl = newRepo.clone_url; const repoContentsUrl = `${newRepo.html_url}/blob/${defaultBranch}`; - const gitAuthorInfo = { - name: gitAuthorName - ? gitAuthorName - : config.getOptionalString('scaffolder.defaultAuthor.name'), - email: gitAuthorEmail - ? gitAuthorEmail - : config.getOptionalString('scaffolder.defaultAuthor.email'), - }; - - await initRepoAndPush({ - dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath), + await initRepoPushAndProtect( remoteUrl, + octokitOptions.auth, + ctx.workspacePath, + ctx.input.sourcePath, defaultBranch, - auth: { - username: 'x-access-token', - password: octokitOptions.auth, - }, - logger: ctx.logger, - commitMessage: gitCommitMessage - ? gitCommitMessage - : config.getOptionalString('scaffolder.defaultCommitMessage'), - gitAuthorInfo, - }); - - if (protectDefaultBranch) { - try { - await enableBranchProtectionOnDefaultRepoBranch({ - owner, - client, - repoName: newRepo.name, - logger: ctx.logger, - defaultBranch, - requireCodeOwnerReviews, - requiredStatusCheckContexts, - }); - } catch (e) { - assertError(e); - ctx.logger.warn( - `Skipping: default branch protection on '${newRepo.name}', ${e.message}`, - ); - } - } + protectDefaultBranch, + owner, + client, + repo, + requireCodeOwnerReviews, + requiredStatusCheckContexts, + config, + ctx.logger, + gitCommitMessage, + gitAuthorName, + gitAuthorEmail, + ); ctx.output('remoteUrl', remoteUrl); ctx.output('repoContentsUrl', repoContentsUrl); }, }); } - -function extractCollaboratorName( - collaborator: { user: string } | { team: string } | { username: string }, -) { - if ('username' in collaborator) return collaborator.username; - if ('user' in collaborator) return collaborator.user; - return collaborator.team; -} diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.test.ts new file mode 100644 index 0000000000..987e360617 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.test.ts @@ -0,0 +1,207 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { getRootLogger } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { ScmIntegrations } from '@backstage/integration'; +import mockFs from 'mock-fs'; +import os from 'os'; +import { resolve as resolvePath } from 'path'; +import { Writable } from 'stream'; +import { TemplateAction } from '../../types'; +import { createPublishGitlabMergeRequestAction } from './gitlabMergeRequest'; + +const root = os.platform() === 'win32' ? 'C:\\root' : '/root'; +const workspacePath = resolvePath(root, 'my-workspace'); + +const mockGitlabClient = { + Namespaces: { + show: jest.fn(), + }, + Branches: { + create: jest.fn(), + }, + Commits: { + create: jest.fn(), + }, + MergeRequests: { + create: jest.fn(async (_: any) => { + return { + default_branch: 'main', + }; + }), + }, + Projects: { + create: jest.fn(), + show: jest.fn(async (_: any) => { + return { + default_branch: 'main', + }; + }), + }, + Users: { + current: jest.fn(), + }, +}; + +jest.mock('@gitbeaker/node', () => ({ + Gitlab: class { + constructor() { + return mockGitlabClient; + } + }, +})); + +describe('createGitLabMergeRequest', () => { + let instance: TemplateAction; + + beforeEach(() => { + const config = new ConfigReader({ + integrations: { + gitlab: [ + { + host: 'gitlab.com', + token: 'token', + apiBaseUrl: 'https://api.gitlab.com', + }, + { + host: 'hosted.gitlab.com', + apiBaseUrl: 'https://api.hosted.gitlab.com', + }, + ], + }, + }); + + const integrations = ScmIntegrations.fromConfig(config); + instance = createPublishGitlabMergeRequestAction({ integrations }); + }); + + afterEach(() => { + mockFs.restore(); + }); + + describe('createGitLabMergeRequestWithoutRemoveBranch', () => { + it('removeSourceBranch is false by default when not passed in options', async () => { + const input = { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + title: 'Create my new MR', + branchName: 'new-mr', + description: 'This MR is really good', + draft: true, + targetPath: 'Subdirectory', + }; + mockFs({ + [workspacePath]: { + source: { 'foo.txt': 'Hello there!' }, + irrelevant: { 'bar.txt': 'Nothing to see here' }, + }, + }); + const ctx = { + createTemporaryDirectory: jest.fn(), + output: jest.fn(), + logger: getRootLogger(), + logStream: new Writable(), + input, + workspacePath, + }; + await instance.handler(ctx); + + expect(mockGitlabClient.MergeRequests.create).toHaveBeenCalledWith( + 'owner/repo', + 'new-mr', + 'main', + 'Create my new MR', + { description: 'This MR is really good', removeSourceBranch: false }, + ); + }); + }); + + describe('createGitLabMergeRequestWithRemoveBranch', () => { + it('removeSourceBranch is true when true is passed in options', async () => { + const input = { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + title: 'Create my new MR', + branchName: 'new-mr', + description: 'MR description', + removeSourceBranch: true, + draft: true, + targetPath: 'Subdirectory', + }; + mockFs({ + [workspacePath]: { + source: { 'foo.txt': 'Hello there!' }, + irrelevant: { 'bar.txt': 'Nothing to see here' }, + }, + }); + + const ctx = { + createTemporaryDirectory: jest.fn(), + output: jest.fn(), + logger: getRootLogger(), + logStream: new Writable(), + input, + workspacePath, + }; + await instance.handler(ctx); + + expect(mockGitlabClient.MergeRequests.create).toHaveBeenCalledWith( + 'owner/repo', + 'new-mr', + 'main', + 'Create my new MR', + { description: 'MR description', removeSourceBranch: true }, + ); + }); + + it('removeSourceBranch is false when false is passed in options', async () => { + const input = { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + title: 'Create my new MR', + branchName: 'new-mr', + description: 'other MR description', + removeSourceBranch: false, + draft: true, + targetPath: 'Subdirectory', + }; + mockFs({ + [workspacePath]: { + source: { 'foo.txt': 'Hello there!' }, + irrelevant: { 'bar.txt': 'Nothing to see here' }, + }, + }); + + const ctx = { + createTemporaryDirectory: jest.fn(), + output: jest.fn(), + logger: getRootLogger(), + logStream: new Writable(), + input, + workspacePath, + }; + await instance.handler(ctx); + + expect(mockGitlabClient.MergeRequests.create).toHaveBeenCalledWith( + 'owner/repo', + 'new-mr', + 'main', + 'Create my new MR', + { + description: 'other MR description', + removeSourceBranch: false, + }, + ); + }); + }); +}); 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 f717a7a0c6..b1d5b35fa3 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts @@ -42,6 +42,7 @@ export const createPublishGitlabMergeRequestAction = (options: { token?: string; /** @deprecated Use projectPath instead */ projectid?: string; + removeSourceBranch?: boolean; }>({ id: 'publish:gitlab:merge-request', schema: { @@ -85,6 +86,12 @@ export const createPublishGitlabMergeRequestAction = (options: { type: 'string', description: 'The token to use for authorization to GitLab', }, + removeSourceBranch: { + title: 'Delete source branch', + type: 'boolean', + description: + 'Option to delete source branch once the MR has been merged. Default: false', + }, }, }, output: { @@ -187,7 +194,12 @@ export const createPublishGitlabMergeRequestAction = (options: { destinationBranch, String(defaultBranch), ctx.input.title, - { description: ctx.input.description }, + { + description: ctx.input.description, + removeSourceBranch: ctx.input.removeSourceBranch + ? ctx.input.removeSourceBranch + : false, + }, ).then((mergeRequest: { web_url: string }) => { return mergeRequest.web_url; }); diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index 4919d2e5f9..2abb730250 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -23,13 +23,14 @@ import { } from '@backstage/catalog-model'; import { Entity } from '@backstage/catalog-model'; import { Config, JsonObject } from '@backstage/config'; -import { InputError, NotFoundError } from '@backstage/errors'; +import { InputError, NotFoundError, stringifyError } from '@backstage/errors'; import { ScmIntegrations } from '@backstage/integration'; import { TemplateEntityV1beta3, TaskSpec, templateEntityV1beta3Validator, } from '@backstage/plugin-scaffolder-common'; +import { JsonValue } from '@backstage/types'; import express from 'express'; import Router from 'express-promise-router'; import { validate } from 'jsonschema'; @@ -431,17 +432,36 @@ function parseBearerToken(header?: string): { token?: string; entityRef?: string; } { - const token = header?.match(/Bearer\s+(\S+)/i)?.[1]; + if (!header) { + return {}; + } - if (!token) return {}; + try { + const token = header.match(/^Bearer\s(\S+\.\S+\.\S+)$/i)?.[1]; + if (!token) { + throw new TypeError('Expected Bearer with JWT'); + } - const [_header, rawPayload, _signature] = token.split('.'); - const payload: { sub: string } = JSON.parse( - Buffer.from(rawPayload, 'base64').toString(), - ); + const [_header, rawPayload, _signature] = token.split('.'); + const payload: JsonValue = JSON.parse( + Buffer.from(rawPayload, 'base64').toString(), + ); - return { - entityRef: payload.sub, - token, - }; + if ( + typeof payload !== 'object' || + payload === null || + Array.isArray(payload) + ) { + throw new TypeError('Malformed JWT payload'); + } + + const sub = payload.sub; + if (typeof sub !== 'string') { + throw new TypeError('Expected string sub claim'); + } + + return { entityRef: sub, token }; + } catch (e) { + throw new InputError(`Invalid authorization header: ${stringifyError(e)}`); + } } diff --git a/plugins/scaffolder-common/package.json b/plugins/scaffolder-common/package.json index 06d178caf3..09503d0be6 100644 --- a/plugins/scaffolder-common/package.json +++ b/plugins/scaffolder-common/package.json @@ -39,10 +39,10 @@ "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/catalog-model": "^1.1.0-next.1", "@backstage/types": "^1.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0" + "@backstage/cli": "^0.18.0-next.1" } } diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index 715c2136f8..a8a606c73d 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,47 @@ # @backstage/plugin-scaffolder +## 1.4.0-next.2 + +### Minor Changes + +- d8eb82f447: Add `allowedRepos` `ui:option` to `RepoUrlPicker` component, and move `repoName` field to own component + +### Patch Changes + +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +- 14146703e5: Add `allowArbitraryValues` to `ui:options` in `OwnedEntityPicker`, similar to `allowArbitraryValues` in `EntityPicker` +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/integration@1.2.2-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/integration-react@1.1.2-next.2 + +## 1.4.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/plugin-catalog-common@1.0.4-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + - @backstage/plugin-permission-react@0.4.3-next.0 + ## 1.4.0-next.0 ### Minor Changes diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index 9ffca426ac..3fa623b5b9 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -153,6 +153,8 @@ export const OwnedEntityPickerFieldExtension: FieldExtensionComponent< // @public export interface OwnedEntityPickerUiOptions { + // (undocumented) + allowArbitraryValues?: boolean; // (undocumented) allowedKinds?: string[]; // (undocumented) @@ -193,6 +195,8 @@ export interface RepoUrlPickerUiOptions { // (undocumented) allowedOwners?: string[]; // (undocumented) + allowedRepos?: string[]; + // (undocumented) requestUserCredentials?: { secretsKey: string; additionalScopes?: { diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 2c81ef7162..c371c47907 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder", "description": "The Backstage plugin that helps you create new things", - "version": "1.4.0-next.0", + "version": "1.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,19 +35,19 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/integration-react": "^1.1.2-next.0", - "@backstage/plugin-catalog-common": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/plugin-permission-react": "^0.4.2", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.2", + "@backstage/integration-react": "^1.1.2-next.2", + "@backstage/plugin-catalog-common": "^1.0.4-next.0", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/plugin-permission-react": "^0.4.3-next.0", "@backstage/plugin-scaffolder-common": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/theme": "^0.2.16-next.1", "@backstage/types": "^1.0.0", "@codemirror/language": "^6.0.0", "@codemirror/legacy-modes": "^6.1.0", @@ -61,7 +61,7 @@ "@types/json-schema": "^7.0.9", "@uiw/react-codemirror": "^4.9.3", "classnames": "^2.2.6", - "git-url-parse": "^11.6.0", + "git-url-parse": "^12.0.0", "humanize-duration": "^3.25.1", "immer": "^9.0.1", "json-schema": "^0.4.0", @@ -80,11 +80,11 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/plugin-catalog": "^1.3.1-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/plugin-catalog": "^1.4.0-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", @@ -94,7 +94,7 @@ "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", "event-source-polyfill": "1.0.25", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx index 8e3590e8bf..a280ebad6a 100644 --- a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx @@ -37,6 +37,7 @@ import { FieldExtensionComponentProps } from '../../../extensions'; export interface OwnedEntityPickerUiOptions { allowedKinds?: string[]; defaultKind?: string; + allowArbitraryValues?: boolean; } /** @@ -60,6 +61,8 @@ export const OwnedEntityPicker = ( const allowedKinds = uiSchema['ui:options']?.allowedKinds; const defaultKind = uiSchema['ui:options']?.defaultKind; + const allowArbitraryValues = + uiSchema['ui:options']?.allowArbitraryValues ?? true; const { ownedEntities, loading } = useOwnedEntities(allowedKinds); const entityRefs = ownedEntities?.items @@ -83,7 +86,7 @@ export const OwnedEntityPicker = ( onChange={onSelect} options={entityRefs || []} autoSelect - freeSolo + freeSolo={allowArbitraryValues} renderInput={params => ( { - it('renders the three input fields', async () => { + it('renders the two input fields', async () => { const { getAllByRole } = render( , ); const allInputs = getAllByRole('textbox'); - expect(allInputs).toHaveLength(3); + expect(allInputs).toHaveLength(2); }); describe('org field', () => { @@ -58,19 +58,4 @@ describe('AzureRepoPicker', () => { expect(onChange).toHaveBeenCalledWith({ owner: 'owner' }); }); }); - - describe('repoName field', () => { - it('calls onChange when the repoName changes', () => { - const onChange = jest.fn(); - const { getAllByRole } = render( - , - ); - - const repoNameInput = getAllByRole('textbox')[2]; - - fireEvent.change(repoNameInput, { target: { value: 'repoName' } }); - - expect(onChange).toHaveBeenCalledWith({ repoName: 'repoName' }); - }); - }); }); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/AzureRepoPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/AzureRepoPicker.tsx index 0efadf4017..0246c67801 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/AzureRepoPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/AzureRepoPicker.tsx @@ -27,7 +27,7 @@ export const AzureRepoPicker = (props: { rawErrors: string[]; }) => { const { rawErrors, state, onChange } = props; - const { organization, repoName, owner } = state; + const { organization, owner } = state; return ( <> The Owner that this repo will belong to - 0 && !repoName} - > - Repository - onChange({ repoName: e.target.value })} - value={repoName} - /> - The name of the repository - ); }; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.test.tsx index 17fe656006..0ced19a596 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.test.tsx @@ -26,7 +26,7 @@ describe('BitbucketRepoPicker', () => { , ); - expect(getAllByRole('textbox')).toHaveLength(3); + expect(getAllByRole('textbox')).toHaveLength(2); expect(getAllByRole('textbox')[0]).toHaveValue('lolsWorkspace'); }); @@ -39,7 +39,7 @@ describe('BitbucketRepoPicker', () => { , ); - expect(getAllByRole('textbox')).toHaveLength(2); + expect(getAllByRole('textbox')).toHaveLength(1); }); describe('workspace field', () => { it('calls onChange when the workspace changes', () => { @@ -78,23 +78,4 @@ describe('BitbucketRepoPicker', () => { expect(onChange).toHaveBeenCalledWith({ project: 'test-project' }); }); }); - - describe('repoName field', () => { - it('calls onChange when the repoName changes', () => { - const onChange = jest.fn(); - const { getAllByRole } = render( - , - ); - - const repoNameInput = getAllByRole('textbox')[2]; - - fireEvent.change(repoNameInput, { target: { value: 'test-repo' } }); - - expect(onChange).toHaveBeenCalledWith({ repoName: 'test-repo' }); - }); - }); }); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.tsx index 64eb4b8dac..fc59398d94 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.tsx @@ -26,7 +26,7 @@ export const BitbucketRepoPicker = (props: { rawErrors: string[]; }) => { const { onChange, rawErrors, state } = props; - const { host, workspace, project, repoName } = state; + const { host, workspace, project } = state; return ( <> {host === 'bitbucket.org' && ( @@ -61,19 +61,6 @@ export const BitbucketRepoPicker = (props: { The Project that this repo will belong to - 0 && !repoName} - > - Repository - onChange({ repoName: e.target.value })} - value={repoName} - /> - The name of the repository - ); }; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GerritRepoPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GerritRepoPicker.test.tsx index edc6732588..66f0a234be 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GerritRepoPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GerritRepoPicker.test.tsx @@ -56,23 +56,4 @@ describe('BitbucketRepoPicker', () => { expect(onChange).toHaveBeenCalledWith({ workspace: 'test-parent' }); }); }); - - describe('repoName field', () => { - it('calls onChange when the repoName changes', () => { - const onChange = jest.fn(); - const { getAllByRole } = render( - , - ); - - const repoNameInput = getAllByRole('textbox')[2]; - - fireEvent.change(repoNameInput, { target: { value: 'test-repo' } }); - - expect(onChange).toHaveBeenCalledWith({ repoName: 'test-repo' }); - }); - }); }); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GerritRepoPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GerritRepoPicker.tsx index 4cbc0859e8..f021948532 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GerritRepoPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GerritRepoPicker.tsx @@ -26,7 +26,7 @@ export const GerritRepoPicker = (props: { rawErrors: string[]; }) => { const { onChange, rawErrors, state } = props; - const { workspace, repoName, owner } = state; + const { workspace, owner } = state; return ( <> - 0 && !repoName} - > - Repository - onChange({ repoName: e.target.value })} - value={repoName} - /> - The name of the repository - ); }; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GithubRepoPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GithubRepoPicker.test.tsx index 2c80c40c22..63bc5b8013 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GithubRepoPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GithubRepoPicker.test.tsx @@ -84,24 +84,4 @@ describe('GithubRepoPicker', () => { expect(onChange).toHaveBeenCalledWith({ owner: 'my-mock-owner' }); }); }); - - describe('repo name', () => { - it('should render free text field for input of repo name', () => { - const onChange = jest.fn(); - const { getAllByRole } = render( - , - ); - - const repoNameField = getAllByRole('textbox')[1]; - fireEvent.change(repoNameField, { - target: { value: 'my-mock-repo-name' }, - }); - - expect(onChange).toHaveBeenCalledWith({ repoName: 'my-mock-repo-name' }); - }); - }); }); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GithubRepoPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GithubRepoPicker.tsx index 13b57cb449..ec59d89ef8 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GithubRepoPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GithubRepoPicker.tsx @@ -32,7 +32,7 @@ export const GithubRepoPicker = (props: { ? allowedOwners.map(i => ({ label: i, value: i })) : [{ label: 'Loading...', value: 'loading' }]; - const { owner, repoName } = state; + const { owner } = state; return ( <> @@ -66,19 +66,6 @@ export const GithubRepoPicker = (props: { The organization, user or project that this repo will belong to - 0 && !repoName} - > - Repository - onChange({ repoName: e.target.value })} - value={repoName} - /> - The name of the repository - ); }; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GitlabRepoPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GitlabRepoPicker.test.tsx index 49a91c116e..ad5c7f765e 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GitlabRepoPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GitlabRepoPicker.test.tsx @@ -84,24 +84,4 @@ describe('GitlabRepoPicker', () => { expect(onChange).toHaveBeenCalledWith({ owner: 'my-mock-owner' }); }); }); - - describe('repo name', () => { - it('should render free text field for input of repo name', () => { - const onChange = jest.fn(); - const { getAllByRole } = render( - , - ); - - const repoNameField = getAllByRole('textbox')[1]; - fireEvent.change(repoNameField, { - target: { value: 'my-mock-repo-name' }, - }); - - expect(onChange).toHaveBeenCalledWith({ repoName: 'my-mock-repo-name' }); - }); - }); }); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GitlabRepoPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GitlabRepoPicker.tsx index e2052b792f..c628b364b9 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GitlabRepoPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GitlabRepoPicker.tsx @@ -23,16 +23,17 @@ import { RepoUrlPickerState } from './types'; export const GitlabRepoPicker = (props: { allowedOwners?: string[]; + allowedRepos?: string[]; state: RepoUrlPickerState; onChange: (state: RepoUrlPickerState) => void; rawErrors: string[]; }) => { - const { allowedOwners = [], rawErrors, state, onChange } = props; + const { allowedOwners = [], state, onChange, rawErrors } = props; const ownerItems: SelectItem[] = allowedOwners ? allowedOwners.map(i => ({ label: i, value: i })) : [{ label: 'Loading...', value: 'loading' }]; - const { owner, repoName } = state; + const { owner } = state; return ( <> @@ -69,19 +70,6 @@ export const GitlabRepoPicker = (props: { namespaces in gitlab), that this repo will belong to - 0 && !repoName} - > - Repository - onChange({ repoName: e.target.value })} - value={repoName} - /> - The name of the repository - ); }; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx index 6f762933b6..b36b332d9e 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx @@ -26,6 +26,7 @@ import { BitbucketRepoPicker } from './BitbucketRepoPicker'; import { GerritRepoPicker } from './GerritRepoPicker'; import { FieldExtensionComponentProps } from '../../../extensions'; import { RepoUrlPickerHost } from './RepoUrlPickerHost'; +import { RepoUrlPickerRepoName } from './RepoUrlPickerRepoName'; import { parseRepoPickerUrl, serializeRepoPickerUrl } from './utils'; import { RepoUrlPickerState } from './types'; import useDebounce from 'react-use/lib/useDebounce'; @@ -40,6 +41,7 @@ import { useTemplateSecrets } from '../../secrets'; export interface RepoUrlPickerUiOptions { allowedHosts?: string[]; allowedOwners?: string[]; + allowedRepos?: string[]; requestUserCredentials?: { secretsKey: string; additionalScopes?: { @@ -76,6 +78,10 @@ export const RepoUrlPicker = ( () => uiSchema?.['ui:options']?.allowedOwners ?? [], [uiSchema], ); + const allowedRepos = useMemo( + () => uiSchema?.['ui:options']?.allowedRepos ?? [], + [uiSchema], + ); useEffect(() => { onChange(serializeRepoPickerUrl(state)); @@ -87,6 +93,11 @@ export const RepoUrlPicker = ( setState(prevState => ({ ...prevState, owner: allowedOwners[0] })); } }, [setState, allowedOwners]); + useEffect(() => { + if (allowedRepos.length === 1) { + setState(prevState => ({ ...prevState, repoName: allowedRepos[0] })); + } + }, [setState, allowedRepos]); const updateLocalState = useCallback( (newState: RepoUrlPickerState) => { @@ -179,6 +190,14 @@ export const RepoUrlPicker = ( onChange={updateLocalState} /> )} + + setState(prevState => ({ ...prevState, repoName })) + } + rawErrors={rawErrors} + /> ); }; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.test.tsx new file mode 100644 index 0000000000..4c392d646c --- /dev/null +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.test.tsx @@ -0,0 +1,76 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; +import { RepoUrlPickerRepoName } from './RepoUrlPickerRepoName'; +import { render, fireEvent } from '@testing-library/react'; + +describe('RepoUrlPickerRepoName', () => { + it('should call onChange with the first allowed repo if there is none set already', async () => { + const onChange = jest.fn(); + + render( + , + ); + + expect(onChange).toHaveBeenCalledWith('foo'); + }); + + it('should render a dropdown of all the options', async () => { + const allowedRepos = ['foo', 'bar']; + + const onChange = jest.fn(); + + const { getByRole } = render( + , + ); + + const select = getByRole('combobox'); + await fireEvent.click(select); + + for (const option of allowedRepos) { + const element = getByRole('option', { name: option }); + expect(element).toBeVisible(); + } + }); + + it('should render a normal text area when no options are passed', async () => { + const onChange = jest.fn(); + + const { getByRole } = render( + , + ); + + const textArea = getByRole('textbox'); + + expect(textArea).toBeVisible(); + + fireEvent.change(textArea, { target: { value: 'foo' } }); + + expect(onChange).toHaveBeenCalledWith('foo'); + }); +}); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.tsx new file mode 100644 index 0000000000..1393b1902e --- /dev/null +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.tsx @@ -0,0 +1,77 @@ +/* + * 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 React, { useEffect } from 'react'; +import { Select, SelectItem } from '@backstage/core-components'; +import FormControl from '@material-ui/core/FormControl'; +import FormHelperText from '@material-ui/core/FormHelperText'; +import Input from '@material-ui/core/Input'; +import InputLabel from '@material-ui/core/InputLabel'; + +export const RepoUrlPickerRepoName = (props: { + repoName?: string; + allowedRepos?: string[]; + onChange: (host: string) => void; + rawErrors: string[]; +}) => { + const { repoName, allowedRepos, onChange, rawErrors } = props; + + useEffect(() => { + // If there is no repoName chosen currently + if (!repoName) { + // Set the first of the allowedRepos option if that available + if (allowedRepos?.length) { + onChange(allowedRepos[0]); + } + } + }, [allowedRepos, repoName, onChange]); + + const repoItems: SelectItem[] = allowedRepos + ? allowedRepos.map(i => ({ label: i, value: i })) + : [{ label: 'Loading...', value: 'loading' }]; + + return ( + <> + 0 && !repoName} + > + {allowedRepos?.length ? ( + onChange(String(e.target.value))} + value={repoName} + /> + + )} + The name of the repository + + + ); +}; diff --git a/plugins/search-backend-module-elasticsearch/CHANGELOG.md b/plugins/search-backend-module-elasticsearch/CHANGELOG.md index 72b81689dd..eadb4e5c8b 100644 --- a/plugins/search-backend-module-elasticsearch/CHANGELOG.md +++ b/plugins/search-backend-module-elasticsearch/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/plugin-search-backend-module-elasticsearch +## 0.2.0-next.1 + +### Minor Changes + +- c5af773757: **BREAKING**: In order to remain interoperable with all currently supported + deployments of Elasticsearch, this package will now conditionally use either + the `@elastic/elasticsearch` or `@opensearch-project/opensearch` client when + communicating with your deployed cluster. + + If you do not rely on types exported from this package, or if you do not make + use of the `createElasticSearchClientOptions` or `newClient` methods on the + `ElasticSearchSearchEngine` class, then upgrading to this version should not + require any further action on your part. Everything will continue to work as it + always has. + + If you _do_ rely on either of the above methods or any underlying types, some + changes may be needed to your custom code. A type guard is now exported by this + package (`isOpenSearchCompatible(options)`), which you may use to help clarify + which client options are compatible with which client constructors. + + If you are using this package with the `search.elasticsearch.provider` set to + `aws`, and you are making use of the `newClient` method in particular, you may + wish to start using the `@opensearch-project/opensearch` client in your custom + code. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-node@0.6.3-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + ## 0.1.6-next.0 ### Patch Changes diff --git a/plugins/search-backend-module-elasticsearch/api-report.md b/plugins/search-backend-module-elasticsearch/api-report.md index 04b7f96f93..eed2b1b10a 100644 --- a/plugins/search-backend-module-elasticsearch/api-report.md +++ b/plugins/search-backend-module-elasticsearch/api-report.md @@ -5,60 +5,27 @@ ```ts /// +import { ApiResponse } from '@opensearch-project/opensearch'; import { BatchSearchEngineIndexer } from '@backstage/plugin-search-backend-node'; -import { Client } from '@elastic/elasticsearch'; +import { BulkHelper } from '@opensearch-project/opensearch/lib/Helpers'; +import { BulkStats } from '@opensearch-project/opensearch/lib/Helpers'; import { Config } from '@backstage/config'; import type { ConnectionOptions } from 'tls'; import { IndexableDocument } from '@backstage/plugin-search-common'; import { IndexableResultSet } from '@backstage/plugin-search-common'; import { Logger } from 'winston'; +import { Readable } from 'stream'; import { SearchEngine } from '@backstage/plugin-search-common'; import { SearchQuery } from '@backstage/plugin-search-common'; - -// @public (undocumented) -export interface ElasticSearchAgentOptions { - // (undocumented) - keepAlive?: boolean; - // (undocumented) - keepAliveMsecs?: number; - // (undocumented) - maxFreeSockets?: number; - // (undocumented) - maxSockets?: number; -} - -// @public (undocumented) -export type ElasticSearchAuth = - | { - username: string; - password: string; - } - | { - apiKey: - | string - | { - id: string; - api_key: string; - }; - }; +import { TransportRequestPromise } from '@opensearch-project/opensearch/lib/Transport'; // @public -export interface ElasticSearchClientOptions { +export interface BaseElasticSearchClientOptions { // (undocumented) agent?: ElasticSearchAgentOptions | ((opts?: any) => unknown) | false; // (undocumented) - auth?: ElasticSearchAuth; - // (undocumented) - cloud?: { - id: string; - username?: string; - password?: string; - }; - // (undocumented) compression?: 'gzip'; // (undocumented) - Connection?: ElasticSearchConnectionConstructor; - // (undocumented) disablePrototypePoisoningProtection?: boolean | 'proto' | 'constructor'; // (undocumented) enableMetaHeader?: boolean; @@ -69,28 +36,14 @@ export interface ElasticSearchClientOptions { // (undocumented) name?: string | symbol; // (undocumented) - node?: - | string - | string[] - | ElasticSearchNodeOptions - | ElasticSearchNodeOptions[]; - // (undocumented) nodeFilter?: (connection: any) => boolean; // (undocumented) - nodes?: - | string - | string[] - | ElasticSearchNodeOptions - | ElasticSearchNodeOptions[]; - // (undocumented) nodeSelector?: ((connections: any[]) => any) | string; // (undocumented) opaqueIdPrefix?: string; // (undocumented) pingTimeout?: number; // (undocumented) - provider?: 'aws' | 'elastic'; - // (undocumented) proxy?: string | URL; // (undocumented) requestTimeout?: number; @@ -112,6 +65,118 @@ export interface ElasticSearchClientOptions { Transport?: ElasticSearchTransportConstructor; } +// @public (undocumented) +export interface ElasticSearchAgentOptions { + // (undocumented) + keepAlive?: boolean; + // (undocumented) + keepAliveMsecs?: number; + // (undocumented) + maxFreeSockets?: number; + // (undocumented) + maxSockets?: number; +} + +// @public (undocumented) +export type ElasticSearchAliasAction = + | { + remove: { + index: any; + alias: any; + }; + add?: undefined; + } + | { + add: { + indices: any; + alias: any; + index?: undefined; + }; + remove?: undefined; + } + | { + add: { + index: any; + alias: any; + indices?: undefined; + }; + remove?: undefined; + } + | undefined; + +// @public (undocumented) +export type ElasticSearchAuth = + | OpenSearchAuth + | { + apiKey: + | string + | { + id: string; + api_key: string; + }; + }; + +// @public +export type ElasticSearchClientOptions = + | ElasticSearchElasticSearchClientOptions + | OpenSearchElasticSearchClientOptions; + +// @public +export class ElasticSearchClientWrapper { + // (undocumented) + bulk(bulkOptions: { + datasource: Readable; + onDocument: () => ElasticSearchIndexAction; + refreshOnCompletion?: string | boolean; + }): BulkHelper; + // (undocumented) + createIndex({ + index, + }: { + index: string; + }): TransportRequestPromise, unknown>>; + // (undocumented) + deleteIndex({ + index, + }: { + index: string | string[]; + }): TransportRequestPromise, unknown>>; + // (undocumented) + static fromClientOptions( + options: ElasticSearchClientOptions, + ): ElasticSearchClientWrapper; + // (undocumented) + getAliases({ + aliases, + }: { + aliases: string[]; + }): TransportRequestPromise, unknown>>; + // (undocumented) + indexExists({ + index, + }: { + index: string | string[]; + }): TransportRequestPromise>; + // (undocumented) + putIndexTemplate( + template: ElasticSearchCustomIndexTemplate, + ): TransportRequestPromise, unknown>>; + // (undocumented) + search({ + index, + body, + }: { + index: string | string[]; + body: Object; + }): TransportRequestPromise, unknown>>; + // (undocumented) + updateAliases({ + actions, + }: { + actions: ElasticSearchAliasAction[]; + }): TransportRequestPromise, unknown>>; +} + // @public export type ElasticSearchConcreteQuery = { documentTypes?: string[]; @@ -150,6 +215,35 @@ export type ElasticSearchCustomIndexTemplateBody = { template?: Record; }; +// @public +export interface ElasticSearchElasticSearchClientOptions + extends BaseElasticSearchClientOptions { + // (undocumented) + auth?: ElasticSearchAuth; + // (undocumented) + cloud?: { + id: string; + username?: string; + password?: string; + }; + // (undocumented) + Connection?: ElasticSearchConnectionConstructor; + // (undocumented) + node?: + | string + | string[] + | ElasticSearchNodeOptions + | ElasticSearchNodeOptions[]; + // (undocumented) + nodes?: + | string + | string[] + | ElasticSearchNodeOptions + | ElasticSearchNodeOptions[]; + // (undocumented) + provider?: 'elastic'; +} + // @public (undocumented) export type ElasticSearchHighlightConfig = { fragmentDelimiter: string; @@ -166,6 +260,14 @@ export type ElasticSearchHighlightOptions = { numFragments?: number; }; +// @public (undocumented) +export type ElasticSearchIndexAction = { + index: { + _index: string; + [key: string]: any; + }; +}; + // @public (undocumented) export interface ElasticSearchNodeOptions { // (undocumented) @@ -258,7 +360,7 @@ export type ElasticSearchSearchEngineIndexerOptions = { indexSeparator: string; alias: string; logger: Logger; - elasticSearchClient: Client; + elasticSearchClientWrapper: ElasticSearchClientWrapper; }; // @public (undocumented) @@ -273,4 +375,67 @@ export interface ElasticSearchTransportConstructor { DEFAULT: string; }; } + +// @public +export const isOpenSearchCompatible: ( + opts: ElasticSearchClientOptions, +) => opts is OpenSearchElasticSearchClientOptions; + +// @public (undocumented) +export type OpenSearchAuth = { + username: string; + password: string; +}; + +// @public (undocumented) +export interface OpenSearchConnectionConstructor { + // (undocumented) + new (opts?: any): any; + // (undocumented) + roles: { + MASTER: string; + DATA: string; + INGEST: string; + }; + // (undocumented) + statuses: { + ALIVE: string; + DEAD: string; + }; +} + +// @public +export interface OpenSearchElasticSearchClientOptions + extends BaseElasticSearchClientOptions { + // (undocumented) + auth?: OpenSearchAuth; + // (undocumented) + connection?: OpenSearchConnectionConstructor; + // (undocumented) + node?: string | string[] | OpenSearchNodeOptions | OpenSearchNodeOptions[]; + // (undocumented) + nodes?: string | string[] | OpenSearchNodeOptions | OpenSearchNodeOptions[]; + // (undocumented) + provider?: 'aws'; +} + +// @public (undocumented) +export interface OpenSearchNodeOptions { + // (undocumented) + agent?: ElasticSearchAgentOptions; + // (undocumented) + headers?: Record; + // (undocumented) + id?: string; + // (undocumented) + roles?: { + master: boolean; + data: boolean; + ingest: boolean; + }; + // (undocumented) + ssl?: ConnectionOptions; + // (undocumented) + url: URL; +} ``` diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index 99339ef99c..b12a87c37d 100644 --- a/plugins/search-backend-module-elasticsearch/package.json +++ b/plugins/search-backend-module-elasticsearch/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-elasticsearch", "description": "A module for the search backend that implements search using ElasticSearch", - "version": "0.1.6-next.0", + "version": "0.2.0-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,11 +23,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@acuris/aws-es-connection": "^2.2.0", "@backstage/config": "^1.0.1", - "@backstage/plugin-search-backend-node": "^0.6.3-next.0", - "@backstage/plugin-search-common": "^0.3.5", - "@elastic/elasticsearch": "7.13.0", + "@backstage/plugin-search-backend-node": "^0.6.3-next.1", + "@backstage/plugin-search-common": "^0.3.6-next.0", + "@elastic/elasticsearch": "^7.13.0", + "@opensearch-project/opensearch": "^1.1.0", + "aws-os-connection": "^0.1.0", "aws-sdk": "^2.948.0", "elastic-builder": "^2.16.0", "lodash": "^4.17.21", @@ -35,9 +36,10 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/cli": "^0.17.3-next.0", - "@elastic/elasticsearch-mock": "^1.0.0" + "@backstage/backend-common": "^0.14.1-next.1", + "@backstage/cli": "^0.18.0-next.1", + "@elastic/elasticsearch-mock": "^1.0.0", + "@short.io/opensearch-mock": "^0.3.1" }, "files": [ "dist", diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientOptions.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientOptions.ts index c5d1f11b0c..74523020db 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientOptions.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientOptions.ts @@ -16,17 +16,60 @@ import type { ConnectionOptions as TLSConnectionOptions } from 'tls'; /** - * Options used to configure the `@elastic/elasticsearch` client and - * are what will be passed as an argument to the - * {@link ElasticSearchSearchEngine.newClient} method - * - * They are drawn from the `ClientOptions` class of `@elastic/elasticsearch`, - * but are maintained separately so that this interface is not coupled to + * Typeguard to differentiate ElasticSearch client options which are compatible + * with OpenSearch vs. ElasticSearch clients. Useful when calling the + * {@link ElasticSearchSearchEngine.newClient} method. * * @public */ -export interface ElasticSearchClientOptions { - provider?: 'aws' | 'elastic'; +export const isOpenSearchCompatible = ( + opts: ElasticSearchClientOptions, +): opts is OpenSearchElasticSearchClientOptions => { + return opts?.provider === 'aws'; +}; + +/** + * Options used to configure the `@elastic/elasticsearch` client or the + * `@opensearch-project/opensearch` client, depending on the given config. It + * will be passed as an argument to the + * {@link ElasticSearchSearchEngine.newClient} method. + * + * @public + */ +export type ElasticSearchClientOptions = + | ElasticSearchElasticSearchClientOptions + | OpenSearchElasticSearchClientOptions; + +/** + * Options used to configure the `@opensearch-project/opensearch` client. + * + * They are drawn from the `ClientOptions` class of `@opensearch-project/opensearch`, + * but are maintained separately so that this interface is not coupled to it. + * + * @public + */ +export interface OpenSearchElasticSearchClientOptions + extends BaseElasticSearchClientOptions { + provider?: 'aws'; + auth?: OpenSearchAuth; + connection?: OpenSearchConnectionConstructor; + node?: string | string[] | OpenSearchNodeOptions | OpenSearchNodeOptions[]; + nodes?: string | string[] | OpenSearchNodeOptions | OpenSearchNodeOptions[]; +} + +/** + * Options used to configure the `@elastic/elasticsearch` client. + * + * They are drawn from the `ClientOptions` class of `@elastic/elasticsearch`, + * but are maintained separately so that this interface is not coupled to it. + * + * @public + */ +export interface ElasticSearchElasticSearchClientOptions + extends BaseElasticSearchClientOptions { + provider?: 'elastic'; + auth?: ElasticSearchAuth; + Connection?: ElasticSearchConnectionConstructor; node?: | string | string[] @@ -37,8 +80,21 @@ export interface ElasticSearchClientOptions { | string[] | ElasticSearchNodeOptions | ElasticSearchNodeOptions[]; + cloud?: { + id: string; + username?: string; + password?: string; + }; +} + +/** + * Base client options that are shared across `@opensearch-project/opensearch` + * and `@elastic/elasticsearch` clients. + * + * @public + */ +export interface BaseElasticSearchClientOptions { Transport?: ElasticSearchTransportConstructor; - Connection?: ElasticSearchConnectionConstructor; maxRetries?: number; requestTimeout?: number; pingTimeout?: number; @@ -56,25 +112,24 @@ export interface ElasticSearchClientOptions { headers?: Record; opaqueIdPrefix?: string; name?: string | symbol; - auth?: ElasticSearchAuth; proxy?: string | URL; enableMetaHeader?: boolean; - cloud?: { - id: string; - username?: string; - password?: string; - }; disablePrototypePoisoningProtection?: boolean | 'proto' | 'constructor'; } +/** + * @public + */ +export type OpenSearchAuth = { + username: string; + password: string; +}; + /** * @public */ export type ElasticSearchAuth = - | { - username: string; - password: string; - } + | OpenSearchAuth | { apiKey: | string @@ -101,6 +156,22 @@ export interface ElasticSearchNodeOptions { }; } +/** + * @public + */ +export interface OpenSearchNodeOptions { + url: URL; + id?: string; + agent?: ElasticSearchAgentOptions; + ssl?: TLSConnectionOptions; + headers?: Record; + roles?: { + master: boolean; + data: boolean; + ingest: boolean; + }; +} + /** * @public */ @@ -127,6 +198,23 @@ export interface ElasticSearchConnectionConstructor { ML: string; }; } + +/** + * @public + */ +export interface OpenSearchConnectionConstructor { + new (opts?: any): any; + statuses: { + ALIVE: string; + DEAD: string; + }; + roles: { + MASTER: string; + DATA: string; + INGEST: string; + }; +} + /** * @public */ @@ -139,3 +227,5 @@ export interface ElasticSearchTransportConstructor { DEFAULT: string; }; } + +// todo(iamEAP) implement canary types to ensure we remain compatible through upgrades. diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientWrapper.test.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientWrapper.test.ts new file mode 100644 index 0000000000..5bd8bb30b0 --- /dev/null +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientWrapper.test.ts @@ -0,0 +1,337 @@ +/* + * 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 { ConfigReader } from '@backstage/config'; +import { Client as ElasticSearchClient } from '@elastic/elasticsearch'; +import { Client as OpenSearchClient } from '@opensearch-project/opensearch'; +import Mock from '@short.io/opensearch-mock'; +import { Readable } from 'stream'; + +import { ElasticSearchClientWrapper } from './ElasticSearchClientWrapper'; +import { + createElasticSearchClientOptions, + ElasticSearchClientOptions, +} from './ElasticSearchSearchEngine'; + +jest.mock('@elastic/elasticsearch', () => ({ + ...jest.requireActual('@elastic/elasticsearch'), + Client: jest.fn().mockReturnValue({ + search: jest + .fn() + .mockImplementation(async args => ({ client: 'es', args })), + cat: { + aliases: jest + .fn() + .mockImplementation(async args => ({ client: 'es', args })), + }, + helpers: { + bulk: jest + .fn() + .mockImplementation(async args => ({ client: 'es', args })), + }, + indices: { + create: jest + .fn() + .mockImplementation(async args => ({ client: 'es', args })), + delete: jest + .fn() + .mockImplementation(async args => ({ client: 'es', args })), + exists: jest + .fn() + .mockImplementation(async args => ({ client: 'es', args })), + putIndexTemplate: jest + .fn() + .mockImplementation(async args => ({ client: 'es', args })), + updateAliases: jest + .fn() + .mockImplementation(async args => ({ client: 'es', args })), + }, + }), +})); + +jest.mock('@opensearch-project/opensearch', () => ({ + ...jest.requireActual('@opensearch-project/opensearch'), + Client: jest.fn().mockReturnValue({ + search: jest + .fn() + .mockImplementation(async args => ({ client: 'os', args })), + cat: { + aliases: jest + .fn() + .mockImplementation(async args => ({ client: 'os', args })), + }, + helpers: { + bulk: jest + .fn() + .mockImplementation(async args => ({ client: 'os', args })), + }, + indices: { + create: jest + .fn() + .mockImplementation(async args => ({ client: 'os', args })), + delete: jest + .fn() + .mockImplementation(async args => ({ client: 'os', args })), + exists: jest + .fn() + .mockImplementation(async args => ({ client: 'os', args })), + putIndexTemplate: jest + .fn() + .mockImplementation(async args => ({ client: 'os', args })), + updateAliases: jest + .fn() + .mockImplementation(async args => ({ client: 'os', args })), + }, + }), +})); + +describe('ElasticSearchClientWrapper', () => { + describe('elasticSearchClient', () => { + let esOptions: ElasticSearchClientOptions; + + beforeEach(async () => { + esOptions = await createElasticSearchClientOptions( + new ConfigReader({ + node: 'http://localhost:9200', + }), + ); + jest.clearAllMocks(); + }); + + it('instantiation', () => { + ElasticSearchClientWrapper.fromClientOptions(esOptions); + expect(ElasticSearchClient).toHaveBeenCalledWith(esOptions); + }); + + it('search', async () => { + const wrapper = ElasticSearchClientWrapper.fromClientOptions(esOptions); + + const searchInput = { index: 'xyz', body: { eg: 'etc' } }; + const result = (await wrapper.search(searchInput)) as any; + + // Should call the ElasticSearch client's search with expected input. + expect(result.client).toBe('es'); + expect(result.args).toStrictEqual(searchInput); + }); + + it('bulk', async () => { + const wrapper = ElasticSearchClientWrapper.fromClientOptions(esOptions); + + const bulkInput = { + datasource: Readable.from([{}]), + onDocument() { + return { index: { _index: 'xyz' } }; + }, + refreshCompletion: 'xyz', + }; + const result = (await wrapper.bulk(bulkInput)) as any; + + // Should call the ElasticSearch client's bulk helper with expected input + expect(result.client).toBe('es'); + expect(result.args).toStrictEqual(bulkInput); + }); + + it('putIndexTemplate', async () => { + const wrapper = ElasticSearchClientWrapper.fromClientOptions(esOptions); + + const indexTemplate = { name: 'xyz', body: { index_patterns: ['*'] } }; + const result = (await wrapper.putIndexTemplate(indexTemplate)) as any; + + // Should call the ElasticSearch client with expected input. + expect(result.client).toBe('es'); + expect(result.args).toStrictEqual(indexTemplate); + }); + + it('indexExists', async () => { + const wrapper = ElasticSearchClientWrapper.fromClientOptions(esOptions); + + const input = { index: 'xyz' }; + const result = (await wrapper.indexExists(input)) as any; + + // Should call the ElasticSearch client with expected input. + expect(result.client).toBe('es'); + expect(result.args).toStrictEqual(input); + }); + + it('deleteIndex', async () => { + const wrapper = ElasticSearchClientWrapper.fromClientOptions(esOptions); + + const input = { index: 'xyz' }; + const result = (await wrapper.deleteIndex(input)) as any; + + // Should call the OpenSearch client with expected input. + expect(result.client).toBe('es'); + expect(result.args).toStrictEqual(input); + }); + + it('createIndex', async () => { + const wrapper = ElasticSearchClientWrapper.fromClientOptions(esOptions); + + const input = { index: 'xyz' }; + const result = (await wrapper.createIndex(input)) as any; + + // Should call the OpenSearch client with expected input. + expect(result.client).toBe('es'); + expect(result.args).toStrictEqual(input); + }); + + it('getAliases', async () => { + const wrapper = ElasticSearchClientWrapper.fromClientOptions(esOptions); + + const input = { aliases: ['xyz'] }; + const result = (await wrapper.getAliases(input)) as any; + + // Should call the OpenSearch client with expected input. + expect(result.client).toBe('es'); + expect(result.args).toStrictEqual({ + format: 'json', + name: input.aliases, + }); + }); + + it('updateAliases', async () => { + const wrapper = ElasticSearchClientWrapper.fromClientOptions(esOptions); + + const input = { actions: [{ remove: { index: 'xyz', alias: 'abc' } }] }; + const result = (await wrapper.updateAliases(input)) as any; + + // Should call the OpenSearch client with expected input. + expect(result.client).toBe('es'); + expect(result.args).toStrictEqual({ + body: { actions: input.actions }, + }); + }); + }); + + describe('openSearchClient', () => { + const mock = new Mock(); + let osOptions: ElasticSearchClientOptions; + + beforeEach(() => { + osOptions = { + provider: 'aws', + node: 'https://my-es-cluster.eu-west-1.es.amazonaws.com', + connection: mock.getConnection(), + }; + + jest.clearAllMocks(); + }); + + it('instantiation', () => { + ElasticSearchClientWrapper.fromClientOptions(osOptions); + expect(OpenSearchClient).toHaveBeenCalledWith(osOptions); + }); + + it('search', async () => { + const wrapper = ElasticSearchClientWrapper.fromClientOptions(osOptions); + + const searchInput = { index: 'xyz', body: { eg: 'etc' } }; + const result = (await wrapper.search(searchInput)) as any; + + // Should call the OpenSearch client's search with expected input. + expect(result.client).toBe('os'); + expect(result.args).toStrictEqual(searchInput); + }); + + it('bulk', async () => { + const wrapper = ElasticSearchClientWrapper.fromClientOptions(osOptions); + + const bulkInput = { + datasource: Readable.from([{}]), + onDocument() { + return { index: { _index: 'xyz' } }; + }, + refreshCompletion: 'xyz', + }; + const result = (await wrapper.bulk(bulkInput)) as any; + + // Should call the OpenSearch client's bulk helper with expected input. + expect(result.client).toBe('os'); + expect(result.args).toStrictEqual(bulkInput); + }); + + it('putIndexTemplate', async () => { + const wrapper = ElasticSearchClientWrapper.fromClientOptions(osOptions); + + const indexTemplate = { name: 'xyz', body: { index_patterns: ['*'] } }; + const result = (await wrapper.putIndexTemplate(indexTemplate)) as any; + + // Should call the OpenSearch client with expected input. + expect(result.client).toBe('os'); + expect(result.args).toStrictEqual(indexTemplate); + }); + + it('indexExists', async () => { + const wrapper = ElasticSearchClientWrapper.fromClientOptions(osOptions); + + const input = { index: 'xyz' }; + const result = (await wrapper.indexExists(input)) as any; + + // Should call the OpenSearch client with expected input. + expect(result.client).toBe('os'); + expect(result.args).toStrictEqual(input); + }); + + it('deleteIndex', async () => { + const wrapper = ElasticSearchClientWrapper.fromClientOptions(osOptions); + + const input = { index: 'xyz' }; + const result = (await wrapper.deleteIndex(input)) as any; + + // Should call the OpenSearch client with expected input. + expect(result.client).toBe('os'); + expect(result.args).toStrictEqual(input); + }); + + it('createIndex', async () => { + const wrapper = ElasticSearchClientWrapper.fromClientOptions(osOptions); + + const input = { index: 'xyz' }; + const result = (await wrapper.createIndex(input)) as any; + + // Should call the OpenSearch client with expected input. + expect(result.client).toBe('os'); + expect(result.args).toStrictEqual(input); + }); + + it('getAliases', async () => { + const wrapper = ElasticSearchClientWrapper.fromClientOptions(osOptions); + + const input = { aliases: ['xyz'] }; + const result = (await wrapper.getAliases(input)) as any; + + // Should call the OpenSearch client with expected input. + expect(result.client).toBe('os'); + expect(result.args).toStrictEqual({ + format: 'json', + name: input.aliases, + }); + }); + + it('updateAliases', async () => { + const wrapper = ElasticSearchClientWrapper.fromClientOptions(osOptions); + + const input = { actions: [{ remove: { index: 'xyz', alias: 'abc' } }] }; + const result = (await wrapper.updateAliases(input)) as any; + + // Should call the OpenSearch client with expected input. + expect(result.client).toBe('os'); + expect(result.args).toStrictEqual({ + body: { actions: input.actions }, + }); + }); + }); +}); diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientWrapper.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientWrapper.ts new file mode 100644 index 0000000000..bcf67e091c --- /dev/null +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchClientWrapper.ts @@ -0,0 +1,209 @@ +/* + * 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 { Client as ElasticSearchClient } from '@elastic/elasticsearch'; +import { Client as OpenSearchClient } from '@opensearch-project/opensearch'; +import { Readable } from 'stream'; +import { + ElasticSearchClientOptions, + isOpenSearchCompatible, +} from './ElasticSearchClientOptions'; +import { ElasticSearchCustomIndexTemplate } from './types'; + +/** + * @public + */ +export type ElasticSearchAliasAction = + | { + remove: { index: any; alias: any }; + add?: undefined; + } + | { + add: { indices: any; alias: any; index?: undefined }; + remove?: undefined; + } + | { + add: { index: any; alias: any; indices?: undefined }; + remove?: undefined; + } + | undefined; + +/** + * @public + */ +export type ElasticSearchIndexAction = { + index: { + _index: string; + [key: string]: any; + }; +}; + +/** + * A wrapper class that exposes logical methods that are conditionally fired + * against either a configured Elasticsearch client or a configured Opensearch + * client. + * + * This is necessary because, despite its intention to be API-compatible, the + * opensearch client does not support API key-based authentication. This is + * also the sanest way to accomplish this while making typescript happy. + * + * In the future, if the differences between implementations become + * unmaintainably divergent, we should split out the Opensearch and + * Elasticsearch search engine implementations. + * + * @public + */ +export class ElasticSearchClientWrapper { + private readonly elasticSearchClient: ElasticSearchClient | undefined; + private readonly openSearchClient: OpenSearchClient | undefined; + + private constructor({ + openSearchClient, + elasticSearchClient, + }: { + openSearchClient?: OpenSearchClient; + elasticSearchClient?: ElasticSearchClient; + }) { + this.openSearchClient = openSearchClient; + this.elasticSearchClient = elasticSearchClient; + } + + static fromClientOptions(options: ElasticSearchClientOptions) { + if (isOpenSearchCompatible(options)) { + return new ElasticSearchClientWrapper({ + openSearchClient: new OpenSearchClient(options), + }); + } + + return new ElasticSearchClientWrapper({ + elasticSearchClient: new ElasticSearchClient(options), + }); + } + + search({ index, body }: { index: string | string[]; body: Object }) { + if (this.openSearchClient) { + return this.openSearchClient.search({ index, body }); + } + + if (this.elasticSearchClient) { + return this.elasticSearchClient.search({ index, body }); + } + + throw new Error('No client defined'); + } + + bulk(bulkOptions: { + datasource: Readable; + onDocument: () => ElasticSearchIndexAction; + refreshOnCompletion?: string | boolean; + }) { + if (this.openSearchClient) { + return this.openSearchClient.helpers.bulk(bulkOptions); + } + + if (this.elasticSearchClient) { + return this.elasticSearchClient.helpers.bulk(bulkOptions); + } + + throw new Error('No client defined'); + } + + putIndexTemplate(template: ElasticSearchCustomIndexTemplate) { + if (this.openSearchClient) { + return this.openSearchClient.indices.putIndexTemplate(template); + } + + if (this.elasticSearchClient) { + return this.elasticSearchClient.indices.putIndexTemplate(template); + } + + throw new Error('No client defined'); + } + + indexExists({ index }: { index: string | string[] }) { + if (this.openSearchClient) { + return this.openSearchClient.indices.exists({ index }); + } + + if (this.elasticSearchClient) { + return this.elasticSearchClient.indices.exists({ index }); + } + + throw new Error('No client defined'); + } + + deleteIndex({ index }: { index: string | string[] }) { + if (this.openSearchClient) { + return this.openSearchClient.indices.delete({ index }); + } + + if (this.elasticSearchClient) { + return this.elasticSearchClient.indices.delete({ index }); + } + + throw new Error('No client defined'); + } + + createIndex({ index }: { index: string }) { + if (this.openSearchClient) { + return this.openSearchClient.indices.create({ index }); + } + + if (this.elasticSearchClient) { + return this.elasticSearchClient.indices.create({ index }); + } + + throw new Error('No client defined'); + } + + getAliases({ aliases }: { aliases: string[] }) { + if (this.openSearchClient) { + return this.openSearchClient.cat.aliases({ + format: 'json', + name: aliases, + }); + } + + if (this.elasticSearchClient) { + return this.elasticSearchClient.cat.aliases({ + format: 'json', + name: aliases, + }); + } + + throw new Error('No client defined'); + } + + updateAliases({ actions }: { actions: ElasticSearchAliasAction[] }) { + const filteredActions = actions.filter(Boolean); + if (this.openSearchClient) { + return this.openSearchClient.indices.updateAliases({ + body: { + actions: filteredActions, + }, + }); + } + + if (this.elasticSearchClient) { + return this.elasticSearchClient.indices.updateAliases({ + body: { + actions: filteredActions, + }, + }); + } + + throw new Error('No client defined'); + } +} diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.test.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.test.ts index 7892b731ed..b59c67c69c 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.test.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.test.ts @@ -16,8 +16,9 @@ import { getVoidLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; -import { Client, errors } from '@elastic/elasticsearch'; +import { errors } from '@elastic/elasticsearch'; import Mock from '@elastic/elasticsearch-mock'; +import { ElasticSearchClientWrapper } from './ElasticSearchClientWrapper'; import { ElasticSearchConcreteQuery, decodePageCursor, @@ -70,7 +71,7 @@ const customIndexTemplate = { describe('ElasticSearchSearchEngine', () => { let testSearchEngine: ElasticSearchSearchEngine; let inspectableSearchEngine: ElasticSearchSearchEngineForTranslatorTests; - let client: Client; + let clientWrapper: ElasticSearchClientWrapper; beforeEach(() => { testSearchEngine = new ElasticSearchSearchEngine( @@ -86,7 +87,7 @@ describe('ElasticSearchSearchEngine', () => { getVoidLogger(), ); // eslint-disable-next-line dot-notation - client = testSearchEngine['elasticSearchClient']; + clientWrapper = testSearchEngine['elasticSearchClientWrapper']; }); describe('custom index template', () => { @@ -686,7 +687,7 @@ describe('ElasticSearchSearchEngine', () => { }); it('should handle index/search type filtering correctly', async () => { - const elasticSearchQuerySpy = jest.spyOn(client, 'search'); + const elasticSearchQuerySpy = jest.spyOn(clientWrapper, 'search'); await testSearchEngine.query({ term: 'testTerm', filters: {}, @@ -725,7 +726,7 @@ describe('ElasticSearchSearchEngine', () => { }); it('should create matchAll query if no term defined', async () => { - const elasticSearchQuerySpy = jest.spyOn(client, 'search'); + const elasticSearchQuerySpy = jest.spyOn(clientWrapper, 'search'); await testSearchEngine.query({ term: '', filters: {}, @@ -759,7 +760,7 @@ describe('ElasticSearchSearchEngine', () => { }); it('should query only specified indices if defined', async () => { - const elasticSearchQuerySpy = jest.spyOn(client, 'search'); + const elasticSearchQuerySpy = jest.spyOn(clientWrapper, 'search'); await testSearchEngine.query({ term: '', filters: {}, @@ -792,6 +793,29 @@ describe('ElasticSearchSearchEngine', () => { elasticSearchQuerySpy.mockClear(); }); + + it('should throws missing index error', async () => { + jest.spyOn(clientWrapper, 'search').mockRejectedValue({ + meta: { + body: { + error: { + type: 'index_not_found_exception', + }, + }, + }, + }); + + await expect( + async () => + await testSearchEngine.query({ + term: 'testTerm', + types: ['unknown'], + filters: {}, + }), + ).rejects.toThrow( + 'Missing index for unknown__search. This means there are no documents to search through.', + ); + }); }); describe('indexer', () => { @@ -809,7 +833,7 @@ describe('ElasticSearchSearchEngine', () => { type: 'test-index', indexPrefix: '', indexSeparator: '-index__', - elasticSearchClient: client, + elasticSearchClientWrapper: clientWrapper, }), ); expect(indexerMock.on).toHaveBeenCalledWith( diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts index 31112e3446..42c99dfe61 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts @@ -14,10 +14,7 @@ * limitations under the License. */ -import { - awsGetCredentials, - createAWSConnection, -} from '@acuris/aws-es-connection'; +import { awsGetCredentials, createAWSConnection } from 'aws-os-connection'; import { Config } from '@backstage/config'; import { IndexableDocument, @@ -26,47 +23,18 @@ import { SearchEngine, SearchQuery, } from '@backstage/plugin-search-common'; -import { Client } from '@elastic/elasticsearch'; +import { MissingIndexError } from '@backstage/plugin-search-backend-node'; import esb from 'elastic-builder'; import { isEmpty, isNaN as nan, isNumber } from 'lodash'; import { v4 as uuid } from 'uuid'; import { Logger } from 'winston'; -import type { ElasticSearchClientOptions } from './ElasticSearchClientOptions'; +import { ElasticSearchClientOptions } from './ElasticSearchClientOptions'; import { ElasticSearchSearchEngineIndexer } from './ElasticSearchSearchEngineIndexer'; +import { ElasticSearchCustomIndexTemplate } from './types'; +import { ElasticSearchClientWrapper } from './ElasticSearchClientWrapper'; export type { ElasticSearchClientOptions }; -/** - * Elasticsearch specific index template - * @public - */ -export type ElasticSearchCustomIndexTemplate = { - name: string; - body: ElasticSearchCustomIndexTemplateBody; -}; - -/** - * Elasticsearch specific index template body - * @public - */ -export type ElasticSearchCustomIndexTemplateBody = { - /** - * Array of wildcard (*) expressions used to match the names of data streams and indices during creation. - */ - index_patterns: string[]; - /** - * An ordered list of component template names. - * Component templates are merged in the order specified, - * meaning that the last component template specified has the highest precedence. - */ - composed_of?: string[]; - /** - * See available properties of template - * https://www.elastic.co/guide/en/elasticsearch/reference/7.15/indices-put-template.html#put-index-template-api-request-body - */ - template?: Record; -}; - /** * Search query that the elasticsearch engine understands. * @public @@ -143,7 +111,7 @@ function isBlank(str: string) { * @public */ export class ElasticSearchSearchEngine implements SearchEngine { - private readonly elasticSearchClient: Client; + private readonly elasticSearchClientWrapper: ElasticSearchClientWrapper; private readonly highlightOptions: ElasticSearchHighlightConfig; constructor( @@ -153,7 +121,8 @@ export class ElasticSearchSearchEngine implements SearchEngine { private readonly logger: Logger, highlightOptions?: ElasticSearchHighlightOptions, ) { - this.elasticSearchClient = this.newClient(options => new Client(options)); + this.elasticSearchClientWrapper = + ElasticSearchClientWrapper.fromClientOptions(elasticSearchClientOptions); const uuidTag = uuid(); this.highlightOptions = { preTag: `<${uuidTag}>`, @@ -177,7 +146,7 @@ export class ElasticSearchSearchEngine implements SearchEngine { if (options.provider === 'elastic') { logger.info('Initializing Elastic.co ElasticSearch search engine.'); } else if (options.provider === 'aws') { - logger.info('Initializing AWS ElasticSearch search engine.'); + logger.info('Initializing AWS OpenSearch search engine.'); } else { logger.info('Initializing ElasticSearch search engine.'); } @@ -269,7 +238,7 @@ export class ElasticSearchSearchEngine implements SearchEngine { async setIndexTemplate(template: ElasticSearchCustomIndexTemplate) { try { - await this.elasticSearchClient.indices.putIndexTemplate(template); + await this.elasticSearchClientWrapper.putIndexTemplate(template); this.logger.info('Custom index template set'); } catch (error) { this.logger.error(`Unable to set custom index template: ${error}`); @@ -284,7 +253,7 @@ export class ElasticSearchSearchEngine implements SearchEngine { indexPrefix: this.indexPrefix, indexSeparator: this.indexSeparator, alias, - elasticSearchClient: this.elasticSearchClient, + elasticSearchClientWrapper: this.elasticSearchClientWrapper, logger: this.logger, }); @@ -292,13 +261,13 @@ export class ElasticSearchSearchEngine implements SearchEngine { indexer.on('error', async e => { this.logger.error(`Failed to index documents for type ${type}`, e); try { - const response = await this.elasticSearchClient.indices.exists({ + const response = await this.elasticSearchClientWrapper.indexExists({ index: indexer.indexName, }); const indexCreated = response.body; if (indexCreated) { this.logger.info(`Removing created index ${indexer.indexName}`); - await this.elasticSearchClient.indices.delete({ + await this.elasticSearchClientWrapper.deleteIndex({ index: indexer.indexName, }); } @@ -319,7 +288,7 @@ export class ElasticSearchSearchEngine implements SearchEngine { ? documentTypes.map(it => this.constructSearchAlias(it)) : this.constructSearchAlias('*'); try { - const result = await this.elasticSearchClient.search({ + const result = await this.elasticSearchClientWrapper.search({ index: queryIndices, body: elasticSearchQuery, }); @@ -361,10 +330,16 @@ export class ElasticSearchSearchEngine implements SearchEngine { nextPageCursor, previousPageCursor, }; - } catch (e) { + } catch (error) { + if (error.meta?.body?.error?.type === 'index_not_found_exception') { + throw new MissingIndexError( + `Missing index for ${queryIndices}. This means there are no documents to search through.`, + error, + ); + } this.logger.error( `Failed to query documents for indices ${queryIndices}`, - e, + error, ); return Promise.reject({ results: [] }); } @@ -398,7 +373,7 @@ export function encodePageCursor({ page }: { page: number }): string { return Buffer.from(`${page}`, 'utf-8').toString('base64'); } -async function createElasticSearchClientOptions( +export async function createElasticSearchClientOptions( config?: Config, ): Promise { if (!config) { diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.test.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.test.ts index 4e0e8e229f..eff056c3f4 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.test.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.test.ts @@ -16,13 +16,13 @@ import { getVoidLogger } from '@backstage/backend-common'; import { TestPipeline } from '@backstage/plugin-search-backend-node'; -import { Client } from '@elastic/elasticsearch'; import Mock from '@elastic/elasticsearch-mock'; import { range } from 'lodash'; +import { ElasticSearchClientWrapper } from './ElasticSearchClientWrapper'; import { ElasticSearchSearchEngineIndexer } from './ElasticSearchSearchEngineIndexer'; const mock = new Mock(); -const client = new Client({ +const clientWrapper = ElasticSearchClientWrapper.fromClientOptions({ node: 'http://localhost:9200', Connection: mock.getConnection(), }); @@ -43,7 +43,7 @@ describe('ElasticSearchSearchEngineIndexer', () => { indexSeparator: '-index__', alias: 'some-type-index__search', logger: getVoidLogger(), - elasticSearchClient: client, + elasticSearchClientWrapper: clientWrapper, }); // Set up all requisite Elastic mocks. diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.ts index fd16d0c963..87a4472a15 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngineIndexer.ts @@ -16,9 +16,9 @@ import { BatchSearchEngineIndexer } from '@backstage/plugin-search-backend-node'; import { IndexableDocument } from '@backstage/plugin-search-common'; -import { Client } from '@elastic/elasticsearch'; import { Readable } from 'stream'; import { Logger } from 'winston'; +import { ElasticSearchClientWrapper } from './ElasticSearchClientWrapper'; /** * Options for instansiate ElasticSearchSearchEngineIndexer @@ -30,7 +30,7 @@ export type ElasticSearchSearchEngineIndexerOptions = { indexSeparator: string; alias: string; logger: Logger; - elasticSearchClient: Client; + elasticSearchClientWrapper: ElasticSearchClientWrapper; }; function duration(startTimestamp: [number, number]): string { @@ -57,7 +57,7 @@ export class ElasticSearchSearchEngineIndexer extends BatchSearchEngineIndexer { private readonly removableAlias: string; private readonly logger: Logger; private readonly sourceStream: Readable; - private readonly elasticSearchClient: Client; + private readonly elasticSearchClientWrapper: ElasticSearchClientWrapper; private bulkResult: Promise; constructor(options: ElasticSearchSearchEngineIndexerOptions) { @@ -70,7 +70,7 @@ export class ElasticSearchSearchEngineIndexer extends BatchSearchEngineIndexer { this.indexName = this.constructIndexName(`${Date.now()}`); this.alias = options.alias; this.removableAlias = `${this.alias}_removable`; - this.elasticSearchClient = options.elasticSearchClient; + this.elasticSearchClientWrapper = options.elasticSearchClientWrapper; // The ES client bulk helper supports stream-based indexing, but we have to // supply the stream directly to it at instantiation-time. We can't supply @@ -83,7 +83,7 @@ export class ElasticSearchSearchEngineIndexer extends BatchSearchEngineIndexer { // Keep a reference to the ES Bulk helper so that we can know when all // documents have been successfully written to ES. - this.bulkResult = this.elasticSearchClient.helpers.bulk({ + this.bulkResult = this.elasticSearchClientWrapper.bulk({ datasource: this.sourceStream, onDocument() { that.processed++; @@ -98,16 +98,15 @@ export class ElasticSearchSearchEngineIndexer extends BatchSearchEngineIndexer { async initialize(): Promise { this.logger.info(`Started indexing documents for index ${this.type}`); - const aliases = await this.elasticSearchClient.cat.aliases({ - format: 'json', - name: [this.alias, this.removableAlias], + const aliases = await this.elasticSearchClientWrapper.getAliases({ + aliases: [this.alias, this.removableAlias], }); this.removableIndices = [ ...new Set(aliases.body.map((r: Record) => r.index)), ] as string[]; - await this.elasticSearchClient.indices.create({ + await this.elasticSearchClientWrapper.createIndex({ index: this.indexName, }); } @@ -140,25 +139,23 @@ export class ElasticSearchSearchEngineIndexer extends BatchSearchEngineIndexer { )}`, result, ); - await this.elasticSearchClient.indices.updateAliases({ - body: { - actions: [ - { - remove: { index: this.constructIndexName('*'), alias: this.alias }, - }, - this.removableIndices.length - ? { - add: { - indices: this.removableIndices, - alias: this.removableAlias, - }, - } - : undefined, - { - add: { index: this.indexName, alias: this.alias }, - }, - ].filter(Boolean), - }, + await this.elasticSearchClientWrapper.updateAliases({ + actions: [ + { + remove: { index: this.constructIndexName('*'), alias: this.alias }, + }, + this.removableIndices.length + ? { + add: { + indices: this.removableIndices, + alias: this.removableAlias, + }, + } + : undefined, + { + add: { index: this.indexName, alias: this.alias }, + }, + ].filter(Boolean), }); // If any indices are removable, remove them. Do not bubble up this error, @@ -166,7 +163,7 @@ export class ElasticSearchSearchEngineIndexer extends BatchSearchEngineIndexer { if (this.removableIndices.length) { this.logger.info('Removing stale search indices', this.removableIndices); try { - await this.elasticSearchClient.indices.delete({ + await this.elasticSearchClientWrapper.deleteIndex({ index: this.removableIndices, }); } catch (e) { diff --git a/plugins/search-backend-module-elasticsearch/src/engines/index.ts b/plugins/search-backend-module-elasticsearch/src/engines/index.ts index 8ac86970a1..8c3b9e3c6d 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/index.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/index.ts @@ -15,13 +15,25 @@ */ export { ElasticSearchSearchEngine } from './ElasticSearchSearchEngine'; +export { isOpenSearchCompatible } from './ElasticSearchClientOptions'; export type { + BaseElasticSearchClientOptions, ElasticSearchAgentOptions, ElasticSearchConnectionConstructor, + ElasticSearchElasticSearchClientOptions, ElasticSearchTransportConstructor, ElasticSearchNodeOptions, ElasticSearchAuth, + OpenSearchAuth, + OpenSearchConnectionConstructor, + OpenSearchElasticSearchClientOptions, + OpenSearchNodeOptions, } from './ElasticSearchClientOptions'; +export type { + ElasticSearchAliasAction, + ElasticSearchClientWrapper, + ElasticSearchIndexAction, +} from './ElasticSearchClientWrapper'; export type { ElasticSearchConcreteQuery, ElasticSearchClientOptions, @@ -30,10 +42,12 @@ export type { ElasticSearchQueryTranslator, ElasticSearchQueryTranslatorOptions, ElasticSearchOptions, - ElasticSearchCustomIndexTemplate, - ElasticSearchCustomIndexTemplateBody, } from './ElasticSearchSearchEngine'; export type { ElasticSearchSearchEngineIndexer, ElasticSearchSearchEngineIndexerOptions, } from './ElasticSearchSearchEngineIndexer'; +export type { + ElasticSearchCustomIndexTemplate, + ElasticSearchCustomIndexTemplateBody, +} from './types'; diff --git a/plugins/search-backend-module-elasticsearch/src/engines/types.ts b/plugins/search-backend-module-elasticsearch/src/engines/types.ts new file mode 100644 index 0000000000..a83e8b09b6 --- /dev/null +++ b/plugins/search-backend-module-elasticsearch/src/engines/types.ts @@ -0,0 +1,46 @@ +/* + * 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. + */ + +/** + * Elasticsearch specific index template + * @public + */ +export type ElasticSearchCustomIndexTemplate = { + name: string; + body: ElasticSearchCustomIndexTemplateBody; +}; + +/** + * Elasticsearch specific index template body + * @public + */ +export type ElasticSearchCustomIndexTemplateBody = { + /** + * Array of wildcard (*) expressions used to match the names of data streams and indices during creation. + */ + index_patterns: string[]; + /** + * An ordered list of component template names. + * Component templates are merged in the order specified, + * meaning that the last component template specified has the highest precedence. + */ + composed_of?: string[]; + /** + * See available properties of template + * https://www.elastic.co/guide/en/elasticsearch/reference/7.15/indices-put-template.html#put-index-template-api-request-body + */ + template?: Record; +}; diff --git a/plugins/search-backend-module-elasticsearch/src/index.ts b/plugins/search-backend-module-elasticsearch/src/index.ts index adf7fa43f2..cb4f62098a 100644 --- a/plugins/search-backend-module-elasticsearch/src/index.ts +++ b/plugins/search-backend-module-elasticsearch/src/index.ts @@ -20,13 +20,18 @@ * @packageDocumentation */ -export { ElasticSearchSearchEngine } from './engines'; +export { ElasticSearchSearchEngine, isOpenSearchCompatible } from './engines'; export type { + BaseElasticSearchClientOptions, ElasticSearchAgentOptions, + ElasticSearchAliasAction, + ElasticSearchClientWrapper, ElasticSearchConcreteQuery, ElasticSearchClientOptions, + ElasticSearchElasticSearchClientOptions, ElasticSearchHighlightConfig, ElasticSearchHighlightOptions, + ElasticSearchIndexAction, ElasticSearchQueryTranslator, ElasticSearchQueryTranslatorOptions, ElasticSearchConnectionConstructor, @@ -38,4 +43,8 @@ export type { ElasticSearchSearchEngineIndexerOptions, ElasticSearchCustomIndexTemplate, ElasticSearchCustomIndexTemplateBody, + OpenSearchAuth, + OpenSearchConnectionConstructor, + OpenSearchElasticSearchClientOptions, + OpenSearchNodeOptions, } from './engines'; diff --git a/plugins/search-backend-module-pg/CHANGELOG.md b/plugins/search-backend-module-pg/CHANGELOG.md index 054c477cfb..fdbf4d01e4 100644 --- a/plugins/search-backend-module-pg/CHANGELOG.md +++ b/plugins/search-backend-module-pg/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-search-backend-module-pg +## 0.3.5-next.2 + +### Patch Changes + +- 423e3d8e95: **DEPRECATED**: `PgSearchEngine` static `from` has been deprecated and will be removed in a future release. Use static `fromConfig` method to instantiate. + + Added support for highlighting matched terms in search result data + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- Updated dependencies + - @backstage/backend-common@0.14.1-next.2 + +## 0.3.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/plugin-search-backend-node@0.6.3-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + ## 0.3.5-next.0 ### Patch Changes diff --git a/plugins/search-backend-module-pg/README.md b/plugins/search-backend-module-pg/README.md index d3f98132aa..49804a927c 100644 --- a/plugins/search-backend-module-pg/README.md +++ b/plugins/search-backend-module-pg/README.md @@ -14,3 +14,31 @@ other plugins. See [Backstage documentation](https://backstage.io/docs/features/search/search-engines#postgres) for details on how to setup Postgres based search for your Backstage instance. + +## Optional Configuration + +The following is an example of the optional configuration that can be applied when using Postgres as the search backend. Currently this is mostly for just the highlight feature: + +```yaml +search: + pg: + highlightOptions: + useHighlight: true # Used to enable to disable the highlight feature. The default value is true + maxWord: 35 # Used to set the longest headlines to output. The default value is 35. + minWord: 15 # Used to set the shortest headlines to output. The default value is 15. + shortWord: 3 # Words of this length or less will be dropped at the start and end of a headline, unless they are query terms. The default value of three (3) eliminates common English articles. + highlightAll: false # If true the whole document will be used as the headline, ignoring the preceding three parameters. The default is false. + maxFragments: 0 # Maximum number of text fragments to display. The default value of zero selects a non-fragment-based headline generation method. A value greater than zero selects fragment-based headline generation (see the linked documentation above for more details). + fragmentDelimiter: ' ... ' # Delimiter string used to concatenate fragments. Defaults to " ... ". +``` + +**Note:** the highlight search term feature uses `ts_headline` which has been known to potentially impact performance. You only need this minimal config to disable it should you have issues: + +```yaml +search: + pg: + highlightOptions: + useHighlight: false +``` + +The Postgres documentation on [Highlighting Results](https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-HEADLINE) has more details. diff --git a/plugins/search-backend-module-pg/api-report.md b/plugins/search-backend-module-pg/api-report.md index 71ceac996e..f7a188a14e 100644 --- a/plugins/search-backend-module-pg/api-report.md +++ b/plugins/search-backend-module-pg/api-report.md @@ -4,6 +4,7 @@ ```ts import { BatchSearchEngineIndexer } from '@backstage/plugin-search-backend-node'; +import { Config } from '@backstage/config'; import { IndexableDocument } from '@backstage/plugin-search-common'; import { IndexableResultSet } from '@backstage/plugin-search-common'; import { Knex } from 'knex'; @@ -11,9 +12,7 @@ import { PluginDatabaseManager } from '@backstage/backend-common'; import { SearchEngine } from '@backstage/plugin-search-backend-node'; import { SearchQuery } from '@backstage/plugin-search-common'; -// Warning: (ae-missing-release-tag) "ConcretePgSearchQuery" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type ConcretePgSearchQuery = { pgQuery: PgSearchQuery; pageSize: number; @@ -43,7 +42,7 @@ export class DatabaseDocumentStore implements DatabaseStore { // (undocumented) query( tx: Knex.Transaction, - { types, pgTerm, fields, offset, limit }: PgSearchQuery, + searchQuery: PgSearchQuery, ): Promise; // (undocumented) static supported(knex: Knex): Promise; @@ -80,23 +79,31 @@ export interface DatabaseStore { // // @public (undocumented) export class PgSearchEngine implements SearchEngine { - constructor(databaseStore: DatabaseStore); - // (undocumented) + // @deprecated + constructor(databaseStore: DatabaseStore, config: Config); + // @deprecated (undocumented) static from(options: { database: PluginDatabaseManager; + config: Config; }): Promise; // (undocumented) + static fromConfig( + config: Config, + options: PgSearchOptions, + ): Promise; + // (undocumented) getIndexer(type: string): Promise; // (undocumented) query(query: SearchQuery): Promise; // (undocumented) - setTranslator( - translator: (query: SearchQuery) => ConcretePgSearchQuery, - ): void; + setTranslator(translator: PgSearchQueryTranslator): void; // (undocumented) static supported(database: PluginDatabaseManager): Promise; // (undocumented) - translator(query: SearchQuery): ConcretePgSearchQuery; + translator( + query: SearchQuery, + options: PgSearchQueryTranslatorOptions, + ): ConcretePgSearchQuery; } // Warning: (ae-missing-release-tag) "PgSearchEngineIndexer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -121,6 +128,24 @@ export type PgSearchEngineIndexerOptions = { databaseStore: DatabaseStore; }; +// @public +export type PgSearchHighlightOptions = { + useHighlight?: boolean; + maxWords?: number; + minWords?: number; + shortWord?: number; + highlightAll?: boolean; + maxFragments?: number; + fragmentDelimiter?: string; + preTag: string; + postTag: string; +}; + +// @public +export type PgSearchOptions = { + database: PluginDatabaseManager; +}; + // Warning: (ae-missing-release-tag) "PgSearchQuery" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -132,11 +157,24 @@ export interface PgSearchQuery { // (undocumented) offset: number; // (undocumented) + options: PgSearchHighlightOptions; + // (undocumented) pgTerm?: string; // (undocumented) types?: string[]; } +// @public +export type PgSearchQueryTranslator = ( + query: SearchQuery, + options: PgSearchQueryTranslatorOptions, +) => ConcretePgSearchQuery; + +// @public +export type PgSearchQueryTranslatorOptions = { + highlightOptions: PgSearchHighlightOptions; +}; + // Warning: (ae-missing-release-tag) "RawDocumentRow" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) diff --git a/plugins/search-backend-module-pg/config.d.ts b/plugins/search-backend-module-pg/config.d.ts new file mode 100644 index 0000000000..7367b770bc --- /dev/null +++ b/plugins/search-backend-module-pg/config.d.ts @@ -0,0 +1,62 @@ +/* + * 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 interface Config { + /** Configuration options for the search plugin */ + search?: { + /** + * Options for PG + */ + pg?: { + /** + * Options for configuring highlight settings + * See https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-HEADLINE + */ + highlightOptions?: { + /** + * Used to enable to disable the highlight feature. The default value is true + */ + useHighlight?: boolean; + /** + * Used to set the longest headlines to output. The default value is 35. + */ + maxWords?: number; + /** + * Used to set the shortest headlines to output. The default value is 15. + */ + minWords?: number; + /** + * Words of this length or less will be dropped at the start and end of a headline, unless they are query terms. + * The default value of three (3) eliminates common English articles. + */ + shortWord?: number; + /** + * If true the whole document will be used as the headline, ignoring the preceding three parameters. The default is false. + */ + highlightAll?: boolean; + /** + * Maximum number of text fragments to display. The default value of zero selects a non-fragment-based headline generation method. + * A value greater than zero selects fragment-based headline generation (see the linked documentation above for more details). + */ + maxFragments?: number; + /** + * Delimiter string used to concatenate fragments. Defaults to " ... ". + */ + fragmentDelimiter?: string; + }; + }; + }; +} diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index cf072f5fe3..9e58859449 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.3.5-next.0", + "version": "0.3.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,18 +23,22 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/plugin-search-backend-node": "^0.6.3-next.0", - "@backstage/plugin-search-common": "^0.3.5", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/config": "^1.0.1", + "@backstage/plugin-search-backend-node": "^0.6.3-next.1", + "@backstage/plugin-search-common": "^0.3.6-next.0", "lodash": "^4.17.21", - "knex": "^1.0.2" + "knex": "^2.0.0", + "uuid": "^8.3.2" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.26-next.0", - "@backstage/cli": "^0.17.3-next.0" + "@backstage/backend-test-utils": "^0.1.26-next.2", + "@backstage/cli": "^0.18.0-next.2" }, "files": [ "dist", - "migrations" - ] + "migrations", + "config.d.ts" + ], + "configSchema": "config.d.ts" } diff --git a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.test.ts b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.test.ts index 3ed002567e..23f8983074 100644 --- a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.test.ts +++ b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.test.ts @@ -13,15 +13,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { ConfigReader } from '@backstage/config'; import { DatabaseStore } from '../database'; import { ConcretePgSearchQuery, decodePageCursor, encodePageCursor, PgSearchEngine, + PgSearchHighlightOptions, } from './PgSearchEngine'; import { PgSearchEngineIndexer } from './PgSearchEngineIndexer'; +const highlightOptions: PgSearchHighlightOptions = { + preTag: '', + postTag: '', + useHighlight: true, + maxWords: 35, + minWords: 15, + shortWord: 3, + highlightAll: false, + maxFragments: 0, + fragmentDelimiter: ' ... ', +}; + +jest.mock('uuid', () => ({ v4: () => 'tag' })); + jest.mock('./PgSearchEngineIndexer', () => ({ PgSearchEngineIndexer: jest .fn() @@ -32,6 +48,13 @@ describe('PgSearchEngine', () => { const tx: any = {} as any; let searchEngine: PgSearchEngine; let database: jest.Mocked; + const config = { + search: { + pg: { + highlightOptions, + }, + }, + }; beforeEach(() => { database = { @@ -42,7 +65,7 @@ describe('PgSearchEngine', () => { completeInsert: jest.fn(), prepareInsert: jest.fn(), }; - searchEngine = new PgSearchEngine(database); + searchEngine = new PgSearchEngine(database, new ConfigReader(config)); }); describe('translator', () => { @@ -58,17 +81,23 @@ describe('PgSearchEngine', () => { filters: {}, }); - expect(translatorSpy).toHaveBeenCalledWith({ - term: 'testTerm', - filters: {}, - }); + expect(translatorSpy).toHaveBeenCalledWith( + { + term: 'testTerm', + filters: {}, + }, + { highlightOptions }, + ); }); it('should pass page cursor', async () => { - const actualTranslatedQuery = searchEngine.translator({ - term: 'Hello', - pageCursor: 'MQ==', - }); + const actualTranslatedQuery = searchEngine.translator( + { + term: 'Hello', + pageCursor: 'MQ==', + }, + { highlightOptions }, + ); expect(actualTranslatedQuery).toMatchObject({ pgQuery: { @@ -81,9 +110,12 @@ describe('PgSearchEngine', () => { }); it('should return translated query term', async () => { - const actualTranslatedQuery = searchEngine.translator({ - term: 'Hello World', - }); + const actualTranslatedQuery = searchEngine.translator( + { + term: 'Hello World', + }, + { highlightOptions }, + ); expect(actualTranslatedQuery).toMatchObject({ pgQuery: { @@ -96,10 +128,13 @@ describe('PgSearchEngine', () => { }); it('should sanitize query term', async () => { - const actualTranslatedQuery = searchEngine.translator({ - term: 'H&e|l!l*o W\0o(r)l:d', - pageCursor: '', - }) as ConcretePgSearchQuery; + const actualTranslatedQuery = searchEngine.translator( + { + term: 'H&e|l!l*o W\0o(r)l:d', + pageCursor: '', + }, + { highlightOptions }, + ) as ConcretePgSearchQuery; expect(actualTranslatedQuery).toMatchObject({ pgQuery: { @@ -110,11 +145,14 @@ describe('PgSearchEngine', () => { }); it('should return translated query with filters', async () => { - const actualTranslatedQuery = searchEngine.translator({ - term: 'testTerm', - filters: { kind: 'testKind' }, - types: ['my-filter'], - }); + const actualTranslatedQuery = searchEngine.translator( + { + term: 'testTerm', + filters: { kind: 'testKind' }, + types: ['my-filter'], + }, + { highlightOptions }, + ); expect(actualTranslatedQuery).toMatchObject({ pgQuery: { @@ -158,6 +196,11 @@ describe('PgSearchEngine', () => { location: 'location-1', }, type: 'my-type', + highlight: { + title: 'Hello World', + text: 'Lorem Ipsum', + location: 'location-1', + }, }, ]); @@ -175,6 +218,16 @@ describe('PgSearchEngine', () => { }, type: 'my-type', rank: 1, + highlight: { + preTag: '', + postTag: '', + fields: { + title: 'Hello World', + text: 'Lorem Ipsum', + location: 'location-1', + path: '', + }, + }, }, ], nextPageCursor: undefined, @@ -184,6 +237,7 @@ describe('PgSearchEngine', () => { pgTerm: '("Hello" | "Hello":*)&("World" | "World":*)', offset: 0, limit: 26, + options: highlightOptions, }); }); @@ -199,6 +253,11 @@ describe('PgSearchEngine', () => { location: `location-${i}`, }, type: 'my-type', + highlight: { + title: 'Hello World', + text: 'Lorem Ipsum', + location: 'location-1', + }, })), ); @@ -217,6 +276,16 @@ describe('PgSearchEngine', () => { }, type: 'my-type', rank: i + 1, + highlight: { + preTag: '', + postTag: '', + fields: { + title: 'Hello World', + text: 'Lorem Ipsum', + location: 'location-1', + path: '', + }, + }, })), nextPageCursor: 'MQ==', }); @@ -225,6 +294,7 @@ describe('PgSearchEngine', () => { pgTerm: '("Hello" | "Hello":*)&("World" | "World":*)', offset: 0, limit: 26, + options: highlightOptions, }); }); @@ -240,6 +310,11 @@ describe('PgSearchEngine', () => { location: `location-${i}`, }, type: 'my-type', + highlight: { + title: 'Hello World', + text: 'Lorem Ipsum', + location: 'location-1', + }, })) .slice(25), ); @@ -260,6 +335,16 @@ describe('PgSearchEngine', () => { }, type: 'my-type', rank: i + 1, + highlight: { + preTag: '', + postTag: '', + fields: { + title: 'Hello World', + text: 'Lorem Ipsum', + location: 'location-1', + path: '', + }, + }, })) .slice(25), previousPageCursor: 'MA==', @@ -269,6 +354,7 @@ describe('PgSearchEngine', () => { pgTerm: '("Hello" | "Hello":*)&("World" | "World":*)', offset: 25, limit: 26, + options: highlightOptions, }); }); }); diff --git a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts index bf98c58de9..abf7cdbf5c 100644 --- a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts +++ b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts @@ -26,20 +26,104 @@ import { DatabaseStore, PgSearchQuery, } from '../database'; +import { v4 as uuid } from 'uuid'; +import { Config } from '@backstage/config'; +/** + * Search query that the Postgres search engine understands. + * @public + */ export type ConcretePgSearchQuery = { pgQuery: PgSearchQuery; pageSize: number; }; -export class PgSearchEngine implements SearchEngine { - constructor(private readonly databaseStore: DatabaseStore) {} +/** + * Options available for the Postgres specific query translator. + * @public + */ +export type PgSearchQueryTranslatorOptions = { + highlightOptions: PgSearchHighlightOptions; +}; +/** + * Postgres specific query translator. + * @public + */ +export type PgSearchQueryTranslator = ( + query: SearchQuery, + options: PgSearchQueryTranslatorOptions, +) => ConcretePgSearchQuery; + +/** + * Options to instantiate PgSearchEngine + * @public + */ +export type PgSearchOptions = { + database: PluginDatabaseManager; +}; + +/** + * Options for highlighting search terms + * @public + */ +export type PgSearchHighlightOptions = { + useHighlight?: boolean; + maxWords?: number; + minWords?: number; + shortWord?: number; + highlightAll?: boolean; + maxFragments?: number; + fragmentDelimiter?: string; + preTag: string; + postTag: string; +}; + +export class PgSearchEngine implements SearchEngine { + private readonly highlightOptions: PgSearchHighlightOptions; + + /** + * @deprecated This will be marked as private in a future release, please us fromConfig instead + */ + constructor(private readonly databaseStore: DatabaseStore, config: Config) { + const uuidTag = uuid(); + const highlightConfig = config.getOptionalConfig( + 'search.pg.highlightOptions', + ); + + const highlightOptions: PgSearchHighlightOptions = { + preTag: `<${uuidTag}>`, + postTag: ``, + useHighlight: highlightConfig?.getOptionalBoolean('useHighlight') ?? true, + maxWords: highlightConfig?.getOptionalNumber('maxWords') ?? 35, + minWords: highlightConfig?.getOptionalNumber('minWords') ?? 15, + shortWord: highlightConfig?.getOptionalNumber('shortWord') ?? 3, + highlightAll: + highlightConfig?.getOptionalBoolean('highlightAll') ?? false, + maxFragments: highlightConfig?.getOptionalNumber('maxFragments') ?? 0, + fragmentDelimiter: + highlightConfig?.getOptionalString('fragmentDelimiter') ?? ' ... ', + }; + this.highlightOptions = highlightOptions; + } + + /** + * @deprecated This will be removed in a future release, please us fromConfig instead + */ static async from(options: { database: PluginDatabaseManager; + config: Config; }): Promise { return new PgSearchEngine( await DatabaseDocumentStore.create(await options.database.getClient()), + options.config, + ); + } + + static async fromConfig(config: Config, options: PgSearchOptions) { + return new PgSearchEngine( + await DatabaseDocumentStore.create(await options.database.getClient()), + config, ); } @@ -47,7 +131,10 @@ export class PgSearchEngine implements SearchEngine { return await DatabaseDocumentStore.supported(await database.getClient()); } - translator(query: SearchQuery): ConcretePgSearchQuery { + translator( + query: SearchQuery, + options: PgSearchQueryTranslatorOptions, + ): ConcretePgSearchQuery { const pageSize = 25; const { page } = decodePageCursor(query.pageCursor); const offset = page * pageSize; @@ -66,14 +153,13 @@ export class PgSearchEngine implements SearchEngine { types: query.types, offset, limit, + options: options.highlightOptions, }, pageSize, }; } - setTranslator( - translator: (query: SearchQuery) => ConcretePgSearchQuery, - ): void { + setTranslator(translator: PgSearchQueryTranslator) { this.translator = translator; } @@ -86,7 +172,9 @@ export class PgSearchEngine implements SearchEngine { } async query(query: SearchQuery): Promise { - const { pgQuery, pageSize } = this.translator(query); + const { pgQuery, pageSize } = this.translator(query, { + highlightOptions: this.highlightOptions, + }); const rows = await this.databaseStore.transaction(async tx => this.databaseStore.query(tx, pgQuery), @@ -106,10 +194,22 @@ export class PgSearchEngine implements SearchEngine { : undefined; const results = pageRows.map( - ({ type, document }, index): IndexableResult => ({ + ({ type, document, highlight }, index): IndexableResult => ({ type, document, rank: page * pageSize + index + 1, + highlight: { + preTag: pgQuery.options.preTag, + postTag: pgQuery.options.postTag, + fields: highlight + ? { + text: highlight.text, + title: highlight.title, + location: highlight.location, + path: '', + } + : {}, + }, }), ); diff --git a/plugins/search-backend-module-pg/src/PgSearchEngine/index.ts b/plugins/search-backend-module-pg/src/PgSearchEngine/index.ts index 7f8e297648..e9ea04e5c4 100644 --- a/plugins/search-backend-module-pg/src/PgSearchEngine/index.ts +++ b/plugins/search-backend-module-pg/src/PgSearchEngine/index.ts @@ -14,7 +14,13 @@ * limitations under the License. */ export { PgSearchEngine } from './PgSearchEngine'; -export type { ConcretePgSearchQuery } from './PgSearchEngine'; +export type { + ConcretePgSearchQuery, + PgSearchQueryTranslatorOptions, + PgSearchQueryTranslator, + PgSearchOptions, + PgSearchHighlightOptions, +} from './PgSearchEngine'; export type { PgSearchEngineIndexer, PgSearchEngineIndexerOptions, diff --git a/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.test.ts b/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.test.ts index b973c2e14f..355e41352d 100644 --- a/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.test.ts +++ b/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.test.ts @@ -15,8 +15,21 @@ */ import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; import { IndexableDocument } from '@backstage/plugin-search-common'; +import { PgSearchHighlightOptions } from '../PgSearchEngine'; import { DatabaseDocumentStore } from './DatabaseDocumentStore'; +const highlightOptions: PgSearchHighlightOptions = { + preTag: '', + postTag: '', + useHighlight: false, + maxWords: 35, + minWords: 15, + shortWord: 3, + highlightAll: false, + maxFragments: 0, + fragmentDelimiter: ' ... ', +}; + describe('DatabaseDocumentStore', () => { describe('unsupported', () => { const databases = TestDatabases.create({ @@ -220,7 +233,12 @@ describe('DatabaseDocumentStore', () => { }); const rows = await store.transaction(tx => - store.query(tx, { pgTerm: 'Hello & World', offset: 1, limit: 1 }), + store.query(tx, { + pgTerm: 'Hello & World', + offset: 1, + limit: 1, + options: highlightOptions, + }), ); expect(rows).toEqual([ @@ -261,7 +279,12 @@ describe('DatabaseDocumentStore', () => { }); const rows = await store.transaction(tx => - store.query(tx, { pgTerm: 'Hello & World', offset: 0, limit: 25 }), + store.query(tx, { + pgTerm: 'Hello & World', + offset: 0, + limit: 25, + options: highlightOptions, + }), ); expect(rows).toEqual([ @@ -322,6 +345,7 @@ describe('DatabaseDocumentStore', () => { types: ['my-type'], offset: 0, limit: 25, + options: highlightOptions, }), ); @@ -375,6 +399,7 @@ describe('DatabaseDocumentStore', () => { fields: { myField: 'this' }, offset: 0, limit: 25, + options: highlightOptions, }), ); @@ -429,6 +454,7 @@ describe('DatabaseDocumentStore', () => { fields: { myField: ['this', 'that'] }, offset: 0, limit: 25, + options: highlightOptions, }), ); @@ -490,6 +516,7 @@ describe('DatabaseDocumentStore', () => { fields: { myField: 'this', otherField: 'another' }, offset: 0, limit: 25, + options: highlightOptions, }), ); @@ -539,6 +566,7 @@ describe('DatabaseDocumentStore', () => { fields: { myField: 'this' }, offset: 0, limit: 25, + options: highlightOptions, }), ); diff --git a/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.ts b/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.ts index 33b2d0c0d6..8e73c0f16f 100644 --- a/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.ts +++ b/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.ts @@ -132,10 +132,13 @@ export class DatabaseDocumentStore implements DatabaseStore { async query( tx: Knex.Transaction, - { types, pgTerm, fields, offset, limit }: PgSearchQuery, + searchQuery: PgSearchQuery, ): Promise { + const { types, pgTerm, fields, offset, limit, options } = searchQuery; + // TODO(awanlin): We should make the language a parameter so that we can support more then just english // Builds a query like: - // SELECT ts_rank_cd(body, query) AS rank, type, document + // SELECT ts_rank_cd(body, query) AS rank, type, document, + // ts_headline('english', document, query) AS highlight // FROM documents, to_tsquery('english', 'consent') query // WHERE query @@ body AND (document @> '{"kind": "API"}') // ORDER BY rank DESC @@ -170,7 +173,17 @@ export class DatabaseDocumentStore implements DatabaseStore { query.select('type', 'document'); - if (pgTerm) { + if (pgTerm && options.useHighlight) { + const headlineOptions = `MaxWords=${options.maxWords}, MinWords=${options.minWords}, ShortWord=${options.shortWord}, HighlightAll=${options.highlightAll}, MaxFragments=${options.maxFragments}, FragmentDelimiter=${options.fragmentDelimiter}, StartSel=${options.preTag}, StopSel=${options.postTag}`; + query + .select(tx.raw('ts_rank_cd(body, query) AS "rank"')) + .select( + tx.raw( + `ts_headline(\'english\', document, query, '${headlineOptions}') as "highlight"`, + ), + ) + .orderBy('rank', 'desc'); + } else if (pgTerm && !options.useHighlight) { query .select(tx.raw('ts_rank_cd(body, query) AS "rank"')) .orderBy('rank', 'desc'); diff --git a/plugins/search-backend-module-pg/src/database/types.ts b/plugins/search-backend-module-pg/src/database/types.ts index 7e87658745..151be7d13f 100644 --- a/plugins/search-backend-module-pg/src/database/types.ts +++ b/plugins/search-backend-module-pg/src/database/types.ts @@ -15,6 +15,7 @@ */ import { IndexableDocument } from '@backstage/plugin-search-common'; import { Knex } from 'knex'; +import { PgSearchHighlightOptions } from '../PgSearchEngine'; export interface PgSearchQuery { fields?: Record; @@ -22,6 +23,7 @@ export interface PgSearchQuery { pgTerm?: string; offset: number; limit: number; + options: PgSearchHighlightOptions; } export interface DatabaseStore { @@ -49,4 +51,5 @@ export interface RawDocumentRow { export interface DocumentResultRow { document: IndexableDocument; type: string; + highlight: IndexableDocument; } diff --git a/plugins/search-backend-node/CHANGELOG.md b/plugins/search-backend-node/CHANGELOG.md index 366cf55e6e..d1b631fd53 100644 --- a/plugins/search-backend-node/CHANGELOG.md +++ b/plugins/search-backend-node/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-search-backend-node +## 0.6.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/backend-tasks@0.3.3-next.1 + - @backstage/plugin-permission-common@0.6.3-next.0 + - @backstage/plugin-search-common@0.3.6-next.0 + ## 0.6.3-next.0 ### Patch Changes diff --git a/plugins/search-backend-node/api-report.md b/plugins/search-backend-node/api-report.md index 7649bc5d0f..ff9480c19d 100644 --- a/plugins/search-backend-node/api-report.md +++ b/plugins/search-backend-node/api-report.md @@ -113,6 +113,12 @@ export class LunrSearchEngineIndexer extends BatchSearchEngineIndexer { initialize(): Promise; } +// @public +export class MissingIndexError extends Error { + constructor(message?: string, cause?: Error | unknown); + readonly cause?: Error | undefined; +} + // @public export class NewlineDelimitedJsonCollatorFactory implements DocumentCollatorFactory diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index 0db5793549..47d613c160 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-node", "description": "A library for Backstage backend plugins that want to interact with the search backend plugin", - "version": "0.6.3-next.0", + "version": "0.6.3-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,12 +23,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/backend-tasks": "^0.3.3-next.0", + "@backstage/backend-common": "^0.14.1-next.1", + "@backstage/backend-tasks": "^0.3.3-next.1", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-permission-common": "^0.6.2", - "@backstage/plugin-search-common": "^0.3.5", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-permission-common": "^0.6.3-next.0", + "@backstage/plugin-search-common": "^0.3.6-next.0", "@types/lunr": "^2.3.3", "lodash": "^4.17.21", "lunr": "^2.3.9", @@ -38,8 +38,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/cli": "^0.17.3-next.0", + "@backstage/backend-common": "^0.14.1-next.1", + "@backstage/cli": "^0.18.0-next.1", "@types/ndjson": "^2.0.1" }, "files": [ diff --git a/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts b/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts index 098d1e8b16..1f69460448 100644 --- a/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts +++ b/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts @@ -949,6 +949,19 @@ describe('LunrSearchEngine', () => { previousPageCursor: undefined, }); }); + + it('should throws missing index error', async () => { + await expect( + async () => + await testLunrSearchEngine.query({ + term: 'testTerm', + types: ['unknown'], + filters: {}, + }), + ).rejects.toThrow( + "Missing index for unknown. This could be because the index hasn't been created yet or there was a problem during index creation.", + ); + }); }); it('should return previous page cursor if on another page', async () => { diff --git a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts index 03cb421653..ec8550d721 100644 --- a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts +++ b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts @@ -21,6 +21,7 @@ import { QueryTranslator, SearchEngine, } from '@backstage/plugin-search-common'; +import { MissingIndexError } from '../errors'; import lunr from 'lunr'; import { v4 as uuid } from 'uuid'; import { Logger } from 'winston'; @@ -163,30 +164,38 @@ export class LunrSearchEngine implements SearchEngine { const results: LunrResultEnvelope[] = []; + const indexKeys = Object.keys(this.lunrIndices).filter( + type => !documentTypes || documentTypes.includes(type), + ); + + if (documentTypes?.length && !indexKeys.length) { + throw new MissingIndexError( + `Missing index for ${documentTypes?.toString()}. This could be because the index hasn't been created yet or there was a problem during index creation.`, + ); + } + // Iterate over the filtered list of this.lunrIndex keys. - Object.keys(this.lunrIndices) - .filter(type => !documentTypes || documentTypes.includes(type)) - .forEach(type => { - try { - results.push( - ...this.lunrIndices[type].query(lunrQueryBuilder).map(result => { - return { - result: result, - type: type, - }; - }), - ); - } catch (err) { - // if a field does not exist on a index, we can see that as a no-match - if ( - err instanceof Error && - err.message.startsWith('unrecognised field') - ) { - return; - } - throw err; + indexKeys.forEach(type => { + try { + results.push( + ...this.lunrIndices[type].query(lunrQueryBuilder).map(result => { + return { + result: result, + type: type, + }; + }), + ); + } catch (err) { + // if a field does not exist on a index, we can see that as a no-match + if ( + err instanceof Error && + err.message.startsWith('unrecognised field') + ) { + return; } - }); + throw err; + } + }); // Sort results. results.sort((doc1, doc2) => { diff --git a/plugins/search-backend-node/src/errors.ts b/plugins/search-backend-node/src/errors.ts new file mode 100644 index 0000000000..00b168d460 --- /dev/null +++ b/plugins/search-backend-node/src/errors.ts @@ -0,0 +1,37 @@ +/* + * 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 { isError } from '@backstage/errors'; + +/** + * Failed to query documents for index that does not exist. + * @public + */ +export class MissingIndexError extends Error { + /** + * An inner error that caused this error to be thrown, if any. + */ + readonly cause?: Error | undefined; + + constructor(message?: string, cause?: Error | unknown) { + super(message); + + Error.captureStackTrace?.(this, this.constructor); + + this.name = this.constructor.name; + this.cause = isError(cause) ? cause : undefined; + } +} diff --git a/plugins/search-backend-node/src/index.ts b/plugins/search-backend-node/src/index.ts index d342bb9259..854881829c 100644 --- a/plugins/search-backend-node/src/index.ts +++ b/plugins/search-backend-node/src/index.ts @@ -34,6 +34,7 @@ export type { RegisterCollatorParameters, RegisterDecoratorParameters, } from './types'; +export * from './errors'; export * from './indexing'; export * from './test-utils'; diff --git a/plugins/search-backend/CHANGELOG.md b/plugins/search-backend/CHANGELOG.md index 9640805095..c779dbef3a 100644 --- a/plugins/search-backend/CHANGELOG.md +++ b/plugins/search-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-search-backend +## 0.5.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/plugin-auth-node@0.2.3-next.1 + - @backstage/plugin-permission-common@0.6.3-next.0 + - @backstage/plugin-permission-node@0.6.3-next.1 + - @backstage/plugin-search-backend-node@0.6.3-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + ## 0.5.4-next.0 ### Patch Changes diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index bd2cc3ecb6..3e2e429b5a 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.5.4-next.0", + "version": "0.5.4-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,14 +23,14 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", + "@backstage/backend-common": "^0.14.1-next.1", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-auth-node": "^0.2.3-next.0", - "@backstage/plugin-permission-common": "^0.6.2", - "@backstage/plugin-permission-node": "^0.6.3-next.0", - "@backstage/plugin-search-backend-node": "^0.6.3-next.0", - "@backstage/plugin-search-common": "^0.3.5", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-auth-node": "^0.2.3-next.1", + "@backstage/plugin-permission-common": "^0.6.3-next.0", + "@backstage/plugin-permission-node": "^0.6.3-next.1", + "@backstage/plugin-search-backend-node": "^0.6.3-next.1", + "@backstage/plugin-search-common": "^0.3.6-next.0", "@backstage/types": "^1.0.0", "@types/express": "^4.17.6", "dataloader": "^2.0.0", @@ -43,7 +43,7 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/search-backend/src/service/router.ts b/plugins/search-backend/src/service/router.ts index f54c2d388f..e4ac233406 100644 --- a/plugins/search-backend/src/service/router.ts +++ b/plugins/search-backend/src/service/router.ts @@ -19,7 +19,7 @@ import Router from 'express-promise-router'; import { Logger } from 'winston'; import { z } from 'zod'; import { errorHandler } from '@backstage/backend-common'; -import { InputError } from '@backstage/errors'; +import { ErrorResponseBody, InputError } from '@backstage/errors'; import { Config } from '@backstage/config'; import { JsonObject, JsonValue } from '@backstage/types'; import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node'; @@ -129,7 +129,10 @@ export async function createRouter( const router = Router(); router.get( '/query', - async (req: express.Request, res: express.Response) => { + async ( + req: express.Request, + res: express.Response, + ) => { const parseResult = requestSchema.safeParse(req.query); if (!parseResult.success) { @@ -154,9 +157,14 @@ export async function createRouter( const resultSet = await engine?.query(query, { token }); res.send(filterResultSet(toSearchResults(resultSet))); - } catch (err) { + } catch (error) { + if (error.name === 'MissingIndexError') { + // re-throw and let the default error handler middleware captures it and serializes it with the right response code on the standard form + throw error; + } + throw new Error( - `There was a problem performing the search query. ${err}`, + `There was a problem performing the search query. ${error}`, ); } }, diff --git a/plugins/search-common/CHANGELOG.md b/plugins/search-common/CHANGELOG.md index 53a8afb0bf..3623d21e93 100644 --- a/plugins/search-common/CHANGELOG.md +++ b/plugins/search-common/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-search-common +## 0.3.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.6.3-next.0 + ## 0.3.5 ### Patch Changes diff --git a/plugins/search-common/package.json b/plugins/search-common/package.json index 86005e8756..65152206e2 100644 --- a/plugins/search-common/package.json +++ b/plugins/search-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-common", "description": "Common functionalities for Search, to be shared between various search-enabled plugins", - "version": "0.3.5", + "version": "0.3.6-next.0", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -40,10 +40,10 @@ }, "dependencies": { "@backstage/types": "^1.0.0", - "@backstage/plugin-permission-common": "^0.6.2" + "@backstage/plugin-permission-common": "^0.6.3-next.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0" + "@backstage/cli": "^0.18.0-next.1" }, "jest": { "roots": [ diff --git a/plugins/search-react/CHANGELOG.md b/plugins/search-react/CHANGELOG.md index 0d203f1c06..685aa56a86 100644 --- a/plugins/search-react/CHANGELOG.md +++ b/plugins/search-react/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-search-react +## 0.2.2-next.2 + +### Patch Changes + +- 60408ca9d4: Fix search pagination to reset page cursor also when a term is cleared. +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## 0.2.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-search-common@0.3.6-next.0 + ## 0.2.2-next.0 ### Patch Changes diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index 925804ea52..3e3b362919 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-react", - "version": "0.2.2-next.0", + "version": "0.2.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,11 +31,11 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/plugin-search-common": "^0.3.5", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/plugin-search-common": "^0.3.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", "@backstage/version-bridge": "^1.0.1", - "@backstage/theme": "^0.2.15", + "@backstage/theme": "^0.2.16-next.1", "@backstage/types": "^1.0.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -49,7 +49,7 @@ }, "devDependencies": { "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/search-react/src/context/SearchContext.test.tsx b/plugins/search-react/src/context/SearchContext.test.tsx index 0272176150..68c79d3a5e 100644 --- a/plugins/search-react/src/context/SearchContext.test.tsx +++ b/plugins/search-react/src/context/SearchContext.test.tsx @@ -108,40 +108,58 @@ describe('SearchContext', () => { expect(result.current).toEqual(expect.objectContaining(initialState)); }); - it('Resets cursor when term is set (and different from previous)', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState: { - ...initialState, - pageCursor: 'SOMEPAGE', + describe('Resets cursor', () => { + it('When term is cleared', async () => { + const { result, waitForNextUpdate } = renderHook(() => useSearch(), { + wrapper, + initialProps: { + initialState: { + ...initialState, + term: 'first term', + pageCursor: 'SOMEPAGE', + }, }, - }, + }); + + await waitForNextUpdate(); + + expect(result.current.term).toEqual('first term'); + expect(result.current.pageCursor).toEqual('SOMEPAGE'); + + act(() => { + result.current.setTerm(''); + }); + + await waitForNextUpdate(); + + expect(result.current.pageCursor).toBeUndefined(); }); - await waitForNextUpdate(); + it('When term is set (and different from previous)', async () => { + const { result, waitForNextUpdate } = renderHook(() => useSearch(), { + wrapper, + initialProps: { + initialState: { + ...initialState, + term: 'first term', + pageCursor: 'SOMEPAGE', + }, + }, + }); - expect(result.current.pageCursor).toEqual('SOMEPAGE'); + await waitForNextUpdate(); - act(() => { - result.current.setTerm('first term'); + expect(result.current.term).toEqual('first term'); + expect(result.current.pageCursor).toEqual('SOMEPAGE'); + + act(() => { + result.current.setTerm('second term'); + }); + + await waitForNextUpdate(); + + expect(result.current.pageCursor).toBeUndefined(); }); - - act(() => { - result.current.setPageCursor('OTHERPAGE'); - }); - - await waitForNextUpdate(); - - expect(result.current.pageCursor).toEqual('OTHERPAGE'); - - act(() => { - result.current.setTerm('second term'); - }); - - await waitForNextUpdate(); - - expect(result.current.pageCursor).toEqual(undefined); }); describe('Performs search (and sets results)', () => { diff --git a/plugins/search-react/src/context/SearchContext.tsx b/plugins/search-react/src/context/SearchContext.tsx index 8a0f962121..faad50f37a 100644 --- a/plugins/search-react/src/context/SearchContext.tsx +++ b/plugins/search-react/src/context/SearchContext.tsx @@ -150,10 +150,11 @@ export const SearchContextProvider = (props: SearchContextProviderProps) => { useEffect(() => { // Any time a term is reset, we want to start from page 0. - if (term && prevTerm && term !== prevTerm) { + // Only reset the term if it has been modified by the user at least once, the initial state must not reset the term. + if (prevTerm !== undefined && term !== prevTerm) { setPageCursor(undefined); } - }, [term, prevTerm, initialState.pageCursor]); + }, [term, prevTerm, setPageCursor]); const value: SearchContextValue = { result, diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index 985b7807c3..707ba1cab7 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-search +## 0.9.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/plugin-search-react@0.2.2-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.9.1-next.1 + +### Patch Changes + +- 509c4092f0: To allow people to use a global search context in the search modal, the code for the search modal has been changed to only create a local search context if there is no parent context already defined. + + If you want to continue using a local context even if you define a global one, you will have to wrap the modal in a new local context manually: + + ```tsx + + + + ``` + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + - @backstage/plugin-search-react@0.2.2-next.1 + ## 0.9.1-next.0 ### Patch Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index 196b09a874..ed700e643f 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.9.1-next.0", + "version": "0.9.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,15 +33,15 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/plugin-search-common": "^0.3.5", - "@backstage/plugin-search-react": "^0.2.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/plugin-search-common": "^0.3.6-next.0", + "@backstage/plugin-search-react": "^0.2.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@backstage/types": "^1.0.0", "@backstage/version-bridge": "^1.0.1", "@material-ui/core": "^4.12.2", @@ -57,10 +57,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", @@ -68,7 +68,7 @@ "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index 7a87d94aa6..28903311c5 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-sentry +## 0.3.45-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.3.45-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.3.45-next.0 ### Patch Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index aaa008b368..7b913fcefe 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.45-next.0", + "version": "0.3.45-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,11 +35,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-table/core": "^3.1.0", "@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.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", @@ -65,7 +65,7 @@ "@types/node": "^16.11.26", "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/shortcuts/CHANGELOG.md b/plugins/shortcuts/CHANGELOG.md index 6343bf2b58..c32e53638c 100644 --- a/plugins/shortcuts/CHANGELOG.md +++ b/plugins/shortcuts/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-shortcuts +## 0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## 0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + ## 0.2.8-next.0 ### Patch Changes diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index 651cbf64e1..2acbd5db5d 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.2.8-next.0", + "version": "0.2.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,9 +24,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/theme": "^0.2.15", + "@backstage/theme": "^0.2.16-next.1", "@backstage/types": "^1.0.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -42,17 +42,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index 01b09623e4..072979d537 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-sonarqube +## 0.3.7-next.2 + +### Patch Changes + +- 15201b1032: Updated dependency `rc-progress` to `3.4.0`. +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.3.7-next.0 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index 6deb2cbebd..beca17ae35 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sonarqube", "description": "", - "version": "0.3.7-next.0", + "version": "0.3.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -36,33 +36,33 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "@material-ui/styles": "^4.10.0", "cross-fetch": "^3.1.5", - "rc-progress": "3.3.3", + "rc-progress": "3.4.0", "react-use": "^17.2.4" }, "peerDependencies": { "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/splunk-on-call/CHANGELOG.md b/plugins/splunk-on-call/CHANGELOG.md index d7f227a116..c48e6acab2 100644 --- a/plugins/splunk-on-call/CHANGELOG.md +++ b/plugins/splunk-on-call/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-splunk-on-call +## 0.3.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.3.31-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.3.31-next.0 ### Patch Changes diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index ca97ebca34..6d0b2ac632 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.31-next.0", + "version": "0.3.31-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,11 +34,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -51,10 +51,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", @@ -62,7 +62,7 @@ "@types/luxon": "^2.0.4", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "configSchema": "config.d.ts", "files": [ diff --git a/plugins/stack-overflow-backend/CHANGELOG.md b/plugins/stack-overflow-backend/CHANGELOG.md index 9f3a2d98a3..6c19f2bfe4 100644 --- a/plugins/stack-overflow-backend/CHANGELOG.md +++ b/plugins/stack-overflow-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-stack-overflow-backend +## 0.1.3-next.0 + +### Patch Changes + +- 52b4f796e3: app-config is now picked up properly. +- Updated dependencies + - @backstage/plugin-search-common@0.3.6-next.0 + ## 0.1.2 ### Patch Changes diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index 083ab18b42..07cdbfb242 100644 --- a/plugins/stack-overflow-backend/package.json +++ b/plugins/stack-overflow-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-stack-overflow-backend", - "version": "0.1.2", + "version": "0.1.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,7 +33,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/plugin-search-common": "^0.3.5", + "@backstage/plugin-search-common": "^0.3.6-next.0", "@backstage/config": "^1.0.1", "qs": "^6.9.4", "cross-fetch": "^3.1.5", diff --git a/plugins/stack-overflow/CHANGELOG.md b/plugins/stack-overflow/CHANGELOG.md index 0b0845b7b6..bbba0a273d 100644 --- a/plugins/stack-overflow/CHANGELOG.md +++ b/plugins/stack-overflow/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-stack-overflow +## 0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-home@0.4.23-next.2 + +## 0.1.3-next.1 + +### Patch Changes + +- 52b4f796e3: app-config is now picked up properly. +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/plugin-home@0.4.23-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-search-common@0.3.6-next.0 + ## 0.1.3-next.0 ### Patch Changes diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index 793e42881d..e1245b743a 100644 --- a/plugins/stack-overflow/package.json +++ b/plugins/stack-overflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-stack-overflow", - "version": "0.1.3-next.0", + "version": "0.1.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,11 +24,11 @@ }, "dependencies": { "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/plugin-home": "^0.4.23-next.0", - "@backstage/plugin-search-common": "^0.3.5", - "@backstage/theme": "^0.2.15", + "@backstage/plugin-home": "^0.4.23-next.2", + "@backstage/plugin-search-common": "^0.3.6-next.0", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@testing-library/jest-dom": "^5.10.1", @@ -42,15 +42,15 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md index 3911f2111f..4be66cb389 100644 --- a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md +++ b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-tech-insights-backend-module-jsonfc +## 0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + ## 0.1.18-next.0 ### Patch Changes diff --git a/plugins/tech-insights-backend-module-jsonfc/package.json b/plugins/tech-insights-backend-module-jsonfc/package.json index c1d9b020e6..d0b3626ac5 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.18-next.0", + "version": "0.1.18-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,9 +34,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", + "@backstage/backend-common": "^0.14.1-next.1", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", + "@backstage/errors": "^1.1.0-next.0", "@backstage/plugin-tech-insights-common": "^0.2.4", "@backstage/plugin-tech-insights-node": "^0.3.2-next.0", "ajv": "^8.10.0", @@ -46,7 +46,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0" + "@backstage/cli": "^0.18.0-next.1" }, "files": [ "dist" diff --git a/plugins/tech-insights-backend/CHANGELOG.md b/plugins/tech-insights-backend/CHANGELOG.md index 41b303b5ca..9a08f51d33 100644 --- a/plugins/tech-insights-backend/CHANGELOG.md +++ b/plugins/tech-insights-backend/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-tech-insights-backend +## 0.5.0-next.2 + +### Minor Changes + +- 818fa28d71: Allow FactRetrieverRegistry to be injected into buildTechInsightsContext so that we can override default registry implementation. + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + - @backstage/backend-tasks@0.3.3-next.2 + +## 0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/backend-tasks@0.3.3-next.1 + - @backstage/catalog-client@1.0.4-next.1 + ## 0.4.2-next.0 ### Patch Changes diff --git a/plugins/tech-insights-backend/api-report.md b/plugins/tech-insights-backend/api-report.md index 9fee3be281..32d45f8afd 100644 --- a/plugins/tech-insights-backend/api-report.md +++ b/plugins/tech-insights-backend/api-report.md @@ -11,6 +11,7 @@ import { FactCheckerFactory } from '@backstage/plugin-tech-insights-node'; import { FactLifecycle } from '@backstage/plugin-tech-insights-node'; import { FactRetriever } from '@backstage/plugin-tech-insights-node'; import { FactRetrieverRegistration } from '@backstage/plugin-tech-insights-node'; +import { FactSchema } from '@backstage/plugin-tech-insights-node'; import { Logger } from 'winston'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; @@ -51,6 +52,22 @@ export type FactRetrieverRegistrationOptions = { lifecycle?: FactLifecycle; }; +// @public (undocumented) +export interface FactRetrieverRegistry { + // (undocumented) + get(retrieverReference: string): FactRetrieverRegistration; + // (undocumented) + getSchemas(): FactSchema[]; + // (undocumented) + listRegistrations(): FactRetrieverRegistration[]; + // (undocumented) + listRetrievers(): FactRetriever[]; + // (undocumented) + register(registration: FactRetrieverRegistration): void; + // (undocumented) + readonly retrievers: Map; +} + // @public export type PersistenceContext = { techInsightsStore: TechInsightsStore; @@ -91,7 +108,8 @@ export interface TechInsightsOptions< // (undocumented) discovery: PluginEndpointDiscovery; factCheckerFactory?: FactCheckerFactory; - factRetrievers: FactRetrieverRegistration[]; + factRetrieverRegistry?: FactRetrieverRegistry; + factRetrievers?: FactRetrieverRegistration[]; // (undocumented) logger: Logger; // (undocumented) diff --git a/plugins/tech-insights-backend/package.json b/plugins/tech-insights-backend/package.json index 5461f22789..0ecdb6b6e8 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.4.2-next.0", + "version": "0.5.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,18 +34,18 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/backend-tasks": "^0.3.3-next.0", - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/backend-tasks": "^0.3.3-next.2", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", + "@backstage/errors": "^1.1.0-next.0", "@backstage/plugin-tech-insights-common": "^0.2.4", "@backstage/plugin-tech-insights-node": "^0.3.2-next.0", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", - "knex": "^1.0.2", + "knex": "^2.0.0", "lodash": "^4.17.21", "luxon": "^2.0.2", "semver": "^7.3.5", @@ -54,8 +54,8 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.26-next.0", - "@backstage/cli": "^0.17.3-next.0", + "@backstage/backend-test-utils": "^0.1.26-next.2", + "@backstage/cli": "^0.18.0-next.2", "@types/supertest": "^2.0.8", "@types/semver": "^7.3.8", "supertest": "^6.1.3", diff --git a/plugins/tech-insights-backend/src/index.ts b/plugins/tech-insights-backend/src/index.ts index 82fda47367..66180b1006 100644 --- a/plugins/tech-insights-backend/src/index.ts +++ b/plugins/tech-insights-backend/src/index.ts @@ -25,5 +25,6 @@ export type { export type { PersistenceContext } from './service/persistence/persistenceContext'; export { createFactRetrieverRegistration } from './service/fact/createFactRetriever'; +export type { FactRetrieverRegistry } from './service/fact/FactRetrieverRegistry'; export type { FactRetrieverRegistrationOptions } from './service/fact/createFactRetriever'; export * from './service/fact/factRetrievers'; diff --git a/plugins/tech-insights-backend/src/service/fact/FactRetrieverRegistry.ts b/plugins/tech-insights-backend/src/service/fact/FactRetrieverRegistry.ts index b122f52f0a..504d561f17 100644 --- a/plugins/tech-insights-backend/src/service/fact/FactRetrieverRegistry.ts +++ b/plugins/tech-insights-backend/src/service/fact/FactRetrieverRegistry.ts @@ -21,8 +21,21 @@ import { } from '@backstage/plugin-tech-insights-node'; import { ConflictError, NotFoundError } from '@backstage/errors'; -export class FactRetrieverRegistry { - private readonly retrievers = new Map(); +/** + * @public + * + */ +export interface FactRetrieverRegistry { + readonly retrievers: Map; + register(registration: FactRetrieverRegistration): void; + get(retrieverReference: string): FactRetrieverRegistration; + listRetrievers(): FactRetriever[]; + listRegistrations(): FactRetrieverRegistration[]; + getSchemas(): FactSchema[]; +} + +export class DefaultFactRetrieverRegistry implements FactRetrieverRegistry { + readonly retrievers = new Map(); constructor(retrievers: FactRetrieverRegistration[]) { retrievers.forEach(it => { diff --git a/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.test.ts b/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.test.ts new file mode 100644 index 0000000000..82f504c8a8 --- /dev/null +++ b/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.test.ts @@ -0,0 +1,91 @@ +/* + * 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 { buildTechInsightsContext } from './techInsightsContextBuilder'; +import { + DatabaseManager, + getVoidLogger, + PluginDatabaseManager, + ServerTokenManager, +} from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { TaskScheduler } from '@backstage/backend-tasks'; +import { DefaultFactRetrieverRegistry } from './fact/FactRetrieverRegistry'; +import { Knex } from 'knex'; + +jest.mock('./fact/FactRetrieverRegistry'); +jest.mock('./fact/FactRetrieverEngine', () => ({ + FactRetrieverEngine: { + create: jest.fn().mockResolvedValue({ + schedule: jest.fn(), + }), + }, +})); + +describe('buildTechInsightsContext', () => { + const pluginDatabase: PluginDatabaseManager = { + getClient: () => { + return Promise.resolve({ + migrate: { + latest: () => {}, + }, + }) as unknown as Promise; + }, + }; + const databaseManager: Partial = { + forPlugin: () => pluginDatabase, + }; + const manager = databaseManager as DatabaseManager; + const discoveryMock = { + getBaseUrl: (_: string) => Promise.resolve('http://mock.url'), + getExternalBaseUrl: (_: string) => Promise.resolve('http://mock.url'), + }; + const scheduler = new TaskScheduler(manager, getVoidLogger()).forPlugin( + 'tech-insights', + ); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('constructs the default FactRetrieverRegistry if factRetrievers but no factRetrieverRegistry are passed', () => { + buildTechInsightsContext({ + database: pluginDatabase, + logger: getVoidLogger(), + factRetrievers: [], + scheduler: scheduler, + config: ConfigReader.fromConfigs([]), + discovery: discoveryMock, + tokenManager: ServerTokenManager.noop(), + }); + expect(DefaultFactRetrieverRegistry).toHaveBeenCalledTimes(1); + }); + + it('uses factRetrieverRegistry implementation instead of the default FactRetrieverRegistry if it is passed in', () => { + const factRetrieverRegistryMock = {} as DefaultFactRetrieverRegistry; + + buildTechInsightsContext({ + database: pluginDatabase, + logger: getVoidLogger(), + factRetrievers: [], + factRetrieverRegistry: factRetrieverRegistryMock, + scheduler: scheduler, + config: ConfigReader.fromConfigs([]), + discovery: discoveryMock, + tokenManager: ServerTokenManager.noop(), + }); + expect(DefaultFactRetrieverRegistry).not.toHaveBeenCalled(); + }); +}); diff --git a/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.ts b/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.ts index e22bfbd253..008acf192d 100644 --- a/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.ts +++ b/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.ts @@ -16,7 +16,10 @@ import { FactRetrieverEngine } from './fact/FactRetrieverEngine'; import { Logger } from 'winston'; -import { FactRetrieverRegistry } from './fact/FactRetrieverRegistry'; +import { + DefaultFactRetrieverRegistry, + FactRetrieverRegistry, +} from './fact/FactRetrieverRegistry'; import { Config } from '@backstage/config'; import { PluginDatabaseManager, @@ -49,16 +52,25 @@ export interface TechInsightsOptions< CheckResultType extends CheckResult, > { /** - * A collection of FactRetrieverRegistrations. + * Optional collection of FactRetrieverRegistrations (required if no factRetrieverRegistry passed in). * Used to register FactRetrievers and their schemas and schedule an execution loop for them. + * + * Not needed if passing in your own FactRetrieverRegistry implementation. Required otherwise. */ - factRetrievers: FactRetrieverRegistration[]; + factRetrievers?: FactRetrieverRegistration[]; /** * Optional factory exposing a `construct` method to initialize a FactChecker implementation */ factCheckerFactory?: FactCheckerFactory; + /** + * Optional FactRetrieverRegistry implementation that replaces the default one. + * + * If passing this in you don't need to pass in factRetrievers also. + */ + factRetrieverRegistry?: FactRetrieverRegistry; + logger: Logger; config: Config; discovery: PluginEndpointDiscovery; @@ -109,7 +121,19 @@ export const buildTechInsightsContext = async < tokenManager, } = options; - const factRetrieverRegistry = new FactRetrieverRegistry(factRetrievers); + const buildFactRetrieverRegistry = (): FactRetrieverRegistry => { + if (!options.factRetrieverRegistry) { + if (!factRetrievers) { + throw new Error( + 'Failed to build FactRetrieverRegistry because no factRetrievers found', + ); + } + return new DefaultFactRetrieverRegistry(factRetrievers); + } + return options.factRetrieverRegistry; + }; + + const factRetrieverRegistry = buildFactRetrieverRegistry(); const persistenceContext = await initializePersistenceContext( await database.getClient(), diff --git a/plugins/tech-insights-common/package.json b/plugins/tech-insights-common/package.json index 5d6bc49611..14ec147bb9 100644 --- a/plugins/tech-insights-common/package.json +++ b/plugins/tech-insights-common/package.json @@ -38,7 +38,7 @@ "@backstage/types": "^1.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0" + "@backstage/cli": "^0.18.0-next.1" }, "files": [ "dist" diff --git a/plugins/tech-insights-node/package.json b/plugins/tech-insights-node/package.json index f4e53ca987..3139865ddf 100644 --- a/plugins/tech-insights-node/package.json +++ b/plugins/tech-insights-node/package.json @@ -33,7 +33,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", + "@backstage/backend-common": "^0.14.1-next.1", "@backstage/config": "^1.0.1", "@backstage/plugin-tech-insights-common": "^0.2.4", "@backstage/types": "^1.0.0", @@ -42,7 +42,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0" + "@backstage/cli": "^0.18.0-next.1" }, "files": [ "dist" diff --git a/plugins/tech-insights/CHANGELOG.md b/plugins/tech-insights/CHANGELOG.md index 3a900ddda9..68e60fd0d1 100644 --- a/plugins/tech-insights/CHANGELOG.md +++ b/plugins/tech-insights/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-tech-insights +## 0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.2.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.2.3-next.0 ### Patch Changes diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index bcf8037b5d..75308d67bc 100644 --- a/plugins/tech-insights/package.json +++ b/plugins/tech-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights", - "version": "0.2.3-next.0", + "version": "0.2.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -28,13 +28,13 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", "@backstage/plugin-tech-insights-common": "^0.2.4", - "@backstage/theme": "^0.2.15", + "@backstage/theme": "^0.2.16-next.1", "@backstage/types": "^1.0.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -47,17 +47,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/tech-radar/CHANGELOG.md b/plugins/tech-radar/CHANGELOG.md index 96455c64b1..99d537779f 100644 --- a/plugins/tech-radar/CHANGELOG.md +++ b/plugins/tech-radar/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-tech-radar +## 0.5.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## 0.5.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + ## 0.5.14-next.0 ### Patch Changes diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 4bd4462cd1..421297fcca 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.14-next.0", + "version": "0.5.14-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,9 +34,9 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/theme": "^0.2.15", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -49,10 +49,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", @@ -62,7 +62,7 @@ "@types/node": "^16.11.26", "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/techdocs-addons-test-utils/CHANGELOG.md b/plugins/techdocs-addons-test-utils/CHANGELOG.md index 711a426a6a..667c189a99 100644 --- a/plugins/techdocs-addons-test-utils/CHANGELOG.md +++ b/plugins/techdocs-addons-test-utils/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-techdocs-addons-test-utils +## 1.0.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/plugin-search-react@0.2.2-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-techdocs@1.2.1-next.2 + - @backstage/plugin-catalog@1.4.0-next.2 + - @backstage/integration-react@1.1.2-next.2 + - @backstage/plugin-techdocs-react@1.0.2-next.1 + +## 1.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/plugin-catalog@1.3.1-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-techdocs@1.2.1-next.1 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/test-utils@1.1.2-next.1 + - @backstage/plugin-search-react@0.2.2-next.1 + ## 1.0.2-next.0 ### Patch Changes diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index 0debd31d49..34580c7475 100644 --- a/plugins/techdocs-addons-test-utils/package.json +++ b/plugins/techdocs-addons-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-addons-test-utils", - "version": "1.0.2-next.0", + "version": "1.0.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,16 +32,16 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/integration-react": "^1.1.2-next.0", - "@backstage/plugin-catalog": "^1.3.1-next.0", - "@backstage/plugin-search-react": "^0.2.2-next.0", - "@backstage/plugin-techdocs": "^1.2.1-next.0", - "@backstage/plugin-techdocs-react": "^1.0.2-next.0", - "@backstage/test-utils": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/integration-react": "^1.1.2-next.2", + "@backstage/plugin-catalog": "^1.4.0-next.2", + "@backstage/plugin-search-react": "^0.2.2-next.2", + "@backstage/plugin-techdocs": "^1.2.1-next.2", + "@backstage/plugin-techdocs-react": "^1.0.2-next.1", + "@backstage/test-utils": "^1.1.2-next.1", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -56,14 +56,14 @@ "react-dom": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", + "@backstage/cli": "^0.18.0-next.2", + "@backstage/dev-utils": "^1.0.4-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", - "msw": "^0.42.0", + "msw": "^0.43.0", "cross-fetch": "^3.1.5" }, "files": [ diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index b8bdde8fca..3039a7c50c 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/plugin-techdocs-backend +## 1.2.0-next.2 + +### Patch Changes + +- 679b32172e: Updated dependency `knex` to `^2.0.0`. +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + - @backstage/integration@1.2.2-next.2 + - @backstage/plugin-techdocs-node@1.2.0-next.2 + +## 1.2.0-next.1 + +### Minor Changes + +- 860765ff45: Added local publishing target directory `config`: `techdocs.publisher.local.publishDirectory` + +### Patch Changes + +- 726577958f: Add sample headings on the documented component homepage. +- Updated dependencies + - @backstage/plugin-techdocs-node@1.2.0-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + - @backstage/plugin-catalog-common@1.0.4-next.0 + - @backstage/plugin-permission-common@0.6.3-next.0 + - @backstage/plugin-search-common@0.3.6-next.0 + ## 1.1.3-next.0 ### Patch Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index bf29eeb9af..deabdea689 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-backend", "description": "The Backstage backend plugin that renders technical documentation for your components", - "version": "1.1.3-next.0", + "version": "1.2.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,33 +34,33 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/plugin-catalog-common": "^1.0.3", - "@backstage/plugin-permission-common": "^0.6.2", - "@backstage/plugin-search-common": "^0.3.5", - "@backstage/plugin-techdocs-node": "^1.1.3-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.2", + "@backstage/plugin-catalog-common": "^1.0.4-next.0", + "@backstage/plugin-permission-common": "^0.6.3-next.0", + "@backstage/plugin-search-common": "^0.3.6-next.0", + "@backstage/plugin-techdocs-node": "^1.2.0-next.2", "@types/express": "^4.17.6", "dockerode": "^3.3.1", "express": "^4.17.1", "express-promise-router": "^4.1.0", "fs-extra": "10.1.0", - "knex": "^1.0.2", + "knex": "^2.0.0", "lodash": "^4.17.21", "node-fetch": "^2.6.7", "p-limit": "^3.1.0", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.26-next.0", - "@backstage/cli": "^0.17.3-next.0", - "@backstage/plugin-search-backend-node": "0.6.3-next.0", + "@backstage/backend-test-utils": "^0.1.26-next.2", + "@backstage/cli": "^0.18.0-next.2", + "@backstage/plugin-search-backend-node": "0.6.3-next.1", "@types/dockerode": "^3.3.0", - "msw": "^0.42.0", + "msw": "^0.43.0", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/techdocs-module-addons-contrib/CHANGELOG.md b/plugins/techdocs-module-addons-contrib/CHANGELOG.md index 1a1d9812bb..049cf72493 100644 --- a/plugins/techdocs-module-addons-contrib/CHANGELOG.md +++ b/plugins/techdocs-module-addons-contrib/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-techdocs-module-addons-contrib +## 1.0.2-next.2 + +### Patch Changes + +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/integration@1.2.2-next.2 + - @backstage/integration-react@1.1.2-next.2 + - @backstage/plugin-techdocs-react@1.0.2-next.1 + +## 1.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + - @backstage/integration@1.2.2-next.1 + - @backstage/integration-react@1.1.2-next.1 + ## 1.0.2-next.0 ### Patch Changes diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 864262b773..e089428dbe 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-module-addons-contrib", "description": "Plugin module for contributed TechDocs Addons", - "version": "1.0.2-next.0", + "version": "1.0.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,35 +34,35 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/integration-react": "^1.1.2-next.0", - "@backstage/plugin-techdocs-react": "^1.0.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/integration": "^1.2.2-next.2", + "@backstage/integration-react": "^1.1.2-next.2", + "@backstage/plugin-techdocs-react": "^1.0.2-next.1", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "@react-hookz/web": "^14.0.0", - "git-url-parse": "^11.6.0", + "git-url-parse": "^12.0.0", "react-use": "^17.2.4" }, "peerDependencies": { "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/plugin-techdocs-addons-test-utils": "^1.0.2-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/plugin-techdocs-addons-test-utils": "^1.0.2-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "@types/react": "^16.13.1 || ^17.0.0", - "msw": "^0.42.0", + "msw": "^0.43.0", "cross-fetch": "^3.1.5" }, "files": [ diff --git a/plugins/techdocs-node/CHANGELOG.md b/plugins/techdocs-node/CHANGELOG.md index 8a99e3a036..159966eaae 100644 --- a/plugins/techdocs-node/CHANGELOG.md +++ b/plugins/techdocs-node/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-techdocs-node +## 1.2.0-next.2 + +### Patch Changes + +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/backend-common@0.14.1-next.2 + - @backstage/integration@1.2.2-next.2 + +## 1.2.0-next.1 + +### Minor Changes + +- 860765ff45: Added local publishing target directory `config`: `techdocs.publisher.local.publishDirectory` + +### Patch Changes + +- a5d73da942: Fix the flag parsing for `legacyCopyReadmeMdToIndexMd` in `techdocs-cli generate` command, and decouple it's logic from the `techdocs-ref` flag. +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/integration@1.2.2-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + ## 1.1.3-next.0 ### Patch Changes diff --git a/plugins/techdocs-node/package.json b/plugins/techdocs-node/package.json index 8d9e493d05..24ca02de8a 100644 --- a/plugins/techdocs-node/package.json +++ b/plugins/techdocs-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-node", "description": "Common node.js functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", - "version": "1.1.3-next.0", + "version": "1.2.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -42,19 +42,19 @@ "dependencies": { "@azure/identity": "^2.0.1", "@azure/storage-blob": "^12.5.0", - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/plugin-search-common": "^0.3.5", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.2", + "@backstage/plugin-search-common": "^0.3.6-next.0", "@google-cloud/storage": "^6.0.0", "@trendyol-js/openstack-swift-sdk": "^0.0.5", "@types/express": "^4.17.6", "aws-sdk": "^2.840.0", "express": "^4.17.1", "fs-extra": "10.1.0", - "git-url-parse": "^11.6.0", + "git-url-parse": "^12.0.0", "js-yaml": "^4.0.0", "json5": "^2.1.3", "mime-types": "^2.1.27", @@ -64,7 +64,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@types/fs-extra": "^9.0.5", "@types/js-yaml": "^4.0.0", "@types/mime-types": "^2.1.0", diff --git a/plugins/techdocs-react/CHANGELOG.md b/plugins/techdocs-react/CHANGELOG.md index 6feb9062d3..aa839600c3 100644 --- a/plugins/techdocs-react/CHANGELOG.md +++ b/plugins/techdocs-react/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-techdocs-react +## 1.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + ## 1.0.2-next.0 ### Patch Changes diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index 698cff4c84..042dd4c81b 100644 --- a/plugins/techdocs-react/package.json +++ b/plugins/techdocs-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-react", "description": "Shared frontend utilities for TechDocs and Addons", - "version": "1.0.2-next.0", + "version": "1.0.2-next.1", "private": false, "publishConfig": { "access": "public", @@ -35,8 +35,8 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", "@backstage/version-bridge": "^1.0.1", "@material-ui/core": "^4.12.2", @@ -56,8 +56,8 @@ "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", - "@backstage/test-utils": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15" + "@backstage/test-utils": "^1.1.2-next.1", + "@backstage/theme": "^0.2.16-next.1" }, "files": [ "alpha", diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index b7367c4ee5..aad89b46cf 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-techdocs +## 1.2.1-next.2 + +### Patch Changes + +- e2d7b76f43: Upgrade git-url-parse to 12.0.0. + + Motivation for upgrade is transitively upgrading parse-url which is vulnerable + to several CVEs detected by Snyk. + + - SNYK-JS-PARSEURL-2935944 + - SNYK-JS-PARSEURL-2935947 + - SNYK-JS-PARSEURL-2936249 + +- 7739141ab2: Fix: When docs are shown in an entity page under the docs tab the sidebars start overlapping with the header and tabs in the page when you scroll the documentation content. +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/plugin-search-react@0.2.2-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/integration@1.2.2-next.2 + - @backstage/plugin-catalog-react@1.1.2-next.2 + - @backstage/integration-react@1.1.2-next.2 + - @backstage/plugin-techdocs-react@1.0.2-next.1 + +## 1.2.1-next.1 + +### Patch Changes + +- 726577958f: Remove the 60% factor from the font size calculation of headers to use the exact size defined in BackstageTheme. +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/integration@1.2.2-next.1 + - @backstage/integration-react@1.1.2-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.1 + - @backstage/plugin-search-common@0.3.6-next.0 + - @backstage/plugin-search-react@0.2.2-next.1 + ## 1.2.1-next.0 ### Patch Changes diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 9890173851..55b4a7c707 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs", "description": "The Backstage plugin that renders technical documentation for your components", - "version": "1.2.1-next.0", + "version": "1.2.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,25 +35,25 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", - "@backstage/integration-react": "^1.1.2-next.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/plugin-search-common": "^0.3.5", - "@backstage/plugin-search-react": "^0.2.2-next.0", - "@backstage/plugin-techdocs-react": "^1.0.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.2", + "@backstage/integration-react": "^1.1.2-next.2", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/plugin-search-common": "^0.3.6-next.0", + "@backstage/plugin-search-react": "^0.2.2-next.2", + "@backstage/plugin-techdocs-react": "^1.0.2-next.1", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "@material-ui/styles": "^4.10.0", "dompurify": "^2.2.9", "event-source-polyfill": "1.0.25", - "git-url-parse": "^11.6.0", + "git-url-parse": "^12.0.0", "jss": "~10.8.2", "lodash": "^4.17.21", "react-helmet": "6.1.0", @@ -67,10 +67,10 @@ "react-dom": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", @@ -81,7 +81,7 @@ "@types/node": "^16.11.26", "canvas": "^2.6.1", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist", diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx index 6885957002..9f69dcb8d8 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx @@ -106,16 +106,18 @@ export const TechDocsReaderPage = (props: TechDocsReaderPageProps) => { return ( {({ metadata, entityMetadata, onReady }) => ( - - {children instanceof Function - ? children({ - entityRef, - techdocsMetadataValue: metadata.value, - entityMetadataValue: entityMetadata.value, - onReady, - }) - : children} - +
+ + {children instanceof Function + ? children({ + entityRef, + techdocsMetadataValue: metadata.value, + entityMetadataValue: entityMetadata.value, + onReady, + }) + : children} + +
)}
); diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx index 9f561bfcd3..76b07c9d32 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx @@ -81,9 +81,17 @@ export const useTechDocsReaderDom = ( if (isMobileMedia) { element.style.top = '0px'; } else { - const domTop = dom.getBoundingClientRect().top ?? 0; + const page = document?.querySelector('.techdocs-reader-page'); + const pageTop = page?.getBoundingClientRect().top ?? 0; + let domTop = dom.getBoundingClientRect().top ?? 0; + const tabs = dom.querySelector('.md-container > .md-tabs'); const tabsHeight = tabs?.getBoundingClientRect().height ?? 0; + + // the sidebars should not scroll beyond the total height of the header and tabs + if (domTop < pageTop) { + domTop = pageTop; + } element.style.top = `${Math.max(domTop, 0) + tabsHeight}px`; } diff --git a/plugins/todo-backend/CHANGELOG.md b/plugins/todo-backend/CHANGELOG.md index e2cec9e01e..005a900f20 100644 --- a/plugins/todo-backend/CHANGELOG.md +++ b/plugins/todo-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-todo-backend +## 0.1.31-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/catalog-client@1.0.4-next.1 + - @backstage/integration@1.2.2-next.1 + ## 0.1.31-next.0 ### Patch Changes diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index 97053da997..a49bd6fae5 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.31-next.0", + "version": "0.1.31-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,12 +29,12 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/catalog-client": "^1.0.4-next.0", - "@backstage/catalog-model": "^1.1.0-next.0", + "@backstage/backend-common": "^0.14.1-next.1", + "@backstage/catalog-client": "^1.0.4-next.1", + "@backstage/catalog-model": "^1.1.0-next.1", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.2.2-next.0", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/integration": "^1.2.2-next.1", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -43,9 +43,9 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.1", "@types/supertest": "^2.0.8", - "msw": "^0.42.0", + "msw": "^0.43.0", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/todo/CHANGELOG.md b/plugins/todo/CHANGELOG.md index a1ef01aea5..a2892e3036 100644 --- a/plugins/todo/CHANGELOG.md +++ b/plugins/todo/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-todo +## 0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.2.9-next.0 ### Patch Changes diff --git a/plugins/todo/package.json b/plugins/todo/package.json index 0e17b6ef10..255a58a0d5 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo", "description": "A Backstage plugin that lets you browse TODO comments in your source code", - "version": "0.2.9-next.0", + "version": "0.2.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,12 +30,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -45,17 +45,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0", + "msw": "^0.43.0", "react-router": "6.0.0-beta.0" }, "files": [ diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index 1fcdc650d1..a515a7572a 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-user-settings +## 0.4.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## 0.4.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/theme@0.2.16-next.0 + ## 0.4.6-next.0 ### Patch Changes diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index e186e2539d..e2527933ee 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.4.6-next.0", + "version": "0.4.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,9 +34,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/theme": "^0.2.15", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -48,17 +48,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "^26.0.7", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/vault-backend/CHANGELOG.md b/plugins/vault-backend/CHANGELOG.md index 5c12ada8f5..6b1dba1bfa 100644 --- a/plugins/vault-backend/CHANGELOG.md +++ b/plugins/vault-backend/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-vault-backend +## 0.2.0-next.2 + +### Patch Changes + +- 7ee4abdcc9: Added a path notion in addition to secret name to allow to differentiate secrets in sub-paths +- Updated dependencies + - @backstage/backend-common@0.14.1-next.2 + - @backstage/backend-tasks@0.3.3-next.2 + - @backstage/backend-test-utils@0.1.26-next.2 + +## 0.2.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.14.1-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/backend-tasks@0.3.3-next.1 + - @backstage/backend-test-utils@0.1.26-next.1 + ## 0.2.0-next.0 ### Minor Changes diff --git a/plugins/vault-backend/api-report.md b/plugins/vault-backend/api-report.md index 9f738b15e9..d2e9e1b177 100644 --- a/plugins/vault-backend/api-report.md +++ b/plugins/vault-backend/api-report.md @@ -70,6 +70,7 @@ export interface VaultEnvironment { // @public export type VaultSecret = { name: string; + path: string; showUrl: string; editUrl: string; }; diff --git a/plugins/vault-backend/package.json b/plugins/vault-backend/package.json index 490a19be6d..df5d0f5fa6 100644 --- a/plugins/vault-backend/package.json +++ b/plugins/vault-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-vault-backend", "description": "A Backstage backend plugin that integrates towards Vault", - "version": "0.2.0-next.0", + "version": "0.2.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,11 +34,11 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/backend-common": "^0.14.1-next.0", - "@backstage/backend-tasks": "^0.3.3-next.0", - "@backstage/backend-test-utils": "^0.1.26-next.0", + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/backend-tasks": "^0.3.3-next.2", + "@backstage/backend-test-utils": "^0.1.26-next.2", "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.0.0", + "@backstage/errors": "^1.1.0-next.0", "@types/express": "*", "compression": "^1.7.4", "cors": "^2.8.5", @@ -51,10 +51,10 @@ "yn": "^5.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@types/compression": "^1.7.2", "@types/supertest": "^2.0.8", - "msw": "^0.42.0", + "msw": "^0.43.0", "supertest": "^6.1.6" }, "files": [ diff --git a/plugins/vault-backend/src/service/vaultApi.test.ts b/plugins/vault-backend/src/service/vaultApi.test.ts index e80703c99f..1fb869ef60 100644 --- a/plugins/vault-backend/src/service/vaultApi.test.ts +++ b/plugins/vault-backend/src/service/vaultApi.test.ts @@ -46,11 +46,13 @@ describe('VaultApi', () => { const mockSecretsResult: VaultSecret[] = [ { name: 'secret::one', + path: 'test/success', editUrl: `${mockBaseUrl}/ui/vault/secrets/secrets/edit/test/success/secret::one`, showUrl: `${mockBaseUrl}/ui/vault/secrets/secrets/show/test/success/secret::one`, }, { name: 'secret::two', + path: 'test/success', editUrl: `${mockBaseUrl}/ui/vault/secrets/secrets/edit/test/success/secret::two`, showUrl: `${mockBaseUrl}/ui/vault/secrets/secrets/show/test/success/secret::two`, }, diff --git a/plugins/vault-backend/src/service/vaultApi.ts b/plugins/vault-backend/src/service/vaultApi.ts index 14607a694f..158778294a 100644 --- a/plugins/vault-backend/src/service/vaultApi.ts +++ b/plugins/vault-backend/src/service/vaultApi.ts @@ -36,6 +36,7 @@ export type VaultSecretList = { */ export type VaultSecret = { name: string; + path: string; showUrl: string; editUrl: string; }; @@ -134,6 +135,7 @@ export class VaultClient implements VaultApi { } else { secrets.push({ name: secret, + path: secretPath, editUrl: `${this.vaultConfig.baseUrl}/ui/vault/secrets/${this.vaultConfig.secretEngine}/edit/${secretPath}/${secret}`, showUrl: `${this.vaultConfig.baseUrl}/ui/vault/secrets/${this.vaultConfig.secretEngine}/show/${secretPath}/${secret}`, }); diff --git a/plugins/vault/CHANGELOG.md b/plugins/vault/CHANGELOG.md index 3b371bf5b9..317d6ae7d6 100644 --- a/plugins/vault/CHANGELOG.md +++ b/plugins/vault/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-vault +## 0.1.1-next.2 + +### Patch Changes + +- 7ee4abdcc9: Added a path notion in addition to secret name to allow to differentiate secrets in sub-paths +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/catalog-model@1.1.0-next.2 + - @backstage/theme@0.2.16-next.1 + - @backstage/plugin-catalog-react@1.1.2-next.2 + +## 0.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/catalog-model@1.1.0-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + - @backstage/plugin-catalog-react@1.1.2-next.1 + ## 0.1.1-next.0 ### Patch Changes diff --git a/plugins/vault/api-report.md b/plugins/vault/api-report.md index f6fa8d1269..b347989800 100644 --- a/plugins/vault/api-report.md +++ b/plugins/vault/api-report.md @@ -32,6 +32,7 @@ export const vaultPlugin: BackstagePlugin<{}, {}>; // @public export type VaultSecret = { name: string; + path: string; showUrl: string; editUrl: string; }; diff --git a/plugins/vault/dev/index.tsx b/plugins/vault/dev/index.tsx index f5056cd057..8d902e14c5 100644 --- a/plugins/vault/dev/index.tsx +++ b/plugins/vault/dev/index.tsx @@ -45,11 +45,13 @@ const mockedApi: VaultApi = { return [ { name: 'a::b', + path: '', editUrl: 'https://example.com', showUrl: 'https://example.com', }, { name: 'c::d', + path: '', editUrl: 'https://example.com', showUrl: 'https://example.com', }, diff --git a/plugins/vault/package.json b/plugins/vault/package.json index 01b3182641..43ac2fdb26 100644 --- a/plugins/vault/package.json +++ b/plugins/vault/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-vault", "description": "A Backstage plugin that integrates towards Vault", - "version": "0.1.1-next.0", + "version": "0.1.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,12 +34,12 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0-next.0", - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/plugin-catalog-react": "^1.1.2-next.0", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/plugin-catalog-react": "^1.1.2-next.2", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "^4.0.0-alpha.57", @@ -49,17 +49,17 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/jest": "*", "@types/node": "*", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/plugins/vault/src/api.test.ts b/plugins/vault/src/api.test.ts index 3733d8be0f..4ce6f95c41 100644 --- a/plugins/vault/src/api.test.ts +++ b/plugins/vault/src/api.test.ts @@ -31,11 +31,13 @@ describe('api', () => { items: [ { name: 'secret::one', + path: 'test/success', editUrl: `${mockBaseUrl}/ui/vault/secrets/secrets/edit/test/success/secret::one`, showUrl: `${mockBaseUrl}/ui/vault/secrets/secrets/show/test/success/secret::one`, }, { name: 'secret::two', + path: 'test/success', editUrl: `${mockBaseUrl}/ui/vault/secrets/secrets/edit/test/success/secret::two`, showUrl: `${mockBaseUrl}/ui/vault/secrets/secrets/show/test/success/secret::two`, }, diff --git a/plugins/vault/src/api.ts b/plugins/vault/src/api.ts index 6c17e34d9a..bdd881e08c 100644 --- a/plugins/vault/src/api.ts +++ b/plugins/vault/src/api.ts @@ -29,6 +29,7 @@ export const vaultApiRef = createApiRef({ */ export type VaultSecret = { name: string; + path: string; showUrl: string; editUrl: string; }; diff --git a/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.test.tsx b/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.test.tsx index f3d7748b3e..82a90f23e1 100644 --- a/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.test.tsx +++ b/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.test.tsx @@ -72,11 +72,13 @@ describe('EntityVaultTable', () => { items: [ { name: 'secret::one', + path: 'test/success', editUrl: `${mockBaseUrl}/ui/vault/secrets/secrets/edit/test/success/secret::one`, showUrl: `${mockBaseUrl}/ui/vault/secrets/secrets/show/test/success/secret::one`, }, { name: 'secret::two', + path: 'test/success', editUrl: `${mockBaseUrl}/ui/vault/secrets/secrets/edit/test/success/secret::two`, showUrl: `${mockBaseUrl}/ui/vault/secrets/secrets/show/test/success/secret::two`, }, diff --git a/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.tsx b/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.tsx index 8311dea2aa..efc345b07f 100644 --- a/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.tsx +++ b/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.tsx @@ -53,12 +53,16 @@ export const EntityVaultTable = ({ entity }: { entity: Entity }) => { ]; const data = (value || []).map(secret => { + const secretName = `${secret.path.replace(`${secretPath}/`, '')}/${ + secret.name + }`; + return { - secret: secret.name, + secret: secretName, view: ( @@ -67,7 +71,7 @@ export const EntityVaultTable = ({ entity }: { entity: Entity }) => { edit: ( diff --git a/plugins/xcmetrics/CHANGELOG.md b/plugins/xcmetrics/CHANGELOG.md index 3e1e1ad9c2..a8ac7904a0 100644 --- a/plugins/xcmetrics/CHANGELOG.md +++ b/plugins/xcmetrics/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-xcmetrics +## 0.2.27-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.10.0-next.2 + - @backstage/theme@0.2.16-next.1 + +## 0.2.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.9.6-next.1 + - @backstage/errors@1.1.0-next.0 + - @backstage/theme@0.2.16-next.0 + ## 0.2.27-next.0 ### Patch Changes diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index 1ab1c9f844..67a63f0342 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.27-next.0", + "version": "0.2.27-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,10 +24,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.9.6-next.0", + "@backstage/core-components": "^0.10.0-next.2", "@backstage/core-plugin-api": "^1.0.3", - "@backstage/errors": "^1.0.0", - "@backstage/theme": "^0.2.15", + "@backstage/errors": "^1.1.0-next.0", + "@backstage/theme": "^0.2.16-next.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -40,10 +40,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.17.3-next.0", + "@backstage/cli": "^0.18.0-next.2", "@backstage/core-app-api": "^1.0.4-next.0", - "@backstage/dev-utils": "^1.0.4-next.0", - "@backstage/test-utils": "^1.1.2-next.0", + "@backstage/dev-utils": "^1.0.4-next.2", + "@backstage/test-utils": "^1.1.2-next.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", @@ -51,7 +51,7 @@ "@types/luxon": "^2.0.4", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.42.0" + "msw": "^0.43.0" }, "files": [ "dist" diff --git a/scripts/api-extractor.ts b/scripts/api-extractor.ts index 2ca7aef17f..0d40ebb60a 100644 --- a/scripts/api-extractor.ts +++ b/scripts/api-extractor.ts @@ -23,7 +23,7 @@ import { dirname, join, } from 'path'; -import { spawnSync } from 'child_process'; +import { spawnSync, execFile } from 'child_process'; import prettier from 'prettier'; import fs from 'fs-extra'; import { @@ -197,18 +197,6 @@ ApiReportGenerator.generateReviewFileContent = const PACKAGE_ROOTS = ['packages', 'plugins']; -const SKIPPED_PACKAGES = [ - join('packages', 'app'), - join('packages', 'backend'), - join('packages', 'cli'), - join('packages', 'codemods'), - join('packages', 'create-app'), - join('packages', 'e2e-test'), - join('packages', 'techdocs-cli-embedded-app'), - join('packages', 'storybook'), - join('packages', 'techdocs-cli'), -]; - const ALLOW_WARNINGS = [ 'packages/core-components', 'plugins/allure', @@ -303,9 +291,6 @@ async function findSpecificPackageDirs(unresolvedPackageDirs: string[]) { if (!packageDir) { throw new Error(`'${unresolvedPackageDir}' is not a valid package path`); } - if (SKIPPED_PACKAGES.includes(packageDir)) { - throw new Error(`'${packageDir}' does not have an API report`); - } packageDirs.push(packageDir); } @@ -328,9 +313,7 @@ async function findPackageDirs() { continue; } - if (!SKIPPED_PACKAGES.includes(packageDir)) { - packageDirs.push(packageDir); - } + packageDirs.push(packageDir); } } @@ -1065,6 +1048,252 @@ async function buildDocs({ documenter.generateFiles(); } +async function categorizePackageDirs(projectRoot, packageDirs) { + const dirs = packageDirs.slice(); + const tsPackageDirs = new Array(); + const cliPackageDirs = new Array(); + + await Promise.all( + Array(10) + .fill(0) + .map(async () => { + for (;;) { + const dir = dirs.pop(); + if (!dir) { + return; + } + + const pkgJson = await fs + .readJson(resolvePath(projectRoot, dir, 'package.json')) + .catch(error => { + if (error.code === 'ENOENT') { + return undefined; + } + throw error; + }); + const role = pkgJson?.backstage?.role; + if (!role) { + throw new Error(`No backstage.role in ${dir}/package.json`); + } + if (role === 'cli') { + cliPackageDirs.push(dir); + } else if (role !== 'frontend' && role !== 'backend') { + tsPackageDirs.push(dir); + } + } + }), + ); + + return { tsPackageDirs, cliPackageDirs }; +} + +function createBinRunner(cwd: string, path: string) { + return async (...command: string[]) => + new Promise((resolve, reject) => { + execFile( + 'node', + [path, ...command], + { + cwd, + shell: true, + timeout: 60000, + maxBuffer: 1024 * 1024, + }, + (err, stdout, stderr) => { + if (err) { + reject(new Error(`${err.message}\n${stderr}`)); + } else if (stderr) { + reject(new Error(`Command printed error output: ${stderr}`)); + } else { + resolve(stdout); + } + }, + ); + }); +} + +function parseHelpPage(helpPageContent: string) { + const [, usage] = helpPageContent.match(/^\s*Usage: (.*)$/im) ?? []; + const lines = helpPageContent.split(/\r?\n/); + + let options = new Array(); + let commands = new Array(); + + while (lines.length > 0) { + while (lines.length > 0 && !lines[0].endsWith(':')) { + lines.shift(); + } + if (lines.length > 0) { + // Start of a new section, e.g. "Options:" + const sectionName = lines.shift(); + // Take lines until we hit the next section or the end + const sectionEndIndex = lines.findIndex( + line => line && !line.match(/^\s/), + ); + const sectionLines = lines.slice(0, sectionEndIndex); + lines.splice(0, sectionLines.length); + + // Trim away documentation + const sectionItems = sectionLines + .map(line => line.match(/^\s{1,8}(.*?)\s\s+/)?.[1]) + .filter(Boolean); + + if (sectionName.toLocaleLowerCase('en-US') === 'options:') { + options = sectionItems; + } else if (sectionName.toLocaleLowerCase('en-US') === 'commands:') { + commands = sectionItems; + } else { + throw new Error(`Unknown CLI section: ${sectionName}`); + } + } + } + + return { + usage, + options, + commands, + }; +} + +// Represents the help page os a CLI command +interface CliHelpPage { + // Path of commands to reach this page + path: string[]; + // Parsed content + usage: string | undefined; + options: string[]; + commands: string[]; +} + +async function exploreCliHelpPages( + run: (...args: string[]) => Promise, +): Promise { + const helpPages = new Array(); + + async function exploreHelpPage(...path: string[]) { + const content = await run(...path, '--help'); + const parsed = parseHelpPage(content); + helpPages.push({ path, ...parsed }); + + await Promise.all( + parsed.commands.map(async fullCommand => { + const command = fullCommand.split(/[|\s]/)[0]; + if (command !== 'help') { + await exploreHelpPage(...path, command); + } + }), + ); + } + + await exploreHelpPage(); + + helpPages.sort((a, b) => a.path.join(' ').localeCompare(b.path.join(' '))); + + return helpPages; +} + +// The API model for a CLI entry point +interface CliModel { + name: string; + helpPages: CliHelpPage[]; +} + +function generateCliReport(name: string, models: CliModel[]): string { + const content = [ + `## CLI Report file for "${name}"`, + '', + '> Do not edit this file. It is a report generated by `yarn build:api-reports`', + '', + ]; + + for (const model of models) { + for (const helpPage of model.helpPages) { + content.push( + `### \`${[model.name, ...helpPage.path].join(' ')}\``, + '', + '```', + `Usage: ${helpPage.usage ?? ''}`, + ); + + if (helpPage.options.length > 0) { + content.push('', 'Options:', ...helpPage.options.map(l => ` ${l}`)); + } + + if (helpPage.commands.length > 0) { + content.push('', 'Commands:', ...helpPage.commands.map(l => ` ${l}`)); + } + content.push('```', ''); + } + } + + return content.join('\n'); +} + +interface CliExtractionOptions { + projectRoot: string; + packageDirs: string[]; + isLocalBuild: boolean; +} + +async function runCliExtraction({ + projectRoot, + packageDirs, + isLocalBuild, +}: CliExtractionOptions) { + for (const packageDir of packageDirs) { + console.log(`## Processing ${packageDir}`); + const fullDir = resolvePath(projectRoot, packageDir); + const pkgJson = await fs.readJson(resolvePath(fullDir, 'package.json')); + + if (!pkgJson.bin) { + throw new Error(`CLI Package in ${packageDir} has no bin field`); + } + const models = new Array(); + for (const [name, path] of Object.entries(pkgJson.bin)) { + const run = createBinRunner(fullDir, path); + const helpPages = await exploreCliHelpPages(run); + models.push({ name, helpPages }); + } + + const report = generateCliReport(pkgJson.name, models); + + const reportPath = resolvePath(fullDir, 'cli-report.md'); + const existingReport = await fs + .readFile(reportPath, 'utf8') + .catch(error => { + if (error.code === 'ENOENT') { + return undefined; + } + throw error; + }); + + if (existingReport !== report) { + if (isLocalBuild) { + console.warn(`CLI report changed for ${packageDir}`); + await fs.writeFile(reportPath, report); + } else { + logApiReportInstructions(); + + if (existingReport) { + console.log(''); + console.log( + `The conflicting file is ${relativePath( + projectRoot, + reportPath, + )}, expecting the following content:`, + ); + console.log(''); + + console.log(report); + + logApiReportInstructions(); + } + throw new Error(`CLI report changed for ${packageDir}, `); + } + } + } +} + async function main() { const projectRoot = resolvePath(__dirname, '..'); const isCiBuild = process.argv.includes('--ci'); @@ -1121,13 +1350,28 @@ async function main() { const packageDirs = selectedPackageDirs ?? (await findPackageDirs()); - console.log('# Generating package API reports'); - await runApiExtraction({ + const { tsPackageDirs, cliPackageDirs } = await categorizePackageDirs( + projectRoot, packageDirs, - outputDir: tmpDir, - isLocalBuild: !isCiBuild, - tsconfigFilePath, - }); + ); + + if (tsPackageDirs.length > 0) { + console.log('# Generating package API reports'); + await runApiExtraction({ + packageDirs: tsPackageDirs, + outputDir: tmpDir, + isLocalBuild: !isCiBuild, + tsconfigFilePath, + }); + } + if (cliPackageDirs.length > 0) { + console.log('# Generating package CLI reports'); + await runCliExtraction({ + projectRoot, + packageDirs: cliPackageDirs, + isLocalBuild: !isCiBuild, + }); + } if (isDocsBuild) { console.log('# Generating package documentation'); diff --git a/scripts/create-release-tag.js b/scripts/create-release-tag.js index 637467f285..a2706c578f 100755 --- a/scripts/create-release-tag.js +++ b/scripts/create-release-tag.js @@ -57,22 +57,7 @@ async function createGitTag(octokit, commitSha, tagName) { } } -async function dispatchReleaseWorkflows(octokit, releaseVersion) { - console.log('Dispatching release manifest sync'); - await octokit.actions.createWorkflowDispatch({ - owner: 'backstage', - repo: 'backstage', - workflow_id: 'sync_release-manifest.yml', - ref: 'master', - inputs: { - version: releaseVersion, - }, - }); -} - async function main() { - const shouldDispatch = process.argv.includes('--dispatch-workflows'); - if (!process.env.GITHUB_SHA) { throw new Error('GITHUB_SHA is not set'); } @@ -90,11 +75,7 @@ async function main() { await createGitTag(octokit, commitSha, tagName); console.log(`::set-output name=tag_name::${tagName}`); - - if (shouldDispatch) { - console.log(`Dispatching release workflows for ${tagName}`); - await dispatchReleaseWorkflows(octokit, releaseVersion); - } + console.log(`::set-output name=version::${releaseVersion}`); } main().catch(error => { diff --git a/scripts/generate-changeset-feedback.js b/scripts/generate-changeset-feedback.js index b614459a0e..b34147798d 100644 --- a/scripts/generate-changeset-feedback.js +++ b/scripts/generate-changeset-feedback.js @@ -42,7 +42,7 @@ function isPublishedPath(path) { return false; } // API report changes by themselves don't count - if (path === 'api-report.md') { + if (path === 'api-report.md' || path === 'cli-report.md') { return false; } // Lint changes don't count diff --git a/scripts/goalie-labels.js b/scripts/goalie-labels.js deleted file mode 100644 index e0a5b966d0..0000000000 --- a/scripts/goalie-labels.js +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2022 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const Codeowners = require('codeowners'); - -const getRepoEvents = async ({ github, context, pull_number }) => { - const commits = await github.paginate(github.rest.pulls.listCommits, { - owner: context.repo.owner, - repo: context.repo.repo, - pull_number, - }); - - const reviews = await github.paginate(github.rest.pulls.listReviews, { - owner: context.repo.owner, - repo: context.repo.repo, - pull_number, - }); - - const pullComments = await github.paginate( - 'GET /repos/{owner}/{repo}/pulls/{pull_number}/comments', - { - owner: context.repo.owner, - repo: context.repo.repo, - pull_number, - }, - ); - - const comments = await github.paginate(github.rest.issues.listComments, { - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: pull_number, - }); - - const events = [ - ...reviews.map(({ user, submitted_at }) => ({ - user, - updated_at: submitted_at, - type: 'review', - })), - ...commits.map(({ commit, author, committer }) => ({ - user: author || committer, - updated_at: commit.author.date || commit.committer.date, - type: 'commit', - })), - ...pullComments.map(({ user, updated_at }) => ({ - user, - updated_at, - type: 'pr_comment', - })), - ...comments.map(({ user, updated_at }) => ({ - user, - updated_at, - type: 'pr_comment', - })), - ]; - - return events - .sort((a, b) => new Date(a.updated_at) - new Date(b.updated_at)) - .filter(({ user }) => (user ? !user.login.includes('[bot]') : false)); -}; - -module.exports = async ({ github, context, core }) => { - // first get all open pull requests - const allPullRequests = await github.paginate(github.rest.pulls.list, { - owner: context.repo.owner, - repo: context.repo.repo, - state: 'open', - }); - - const { data: teams } = await github.request('GET /orgs/{org}/teams', { - org: context.repo.owner, - }); - - const groupMembers = await Promise.all( - teams.map(async team => { - const { data } = await github.rest.teams.listMembersInOrg({ - org: context.repo.owner, - team_slug: team.slug, - }); - - return { team: `@backstage/${team.slug}`, data }; - }), - ); - - const codeowners = new Codeowners(); - - for (const pullRequest of allPullRequests) { - // Go through each file changed and get the codeowners for that file. - // Find the group in the group list that matches the codeowner. - // If it does match push the owner to a list of reviewers - // check to see the reviews and if there is at least one matching reviewer from those group - - const changedFiles = await github.paginate(github.rest.pulls.listFiles, { - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: pullRequest.number, - }); - - const allReviews = await github.paginate(github.rest.pulls.listReviews, { - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: pullRequest.number, - }); - - const expectedReviewers = new Set(); - - for (const file of changedFiles) { - expectedReviewers.add(...codeowners.getOwner(file.filename)); - } - - const hasReviewed = new Set(); - - // For each reviewer in the group, check to see if they have a review set - for (const reviewer of expectedReviewers) { - const members = groupMembers.find(member => member.team === reviewer); - if (members) { - // then we are dealing with a group - const hasMemberReview = allReviews.some(review => - members.data.some(member => member.login === review.user.login), - ); - if (hasMemberReview) { - hasReviewed.add(reviewer); - } - } else { - // reviewer is a person - const hasReview = allReviews.some( - review => reviewer === `@${review.user.login}`, - ); - if (hasReview) { - hasReviewed.add(reviewer); - } - } - } - - // if all required reviewers have reviewed - if (hasReviewed.size === expectedReviewers.size) { - const repoEvents = await getRepoEvents({ - github, - context, - pull_number: pullRequest.number, - }); - // if the last event for the issue is not by the author, remove the label - if ( - repoEvents[repoEvents.length - 1].user.login !== pullRequest.user.login - ) { - await github.rest.issues - .removeLabel({ - issue_number: pullRequest.number, - owner: context.repo.owner, - repo: context.repo.repo, - name: 'awaiting-review', - }) - .catch(e => { - console.error(e); - }); - } - // add the awaiting-review label to tell us that the PR is waiting on reviews - } else { - await github.rest.issues - .addLabels({ - issue_number: pullRequest.number, - owner: context.repo.owner, - repo: context.repo.repo, - labels: ['awaiting-review'], - }) - .catch(e => { - console.error(e); - }); - } - } -}; diff --git a/storybook/yarn.lock b/storybook/yarn.lock index 6bf41324eb..cf6ecae523 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -8387,9 +8387,9 @@ style-to-object@0.3.0, style-to-object@^0.3.0: inline-style-parser "0.1.1" sucrase@^3.21.0: - version "3.21.1" - resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.21.1.tgz#7e29ddaca012764cf843280b00e74a843bdf790f" - integrity sha512-kxXnC9yZEav5USAu8gooZID9Ph3xqwdJxZoh+WbOWQZHTB7CHj3ANwENVMZ6mAZ9k7UtJtFxvQD9R03q3yU2YQ== + version "3.23.0" + resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.23.0.tgz#2a7fa80a04f055fb2e95d2aead03fec1dba52838" + integrity sha512-xgC1xboStzGhCnRywlBf/DLmkC+SkdAKqrNCDsxGrzM0phR5oUxoFKiQNrsc2D8wDdAm03iLbSZqjHDddo3IzQ== dependencies: commander "^4.0.0" glob "7.1.6" diff --git a/yarn.lock b/yarn.lock index c1eaefe398..0e22d659aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,13 +2,6 @@ # yarn lockfile v1 -"@acuris/aws-es-connection@^2.2.0": - version "2.3.0" - resolved "https://registry.npmjs.org/@acuris/aws-es-connection/-/aws-es-connection-2.3.0.tgz#bfa736163bdfe2e7fc12f8529eead949fb4e73fe" - integrity sha512-k8jSkdNwpSPty7oautGaJXoAzzPjP7WKbmaAE9i+vJrKWg9n2UtjesHeDhOAPzV9MG8EzXofGozYjaLdeTP+Ug== - dependencies: - aws4 "^1.11.0" - "@ampproject/remapping@^2.1.0": version "2.1.2" resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" @@ -181,10 +174,10 @@ node-fetch "^2.6.0" tiny-merge-patch "^0.1.2" -"@asyncapi/react-component@1.0.0-next.38": - version "1.0.0-next.38" - resolved "https://registry.npmjs.org/@asyncapi/react-component/-/react-component-1.0.0-next.38.tgz#33909f556f18870faca8d8a9e9827a7e341a90ea" - integrity sha512-Uq0wcVHqmKXfvYCa74OiCEgNz3CbpVodeeIjrIsKWqyb9H6QjEA0pIJSLbvEwA+YKVGDXb48R3zsMSmRaqnmnA== +"@asyncapi/react-component@1.0.0-next.39": + version "1.0.0-next.39" + resolved "https://registry.npmjs.org/@asyncapi/react-component/-/react-component-1.0.0-next.39.tgz#2aa236b1783f36249752b3c30e0c7e0125af8c1f" + integrity sha512-UQYmzbvKwDm3HVGjLL1znK35bOKlWNiTUw29oSe6Xdil/Y7RODLctGQrbwKSCeP0VwtsokhwivQ3QHuL3byjVw== dependencies: "@asyncapi/avro-schema-parser" "^0.3.0" "@asyncapi/openapi-schema-parser" "^2.0.0" @@ -1464,7 +1457,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.6", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.6", "@babel/runtime@^7.15.4", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.17.7" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.7.tgz#a5f3328dc41ff39d803f311cfe17703418cf9825" integrity sha512-L6rvG9GDxaLgFjg41K+5Yv9OMrU98sWe+Ykmc6FDJW/+vYZMhdOMKkISgzptMaERHvS2Y2lw9MDRm2gHhlQQoA== @@ -1478,6 +1471,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.18.3": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.6.tgz#6a1ef59f838debd670421f8c7f2cbb8da9751580" + integrity sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.16.7", "@babel/template@^7.3.3": version "7.16.7" resolved "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" @@ -1602,6 +1602,15 @@ zen-observable "^0.8.15" zod "^3.11.6" +"@backstage/errors@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@backstage/errors/-/errors-1.0.0.tgz#08ebf53afdeaca32362955ea8551e8ffa0bb3cd7" + integrity sha512-2SpjdhH9ZOQ4RGEeu3/A7ARkl/1E9E6uBGQZ2DZOU4azTK1UZG/HE1KBMOThp3jL/8is2vOIJZLBA3r3DxLfVw== + dependencies: + "@backstage/types" "^1.0.0" + cross-fetch "^3.1.5" + serialize-error "^8.0.1" + "@backstage/integration-react@^1.0.0": version "1.1.1" resolved "https://registry.npmjs.org/@backstage/integration-react/-/integration-react-1.1.1.tgz#936fd1441c47709fa8825360ea14ada26046b910" @@ -1631,6 +1640,14 @@ lodash "^4.17.21" luxon "^2.0.2" +"@backstage/plugin-catalog-common@^1.0.3": + version "1.0.3" + resolved "https://registry.npmjs.org/@backstage/plugin-catalog-common/-/plugin-catalog-common-1.0.3.tgz#96b1de2847fec0533c49ee19f93781777eedfd0d" + integrity sha512-Sf5IQocTRQaTh9ofZUy4/szWwDl5Eek6odKVx6v33jrMot5i3grybOELrVM3/Kgcr+5/ixSSopgQPUFO/T9KBA== + dependencies: + "@backstage/plugin-permission-common" "^0.6.2" + "@backstage/plugin-search-common" "^0.3.5" + "@backstage/plugin-catalog-react@^1.0.0", "@backstage/plugin-catalog-react@^1.1.1": version "1.1.1" resolved "https://registry.npmjs.org/@backstage/plugin-catalog-react/-/plugin-catalog-react-1.1.1.tgz#0441bcf1291349ad355ff51e28245d7ea26a3e01" @@ -1679,6 +1696,38 @@ react-router "6.0.0-beta.0" react-use "^17.2.4" +"@backstage/plugin-permission-common@^0.6.2": + version "0.6.2" + resolved "https://registry.npmjs.org/@backstage/plugin-permission-common/-/plugin-permission-common-0.6.2.tgz#2ab5cf3d8a4a3394edc0d552719df4f34804bfbb" + integrity sha512-tbKjm0xw6stoaFzeWL59XRz/yEEXxnBMgm3ioNbh0Qdbj44z8KivjkDjWPovI5DW6x0jFxzLQYCNMlZxOpqL6A== + dependencies: + "@backstage/config" "^1.0.1" + "@backstage/errors" "^1.0.0" + cross-fetch "^3.1.5" + uuid "^8.0.0" + zod "^3.11.6" + +"@backstage/plugin-permission-react@^0.4.2": + version "0.4.2" + resolved "https://registry.npmjs.org/@backstage/plugin-permission-react/-/plugin-permission-react-0.4.2.tgz#efc39619617e5800a68728871b87c772a0861711" + integrity sha512-isofTbK1gFgLTgr51efbFO0jWOkhQwzErL24pwY6gFVKnz7Z53AfGv1lHabxAWnNhEyTzLPMA/7s7lKuKEtOXw== + dependencies: + "@backstage/config" "^1.0.1" + "@backstage/core-plugin-api" "^1.0.3" + "@backstage/plugin-permission-common" "^0.6.2" + cross-fetch "^3.1.5" + react-router "6.0.0-beta.0" + react-use "^17.2.4" + swr "^1.1.2" + +"@backstage/plugin-search-common@^0.3.5": + version "0.3.5" + resolved "https://registry.npmjs.org/@backstage/plugin-search-common/-/plugin-search-common-0.3.5.tgz#6a374541f2bd7d9545e29abbaecc70e7ad1b5ea3" + integrity sha512-sq7IDjCLrgZQHBFi+lFVkna3lLRA5eldiTbit/rCUCO4Eq52lWdQHLrQAhsyuObmIWHDh6R2lp2qoL6aAC2AOg== + dependencies: + "@backstage/plugin-permission-common" "^0.6.2" + "@backstage/types" "^1.0.0" + "@backstage/plugin-stack-overflow@^0.1.2": version "0.1.2" resolved "https://registry.npmjs.org/@backstage/plugin-stack-overflow/-/plugin-stack-overflow-0.1.2.tgz#bc140bb22d239a7106f91ea1d4c637551dc91ca5" @@ -1698,6 +1747,13 @@ qs "^6.9.4" react-use "^17.2.4" +"@backstage/theme@^0.2.15", "@backstage/theme@^0.2.6", "@backstage/theme@^0.2.7", "@backstage/theme@^0.2.9": + version "0.2.15" + resolved "https://registry.npmjs.org/@backstage/theme/-/theme-0.2.15.tgz#478491c9bca9dca85d5af08767ba512eabcd3669" + integrity sha512-Srl5q0X47tFofw6wuElkUqtlbYSfA3J3zlfN6jcQF4801mTrFRw+pVxZmrdxayt4gUzCN+me3mO7tij6F6xQUQ== + dependencies: + "@material-ui/core" "^4.12.2" + "@balena/dockerignore@^1.0.2": version "1.0.2" resolved "https://registry.npmjs.org/@balena/dockerignore/-/dockerignore-1.0.2.tgz#9ffe4726915251e8eb69f44ef3547e0da2c03e0d" @@ -1933,9 +1989,9 @@ "@lezer/common" "^1.0.0" "@codemirror/language@^6.0.0": - version "6.1.0" - resolved "https://registry.npmjs.org/@codemirror/language/-/language-6.1.0.tgz#7686f0ecafd958c35332c3cc2aa3d564fd33dc44" - integrity sha512-CeqY80nvUFrJcXcBW115aNi06D0PS8NSW6nuJRSwbrYFkE0SfJnPfyLGrcM90AV95lqg5+4xUi99BCmzNaPGJg== + version "6.2.0" + resolved "https://registry.npmjs.org/@codemirror/language/-/language-6.2.0.tgz#f8d103927bb61346e93781b1ca7d3f4ac3c9280b" + integrity sha512-tabB0Ef/BflwoEmTB4a//WZ9P90UQyne9qWB9YFsmeS4bnEqSys7UpGk/da1URMXhyfuzWCwp+AQNMhvu8SfnA== dependencies: "@codemirror/state" "^6.0.0" "@codemirror/view" "^6.0.0" @@ -2079,10 +2135,10 @@ find-my-way "^4.3.3" into-stream "^6.0.0" -"@elastic/elasticsearch@7.13.0": - version "7.13.0" - resolved "https://registry.npmjs.org/@elastic/elasticsearch/-/elasticsearch-7.13.0.tgz#6dcf511dfa91187e22c81e54f41f4bd0fd96b4d6" - integrity sha512-WgwLWo2p9P2tdqzBGX9fHeG8p5IOTXprXNTECQG2mJ7z9n93N5AFBJpEw4d35tWWeCWi9jI13A2wzQZH7XZ/xw== +"@elastic/elasticsearch@^7.13.0": + version "7.17.0" + resolved "https://registry.npmjs.org/@elastic/elasticsearch/-/elasticsearch-7.17.0.tgz#589fb219234cf1b0da23744e82b1d25e2fe9a797" + integrity sha512-5QLPCjd0uLmLj1lSuKSThjNpq39f6NmlTy9ROLFwG5gjyTgpwSqufDeYG/Fm43Xs05uF7WcscoO7eguI3HuuYA== dependencies: debug "^4.3.1" hpagent "^0.1.1" @@ -2256,10 +2312,10 @@ arrify "^2.0.0" extend "^3.0.2" -"@google-cloud/projectify@^2.0.0": - version "2.0.1" - resolved "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-2.0.1.tgz#13350ee609346435c795bbfe133a08dfeab78d65" - integrity sha512-ZDG38U/Yy6Zr21LaR3BTiiLtpJl6RkPS/JwoRT453G+6Q1DhlV0waNf8Lfu+YVYGIIxgKnLayJRfYlFJfiI8iQ== +"@google-cloud/projectify@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-3.0.0.tgz#302b25f55f674854dce65c2532d98919b118a408" + integrity sha512-HRkZsNmjScY6Li8/kb70wjGlDDyLkVk3KvoEo9uIoxSjYLJasGiCch9+PqRVDOCGUFvEIqyogl+BeqILL4OJHA== "@google-cloud/promisify@^3.0.0": version "3.0.0" @@ -2267,12 +2323,12 @@ integrity sha512-91ArYvRgXWb73YvEOBMmOcJc0bDRs5yiVHnqkwoG0f3nm7nZuipllz6e7BvFESBvjkDTBC0zMD8QxedUwNLc1A== "@google-cloud/storage@^6.0.0": - version "6.1.0" - resolved "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.1.0.tgz#f882a969c5637ff445764d7b172f68fd0d9e63f8" - integrity sha512-zqZwzpRWCJuPne7x9Vc2H79zANl0uh9bNPGis0xAuC88ZEvBXfQqYCAVyiL1YIxi7rf51l8wy9vBr1pONMfxxA== + version "6.2.2" + resolved "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.2.2.tgz#1fd3ee85e5fea55a9696c98769d097b28ff4d775" + integrity sha512-KhAOxmGfmELKKn6cdvgGfAi/YBLi19hI1jX3QI7xQmbeajSFMgUKrIPbbyfMIxQPOEQ9vG0MQX1uganlA/HTRA== dependencies: "@google-cloud/paginator" "^3.0.7" - "@google-cloud/projectify" "^2.0.0" + "@google-cloud/projectify" "^3.0.0" "@google-cloud/promisify" "^3.0.0" abort-controller "^3.0.0" arrify "^2.0.0" @@ -2292,10 +2348,10 @@ teeny-request "^8.0.0" uuid "^8.0.0" -"@graphiql/react@^0.4.2": - version "0.4.2" - resolved "https://registry.npmjs.org/@graphiql/react/-/react-0.4.2.tgz#2a12c7cf0f3945022c2231ce4e814561f2363ef7" - integrity sha512-Df2BaA0HGRkzETCaUw4ZSDe///sfIAGZ6H436A08hmg7SU3yoWJboWGWGc/QD2NyBKVgVBMmzmHcgWhsYh03EA== +"@graphiql/react@^0.4.3": + version "0.4.3" + resolved "https://registry.npmjs.org/@graphiql/react/-/react-0.4.3.tgz#29ca3125c7a349de5e9beb2aef660137fbcbde2e" + integrity sha512-MnH+7LqRqFnwo8YBDtgDfJOdeS5QqNTzH2gTvTbEYYWaNQW1+Vhbsyu2RKHnPSgKVQlfLzdjw6SAMtSb3q1Qog== dependencies: "@graphiql/toolkit" "^0.6.0" codemirror "^5.65.3" @@ -2315,21 +2371,21 @@ meros "^1.1.4" "@graphql-codegen/cli@^2.3.1": - version "2.6.2" - resolved "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-2.6.2.tgz#a9aa4656141ee0998cae8c7ad7d0bf9ca8e0c9ae" - integrity sha512-UO75msoVgvLEvfjCezM09cQQqp32+mR8Ma1ACsBpr7nroFvHbgcu2ulx1cMovg4sxDBCsvd9Eq/xOOMpARUxtw== + version "2.7.0" + resolved "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-2.7.0.tgz#610f3cb2798d581fff3af8d8ba522113a1811fc5" + integrity sha512-qlBcS6jGfZ/xWXwqiyRLHGRuLC9gUdF8AwGHN7LdAYEP5MjL7pIXb02W5JuvMn47rrvr2Q22H9ECppZX65oSAg== dependencies: "@graphql-codegen/core" "2.5.1" "@graphql-codegen/plugin-helpers" "^2.4.1" - "@graphql-tools/apollo-engine-loader" "^7.0.5" + "@graphql-tools/apollo-engine-loader" "^7.3.1" "@graphql-tools/code-file-loader" "^7.0.6" "@graphql-tools/git-loader" "^7.0.5" "@graphql-tools/github-loader" "^7.0.5" "@graphql-tools/graphql-file-loader" "^7.0.5" "@graphql-tools/json-file-loader" "^7.1.2" "@graphql-tools/load" "^7.3.0" - "@graphql-tools/prisma-loader" "^7.0.6" - "@graphql-tools/url-loader" "^7.0.11" + "@graphql-tools/prisma-loader" "^7.2.2" + "@graphql-tools/url-loader" "^7.12.1" "@graphql-tools/utils" "^8.1.1" ansi-escapes "^4.3.1" chalk "^4.1.0" @@ -2338,10 +2394,7 @@ common-tags "^1.8.0" cosmiconfig "^7.0.0" debounce "^1.2.0" - dependency-graph "^0.11.0" detect-indent "^6.0.0" - glob "^7.1.6" - globby "^11.0.4" graphql-config "^4.1.0" inquirer "^8.0.0" is-glob "^4.0.1" @@ -2350,12 +2403,9 @@ listr "^0.14.3" listr-update-renderer "^0.5.0" log-symbols "^4.0.0" - minimatch "^4.0.0" mkdirp "^1.0.4" string-env-interpolation "^1.0.1" ts-log "^2.2.3" - tslib "~2.3.0" - valid-url "^1.0.9" wrap-ansi "^7.0.0" yaml "^1.10.0" yargs "^17.0.0" @@ -2371,13 +2421,13 @@ tslib "~2.3.0" "@graphql-codegen/graphql-modules-preset@^2.3.2": - version "2.3.13" - resolved "https://registry.npmjs.org/@graphql-codegen/graphql-modules-preset/-/graphql-modules-preset-2.3.13.tgz#181ab8acacf376c38d572d6d50aad609aba3cd3d" - integrity sha512-hi/vKUrVa62d5W2euSapUqTNf2ysfq4RjRc0Pcren7zPqMzD3QgbYRLjDtPsXXQntZDmDxoJVd1BEzjpPGD2/g== + version "2.3.14" + resolved "https://registry.npmjs.org/@graphql-codegen/graphql-modules-preset/-/graphql-modules-preset-2.3.14.tgz#78afc5193707cba8a9ef6e2053e90eb9a9a3499c" + integrity sha512-6i2n3pGqvSniA8Qued0KUxMdAEWPREzD9nSMa+hC+r6u0k6V8nW+jWWeLNEi65Ctmt527KSYmGj8PH1RFRqhiw== dependencies: "@graphql-codegen/plugin-helpers" "^2.4.0" - "@graphql-codegen/visitor-plugin-common" "2.9.1" - "@graphql-tools/utils" "8.6.13" + "@graphql-codegen/visitor-plugin-common" "2.10.0" + "@graphql-tools/utils" "8.8.0" change-case-all "1.0.14" parse-filepath "^1.0.2" tslib "~2.4.0" @@ -2404,32 +2454,32 @@ tslib "~2.3.0" "@graphql-codegen/typescript-resolvers@^2.4.3": - version "2.6.6" - resolved "https://registry.npmjs.org/@graphql-codegen/typescript-resolvers/-/typescript-resolvers-2.6.6.tgz#c42cabbc05103b44a29df5ac4a015f2a8e8ab4aa" - integrity sha512-6yVU0rojI64qZbAtGy4+5kA1xJbolcWbefd4y/nwLOn2g99QBHt9nQRCVl96rppfBNinLPkiJCtQ0thOHu9glg== + version "2.6.7" + resolved "https://registry.npmjs.org/@graphql-codegen/typescript-resolvers/-/typescript-resolvers-2.6.7.tgz#a6cadbd6822680678675fffbb826c7163ac60ca0" + integrity sha512-zdB4VuXzBRl2EbxQ/SZ9DRiRMcvCY3eZ2FPM2MnEidR7ggh3GdSg3Ewo6HgwRIHBxI0+DeoK0IM/Po0Rs3q0DA== dependencies: "@graphql-codegen/plugin-helpers" "^2.4.0" - "@graphql-codegen/typescript" "^2.5.1" - "@graphql-codegen/visitor-plugin-common" "2.9.1" + "@graphql-codegen/typescript" "^2.6.0" + "@graphql-codegen/visitor-plugin-common" "2.10.0" "@graphql-tools/utils" "^8.1.1" auto-bind "~4.0.0" tslib "~2.4.0" -"@graphql-codegen/typescript@^2.4.2", "@graphql-codegen/typescript@^2.5.1": - version "2.5.1" - resolved "https://registry.npmjs.org/@graphql-codegen/typescript/-/typescript-2.5.1.tgz#5131485ff3ac83d5bc0aae11a2af0c9bdc08854c" - integrity sha512-D/9V2VfVIE4Mu5UiMGQtxyFU5xe1ZkAZi8g/IsqymW8rqlhTwsGhtk4JR55qPfOYxR8G94RJSJpzgNakRneytw== +"@graphql-codegen/typescript@^2.4.2", "@graphql-codegen/typescript@^2.6.0": + version "2.6.0" + resolved "https://registry.npmjs.org/@graphql-codegen/typescript/-/typescript-2.6.0.tgz#75e7a54a25b29906ca4e462d1be6bf830f21b328" + integrity sha512-f36ilg8J+wui0OhmQglIZ+2z4Ybc08Y7r7BlBDqfJ1F5X0zau0SlC7Hp2iCoCA0ucqZYtiUU/0n+/R8m1cTrQQ== dependencies: "@graphql-codegen/plugin-helpers" "^2.4.0" "@graphql-codegen/schema-ast" "^2.4.1" - "@graphql-codegen/visitor-plugin-common" "2.9.1" + "@graphql-codegen/visitor-plugin-common" "2.10.0" auto-bind "~4.0.0" tslib "~2.4.0" -"@graphql-codegen/visitor-plugin-common@2.9.1": - version "2.9.1" - resolved "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-2.9.1.tgz#17dfe33e19e846e7475ab9d4ff43de5130e18397" - integrity sha512-j9eGOSGt+sJcwv0ijhZiQ2cF/0ponscekNVoF+vHdOT4RB0qgOQxykPBk6EbKxIHECnkdV8ARdPVTA21A93/QQ== +"@graphql-codegen/visitor-plugin-common@2.10.0": + version "2.10.0" + resolved "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-2.10.0.tgz#d886d8281dfc6e4b9729a5468ffe18ebaefc883f" + integrity sha512-nWoxHKUdwOJCWV96Ks1x4EwYCWsZDJXB+2j6EQz5j27DzdxmQInZ86degaDCd3EgbwhMQEMtiZiPGFFDrgBkHA== dependencies: "@graphql-codegen/plugin-helpers" "^2.4.0" "@graphql-tools/optimize" "^1.0.1" @@ -2442,15 +2492,15 @@ parse-filepath "^1.0.2" tslib "~2.4.0" -"@graphql-tools/apollo-engine-loader@^7.0.5": - version "7.2.11" - resolved "https://registry.npmjs.org/@graphql-tools/apollo-engine-loader/-/apollo-engine-loader-7.2.11.tgz#c247eef8986ce259de6dd2da39daeaba7960ac33" - integrity sha512-0NmAlTd/lQl35OaP18dhxlcdu4w4K+auPfbkiaDfArzdhn6Duhq+ATqMvj6Fx5C23zlcvQ0AJnT5a5Yb55K/5w== +"@graphql-tools/apollo-engine-loader@^7.3.1": + version "7.3.1" + resolved "https://registry.npmjs.org/@graphql-tools/apollo-engine-loader/-/apollo-engine-loader-7.3.1.tgz#535cb259fa6e0dbf1cf960e7212d58b8294bb370" + integrity sha512-PJhX4gQeoPtR2BJFYHYVLdLYkqQHB94r9IC64GamFV+kxR+jzQYZJdDTgnFZxvpvGJ7rEgYKNjcfWS+r+CQisQ== dependencies: - "@graphql-tools/utils" "8.6.9" - cross-undici-fetch "^0.3.0" - sync-fetch "0.3.1" - tslib "~2.3.0" + "@graphql-tools/utils" "8.8.0" + cross-undici-fetch "^0.4.11" + sync-fetch "0.4.1" + tslib "^2.4.0" "@graphql-tools/batch-execute@8.4.6": version "8.4.6" @@ -2462,6 +2512,16 @@ tslib "~2.3.0" value-or-promise "1.0.11" +"@graphql-tools/batch-execute@8.5.0": + version "8.5.0" + resolved "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-8.5.0.tgz#2767a9abf4e2712871a69360a27ef13ada1c019e" + integrity sha512-S9/76X4uYIbVlJyRzXhCBbTJvVD0VvaWNqGiKgkITxlq4aBsTOHVuE84OSi3E1QKP3PTiJYrgMIn220iFOkyQw== + dependencies: + "@graphql-tools/utils" "8.8.0" + dataloader "2.1.0" + tslib "^2.4.0" + value-or-promise "1.0.11" + "@graphql-tools/code-file-loader@^7.0.6": version "7.2.14" resolved "https://registry.npmjs.org/@graphql-tools/code-file-loader/-/code-file-loader-7.2.14.tgz#b43ce0c682040b3969f1f785b18fc33c79341084" @@ -2486,6 +2546,18 @@ tslib "~2.3.0" value-or-promise "1.0.11" +"@graphql-tools/delegate@8.8.0": + version "8.8.0" + resolved "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-8.8.0.tgz#acd3e48e4ca82aace92cc3d920b5c727c35eaf7b" + integrity sha512-dbhfOI8rQXPcowXrbwHLOBY9oGi7qxtlrXF4RuRXmjqGTs2AgogdOE3Ep1+6wFD7qYTuFmHXZ8Cl0PmhoZUgrg== + dependencies: + "@graphql-tools/batch-execute" "8.5.0" + "@graphql-tools/schema" "8.5.0" + "@graphql-tools/utils" "8.8.0" + dataloader "2.1.0" + tslib "~2.4.0" + value-or-promise "1.0.11" + "@graphql-tools/git-loader@^7.0.5": version "7.1.13" resolved "https://registry.npmjs.org/@graphql-tools/git-loader/-/git-loader-7.1.13.tgz#95f4715f4caf290dde975813bc87e0a96a81095d" @@ -2568,6 +2640,14 @@ "@graphql-tools/utils" "8.6.9" tslib "~2.3.0" +"@graphql-tools/merge@8.3.0": + version "8.3.0" + resolved "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.3.0.tgz#d3a8ba10942f8598788c3e03f97cc1d0c0b055f8" + integrity sha512-xRa7RAQok/0DD2YnjuqikMrr7dUAxTpdGtZ7BkvUUGhYs3B3p7reCAfvOVr1DJAqVToP7hdlMk+S5+Ylk+AaqA== + dependencies: + "@graphql-tools/utils" "8.8.0" + tslib "^2.4.0" + "@graphql-tools/mock@^8.1.2": version "8.6.8" resolved "https://registry.npmjs.org/@graphql-tools/mock/-/mock-8.6.8.tgz#232a23c0c14dcfca88012886230b93e6fc2303e2" @@ -2585,13 +2665,13 @@ dependencies: tslib "~2.3.0" -"@graphql-tools/prisma-loader@^7.0.6": - version "7.1.13" - resolved "https://registry.npmjs.org/@graphql-tools/prisma-loader/-/prisma-loader-7.1.13.tgz#3b46e9d9414e71cfeb1a8284c945329eca77a190" - integrity sha512-rctgCI11ZjPJd4ncNTV7mmjV2WN2LRL3aTuTJWHjudO+iJPgoWyor0idl+aP0fOX2GnDK7zASmWwVShuGBJb9g== +"@graphql-tools/prisma-loader@^7.2.2": + version "7.2.2" + resolved "https://registry.npmjs.org/@graphql-tools/prisma-loader/-/prisma-loader-7.2.2.tgz#ee56371f75a4e82330b0e4915f57976bf0f4a16a" + integrity sha512-f5txUBRwwZmPQYL5g5CNdOjOglFE/abtnEVOvUCq+nET0BRuxcuxUD5vykfZnkql9sNvnCFAfrZuBVe5S2n3bA== dependencies: - "@graphql-tools/url-loader" "7.9.14" - "@graphql-tools/utils" "8.6.9" + "@graphql-tools/url-loader" "7.12.1" + "@graphql-tools/utils" "8.8.0" "@types/js-yaml" "^4.0.0" "@types/json-stable-stringify" "^1.0.32" "@types/jsonwebtoken" "^8.5.0" @@ -2608,7 +2688,7 @@ lodash "^4.17.20" replaceall "^0.1.6" scuid "^1.1.0" - tslib "~2.3.0" + tslib "^2.4.0" yaml-ast-parser "^0.0.43" "@graphql-tools/relay-operation-optimizer@^6.4.14": @@ -2630,7 +2710,38 @@ tslib "~2.3.0" value-or-promise "1.0.11" -"@graphql-tools/url-loader@7.9.14", "@graphql-tools/url-loader@^7.0.11", "@graphql-tools/url-loader@^7.4.2": +"@graphql-tools/schema@8.5.0": + version "8.5.0" + resolved "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.5.0.tgz#0332b3a2e674d16e9bf8a58dfd47432449ce2368" + integrity sha512-VeFtKjM3SA9/hCJJfr95aEdC3G0xIKM9z0Qdz4i+eC1g2fdZYnfWFt2ucW4IME+2TDd0enHlKzaV0qk2SLVUww== + dependencies: + "@graphql-tools/merge" "8.3.0" + "@graphql-tools/utils" "8.8.0" + tslib "^2.4.0" + value-or-promise "1.0.11" + +"@graphql-tools/url-loader@7.12.1", "@graphql-tools/url-loader@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@graphql-tools/url-loader/-/url-loader-7.12.1.tgz#931a65da4faced1a71ddc5af638b87140ff3dfb6" + integrity sha512-Fd3ZZLEEr9GGFHEbdrcaMHFQu01BLpFnNDBkISupvjokd497O5Uh0xZvsZGC6mxVt0WWQWpgaK2ef+oLuOdLqQ== + dependencies: + "@graphql-tools/delegate" "8.8.0" + "@graphql-tools/utils" "8.8.0" + "@graphql-tools/wrap" "8.5.0" + "@n1ru4l/graphql-live-query" "^0.9.0" + "@types/ws" "^8.0.0" + cross-undici-fetch "^0.4.11" + dset "^3.1.2" + extract-files "^11.0.0" + graphql-ws "^5.4.1" + isomorphic-ws "^5.0.0" + meros "^1.1.4" + sync-fetch "^0.4.0" + tslib "^2.4.0" + value-or-promise "^1.0.11" + ws "^8.3.0" + +"@graphql-tools/url-loader@^7.4.2": version "7.9.14" resolved "https://registry.npmjs.org/@graphql-tools/url-loader/-/url-loader-7.9.14.tgz#9f76af9a6c55a0cf2e87ccf9b3be15eeb6af188c" integrity sha512-7IXiqUYp0cHeM+qvgjM4jAq8uJhl3PDdQYkyIj5wzZ7XjrkdV3JjPt0cHj2IBIeEwQJOjEKNeFYXjOlg73guCQ== @@ -2666,6 +2777,13 @@ dependencies: tslib "~2.3.0" +"@graphql-tools/utils@8.8.0": + version "8.8.0" + resolved "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.8.0.tgz#8332ff80a1da9204ccf514750dd6f5c5cccf17dc" + integrity sha512-KJrtx05uSM/cPYFdTnGAS1doL5bftJLAiFCDMZ8Vkifztz3BFn3gpFiy/o4wDtM8s39G46mxmt2Km/RmeltfGw== + dependencies: + tslib "^2.4.0" + "@graphql-tools/wrap@8.4.16", "@graphql-tools/wrap@^8.3.1": version "8.4.16" resolved "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-8.4.16.tgz#87dce9ec623a921e5a62f44e75abc9655892724b" @@ -2677,6 +2795,17 @@ tslib "~2.3.0" value-or-promise "1.0.11" +"@graphql-tools/wrap@8.5.0": + version "8.5.0" + resolved "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-8.5.0.tgz#ce1b0d775e1fc3a17404df566f4d2196d31c6e20" + integrity sha512-I+x9dBNzC135WWPi04ejqurR/zDmhfeGbCftCaYKF4CvgWd+ZaJx4Uc74n1SBegQtrj+KDrOS4HgKwf9vAVR7A== + dependencies: + "@graphql-tools/delegate" "8.8.0" + "@graphql-tools/schema" "8.5.0" + "@graphql-tools/utils" "8.8.0" + tslib "^2.4.0" + value-or-promise "1.0.11" + "@graphql-typed-document-node/core@^3.1.0", "@graphql-typed-document-node/core@^3.1.1": version "3.1.1" resolved "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz#076d78ce99822258cf813ecc1e7fa460fa74d052" @@ -3349,14 +3478,14 @@ integrity sha512-CtzORUwWTTOTqfVtHaKRJ0I1kNQd1bpn3sUh8I3nJDVY+5/M/Oe1DnEWzPQvqq/xPIIkzzzIP7mfCoAjFRvDhg== "@jridgewell/resolve-uri@^3.0.3": - version "3.0.7" - resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe" - integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA== + version "3.0.8" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.8.tgz#687cc2bbf243f4e9a868ecf2262318e2658873a1" + integrity sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w== "@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.13" - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c" - integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w== + version "1.4.14" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== "@jridgewell/trace-mapping@0.3.9": version "0.3.9" @@ -3393,11 +3522,11 @@ integrity sha512-zMM9Ds+SawiUkakS7y94Ymqx+S0ORzpG3frZirN3l+UlXUmSUR7hF4wxCVqW+ei94JzV5kt0uXBcoOEAuiydrw== "@keyv/redis@^2.2.3": - version "2.3.6" - resolved "https://registry.npmjs.org/@keyv/redis/-/redis-2.3.6.tgz#462991af60b5b35af4e9ac8d05ad99a08ae2cfc2" - integrity sha512-MKRAeWaKI7zpGb+lSgAAlznQi725NEN18I/Uj2CJysk1o6hBqyXyxCvyI+b9qKwoFAkzxoogdvONIpstzI7t/Q== + version "2.3.7" + resolved "https://registry.npmjs.org/@keyv/redis/-/redis-2.3.7.tgz#4f6f6d85be07668a976bb3c9d910c57d1ab12c70" + integrity sha512-aBxnl2Bt1D7JUXQwdO9dDOBJi3VmKO5yfIiwxvEr/hVSryho0Zn1EuWr3fi6UE8WYw5X8FPUyD6h5wuVQreQsA== dependencies: - ioredis "^5.0.4" + ioredis "^5.1.0" "@kubernetes/client-node@^0.16.0": version "0.16.3" @@ -4309,9 +4438,9 @@ react-is "^16.8.0 || ^17.0.0" "@maxim_mazurok/gapi.client.calendar@^3.0.20220408": - version "3.0.20220617" - resolved "https://registry.npmjs.org/@maxim_mazurok/gapi.client.calendar/-/gapi.client.calendar-3.0.20220617.tgz#140bbfd2caa1770fedbdaec4182eb43684f2d876" - integrity sha512-Vek5Y655GUi4RmUs3cNLfo/KQeReEuvcViJ0KYHl28KmC2Pqmxb4V2YIUhsH7BGVyq84cTIT59qHSirB919Prw== + version "3.0.20220624" + resolved "https://registry.npmjs.org/@maxim_mazurok/gapi.client.calendar/-/gapi.client.calendar-3.0.20220624.tgz#17817142e348ce811415dfb111299fbdac2450a0" + integrity sha512-5+x4A6l8GY+dojvXUBQGc0Y4JOm9lBY1YZfCAEEZPjBcXkx0vs/CenPnmAu/fwQgGSrQLipxFV+pS6RL3L28mg== dependencies: "@types/gapi.client" "*" @@ -5127,6 +5256,16 @@ rxjs "7.5.5" tslib "2.0.3" +"@opensearch-project/opensearch@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@opensearch-project/opensearch/-/opensearch-1.1.0.tgz#8b3c8b4cbcea01755ba092d2997bf0b4ca7f22f7" + integrity sha512-1TDw92JL8rD1b2QGluqBsIBLIiD5SGciIpz4qkrGAe9tcdfQ1ptub5e677rhWl35UULSjr6hP8M6HmISZ/M5HQ== + dependencies: + debug "^4.3.1" + hpagent "^0.1.1" + ms "^2.1.3" + secure-json-parse "^2.4.0" + "@opentelemetry/api@^1.0.1": version "1.0.4" resolved "https://registry.npmjs.org/@opentelemetry/api/-/api-1.0.4.tgz#a167e46c10d05a07ab299fc518793b0cff8f6924" @@ -5203,9 +5342,9 @@ "@react-hookz/deep-equal" "^1.0.1" "@react-hookz/web@^14.0.0": - version "14.2.2" - resolved "https://registry.npmjs.org/@react-hookz/web/-/web-14.2.2.tgz#eee0085f954e5b62d0a6c5b20d8786c28abfb9ad" - integrity sha512-6FeZHKV3FFOYnbSJMkkqXDoMuIX0HEFJlDF4LpHR7RsA3zrH2xzhtF8nSYZ+pG6fDIqYKID9yQuILFmbAWaqCQ== + version "14.7.1" + resolved "https://registry.npmjs.org/@react-hookz/web/-/web-14.7.1.tgz#5e39e6fc21331cc4ae95f36e8135ad763e6c29fb" + integrity sha512-kU1CccZDXvQ9G4vcCCpX3mDQqYKkuLXGFOtPMgmbZ9KrvkEduMRH4JqSVXp1nI/bGI1GJ0KAWm4UEb1x5eDGAg== dependencies: "@react-hookz/deep-equal" "^1.0.2" @@ -5323,9 +5462,9 @@ react-use "^17.2.4" "@rollup/plugin-commonjs@^22.0.0": - version "22.0.0" - resolved "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.0.tgz#f4d87016e2fbf187a593ab9f46626fe05b59e8bd" - integrity sha512-Ktvf2j+bAO+30awhbYoCaXpBcyPmJbaEUYClQns/+6SNCYFURbvBiNbWgHITEsIgDDWCDUclWRKEuf8cwZCFoQ== + version "22.0.1" + resolved "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.1.tgz#f7cb777d20de3eeeaf994f39080115c336bef810" + integrity sha512-dGfEZvdjDHObBiP5IvwTKMVeq/tBZGMBHZFMdIV1ClMM/YoWS34xrHFGfag9SN2ZtMgNZRFruqvxZQEa70O6nQ== dependencies: "@rollup/pluginutils" "^3.1.0" commondir "^1.0.1" @@ -5420,6 +5559,15 @@ dependencies: any-observable "^0.3.0" +"@short.io/opensearch-mock@^0.3.1": + version "0.3.1" + resolved "https://registry.npmjs.org/@short.io/opensearch-mock/-/opensearch-mock-0.3.1.tgz#41678404b94342ac60263a8df590f9b1efa80622" + integrity sha512-gwLTzxJrZNGVQNn+FHLhpw7at3jHb6tNczq2hvFPJ3C3nLaCBRkbP2IQHrIDzklLBVFV83Ug0Xgs73A5o9eLtg== + dependencies: + fast-deep-equal "^3.1.3" + find-my-way "^4.3.3" + into-stream "^6.0.0" + "@sideway/address@^4.1.0": version "4.1.1" resolved "https://registry.npmjs.org/@sideway/address/-/address-4.1.1.tgz#9e321e74310963fdf8eebfbee09c7bd69972de4d" @@ -5749,24 +5897,24 @@ path-browserify "^1.0.1" "@tsconfig/node10@^1.0.7": - version "1.0.8" - resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" - integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== + version "1.0.9" + resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== "@tsconfig/node12@^1.0.7": - version "1.0.9" - resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" - integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== + version "1.0.11" + resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== "@tsconfig/node14@^1.0.0": - version "1.0.1" - resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" - integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== + version "1.0.3" + resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== "@tsconfig/node16@^1.0.2": - version "1.0.2" - resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" - integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== + version "1.0.3" + resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" + integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== "@types/accepts@^1.3.5": version "1.3.5" @@ -6144,7 +6292,7 @@ "@types/eslint" "*" "@types/estree" "*" -"@types/eslint@*", "@types/eslint@^7.28.2": +"@types/eslint@*": version "7.29.0" resolved "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz#e56ddc8e542815272720bb0b4ccc2aff9c3e1c78" integrity sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng== @@ -6152,6 +6300,14 @@ "@types/estree" "*" "@types/json-schema" "*" +"@types/eslint@^7.29.0 || ^8.4.1": + version "8.4.3" + resolved "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.3.tgz#5c92815a3838b1985c90034cd85f26f59d9d0ece" + integrity sha512-YP1S7YJRMPs+7KZKDb9G63n8YejIwW9BALq7a5j2+H4yl6iOv9CB29edho+cuFRrvmJbbaH2yiVChKLJVysDGw== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + "@types/estree@*", "@types/estree@^0.0.51": version "0.0.51" resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" @@ -6343,9 +6499,9 @@ "@types/node" "*" "@types/jest-when@^3.5.0": - version "3.5.1" - resolved "https://registry.npmjs.org/@types/jest-when/-/jest-when-3.5.1.tgz#296a0d62b576615046773daf123d518b10adee32" - integrity sha512-8pzJWwU4h7KyCgwAB2Hs9xuy+a1YgVcdh0vE4LT4DZx5Yo7rFO9FAPIsSORVBVCk8QfjuGZaaU9HTTh3mJnEAg== + version "3.5.2" + resolved "https://registry.npmjs.org/@types/jest-when/-/jest-when-3.5.2.tgz#7e6225e827267d26f115dc97da6403a3b37556c5" + integrity sha512-1WP+wJDW7h4TYAVLoIebxRIVv8GPk66Qsq2nU7PkwKZ6usurnDQZgk0DfBNKAJ9gVzapCXSV53Vn/3nBHBNzAw== dependencies: "@types/jest" "*" @@ -6585,9 +6741,9 @@ integrity sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A== "@types/node@^16.0.0", "@types/node@^16.11.26", "@types/node@^16.9.2": - version "16.11.41" - resolved "https://registry.npmjs.org/@types/node/-/node-16.11.41.tgz#88eb485b1bfdb4c224d878b7832239536aa2f813" - integrity sha512-mqoYK2TnVjdkGk8qXAVGc/x9nSaTpSrFaGFm43BUH3IdoBV0nta6hYaGmdOvIMlbHJbUEVen3gvwpwovAZKNdQ== + version "16.11.43" + resolved "https://registry.npmjs.org/@types/node/-/node-16.11.43.tgz#555e5a743f76b6b897d47f945305b618525ddbe6" + integrity sha512-GqWykok+3uocgfAJM8imbozrqLnPyTrpFlrryURQlw1EesPUCx5XxTiucWDSFF9/NUEXDuD4bnvHm8xfVGWTpQ== "@types/normalize-package-data@^2.4.0": version "2.4.1" @@ -7168,13 +7324,13 @@ integrity sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw== "@typescript-eslint/eslint-plugin@^5.9.0": - version "5.29.0" - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.29.0.tgz#c67794d2b0fd0b4a47f50266088acdc52a08aab6" - integrity sha512-kgTsISt9pM53yRFQmLZ4npj99yGl3x3Pl7z4eA66OuTzAGC4bQB5H5fuLwPnqTKU3yyrrg4MIhjF17UYnL4c0w== + version "5.30.5" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.5.tgz#e9a0afd6eb3b1d663db91cf1e7bc7584d394503d" + integrity sha512-lftkqRoBvc28VFXEoRgyZuztyVUQ04JvUnATSPtIRFAccbXTWL6DEtXGYMcbg998kXw1NLUJm7rTQ9eUt+q6Ig== dependencies: - "@typescript-eslint/scope-manager" "5.29.0" - "@typescript-eslint/type-utils" "5.29.0" - "@typescript-eslint/utils" "5.29.0" + "@typescript-eslint/scope-manager" "5.30.5" + "@typescript-eslint/type-utils" "5.30.5" + "@typescript-eslint/utils" "5.30.5" debug "^4.3.4" functional-red-black-tree "^1.0.1" ignore "^5.2.0" @@ -7195,13 +7351,13 @@ eslint-utils "^3.0.0" "@typescript-eslint/parser@^5.9.0": - version "5.29.0" - resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.29.0.tgz#41314b195b34d44ff38220caa55f3f93cfca43cf" - integrity sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw== + version "5.30.5" + resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.5.tgz#f667c34e4e4c299d98281246c9b1e68c03a92522" + integrity sha512-zj251pcPXI8GO9NDKWWmygP6+UjwWmrdf9qMW/L/uQJBM/0XbU2inxe5io/234y/RCvwpKEYjZ6c1YrXERkK4Q== dependencies: - "@typescript-eslint/scope-manager" "5.29.0" - "@typescript-eslint/types" "5.29.0" - "@typescript-eslint/typescript-estree" "5.29.0" + "@typescript-eslint/scope-manager" "5.30.5" + "@typescript-eslint/types" "5.30.5" + "@typescript-eslint/typescript-estree" "5.30.5" debug "^4.3.4" "@typescript-eslint/scope-manager@5.20.0": @@ -7212,13 +7368,13 @@ "@typescript-eslint/types" "5.20.0" "@typescript-eslint/visitor-keys" "5.20.0" -"@typescript-eslint/scope-manager@5.29.0": - version "5.29.0" - resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.29.0.tgz#2a6a32e3416cb133e9af8dcf54bf077a916aeed3" - integrity sha512-etbXUT0FygFi2ihcxDZjz21LtC+Eps9V2xVx09zFoN44RRHPrkMflidGMI+2dUs821zR1tDS6Oc9IXxIjOUZwA== +"@typescript-eslint/scope-manager@5.30.5": + version "5.30.5" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.5.tgz#7f90b9d6800552c856a5f3644f5e55dd1469d964" + integrity sha512-NJ6F+YHHFT/30isRe2UTmIGGAiXKckCyMnIV58cE3JkHmaD6e5zyEYm5hBDv0Wbin+IC0T1FWJpD3YqHUG/Ydg== dependencies: - "@typescript-eslint/types" "5.29.0" - "@typescript-eslint/visitor-keys" "5.29.0" + "@typescript-eslint/types" "5.30.5" + "@typescript-eslint/visitor-keys" "5.30.5" "@typescript-eslint/scope-manager@5.9.0": version "5.9.0" @@ -7228,12 +7384,12 @@ "@typescript-eslint/types" "5.9.0" "@typescript-eslint/visitor-keys" "5.9.0" -"@typescript-eslint/type-utils@5.29.0": - version "5.29.0" - resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.29.0.tgz#241918001d164044020b37d26d5b9f4e37cc3d5d" - integrity sha512-JK6bAaaiJozbox3K220VRfCzLa9n0ib/J+FHIwnaV3Enw/TO267qe0pM1b1QrrEuy6xun374XEAsRlA86JJnyg== +"@typescript-eslint/type-utils@5.30.5": + version "5.30.5" + resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.30.5.tgz#7a9656f360b4b1daea635c4621dab053d08bf8a9" + integrity sha512-k9+ejlv1GgwN1nN7XjVtyCgE0BTzhzT1YsQF0rv4Vfj2U9xnslBgMYYvcEYAFVdvhuEscELJsB7lDkN7WusErw== dependencies: - "@typescript-eslint/utils" "5.29.0" + "@typescript-eslint/utils" "5.30.5" debug "^4.3.4" tsutils "^3.21.0" @@ -7242,10 +7398,10 @@ resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.20.0.tgz#fa39c3c2aa786568302318f1cb51fcf64258c20c" integrity sha512-+d8wprF9GyvPwtoB4CxBAR/s0rpP25XKgnOvMf/gMXYDvlUC3rPFHupdTQ/ow9vn7UDe5rX02ovGYQbv/IUCbg== -"@typescript-eslint/types@5.29.0": - version "5.29.0" - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.29.0.tgz#7861d3d288c031703b2d97bc113696b4d8c19aab" - integrity sha512-X99VbqvAXOMdVyfFmksMy3u8p8yoRGITgU1joBJPzeYa0rhdf5ok9S56/itRoUSh99fiDoMtarSIJXo7H/SnOg== +"@typescript-eslint/types@5.30.5": + version "5.30.5" + resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.5.tgz#36a0c05a72af3623cdf9ee8b81ea743b7de75a98" + integrity sha512-kZ80w/M2AvsbRvOr3PjaNh6qEW1LFqs2pLdo2s5R38B2HYXG8Z0PP48/4+j1QHJFL3ssHIbJ4odPRS8PlHrFfw== "@typescript-eslint/types@5.9.0": version "5.9.0" @@ -7265,13 +7421,13 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/typescript-estree@5.29.0": - version "5.29.0" - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.29.0.tgz#e83d19aa7fd2e74616aab2f25dfbe4de4f0b5577" - integrity sha512-mQvSUJ/JjGBdvo+1LwC+GY2XmSYjK1nAaVw2emp/E61wEVYEyibRHCqm1I1vEKbXCpUKuW4G7u9ZCaZhJbLoNQ== +"@typescript-eslint/typescript-estree@5.30.5": + version "5.30.5" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.5.tgz#c520e4eba20551c4ec76af8d344a42eb6c9767bb" + integrity sha512-qGTc7QZC801kbYjAr4AgdOfnokpwStqyhSbiQvqGBLixniAKyH+ib2qXIVo4P9NgGzwyfD9I0nlJN7D91E1VpQ== dependencies: - "@typescript-eslint/types" "5.29.0" - "@typescript-eslint/visitor-keys" "5.29.0" + "@typescript-eslint/types" "5.30.5" + "@typescript-eslint/visitor-keys" "5.30.5" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -7291,15 +7447,15 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/utils@5.29.0": - version "5.29.0" - resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz#775046effd5019667bd086bcf326acbe32cd0082" - integrity sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A== +"@typescript-eslint/utils@5.30.5": + version "5.30.5" + resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.30.5.tgz#3999cbd06baad31b9e60d084f20714d1b2776765" + integrity sha512-o4SSUH9IkuA7AYIfAvatldovurqTAHrfzPApOZvdUq01hHojZojCFXx06D/aFpKCgWbMPRdJBWAC3sWp3itwTA== dependencies: "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.29.0" - "@typescript-eslint/types" "5.29.0" - "@typescript-eslint/typescript-estree" "5.29.0" + "@typescript-eslint/scope-manager" "5.30.5" + "@typescript-eslint/types" "5.30.5" + "@typescript-eslint/typescript-estree" "5.30.5" eslint-scope "^5.1.1" eslint-utils "^3.0.0" @@ -7323,12 +7479,12 @@ "@typescript-eslint/types" "5.20.0" eslint-visitor-keys "^3.0.0" -"@typescript-eslint/visitor-keys@5.29.0": - version "5.29.0" - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz#7a4749fa7ef5160c44a451bf060ac1dc6dfb77ee" - integrity sha512-Hpb/mCWsjILvikMQoZIE3voc9wtQcS0A9FUw3h8bhr9UxBdtI/tw1ZDZUOXHXLOVMedKCH5NxyzATwnU78bWCQ== +"@typescript-eslint/visitor-keys@5.30.5": + version "5.30.5" + resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.5.tgz#d4bb969202019d5d5d849a0aaedc7370cc044b14" + integrity sha512-D+xtGo9HUMELzWIUqcQc0p2PO4NyvTrgIOK/VnSH083+8sq0tiLozNRKuLarwHYGRuA6TVBQSuuLwJUDWd3aaA== dependencies: - "@typescript-eslint/types" "5.29.0" + "@typescript-eslint/types" "5.30.5" eslint-visitor-keys "^3.3.0" "@typescript-eslint/visitor-keys@5.9.0": @@ -7340,9 +7496,9 @@ eslint-visitor-keys "^3.0.0" "@uiw/react-codemirror@^4.9.3": - version "4.9.4" - resolved "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.9.4.tgz#4643201f279fed103f2cf15df9431931fe4e9f15" - integrity sha512-IsC5xDevpIeLMzHQQwT2W40gFFIdKeT1T0DHjzzai+s5SIrMlGe3QSHWeC1wSO7FtfNxFpFlTYMGJm5JwUviMA== + version "4.9.5" + resolved "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.9.5.tgz#0f66c09dfc355baef5a7020f206da8db90bae223" + integrity sha512-KHgP/PII9Gv4iEUzbdO95qpSSPy27iSHzxQ01mBPWC4UvzuA0eQY2h64gzi/ld68esbKMGYoevgOBPCRJwNN1A== dependencies: "@babel/runtime" ">=7.11.0" "@codemirror/theme-one-dark" "^6.0.0" @@ -7495,9 +7651,9 @@ integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== "@yarnpkg/parsers@^3.0.0-rc.4": - version "3.0.0-rc.9" - resolved "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.9.tgz#2d284e4e0c79b1c4e410465e217fa303d98b7be3" - integrity sha512-JMBE+6OJoNN9AXBzZ72u22/t9M25K8KgUWZIjvk8CU/NsE/m946l8D7SqMhbi3ZaUfYa5QitqCqVWTTFtysGJQ== + version "3.0.0-rc.11" + resolved "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.11.tgz#4c2e69f3c904693eea58a8999ca9a189b0d78b41" + integrity sha512-qQ2EBj1lRA2iB1SwcyvGI53w5TlEBMgJ/hAR42ts+6bKK/am/xQoozQxtBiqodAyphIGVSm3sfQmQXN2pjMlNA== dependencies: js-yaml "^3.10.0" tslib "^1.13.0" @@ -8050,7 +8206,7 @@ array-ify@^1.0.0: resolved "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4= -array-includes@^3.1.2, array-includes@^3.1.3, array-includes@^3.1.4: +array-includes@^3.1.2, array-includes@^3.1.4: version "3.1.4" resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz#f5b493162c760f3539631f005ba2bb46acb45ba9" integrity sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw== @@ -8250,6 +8406,13 @@ available-typed-arrays@^1.0.2: dependencies: array-filter "^1.0.0" +aws-os-connection@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/aws-os-connection/-/aws-os-connection-0.1.0.tgz#02c1be08cf63448c5bdc9d47b03b7ad3222b662c" + integrity sha512-WBN2S/5zgzfPpEiOTEW7IPJX+hlq+AQeAVKK4AL/Th0SfRRKu6a46i4aZKovQslBkKnmcSFvy+mHSJ299N8YWA== + dependencies: + aws4 "^1.11.0" + aws-sdk-mock@^5.2.1: version "5.7.0" resolved "https://registry.npmjs.org/aws-sdk-mock/-/aws-sdk-mock-5.7.0.tgz#b2a9454c78d008186c3f1a460b79cdb9cc9dfdc4" @@ -8260,9 +8423,9 @@ aws-sdk-mock@^5.2.1: traverse "^0.6.6" aws-sdk@^2.1122.0, aws-sdk@^2.840.0, aws-sdk@^2.948.0: - version "2.1159.0" - resolved "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1159.0.tgz#64d585ac608d58e6ff62678be71a4c4ca61ca5dc" - integrity sha512-zm3k/ufwZnkWc6M+HDz00CWuILot4L9kJ5VJsuDS9fwsT9To6k91Y1njCtIV4tcgcXvUru0Sbm4D0w5bc2847A== + version "2.1167.0" + resolved "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1167.0.tgz#e8614bce1a7355782734b6928792f14d11b39231" + integrity sha512-hUJzAqWVfNYpct1S+GjyPIc2s+GZcAhbWVqIG4qbLYZ3+sBTcjv3lLH5zx7K+qcTGINDU0g4EsMi6hIrAU+blg== dependencies: buffer "4.9.2" events "1.1.1" @@ -8284,10 +8447,10 @@ aws4@^1.11.0, aws4@^1.8.0: resolved "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -axe-core@^4.3.5: - version "4.3.5" - resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.3.5.tgz#78d6911ba317a8262bfee292aeafcc1e04b49cc5" - integrity sha512-WKTW1+xAzhMS5dJsxWkliixlO/PqC4VhmO9T4juNYcaTg9jzWiJsou6m5pxWYGfigWbwzJWeFY6z47a+4neRXA== +axe-core@^4.4.2: + version "4.4.2" + resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.4.2.tgz#dcf7fb6dea866166c3eab33d68208afe4d5f670c" + integrity sha512-LVAaGp/wkkgYJcjmHsoKx4juT1aQvJyPcW09MLCjVTh3V2cc6PnyempiLMNH5iMdfIX/zdbjUx2KDjMLCTdPeA== axios-cached-dns-resolve@0.5.2: version "0.5.2" @@ -8997,7 +9160,7 @@ buffer@4.9.2, buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.2.0, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0, buffer@^5.7.0: +buffer@^5.2.0, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0, buffer@^5.7.0, buffer@^5.7.1: version "5.7.1" resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -9040,6 +9203,13 @@ builtins@^5.0.0: dependencies: semver "^7.0.0" +busboy@^1.6.0: + version "1.6.0" + resolved "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== + dependencies: + streamsearch "^1.1.0" + byline@^5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" @@ -9245,9 +9415,9 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001286: integrity sha512-5v7LFQU4Sb/qvkz7JcZkvtSH1Ko+1x2kgo3ocdBeMGZSOFpuE1kkm0kpTwLtWeFrw5qw08ulLxJjVIXIS8MkiQ== canvas@^2.6.1: - version "2.9.1" - resolved "https://registry.npmjs.org/canvas/-/canvas-2.9.1.tgz#58ec841cba36cef0675bc7a74ebd1561f0b476b0" - integrity sha512-vSQti1uG/2gjv3x6QLOZw7TctfufaerTWbVe+NSduHxxLGB+qf3kFgQ6n66DSnuoINtVUjrLLIK2R+lxrBG07A== + version "2.9.3" + resolved "https://registry.npmjs.org/canvas/-/canvas-2.9.3.tgz#8723c4f970442d4cdcedba5221579f9660a58bdb" + integrity sha512-WOUM7ghii5TV2rbhaZkh1youv/vW1/Canev6Yx6BG2W+1S07w8jKZqKkPnbiPpQEDsnJdN8ouDd7OvQEGXDcUw== dependencies: "@mapbox/node-pre-gyp" "^1.0.0" nan "^2.15.0" @@ -10073,10 +10243,10 @@ configstore@^5.0.1: write-file-atomic "^3.0.0" xdg-basedir "^4.0.0" -connect-history-api-fallback@^1.6.0: - version "1.6.0" - resolved "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" - integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== +connect-history-api-fallback@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" + integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== consola@^2.15.0: version "2.15.3" @@ -10285,9 +10455,9 @@ core-js@^2.4.0, core-js@^2.5.0, core-js@^2.6.10: integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== core-js@^3.4.1, core-js@^3.6.5: - version "3.23.2" - resolved "https://registry.npmjs.org/core-js/-/core-js-3.23.2.tgz#e07a60ca8b14dd129cabdc3d2551baf5a01c76f0" - integrity sha512-ELJOWxNrJfOH/WK4VJ3Qd+fOqZuOuDNDJz0xG6Bt4mGg2eO/UT9CljCrbqDGovjLKUrGajEEBcoTOc0w+yBYeQ== + version "3.23.3" + resolved "https://registry.npmjs.org/core-js/-/core-js-3.23.3.tgz#3b977612b15da6da0c9cc4aec487e8d24f371112" + integrity sha512-oAKwkj9xcWNBAvGbT//WiCdOMpb9XQG92/Fe3ABFM/R16BsHgePG00mFOgKf7IsCtfj8tA1kHtf/VwErhriz5Q== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -10403,9 +10573,9 @@ cron@^2.0.0: luxon "^1.23.x" cronstrue@^2.2.0: - version "2.10.0" - resolved "https://registry.npmjs.org/cronstrue/-/cronstrue-2.10.0.tgz#9b57e9acc18eb44ebe9be5dc993753fd7d6d8e56" - integrity sha512-WCCaKuuzjZJl/xTaJiK2KB2lhHqAz+cTAHgSiZQc/pNnF2XUSZX0FBfxAG0qa9CogToNoQw7pEBJExc77QnFBQ== + version "2.11.0" + resolved "https://registry.npmjs.org/cronstrue/-/cronstrue-2.11.0.tgz#18ff1b95a836b9b4e06854f796db2dc8fa98ce41" + integrity sha512-iIBCSis5yqtFYWtJAmNOiwDveFWWIn+8uV5UYuPHYu/Aeu5CSSJepSbaHMyfc+pPFgnsCcGzfPQEo7LSGmWbTg== cross-env@^7.0.0: version "7.0.3" @@ -10474,6 +10644,19 @@ cross-undici-fetch@^0.3.0: undici "^5.0.0" web-streams-polyfill "^3.2.0" +cross-undici-fetch@^0.4.11: + version "0.4.11" + resolved "https://registry.npmjs.org/cross-undici-fetch/-/cross-undici-fetch-0.4.11.tgz#bef38dc729a01db6e07c84fee6de1089b5d3d0a4" + integrity sha512-pRp+EWewyOPYIeUvwOqCIqylCFWqlBwwr6nlZB38v3PhWxS1RYfSgHUJApYTT8jm71SbL5p4qg5kUQv6ZyS24A== + dependencies: + abort-controller "^3.0.0" + busboy "^1.6.0" + form-data-encoder "^1.7.1" + formdata-node "^4.3.1" + node-fetch "^2.6.7" + undici "5.5.1" + web-streams-polyfill "^3.2.0" + crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -10747,9 +10930,9 @@ cypress-plugin-snapshots@^1.4.4: unidiff "1.0.2" cypress@^10.0.0: - version "10.2.0" - resolved "https://registry.npmjs.org/cypress/-/cypress-10.2.0.tgz#ca078abfceb13be2a33cbba6e0e80ded770f542a" - integrity sha512-+i9lY5ENlfi2mJwsggzR+XASOIgMd7S/Gd3/13NCpv596n3YSplMAueBTIxNLcxDpTcIksp+9pM3UaDrJDpFqA== + version "10.3.0" + resolved "https://registry.npmjs.org/cypress/-/cypress-10.3.0.tgz#fae8d32f0822fcfb938e79c7c31ef344794336ae" + integrity sha512-txkQWKzvBVnWdCuKs5Xc08gjpO89W2Dom2wpZgT9zWZT5jXxqPIxqP/NC1YArtkpmp3fN5HW8aDjYBizHLUFvg== dependencies: "@cypress/request" "^2.88.10" "@cypress/xvfb" "^1.2.4" @@ -11014,10 +11197,10 @@ dagre@^0.8.5: graphlib "^2.1.8" lodash "^4.17.15" -damerau-levenshtein@^1.0.7: - version "1.0.7" - resolved "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz#64368003512a1a6992593741a09a9d31a836f55d" - integrity sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw== +damerau-levenshtein@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" + integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== dargs@^7.0.0: version "7.0.0" @@ -11377,10 +11560,10 @@ detect-port-alt@^1.1.6: address "^1.0.1" debug "^2.6.0" -devtools-protocol@0.0.1001819: - version "0.0.1001819" - resolved "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1001819.tgz#0a98f44cefdb02cc684f3d5e6bd898a1690231d9" - integrity sha512-G6OsIFnv/rDyxSqBa2lDLR6thp9oJioLsb2Gl+LbQlyoA9/OBAkrTU9jiCcQ8Pnh7z4d6slDiLaogR5hzgJLmQ== +devtools-protocol@0.0.1011705: + version "0.0.1011705" + resolved "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1011705.tgz#2582ed29f84848df83fba488122015540a744539" + integrity sha512-OKvTvu9n3swmgYshvsyVHYX0+aPzCoYUnyXUacfQMmFtBtBKewV/gT4I9jkAbpTqtTi2E4S9MXLlvzBDUlqg0Q== dezalgo@1.0.3, dezalgo@^1.0.0: version "1.0.3" @@ -11620,7 +11803,7 @@ drange@^1.0.2: resolved "https://registry.npmjs.org/drange/-/drange-1.1.1.tgz#b2aecec2aab82fcef11dbbd7b9e32b83f8f6c0b8" integrity sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA== -dset@^3.1.0, dset@^3.1.1: +dset@^3.1.0, dset@^3.1.1, dset@^3.1.2: version "3.1.2" resolved "https://registry.npmjs.org/dset/-/dset-3.1.2.tgz#89c436ca6450398396dc6538ea00abc0c54cd45a" integrity sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q== @@ -11973,75 +12156,75 @@ es6-error@^4.1.1: resolved "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== -esbuild-android-64@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.47.tgz#ef95b42c67bcf4268c869153fa3ad1466c4cea6b" - integrity sha512-R13Bd9+tqLVFndncMHssZrPWe6/0Kpv2/dt4aA69soX4PRxlzsVpCvoJeFE8sOEoeVEiBkI0myjlkDodXlHa0g== +esbuild-android-64@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.48.tgz#7e6394a0e517f738641385aaf553c7e4fb6d1ae3" + integrity sha512-3aMjboap/kqwCUpGWIjsk20TtxVoKck8/4Tu19rubh7t5Ra0Yrpg30Mt1QXXlipOazrEceGeWurXKeFJgkPOUg== -esbuild-android-arm64@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.47.tgz#4ebd7ce9fb250b4695faa3ee46fd3b0754ecd9e6" - integrity sha512-OkwOjj7ts4lBp/TL6hdd8HftIzOy/pdtbrNA4+0oVWgGG64HrdVzAF5gxtJufAPOsEjkyh1oIYvKAUinKKQRSQ== +esbuild-android-arm64@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.48.tgz#6877566be0f82dd5a43030c0007d06ece7f7c02f" + integrity sha512-vptI3K0wGALiDq+EvRuZotZrJqkYkN5282iAfcffjI5lmGG9G1ta/CIVauhY42MBXwEgDJkweiDcDMRLzBZC4g== -esbuild-darwin-64@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.47.tgz#e0da6c244f497192f951807f003f6a423ed23188" - integrity sha512-R6oaW0y5/u6Eccti/TS6c/2c1xYTb1izwK3gajJwi4vIfNs1s8B1dQzI1UiC9T61YovOQVuePDcfqHLT3mUZJA== +esbuild-darwin-64@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.48.tgz#ea3caddb707d88f844b1aa1dea5ff3b0a71ef1fd" + integrity sha512-gGQZa4+hab2Va/Zww94YbshLuWteyKGD3+EsVon8EWTWhnHFRm5N9NbALNbwi/7hQ/hM1Zm4FuHg+k6BLsl5UA== -esbuild-darwin-arm64@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.47.tgz#cd40fd49a672fca581ed202834239dfe540a9028" - integrity sha512-seCmearlQyvdvM/noz1L9+qblC5vcBrhUaOoLEDDoLInF/VQ9IkobGiLlyTPYP5dW1YD4LXhtBgOyevoIHGGnw== +esbuild-darwin-arm64@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.48.tgz#4e5eaab54df66cc319b76a2ac0e8af4e6f0d9c2f" + integrity sha512-bFjnNEXjhZT+IZ8RvRGNJthLWNHV5JkCtuOFOnjvo5pC0sk2/QVk0Qc06g2PV3J0TcU6kaPC3RN9yy9w2PSLEA== -esbuild-freebsd-64@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.47.tgz#8da6a14c095b29c01fc8087a16cb7906debc2d67" - integrity sha512-ZH8K2Q8/Ux5kXXvQMDsJcxvkIwut69KVrYQhza/ptkW50DC089bCVrJZZ3sKzIoOx+YPTrmsZvqeZERjyYrlvQ== +esbuild-freebsd-64@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.48.tgz#47b5abc7426eae66861490ffbb380acc67af5b15" + integrity sha512-1NOlwRxmOsnPcWOGTB10JKAkYSb2nue0oM1AfHWunW/mv3wERfJmnYlGzL3UAOIUXZqW8GeA2mv+QGwq7DToqA== -esbuild-freebsd-arm64@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.47.tgz#ad31f9c92817ff8f33fd253af7ab5122dc1b83f6" - integrity sha512-ZJMQAJQsIOhn3XTm7MPQfCzEu5b9STNC+s90zMWe2afy9EwnHV7Ov7ohEMv2lyWlc2pjqLW8QJnz2r0KZmeAEQ== +esbuild-freebsd-arm64@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.48.tgz#e8c54c8637cd44feed967ea12338b0a4da3a7b11" + integrity sha512-gXqKdO8wabVcYtluAbikDH2jhXp+Klq5oCD5qbVyUG6tFiGhrC9oczKq3vIrrtwcxDQqK6+HDYK8Zrd4bCA9Gw== -esbuild-linux-32@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.47.tgz#de085e4db2e692ea30c71208ccc23fdcf5196c58" - integrity sha512-FxZOCKoEDPRYvq300lsWCTv1kcHgiiZfNrPtEhFAiqD7QZaXrad8LxyJ8fXGcWzIFzRiYZVtB3ttvITBvAFhKw== +esbuild-linux-32@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.48.tgz#229cf3246de2b7937c3ac13fac622d4d7a1344c5" + integrity sha512-ghGyDfS289z/LReZQUuuKq9KlTiTspxL8SITBFQFAFRA/IkIvDpnZnCAKTCjGXAmUqroMQfKJXMxyjJA69c/nQ== -esbuild-linux-64@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.47.tgz#2a9321bbccb01f01b04cebfcfccbabeba3658ba1" - integrity sha512-nFNOk9vWVfvWYF9YNYksZptgQAdstnDCMtR6m42l5Wfugbzu11VpMCY9XrD4yFxvPo9zmzcoUL/88y0lfJZJJw== +esbuild-linux-64@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.48.tgz#7c0e7226c02c42aacc5656c36977493dc1e96c4f" + integrity sha512-vni3p/gppLMVZLghI7oMqbOZdGmLbbKR23XFARKnszCIBpEMEDxOMNIKPmMItQrmH/iJrL1z8Jt2nynY0bE1ug== -esbuild-linux-arm64@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.47.tgz#b9da7b6fc4b0ca7a13363a0c5b7bb927e4bc535a" - integrity sha512-ywfme6HVrhWcevzmsufjd4iT3PxTfCX9HOdxA7Hd+/ZM23Y9nXeb+vG6AyA6jgq/JovkcqRHcL9XwRNpWG6XRw== +esbuild-linux-arm64@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.48.tgz#0af1eda474b5c6cc0cace8235b74d0cb8fcf57a7" + integrity sha512-3CFsOlpoxlKPRevEHq8aAntgYGYkE1N9yRYAcPyng/p4Wyx0tPR5SBYsxLKcgPB9mR8chHEhtWYz6EZ+H199Zw== -esbuild-linux-arm@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.47.tgz#56fec2a09b9561c337059d4af53625142aded853" - integrity sha512-ZGE1Bqg/gPRXrBpgpvH81tQHpiaGxa8c9Rx/XOylkIl2ypLuOcawXEAo8ls+5DFCcRGt/o3sV+PzpAFZobOsmA== +esbuild-linux-arm@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.48.tgz#de4d1fa6b77cdcd00e2bb43dd0801e4680f0ab52" + integrity sha512-+VfSV7Akh1XUiDNXgqgY1cUP1i2vjI+BmlyXRfVz5AfV3jbpde8JTs5Q9sYgaoq5cWfuKfoZB/QkGOI+QcL1Tw== -esbuild-linux-mips64le@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.47.tgz#9db21561f8f22ed79ef2aedb7bbef082b46cf823" - integrity sha512-mg3D8YndZ1LvUiEdDYR3OsmeyAew4MA/dvaEJxvyygahWmpv1SlEEnhEZlhPokjsUMfRagzsEF/d/2XF+kTQGg== +esbuild-linux-mips64le@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.48.tgz#822c1778495f7868e990d4da47ad7281df28fd15" + integrity sha512-cs0uOiRlPp6ymknDnjajCgvDMSsLw5mST2UXh+ZIrXTj2Ifyf2aAP3Iw4DiqgnyYLV2O/v/yWBJx+WfmKEpNLA== -esbuild-linux-ppc64le@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.47.tgz#dc3a3da321222b11e96e50efafec9d2de408198b" - integrity sha512-WER+f3+szmnZiWoK6AsrTKGoJoErG2LlauSmk73LEZFQ/iWC+KhhDsOkn1xBUpzXWsxN9THmQFltLoaFEH8F8w== +esbuild-linux-ppc64le@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.48.tgz#55de0a9ec4a48fedfe82a63e083164d001709447" + integrity sha512-+2F0vJMkuI0Wie/wcSPDCqXvSFEELH7Jubxb7mpWrA/4NpT+/byjxDz0gG6R1WJoeDefcrMfpBx4GFNN1JQorQ== -esbuild-linux-riscv64@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.47.tgz#9bd6dcd3dca6c0357084ecd06e1d2d4bf105335f" - integrity sha512-1fI6bP3A3rvI9BsaaXbMoaOjLE3lVkJtLxsgLHqlBhLlBVY7UqffWBvkrX/9zfPhhVMd9ZRFiaqXnB1T7BsL2g== +esbuild-linux-riscv64@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.48.tgz#cd2b7381880b2f4b21a5a598fb673492120f18a5" + integrity sha512-BmaK/GfEE+5F2/QDrIXteFGKnVHGxlnK9MjdVKMTfvtmudjY3k2t8NtlY4qemKSizc+QwyombGWTBDc76rxePA== -esbuild-linux-s390x@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.47.tgz#a458af939b52f2cd32fc561410d441a51f69d41f" - integrity sha512-eZrWzy0xFAhki1CWRGnhsHVz7IlSKX6yT2tj2Eg8lhAwlRE5E96Hsb0M1mPSE1dHGpt1QVwwVivXIAacF/G6mw== +esbuild-linux-s390x@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.48.tgz#4b319eca2a5c64637fc7397ffbd9671719cdb6bf" + integrity sha512-tndw/0B9jiCL+KWKo0TSMaUm5UWBLsfCKVdbfMlb3d5LeV9WbijZ8Ordia8SAYv38VSJWOEt6eDCdOx8LqkC4g== esbuild-loader@^2.18.0: version "2.19.0" @@ -12055,61 +12238,61 @@ esbuild-loader@^2.18.0: tapable "^2.2.0" webpack-sources "^2.2.0" -esbuild-netbsd-64@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.47.tgz#6388e785d7e7e4420cb01348d7483ab511b16aa8" - integrity sha512-Qjdjr+KQQVH5Q2Q1r6HBYswFTToPpss3gqCiSw2Fpq/ua8+eXSQyAMG+UvULPqXceOwpnPo4smyZyHdlkcPppQ== +esbuild-netbsd-64@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.48.tgz#c27cde8b5cb55dcc227943a18ab078fb98d0adbf" + integrity sha512-V9hgXfwf/T901Lr1wkOfoevtyNkrxmMcRHyticybBUHookznipMOHoF41Al68QBsqBxnITCEpjjd4yAos7z9Tw== -esbuild-openbsd-64@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.47.tgz#309af806db561aa886c445344d1aacab850dbdc5" - integrity sha512-QpgN8ofL7B9z8g5zZqJE+eFvD1LehRlxr25PBkjyyasakm4599iroUpaj96rdqRlO2ShuyqwJdr+oNqWwTUmQw== +esbuild-openbsd-64@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.48.tgz#af5ab2d1cb41f09064bba9465fc8bf1309150df1" + integrity sha512-+IHf4JcbnnBl4T52egorXMatil/za0awqzg2Vy6FBgPcBpisDWT2sVz/tNdrK9kAqj+GZG/jZdrOkj7wsrNTKA== -esbuild-sunos-64@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.47.tgz#3f19612dcdb89ba6c65283a7ff6e16f8afbf8aaa" - integrity sha512-uOeSgLUwukLioAJOiGYm3kNl+1wJjgJA8R671GYgcPgCx7QR73zfvYqXFFcIO93/nBdIbt5hd8RItqbbf3HtAQ== +esbuild-sunos-64@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.48.tgz#db3ae20526055cf6fd5c4582676233814603ac54" + integrity sha512-77m8bsr5wOpOWbGi9KSqDphcq6dFeJyun8TA+12JW/GAjyfTwVtOnN8DOt6DSPUfEV+ltVMNqtXUeTeMAxl5KA== -esbuild-windows-32@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.47.tgz#a92d279c8458d5dc319abcfeb30aa49e8f2e6f7f" - integrity sha512-H0fWsLTp2WBfKLBgwYT4OTfFly4Im/8B5f3ojDv1Kx//kiubVY0IQunP2Koc/fr/0wI7hj3IiBDbSrmKlrNgLQ== +esbuild-windows-32@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.48.tgz#021ffceb0a3f83078262870da88a912293c57475" + integrity sha512-EPgRuTPP8vK9maxpTGDe5lSoIBHGKO/AuxDncg5O3NkrPeLNdvvK8oywB0zGaAZXxYWfNNSHskvvDgmfVTguhg== -esbuild-windows-64@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.47.tgz#2564c3fcf0c23d701edb71af8c52d3be4cec5f8a" - integrity sha512-/Pk5jIEH34T68r8PweKRi77W49KwanZ8X6lr3vDAtOlH5EumPE4pBHqkCUdELanvsT14yMXLQ/C/8XPi1pAtkQ== +esbuild-windows-64@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.48.tgz#a4d3407b580f9faac51f61eec095fa985fb3fee4" + integrity sha512-YmpXjdT1q0b8ictSdGwH3M8VCoqPpK1/UArze3X199w6u8hUx3V8BhAi1WjbsfDYRBanVVtduAhh2sirImtAvA== -esbuild-windows-arm64@0.14.47: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.47.tgz#86d9db1a22d83360f726ac5fba41c2f625db6878" - integrity sha512-HFSW2lnp62fl86/qPQlqw6asIwCnEsEoNIL1h2uVMgakddf+vUuMcCbtUY1i8sst7KkgHrVKCJQB33YhhOweCQ== +esbuild-windows-arm64@0.14.48: + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.48.tgz#762c0562127d8b09bfb70a3c816460742dd82880" + integrity sha512-HHaOMCsCXp0rz5BT2crTka6MPWVno121NKApsGs/OIW5QC0ggC69YMGs1aJct9/9FSUF4A1xNE/cLvgB5svR4g== esbuild@^0.14.1, esbuild@^0.14.10, esbuild@^0.14.39: - version "0.14.47" - resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.14.47.tgz#0d6415f6bd8eb9e73a58f7f9ae04c5276cda0e4d" - integrity sha512-wI4ZiIfFxpkuxB8ju4MHrGwGLyp1+awEHAHVpx6w7a+1pmYIq8T9FGEVVwFo0iFierDoMj++Xq69GXWYn2EiwA== + version "0.14.48" + resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.14.48.tgz#da5d8d25cd2d940c45ea0cfecdca727f7aee2b85" + integrity sha512-w6N1Yn5MtqK2U1/WZTX9ZqUVb8IOLZkZ5AdHkT6x3cHDMVsYWC7WPdiLmx19w3i4Rwzy5LqsEMtVihG3e4rFzA== optionalDependencies: - esbuild-android-64 "0.14.47" - esbuild-android-arm64 "0.14.47" - esbuild-darwin-64 "0.14.47" - esbuild-darwin-arm64 "0.14.47" - esbuild-freebsd-64 "0.14.47" - esbuild-freebsd-arm64 "0.14.47" - esbuild-linux-32 "0.14.47" - esbuild-linux-64 "0.14.47" - esbuild-linux-arm "0.14.47" - esbuild-linux-arm64 "0.14.47" - esbuild-linux-mips64le "0.14.47" - esbuild-linux-ppc64le "0.14.47" - esbuild-linux-riscv64 "0.14.47" - esbuild-linux-s390x "0.14.47" - esbuild-netbsd-64 "0.14.47" - esbuild-openbsd-64 "0.14.47" - esbuild-sunos-64 "0.14.47" - esbuild-windows-32 "0.14.47" - esbuild-windows-64 "0.14.47" - esbuild-windows-arm64 "0.14.47" + esbuild-android-64 "0.14.48" + esbuild-android-arm64 "0.14.48" + esbuild-darwin-64 "0.14.48" + esbuild-darwin-arm64 "0.14.48" + esbuild-freebsd-64 "0.14.48" + esbuild-freebsd-arm64 "0.14.48" + esbuild-linux-32 "0.14.48" + esbuild-linux-64 "0.14.48" + esbuild-linux-arm "0.14.48" + esbuild-linux-arm64 "0.14.48" + esbuild-linux-mips64le "0.14.48" + esbuild-linux-ppc64le "0.14.48" + esbuild-linux-riscv64 "0.14.48" + esbuild-linux-s390x "0.14.48" + esbuild-netbsd-64 "0.14.48" + esbuild-openbsd-64 "0.14.48" + esbuild-sunos-64 "0.14.48" + esbuild-windows-32 "0.14.48" + esbuild-windows-64 "0.14.48" + esbuild-windows-arm64 "0.14.48" escalade@^3.1.1: version "3.1.1" @@ -12233,22 +12416,23 @@ eslint-plugin-jest@^26.1.2: "@typescript-eslint/utils" "^5.10.0" eslint-plugin-jsx-a11y@^6.5.1: - version "6.5.1" - resolved "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz#cdbf2df901040ca140b6ec14715c988889c2a6d8" - integrity sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g== + version "6.6.0" + resolved "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.0.tgz#2c5ac12e013eb98337b9aa261c3b355275cc6415" + integrity sha512-kTeLuIzpNhXL2CwLlc8AHI0aFRwWHcg483yepO9VQiHzM9bZwJdzTkzBszbuPrbgGmq2rlX/FaT2fJQsjUSHsw== dependencies: - "@babel/runtime" "^7.16.3" + "@babel/runtime" "^7.18.3" aria-query "^4.2.2" - array-includes "^3.1.4" + array-includes "^3.1.5" ast-types-flow "^0.0.7" - axe-core "^4.3.5" + axe-core "^4.4.2" axobject-query "^2.2.0" - damerau-levenshtein "^1.0.7" + damerau-levenshtein "^1.0.8" emoji-regex "^9.2.2" has "^1.0.3" - jsx-ast-utils "^3.2.1" + jsx-ast-utils "^3.3.1" language-tags "^1.0.5" - minimatch "^3.0.4" + minimatch "^3.1.2" + semver "^6.3.0" eslint-plugin-monorepo@^0.3.2: version "0.3.2" @@ -12278,9 +12462,9 @@ eslint-plugin-react-hooks@^4.3.0: integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== eslint-plugin-react@^7.28.0: - version "7.30.0" - resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.30.0.tgz#8e7b1b2934b8426ac067a0febade1b13bd7064e3" - integrity sha512-RgwH7hjW48BleKsYyHK5vUAvxtE9SMPDKmcPRQgtRCYaZA0XQPt5FSkrU3nhz5ifzMZcA8opwmRJ2cmOO8tr5A== + version "7.30.1" + resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.30.1.tgz#2be4ab23ce09b5949c6631413ba64b2810fd3e22" + integrity sha512-NbEvI9jtqO46yJA3wcRF9Mo0lF9T/jhdHqhCHXiXtD+Zcb98812wvokjWpU7Q4QH5edo6dmqrukxVvWWXHlsUg== dependencies: array-includes "^3.1.5" array.prototype.flatmap "^1.3.0" @@ -12331,20 +12515,20 @@ eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0: integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== eslint-webpack-plugin@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.1.1.tgz#83dad2395e5f572d6f4d919eedaa9cf902890fcb" - integrity sha512-xSucskTN9tOkfW7so4EaiFIkulWLXwCB/15H917lR6pTv0Zot6/fetFucmENRb7J5whVSFKIvwnrnsa78SG2yg== + version "3.2.0" + resolved "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.2.0.tgz#1978cdb9edc461e4b0195a20da950cf57988347c" + integrity sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w== dependencies: - "@types/eslint" "^7.28.2" - jest-worker "^27.3.1" - micromatch "^4.0.4" + "@types/eslint" "^7.29.0 || ^8.4.1" + jest-worker "^28.0.2" + micromatch "^4.0.5" normalize-path "^3.0.0" - schema-utils "^3.1.1" + schema-utils "^4.0.0" eslint@^8.6.0: - version "8.18.0" - resolved "https://registry.npmjs.org/eslint/-/eslint-8.18.0.tgz#78d565d16c993d0b73968c523c0446b13da784fd" - integrity sha512-As1EfFMVk7Xc6/CvhssHUjsAQSkpfXvUGMFC3ce8JDe6WvqCgRrLOBQbVpsBFr1X1V+RACOadnzVvcUS5ni2bA== + version "8.19.0" + resolved "https://registry.npmjs.org/eslint/-/eslint-8.19.0.tgz#7342a3cbc4fbc5c106a1eefe0fd0b50b6b1a7d28" + integrity sha512-SXOPj3x9VKvPe81TjjUJCYlV4oJjQw68Uek+AM0X4p+33dj2HY5bpTZOgnQHcG2eAm1mtCU9uNMnJi7exU/kYw== dependencies: "@eslint/eslintrc" "^1.3.0" "@humanwhocodes/config-array" "^0.9.2" @@ -12502,63 +12686,63 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: safe-buffer "^5.1.1" "example-app@link:packages/app": - version "0.2.73-next.0" + version "0.2.73-next.2" dependencies: - "@backstage/app-defaults" "^1.0.4-next.0" - "@backstage/catalog-model" "^1.1.0-next.0" - "@backstage/cli" "^0.17.3-next.0" + "@backstage/app-defaults" "^1.0.4-next.2" + "@backstage/catalog-model" "^1.1.0-next.2" + "@backstage/cli" "^0.18.0-next.2" "@backstage/config" "^1.0.1" "@backstage/core-app-api" "^1.0.4-next.0" - "@backstage/core-components" "^0.9.6-next.0" + "@backstage/core-components" "^0.10.0-next.2" "@backstage/core-plugin-api" "^1.0.3" - "@backstage/integration-react" "^1.1.2-next.0" - "@backstage/plugin-airbrake" "^0.3.7-next.0" - "@backstage/plugin-apache-airflow" "^0.1.15-next.0" - "@backstage/plugin-api-docs" "^0.8.7-next.0" - "@backstage/plugin-azure-devops" "^0.1.23-next.0" - "@backstage/plugin-badges" "^0.2.31-next.0" - "@backstage/plugin-catalog" "^1.3.1-next.0" - "@backstage/plugin-catalog-common" "^1.0.3" - "@backstage/plugin-catalog-graph" "^0.2.19-next.0" - "@backstage/plugin-catalog-import" "^0.8.10-next.0" - "@backstage/plugin-catalog-react" "^1.1.2-next.0" - "@backstage/plugin-circleci" "^0.3.7-next.0" - "@backstage/plugin-cloudbuild" "^0.3.7-next.0" - "@backstage/plugin-code-coverage" "^0.1.34-next.0" - "@backstage/plugin-cost-insights" "^0.11.29-next.0" - "@backstage/plugin-dynatrace" "^0.1.1-next.0" - "@backstage/plugin-explore" "^0.3.38-next.0" - "@backstage/plugin-gcalendar" "^0.3.3-next.0" - "@backstage/plugin-gcp-projects" "^0.3.26-next.0" - "@backstage/plugin-github-actions" "^0.5.7-next.0" - "@backstage/plugin-gocd" "^0.1.13-next.0" - "@backstage/plugin-graphiql" "^0.2.39-next.0" - "@backstage/plugin-home" "^0.4.23-next.0" - "@backstage/plugin-jenkins" "^0.7.6-next.0" - "@backstage/plugin-kafka" "^0.3.7-next.0" - "@backstage/plugin-kubernetes" "^0.6.7-next.0" - "@backstage/plugin-lighthouse" "^0.3.7-next.0" - "@backstage/plugin-newrelic" "^0.3.25-next.0" - "@backstage/plugin-newrelic-dashboard" "^0.1.15-next.0" - "@backstage/plugin-org" "^0.5.7-next.0" - "@backstage/plugin-pagerduty" "0.5.0-next.0" - "@backstage/plugin-permission-react" "^0.4.2" - "@backstage/plugin-rollbar" "^0.4.7-next.0" - "@backstage/plugin-scaffolder" "^1.4.0-next.0" - "@backstage/plugin-search" "^0.9.1-next.0" - "@backstage/plugin-search-common" "^0.3.5" - "@backstage/plugin-search-react" "^0.2.2-next.0" - "@backstage/plugin-sentry" "^0.3.45-next.0" - "@backstage/plugin-shortcuts" "^0.2.8-next.0" - "@backstage/plugin-stack-overflow" "^0.1.3-next.0" - "@backstage/plugin-tech-insights" "^0.2.3-next.0" - "@backstage/plugin-tech-radar" "^0.5.14-next.0" - "@backstage/plugin-techdocs" "^1.2.1-next.0" - "@backstage/plugin-techdocs-module-addons-contrib" "^1.0.2-next.0" - "@backstage/plugin-techdocs-react" "^1.0.2-next.0" - "@backstage/plugin-todo" "^0.2.9-next.0" - "@backstage/plugin-user-settings" "^0.4.6-next.0" - "@backstage/theme" "^0.2.15" + "@backstage/integration-react" "^1.1.2-next.2" + "@backstage/plugin-airbrake" "^0.3.7-next.2" + "@backstage/plugin-apache-airflow" "^0.2.0-next.2" + "@backstage/plugin-api-docs" "^0.8.7-next.2" + "@backstage/plugin-azure-devops" "^0.1.23-next.2" + "@backstage/plugin-badges" "^0.2.31-next.2" + "@backstage/plugin-catalog" "^1.4.0-next.2" + "@backstage/plugin-catalog-common" "^1.0.4-next.0" + "@backstage/plugin-catalog-graph" "^0.2.19-next.2" + "@backstage/plugin-catalog-import" "^0.8.10-next.2" + "@backstage/plugin-catalog-react" "^1.1.2-next.2" + "@backstage/plugin-circleci" "^0.3.7-next.2" + "@backstage/plugin-cloudbuild" "^0.3.7-next.2" + "@backstage/plugin-code-coverage" "^0.1.34-next.2" + "@backstage/plugin-cost-insights" "^0.11.29-next.2" + "@backstage/plugin-dynatrace" "^0.1.1-next.2" + "@backstage/plugin-explore" "^0.3.38-next.2" + "@backstage/plugin-gcalendar" "^0.3.3-next.2" + "@backstage/plugin-gcp-projects" "^0.3.26-next.2" + "@backstage/plugin-github-actions" "^0.5.7-next.2" + "@backstage/plugin-gocd" "^0.1.13-next.2" + "@backstage/plugin-graphiql" "^0.2.39-next.2" + "@backstage/plugin-home" "^0.4.23-next.2" + "@backstage/plugin-jenkins" "^0.7.6-next.2" + "@backstage/plugin-kafka" "^0.3.7-next.2" + "@backstage/plugin-kubernetes" "^0.6.7-next.2" + "@backstage/plugin-lighthouse" "^0.3.7-next.2" + "@backstage/plugin-newrelic" "^0.3.25-next.2" + "@backstage/plugin-newrelic-dashboard" "^0.1.15-next.2" + "@backstage/plugin-org" "^0.5.7-next.2" + "@backstage/plugin-pagerduty" "0.5.0-next.2" + "@backstage/plugin-permission-react" "^0.4.3-next.0" + "@backstage/plugin-rollbar" "^0.4.7-next.2" + "@backstage/plugin-scaffolder" "^1.4.0-next.2" + "@backstage/plugin-search" "^0.9.1-next.2" + "@backstage/plugin-search-common" "^0.3.6-next.0" + "@backstage/plugin-search-react" "^0.2.2-next.2" + "@backstage/plugin-sentry" "^0.3.45-next.2" + "@backstage/plugin-shortcuts" "^0.2.8-next.2" + "@backstage/plugin-stack-overflow" "^0.1.3-next.2" + "@backstage/plugin-tech-insights" "^0.2.3-next.2" + "@backstage/plugin-tech-radar" "^0.5.14-next.2" + "@backstage/plugin-techdocs" "^1.2.1-next.2" + "@backstage/plugin-techdocs-module-addons-contrib" "^1.0.2-next.2" + "@backstage/plugin-techdocs-react" "^1.0.2-next.1" + "@backstage/plugin-todo" "^0.2.9-next.2" + "@backstage/plugin-user-settings" "^0.4.6-next.2" + "@backstage/theme" "^0.2.16-next.1" "@material-ui/core" "^4.12.2" "@material-ui/icons" "^4.9.1" "@material-ui/lab" "4.0.0-alpha.57" @@ -13736,6 +13920,14 @@ git-up@^4.0.0: is-ssh "^1.3.0" parse-url "^5.0.0" +git-up@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/git-up/-/git-up-6.0.0.tgz#dbd6e4eee270338be847a0601e6d0763c90b74db" + integrity sha512-6RUFSNd1c/D0xtGnyWN2sxza2bZtZ/EmI9448n6rCZruFwV/ezeEn2fJP7XnUQGwf0RAtd/mmUCbtH6JPYA2SA== + dependencies: + is-ssh "^1.4.0" + parse-url "^7.0.2" + git-url-parse@^11.4.4, git-url-parse@^11.6.0: version "11.6.0" resolved "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.6.0.tgz#c634b8de7faa66498a2b88932df31702c67df605" @@ -13743,6 +13935,13 @@ git-url-parse@^11.4.4, git-url-parse@^11.6.0: dependencies: git-up "^4.0.0" +git-url-parse@^12.0.0: + version "12.0.0" + resolved "https://registry.npmjs.org/git-url-parse/-/git-url-parse-12.0.0.tgz#4ba70bc1e99138321c57e3765aaf7428e5abb793" + integrity sha512-I6LMWsxV87vysX1WfsoglXsXg6GjQRKq7+Dgiseo+h0skmp5Hp2rzmcEIRQot9CPA+uzU7x1x7jZdqvTFGnB+Q== + dependencies: + git-up "^6.0.0" + gitconfiglocal@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz#41d045f3851a5ea88f03f24ca1c6178114464b9b" @@ -13912,9 +14111,9 @@ google-auth-library@^7.14.0: lru-cache "^6.0.0" google-auth-library@^8.0.0, google-auth-library@^8.0.1, google-auth-library@^8.0.2: - version "8.0.3" - resolved "https://registry.npmjs.org/google-auth-library/-/google-auth-library-8.0.3.tgz#1e780430632d03df36dc22a3f5c89dbc251f2105" - integrity sha512-1eC6yaCrPfkv3bwtb3e0AOct7E7xR/uikDyXNo/j8Wd6a1ldRgAey5FmaDGNJnHNDPLtDiENQLYsA69eXOF5sA== + version "8.1.0" + resolved "https://registry.npmjs.org/google-auth-library/-/google-auth-library-8.1.0.tgz#879e8d2e90a9d47e6eab32fd1d5fd9ed52d7d441" + integrity sha512-J/fNXEnqLgbr3kmeUshZCtHQia6ZiNbbrebVzpt/+LTeY6Ka9CtbQvloTjVGVO7nyYbs0KYeuIwgUC/t2Gp1Jw== dependencies: arrify "^2.0.0" base64-js "^1.3.0" @@ -14050,11 +14249,11 @@ grapheme-splitter@^1.0.4: integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== graphiql@^1.5.12, graphiql@^1.8.8: - version "1.9.9" - resolved "https://registry.npmjs.org/graphiql/-/graphiql-1.9.9.tgz#dfc1760e7552140247e591e3c66d1ccc389ea71f" - integrity sha512-eJ5kGpXFXw69QG/1SJrQs/mzGpDIv4XeGqohGSKQCOh7NtsAsQIxs/VMVR8Lvv9tx6YiIFUvAHp997NlyOwHbQ== + version "1.9.10" + resolved "https://registry.npmjs.org/graphiql/-/graphiql-1.9.10.tgz#ba7113ed8b1bc988d00d8d7cc51901b51b684bde" + integrity sha512-uYYK/zBTV9Y/IHw4uopGVRusbF2xmPnptx7OMFTnTHOTQOmzfIGRTn58WuPgevyEi+9zSLojM86lot9xvNA1/w== dependencies: - "@graphiql/react" "^0.4.2" + "@graphiql/react" "^0.4.3" "@graphiql/toolkit" "^0.6.0" entities "^2.0.0" graphql-language-service "^5.0.6" @@ -14129,9 +14328,9 @@ graphql-type-json@^0.3.2: integrity sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg== graphql-ws@^5.4.1: - version "5.9.0" - resolved "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.9.0.tgz#1fea3cca4582bbda15bc3a50bf30b539869b826f" - integrity sha512-CXv0l0nI1bgChwl4Rm+BqNOAKwL/C9T2N8RfmTkhQ38YLFdUXCi2WNW4oFp8BJP+t75nCLzjHHgR04sP1oF02w== + version "5.9.1" + resolved "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.9.1.tgz#9c0fa48ceb695d61d574ed3ab21b426729e87f2d" + integrity sha512-mL/SWGBwIT9Meq0NlfS55yXXTOeWPMbK7bZBEZhFu46bcGk1coTx2Sdtzxdk+9yHWngD+Fk1PZDWaAutQa9tpw== graphql@^16.0.0, graphql@^16.3.0: version "16.5.0" @@ -15046,10 +15245,10 @@ invert-kv@^1.0.0: resolved "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= -ioredis@^5.0.4: - version "5.0.4" - resolved "https://registry.npmjs.org/ioredis/-/ioredis-5.0.4.tgz#0d4abfd818adfc5ef5029fddac4b8f503a1433b7" - integrity sha512-qFJw3MnPNsJF1lcIOP3vztbsasOXK3nDdNAgjQj7t7/Bn/w10PGchTOpqylQNxjzPbLoYDu34LjeJtSWiKBntQ== +ioredis@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/ioredis/-/ioredis-5.1.0.tgz#17bc0bc40f164ef26910ca6e56981c2a9bfdf57e" + integrity sha512-HYHnvwxFwefeUBj0hZFejLvd8Q/YNAfnZlZG/hSRxkRhXMs1H8soMEVccHd1WlLrKkynorXBsAtqDGskOdAfVQ== dependencies: "@ioredis/commands" "^1.1.1" cluster-key-slot "^1.1.0" @@ -15562,6 +15761,13 @@ is-ssh@^1.3.0: dependencies: protocols "^1.1.0" +is-ssh@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz#4f8220601d2839d8fa624b3106f8e8884f01b8b2" + integrity sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ== + dependencies: + protocols "^2.0.1" + is-stream-ended@^0.1.4: version "0.1.4" resolved "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz#f50224e95e06bce0e356d440a4827cd35b267eda" @@ -15772,6 +15978,11 @@ isomorphic-ws@^4.0.1: resolved "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== +isomorphic-ws@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" + integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== + isstream@~0.1.2: version "0.1.2" resolved "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -16267,7 +16478,7 @@ jest-when@^3.1.0: resolved "https://registry.npmjs.org/jest-when/-/jest-when-3.5.1.tgz#33ab6f923661cf878cd08fe9df64b507934603db" integrity sha512-o+HiaIVCg1IC95sMDKHU9G5v5N5l3UHqXvJpf0PgAMThZeQo4Hf5Sgoj+wpCBRGg4/KtzSAZZZEKNiLqE0i4eQ== -jest-worker@^27.3.1, jest-worker@^27.4.5, jest-worker@^27.5.1: +jest-worker@^27.4.5, jest-worker@^27.5.1: version "27.5.1" resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== @@ -16276,6 +16487,15 @@ jest-worker@^27.3.1, jest-worker@^27.4.5, jest-worker@^27.5.1: merge-stream "^2.0.0" supports-color "^8.0.0" +jest-worker@^28.0.2: + version "28.1.1" + resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.1.tgz#3480c73247171dfd01eda77200f0063ab6a3bf28" + integrity sha512-Au7slXB08C6h+xbJPp7VIb6U0XX5Kc9uel/WFc6/rcTzGiaVCBRngBExSYuXSLFPULPSYU3cJ3ybS988lNFQhQ== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + jest@^27.5.1: version "27.5.1" resolved "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz#dadf33ba70a779be7a6fc33015843b51494f63fc" @@ -16336,9 +16556,9 @@ jose@^4.1.4: integrity sha512-GFcVFQwYQKbQTUOo2JlpFGXTkgBw26uzDsRMD2q1WgSKNSnpKS9Ug7bdQ8dS+p4sZHNH6iRPu6WK2jLIjspaMA== jose@^4.6.0: - version "4.8.1" - resolved "https://registry.npmjs.org/jose/-/jose-4.8.1.tgz#dc7c2660b115ba29b44880e588c5ac313c158247" - integrity sha512-+/hpTbRcCw9YC0TOfN1W47pej4a9lRmltdOVdRLz5FP5UvUq3CenhXjQK7u/8NdMIIShMXYAh9VLPhc7TjhvFw== + version "4.8.3" + resolved "https://registry.npmjs.org/jose/-/jose-4.8.3.tgz#5a754fb4aa5f2806608d083f438e6916b11087da" + integrity sha512-7rySkpW78d8LBp4YU70Wb7+OTgE3OwAALNVZxhoIhp4Kscp+p/fBkdpxGAMKxvCAMV4QfXBU9m6l9nX/vGwd2g== joycon@^3.0.1: version "3.1.0" @@ -16810,12 +17030,12 @@ jss@~10.8.2: array-includes "^3.1.2" object.assign "^4.1.2" -jsx-ast-utils@^3.2.1: - version "3.2.1" - resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz#720b97bfe7d901b927d87c3773637ae8ea48781b" - integrity sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA== +jsx-ast-utils@^3.3.1: + version "3.3.1" + resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.1.tgz#a3e0f1cb7e230954eab4dcbce9f6288a78f8ba44" + integrity sha512-pxrjmNpeRw5wwVeWyEAk7QJu2GnBO3uzPFmHCKJJFPKK2Cy0cWL23krGtLdnMmbIi6/FjlrQpPyfQI19ByPOhQ== dependencies: - array-includes "^3.1.3" + array-includes "^3.1.5" object.assign "^4.1.2" just-diff-apply@^4.0.1: @@ -16872,10 +17092,10 @@ jwt-decode@*, jwt-decode@^3.1.0: resolved "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz#3fb319f3675a2df0c2895c8f5e9fa4b67b04ed59" integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A== -kafkajs@^1.16.0-beta.6: - version "1.16.0" - resolved "https://registry.npmjs.org/kafkajs/-/kafkajs-1.16.0.tgz#bfcc3ae2b69265ca8435b53a01ee9e8787b9fee5" - integrity sha512-+Rcfu2hyQ/jv5skqRY8xA7Ra+mmRkDAzCaLDYbkGtgsNKpzxPWiLbk8ub0dgr4EbWrN1Zb4BCXHUkD6+zYfdWg== +kafkajs@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/kafkajs/-/kafkajs-2.1.0.tgz#32ede4e8080cc75586c5e4406eeb582fa73f7b1e" + integrity sha512-6IYiOdGWvFPbSbVB+AV3feT+A7vzw5sXm7Ze4QTfP7FRNdY8pGcpiNPvD2lfgYFD8Dm9KbMgBgTt2mf8KaIkzw== keyv-memcache@^1.2.5: version "1.2.9" @@ -16934,10 +17154,10 @@ kleur@^4.0.3, kleur@^4.1.4: resolved "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz#8c202987d7e577766d039a8cd461934c01cda04d" integrity sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA== -knex@^1.0.2: - version "1.0.7" - resolved "https://registry.npmjs.org/knex/-/knex-1.0.7.tgz#965f4490efc451b140aac4c5c6efa39fd877597b" - integrity sha512-89jxuRATt4qJMb9ZyyaKBy0pQ4d5h7eOFRqiNFnUvsgU+9WZ2eIaZKrAPG1+F3mgu5UloPUnkVE5Yo2sKZUs6Q== +knex@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/knex/-/knex-2.1.0.tgz#9348aace3a08ff5be26eb1c8e838416ddf1aa216" + integrity sha512-vVsnD6UJdSJy55TvCXfFF9syfwyXNxfE9mvr2hJL/4Obciy2EPGoqjDpgRSlMruHuPWDOeYAG25nyrGvU+jJog== dependencies: colorette "2.0.16" commander "^9.1.0" @@ -17139,9 +17359,9 @@ linkify-it@^3.0.1: uc.micro "^1.0.1" lint-staged@^13.0.0: - version "13.0.2" - resolved "https://registry.npmjs.org/lint-staged/-/lint-staged-13.0.2.tgz#35a1c57130e9ad5b1dea784972a40777ba433dd5" - integrity sha512-qQLfLTh9z34eMzfEHENC+QBskZfxjomrf+snF3xJ4BzilORbD989NLqQ00ughsF/A+PT41e87+WsMFabf9++pQ== + version "13.0.3" + resolved "https://registry.npmjs.org/lint-staged/-/lint-staged-13.0.3.tgz#d7cdf03a3830b327a2b63c6aec953d71d9dc48c6" + integrity sha512-9hmrwSCFroTSYLjflGI8Uk+GWAwMB4OlpU4bMJEAT5d/llQwtYKoim4bLOyLCuWFAhWEupE0vkIFqtw/WIsPug== dependencies: cli-truncate "^3.1.0" colorette "^2.0.17" @@ -18516,7 +18736,7 @@ mime@1.6.0, mime@^1.3.4: resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.2.0, mime@^2.5.0, mime@^2.5.2: +mime@2.6.0, mime@^2.2.0, mime@^2.5.2: version "2.6.0" resolved "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== @@ -18606,13 +18826,6 @@ minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" -minimatch@^4.0.0: - version "4.2.1" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz#40d9d511a46bdc4e563c22c3080cde9c0d8299b4" - integrity sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g== - dependencies: - brace-expansion "^1.1.7" - minimist-options@4.1.0, minimist-options@^4.0.2: version "4.1.0" resolved "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -18832,10 +19045,10 @@ msw@^0.39.2: type-fest "^1.2.2" yargs "^17.3.1" -msw@^0.42.0: - version "0.42.3" - resolved "https://registry.npmjs.org/msw/-/msw-0.42.3.tgz#150c475e2cb6d53c67503bd0e3f6251bfd075328" - integrity sha512-zrKBIGCDsNUCZLd3DLSeUtRruZ0riwJgORg9/bSDw3D0PTI8XUGAK3nC0LJA9g0rChGuKaWK/SwObA8wpFrz4g== +msw@^0.43.0: + version "0.43.0" + resolved "https://registry.npmjs.org/msw/-/msw-0.43.0.tgz#10c6fc3fb1752c0a144179e5ab04c6a512cc9959" + integrity sha512-XJylZP0qW3D5WUGWh9FFefJEl3MGG4y1I+/8a833d0eedm6B+GaPm6wPVZNcnlS2YVTagvEgShVJ7ZtY66tTRQ== dependencies: "@mswjs/cookies" "^0.2.0" "@mswjs/interceptors" "^0.16.3" @@ -19129,9 +19342,9 @@ node-releases@^2.0.1: integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== nodemon@^2.0.2: - version "2.0.16" - resolved "https://registry.npmjs.org/nodemon/-/nodemon-2.0.16.tgz#d71b31bfdb226c25de34afea53486c8ef225fdef" - integrity sha512-zsrcaOfTWRuUzBn3P44RDliLlp263Z/76FPoHFr3cFFkOz0lTPAcIw8dCzfdVIx/t3AtDYCZRCDkoCojJqaG3w== + version "2.0.18" + resolved "https://registry.npmjs.org/nodemon/-/nodemon-2.0.18.tgz#0f5a3aa7b4587f2626e6f01369deba89cb0462a2" + integrity sha512-uAvrKipi2zAz8E7nkSz4qW4F4zd5fs2wNGsTx+xXlP8KXqd9ucE0vY9wankOsPboeDyuUGN9vsXGV1pLn80l/A== dependencies: chokidar "^3.5.2" debug "^3.2.7" @@ -19210,7 +19423,7 @@ normalize-url@^4.1.0: resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== -normalize-url@^6.0.1: +normalize-url@^6.0.1, normalize-url@^6.1.0: version "6.1.0" resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== @@ -19280,9 +19493,9 @@ npm-packlist@^3.0.0: npm-normalize-package-bin "^1.0.1" npm-packlist@^5.0.0, npm-packlist@^5.1.0: - version "5.1.0" - resolved "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.1.0.tgz#f3fd52903a021009913a133732022132eb355ce7" - integrity sha512-a04sqF6FbkyOAFA19AA0e94gS7Et5T2/IMj3VOT9nOF2RaRdVPQ1Q17Fb/HaDRFs+gbC7HOmhVZ29adpWgmDZg== + version "5.1.1" + resolved "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.1.1.tgz#79bcaf22a26b6c30aa4dd66b976d69cc286800e0" + integrity sha512-UfpSvQ5YKwctmodvPPkK6Fwk603aoVsf8AEbmVKAEECrfvL8SSe1A2YIwrJ6xmTHAITKPwwZsWo7WwEbNk0kxw== dependencies: glob "^8.0.1" ignore-walk "^5.0.1" @@ -19554,16 +19767,16 @@ obuf@^1.0.0, obuf@^1.1.2: integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== octokit-plugin-create-pull-request@^3.10.0: - version "3.11.0" - resolved "https://registry.npmjs.org/octokit-plugin-create-pull-request/-/octokit-plugin-create-pull-request-3.11.0.tgz#11f496176111eaa04955fb2bb7e4d953501423d0" - integrity sha512-ZD025HTrm/KoBMRmPYbcCw3tfGomOdAYFB6/K1xiMW+/NFsOyDOeFrEGBbL82b57dhNsPRibs0eL64lpJ3xyvw== + version "3.12.2" + resolved "https://registry.npmjs.org/octokit-plugin-create-pull-request/-/octokit-plugin-create-pull-request-3.12.2.tgz#eaced840587a2f7176c563d94ca6112a93f29da2" + integrity sha512-DwY+vPq7dd2zSiIJw2lN1bYUKEuvjLmBTErTJOQEQd+ujQompN8qjpixeheMZetkJmSNzpWhxxqgZyCMuVnZlQ== dependencies: "@octokit/types" "^6.8.2" octokit@^1.7.1: - version "1.8.0" - resolved "https://registry.npmjs.org/octokit/-/octokit-1.8.0.tgz#c2ea6ace083b3be1d594aa7eb2e05fccd14e7ca5" - integrity sha512-HtArk9ttGy5effKNiaqKCirR6VSZoYjqgLgvVm/1mSRR4WYmww5DHjLnZlCbvj8+DwBLLLduJ3XnX/SPCCcp6A== + version "1.8.1" + resolved "https://registry.npmjs.org/octokit/-/octokit-1.8.1.tgz#399b0032e89e058084a1a1922e40a02e87d4cd61" + integrity sha512-xBLKFIivbl7wnLwxzLYuDO/JDNYxdyxoSjFrl/QMrY/fwGGQYYklvKUDTUyGMU0aXPrQtJ0IZnG3BXpCkDQzWg== dependencies: "@octokit/app" "^12.0.4" "@octokit/core" "^3.5.1" @@ -19655,10 +19868,10 @@ openapi-sampler@^1.2.1: "@types/json-schema" "^7.0.7" json-pointer "0.6.2" -openapi-types@^11.0.1: - version "11.1.0" - resolved "https://registry.npmjs.org/openapi-types/-/openapi-types-11.1.0.tgz#037969f3dfa5999423ee33bf889fb0d12984277e" - integrity sha512-ZW+Jf12flFF6DXSij8DGL3svDA4RtSyHXjC/xB/JAh18gg3uVfVIFLvCfScUMowrpvlkxsMMbErakbth2g3/iQ== +openapi-types@^12.0.0: + version "12.0.0" + resolved "https://registry.npmjs.org/openapi-types/-/openapi-types-12.0.0.tgz#458a99d048f9eae1c067e15d56a8bfb3726041f1" + integrity sha512-6Wd9k8nmGQHgCbehZCP6wwWcfXcvinhybUTBatuhjRsCxUIujuYFZc9QnGeae75CyHASewBtxs0HX/qwREReUw== openid-client@^4.1.1: version "4.9.0" @@ -19674,9 +19887,9 @@ openid-client@^4.1.1: oidc-token-hash "^5.0.1" openid-client@^5.1.3: - version "5.1.6" - resolved "https://registry.npmjs.org/openid-client/-/openid-client-5.1.6.tgz#e5eb2032ecfdcfc108660b5c525910a14e352f11" - integrity sha512-HTFaXWdUHvLFw4GaEMgC0jXYBgpjgzQQNHW1pZsSqJorSgrXzxJ+4u/LWCGaClDEse5HLjXRV+zU5Bn3OefiZw== + version "5.1.8" + resolved "https://registry.npmjs.org/openid-client/-/openid-client-5.1.8.tgz#3a24910288b32c32f548fb6e391f44178ce6370f" + integrity sha512-EPxJY6bT7YIYQEXSGxRC5flQ3GUhLy98ufdto6+BVBrFGPmwjUpy4xBcYuU/Wt9nPkO/3EgljBrr6Ezx4lp1RQ== dependencies: jose "^4.1.4" lru-cache "^6.0.0" @@ -20134,6 +20347,13 @@ parse-path@^4.0.0: is-ssh "^1.3.0" protocols "^1.4.0" +parse-path@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/parse-path/-/parse-path-5.0.0.tgz#f933152f3c6d34f4cf36cfc3d07b138ac113649d" + integrity sha512-qOpH55/+ZJ4jUu/oLO+ifUKjFPNZGfnPJtzvGzKN/4oLMil5m9OH4VpOj6++9/ytJcfks4kzH2hhi87GL/OU9A== + dependencies: + protocols "^2.0.0" + parse-url@^5.0.0: version "5.0.1" resolved "https://registry.npmjs.org/parse-url/-/parse-url-5.0.1.tgz#99c4084fc11be14141efa41b3d117a96fcb9527f" @@ -20144,6 +20364,16 @@ parse-url@^5.0.0: parse-path "^4.0.0" protocols "^1.4.0" +parse-url@^7.0.2: + version "7.0.2" + resolved "https://registry.npmjs.org/parse-url/-/parse-url-7.0.2.tgz#d21232417199b8d371c6aec0cedf1406fd6393f0" + integrity sha512-PqO4Z0eCiQ08Wj6QQmrmp5YTTxpYfONdOEamrtvK63AmzXpcavIVQubGHxOEwiIoDZFb8uDOoQFS0NCcjqIYQg== + dependencies: + is-ssh "^1.4.0" + normalize-url "^6.1.0" + parse-path "^5.0.0" + protocols "^2.0.1" + parse5@6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" @@ -20305,10 +20535,10 @@ path-case@^3.0.4: dot-case "^3.0.4" tslib "^2.0.3" -path-equal@1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/path-equal/-/path-equal-1.1.2.tgz#260e7c449c4c2022f68cc5fa6e617e892858250d" - integrity sha512-p5kxPPwCdbf5AdXzT1bUBJomhgBlEjRBavYNr1XUpMFIE4Hnf2roueCMXudZK5tnaAu1tTmp3GPzqwJK45IHEA== +path-equal@^1.1.2: + version "1.2.2" + resolved "https://registry.npmjs.org/path-equal/-/path-equal-1.2.2.tgz#fa2997f0a829de22ec8f5f86461ca5590d49b832" + integrity sha512-AUJvbcle1Zgb1TgtftHYknlrgrSYyI1ytrYgSbKUHSybwqUDnbD2cw9PIWivuMvsN+GTXmr/DRN4VBXpHG6aGg== path-exists@^2.0.0: version "2.1.0" @@ -21136,6 +21366,11 @@ promise-all-reject-late@^1.0.0: resolved "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz#f8ebf13483e5ca91ad809ccc2fcf25f26f8643c2" integrity sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw== +promise-any-polyfill@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/promise-any-polyfill/-/promise-any-polyfill-1.0.1.tgz#563872dd0abd370bfa8039e63980469b4b8b0d53" + integrity sha512-51Tj+hOoV3LOeCHItmWBklN9FYkyV53uIIjjzgIchitGneTvl6+ivOxWXhxraeUzzS3YFRpXRPPbv7+KD3NzYQ== + promise-call-limit@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-1.0.1.tgz#4bdee03aeb85674385ca934da7114e9bcd3c6e24" @@ -21257,6 +21492,11 @@ protocols@^1.1.0, protocols@^1.4.0: resolved "https://registry.npmjs.org/protocols/-/protocols-1.4.7.tgz#95f788a4f0e979b291ffefcf5636ad113d037d32" integrity sha512-Fx65lf9/YDn3hUX08XUc0J8rSux36rEsyiv21ZGUC1mOyeM3lTRpZLcrm8aAolzS4itwVfm7TAPyxC2E5zd6xg== +protocols@^2.0.0, protocols@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz#8f155da3fc0f32644e83c5782c8e8212ccf70a86" + integrity sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q== + proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -21348,14 +21588,14 @@ pupa@^2.1.1: dependencies: escape-goat "^2.0.0" -puppeteer@^14.0.0: - version "14.4.1" - resolved "https://registry.npmjs.org/puppeteer/-/puppeteer-14.4.1.tgz#6c7437a65f7ba98ef8ad7c2b0f1cf808e91617bb" - integrity sha512-+H0Gm84aXUvSLdSiDROtLlOofftClgw2TdceMvvCU9UvMryappoeS3+eOLfKvoy4sm8B8MWnYmPhWxVFudAOFQ== +puppeteer@^15.0.0: + version "15.2.0" + resolved "https://registry.npmjs.org/puppeteer/-/puppeteer-15.2.0.tgz#9cd81334f9c6a2e1c972b5a7ecf3f18ab3bfb978" + integrity sha512-6Mzj5pbq4J4DxJE5o6V+arrOB9Gma0CxOLP1zKYMrMR7AYuNaPzsK7pBrpDwI64W6Mxk5G7NqiLSFTrgSzR1zg== dependencies: cross-fetch "3.1.5" debug "4.3.4" - devtools-protocol "0.0.1001819" + devtools-protocol "0.0.1011705" extract-zip "2.0.1" https-proxy-agent "5.0.1" pkg-dir "4.2.0" @@ -21364,7 +21604,7 @@ puppeteer@^14.0.0: rimraf "3.0.2" tar-fs "2.1.1" unbzip2-stream "1.4.3" - ws "8.7.0" + ws "8.8.0" q@^1.5.1: version "1.5.1" @@ -21517,6 +21757,15 @@ rc-progress@3.3.3: classnames "^2.2.6" rc-util "^5.16.1" +rc-progress@3.4.0: + version "3.4.0" + resolved "https://registry.npmjs.org/rc-progress/-/rc-progress-3.4.0.tgz#80a33c25c9675f5836ba25a87cd8dc310aad72b1" + integrity sha512-ZuMyOzzTkZnn+EKqGQ7YHzrvGzBtcCCVjx1McC/E/pMTvr6GWVfVRSawDlWsscxsJs7MkqSTwCO6Lu4IeoY2zQ== + dependencies: + "@babel/runtime" "^7.10.1" + classnames "^2.2.6" + rc-util "^5.16.1" + rc-util@^5.16.1: version "5.16.1" resolved "https://registry.npmjs.org/rc-util/-/rc-util-5.16.1.tgz#374db7cb735512f05165ddc3d6b2c61c21b8b4e3" @@ -23881,6 +24130,11 @@ stream-transform@^2.1.3: dependencies: mixme "^0.5.1" +streamsearch@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== + strict-event-emitter@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.2.0.tgz#78e2f75dc6ea502e5d8a877661065a1e2deedecd" @@ -24186,9 +24440,9 @@ stylis@^4.0.6: integrity sha512-OFFeUXFgwnGOKvEXaSv0D0KQ5ADP0n6g3SVONx6I/85JzNZ3u50FRwB3lVIk1QO2HNdI75tbVzc4Z66Gdp9voA== sucrase@^3.18.0, sucrase@^3.20.2: - version "3.21.1" - resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.21.1.tgz#7e29ddaca012764cf843280b00e74a843bdf790f" - integrity sha512-kxXnC9yZEav5USAu8gooZID9Ph3xqwdJxZoh+WbOWQZHTB7CHj3ANwENVMZ6mAZ9k7UtJtFxvQD9R03q3yU2YQ== + version "3.23.0" + resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.23.0.tgz#2a7fa80a04f055fb2e95d2aead03fec1dba52838" + integrity sha512-xgC1xboStzGhCnRywlBf/DLmkC+SkdAKqrNCDsxGrzM0phR5oUxoFKiQNrsc2D8wDdAm03iLbSZqjHDddo3IzQ== dependencies: commander "^4.0.0" glob "7.1.6" @@ -24197,10 +24451,10 @@ sucrase@^3.18.0, sucrase@^3.20.2: pirates "^4.0.1" ts-interface-checker "^0.1.9" -superagent@^7.1.3: - version "7.1.3" - resolved "https://registry.npmjs.org/superagent/-/superagent-7.1.3.tgz#783ff8330e7c2dad6ad8f0095edc772999273b6b" - integrity sha512-WA6et4nAvgBCS73lJvv1D0ssI5uk5Gh+TGN/kNe+B608EtcVs/yzfl+OLXTzDs7tOBDIpvgh/WUs1K2OK1zTeQ== +superagent@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/superagent/-/superagent-8.0.0.tgz#2ea4587df4b81ef023ec01ebc6e1bcb9e2344cb6" + integrity sha512-iudipXEel+SzlP9y29UBWGDjB+Zzag+eeA1iLosaR2YHBRr1Q1kC29iBrF2zIVD9fqVbpZnXkN/VJmwFMVyNWg== dependencies: component-emitter "^1.3.0" cookiejar "^2.1.3" @@ -24209,18 +24463,18 @@ superagent@^7.1.3: form-data "^4.0.0" formidable "^2.0.1" methods "^1.1.2" - mime "^2.5.0" + mime "2.6.0" qs "^6.10.3" readable-stream "^3.6.0" semver "^7.3.7" supertest@^6.1.3, supertest@^6.1.6: - version "6.2.3" - resolved "https://registry.npmjs.org/supertest/-/supertest-6.2.3.tgz#291b220126e5faa654d12abe1ada3658757c8c67" - integrity sha512-3GSdMYTMItzsSYjnIcljxMVZKPW1J9kYHZY+7yLfD0wpPwww97GeImZC1oOk0S5+wYl2niJwuFusBJqwLqYM3g== + version "6.2.4" + resolved "https://registry.npmjs.org/supertest/-/supertest-6.2.4.tgz#3dcebe42f7fd6f28dd7ac74c6cba881f7101b2f0" + integrity sha512-M8xVnCNv+q2T2WXVzxDECvL2695Uv2uUj2O0utxsld/HRyJvOU8W9f1gvsYxSNU4wmIe0/L/ItnpU4iKq0emDA== dependencies: methods "^1.1.2" - superagent "^7.1.3" + superagent "^8.0.0" supports-color@^2.0.0: version "2.0.0" @@ -24367,6 +24621,14 @@ sync-fetch@0.3.1, sync-fetch@^0.3.1: buffer "^5.7.0" node-fetch "^2.6.1" +sync-fetch@0.4.1, sync-fetch@^0.4.0: + version "0.4.1" + resolved "https://registry.npmjs.org/sync-fetch/-/sync-fetch-0.4.1.tgz#87b8684eef2fa25c96c4683ae308473a4e5c571f" + integrity sha512-JDtyFEvnKUzt1CxRtzzsGgkBanEv8XRmLyJo0F0nGkpCR8EjYmpOJJXz8GA/SWtlPU0nAYh0+CNMNnFworGyOA== + dependencies: + buffer "^5.7.1" + node-fetch "^2.6.1" + tapable@^1.0.0: version "1.1.3" resolved "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" @@ -24433,21 +24695,21 @@ tdigest@^0.1.1: bintrees "1.0.1" "techdocs-cli-embedded-app@link:packages/techdocs-cli-embedded-app": - version "0.2.72-next.0" + version "0.2.72-next.2" dependencies: - "@backstage/app-defaults" "^1.0.4-next.0" - "@backstage/catalog-model" "^1.1.0-next.0" - "@backstage/cli" "^0.17.3-next.0" + "@backstage/app-defaults" "^1.0.4-next.2" + "@backstage/catalog-model" "^1.1.0-next.2" + "@backstage/cli" "^0.18.0-next.2" "@backstage/config" "^1.0.1" "@backstage/core-app-api" "^1.0.4-next.0" - "@backstage/core-components" "^0.9.6-next.0" + "@backstage/core-components" "^0.10.0-next.2" "@backstage/core-plugin-api" "^1.0.3" - "@backstage/integration-react" "^1.1.2-next.0" - "@backstage/plugin-catalog" "^1.3.1-next.0" - "@backstage/plugin-techdocs" "^1.2.1-next.0" - "@backstage/plugin-techdocs-react" "^1.0.2-next.0" - "@backstage/test-utils" "^1.1.2-next.0" - "@backstage/theme" "^0.2.15" + "@backstage/integration-react" "^1.1.2-next.2" + "@backstage/plugin-catalog" "^1.4.0-next.2" + "@backstage/plugin-techdocs" "^1.2.1-next.2" + "@backstage/plugin-techdocs-react" "^1.0.2-next.1" + "@backstage/test-utils" "^1.1.2-next.1" + "@backstage/theme" "^0.2.16-next.1" "@material-ui/core" "^4.11.0" "@material-ui/icons" "^4.9.1" history "^5.0.0" @@ -24524,9 +24786,9 @@ test-exclude@^6.0.0: minimatch "^3.0.4" testcontainers@^8.1.2: - version "8.10.1" - resolved "https://registry.npmjs.org/testcontainers/-/testcontainers-8.10.1.tgz#2b3d1d25932f437ba4c46a1f32380ce7987629f8" - integrity sha512-MQFoWe6sJrbcZqXb+fM7uN2w9WnV2KZnNyI7Qc9pbxQZS6oLa/or5kgL4DADAuzYFxXJvL3f8inIGI+/1S+rvA== + version "8.11.0" + resolved "https://registry.npmjs.org/testcontainers/-/testcontainers-8.11.0.tgz#f19307557289b7e80c7e1d65b39ab0054a2b2549" + integrity sha512-sc9FA40waYXKVTp/Dm9qmcc8I5/TLyZd+JxtnYjIQDp1UvLzAckQPjSlGCDTdM00J2X4KDwG0+jY+8WprZbpnQ== dependencies: "@balena/dockerignore" "^1.0.2" "@types/archiver" "^5.3.1" @@ -24897,9 +25159,9 @@ ts-morph@^15.0.0: code-block-writer "^11.0.0" ts-node@^10.0.0, ts-node@^10.2.1, ts-node@^10.4.0: - version "10.8.1" - resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.8.1.tgz#ea2bd3459011b52699d7e88daa55a45a1af4f066" - integrity sha512-Wwsnao4DQoJsN034wePSg5nZiw4YKXf56mPIAeD6wVmiv+RytNSWqc2f3fKvcUoV+Yn2+yocD71VOfQHbmVX4g== + version "10.8.2" + resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.8.2.tgz#3185b75228cef116bf82ffe8762594f54b2a23f2" + integrity sha512-LYdGnoGddf1D6v8REPtIH+5iq/gTDuZqv2/UJUU7tKjuEU8xVZorBM+buCGNjj+pGEud+sOoM4CX3/YzINpENA== dependencies: "@cspotcode/source-map-support" "^0.8.0" "@tsconfig/node10" "^1.0.7" @@ -25087,15 +25349,15 @@ typedarray@^0.0.6: resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript-json-schema@^0.53.0: - version "0.53.1" - resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.53.1.tgz#9204547f3e145169b40928998366ff6d28b81d32" - integrity sha512-Hg+RnOKUd38MOzC0rDft03a8xvwO+gCcj1F77smw2tCoZYQpFoLtrXWBGdvCX+REliko5WYel2kux17HPFqjLQ== +typescript-json-schema@^0.54.0: + version "0.54.0" + resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.54.0.tgz#b3fc42ad90df6a0f6ab57571ebc8b4d41125df4f" + integrity sha512-/MNhm1pjdxXiVspjjyRCrQAA1B768cRzHU83aIqN5vQqQEW2NgyyKOfcguiRIMM64lseIZIelegnHOHEu7YDCg== dependencies: "@types/json-schema" "^7.0.9" "@types/node" "^16.9.2" glob "^7.1.7" - path-equal "1.1.2" + path-equal "^1.1.2" safe-stable-stringify "^2.2.0" ts-node "^10.2.1" typescript "~4.6.0" @@ -25171,7 +25433,7 @@ underscore@^1.12.1, underscore@^1.9.1: resolved "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz#0c1c6bd2df54b6b69f2314066d65b6cde6fcf9d1" integrity sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g== -undici@^5.0.0: +undici@5.5.1, undici@^5.0.0: version "5.5.1" resolved "https://registry.npmjs.org/undici/-/undici-5.5.1.tgz#baaf25844a99eaa0b22e1ef8d205bffe587c8f43" integrity sha512-MEvryPLf18HvlCbLSzCW0U00IMftKGI5udnjrQbC5D4P0Hodwffhv+iGfWuJwg16Y/TK11ZFK8i+BPVW2z/eAw== @@ -25603,11 +25865,6 @@ v8-to-istanbul@^8.1.0: convert-source-map "^1.6.0" source-map "^0.7.3" -valid-url@^1.0.9: - version "1.0.9" - resolved "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" - integrity sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA= - validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: version "3.0.4" resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -25856,9 +26113,9 @@ webpack-dev-middleware@^5.3.1: schema-utils "^4.0.0" webpack-dev-server@^4.7.3: - version "4.9.2" - resolved "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.9.2.tgz#c188db28c7bff12f87deda2a5595679ebbc3c9bc" - integrity sha512-H95Ns95dP24ZsEzO6G9iT+PNw4Q7ltll1GfJHV4fKphuHWgKFzGHWi4alTlTnpk1SPPk41X+l2RB7rLfIhnB9Q== + version "4.9.3" + resolved "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.9.3.tgz#2360a5d6d532acb5410a668417ad549ee3b8a3c9" + integrity sha512-3qp/eoboZG5/6QgiZ3llN8TUzkSpYg1Ko9khWX1h40MIEUNS2mDoIa8aXsPfskER+GbTvs/IJZ1QTBBhhuetSw== dependencies: "@types/bonjour" "^3.5.9" "@types/connect-history-api-fallback" "^1.3.5" @@ -25872,7 +26129,7 @@ webpack-dev-server@^4.7.3: chokidar "^3.5.3" colorette "^2.0.10" compression "^1.7.4" - connect-history-api-fallback "^1.6.0" + connect-history-api-fallback "^2.0.0" default-gateway "^6.0.3" express "^4.17.3" graceful-fs "^4.2.6" @@ -26083,9 +26340,9 @@ winston-transport@^4.5.0: triple-beam "^1.3.0" winston@^3.2.1, winston@^3.7.2: - version "3.7.2" - resolved "https://registry.npmjs.org/winston/-/winston-3.7.2.tgz#95b4eeddbec902b3db1424932ac634f887c400b1" - integrity sha512-QziIqtojHBoyzUOdQvQiar1DH0Xp9nF1A1y7NVy2DGEsz82SBDtOalS0ulTRGVT14xPX3WRWkCsdcJKqNflKng== + version "3.8.1" + resolved "https://registry.npmjs.org/winston/-/winston-3.8.1.tgz#76f15b3478cde170b780234e0c4cf805c5a7fb57" + integrity sha512-r+6YAiCR4uI3N8eQNOg8k3P3PqwAm20cLKlzVD9E66Ch39+LZC+VH1UKf9JemQj2B3QoUHfKD7Poewn0Pr3Y1w== dependencies: "@dabh/diagnostics" "^2.0.2" async "^3.2.3" @@ -26207,21 +26464,16 @@ write-pkg@^4.0.0: type-fest "^0.4.1" write-json-file "^3.2.0" -ws@8.7.0: - version "8.7.0" - resolved "https://registry.npmjs.org/ws/-/ws-8.7.0.tgz#eaf9d874b433aa00c0e0d8752532444875db3957" - integrity sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg== +ws@8.8.0, ws@^8.0.0, ws@^8.3.0: + version "8.8.0" + resolved "https://registry.npmjs.org/ws/-/ws-8.8.0.tgz#8e71c75e2f6348dbf8d78005107297056cb77769" + integrity sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ== ws@^7.3.1, ws@^7.4.6: version "7.5.7" resolved "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== -ws@^8.0.0, ws@^8.3.0: - version "8.8.0" - resolved "https://registry.npmjs.org/ws/-/ws-8.8.0.tgz#8e71c75e2f6348dbf8d78005107297056cb77769" - integrity sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ== - ws@^8.4.2: version "8.5.0" resolved "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f"