diff --git a/.changeset/analytics-millenial-whoop.md b/.changeset/analytics-millenial-whoop.md deleted file mode 100644 index 265e0072ce..0000000000 --- a/.changeset/analytics-millenial-whoop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-app-api': patch ---- - -Fixed a bug that could cause `navigate` analytics events to be misattributed to the plugin mounted on the root route (e.g. the `home` plugin at `/`) when the route that was navigated to wasn't associated with a routable extension. diff --git a/.changeset/chatty-foxes-buy.md b/.changeset/chatty-foxes-buy.md deleted file mode 100644 index 609ddc5269..0000000000 --- a/.changeset/chatty-foxes-buy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-graph': patch ---- - -Propagate entity spec to EntityNode so that spec info such as type can be used for graph node customization diff --git a/.changeset/chilly-keys-count.md b/.changeset/chilly-keys-count.md deleted file mode 100644 index 3bbc4e40dc..0000000000 --- a/.changeset/chilly-keys-count.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-playlist': patch ---- - -Displaying an alert popup each time the Playlist is created or deleted diff --git a/.changeset/create-app-1690284535.md b/.changeset/create-app-1690284535.md deleted file mode 100644 index b50d431d4b..0000000000 --- a/.changeset/create-app-1690284535.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Bumped create-app version. diff --git a/.changeset/gorgeous-months-doubt.md b/.changeset/gorgeous-months-doubt.md deleted file mode 100644 index d440e28b72..0000000000 --- a/.changeset/gorgeous-months-doubt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-openapi-utils': patch ---- - -Add a new `createRouter` method for generating an `express` router that validates against your spec. Also fixes a bug with the query parameters type resolution. diff --git a/.changeset/khaki-flies-draw.md b/.changeset/khaki-flies-draw.md deleted file mode 100644 index ada45dea06..0000000000 --- a/.changeset/khaki-flies-draw.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-gitlab': patch ---- - -Added option to skip forked repos in GitlabDiscoveryEntityProvider diff --git a/.changeset/large-experts-poke.md b/.changeset/large-experts-poke.md deleted file mode 100644 index 9f6ca640b6..0000000000 --- a/.changeset/large-experts-poke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-linguist-backend': patch ---- - -Fixed bug in LinguistBackendClient.ts file where if the linguistJsOptions is specified and sent over to the linguist-js package it would get changed (another attribute would be added) causing future entities of the batch to fail with an error diff --git a/.changeset/loud-garlics-press.md b/.changeset/loud-garlics-press.md deleted file mode 100644 index 28aee20619..0000000000 --- a/.changeset/loud-garlics-press.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Reload the frontend when app config changes diff --git a/.changeset/mean-squids-relax.md b/.changeset/mean-squids-relax.md deleted file mode 100644 index 558b42fcfc..0000000000 --- a/.changeset/mean-squids-relax.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-home-react': patch ---- - -Make `title` optional when defining the `createCardExtension` diff --git a/.changeset/neat-lamps-press.md b/.changeset/neat-lamps-press.md deleted file mode 100644 index 23c0b15fb7..0000000000 --- a/.changeset/neat-lamps-press.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/core-components': patch -'@backstage/plugin-splunk-on-call': patch -'@backstage/plugin-xcmetrics': patch -'@backstage/plugin-catalog': patch ---- - -Prefer simple `theme.spacing` without string interpolation diff --git a/.changeset/pink-squids-nail.md b/.changeset/pink-squids-nail.md deleted file mode 100644 index 989b5034d5..0000000000 --- a/.changeset/pink-squids-nail.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-unprocessed': minor ---- - -**BREAKING**: Fixing typo in exported module. You will have to rename the import to the correct spelling. `UnprocessedEntites` -> `UnprocessedEntities` diff --git a/.changeset/pre.json b/.changeset/pre.json deleted file mode 100644 index 46dfaafe4e..0000000000 --- a/.changeset/pre.json +++ /dev/null @@ -1,254 +0,0 @@ -{ - "mode": "pre", - "tag": "next", - "initialVersions": { - "example-app": "0.2.85", - "@backstage/app-defaults": "1.4.1", - "example-backend": "0.2.85", - "@backstage/backend-app-api": "0.4.5", - "@backstage/backend-common": "0.19.1", - "@backstage/backend-defaults": "0.1.12", - "@backstage/backend-dev-utils": "0.1.1", - "example-backend-next": "0.0.13", - "@backstage/backend-openapi-utils": "0.0.2", - "@backstage/backend-plugin-api": "0.5.4", - "@backstage/backend-tasks": "0.5.4", - "@backstage/backend-test-utils": "0.1.39", - "@backstage/catalog-client": "1.4.3", - "@backstage/catalog-model": "1.4.1", - "@backstage/cli": "0.22.9", - "@backstage/cli-common": "0.1.12", - "@backstage/cli-node": "0.1.2", - "@backstage/codemods": "0.1.45", - "@backstage/config": "1.0.8", - "@backstage/config-loader": "1.3.2", - "@backstage/core-app-api": "1.9.0", - "@backstage/core-components": "0.13.3", - "@backstage/core-plugin-api": "1.5.3", - "@backstage/create-app": "0.5.3", - "@backstage/dev-utils": "1.0.17", - "e2e-test": "0.2.5", - "@backstage/errors": "1.2.1", - "@backstage/eslint-plugin": "0.1.3", - "@backstage/integration": "1.5.1", - "@backstage/integration-aws-node": "0.1.5", - "@backstage/integration-react": "1.1.15", - "@backstage/release-manifests": "0.0.9", - "@backstage/repo-tools": "0.3.2", - "@techdocs/cli": "1.4.4", - "techdocs-cli-embedded-app": "0.2.84", - "@backstage/test-utils": "1.4.1", - "@backstage/theme": "0.4.1", - "@backstage/types": "1.1.0", - "@backstage/version-bridge": "1.0.4", - "@backstage/plugin-adr": "0.6.3", - "@backstage/plugin-adr-backend": "0.3.5", - "@backstage/plugin-adr-common": "0.2.11", - "@backstage/plugin-airbrake": "0.3.20", - "@backstage/plugin-airbrake-backend": "0.2.20", - "@backstage/plugin-allure": "0.1.36", - "@backstage/plugin-analytics-module-ga": "0.1.31", - "@backstage/plugin-analytics-module-ga4": "0.1.2", - "@backstage/plugin-apache-airflow": "0.2.13", - "@backstage/plugin-api-docs": "0.9.6", - "@backstage/plugin-api-docs-module-protoc-gen-doc": "0.1.2", - "@backstage/plugin-apollo-explorer": "0.1.13", - "@backstage/plugin-app-backend": "0.3.47", - "@backstage/plugin-auth-backend": "0.18.5", - "@backstage/plugin-auth-node": "0.2.16", - "@backstage/plugin-azure-devops": "0.3.2", - "@backstage/plugin-azure-devops-backend": "0.3.26", - "@backstage/plugin-azure-devops-common": "0.3.0", - "@backstage/plugin-azure-sites": "0.1.9", - "@backstage/plugin-azure-sites-backend": "0.1.9", - "@backstage/plugin-azure-sites-common": "0.1.0", - "@backstage/plugin-badges": "0.2.44", - "@backstage/plugin-badges-backend": "0.2.2", - "@backstage/plugin-bazaar": "0.2.11", - "@backstage/plugin-bazaar-backend": "0.2.10", - "@backstage/plugin-bitbucket-cloud-common": "0.2.8", - "@backstage/plugin-bitrise": "0.1.47", - "@backstage/plugin-catalog": "1.12.0", - "@backstage/plugin-catalog-backend": "1.11.0", - "@backstage/plugin-catalog-backend-module-aws": "0.2.2", - "@backstage/plugin-catalog-backend-module-azure": "0.1.18", - "@backstage/plugin-catalog-backend-module-bitbucket": "0.2.14", - "@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.1.14", - "@backstage/plugin-catalog-backend-module-bitbucket-server": "0.1.12", - "@backstage/plugin-catalog-backend-module-gerrit": "0.1.15", - "@backstage/plugin-catalog-backend-module-github": "0.3.2", - "@backstage/plugin-catalog-backend-module-gitlab": "0.2.3", - "@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.4.0", - "@backstage/plugin-catalog-backend-module-ldap": "0.5.14", - "@backstage/plugin-catalog-backend-module-msgraph": "0.5.6", - "@backstage/plugin-catalog-backend-module-openapi": "0.1.13", - "@backstage/plugin-catalog-backend-module-puppetdb": "0.1.4", - "@backstage/plugin-catalog-backend-module-unprocessed": "0.1.1", - "@backstage/plugin-catalog-common": "1.0.15", - "@internal/plugin-catalog-customized": "0.0.12", - "@backstage/plugin-catalog-graph": "0.2.32", - "@backstage/plugin-catalog-graphql": "0.3.22", - "@backstage/plugin-catalog-import": "0.9.10", - "@backstage/plugin-catalog-node": "1.4.0", - "@backstage/plugin-catalog-react": "1.8.0", - "@backstage/plugin-catalog-unprocessed-entities": "0.1.1", - "@backstage/plugin-cicd-statistics": "0.1.22", - "@backstage/plugin-cicd-statistics-module-gitlab": "0.1.16", - "@backstage/plugin-circleci": "0.3.20", - "@backstage/plugin-cloudbuild": "0.3.20", - "@backstage/plugin-code-climate": "0.1.20", - "@backstage/plugin-code-coverage": "0.2.13", - "@backstage/plugin-code-coverage-backend": "0.2.13", - "@backstage/plugin-codescene": "0.1.15", - "@backstage/plugin-config-schema": "0.1.43", - "@backstage/plugin-cost-insights": "0.12.9", - "@backstage/plugin-cost-insights-common": "0.1.1", - "@backstage/plugin-devtools": "0.1.2", - "@backstage/plugin-devtools-backend": "0.1.2", - "@backstage/plugin-devtools-common": "0.1.2", - "@backstage/plugin-dynatrace": "7.0.0", - "@backstage/plugin-entity-feedback": "0.2.3", - "@backstage/plugin-entity-feedback-backend": "0.1.5", - "@backstage/plugin-entity-feedback-common": "0.1.1", - "@backstage/plugin-entity-validation": "0.1.5", - "@backstage/plugin-events-backend": "0.2.8", - "@backstage/plugin-events-backend-module-aws-sqs": "0.2.2", - "@backstage/plugin-events-backend-module-azure": "0.1.9", - "@backstage/plugin-events-backend-module-bitbucket-cloud": "0.1.9", - "@backstage/plugin-events-backend-module-gerrit": "0.1.9", - "@backstage/plugin-events-backend-module-github": "0.1.9", - "@backstage/plugin-events-backend-module-gitlab": "0.1.9", - "@backstage/plugin-events-backend-test-utils": "0.1.9", - "@backstage/plugin-events-node": "0.2.8", - "@internal/plugin-todo-list": "1.0.15", - "@internal/plugin-todo-list-backend": "1.0.15", - "@internal/plugin-todo-list-common": "1.0.12", - "@backstage/plugin-explore": "0.4.6", - "@backstage/plugin-explore-backend": "0.0.9", - "@backstage/plugin-explore-common": "0.0.1", - "@backstage/plugin-explore-react": "0.0.30", - "@backstage/plugin-firehydrant": "0.2.4", - "@backstage/plugin-fossa": "0.2.52", - "@backstage/plugin-gcalendar": "0.3.16", - "@backstage/plugin-gcp-projects": "0.3.39", - "@backstage/plugin-git-release-manager": "0.3.33", - "@backstage/plugin-github-actions": "0.6.1", - "@backstage/plugin-github-deployments": "0.1.51", - "@backstage/plugin-github-issues": "0.2.9", - "@backstage/plugin-github-pull-requests-board": "0.1.14", - "@backstage/plugin-gitops-profiles": "0.3.38", - "@backstage/plugin-gocd": "0.1.26", - "@backstage/plugin-graphiql": "0.2.52", - "@backstage/plugin-graphql-backend": "0.1.37", - "@backstage/plugin-graphql-voyager": "0.1.5", - "@backstage/plugin-home": "0.5.4", - "@backstage/plugin-home-react": "0.1.1", - "@backstage/plugin-ilert": "0.2.9", - "@backstage/plugin-jenkins": "0.8.2", - "@backstage/plugin-jenkins-backend": "0.2.2", - "@backstage/plugin-jenkins-common": "0.1.17", - "@backstage/plugin-kafka": "0.3.20", - "@backstage/plugin-kafka-backend": "0.2.40", - "@backstage/plugin-kubernetes": "0.9.3", - "@backstage/plugin-kubernetes-backend": "0.11.2", - "@backstage/plugin-kubernetes-common": "0.6.5", - "@backstage/plugin-lighthouse": "0.4.5", - "@backstage/plugin-lighthouse-backend": "0.2.3", - "@backstage/plugin-lighthouse-common": "0.1.2", - "@backstage/plugin-linguist": "0.1.5", - "@backstage/plugin-linguist-backend": "0.3.1", - "@backstage/plugin-linguist-common": "0.1.0", - "@backstage/plugin-microsoft-calendar": "0.1.5", - "@backstage/plugin-newrelic": "0.3.38", - "@backstage/plugin-newrelic-dashboard": "0.2.13", - "@backstage/plugin-nomad": "0.1.1", - "@backstage/plugin-nomad-backend": "0.1.1", - "@backstage/plugin-octopus-deploy": "0.2.2", - "@backstage/plugin-org": "0.6.10", - "@backstage/plugin-org-react": "0.1.9", - "@backstage/plugin-pagerduty": "0.6.1", - "@backstage/plugin-periskop": "0.1.18", - "@backstage/plugin-periskop-backend": "0.1.18", - "@backstage/plugin-permission-backend": "0.5.22", - "@backstage/plugin-permission-common": "0.7.7", - "@backstage/plugin-permission-node": "0.7.10", - "@backstage/plugin-permission-react": "0.4.14", - "@backstage/plugin-playlist": "0.1.12", - "@backstage/plugin-playlist-backend": "0.3.3", - "@backstage/plugin-playlist-common": "0.1.8", - "@backstage/plugin-proxy-backend": "0.2.41", - "@backstage/plugin-puppetdb": "0.1.3", - "@backstage/plugin-rollbar": "0.4.20", - "@backstage/plugin-rollbar-backend": "0.1.44", - "@backstage/plugin-scaffolder": "1.14.1", - "@backstage/plugin-scaffolder-backend": "1.15.1", - "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.2.0", - "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.2.23", - "@backstage/plugin-scaffolder-backend-module-gitlab": "0.2.2", - "@backstage/plugin-scaffolder-backend-module-rails": "0.4.16", - "@backstage/plugin-scaffolder-backend-module-sentry": "0.1.7", - "@backstage/plugin-scaffolder-backend-module-yeoman": "0.2.20", - "@backstage/plugin-scaffolder-common": "1.3.2", - "@backstage/plugin-scaffolder-node": "0.1.5", - "@backstage/plugin-scaffolder-react": "1.5.1", - "@backstage/plugin-search": "1.3.3", - "@backstage/plugin-search-backend": "1.3.3", - "@backstage/plugin-search-backend-module-catalog": "0.1.3", - "@backstage/plugin-search-backend-module-elasticsearch": "1.3.2", - "@backstage/plugin-search-backend-module-explore": "0.1.3", - "@backstage/plugin-search-backend-module-pg": "0.5.8", - "@backstage/plugin-search-backend-module-techdocs": "0.1.3", - "@backstage/plugin-search-backend-node": "1.2.3", - "@backstage/plugin-search-common": "1.2.5", - "@backstage/plugin-search-react": "1.6.3", - "@backstage/plugin-sentry": "0.5.5", - "@backstage/plugin-shortcuts": "0.3.12", - "@backstage/plugin-sonarqube": "0.7.1", - "@backstage/plugin-sonarqube-backend": "0.2.1", - "@backstage/plugin-sonarqube-react": "0.1.7", - "@backstage/plugin-splunk-on-call": "0.4.9", - "@backstage/plugin-stack-overflow": "0.1.18", - "@backstage/plugin-stack-overflow-backend": "0.2.3", - "@backstage/plugin-stackstorm": "0.1.4", - "@backstage/plugin-tech-insights": "0.3.12", - "@backstage/plugin-tech-insights-backend": "0.5.13", - "@backstage/plugin-tech-insights-backend-module-jsonfc": "0.1.31", - "@backstage/plugin-tech-insights-common": "0.2.11", - "@backstage/plugin-tech-insights-node": "0.4.5", - "@backstage/plugin-tech-radar": "0.6.6", - "@backstage/plugin-techdocs": "1.6.5", - "@backstage/plugin-techdocs-addons-test-utils": "1.0.16", - "@backstage/plugin-techdocs-backend": "1.6.4", - "@backstage/plugin-techdocs-module-addons-contrib": "1.0.15", - "@backstage/plugin-techdocs-node": "1.7.3", - "@backstage/plugin-techdocs-react": "1.1.8", - "@backstage/plugin-todo": "0.2.22", - "@backstage/plugin-todo-backend": "0.1.44", - "@backstage/plugin-user-settings": "0.7.5", - "@backstage/plugin-user-settings-backend": "0.1.11", - "@backstage/plugin-vault": "0.1.14", - "@backstage/plugin-vault-backend": "0.3.3", - "@backstage/plugin-xcmetrics": "0.2.40", - "@backstage/plugin-analytics-module-newrelic-browser": "0.0.0" - }, - "changesets": [ - "analytics-millenial-whoop", - "chatty-foxes-buy", - "create-app-1690284535", - "gorgeous-months-doubt", - "large-experts-poke", - "loud-garlics-press", - "mean-squids-relax", - "neat-lamps-press", - "pink-squids-nail", - "quiet-starfishes-kick", - "rare-pens-exist", - "rude-feet-sparkle", - "search-donuts-wash", - "selfish-coats-shout", - "serious-bats-repair", - "smart-pandas-applaud", - "stupid-berries-run", - "ten-otters-appear" - ] -} diff --git a/.changeset/quiet-starfishes-kick.md b/.changeset/quiet-starfishes-kick.md deleted file mode 100644 index 2fc8ed632e..0000000000 --- a/.changeset/quiet-starfishes-kick.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-home': patch ---- - -Now, user can provide a language (optional) as input to receive a greeting in that specific language. Example: `` diff --git a/.changeset/rare-pens-exist.md b/.changeset/rare-pens-exist.md deleted file mode 100644 index 7363f5033a..0000000000 --- a/.changeset/rare-pens-exist.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Enable to print the config schema not merged with the `--no-merge` flag diff --git a/.changeset/rude-feet-sparkle.md b/.changeset/rude-feet-sparkle.md deleted file mode 100644 index fabc83bb0b..0000000000 --- a/.changeset/rude-feet-sparkle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-analytics-module-newrelic-browser': patch ---- - -Introduced the New Relic Browser analytics module. Check out the plugins [README.md](https://github.com/backstage/backstage/tree/master/plugins/analytics-module-newrelic-browser) for more details! diff --git a/.changeset/search-donuts-wash.md b/.changeset/search-donuts-wash.md deleted file mode 100644 index 2fa3325761..0000000000 --- a/.changeset/search-donuts-wash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search-backend-node': patch ---- - -Fix Lunr search engine highlight by ignoring invalid metadata positions. diff --git a/.changeset/selfish-coats-shout.md b/.changeset/selfish-coats-shout.md deleted file mode 100644 index 071c47e371..0000000000 --- a/.changeset/selfish-coats-shout.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -'@backstage/config-loader': minor ---- - -Adds a new `deepVisibility` schema keyword that sets child visibility recursively to the defined value, respecting preexisting values or child `deepVisibility`. - -Example usage: - -```ts -export interface Config { - /** - * Enforces a default of `secret` instead of `backend` for this object. - * @deepVisibility secret - */ - mySecretProperty: { - type: 'object'; - properties: { - secretValue: { - type: 'string'; - }; - - verySecretProperty: { - type: 'string'; - }; - }; - }; -} -``` - -Example of a schema that would not be allowed: - -```ts -export interface Config { - /** - * Set the top level property to secret, enforcing a default of `secret` instead of `backend` for this object. - * @deepVisibility secret - */ - mySecretProperty: { - type: 'object'; - properties: { - frontendUrl: { - /** - * We can NOT override the visibility to reveal a property to the front end. - * @visibility frontend - */ - type: 'string'; - }; - - verySecretProperty: { - type: 'string'; - }; - }; - }; -} -``` diff --git a/.changeset/serious-bats-repair.md b/.changeset/serious-bats-repair.md deleted file mode 100644 index d93b49bda0..0000000000 --- a/.changeset/serious-bats-repair.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/repo-tools': patch ---- - -Update `schema openapi generate` command to now create a default router that can be imported and used directly. diff --git a/.changeset/smart-pandas-applaud.md b/.changeset/smart-pandas-applaud.md deleted file mode 100644 index 5f2c297df5..0000000000 --- a/.changeset/smart-pandas-applaud.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-todo-backend': minor -'@backstage/plugin-catalog-backend': minor -'@backstage/plugin-search-backend': minor ---- - -Now performs request validation based on OpenAPI schema through `@backstage/backend-openapi-utils`. Error responses for invalid input, like `"a"` instead of a number, may have changed. diff --git a/.changeset/stupid-berries-run.md b/.changeset/stupid-berries-run.md deleted file mode 100644 index f506ce2475..0000000000 --- a/.changeset/stupid-berries-run.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-home': patch ---- - -Make sure the widget name is never empty in the `AddWidgetDialog`. If the title was set to "", the entry would contain an empty string. Use the name as a fallback diff --git a/.changeset/ten-otters-appear.md b/.changeset/ten-otters-appear.md deleted file mode 100644 index 4cb3d301ae..0000000000 --- a/.changeset/ten-otters-appear.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-react': patch ---- - -Fixed bug in Workflow component by passing a prop `templateName` down to Stepper component. diff --git a/.clomonitor.yml b/.clomonitor.yml new file mode 100644 index 0000000000..1e217dd400 --- /dev/null +++ b/.clomonitor.yml @@ -0,0 +1,9 @@ +# CLOMonitor metadata file +# This file must be located at the root of the repository +# https://clomonitor.io/projects/cncf/backstage + +# Checks exemptions +exemptions: + - check: trademark_disclaimer # Check identifier (see https://github.com/cncf/clomonitor/blob/main/docs/checks.md#exemptions) + # Justification of this exemption (mandatory, it will be displayed on the UI) + reason: 'The Linux Foundation trademark disclaimer and link are contained within the project web site at https://backstage.io in the copyright footer. However, because the site is delivered dynamically via React through JavaScript, the check cannot currently identify it.' diff --git a/.github/labeler.yml b/.github/labeler.yml index eaba199588..dc048b1744 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -24,6 +24,8 @@ documentation: - docs/**/* microsite: - microsite/**/* +storybook: + - storybook/**/* auth: - plugins/auth-backend/**/* - packages/core-app-api/src/apis/implementations/auth/**/* diff --git a/.github/uffizzi/uffizzi.production.app-config.yaml b/.github/uffizzi/uffizzi.production.app-config.yaml index 77b093e024..4f64e5ffcb 100644 --- a/.github/uffizzi/uffizzi.production.app-config.yaml +++ b/.github/uffizzi/uffizzi.production.app-config.yaml @@ -56,72 +56,73 @@ catalog: - allow: [Template] proxy: - '/circleci/api': - target: https://circleci.com/api/v1.1 - headers: - Circle-Token: ${CIRCLECI_AUTH_TOKEN} + endpoints: + '/circleci/api': + target: https://circleci.com/api/v1.1 + headers: + Circle-Token: ${CIRCLECI_AUTH_TOKEN} - '/jenkins/api': - target: http://localhost:8080 - headers: - Authorization: ${JENKINS_BASIC_AUTH_HEADER} + '/jenkins/api': + target: http://localhost:8080 + headers: + Authorization: ${JENKINS_BASIC_AUTH_HEADER} - '/travisci/api': - target: https://api.travis-ci.com - changeOrigin: true - headers: - Authorization: ${TRAVISCI_AUTH_TOKEN} - travis-api-version: '3' + '/travisci/api': + target: https://api.travis-ci.com + changeOrigin: true + headers: + Authorization: ${TRAVISCI_AUTH_TOKEN} + travis-api-version: '3' - '/newrelic/apm/api': - target: https://api.newrelic.com/v2 - headers: - X-Api-Key: ${NEW_RELIC_REST_API_KEY} + '/newrelic/apm/api': + target: https://api.newrelic.com/v2 + headers: + X-Api-Key: ${NEW_RELIC_REST_API_KEY} - '/newrelic/api': - target: https://api.newrelic.com - headers: - X-Api-Key: ${NEW_RELIC_USER_KEY} + '/newrelic/api': + target: https://api.newrelic.com + headers: + X-Api-Key: ${NEW_RELIC_USER_KEY} - '/pagerduty': - target: https://api.pagerduty.com - headers: - Authorization: Token token=${PAGERDUTY_TOKEN} + '/pagerduty': + target: https://api.pagerduty.com + headers: + Authorization: Token token=${PAGERDUTY_TOKEN} - '/buildkite/api': - target: https://api.buildkite.com/v2/ - headers: - Authorization: ${BUILDKITE_TOKEN} + '/buildkite/api': + target: https://api.buildkite.com/v2/ + headers: + Authorization: ${BUILDKITE_TOKEN} - '/sentry/api': - target: https://sentry.io/api/ - allowedMethods: ['GET'] - headers: - Authorization: ${SENTRY_TOKEN} + '/sentry/api': + target: https://sentry.io/api/ + allowedMethods: ['GET'] + headers: + Authorization: ${SENTRY_TOKEN} - '/ilert': - target: https://api.ilert.com - allowedMethods: ['GET', 'POST', 'PUT'] - allowedHeaders: ['Authorization'] - headers: - Authorization: ${ILERT_AUTH_HEADER} + '/ilert': + target: https://api.ilert.com + allowedMethods: ['GET', 'POST', 'PUT'] + allowedHeaders: ['Authorization'] + headers: + Authorization: ${ILERT_AUTH_HEADER} - '/airflow': - target: https://your.airflow.instance.com/api/v1 - headers: - Authorization: ${AIRFLOW_BASIC_AUTH_HEADER} + '/airflow': + target: https://your.airflow.instance.com/api/v1 + headers: + Authorization: ${AIRFLOW_BASIC_AUTH_HEADER} - '/gocd': - target: https://your.gocd.instance.com/go/api - allowedMethods: ['GET'] - allowedHeaders: ['Authorization'] - headers: - Authorization: Basic ${GOCD_AUTH_CREDENTIALS} + '/gocd': + target: https://your.gocd.instance.com/go/api + allowedMethods: ['GET'] + allowedHeaders: ['Authorization'] + headers: + Authorization: Basic ${GOCD_AUTH_CREDENTIALS} - '/dynatrace': - target: https://your.dynatrace.instance.com/api/v2 - headers: - Authorization: 'Api-Token ${DYNATRACE_ACCESS_TOKEN}' + '/dynatrace': + target: https://your.dynatrace.instance.com/api/v2 + headers: + Authorization: 'Api-Token ${DYNATRACE_ACCESS_TOKEN}' techdocs: builder: 'local' # Alternatives - 'external' diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index ed09c73c91..9fa7af5585 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -123,8 +123,11 @@ FireHydrant Firekube Firestore Fiverr +Flightcontrol +flightcontrol Francesco Frontside +Gaurav gerrit Gerrit gitbeaker @@ -164,6 +167,7 @@ inlined inlinehilite integrator's interop +iterable JaCoCo JavaScript jenkins @@ -257,6 +261,7 @@ padding paddings pagerduty pageview +Pandey parallelization parseable Patrik @@ -405,6 +410,7 @@ unbreak Unconference unicode unmanaged +unmount unregister unregistering unregistration diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 0000000000..85c4b70724 --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,66 @@ +# This workflow uses actions that are not certified by GitHub. They are provided +# by a third-party and are governed by separate terms of service, privacy +# policy, and support documentation. + +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + # branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '41 8 * * 6' + push: + branches: ['master'] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + + steps: + - name: 'Checkout code' + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + with: + persist-credentials: false + + - name: 'Run analysis' + uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # v2.2.0 + with: + results_file: results.sarif + results_format: sarif + # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: + # - you want to enable the Branch-Protection check on a *public* repository, or + # - you are installing Scorecard on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. + # repo_token: ${{ secrets.SCORECARD_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: 'Upload artifact' + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard. + - name: 'Upload to code-scanning' + uses: github/codeql-action/upload-sarif@17573ee1cc1b9d061760f3a006fc4aac4f944fd5 # v2.2.4 + with: + sarif_file: results.sarif diff --git a/.github/workflows/verify_e2e-kubernetes-noop.yml b/.github/workflows/verify_e2e-kubernetes-noop.yml index ee9dbc69e2..ac49fbc469 100644 --- a/.github/workflows/verify_e2e-kubernetes-noop.yml +++ b/.github/workflows/verify_e2e-kubernetes-noop.yml @@ -6,7 +6,7 @@ on: pull_request: paths-ignore: - 'yarn.lock' - - '.github/workflows/verify_kubernetes.yml' + - '.github/workflows/verify_e2e-kubernetes.yml' - 'packages/backend-common/src/**' jobs: diff --git a/.github/workflows/verify_e2e-kubernetes.yml b/.github/workflows/verify_e2e-kubernetes.yml index c05339f595..4c25c259c5 100644 --- a/.github/workflows/verify_e2e-kubernetes.yml +++ b/.github/workflows/verify_e2e-kubernetes.yml @@ -4,7 +4,7 @@ on: pull_request: paths: - 'yarn.lock' - - '.github/workflows/verify_kubernetes.yml' + - '.github/workflows/verify_e2e-kubernetes.yml' - 'packages/backend-common/src/**' jobs: @@ -35,7 +35,7 @@ jobs: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: bootstrap kind - uses: helm/kind-action@v1.7.0 + uses: helm/kind-action@v1.8.0 - name: kubernetes test working-directory: packages/backend-common diff --git a/ADOPTERS.md b/ADOPTERS.md index 926c303313..6668d471bb 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -43,7 +43,7 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/ | [MavTek](https://www.mavtek.com/) | [@fgascon](https://github.com/fgascon) | Developer portal focused on standardizing practices, centralizing documentation and streamlining developer practices. | | [QuintoAndar](https://www.quintoandar.com.br/) | [@quintoandar](https://github.com/quintoandar) | Developer portal, services catalog and centralization of service metrics. | | [empathy.co](https://empathy.co/) | [@guillermotti](https://github.com/guillermotti) | Developer portal for tech docs, service catalog, plugin discovery and much more. | -| [creditas.com](https://creditas.com/) | [@aureliosaraiva](https://github.com/aureliosaraiva) [@Creditas](https://github.com/creditas) | Centralization of all services, standards, documentation, etc. We started the deployment process. | +| [creditas.com](https://creditas.com/) | [@rebender](https://github.com/rebender) [@Creditas](https://github.com/creditas) | Centralization of all services, standards, documentation, etc. We started the deployment process. | | [Prisjakt](https://www.prisjakt.nu) / [PriceSpy](https://pricespy.co.uk) | [@kennylindahl](https://github.com/kennylindahl) | Internal developer portal - Documentation, scaffolding, software catalog, TechRadar, Gitlab org data integration | | [Powerspike](https://powerspike.tv/) | [@trelore](https://github.com/trelore) | Developer portal for documentation of core libraries and repositories. | | [2U](https://2u.com) | [@danielleEriksen](https://github.com/danielleEriksen), [@sbhatia](https://github.com/sbhatia) | Development team home-base, promoting service discoverability, resource dependencies, and tech radar | @@ -254,3 +254,6 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/ | [Celonis](https://celonis.com) | [@georgeyord](https://github.com/georgeyord), [@LauraMoraB](https://github.com/LauraMoraB), [@mariosant](https://github.com/mariosant), [@Rbillon59](https://github.com/Rbillon59) | Internal developer and product portal implementation. | | [Rabobank](https://www.rabobank.com) | [Willem Dekker](https://github.com/wdekker), [Sridhar Gnanasekaran](https://github.com/srid99), [Ruben Ernst](https://github.com/Ruben-E) | At Rabobank, our mission is to make life better for engineers. After exploring various options in the market, we've discovered that Backstage provides the perfect foundation for creating a platform that meets our engineers' needs and helps us achieve our goals. We want to make our engineers happy by offering standardized services, freeing them up to focus on delivering value. Our vision is to create a one-stop platform where engineers can find everything related to software and services. In practice, we're excited about using all the cool features in Backstage, and we're even planning to build our own plugins. | | [JB Hi-Fi](https://www.jbhifi.com.au) | [@bahman](https://github.com/bahman-jb/) | We use Backstage as a central place for all of our components/apis across multiple teams. It helps us to quickly identify the ownership of a component/api, find the related links and have a quick access to CI/CD pipelines. | +| [Zenklub](https://www.zenklub.com.br) | [@zenklub](https://github.com/zenklub), [@gioufop](https://github.com/gioufop) | Developer portal, services catalog and centralization of metrics from Grafana Stack and AWS. Furthermore, centralization of documentation and infra details like Tools, Network services and so on. | +| [Platzi](https://platzi.com/) | [@juancarestre](https://github.com/juancarestre/), [Engineering at Platzi](https://github.com/PlatziDev/) | Backstage allow our developers to get easily engaged with all the internal components, technical documentations and software templates. All new developers reduce its onboarding time via Backstage, and after a couple of integrations it allowed us to create new components with in a couple of clicks. | +| [idealo](https://idealo.de) | [Wanis Fahmy](https://github.com/wanisfahmyDE), [Sajjad Pervaiz](https://github.com/sjvaiz), [Tim Heurich](https://github.com/theurichde) | Backstage is our Internal developer portal. Along with other plugins, We use the software catalog, TechDocs and explore plugins to manage, discover and document our software components and platform products. | diff --git a/OWNERS.md b/OWNERS.md index 5a9457d755..66575e8e35 100644 --- a/OWNERS.md +++ b/OWNERS.md @@ -42,6 +42,7 @@ Scope: Discoverability within Backstage, including the home page, information ar | Emma Indal | Spotify | BUX | [emmaindal](http://github.com/emmaindal) | emmaindal#7503 | | Raghunandan Balachandran | Spotify | BUX | [soapraj](http://github.com/soapraj) | raghunandanb#1114 | | Renan Mendes Carvalho | Spotify | BUX | [aitherios](http://github.com/aitherios) | aitherios#0593 | +| Bailey Brooks | Spotify | BUX | [bailey](http://github.com/bailey) | \_bailey4 | ### Helm Charts diff --git a/README.md b/README.md index d9da778694..ff72c41c87 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ [![Codecov](https://img.shields.io/codecov/c/github/backstage/backstage)](https://codecov.io/gh/backstage/backstage) [![](https://img.shields.io/github/v/release/backstage/backstage)](https://github.com/backstage/backstage/releases) [![Uffizzi](https://img.shields.io/endpoint?url=https%3A%2F%2Fapp.uffizzi.com%2Fapi%2Fv1%2Fpublic%2Fshields%2Fgithub.com%2Fbackstage%2Fbackstage)](https://app.uffizzi.com/ephemeral-environments/backstage/backstage) - -> 🏖️ The week beginning the 26th of June, some of the maintainers will be taking a well earned Summer Holiday break. We will be slower to respond to issues and PRs during this time. Releases will continue to be shipped weekly. Normal service will resume on the 24th of July. 🏝️ +[![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/7678/badge)](https://bestpractices.coreinfrastructure.org/projects/7678) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/backstage/backstage/badge)](https://securityscorecards.dev/viewer/?uri=github.com/backstage/backstage) ## What is Backstage? diff --git a/app-config.yaml b/app-config.yaml index 2b562ee689..37cb61f26e 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -20,6 +20,8 @@ app: - url: https://discord.gg/backstage-687207715902193673 title: '#backstage' + packageName: example-app + backend: # Used for enabling authentication, secret is shared by all backend plugins # See https://backstage.io/docs/auth/service-to-service-auth for @@ -49,80 +51,83 @@ backend: # See README.md in the proxy-backend plugin for information on the configuration format proxy: - '/circleci/api': - target: https://circleci.com/api/v1.1 - headers: - Circle-Token: ${CIRCLECI_AUTH_TOKEN} + endpoints: + '/circleci/api': + target: https://circleci.com/api/v1.1 + headers: + Circle-Token: ${CIRCLECI_AUTH_TOKEN} - '/jenkins/api': - target: http://localhost:8080 - headers: - Authorization: ${JENKINS_BASIC_AUTH_HEADER} + '/jenkins/api': + target: http://localhost:8080 + headers: + Authorization: ${JENKINS_BASIC_AUTH_HEADER} - '/travisci/api': - target: https://api.travis-ci.com - changeOrigin: true - headers: - Authorization: ${TRAVISCI_AUTH_TOKEN} - travis-api-version: '3' + '/travisci/api': + target: https://api.travis-ci.com + changeOrigin: true + headers: + Authorization: ${TRAVISCI_AUTH_TOKEN} + travis-api-version: '3' - '/newrelic/apm/api': - target: https://api.newrelic.com/v2 - headers: - X-Api-Key: ${NEW_RELIC_REST_API_KEY} + '/newrelic/apm/api': + target: https://api.newrelic.com/v2 + headers: + X-Api-Key: ${NEW_RELIC_REST_API_KEY} + allowedHeaders: + - link - '/newrelic/api': - target: https://api.newrelic.com - headers: - X-Api-Key: ${NEW_RELIC_USER_KEY} + '/newrelic/api': + target: https://api.newrelic.com + headers: + X-Api-Key: ${NEW_RELIC_USER_KEY} - '/pagerduty': - target: https://api.pagerduty.com - headers: - Authorization: Token token=${PAGERDUTY_TOKEN} + '/pagerduty': + target: https://api.pagerduty.com + headers: + Authorization: Token token=${PAGERDUTY_TOKEN} - '/buildkite/api': - target: https://api.buildkite.com/v2/ - headers: - Authorization: ${BUILDKITE_TOKEN} + '/buildkite/api': + target: https://api.buildkite.com/v2/ + headers: + Authorization: ${BUILDKITE_TOKEN} - '/sentry/api': - target: https://sentry.io/api/ - allowedMethods: ['GET'] - headers: - Authorization: ${SENTRY_TOKEN} + '/sentry/api': + target: https://sentry.io/api/ + allowedMethods: ['GET'] + headers: + Authorization: ${SENTRY_TOKEN} - '/ilert': - target: https://api.ilert.com - allowedMethods: ['GET', 'POST', 'PUT'] - allowedHeaders: ['Authorization'] - headers: - Authorization: ${ILERT_AUTH_HEADER} + '/ilert': + target: https://api.ilert.com + allowedMethods: ['GET', 'POST', 'PUT'] + allowedHeaders: ['Authorization'] + headers: + Authorization: ${ILERT_AUTH_HEADER} - '/airflow': - target: https://your.airflow.instance.com/api/v1 - headers: - Authorization: ${AIRFLOW_BASIC_AUTH_HEADER} + '/airflow': + target: https://your.airflow.instance.com/api/v1 + headers: + Authorization: ${AIRFLOW_BASIC_AUTH_HEADER} - '/gocd': - target: https://your.gocd.instance.com/go/api - allowedMethods: ['GET'] - allowedHeaders: ['Authorization'] - headers: - Authorization: Basic ${GOCD_AUTH_CREDENTIALS} + '/gocd': + target: https://your.gocd.instance.com/go/api + allowedMethods: ['GET'] + allowedHeaders: ['Authorization'] + headers: + Authorization: Basic ${GOCD_AUTH_CREDENTIALS} - '/dynatrace': - target: https://your.dynatrace.instance.com/api/v2 - headers: - Authorization: 'Api-Token ${DYNATRACE_ACCESS_TOKEN}' + '/dynatrace': + target: https://your.dynatrace.instance.com/api/v2 + headers: + Authorization: 'Api-Token ${DYNATRACE_ACCESS_TOKEN}' - '/stackstorm': - target: https://your.stackstorm.instance.com/api - headers: - St2-Api-Key: ${ST2_API_KEY} + '/stackstorm': + target: https://your.stackstorm.instance.com/api + headers: + St2-Api-Key: ${ST2_API_KEY} - '/puppetdb': - target: https://your.puppetdb.instance.com + '/puppetdb': + target: https://your.puppetdb.instance.com organization: name: My Company @@ -211,7 +216,7 @@ integrations: # clientEmail: 'example@example.com' # privateKey: ${GCS_PRIVATE_KEY} awsS3: - - host: amazonaws.com + - endpoint: ${AWS_S3_ENDPOINT} accessKeyId: ${AWS_ACCESS_KEY_ID} secretAccessKey: ${AWS_SECRET_ACCESS_KEY} @@ -352,8 +357,6 @@ auth: metadataUrl: ${AUTH_OIDC_METADATA_URL} clientId: ${AUTH_OIDC_CLIENT_ID} clientSecret: ${AUTH_OIDC_CLIENT_SECRET} - authorizationUrl: ${AUTH_OIDC_AUTH_URL} - tokenUrl: ${AUTH_OIDC_TOKEN_URL} tokenEndpointAuthMethod: ${AUTH_OIDC_TOKEN_ENDPOINT_AUTH_METHOD} # default='client_secret_basic' tokenSignedResponseAlg: ${AUTH_OIDC_TOKEN_SIGNED_RESPONSE_ALG} # default='RS256' scope: ${AUTH_OIDC_SCOPE} # default='openid profile email' @@ -434,8 +437,10 @@ costInsights: kind: 'PINTS_OF_ICE_CREAM' unit: 'ice cream pint' rate: 5.5 -pagerduty: + +pagerDuty: eventsBaseUrl: 'https://events.pagerduty.com/v2' + jenkins: instances: - name: default diff --git a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md index 1bdf9cc367..f28a62c018 100644 --- a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md +++ b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md @@ -58,6 +58,7 @@ When using ALB authentication Backstage will only be loaded once the user has su import React from 'react'; import { UserIdentity } from '@backstage/core-components'; import { SignInPageProps } from '@backstage/core-app-api'; +import { useApi, configApiRef } from '@backstage/core-plugin-api'; const SampleSignInComponent: any = (props: SignInPageProps) => { const [error, setError] = React.useState(); @@ -90,8 +91,8 @@ const SampleSignInComponent: any = (props: SignInPageProps) => { }, }), ); - } catch (err) { - setError(err.message); + } catch (err: any) { + setError(err.message as string); } } }, [config]); @@ -135,12 +136,14 @@ export default async function createPlugin({ database, config, discovery, + tokenManager, }: PluginEnvironment): Promise { return await createRouter({ logger, config, database, discovery, + tokenManager, providerFactories: { awsalb: providers.awsAlb.create({ authHandler: async ({ fullProfile }) => { @@ -168,25 +171,29 @@ export default async function createPlugin({ }; }, signIn: { - resolver: async ({ profile: { email } }, ctx) => { - const [id] = email?.split('@') ?? ''; - // Fetch from an external system that returns entity claims like: - // ['user:default/breanna.davison', ...] - const userEntityRef = stringifyEntityRef({ + resolver: async ({ profile }, ctx) => { + if (!profile.email) { + throw new Error('Profile contained no email'); + } + + const [id] = profile.email.split('@'); + if (!id) { + throw new Error('Invalid email format'); + } + + const userRef = stringifyEntityRef({ kind: 'User', - namespace: DEFAULT_NAMESPACE, name: id, + namespace: DEFAULT_NAMESPACE, }); - // Resolve group membership from the Backstage catalog - const fullEnt = - await ctx.catalogIdentityClient.resolveCatalogMembership({ - entityRefs: [id].concat([userEntityRef]), - logger: ctx.logger, - }); - const token = await ctx.tokenIssuer.issueToken({ - claims: { sub: userEntityRef, ent: fullEnt }, + const { token } = await ctx.issueToken({ + claims: { + sub: userRef, + ent: [userRef], + }, }); + return { id, token }; }, }, diff --git a/docs/auth/auth0/provider.md b/docs/auth/auth0/provider.md index e9393cfa0b..dcd02d226f 100644 --- a/docs/auth/auth0/provider.md +++ b/docs/auth/auth0/provider.md @@ -41,14 +41,18 @@ auth: secret: ${AUTH_SESSION_SECRET} ``` -The Auth0 provider is a structure with three configuration keys: +The Auth0 provider is a structure with these configuration keys: - `clientId`: The Application client ID, found on the Auth0 Application page - `clientSecret`: The Application client secret, found on the Auth0 Application page - `domain`: The Application domain, found on the Auth0 Application page -Because Auth0 requires a session you need to give the session a secret key. +It additionally relies on the following configuration to function: + +- `session.secret`: The session secret is a key used for signing and/or encrypting cookies set by the application to maintain session state. In this case, 'your session secret' should be replaced with a long, complex, and unique string that only your application knows. + +Auth0 requires a session, so you need to give the session a secret key. ## Optional Configuration diff --git a/docs/auth/oauth2-proxy/provider.md b/docs/auth/oauth2-proxy/provider.md index 9c8f681138..5cff655c02 100644 --- a/docs/auth/oauth2-proxy/provider.md +++ b/docs/auth/oauth2-proxy/provider.md @@ -20,8 +20,10 @@ The provider configuration can be added to your `app-config.yaml` under the root ```yaml title="app-config.yaml" auth: + environment: development providers: - oauth2Proxy: {} + oauth2Proxy: + development: {} ``` Right now no configuration options are supported, but the empty object is needed @@ -58,6 +60,8 @@ providerFactories: { }, ``` +[An example on how to sign a user in without a matching user](https://github.com/backstage/backstage/blob/master/packages/backend/src/plugins/auth.ts) + ## Adding the provider to the Backstage frontend It is recommended to use the `ProxiedSignInPage` for this provider, which is diff --git a/docs/backend-system/architecture/01-index.md b/docs/backend-system/architecture/01-index.md index aff730b0d1..256d43bc4c 100644 --- a/docs/backend-system/architecture/01-index.md +++ b/docs/backend-system/architecture/01-index.md @@ -59,7 +59,7 @@ Just like plugins, modules also have access to services and can depend on their A detailed explanation of the package architecture can be found in the [Backstage Architecture -Overview](../../overview/architecture-overview.md#package-architecture). The +Overview](../../overview/architecture-overview/#package-architecture). The most important packages to consider for this system are the following: - `plugin--backend` houses the implementation of the backend plugins diff --git a/docs/backend-system/architecture/02-backends.md b/docs/backend-system/architecture/02-backends.md index b6079d71b4..70ea8f7836 100644 --- a/docs/backend-system/architecture/02-backends.md +++ b/docs/backend-system/architecture/02-backends.md @@ -37,4 +37,4 @@ At a high level, when you call `createBackend`, it will create a new backend ins Underneath the hood, `createBackend` calls `createSpecializedBackend` from `@backstage/backend-app-api` which is responsible for actually creating the backend instance, but with no services or no features. You can think of `createBackend` more of a 'batteries included' approach, and `createSpecializedBackend` a little more low level. -As mentioned previously there's also the ability to create multiple of these backends in your project so that you can split apart your backend and deploy different backends that can scale independently of each other. For instance you might choose to deploy a backend with only the catalog plugin enabled, and one with just the scaffolder plugin enabled. We've provided some tools to be able to share services and defaults across your backend system, and you can find out more about that in the [shared environments docs](../building-backends/01-index.md#shared-environments). +As mentioned previously there's also the ability to create multiple of these backends in your project so that you can split apart your backend and deploy different backends that can scale independently of each other. For instance you might choose to deploy a backend with only the catalog plugin enabled, and one with just the scaffolder plugin enabled. diff --git a/docs/backend-system/building-backends/01-index.md b/docs/backend-system/building-backends/01-index.md index 66bf68ab07..d4b463af41 100644 --- a/docs/backend-system/building-backends/01-index.md +++ b/docs/backend-system/building-backends/01-index.md @@ -61,11 +61,11 @@ All of these services can be replaced with your own implementations if you need For example, let's say we want to customize the core configuration service to enable remote configuration loading. That would look something like this: ```ts -import { configServiceFactory } from '@backstage/backend-app-api'; +import { rootConfigServiceFactory } from '@backstage/backend-app-api'; const backend = createBackend({ services: [ - configServiceFactory({ + rootConfigServiceFactory({ remote: { reloadIntervalSeconds: 60 }, }), ], @@ -148,35 +148,3 @@ backend.start(); ``` We've now split the backend into two separate deployments, but we still need to make sure that they can communicate with each other. This is the hard and somewhat tedious part, as Backstage currently doesn't provide an out of the box solution that solves this. You'll need to manually configure the two backends with custom implementations of the `DiscoveryService` and have them return the correct URLs for each other. Likewise, you'll also need to provide a custom implementation of the `DiscoveryApi` in the frontend, unless you surface the two backends via a proxy that handles the routing instead. - -### Shared Environments - -To make it a bit easier to manage multiple backends, it's possible to create a shared environment that can be used across multiple backends. You would typically house it in a separate package that can be referenced by backends in your monorepo, or published to a package registry for broader use. - -A shared environment contains a set of service implementations that should be used across all backends. These services will override the default ones, but if a service is provided directly to the backend, it will override the one in the shared environment. - -A shared environment is defined using `createSharedEnvironment`. In this example we place it in a new and separate package called `backend-env`: - -```ts -// packages/backend-env/src/index.ts -import { createSharedEnvironment } from '@backstage/backend-plugin-api'; -import { customDiscoveryServiceFactory } from './customDiscoveryServiceFactory'; - -export const env = createSharedEnvironment({ - services: [ - customDiscoveryServiceFactory(), // custom DiscoveryService implementation - ], -}); -``` - -And passed on to backends using the `env` option: - -```ts -// packages/backend-b/src/index.ts, imports omitted -import { env } from '@internal/backend-env'; - -const backend = createBackend({ env }); - -backend.add(scaffolderPlugin()); -backend.start(); -``` diff --git a/docs/backend-system/building-plugins-and-modules/02-testing.md b/docs/backend-system/building-plugins-and-modules/02-testing.md index 7f93fab45b..fdd8cdb1e3 100644 --- a/docs/backend-system/building-plugins-and-modules/02-testing.md +++ b/docs/backend-system/building-plugins-and-modules/02-testing.md @@ -37,7 +37,7 @@ describe('myPlugin', () => { const { server } = await startTestBackend({ features: [myPlugin()], - services: [mockServices.config.factory({ data: fakeConfig })], + services: [mockServices.rootConfig.factory({ data: fakeConfig })], }); const response = await request(server).get('/api/example/get-value'); diff --git a/docs/backend-system/core-services/01-index.md b/docs/backend-system/core-services/01-index.md index c688055c96..a51db3c993 100644 --- a/docs/backend-system/core-services/01-index.md +++ b/docs/backend-system/core-services/01-index.md @@ -183,11 +183,11 @@ There's additional configuration that you can optionally pass to setup the `conf You can configure these additional options by adding an override for the core service when calling `createBackend` like follows: ```ts -import { configServiceFactory } from '@backstage/backend-app-api'; +import { rootConfigServiceFactory } from '@backstage/backend-app-api'; const backend = createBackend({ services: [ - configServiceFactory({ + rootConfigServiceFactory({ argv: [ '--config', '/backstage/app-config.development.yaml', diff --git a/docs/deployment/flightcontrol.md b/docs/deployment/flightcontrol.md new file mode 100644 index 0000000000..482e9341ea --- /dev/null +++ b/docs/deployment/flightcontrol.md @@ -0,0 +1,78 @@ +--- +id: flightcontrol +title: Deploying with Flightcontrol +sidebar_label: AWS Fargate via Flightcontrol +description: Deploying Backstage to AWS Fargate via Flightcontrol +--- + +This guide explains how to deploy Backstage to [Flightcontrol](https://www.flightcontrol.dev?ref=backstage), a platform that fully automates deployments to Amazon Web Services (AWS). Flightcontrol supports git-driven and image registry deployments. + +Before you begin, make sure you have a [Flightcontrol account](https://app.flightcontrol.dev/signup?ref=backstage) and a [Github account](https://github.com/login) to follow this guide. + +# Deployment Via Dashboard + +1. Create a new project from the Flightcontrol Dashboard + +2. Select the GitHub repo for your Backstage project + +3. Select `GUI` as the config type: + +4. Then, choose `+ Add Web Server (Fargate)` under Services before entering the following server information: + +| Field Name | Value | +| ----------------- | ----------------- | +| Build Type | Custom Dockerfile | +| Health Check Path | /catalog | +| Port | 7007 | + +5. Click `Create Project` and complete any required steps (like linking your AWS account). + +# Deployment via Code + +1. Create a new project from the Flightcontrol Dashboard + +2. Select the GitHub repo for your Backstage project + +3. Select the `flightcontrol.json` Config Type. + +```json filename="flightcontrol.json" +{ + "$schema": "https://app.flightcontrol.dev/schema.json", + "environments": [ + { + "id": "backstage", + "name": "Backstage", + "region": "us-west-2", + "source": { + "branch": "main" + }, + "services": [ + { + "id": "backstage", + "name": "Backstage", + "type": "fargate", + "buildType": "docker", + "dockerfilePath": "Dockerfile", + "dockerContext": ".", + "healthCheckPath": "/catalog", + "cpu": 0.5, + "memory": 1, + "domain": "backstage.yourapp.com", + "port": 7007, + "minInstances": 1, + "maxInstances": 1 + } + ] + } + ] +} +``` + +# Databases and Redis + +If you need a database or Redis for your Backstage plugins, you can easily add those to your Flightcontrol deployment. For more information, see [the flightcontrol docs](https://www.flightcontrol.dev/docs/guides/flightcontrol/using-code?ref=backstage#redis). + +## Troubleshooting + +- [Flightcontrol Documentation](https://www.flightcontrol.dev/docs?ref=backstage) +- [Troubleshooting](https://www.flightcontrol.dev/docs/troubleshooting?ref=backstage) diff --git a/docs/features/search/how-to-guides.md b/docs/features/search/how-to-guides.md index 7de37cb624..382221d781 100644 --- a/docs/features/search/how-to-guides.md +++ b/docs/features/search/how-to-guides.md @@ -51,7 +51,7 @@ The TechDocs plugin has supported integrations to Search, meaning that it provides a default collator factory ready to be used. The purpose of this guide is to walk you through how to register the -[DefaultTechDocsCollatorFactory](https://github.com/backstage/backstage/blob/de294ce5c410c9eb56da6870a1fab795268f60e3/plugins/techdocs-backend/src/search/DefaultTechDocsCollatorFactory.ts) +[DefaultTechDocsCollatorFactory](https://github.com/backstage/backstage/blob/1adc2c7/plugins/search-backend-module-techdocs/src/collators/DefaultTechDocsCollatorFactory.ts) in your App, so that you can get TechDocs documents indexed. If you have been through the @@ -61,10 +61,10 @@ so, you can go ahead and follow this guide - if not, start by going through the getting started guide. 1. Import the `DefaultTechDocsCollatorFactory` from - `@backstage/plugin-techdocs-backend`. + `@backstage/plugin-search-backend-module-techdocs`. ```typescript - import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-techdocs-backend'; + import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-search-backend-module-techdocs'; ``` 2. If there isn't an existing schedule you'd like to run the collator on, be diff --git a/docs/features/software-catalog/creating-the-catalog-graph.md b/docs/features/software-catalog/creating-the-catalog-graph.md index 8b0f21a52c..4dc5b461b2 100644 --- a/docs/features/software-catalog/creating-the-catalog-graph.md +++ b/docs/features/software-catalog/creating-the-catalog-graph.md @@ -64,7 +64,7 @@ The recommended approach would be to represent information in catalog-info files **Naming strategies:** -- Ldap: Internal ldap usernames as entity names. e.g., owner: user:myuser or user: my-team-name. +- Ldap: Internal ldap usernames as entity names. e.g., owner: user:my-user or user: my-team-name. **Ownership strategies:** diff --git a/docs/features/software-catalog/descriptor-format.md b/docs/features/software-catalog/descriptor-format.md index 0be2bf0292..924c59a6fa 100644 --- a/docs/features/software-catalog/descriptor-format.md +++ b/docs/features/software-catalog/descriptor-format.md @@ -978,9 +978,9 @@ way. The entries of this array are [entity references](https://backstage.io/docs/features/software-catalog/references). -| [`kind`](#apiversion-and-kind-required) | Default [`namespace`](#namespace-optional) | Generated [relation](well-known-relations.md) type | -| --------------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------- | -| [`Group`](#kind-group) (default) | Same as this entity, typically `default` | [`hasMember`, and reverse `memberOf`](well-known-relations.md#memberof-and-hasmember) | +| [`kind`](#apiversion-and-kind-required) | Default [`namespace`](#namespace-optional) | Generated [relation](well-known-relations.md) type | +| --------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------- | +| [`Group`](#kind-group) (default) | Same as this entity, typically `default` | [`parentOf`, and reverse `childOf`](well-known-relations.md#parentof-and-childof) | ### `spec.members` [optional] diff --git a/docs/features/software-templates/writing-custom-actions.md b/docs/features/software-templates/writing-custom-actions.md index c2f14d0ca0..929ba150d2 100644 --- a/docs/features/software-templates/writing-custom-actions.md +++ b/docs/features/software-templates/writing-custom-actions.md @@ -207,5 +207,9 @@ scaffolder backend: | Azure Pipeline Actions | [scaffolder-backend-module-azure-pipelines](https://www.npmjs.com/package/@parfuemerie-douglas/scaffolder-backend-module-azure-pipelines) | [Parfümerie Douglas](https://github.com/Parfuemerie-Douglas) | | Azure Repository Actions | [scaffolder-backend-module-azure-repositories](https://www.npmjs.com/package/@parfuemerie-douglas/scaffolder-backend-module-azure-repositories) | [Parfümerie Douglas](https://github.com/Parfuemerie-Douglas) | | Snyk Import Project | [plugin-scaffolder-backend-module-snyk](https://www.npmjs.com/package/@ma11hewthomas/plugin-scaffolder-backend-module-snyk) | [Matthew Thomas](https://github.com/Ma11hewThomas) | +| JSON Merge Actions | [plugin-scaffolder-json-merge-actions](https://www.npmjs.com/package/@mdude2314/backstage-plugin-scaffolder-json-merge-actions) | [Drew Hill](https://github.com/arhill05) | +| NPM Actions | [plugin-scaffolder-npm-actions](https://www.npmjs.com/package/@mdude2314/backstage-plugin-scaffolder-npm-actions) | [Drew Hill](https://github.com/arhill05) | +| Slack Actions | [plugin-scaffolder-backend-module-slack](https://www.npmjs.com/package/@mdude2314/backstage-plugin-scaffolder-backend-module-slack) | [Drew Hill](https://github.com/arhill05) | +| Microsoft Teams Actions | [plugin-scaffolder-backend-module-ms-teams](https://www.npmjs.com/package/@grvpandey11/backstage-plugin-scaffolder-backend-module-ms-teams) | [Gaurav Pandey](https://github.com/grvpandey11) | Have fun! 🚀 diff --git a/docs/features/software-templates/writing-custom-field-extensions.md b/docs/features/software-templates/writing-custom-field-extensions.md index 20575a0b4a..f22cecd22c 100644 --- a/docs/features/software-templates/writing-custom-field-extensions.md +++ b/docs/features/software-templates/writing-custom-field-extensions.md @@ -89,10 +89,8 @@ export const validateKebabCaseValidation = ( then please use `scaffolderPlugin.provide` from there instead and export it part of your `plugin.ts` rather than re-using the `scaffolder.plugin`. */ -import { - scaffolderPlugin, - createScaffolderFieldExtension, -} from '@backstage/plugin-scaffolder'; +import { scaffolderPlugin } from '@backstage/plugin-scaffolder'; +import { createScaffolderFieldExtension } from '@backstage/plugin-scaffolder-react'; import { ValidateKebabCase, validateKebabCaseValidation, @@ -133,7 +131,7 @@ Should look something like this instead: ```tsx import { ValidateKebabCaseFieldExtension } from './scaffolder/ValidateKebabCase'; -import { ScaffolderFieldExtensions } from '@backstage/plugin-scaffolder'; +import { ScaffolderFieldExtensions } from '@backstage/plugin-scaffolder-react'; const routes = ( diff --git a/docs/features/software-templates/writing-custom-step-layouts.md b/docs/features/software-templates/writing-custom-step-layouts.md index 69d61b93dc..b965f60f6b 100644 --- a/docs/features/software-templates/writing-custom-step-layouts.md +++ b/docs/features/software-templates/writing-custom-step-layouts.md @@ -4,7 +4,7 @@ title: Writing custom step layouts description: How to override the default step form layout --- -Every form in each step rendered in the frontend uses the default form layout from [react-json-schema-form](https://react-jsonschema-form.readthedocs.io/). It is possible to override this behaviour by supplying a `ui:ObjectFieldTemplate` property for a particular step: +Every form in each step rendered in the frontend uses the default form layout from [react-jsonschema-form](https://rjsf-team.github.io/react-jsonschema-form/docs/). It is possible to override this behaviour by supplying a `ui:ObjectFieldTemplate` property for a particular step: ```yaml parameters: @@ -12,7 +12,7 @@ parameters: ui:ObjectFieldTemplate: TwoColumn ``` -This is the same [field](https://react-jsonschema-form.readthedocs.io/en/latest/advanced-customization/custom-templates/#objectfieldtemplate) used by [react-json-schema-form](https://react-jsonschema-form.readthedocs.io/) but we need to add a couple of steps to ensure that the string value of `TwoColumn` above is resolved to a react component. +This is the same [field](https://rjsf-team.github.io/react-jsonschema-form/docs/advanced-customization/custom-templates#objectfieldtemplate) used by [react-jsonschema-form](https://rjsf-team.github.io/react-jsonschema-form/docs/) but we need to add a couple of steps to ensure that the string value of `TwoColumn` above is resolved to a react component. ## Registering a React component as a custom step layout diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index 6e7b66fcc9..135d508513 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -499,6 +499,7 @@ template. These follow the same standard format: - id: fetch-base # A unique id for the step name: Fetch Base # A title displayed in the frontend if: ${{ parameters.name }} # Optional condition, skip the step if not truthy + each: ${{ parameters.iterable }} # Optional iterable, run the same step multiple times action: fetch:template # An action to call input: # Input that is passed as arguments to the action handler url: ./template @@ -510,6 +511,27 @@ By default we ship some [built in actions](./builtin-actions.md) that you can take a look at, or you can [create your own custom actions](./writing-custom-actions.md). +When `each` is provided, the current iteration value is available in the `${{ each }}` input. + +Examples: + +```yaml +each: ['apples', 'oranges'] +input: + values: + fruit: ${{ each.value }} +``` + +```yaml +each: [{ name: 'apple', count: 3 }, { name: 'orange', count: 1 }] +input: + values: + fruit: ${{ each.value.name }} + count: ${{ each.value.count }} +``` + +When `each` is used, the outputs of a repeated step are returned as an array of outputs from each iteration. + ## Outputs Each individual step can output some variables that can be used in the diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md index ab554db3bd..b78a1a55af 100644 --- a/docs/features/techdocs/how-to-guides.md +++ b/docs/features/techdocs/how-to-guides.md @@ -188,15 +188,12 @@ import { } from '@backstage/plugin-techdocs'; import { Entity } from '@backstage/catalog-model'; -import { - EntityListDocsGrid, - DocsGroupConfig, -} from '@backstage/plugin-techdocs'; +import { EntityListDocsGrid } from '@backstage/plugin-techdocs'; export type CustomTechDocsHomeProps = { groups?: Array<{ title: React.ReactNode; - filterPredicate: (entity: Entity) => boolean; + filterPredicate: ((entity: Entity) => boolean) | string; }>; }; diff --git a/docs/overview/glossary.md b/docs/overview/glossary.md index 97a2823365..ab7d224f4d 100644 --- a/docs/overview/glossary.md +++ b/docs/overview/glossary.md @@ -2,25 +2,25 @@ id: glossary title: Backstage Glossary # prettier-ignore -description: List of all the terms, abbreviations, and phrases used in Backstage, together with their explanations. +description: List of terms, abbreviations, and phrases used in Backstage, together with their explanations. --- -The Backstage Glossary lists all the terms, abbreviations, and phrases used in +The Backstage Glossary lists terms, abbreviations, and phrases used in Backstage, together with their explanations. We encourage you to use the terminology below for clarity and consistency when discussing Backstage. -### Authentication Glossary - -This [page](../auth/glossary.md) directs to the terms and phrases related to -authentication and identity section of Backstage. +See also [Authentication Glossary](../auth/glossary.md), a separate glossary of terms and phrases +specifically related to the authentication and identity section of Backstage. ### Backstage User Profiles There are three main user profiles for Backstage: the integrator, the -contributor, and the software engineer. +contributor, and the end user (typically a software engineer). -| Term | Explanation | -| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Integrator | The **integrator** hosts the Backstage app and configures which plugins are available to use in the app. | -| Contributor | The **contributor** adds functionality to the app by writing plugins. | -| Software Engineer | The **software engineer** uses the app's functionality and interacts with its plugins. In practice, this profile covers the various roles that help deliver software, from the Software Engineer themselves, to Designers, Data Scientists, Product Owners, Engineering Managers, etc. | +| Term | Explanation | +| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Integrator | The **integrator** hosts the Backstage app and configures which plugins are available to use in the app. | +| Contributor | The **contributor** adds functionality to the app by writing plugins. | +| End user | The **end user** uses the app's functionality and interacts with its plugins. This profile covers the various roles that help deliver software. The typical end user is a **software engineer**, but users might also consider themselves _designers_, _data scientists_, _product owners_, _engineering managers_, _technical writers_, and so on. | +| Software engineer | The **software engineer** is an **end user** who uses the app's functionality and interacts with its plugins in the course of writing and documenting code. This user is more likely to embed documentation in the code files they produce, and create rough drafts of conceptual pages in collaboration with a **technical writer** or _technical editor_. | +| Technical writer | The **technical writer** is an **end user** who uses the app's functionality and interacts with its plugins in the course of writing and editing documentation. This user is more likely to produce and customize templates and produce conceptual pages to supplement documentation embedded in code files. | diff --git a/docs/plugins/proxying.md b/docs/plugins/proxying.md index 3e20e37cad..442721a355 100644 --- a/docs/plugins/proxying.md +++ b/docs/plugins/proxying.md @@ -36,7 +36,7 @@ Example: ```yaml # in app-config.yaml proxy: - simple-example: http://simple.example.com:8080 + /simple-example: http://simple.example.com:8080 '/larger-example/v1': target: http://larger.example.com:8080/svc.v1 headers: diff --git a/docs/releases/v1.16.0.md b/docs/releases/v1.16.0.md index 5435d15994..37a458cc32 100644 --- a/docs/releases/v1.16.0.md +++ b/docs/releases/v1.16.0.md @@ -84,4 +84,4 @@ Below you can find a list of links and references to help you learn about and st - [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.16.0-changelog.md) - Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) -Sign up for our [newsletter](https://mailchi.mp/spotify/backstage-community) if you want to be informed about what is happening in the world of Backstage. +Sign up for our [newsletter](https://info.backstage.spotify.com/newsletter_subscribe) if you want to be informed about what is happening in the world of Backstage. diff --git a/docs/releases/v1.17.0-changelog.md b/docs/releases/v1.17.0-changelog.md new file mode 100644 index 0000000000..a67226ca9e --- /dev/null +++ b/docs/releases/v1.17.0-changelog.md @@ -0,0 +1,2999 @@ +# Release v1.17.0 + +## @backstage/backend-app-api@0.5.0 + +### Minor Changes + +- b9c57a4f857e: **BREAKING**: Renamed `configServiceFactory` to `rootConfigServiceFactory`. +- a6d7983f349c: **BREAKING**: Removed the `services` option from `createBackend`. Service factories are now `BackendFeature`s and should be installed with `backend.add(...)` instead. The following should be migrated: + + ```ts + const backend = createBackend({ services: [myCustomServiceFactory] }); + ``` + + To instead pass the service factory via `backend.add(...)`: + + ```ts + const backend = createBackend(); + backend.add(customRootLoggerServiceFactory); + ``` + +### Patch Changes + +- e65c4896f755: Do not throw in backend.stop, if start failed +- c7aa4ff1793c: Allow modules to register extension points. +- 57a10c6c69cc: Add validation to make sure that extension points do not cross plugin boundaries. +- cc9256a33bcc: Added new experimental `featureDiscoveryServiceFactory`, available as an `/alpha` export. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/config-loader@1.4.0 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/cli-node@0.1.3 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/backend-tasks@0.5.5 + - @backstage/plugin-permission-node@0.7.11 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/backend-defaults@0.2.0 + +### Minor Changes + +- d008aefef808: **BREAKING**: Removing shared environments concept from the new experimental backend system. +- a6d7983f349c: **BREAKING**: Removed the `services` option from `createBackend`. Service factories are now `BackendFeature`s and should be installed with `backend.add(...)` instead. The following should be migrated: + + ```ts + const backend = createBackend({ services: [myCustomServiceFactory] }); + ``` + + To instead pass the service factory via `backend.add(...)`: + + ```ts + const backend = createBackend(); + backend.add(customRootLoggerServiceFactory); + ``` + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-app-api@0.5.0 + - @backstage/backend-plugin-api@0.6.0 + +## @backstage/backend-plugin-api@0.6.0 + +### Minor Changes + +- c49785f00cab: **BREAKING**: It is no longer possible to declare options as being required with `createServiceFactory`. +- 629cbd194a87: **BREAKING**: Renamed `coreServices.config` to `coreServices.rootConfig`. +- 51987dbdaf87: **BREAKING**: Removed the ability to define options for plugins and modules. Existing options should be migrated to instead use either static configuration or extension points. +- d008aefef808: **BREAKING**: Removing shared environments concept from the new experimental backend system. + +### Patch Changes + +- c7aa4ff1793c: Allow modules to register extension points. + +- cc9256a33bcc: Added new experimental `featureDiscoveryServiceRef`, available as an `/alpha` export. + +- a6d7983f349c: **BREAKING**: Removed the `services` option from `createBackend`. Service factories are now `BackendFeature`s and should be installed with `backend.add(...)` instead. The following should be migrated: + + ```ts + const backend = createBackend({ services: [myCustomServiceFactory] }); + ``` + + To instead pass the service factory via `backend.add(...)`: + + ```ts + const backend = createBackend(); + backend.add(customRootLoggerServiceFactory); + ``` + +- Updated dependencies + - @backstage/plugin-auth-node@0.2.17 + - @backstage/backend-tasks@0.5.5 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/backend-test-utils@0.2.0 + +### Minor Changes + +- b9c57a4f857e: **BREAKING**: Renamed `mockServices.config` to `mockServices.rootConfig`. +- a6d7983f349c: **BREAKING**: Removed the `services` option from `createBackend`. Service factories are now `BackendFeature`s and should be installed with `backend.add(...)` instead. The following should be migrated: + + ```ts + const backend = createBackend({ services: [myCustomServiceFactory] }); + ``` + + To instead pass the service factory via `backend.add(...)`: + + ```ts + const backend = createBackend(); + backend.add(customRootLoggerServiceFactory); + ``` + +### Patch Changes + +- ae9304818136: Add needed constants and constructs to support PostgreSQL version 14 as test database +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-app-api@0.5.0 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + +## @backstage/config-loader@1.4.0 + +### Minor Changes + +- 2f1859585998: Loading invalid TypeScript configuration schemas will now throw an error rather than silently being ignored. + + In particular this includes defining any additional types other than `Config` in the schema file, or use of unsupported types such as `Record` or `Partial`. + +- cd514545d1d0: Adds a new `deepVisibility` schema keyword that sets child visibility recursively to the defined value, respecting preexisting values or child `deepVisibility`. + + Example usage: + + ```ts + export interface Config { + /** + * Enforces a default of `secret` instead of `backend` for this object. + * @deepVisibility secret + */ + mySecretProperty: { + type: 'object'; + properties: { + secretValue: { + type: 'string'; + }; + + verySecretProperty: { + type: 'string'; + }; + }; + }; + } + ``` + + Example of a schema that would not be allowed: + + ```ts + export interface Config { + /** + * Set the top level property to secret, enforcing a default of `secret` instead of `backend` for this object. + * @deepVisibility secret + */ + mySecretProperty: { + type: 'object'; + properties: { + frontendUrl: { + /** + * We can NOT override the visibility to reveal a property to the front end. + * @visibility frontend + */ + type: 'string'; + }; + + verySecretProperty: { + type: 'string'; + }; + }; + }; + } + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/integration@1.6.0 + +### Minor Changes + +- 443afcf7f567: Added `buildGerritGitilesArchiveUrl()` to construct a Gitiles URL to download an archive. + Gitiles URL that uses an authenticated prefix (`/a/`) can now be parsed by the integration. + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-app-node@0.1.0 + +### Minor Changes + +- 9fbe95ef6503: Added the `app` plugin node library, initially providing an extension point that can be used to configure a static fallback handler. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0 + +## @backstage/plugin-catalog-backend@1.12.0 + +### Minor Changes + +- b8cccd8ee858: Support configuring applicable kinds for `AnnotateScmSlugEntityProcessor` +- f32252cdf631: Added OpenTelemetry spans for catalog processing +- ebeb77586975: Now performs request validation based on OpenAPI schema through `@backstage/backend-openapi-utils`. Error responses for invalid input, like `"a"` instead of a number, may have changed. + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- b8d6b22acd57: Internal refactor for load test +- Updated dependencies + - @backstage/plugin-search-backend-module-catalog@0.1.4 + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/backend-openapi-utils@0.0.3 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/plugin-events-node@0.2.9 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - @backstage/plugin-scaffolder-common@1.4.0 + - @backstage/plugin-permission-node@0.7.11 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-catalog-backend-module-gcp@0.1.0 + +### Minor Changes + +- 290eff6692aa: Added GCP catalog plugin with GKE provider + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/backend-tasks@0.5.5 + - @backstage/config@1.0.8 + - @backstage/plugin-kubernetes-common@0.6.5 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.2.0 + +### Minor Changes + +- 5156a94c2e2a: **BREAKING**: Fixing typo in exported module. You will have to rename the import to the correct spelling. `UnprocessedEntites` -> `UnprocessedEntities` + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/catalog-model@1.4.1 + +## @backstage/plugin-kubernetes@0.10.0 + +### Minor Changes + +- 4b6d41737aad: **BREAKING**: Fixed typos in exported module attributes. Many users may see no changes, but if you have customized the plugin output, you may have to rename the following: + + - Component attribute: `` to `` + - Interface attribute: `DetectedError.occuranceCount` to `DetectedError.occurrenceCount`. + +### Patch Changes + +- 562e34d2693f: Fix container memory limits +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-kubernetes-common@0.6.5 + +## @backstage/plugin-linguist-backend@0.4.0 + +### Minor Changes + +- d440f1dd0e72: Adds a processor to the linguist backend which can automatically add language tags to entities +- 0896d85d5ab5: **BREAKING**: Removed the alpha export plugin options from exported `linguistPlugin()` (used by the new backend system) in favour of static config. + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- ca5e591cb86a: Fixed bug in LinguistBackendClient.ts file where if the linguistJsOptions is specified and sent over to the linguist-js package it would get changed (another attribute would be added) causing future entities of the batch to fail with an error +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-linguist-common@0.1.1 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-proxy-backend@0.3.0 + +### Minor Changes + +- 7daf65bfcfa1: Defining proxy endpoints directly under the root `proxy` configuration key is deprecated. Endpoints should now be declared under `proxy.endpoints` instead. The `skipInvalidProxies` and `reviveConsumedRequestBodies` can now also be configured through static configuration. + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/config@1.0.8 + +## @backstage/plugin-scaffolder-backend@1.16.0 + +### Minor Changes + +- e514aac3eac0: Introduce `each` property on action steps, allowing them to be ran repeatedly. + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` + +- 349611126ae2: Removed the options from the alpha `scaffolderPlugin` export. To extend the scaffolder plugin you instead now use the available extension points, `scaffolderActionsExtensionPoint`, `scaffolderTaskBrokerExtensionPoint`, and `scaffolderTemplatingExtensionPoint`. + +- 33c76caef72a: Added examples for the `fs:delete` and `fs:rename` actions + +- e07a4914f621: Deprecated the following type exports, which have been moved to `@backstage/plugin-scaffolder-node` instead: + + - `TemplateFilter` + - `TemplateGlobal` + - `TaskStatus` + - `TaskCompletionState` + - `SerializedTask` + - `TaskEventType` + - `SerializedTaskEvent` + - `TaskBrokerDispatchResult` + - `TaskBrokerDispatchOptions` + - `TaskContext` + - `TaskBroker` + +- 0b1d775be05b: Adds examples to a few scaffolder actions. + +- 88bc6e27a213: The `concurrentTasksLimit` option can now be configured via static configuration as well. Setting it to 0 will now also disable the task worker. + +- 0f873325068d: Add examples for `github:repo:create` and `github:repo:push` scaffolder actions. + +- 5c28ebc79fd6: Updated dependency `esbuild` to `^0.19.0`. + +- d3b31a791eb1: Deprecated `executeShellCommand`, `RunCommandOptions`, and `fetchContents` from `@backstage/plugin-scaffolder-backend`, since they are useful for Scaffolder modules (who should not be importing from the plugin package itself). You should now import these from `@backstage/plugin-scaffolder-backend-node` instead. `RunCommandOptions` was renamed in the Node package as `ExecuteShellCommandOptions`, for consistency. + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-catalog-backend@1.12.0 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-scaffolder-node@0.2.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - @backstage/plugin-scaffolder-common@1.4.0 + - @backstage/plugin-permission-node@0.7.11 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-scaffolder-common@1.4.0 + +### Minor Changes + +- e514aac3eac0: Introduce `each` property on action steps, allowing them to be ran repeatedly. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/types@1.1.0 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-scaffolder-node@0.2.0 + +### Minor Changes + +- e514aac3eac0: Introduce `each` property on action steps, allowing them to be ran repeatedly. + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- e07a4914f621: Added several new types that were moved from `@backstage/plugin-scaffolder-backend`. +- 349611126ae2: Added two new alpha extension points, `scaffolderTaskBrokerExtensionPoint` and `scaffolderTemplatingExtensionPoint`. +- 0b1d775be05b: Export `TemplateExample` from the `createTemplateAction` type. +- d3b31a791eb1: Deprecated `executeShellCommand`, `RunCommandOptions`, and `fetchContents` from `@backstage/plugin-scaffolder-backend`, since they are useful for Scaffolder modules (who should not be importing from the plugin package itself). You should now import these from `@backstage/plugin-scaffolder-backend-node` instead. `RunCommandOptions` was renamed in the Node package as `ExecuteShellCommandOptions`, for consistency. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/integration@1.6.0 + - @backstage/plugin-scaffolder-common@1.4.0 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-search-backend@1.4.0 + +### Minor Changes + +- ebeb77586975: Now performs request validation based on OpenAPI schema through `@backstage/backend-openapi-utils`. Error responses for invalid input, like `"a"` instead of a number, may have changed. + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- 951ab6c9db58: Add missing `configSchema` to package.json +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/backend-openapi-utils@0.0.3 + - @backstage/plugin-search-backend-node@1.2.4 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/plugin-permission-node@0.7.11 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-todo-backend@0.2.0 + +### Minor Changes + +- ebeb77586975: Now performs request validation based on OpenAPI schema through `@backstage/backend-openapi-utils`. Error responses for invalid input, like `"a"` instead of a number, may have changed. + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- ad3fb5401729: Fixed a bug where filter queries from the frontend would always fail validation. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/backend-openapi-utils@0.0.3 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/integration@1.6.0 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/app-defaults@1.4.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.9.1 + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-permission-react@0.4.14 + +## @backstage/backend-common@0.19.2 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` + +- 443afcf7f567: To improve performance, `GerritUrlReader.readTree()` now uses Gitiles to fetch an archive instead of cloning the repository. + If `gitilesBaseUrl` is not configured, `readTree` still uses Git to clone the repository. + + Added `stripFirstDirectory` option to `ReadTreeResponseFactory.fromTarArchive()`, allowing to disable stripping first directory + for `tar` archives. + +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. + +- Updated dependencies + - @backstage/backend-app-api@0.5.0 + - @backstage/config-loader@1.4.0 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/integration@1.6.0 + - @backstage/integration-aws-node@0.1.5 + - @backstage/backend-dev-utils@0.1.1 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/backend-openapi-utils@0.0.3 + +### Patch Changes + +- ebeb77586975: Add a new `createRouter` method for generating an `express` router that validates against your spec. Also fixes a bug with the query parameters type resolution. +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/errors@1.2.1 + +## @backstage/backend-tasks@0.5.5 + +### Patch Changes + +- dfd1b6b2fc33: Make `readTaskScheduleDefinitionFromConfig` properly handle bad inputs +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/cli@0.22.10 + +### Patch Changes + +- 3f67cefb4780: Reload the frontend when app config changes +- cebbf8a27f3c: Enable to print the config schema not merged with the `--no-merge` flag +- 5c28ebc79fd6: Updated dependency `esbuild` to `^0.19.0`. +- 971bdd6a4732: Bumped internal `nodemon` dependency. +- Updated dependencies + - @backstage/config-loader@1.4.0 + - @backstage/cli-node@0.1.3 + - @backstage/integration@1.6.0 + - @backstage/catalog-model@1.4.1 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/eslint-plugin@0.1.3 + - @backstage/release-manifests@0.0.9 + - @backstage/types@1.1.0 + +## @backstage/cli-node@0.1.3 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/core-app-api@1.9.1 + +### Patch Changes + +- 9ae4e7e63836: Fixed a bug that could cause `navigate` analytics events to be misattributed to the plugin mounted on the root route (e.g. the `home` plugin at `/`) when the route that was navigated to wasn't associated with a routable extension. +- Updated dependencies + - @backstage/core-plugin-api@1.5.3 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + - @backstage/version-bridge@1.0.4 + +## @backstage/core-components@0.13.4 + +### Patch Changes + +- 3d86be999fdf: Prefer simple `theme.spacing` without string interpolation +- Updated dependencies + - @backstage/core-plugin-api@1.5.3 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/version-bridge@1.0.4 + +## @backstage/create-app@0.5.4 + +### Patch Changes + +- b441642fbe0d: Bumped create-app version. +- 572abc7edf55: Bumped create-app version. +- 74f77f151a96: Bumped create-app version. +- 5cc0ac5ef3d1: Bump to a newer version of the `concurrently` library +- 46c9a798e41d: Updated the `app-config.yaml` template to use `proxy.endpoints`. +- 971bdd6a4732: Bumped internal `nodemon` dependency. +- Updated dependencies + - @backstage/cli-common@0.1.12 + +## @backstage/dev-utils@1.0.18 + +### Patch Changes + +- 254ad469f053: Removed deprecated calls to `app.getProvider()` and `app.getRouter()` in `DevAppBuilder` +- Updated dependencies + - @backstage/core-app-api@1.9.1 + - @backstage/integration-react@1.1.16 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/app-defaults@1.4.2 + - @backstage/core-plugin-api@1.5.3 + - @backstage/test-utils@1.4.2 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## @backstage/integration-react@1.1.16 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/integration@1.6.0 + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/config@1.0.8 + - @backstage/theme@0.4.1 + +## @backstage/repo-tools@0.3.3 + +### Patch Changes + +- 75702e85862a: Bumped `@microsoft/api-extractor` dependency to `^7.36.4`, and `@microsoft/api-documenter` to `^7.22.33`. +- 1f3337ebc707: Introducing a new, experimental command `backstage-repo-tools generate-catalog-info`, which can be used to create standardized `catalog-info.yaml` files for each Backstage package in a Backstage monorepo. It can also be used to automatically fix existing `catalog-info.yaml` files with the correct metadata (including `metadata.name`, `metadata.title`, and `metadata.description` introspected from the package's `package.json`, as well as `spec.owner` introspected from `CODEOWNERS`), e.g. in a post-commit hook. +- ebeb77586975: Update `schema openapi generate` command to now create a default router that can be imported and used directly. +- Updated dependencies + - @backstage/cli-node@0.1.3 + - @backstage/catalog-model@1.4.1 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.2.1 + +## @techdocs/cli@1.4.5 + +### Patch Changes + +- 971bdd6a4732: Bumped internal `nodemon` dependency. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-techdocs-node@1.7.4 + - @backstage/catalog-model@1.4.1 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + +## @backstage/test-utils@1.4.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.9.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/config@1.0.8 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-permission-react@0.4.14 + +## @backstage/plugin-adr@0.6.4 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/integration-react@1.1.16 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/plugin-search-react@1.6.4 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-adr-common@0.2.12 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-adr-backend@0.3.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/integration@1.6.0 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-adr-common@0.2.12 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-adr-common@0.2.12 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.6.0 + - @backstage/catalog-model@1.4.1 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-airbrake@0.3.21 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/dev-utils@1.0.18 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/test-utils@1.4.2 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-airbrake-backend@0.2.21 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/config@1.0.8 + +## @backstage/plugin-allure@0.1.37 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-analytics-module-ga@0.1.32 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/config@1.0.8 + - @backstage/theme@0.4.1 + +## @backstage/plugin-analytics-module-ga4@0.1.3 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/config@1.0.8 + - @backstage/theme@0.4.1 + +## @backstage/plugin-analytics-module-newrelic-browser@0.0.1 + +### Patch Changes + +- ec7357258853: Introduced the New Relic Browser analytics module. Check out the plugins [README.md](https://github.com/backstage/backstage/tree/master/plugins/analytics-module-newrelic-browser) for more details! +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/config@1.0.8 + +## @backstage/plugin-apache-airflow@0.2.14 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + +## @backstage/plugin-api-docs@0.9.7 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog@1.12.1 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-apollo-explorer@0.1.14 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + +## @backstage/plugin-app-backend@0.3.48 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- d564ad142b17: Migrated the alpha `appBackend` export to use static configuration and extension points rather than accepting options. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/config-loader@1.4.0 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-app-node@0.1.0 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + +## @backstage/plugin-auth-backend@0.18.6 + +### Patch Changes + +- 16452cd007ae: Updated `frameHandler` to return `undefined` when using the redirect flow instead of returning `postMessageReponse` which was causing errors +- 9dad4b0e61bd: Updated config schema to match what was being used in code +- bb70a9c3886a: Add frontend visibility to provider objects in `auth` config. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-auth-node@0.2.17 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-azure-devops@0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-azure-devops-common@0.3.0 + +## @backstage/plugin-azure-devops-backend@0.3.27 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/config@1.0.8 + - @backstage/plugin-azure-devops-common@0.3.0 + +## @backstage/plugin-azure-sites@0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-azure-sites-common@0.1.0 + +## @backstage/plugin-azure-sites-backend@0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/config@1.0.8 + - @backstage/plugin-azure-sites-common@0.1.0 + +## @backstage/plugin-badges@0.2.45 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-badges-backend@0.2.3 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-bazaar@0.2.12 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/cli@0.22.10 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog@1.12.1 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-bazaar-backend@0.2.11 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-bitbucket-cloud-common@0.2.9 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/integration@1.6.0 + +## @backstage/plugin-bitrise@0.1.48 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-catalog@1.12.1 + +### Patch Changes + +- 3d86be999fdf: Prefer simple `theme.spacing` without string interpolation +- 136cea792bd4: Fixed an issue causing `EntitySwitch` to unmount its children once entity refresh was invoked +- Updated dependencies + - @backstage/integration-react@1.1.16 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/plugin-scaffolder-common@1.4.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/plugin-search-react@1.6.4 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-catalog-backend-module-aws@0.2.3 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- b4222908b0c3: Added option to configure AWS `accountId` in `AwsS3EntityProvider` +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - @backstage/integration-aws-node@0.1.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-kubernetes-common@0.6.5 + +## @backstage/plugin-catalog-backend-module-azure@0.1.19 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.9 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/integration@1.6.0 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.15 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-bitbucket-cloud-common@0.2.9 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/plugin-events-node@0.2.9 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/plugin-catalog-common@1.0.15 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.13 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.16 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-catalog-backend-module-github@0.3.3 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- 81c231c9c9ee: Fixed a bug where the visibility filter was case sensitive and casting was inconsistent. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-catalog-backend@1.12.0 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/plugin-events-node@0.2.9 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + +## @backstage/plugin-catalog-backend-module-gitlab@0.2.4 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- e6c721439f37: Added option to skip forked repos in GitlabDiscoveryEntityProvider +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- 2fe1f5973ff7: Filter Gitlab archived projects through APIs +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.4.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- e2b6396a1274: Export new alpha `incrementalIngestionProvidersExtensionPoint` for registering incremental providers, rather than the providers being passed as options to the backend module. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-catalog-backend@1.12.0 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/plugin-events-node@0.2.9 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.15 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + +## @backstage/plugin-catalog-backend-module-msgraph@0.5.7 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- fb93323201bf: The alpha `catalogModuleMicrosoftGraphOrgEntityProvider` export no longer accepts options. Transformers are now instead configured via the `microsoftGraphOrgEntityProviderTransformExtensionPoint`. +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/plugin-catalog-common@1.0.15 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.14 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-catalog-backend@1.12.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/integration@1.6.0 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.1.5 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-catalog-graph@0.2.33 + +### Patch Changes + +- 64ee2c0c7ca5: Propagate entity spec to EntityNode so that spec info such as type can be used for graph node customization +- 62dc7a2b1ad1: Added maximum depth parameter to the catalogGraphParams in CatalogGraphCard. +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-catalog-import@0.9.11 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.16 + - @backstage/integration@1.6.0 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-catalog-common@1.0.15 + +## @backstage/plugin-catalog-node@1.4.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + +## @backstage/plugin-catalog-react@1.8.1 + +### Patch Changes + +- aa3feedce10a: Allow specifying screen size when catalog filters are hidden in drawer +- Updated dependencies + - @backstage/integration@1.6.0 + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + - @backstage/version-bridge@1.0.4 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-permission-react@0.4.14 + +## @backstage/plugin-catalog-unprocessed-entities@0.1.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-cicd-statistics@0.1.23 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.17 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/plugin-cicd-statistics@0.1.23 + +## @backstage/plugin-circleci@0.3.21 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-cloudbuild@0.3.21 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-code-climate@0.1.21 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-code-coverage@0.2.14 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-code-coverage-backend@0.2.14 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/integration@1.6.0 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-codescene@0.1.16 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-config-schema@0.1.44 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-cost-insights@0.12.10 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/theme@0.4.1 + - @backstage/plugin-cost-insights-common@0.1.1 + +## @backstage/plugin-devtools@0.1.3 + +### Patch Changes + +- 48b6a04ad045: Fix readme typo +- Updated dependencies + - @backstage/plugin-devtools-common@0.1.3 + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + - @backstage/plugin-permission-react@0.4.14 + +## @backstage/plugin-devtools-backend@0.1.3 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` + +- 12a8c94eda8d: Add package repository and homepage metadata + +- 2b4f77a4e900: Add DevTools configuration to enable dependency listing to be filtered with custom prefixes. For instance, in your `app-config.yaml`: + + ```yaml + devTools: + info: + packagePrefixes: + - @backstage/ + - @roadiehq/backstage- + - @spotify/backstage- + ``` + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/config-loader@1.4.0 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-devtools-common@0.1.3 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/plugin-permission-node@0.7.11 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-devtools-common@0.1.3 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/types@1.1.0 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-dynatrace@7.0.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-entity-feedback@0.2.4 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-entity-feedback-common@0.1.2 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-entity-feedback-backend@0.1.6 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-entity-feedback-common@0.1.2 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + +## @backstage/plugin-entity-feedback-common@0.1.2 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata + +## @backstage/plugin-entity-validation@0.1.6 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-common@1.0.15 + +## @backstage/plugin-events-backend@0.2.9 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-events-node@0.2.9 + - @backstage/config@1.0.8 + +## @backstage/plugin-events-backend-module-aws-sqs@0.2.3 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-events-node@0.2.9 + - @backstage/backend-tasks@0.5.5 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + +## @backstage/plugin-events-backend-module-azure@0.1.10 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-events-node@0.2.9 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.1.10 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-events-node@0.2.9 + +## @backstage/plugin-events-backend-module-gerrit@0.1.10 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-events-node@0.2.9 + +## @backstage/plugin-events-backend-module-github@0.1.10 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-events-node@0.2.9 + - @backstage/config@1.0.8 + +## @backstage/plugin-events-backend-module-gitlab@0.1.10 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-events-node@0.2.9 + - @backstage/config@1.0.8 + +## @backstage/plugin-events-backend-test-utils@0.1.10 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-events-node@0.2.9 + +## @backstage/plugin-events-node@0.2.9 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0 + +## @backstage/plugin-explore@0.4.7 + +### Patch Changes + +- 41a26248c91c: Support `material-ui` overrides in plugin-explore components +- 83467b0534ee: Don't put "?" in URL if no query parameters. +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/plugin-search-react@1.6.4 + - @backstage/plugin-explore-react@0.0.30 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-explore-backend@0.0.10 + +### Patch Changes + +- eda2a699f40d: Moved the config example from the "Tools as Code" section to the "Tools as Config" section of the README +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-search-backend-module-explore@0.1.4 + - @backstage/backend-common@0.19.2 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-firehydrant@0.2.5 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-fossa@0.2.53 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-gcalendar@0.3.17 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-gcp-projects@0.3.40 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + +## @backstage/plugin-git-release-manager@0.3.34 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/integration@1.6.0 + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + +## @backstage/plugin-github-actions@0.6.2 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.16 + - @backstage/integration@1.6.0 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-github-deployments@0.1.52 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/integration-react@1.1.16 + - @backstage/integration@1.6.0 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-github-issues@0.2.10 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/integration@1.6.0 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-github-pull-requests-board@0.1.15 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.6.0 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-gitops-profiles@0.3.39 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/config@1.0.8 + - @backstage/theme@0.4.1 + +## @backstage/plugin-gocd@0.1.27 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-graphiql@0.2.53 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + +## @backstage/plugin-graphql-backend@0.1.38 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/config@1.0.8 + - @backstage/plugin-catalog-graphql@0.3.22 + +## @backstage/plugin-graphql-voyager@0.1.6 + +### Patch Changes + +- bb1e1c2b26cc: Fix typo in install instructions. +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + +## @backstage/plugin-home@0.5.5 + +### Patch Changes + +- a559ff68de7e: Now, user can provide a language (optional) as input to receive a greeting in that specific language. Example: `` +- 6743d3917a52: Make sure the widget name is never empty in the `AddWidgetDialog`. If the title was set to "", the entry would contain an empty string. Use the name as a fallback +- Updated dependencies + - @backstage/plugin-home-react@0.1.2 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/theme@0.4.1 + +## @backstage/plugin-home-react@0.1.2 + +### Patch Changes + +- bf67dce73174: Make `title` optional when defining the `createCardExtension` +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + +## @backstage/plugin-ilert@0.2.10 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-jenkins@0.8.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-jenkins-common@0.1.18 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-jenkins-backend@0.2.3 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-jenkins-common@0.1.18 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/plugin-permission-node@0.7.11 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-jenkins-common@0.1.18 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-kafka@0.3.21 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/theme@0.4.1 + +## @backstage/plugin-kafka-backend@0.2.41 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-kubernetes-backend@0.11.3 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- bbf4e9c894b5: Fixed a bug where the proxy was not rewriting WebSocket request paths properly. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/plugin-permission-node@0.7.11 + - @backstage/integration-aws-node@0.1.5 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-kubernetes-common@0.6.5 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-lighthouse@0.4.6 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/theme@0.4.1 + - @backstage/plugin-lighthouse-common@0.1.2 + +## @backstage/plugin-lighthouse-backend@0.2.4 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + - @backstage/plugin-lighthouse-common@0.1.2 + +## @backstage/plugin-linguist@0.1.6 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-linguist-common@0.1.1 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-linguist-common@0.1.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- d440f1dd0e72: Exported new LanguageType type alias + +## @backstage/plugin-microsoft-calendar@0.1.6 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- eea2922e749a: README update - example of apiRef definition and fixed component name +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-newrelic@0.3.39 + +### Patch Changes + +- 2167b7eab09b: The newrelic plugin now supports pagination when retrieving results from newrelic. It will no longer truncate results. To see all applications, the link header will need to be allowed through the proxy (see the newrelic plugin readme). +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + +## @backstage/plugin-newrelic-dashboard@0.2.14 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + +## @backstage/plugin-nomad@0.1.2 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/theme@0.4.1 + +## @backstage/plugin-nomad-backend@0.1.2 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-octopus-deploy@0.2.3 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-org@0.6.11 + +### Patch Changes + +- 50331203e2a2: Fixed bug in MembersListCard component where the url for the members was static which was breaking the component when catalog route was changed +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-org-react@0.1.10 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-pagerduty@0.6.2 + +### Patch Changes + +- 5003fc966741: Add new `disableChangeEvents` prop to `EntityPagerDutyCard` to hide the Change Events tab and disable fetching of change events for the PagerDuty service. +- Updated dependencies + - @backstage/plugin-home-react@0.1.2 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-periskop@0.1.19 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-periskop-backend@0.1.19 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/config@1.0.8 + +## @backstage/plugin-permission-backend@0.5.23 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- 0d6ddc62d8da: Refactor backend plugin creation parameter from callback to object. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/plugin-permission-node@0.7.11 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-permission-node@0.7.11 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-playlist@0.1.13 + +### Patch Changes + +- d1e0588324d1: Displaying an alert popup each time the Playlist is created or deleted +- 12a8c94eda8d: Add package repository and homepage metadata +- 8a997547f02a: Adding alert popup whenever user delete the entities from playlist entity table +- Updated dependencies + - @backstage/plugin-playlist-common@0.1.9 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/plugin-search-react@1.6.4 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-permission-react@0.4.14 + +## @backstage/plugin-playlist-backend@0.3.4 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-playlist-common@0.1.9 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/plugin-permission-node@0.7.11 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-playlist-common@0.1.9 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-puppetdb@0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-rollbar@0.4.21 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-rollbar-backend@0.1.45 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/config@1.0.8 + +## @backstage/plugin-scaffolder@1.14.2 + +### Patch Changes + +- 8a0490fb669e: Fix the get entities query in the `MyGroupsPicker` to query the `kind=Group` entities. +- Updated dependencies + - @backstage/integration-react@1.1.16 + - @backstage/integration@1.6.0 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/plugin-scaffolder-common@1.4.0 + - @backstage/plugin-scaffolder-react@1.5.2 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-react@0.4.14 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.1 + +### Patch Changes + +- 0a9b3b14e904: Added example for the `confluence:transform:markdown` that will show in the installed actions list +- 12a8c94eda8d: Add package repository and homepage metadata +- 0d347efc8f18: Use `fetchContents` directly instead of a `fetchPlainAction` +- c186c631b429: Import helpers from the node package instead of the backend package +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-scaffolder-node@0.2.0 + - @backstage/integration@1.6.0 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.24 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- c186c631b429: Import helpers from the node package instead of the backend package +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-scaffolder-node@0.2.0 + - @backstage/integration@1.6.0 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.2.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.0 + - @backstage/integration@1.6.0 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.17 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- c186c631b429: Import helpers from the node package instead of the backend package +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-scaffolder-node@0.2.0 + - @backstage/integration@1.6.0 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.8 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.0 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.21 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.0 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + +## @backstage/plugin-scaffolder-react@1.5.2 + +### Patch Changes + +- ba9ee98a37bd: Fixed bug in Workflow component by passing a prop `templateName` down to Stepper component. +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/plugin-scaffolder-common@1.4.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + - @backstage/version-bridge@1.0.4 + +## @backstage/plugin-search@1.3.4 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/plugin-search-react@1.6.4 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + - @backstage/version-bridge@1.0.4 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-search-backend-module-catalog@0.1.4 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 29f77f923c71: Ensure that all services are dependency injected into the module instead of taken from options +- 12a8c94eda8d: Add package repository and homepage metadata +- ec1032129e47: Breaking change in the alpha export `searchModuleCatalogCollator`: Moved collator settings from module options into app-config. You are now expected to set up the catalog collator under the `search.collators.catalog` configuration key. There is also a new `catalogCollatorExtensionPoint` extension point for the module, wherein you can set custom transformers. +- d4f19a16bd52: Add User Entity email to the search index so that users can be found by their email. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-search-backend-node@1.2.4 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-search-backend-module-elasticsearch@1.3.3 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` + +- 12a8c94eda8d: Add package repository and homepage metadata + +- 631eb3816b48: Index templates can now be configured through configuration under the `search.elasticsearch.indexTemplates`. In addition, the `ElasticSearchSearchEngine.fromConfig` now also accepts a `LoggerService` as the `logger` option as well as a new `translator` option. + + The alpha `searchModuleElasticsearchEngine` export no longer accepts options and a new alpha `elasticsearchTranslatorExtensionPoint` export has been added which lets you customize the query translator. + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-search-backend-node@1.2.4 + - @backstage/integration-aws-node@0.1.5 + - @backstage/config@1.0.8 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-search-backend-module-explore@0.1.4 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 29f77f923c71: Ensure that all services are dependency injected into the module instead of taken from options +- 12a8c94eda8d: Add package repository and homepage metadata +- 6694e79ab396: Breaking change for the alpha export moved `schedule` from module options into app-config for the new backend system. You can now pass in a `TaskScheduleDefinitionConfig` through the `search.collators.explore.schedule` configuration key. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-search-backend-node@1.2.4 + - @backstage/backend-tasks@0.5.5 + - @backstage/config@1.0.8 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-search-backend-module-pg@0.5.9 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-search-backend-node@1.2.4 + - @backstage/config@1.0.8 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-search-backend-module-techdocs@0.1.4 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 29f77f923c71: Ensure that all services are dependency injected into the module instead of taken from options +- 12a8c94eda8d: Add package repository and homepage metadata +- 6694e79ab396: **BREAKING:** Moved `schedule` & `collators` settings from module options into app-config for the new backend system. You can now pass in a `TaskScheduleDefinitionConfig` through the `search.collators.techdocs.schedule` configuration key & configure the `TechDocsCollatorFactory` with the key `search.collators.techdocs`. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-search-backend-node@1.2.4 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/backend-tasks@0.5.5 + - @backstage/plugin-techdocs-node@1.7.4 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-search-backend-node@1.2.4 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- e3e9bc10298b: Fix Lunr search engine highlight by ignoring invalid metadata positions. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/backend-tasks@0.5.5 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-search-react@1.6.4 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + - @backstage/version-bridge@1.0.4 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-sentry@0.5.6 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-shortcuts@0.3.13 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- ee52a48b63d5: Limit the use of the duplicate shortcut name when adding a shortcut +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-sonarqube@0.7.2 + +### Patch Changes + +- b2ccddefbdc6: Remove sonarQube card disable class +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-sonarqube-react@0.1.7 + +## @backstage/plugin-sonarqube-backend@0.2.2 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- a24d9df8757c: Added optional `externalBaseUrl` config for setting a different frontend URL +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-splunk-on-call@0.4.10 + +### Patch Changes + +- 3d86be999fdf: Prefer simple `theme.spacing` without string interpolation +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-stack-overflow@0.1.19 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-home-react@0.1.2 + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/plugin-search-react@1.6.4 + - @backstage/config@1.0.8 + - @backstage/theme@0.4.1 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-stack-overflow-backend@0.2.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/config@1.0.8 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-stackstorm@0.1.5 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-tech-insights@0.3.13 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + - @backstage/plugin-tech-insights-common@0.2.11 + +## @backstage/plugin-tech-insights-backend@0.5.14 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-tasks@0.5.5 + - @backstage/plugin-tech-insights-node@0.4.6 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-tech-insights-common@0.2.11 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.32 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-tech-insights-node@0.4.6 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-tech-insights-common@0.2.11 + +## @backstage/plugin-tech-insights-node@0.4.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-tasks@0.5.5 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + - @backstage/plugin-tech-insights-common@0.2.11 + +## @backstage/plugin-tech-radar@0.6.7 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + +## @backstage/plugin-techdocs@1.6.6 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.16 + - @backstage/integration@1.6.0 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/plugin-search-react@1.6.4 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-search-common@1.2.5 + - @backstage/plugin-techdocs-react@1.1.9 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.17 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.9.1 + - @backstage/integration-react@1.1.16 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog@1.12.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/test-utils@1.4.2 + - @backstage/plugin-search-react@1.6.4 + - @backstage/plugin-techdocs@1.6.6 + - @backstage/theme@0.4.1 + - @backstage/plugin-techdocs-react@1.1.9 + +## @backstage/plugin-techdocs-backend@1.6.5 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/plugin-search-backend-module-techdocs@0.1.4 + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/integration@1.6.0 + - @backstage/plugin-techdocs-node@1.7.4 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-techdocs-module-addons-contrib@1.0.16 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.16 + - @backstage/integration@1.6.0 + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-techdocs-react@1.1.9 + +## @backstage/plugin-techdocs-node@1.7.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/integration@1.6.0 + - @backstage/integration-aws-node@0.1.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-techdocs-react@1.1.9 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/version-bridge@1.0.4 + +## @backstage/plugin-todo@0.2.23 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-user-settings@0.7.6 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.9.1 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-user-settings-backend@0.1.12 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-vault@0.1.15 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-vault-backend@0.3.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-tasks@0.5.5 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-xcmetrics@0.2.41 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- 3d86be999fdf: Prefer simple `theme.spacing` without string interpolation +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## example-app@0.2.86 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.9.1 + - @backstage/plugin-catalog-graph@0.2.33 + - @backstage/plugin-playlist@0.1.13 + - @backstage/plugin-pagerduty@0.6.2 + - @backstage/plugin-scaffolder@1.14.2 + - @backstage/plugin-explore@0.4.7 + - @backstage/plugin-org@0.6.11 + - @backstage/integration-react@1.1.16 + - @backstage/plugin-microsoft-calendar@0.1.6 + - @backstage/plugin-newrelic-dashboard@0.2.14 + - @backstage/plugin-entity-feedback@0.2.4 + - @backstage/plugin-linguist-common@0.1.1 + - @backstage/plugin-apache-airflow@0.2.14 + - @backstage/plugin-octopus-deploy@0.2.3 + - @backstage/plugin-stack-overflow@0.1.19 + - @backstage/plugin-code-coverage@0.2.14 + - @backstage/plugin-tech-insights@0.3.13 + - @backstage/plugin-dynatrace@7.0.1 + - @backstage/plugin-gcalendar@0.3.17 + - @backstage/plugin-shortcuts@0.3.13 + - @backstage/plugin-airbrake@0.3.21 + - @backstage/plugin-kafka@0.3.21 + - @backstage/plugin-nomad@0.1.2 + - @backstage/plugin-adr@0.6.4 + - @backstage/plugin-newrelic@0.3.39 + - @backstage/cli@0.22.10 + - @backstage/plugin-kubernetes@0.10.0 + - @backstage/core-components@0.13.4 + - @backstage/plugin-home@0.5.5 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/plugin-scaffolder-react@1.5.2 + - @backstage/plugin-devtools@0.1.3 + - @backstage/app-defaults@1.4.2 + - @backstage/core-plugin-api@1.5.3 + - @backstage/plugin-api-docs@0.9.7 + - @backstage/plugin-azure-devops@0.3.3 + - @backstage/plugin-azure-sites@0.1.10 + - @backstage/plugin-badges@0.2.45 + - @backstage/plugin-catalog-import@0.9.11 + - @backstage/plugin-catalog-unprocessed-entities@0.1.2 + - @backstage/plugin-circleci@0.3.21 + - @backstage/plugin-cloudbuild@0.3.21 + - @backstage/plugin-cost-insights@0.12.10 + - @backstage/plugin-gcp-projects@0.3.40 + - @backstage/plugin-github-actions@0.6.2 + - @backstage/plugin-gocd@0.1.27 + - @backstage/plugin-graphiql@0.2.53 + - @backstage/plugin-jenkins@0.8.3 + - @backstage/plugin-lighthouse@0.4.6 + - @backstage/plugin-linguist@0.1.6 + - @backstage/plugin-puppetdb@0.1.4 + - @backstage/plugin-rollbar@0.4.21 + - @backstage/plugin-search@1.3.4 + - @backstage/plugin-search-react@1.6.4 + - @backstage/plugin-sentry@0.5.6 + - @backstage/plugin-stackstorm@0.1.5 + - @backstage/plugin-tech-radar@0.6.7 + - @backstage/plugin-techdocs@1.6.6 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.16 + - @backstage/plugin-todo@0.2.23 + - @backstage/plugin-user-settings@0.7.6 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-react@0.4.14 + - @backstage/plugin-search-common@1.2.5 + - @backstage/plugin-techdocs-react@1.1.9 + - @internal/plugin-catalog-customized@0.0.13 + +## example-backend@0.2.86 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-module-elasticsearch@1.3.3 + - @backstage/plugin-search-backend-module-pg@0.5.9 + - @backstage/plugin-azure-devops-backend@0.3.27 + - @backstage/plugin-kubernetes-backend@0.11.3 + - @backstage/plugin-lighthouse-backend@0.2.4 + - @backstage/plugin-permission-backend@0.5.23 + - @backstage/plugin-scaffolder-backend@1.16.0 + - @backstage/plugin-devtools-backend@0.1.3 + - @backstage/plugin-techdocs-backend@1.6.5 + - @backstage/backend-common@0.19.2 + - @backstage/plugin-catalog-backend@1.12.0 + - @backstage/plugin-badges-backend@0.2.3 + - @backstage/plugin-events-backend@0.2.9 + - @backstage/plugin-search-backend@1.4.0 + - @backstage/plugin-kafka-backend@0.2.41 + - @backstage/plugin-proxy-backend@0.3.0 + - @backstage/plugin-todo-backend@0.2.0 + - @backstage/plugin-app-backend@0.3.48 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.1 + - @backstage/plugin-auth-backend@0.18.6 + - @backstage/plugin-explore-backend@0.0.10 + - @backstage/plugin-catalog-backend-module-unprocessed@0.2.0 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.17 + - @backstage/plugin-entity-feedback-backend@0.1.6 + - @backstage/plugin-code-coverage-backend@0.2.14 + - @backstage/plugin-search-backend-node@1.2.4 + - @backstage/plugin-linguist-backend@0.4.0 + - @backstage/plugin-playlist-backend@0.3.4 + - @backstage/plugin-jenkins-backend@0.2.3 + - @backstage/plugin-nomad-backend@0.1.2 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/plugin-events-node@0.2.9 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - example-app@0.2.86 + - @backstage/plugin-adr-backend@0.3.6 + - @backstage/plugin-azure-sites-backend@0.1.10 + - @backstage/plugin-graphql-backend@0.1.38 + - @backstage/plugin-permission-node@0.7.11 + - @backstage/plugin-rollbar-backend@0.1.45 + - @backstage/plugin-tech-insights-backend@0.5.14 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.32 + - @backstage/plugin-tech-insights-node@0.4.6 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-search-common@1.2.5 + +## example-backend-next@0.0.14 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-module-techdocs@0.1.4 + - @backstage/plugin-search-backend-module-catalog@0.1.4 + - @backstage/plugin-search-backend-module-explore@0.1.4 + - @backstage/plugin-azure-devops-backend@0.3.27 + - @backstage/plugin-kubernetes-backend@0.11.3 + - @backstage/plugin-lighthouse-backend@0.2.4 + - @backstage/plugin-permission-backend@0.5.23 + - @backstage/plugin-scaffolder-backend@1.16.0 + - @backstage/backend-defaults@0.2.0 + - @backstage/plugin-devtools-backend@0.1.3 + - @backstage/plugin-techdocs-backend@1.6.5 + - @backstage/plugin-catalog-backend@1.12.0 + - @backstage/plugin-badges-backend@0.2.3 + - @backstage/plugin-search-backend@1.4.0 + - @backstage/plugin-proxy-backend@0.3.0 + - @backstage/plugin-todo-backend@0.2.0 + - @backstage/plugin-app-backend@0.3.48 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.2.0 + - @backstage/plugin-entity-feedback-backend@0.1.6 + - @backstage/plugin-search-backend-node@1.2.4 + - @backstage/plugin-linguist-backend@0.4.0 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/backend-tasks@0.5.5 + - @backstage/plugin-adr-backend@0.3.6 + - @backstage/plugin-permission-node@0.7.11 + - @backstage/plugin-permission-common@0.7.7 + +## e2e-test@0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.4 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.2.1 + +## techdocs-cli-embedded-app@0.2.85 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.9.1 + - @backstage/integration-react@1.1.16 + - @backstage/cli@0.22.10 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog@1.12.1 + - @backstage/app-defaults@1.4.2 + - @backstage/core-plugin-api@1.5.3 + - @backstage/test-utils@1.4.2 + - @backstage/plugin-techdocs@1.6.6 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/theme@0.4.1 + - @backstage/plugin-techdocs-react@1.1.9 + +## @internal/plugin-catalog-customized@0.0.13 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.12.1 + - @backstage/plugin-catalog-react@1.8.1 + +## @internal/plugin-todo-list@1.0.16 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + +## @internal/plugin-todo-list-backend@1.0.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 diff --git a/docs/releases/v1.17.0-next.1-changelog.md b/docs/releases/v1.17.0-next.1-changelog.md new file mode 100644 index 0000000000..5af9f0398b --- /dev/null +++ b/docs/releases/v1.17.0-next.1-changelog.md @@ -0,0 +1,2208 @@ +# Release v1.17.0-next.1 + +## @backstage/backend-app-api@0.5.0-next.1 + +### Minor Changes + +- b9c57a4f857e: **BREAKING**: Renamed `configServiceFactory` to `rootConfigServiceFactory`. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/config-loader@1.4.0-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/plugin-permission-node@0.7.11-next.1 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/backend-defaults@0.2.0-next.1 + +### Minor Changes + +- d008aefef808: **BREAKING**: Removing shared environments concept from the new experimental backend system. + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-app-api@0.5.0-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + +## @backstage/backend-plugin-api@0.6.0-next.1 + +### Minor Changes + +- 629cbd194a87: **BREAKING**: Renamed `coreServices.config` to `coreServices.rootConfig`. +- d008aefef808: **BREAKING**: Removing shared environments concept from the new experimental backend system. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/backend-test-utils@0.2.0-next.1 + +### Minor Changes + +- b9c57a4f857e: **BREAKING**: Renamed `mockServices.config` to `mockServices.rootConfig`. + +### Patch Changes + +- ae9304818136: Add needed constants and constructs to support PostgreSQL version 14 as test database +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-app-api@0.5.0-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + +## @backstage/config-loader@1.4.0-next.1 + +### Minor Changes + +- 2f1859585998: Loading invalid TypeScript configuration schemas will now throw an error rather than silently being ignored. + + In particular this includes defining any additional types other than `Config` in the schema file, or use of unsupported types such as `Record` or `Partial`. + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-catalog-backend@1.12.0-next.1 + +### Minor Changes + +- f32252cdf631: Added OpenTelemetry spans for catalog processing + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/plugin-search-backend-module-catalog@0.1.4-next.1 + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-openapi-utils@0.0.3-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/plugin-events-node@0.2.9-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/plugin-permission-node@0.7.11-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-scaffolder-common@1.3.2 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-catalog-backend-module-gcp@0.1.0-next.0 + +### Minor Changes + +- 290eff6692aa: Added GCP catalog plugin with GKE provider + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/config@1.0.8 + - @backstage/plugin-kubernetes-common@0.6.5 + +## @backstage/backend-common@0.19.2-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/config-loader@1.4.0-next.1 + - @backstage/backend-app-api@0.5.0-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/integration@1.5.1 + - @backstage/integration-aws-node@0.1.5 + - @backstage/backend-dev-utils@0.1.1 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/backend-openapi-utils@0.0.3-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/errors@1.2.1 + +## @backstage/backend-tasks@0.5.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/cli@0.22.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.4.0-next.1 + - @backstage/cli-node@0.1.3-next.0 + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/eslint-plugin@0.1.3 + - @backstage/release-manifests@0.0.9 + - @backstage/types@1.1.0 + +## @backstage/cli-node@0.1.3-next.0 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/create-app@0.5.4-next.1 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.12 + +## @backstage/dev-utils@1.0.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.16-next.1 + - @backstage/app-defaults@1.4.2-next.0 + - @backstage/catalog-model@1.4.1 + - @backstage/core-app-api@1.9.1-next.0 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/test-utils@1.4.2-next.0 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/integration-react@1.1.16-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/integration@1.5.1 + - @backstage/config@1.0.8 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + +## @backstage/repo-tools@0.3.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-node@0.1.3-next.0 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.2.1 + +## @techdocs/cli@1.4.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-techdocs-node@1.7.4-next.1 + - @backstage/catalog-model@1.4.1 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + +## @backstage/plugin-adr@0.6.4-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/integration-react@1.1.16-next.1 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-adr-common@0.2.11 + - @backstage/plugin-catalog-react@1.8.1-next.0 + - @backstage/plugin-search-common@1.2.5 + - @backstage/plugin-search-react@1.6.4-next.0 + +## @backstage/plugin-adr-backend@0.3.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-adr-common@0.2.11 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-airbrake@0.3.21-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/dev-utils@1.0.18-next.1 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/test-utils@1.4.2-next.0 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-airbrake-backend@0.2.21-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/config@1.0.8 + +## @backstage/plugin-allure@0.1.37-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-analytics-module-ga@0.1.32-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/config@1.0.8 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + +## @backstage/plugin-analytics-module-ga4@0.1.3-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/config@1.0.8 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + +## @backstage/plugin-apache-airflow@0.2.14-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + +## @backstage/plugin-api-docs@0.9.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.12.1-next.1 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-apollo-explorer@0.1.14-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + +## @backstage/plugin-app-backend@0.3.48-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/config-loader@1.4.0-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + +## @backstage/plugin-auth-backend@0.18.6-next.1 + +### Patch Changes + +- 9dad4b0e61bd: Updated config schema to match what was being used in code +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-auth-node@0.2.17-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-azure-devops-backend@0.3.27-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/config@1.0.8 + - @backstage/plugin-azure-devops-common@0.3.0 + +## @backstage/plugin-azure-sites-backend@0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/config@1.0.8 + - @backstage/plugin-azure-sites-common@0.1.0 + +## @backstage/plugin-badges-backend@0.2.3-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-bazaar@0.2.12-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/cli@0.22.10-next.1 + - @backstage/plugin-catalog@1.12.1-next.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-bazaar-backend@0.2.11-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-bitbucket-cloud-common@0.2.9-next.0 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/integration@1.5.1 + +## @backstage/plugin-bitrise@0.1.48-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-catalog@1.12.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.16-next.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-catalog-react@1.8.1-next.0 + - @backstage/plugin-scaffolder-common@1.3.2 + - @backstage/plugin-search-common@1.2.5 + - @backstage/plugin-search-react@1.6.4-next.0 + +## @backstage/plugin-catalog-backend-module-aws@0.2.3-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- b4222908b0c3: Added option to configure AWS `accountId` in `AwsS3EntityProvider` +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/integration@1.5.1 + - @backstage/integration-aws-node@0.1.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-kubernetes-common@0.6.5 + +## @backstage/plugin-catalog-backend-module-azure@0.1.19-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-bitbucket-cloud-common@0.2.9-next.0 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.15-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-bitbucket-cloud-common@0.2.9-next.0 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/plugin-events-node@0.2.9-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/plugin-catalog-common@1.0.15 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.13-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.16-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-catalog-backend-module-github@0.3.3-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-backend@1.12.0-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/plugin-events-node@0.2.9-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + +## @backstage/plugin-catalog-backend-module-gitlab@0.2.4-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- e6c721439f37: Added option to skip forked repos in GitlabDiscoveryEntityProvider +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.4.1-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-backend@1.12.0-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/plugin-events-node@0.2.9-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + +## @backstage/plugin-catalog-backend-module-msgraph@0.5.7-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/plugin-catalog-common@1.0.15 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-backend@1.12.0-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.1.5-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.2.0-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/catalog-model@1.4.1 + +## @backstage/plugin-catalog-graph@0.2.33-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-catalog-import@0.9.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.16-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-catalog-node@1.4.1-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.17-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/plugin-cicd-statistics@0.1.23-next.0 + +## @backstage/plugin-code-climate@0.1.21-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-code-coverage@0.2.14-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-code-coverage-backend@0.2.14-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-codescene@0.1.16-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/config@1.0.8 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-config-schema@0.1.44-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/config@1.0.8 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-devtools@0.1.3-next.1 + +### Patch Changes + +- 48b6a04ad045: Fix readme typo +- Updated dependencies + - @backstage/plugin-devtools-common@0.1.3-next.0 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + - @backstage/plugin-permission-react@0.4.14 + +## @backstage/plugin-devtools-backend@0.1.3-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` + +- 12a8c94eda8d: Add package repository and homepage metadata + +- 2b4f77a4e900: Add DevTools configuration to enable dependency listing to be filtered with custom prefixes. For instance, in your `app-config.yaml`: + + ```yaml + devTools: + info: + packagePrefixes: + - @backstage/ + - @roadiehq/backstage- + - @spotify/backstage- + ``` + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/config-loader@1.4.0-next.1 + - @backstage/plugin-devtools-common@0.1.3-next.0 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/plugin-permission-node@0.7.11-next.1 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-devtools-common@0.1.3-next.0 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/types@1.1.0 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-dynatrace@7.0.1-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-entity-feedback@0.2.4-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-entity-feedback-common@0.1.2-next.0 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-entity-feedback-backend@0.1.6-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-entity-feedback-common@0.1.2-next.0 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + +## @backstage/plugin-entity-feedback-common@0.1.2-next.0 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata + +## @backstage/plugin-entity-validation@0.1.6-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-events-backend@0.2.9-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-events-node@0.2.9-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/config@1.0.8 + +## @backstage/plugin-events-backend-module-aws-sqs@0.2.3-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-events-node@0.2.9-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + +## @backstage/plugin-events-backend-module-azure@0.1.10-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-events-node@0.2.9-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.1.10-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-events-node@0.2.9-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + +## @backstage/plugin-events-backend-module-gerrit@0.1.10-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-events-node@0.2.9-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + +## @backstage/plugin-events-backend-module-github@0.1.10-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-events-node@0.2.9-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/config@1.0.8 + +## @backstage/plugin-events-backend-module-gitlab@0.1.10-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-events-node@0.2.9-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/config@1.0.8 + +## @backstage/plugin-events-backend-test-utils@0.1.10-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-events-node@0.2.9-next.1 + +## @backstage/plugin-events-node@0.2.9-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.1 + +## @backstage/plugin-explore-backend@0.0.10-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-search-backend-module-explore@0.1.4-next.1 + - @backstage/backend-common@0.19.2-next.1 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-firehydrant@0.2.5-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-gcalendar@0.3.17-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-git-release-manager@0.3.34-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/integration@1.5.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + +## @backstage/plugin-github-actions@0.6.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.16-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-github-deployments@0.1.52-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/integration-react@1.1.16-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-github-issues@0.2.10-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-graphql-backend@0.1.38-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/config@1.0.8 + - @backstage/plugin-catalog-graphql@0.3.22 + +## @backstage/plugin-graphql-voyager@0.1.6-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + +## @backstage/plugin-ilert@0.2.10-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-jenkins@0.8.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-jenkins-common@0.1.18-next.0 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-jenkins-backend@0.2.3-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-jenkins-common@0.1.18-next.0 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/plugin-permission-node@0.7.11-next.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-jenkins-common@0.1.18-next.0 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-kafka@0.3.21-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-kafka-backend@0.2.41-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-kubernetes-backend@0.11.3-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- bbf4e9c894b5: Fixed a bug where the proxy was not rewriting WebSocket request paths properly. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/plugin-permission-node@0.7.11-next.1 + - @backstage/integration-aws-node@0.1.5 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-kubernetes-common@0.6.5 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-lighthouse-backend@0.2.4-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + - @backstage/plugin-lighthouse-common@0.1.2 + +## @backstage/plugin-linguist@0.1.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-linguist-common@0.1.1-next.0 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-linguist-backend@0.3.2-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-linguist-common@0.1.1-next.0 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-linguist-common@0.1.1-next.0 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata + +## @backstage/plugin-microsoft-calendar@0.1.6-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- eea2922e749a: README update - example of apiRef definition and fixed component name +- Updated dependencies + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## @backstage/plugin-newrelic-dashboard@0.2.14-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-nomad@0.1.2-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-nomad-backend@0.1.2-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-octopus-deploy@0.2.3-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-org@0.6.11-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-org-react@0.1.10-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-periskop@0.1.19-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @backstage/plugin-periskop-backend@0.1.19-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/config@1.0.8 + +## @backstage/plugin-permission-backend@0.5.23-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/plugin-permission-node@0.7.11-next.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-permission-node@0.7.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-playlist@0.1.13-next.1 + +### Patch Changes + +- d1e0588324d1: Displaying an alert popup each time the Playlist is created or deleted +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-playlist-common@0.1.9-next.0 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-catalog-react@1.8.1-next.0 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-permission-react@0.4.14 + - @backstage/plugin-search-react@1.6.4-next.0 + +## @backstage/plugin-playlist-backend@0.3.4-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-playlist-common@0.1.9-next.0 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/plugin-permission-node@0.7.11-next.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-playlist-common@0.1.9-next.0 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-permission-common@0.7.7 + +## @backstage/plugin-proxy-backend@0.2.42-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/config@1.0.8 + +## @backstage/plugin-rollbar-backend@0.1.45-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/config@1.0.8 + +## @backstage/plugin-scaffolder@1.14.2-next.1 + +### Patch Changes + +- 8a0490fb669e: Fix the get entities query in the `MyGroupsPicker` to query the `kind=Group` entities. +- Updated dependencies + - @backstage/integration-react@1.1.16-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-catalog-react@1.8.1-next.0 + - @backstage/plugin-permission-react@0.4.14 + - @backstage/plugin-scaffolder-common@1.3.2 + - @backstage/plugin-scaffolder-react@1.5.2-next.0 + +## @backstage/plugin-scaffolder-backend@1.15.2-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- d3b31a791eb1: Deprecated `executeShellCommand`, `RunCommandOptions`, and `fetchContents` from `@backstage/plugin-scaffolder-backend`, since they are useful for Scaffolder modules (who should not be importing from the plugin package itself). You should now import these from `@backstage/plugin-scaffolder-backend-node` instead. `RunCommandOptions` was renamed in the Node package as `ExecuteShellCommandOptions`, for consistency. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-backend@1.12.0-next.1 + - @backstage/plugin-scaffolder-node@0.1.6-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/plugin-permission-node@0.7.11-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-scaffolder-common@1.3.2 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.1-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- 0d347efc8f18: Use `fetchContents` directly instead of a `fetchPlainAction` +- c186c631b429: Import helpers from the node package instead of the backend package +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-scaffolder-node@0.1.6-next.1 + - @backstage/integration@1.5.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.24-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- c186c631b429: Import helpers from the node package instead of the backend package +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-scaffolder-node@0.1.6-next.1 + - @backstage/integration@1.5.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.2.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.6-next.1 + - @backstage/integration@1.5.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.17-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- c186c631b429: Import helpers from the node package instead of the backend package +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-scaffolder-node@0.1.6-next.1 + - @backstage/integration@1.5.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.8-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.6-next.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.21-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.6-next.1 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + +## @backstage/plugin-scaffolder-node@0.1.6-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- d3b31a791eb1: Deprecated `executeShellCommand`, `RunCommandOptions`, and `fetchContents` from `@backstage/plugin-scaffolder-backend`, since they are useful for Scaffolder modules (who should not be importing from the plugin package itself). You should now import these from `@backstage/plugin-scaffolder-backend-node` instead. `RunCommandOptions` was renamed in the Node package as `ExecuteShellCommandOptions`, for consistency. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-scaffolder-common@1.3.2 + +## @backstage/plugin-search-backend@1.4.0-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- 951ab6c9db58: Add missing `configSchema` to package.json +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-openapi-utils@0.0.3-next.1 + - @backstage/plugin-search-backend-node@1.2.4-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/plugin-permission-node@0.7.11-next.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-search-backend-module-catalog@0.1.4-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-search-backend-node@1.2.4-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-search-backend-module-elasticsearch@1.3.3-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-search-backend-node@1.2.4-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/integration-aws-node@0.1.5 + - @backstage/config@1.0.8 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-search-backend-module-explore@0.1.4-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-search-backend-node@1.2.4-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/config@1.0.8 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-search-backend-module-pg@0.5.9-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-search-backend-node@1.2.4-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/config@1.0.8 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-search-backend-module-techdocs@0.1.4-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-search-backend-node@1.2.4-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/plugin-techdocs-node@1.7.4-next.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-search-backend-node@1.2.4-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-shortcuts@0.3.13-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-sonarqube@0.7.2-next.1 + +### Patch Changes + +- b2ccddefbdc6: Remove sonarQube card disable class +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + - @backstage/plugin-sonarqube-react@0.1.7 + +## @backstage/plugin-sonarqube-backend@0.2.2-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-stack-overflow@0.1.19-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/config@1.0.8 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-home-react@0.1.2-next.0 + - @backstage/plugin-search-common@1.2.5 + - @backstage/plugin-search-react@1.6.4-next.0 + +## @backstage/plugin-stack-overflow-backend@0.2.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/config@1.0.8 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-tech-insights@0.3.13-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-react@1.8.1-next.0 + - @backstage/plugin-tech-insights-common@0.2.11 + +## @backstage/plugin-tech-insights-backend@0.5.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/plugin-tech-insights-node@0.4.6-next.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-tech-insights-common@0.2.11 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.32-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-tech-insights-node@0.4.6-next.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-tech-insights-common@0.2.11 + +## @backstage/plugin-tech-insights-node@0.4.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + - @backstage/plugin-tech-insights-common@0.2.11 + +## @backstage/plugin-techdocs@1.6.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.16-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + - @backstage/plugin-search-common@1.2.5 + - @backstage/plugin-search-react@1.6.4-next.0 + - @backstage/plugin-techdocs-react@1.1.9-next.0 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.16-next.1 + - @backstage/plugin-catalog@1.12.1-next.1 + - @backstage/plugin-techdocs@1.6.6-next.1 + - @backstage/core-app-api@1.9.1-next.0 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/test-utils@1.4.2-next.0 + - @backstage/theme@0.4.1 + - @backstage/plugin-search-react@1.6.4-next.0 + - @backstage/plugin-techdocs-react@1.1.9-next.0 + +## @backstage/plugin-techdocs-backend@1.6.5-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/plugin-search-backend-module-techdocs@0.1.4-next.1 + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/plugin-techdocs-node@1.7.4-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-techdocs-module-addons-contrib@1.0.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.16-next.1 + - @backstage/integration@1.5.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-techdocs-react@1.1.9-next.0 + +## @backstage/plugin-techdocs-node@1.7.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/integration@1.5.1 + - @backstage/integration-aws-node@0.1.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-search-common@1.2.5 + +## @backstage/plugin-todo-backend@0.2.0-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-openapi-utils@0.0.3-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-user-settings-backend@0.1.12-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## @backstage/plugin-vault-backend@0.3.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## @backstage/plugin-xcmetrics@0.2.41-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## example-app@0.2.86-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-playlist@0.1.13-next.1 + - @backstage/plugin-scaffolder@1.14.2-next.1 + - @backstage/integration-react@1.1.16-next.1 + - @backstage/plugin-microsoft-calendar@0.1.6-next.1 + - @backstage/plugin-newrelic-dashboard@0.2.14-next.1 + - @backstage/plugin-entity-feedback@0.2.4-next.1 + - @backstage/plugin-linguist-common@0.1.1-next.0 + - @backstage/plugin-apache-airflow@0.2.14-next.1 + - @backstage/plugin-octopus-deploy@0.2.3-next.1 + - @backstage/plugin-stack-overflow@0.1.19-next.1 + - @backstage/plugin-catalog-graph@0.2.33-next.1 + - @backstage/plugin-code-coverage@0.2.14-next.1 + - @backstage/plugin-tech-insights@0.3.13-next.1 + - @backstage/plugin-dynatrace@7.0.1-next.1 + - @backstage/plugin-gcalendar@0.3.17-next.1 + - @backstage/plugin-shortcuts@0.3.13-next.1 + - @backstage/plugin-airbrake@0.3.21-next.1 + - @backstage/plugin-kafka@0.3.21-next.1 + - @backstage/plugin-nomad@0.1.2-next.1 + - @backstage/plugin-adr@0.6.4-next.1 + - @backstage/plugin-org@0.6.11-next.1 + - @backstage/plugin-devtools@0.1.3-next.1 + - @backstage/cli@0.22.10-next.1 + - @backstage/plugin-catalog-import@0.9.11-next.1 + - @backstage/plugin-github-actions@0.6.2-next.1 + - @backstage/plugin-techdocs@1.6.6-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.16-next.1 + - @backstage/plugin-linguist@0.1.6-next.1 + - @backstage/plugin-jenkins@0.8.3-next.1 + - @backstage/app-defaults@1.4.2-next.0 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/core-app-api@1.9.1-next.0 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-api-docs@0.9.7-next.1 + - @backstage/plugin-azure-devops@0.3.3-next.0 + - @backstage/plugin-azure-sites@0.1.10-next.0 + - @backstage/plugin-badges@0.2.45-next.0 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-catalog-react@1.8.1-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.1.2-next.0 + - @backstage/plugin-circleci@0.3.21-next.0 + - @backstage/plugin-cloudbuild@0.3.21-next.0 + - @backstage/plugin-cost-insights@0.12.10-next.0 + - @backstage/plugin-explore@0.4.7-next.0 + - @backstage/plugin-gcp-projects@0.3.40-next.0 + - @backstage/plugin-gocd@0.1.27-next.0 + - @backstage/plugin-graphiql@0.2.53-next.0 + - @backstage/plugin-home@0.5.5-next.0 + - @backstage/plugin-kubernetes@0.9.4-next.0 + - @backstage/plugin-lighthouse@0.4.6-next.0 + - @backstage/plugin-newrelic@0.3.39-next.0 + - @backstage/plugin-pagerduty@0.6.2-next.0 + - @backstage/plugin-permission-react@0.4.14 + - @backstage/plugin-puppetdb@0.1.4-next.0 + - @backstage/plugin-rollbar@0.4.21-next.0 + - @backstage/plugin-scaffolder-react@1.5.2-next.0 + - @backstage/plugin-search@1.3.4-next.0 + - @backstage/plugin-search-common@1.2.5 + - @backstage/plugin-search-react@1.6.4-next.0 + - @backstage/plugin-sentry@0.5.6-next.0 + - @backstage/plugin-stackstorm@0.1.5-next.0 + - @backstage/plugin-tech-radar@0.6.7-next.0 + - @backstage/plugin-techdocs-react@1.1.9-next.0 + - @backstage/plugin-todo@0.2.23-next.0 + - @backstage/plugin-user-settings@0.7.6-next.0 + - @internal/plugin-catalog-customized@0.0.13-next.1 + +## example-backend@0.2.86-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-module-elasticsearch@1.3.3-next.1 + - @backstage/plugin-search-backend-module-pg@0.5.9-next.1 + - @backstage/plugin-azure-devops-backend@0.3.27-next.1 + - @backstage/plugin-kubernetes-backend@0.11.3-next.1 + - @backstage/plugin-lighthouse-backend@0.2.4-next.1 + - @backstage/plugin-permission-backend@0.5.23-next.1 + - @backstage/plugin-scaffolder-backend@1.15.2-next.1 + - @backstage/plugin-devtools-backend@0.1.3-next.1 + - @backstage/plugin-techdocs-backend@1.6.5-next.1 + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-backend@1.12.0-next.1 + - @backstage/plugin-badges-backend@0.2.3-next.1 + - @backstage/plugin-events-backend@0.2.9-next.1 + - @backstage/plugin-search-backend@1.4.0-next.1 + - @backstage/plugin-kafka-backend@0.2.41-next.1 + - @backstage/plugin-proxy-backend@0.2.42-next.1 + - @backstage/plugin-todo-backend@0.2.0-next.1 + - @backstage/plugin-app-backend@0.3.48-next.1 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.1-next.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.2.0-next.1 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.17-next.1 + - @backstage/plugin-entity-feedback-backend@0.1.6-next.1 + - @backstage/plugin-code-coverage-backend@0.2.14-next.1 + - @backstage/plugin-search-backend-node@1.2.4-next.1 + - @backstage/plugin-linguist-backend@0.3.2-next.1 + - @backstage/plugin-playlist-backend@0.3.4-next.1 + - @backstage/plugin-explore-backend@0.0.10-next.1 + - @backstage/plugin-jenkins-backend@0.2.3-next.1 + - @backstage/plugin-nomad-backend@0.1.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/plugin-events-node@0.2.9-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/plugin-auth-backend@0.18.6-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/plugin-adr-backend@0.3.6-next.1 + - @backstage/plugin-azure-sites-backend@0.1.10-next.1 + - @backstage/plugin-graphql-backend@0.1.38-next.1 + - @backstage/plugin-permission-node@0.7.11-next.1 + - @backstage/plugin-rollbar-backend@0.1.45-next.1 + - @backstage/plugin-tech-insights-backend@0.5.14-next.1 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.32-next.1 + - @backstage/plugin-tech-insights-node@0.4.6-next.1 + - example-app@0.2.86-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-search-common@1.2.5 + +## example-backend-next@0.0.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-module-techdocs@0.1.4-next.1 + - @backstage/plugin-search-backend-module-catalog@0.1.4-next.1 + - @backstage/plugin-search-backend-module-explore@0.1.4-next.1 + - @backstage/plugin-azure-devops-backend@0.3.27-next.1 + - @backstage/plugin-kubernetes-backend@0.11.3-next.1 + - @backstage/plugin-lighthouse-backend@0.2.4-next.1 + - @backstage/plugin-permission-backend@0.5.23-next.1 + - @backstage/plugin-scaffolder-backend@1.15.2-next.1 + - @backstage/backend-defaults@0.2.0-next.1 + - @backstage/plugin-devtools-backend@0.1.3-next.1 + - @backstage/plugin-techdocs-backend@1.6.5-next.1 + - @backstage/plugin-catalog-backend@1.12.0-next.1 + - @backstage/plugin-badges-backend@0.2.3-next.1 + - @backstage/plugin-search-backend@1.4.0-next.1 + - @backstage/plugin-todo-backend@0.2.0-next.1 + - @backstage/plugin-app-backend@0.3.48-next.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.2.0-next.1 + - @backstage/plugin-entity-feedback-backend@0.1.6-next.1 + - @backstage/plugin-search-backend-node@1.2.4-next.1 + - @backstage/plugin-linguist-backend@0.3.2-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/plugin-adr-backend@0.3.6-next.1 + - @backstage/plugin-permission-node@0.7.11-next.1 + - @backstage/plugin-permission-common@0.7.7 + +## e2e-test@0.2.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.4-next.1 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.2.1 + +## techdocs-cli-embedded-app@0.2.85-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.16-next.1 + - @backstage/cli@0.22.10-next.1 + - @backstage/plugin-catalog@1.12.1-next.1 + - @backstage/plugin-techdocs@1.6.6-next.1 + - @backstage/app-defaults@1.4.2-next.0 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/core-app-api@1.9.1-next.0 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/test-utils@1.4.2-next.0 + - @backstage/theme@0.4.1 + - @backstage/plugin-techdocs-react@1.1.9-next.0 + +## @internal/plugin-catalog-customized@0.0.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.12.1-next.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + +## @internal/plugin-todo-list-backend@1.0.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 diff --git a/docs/releases/v1.17.0-next.2-changelog.md b/docs/releases/v1.17.0-next.2-changelog.md new file mode 100644 index 0000000000..d1da6fa2be --- /dev/null +++ b/docs/releases/v1.17.0-next.2-changelog.md @@ -0,0 +1,1430 @@ +# Release v1.17.0-next.2 + +## @backstage/plugin-app-node@0.1.0-next.0 + +### Minor Changes + +- 9fbe95ef6503: Added the `app` plugin node library, initially providing an extension point that can be used to configure a static fallback handler. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + +## @backstage/plugin-catalog-backend@1.12.0-next.2 + +### Minor Changes + +- b8cccd8ee858: Support configuring applicable kinds for `AnnotateScmSlugEntityProcessor` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-module-catalog@0.1.4-next.2 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + - @backstage/plugin-events-node@0.2.9-next.2 + - @backstage/plugin-permission-node@0.7.11-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## @backstage/plugin-linguist-backend@0.4.0-next.2 + +### Minor Changes + +- d440f1dd0e72: Adds a processor to the linguist backend which can automatically add language tags to entities + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-linguist-common@0.1.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## @backstage/plugin-proxy-backend@0.3.0-next.2 + +### Minor Changes + +- 7daf65bfcfa1: Defining proxy endpoints directly under the root `proxy` configuration key is deprecated. Endpoints should now be declared under `proxy.endpoints` instead. The `skipInvalidProxies` and `reviveConsumedRequestBodies` can now also be configured through static configuration. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/backend-app-api@0.5.0-next.2 + +### Patch Changes + +- e65c4896f755: Do not throw in backend.stop, if start failed +- cc9256a33bcc: Added new experimental `featureDiscoveryServiceFactory`, available as an `/alpha` export. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-permission-node@0.7.11-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + - @backstage/config-loader@1.4.0-next.1 + +## @backstage/backend-common@0.19.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-app-api@0.5.0-next.2 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/config-loader@1.4.0-next.1 + +## @backstage/backend-defaults@0.2.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-app-api@0.5.0-next.2 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/backend-plugin-api@0.6.0-next.2 + +### Patch Changes + +- cc9256a33bcc: Added new experimental `featureDiscoveryServiceRef`, available as an `/alpha` export. +- Updated dependencies + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## @backstage/backend-tasks@0.5.5-next.2 + +### Patch Changes + +- dfd1b6b2fc33: Make `readTaskScheduleDefinitionFromConfig` properly handle bad inputs +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/backend-test-utils@0.2.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-app-api@0.5.0-next.2 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## @backstage/create-app@0.5.4-next.2 + +### Patch Changes + +- Bumped create-app version. + +## @backstage/dev-utils@1.0.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/integration-react@1.1.16-next.1 + +## @techdocs/cli@1.4.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-techdocs-node@1.7.4-next.2 + +## @backstage/plugin-adr@0.6.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/integration-react@1.1.16-next.1 + +## @backstage/plugin-adr-backend@0.3.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-airbrake@0.3.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/dev-utils@1.0.18-next.2 + +## @backstage/plugin-airbrake-backend@0.2.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-allure@0.1.37-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-api-docs@0.9.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/plugin-catalog@1.12.1-next.2 + +## @backstage/plugin-app-backend@0.3.48-next.2 + +### Patch Changes + +- d564ad142b17: Migrated the alpha `appBackend` export to use static configuration and extension points rather than accepting options. +- Updated dependencies + - @backstage/plugin-app-node@0.1.0-next.0 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/config-loader@1.4.0-next.1 + +## @backstage/plugin-auth-backend@0.18.6-next.2 + +### Patch Changes + +- 16452cd007ae: Updated `frameHandler` to return `undefined` when using the redirect flow instead of returning `postMessageReponse` which was causing errors +- bb70a9c3886a: Add frontend visibility to provider objects in `auth` config. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## @backstage/plugin-auth-node@0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-azure-devops@0.3.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-azure-devops-backend@0.3.27-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-azure-sites@0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-azure-sites-backend@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-badges@0.2.45-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-badges-backend@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## @backstage/plugin-bazaar@0.2.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/plugin-catalog@1.12.1-next.2 + - @backstage/cli@0.22.10-next.1 + +## @backstage/plugin-bazaar-backend@0.2.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## @backstage/plugin-bitrise@0.1.48-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-catalog@1.12.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/integration-react@1.1.16-next.1 + +## @backstage/plugin-catalog-backend-module-aws@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## @backstage/plugin-catalog-backend-module-azure@0.1.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + - @backstage/plugin-events-node@0.2.9-next.2 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## @backstage/plugin-catalog-backend-module-gcp@0.1.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## @backstage/plugin-catalog-backend-module-github@0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.12.0-next.2 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + - @backstage/plugin-events-node@0.2.9-next.2 + +## @backstage/plugin-catalog-backend-module-gitlab@0.2.4-next.2 + +### Patch Changes + +- 2fe1f5973ff7: Filter Gitlab archived projects through APIs +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.4.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.12.0-next.2 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + - @backstage/plugin-events-node@0.2.9-next.2 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## @backstage/plugin-catalog-backend-module-msgraph@0.5.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.12.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.2.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## @backstage/plugin-catalog-graph@0.2.33-next.2 + +### Patch Changes + +- 62dc7a2b1ad1: Added maximum depth parameter to the catalogGraphParams in CatalogGraphCard. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-catalog-import@0.9.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/integration-react@1.1.16-next.1 + +## @backstage/plugin-catalog-node@1.4.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + +## @backstage/plugin-catalog-react@1.8.1-next.1 + +### Patch Changes + +- aa3feedce10a: Allow specifying screen size when catalog filters are hidden in drawer + +## @backstage/plugin-cicd-statistics@0.1.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-cicd-statistics@0.1.23-next.1 + +## @backstage/plugin-circleci@0.3.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-cloudbuild@0.3.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-code-climate@0.1.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-code-coverage@0.2.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-code-coverage-backend@0.2.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-cost-insights@0.12.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-devtools-backend@0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-permission-node@0.7.11-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + - @backstage/config-loader@1.4.0-next.1 + +## @backstage/plugin-dynatrace@7.0.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-entity-feedback@0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-entity-feedback-backend@0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## @backstage/plugin-entity-validation@0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-events-backend@0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-events-node@0.2.9-next.2 + +## @backstage/plugin-events-backend-module-aws-sqs@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-events-node@0.2.9-next.2 + +## @backstage/plugin-events-backend-module-azure@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/plugin-events-node@0.2.9-next.2 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/plugin-events-node@0.2.9-next.2 + +## @backstage/plugin-events-backend-module-gerrit@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/plugin-events-node@0.2.9-next.2 + +## @backstage/plugin-events-backend-module-github@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/plugin-events-node@0.2.9-next.2 + +## @backstage/plugin-events-backend-module-gitlab@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/plugin-events-node@0.2.9-next.2 + +## @backstage/plugin-events-backend-test-utils@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.9-next.2 + +## @backstage/plugin-events-node@0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + +## @backstage/plugin-explore@0.4.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/plugin-explore-react@0.0.30 + +## @backstage/plugin-explore-backend@0.0.10-next.2 + +### Patch Changes + +- eda2a699f40d: Moved the config example from the "Tools as Code" section to the "Tools as Config" section of the README +- Updated dependencies + - @backstage/plugin-search-backend-module-explore@0.1.4-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-firehydrant@0.2.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-fossa@0.2.53-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-github-actions@0.6.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/integration-react@1.1.16-next.1 + +## @backstage/plugin-github-deployments@0.1.52-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/integration-react@1.1.16-next.1 + +## @backstage/plugin-github-issues@0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-github-pull-requests-board@0.1.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-gocd@0.1.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-graphql-backend@0.1.38-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-graphql-voyager@0.1.6-next.2 + +### Patch Changes + +- bb1e1c2b26cc: Fix typo in install instructions. + +## @backstage/plugin-home@0.5.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/plugin-home-react@0.1.2-next.0 + +## @backstage/plugin-ilert@0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-jenkins@0.8.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-jenkins-backend@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-permission-node@0.7.11-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## @backstage/plugin-kafka@0.3.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-kafka-backend@0.2.41-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-kubernetes@0.9.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-kubernetes-backend@0.11.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + - @backstage/plugin-permission-node@0.7.11-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## @backstage/plugin-lighthouse@0.4.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-lighthouse-backend@0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## @backstage/plugin-linguist@0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-linguist-common@0.1.1-next.1 + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-linguist-common@0.1.1-next.1 + +### Patch Changes + +- d440f1dd0e72: Exported new LanguageType type alias + +## @backstage/plugin-newrelic-dashboard@0.2.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-nomad@0.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-nomad-backend@0.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-octopus-deploy@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-org@0.6.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-org-react@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-pagerduty@0.6.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/plugin-home-react@0.1.2-next.0 + +## @backstage/plugin-periskop@0.1.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-periskop-backend@0.1.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-permission-backend@0.5.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-permission-node@0.7.11-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## @backstage/plugin-permission-node@0.7.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## @backstage/plugin-playlist@0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-playlist-backend@0.3.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-permission-node@0.7.11-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## @backstage/plugin-puppetdb@0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-rollbar@0.4.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-rollbar-backend@0.1.45-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-scaffolder@1.14.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/plugin-scaffolder-react@1.5.2-next.1 + - @backstage/integration-react@1.1.16-next.1 + +## @backstage/plugin-scaffolder-backend@1.15.2-next.2 + +### Patch Changes + +- 33c76caef72a: Added examples for the fs:delete and fs:rename actions +- 0b1d775be05b: Adds examples to a few scaffolder actions. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.12.0-next.2 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/plugin-scaffolder-node@0.1.6-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + - @backstage/plugin-permission-node@0.7.11-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.6-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.24-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.6-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.6-next.2 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.6-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.6-next.2 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.6-next.2 + +## @backstage/plugin-scaffolder-node@0.1.6-next.2 + +### Patch Changes + +- 0b1d775be05b: Export `TemplateExample` from the `createTemplateAction` type. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-scaffolder-react@1.5.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-search@1.3.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-search-backend@1.4.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-permission-node@0.7.11-next.2 + - @backstage/plugin-search-backend-node@1.2.4-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## @backstage/plugin-search-backend-module-catalog@0.1.4-next.2 + +### Patch Changes + +- 29f77f923c71: Ensure that all services are dependency injected into the module instead of taken from options +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + - @backstage/plugin-search-backend-node@1.2.4-next.2 + +## @backstage/plugin-search-backend-module-elasticsearch@1.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-search-backend-node@1.2.4-next.2 + +## @backstage/plugin-search-backend-module-explore@0.1.4-next.2 + +### Patch Changes + +- 29f77f923c71: Ensure that all services are dependency injected into the module instead of taken from options +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-search-backend-node@1.2.4-next.2 + +## @backstage/plugin-search-backend-module-pg@0.5.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-search-backend-node@1.2.4-next.2 + +## @backstage/plugin-search-backend-module-techdocs@0.1.4-next.2 + +### Patch Changes + +- 29f77f923c71: Ensure that all services are dependency injected into the module instead of taken from options +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + - @backstage/plugin-search-backend-node@1.2.4-next.2 + - @backstage/plugin-techdocs-node@1.7.4-next.2 + +## @backstage/plugin-search-backend-node@1.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-sentry@0.5.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-sonarqube@0.7.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-sonarqube-backend@0.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-splunk-on-call@0.4.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-stack-overflow-backend@0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-tech-insights@0.3.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-tech-insights-backend@0.5.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-tech-insights-node@0.4.6-next.2 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-tech-insights-node@0.4.6-next.2 + +## @backstage/plugin-tech-insights-node@0.4.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-techdocs@1.6.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/integration-react@1.1.16-next.1 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.12.1-next.2 + - @backstage/plugin-techdocs@1.6.6-next.2 + - @backstage/integration-react@1.1.16-next.1 + +## @backstage/plugin-techdocs-backend@1.6.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-module-techdocs@0.1.4-next.2 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-techdocs-node@1.7.4-next.2 + +## @backstage/plugin-techdocs-node@1.7.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + +## @backstage/plugin-todo@0.2.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-todo-backend@0.2.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## @backstage/plugin-user-settings@0.7.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-user-settings-backend@0.1.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## @backstage/plugin-vault@0.1.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## @backstage/plugin-vault-backend@0.3.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## example-app@0.2.86-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-graph@0.2.33-next.2 + - @backstage/plugin-linguist-common@0.1.1-next.1 + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/plugin-linguist@0.1.6-next.2 + - @backstage/plugin-adr@0.6.4-next.2 + - @backstage/plugin-airbrake@0.3.21-next.2 + - @backstage/plugin-api-docs@0.9.7-next.2 + - @backstage/plugin-azure-devops@0.3.3-next.1 + - @backstage/plugin-azure-sites@0.1.10-next.1 + - @backstage/plugin-badges@0.2.45-next.1 + - @internal/plugin-catalog-customized@0.0.13-next.2 + - @backstage/plugin-catalog-import@0.9.11-next.2 + - @backstage/plugin-circleci@0.3.21-next.1 + - @backstage/plugin-cloudbuild@0.3.21-next.1 + - @backstage/plugin-code-coverage@0.2.14-next.2 + - @backstage/plugin-cost-insights@0.12.10-next.1 + - @backstage/plugin-dynatrace@7.0.1-next.2 + - @backstage/plugin-entity-feedback@0.2.4-next.2 + - @backstage/plugin-explore@0.4.7-next.1 + - @backstage/plugin-github-actions@0.6.2-next.2 + - @backstage/plugin-gocd@0.1.27-next.1 + - @backstage/plugin-home@0.5.5-next.1 + - @backstage/plugin-jenkins@0.8.3-next.2 + - @backstage/plugin-kafka@0.3.21-next.2 + - @backstage/plugin-kubernetes@0.9.4-next.1 + - @backstage/plugin-lighthouse@0.4.6-next.1 + - @backstage/plugin-newrelic-dashboard@0.2.14-next.2 + - @backstage/plugin-nomad@0.1.2-next.2 + - @backstage/plugin-octopus-deploy@0.2.3-next.2 + - @backstage/plugin-org@0.6.11-next.2 + - @backstage/plugin-pagerduty@0.6.2-next.1 + - @backstage/plugin-playlist@0.1.13-next.2 + - @backstage/plugin-puppetdb@0.1.4-next.1 + - @backstage/plugin-rollbar@0.4.21-next.1 + - @backstage/plugin-scaffolder@1.14.2-next.2 + - @backstage/plugin-scaffolder-react@1.5.2-next.1 + - @backstage/plugin-search@1.3.4-next.1 + - @backstage/plugin-sentry@0.5.6-next.1 + - @backstage/plugin-tech-insights@0.3.13-next.2 + - @backstage/plugin-techdocs@1.6.6-next.2 + - @backstage/plugin-todo@0.2.23-next.1 + - @backstage/plugin-user-settings@0.7.6-next.1 + - @backstage/cli@0.22.10-next.1 + - @backstage/integration-react@1.1.16-next.1 + - @backstage/plugin-apache-airflow@0.2.14-next.1 + - @backstage/plugin-catalog-unprocessed-entities@0.1.2-next.0 + - @backstage/plugin-devtools@0.1.3-next.1 + - @backstage/plugin-gcalendar@0.3.17-next.1 + - @backstage/plugin-gcp-projects@0.3.40-next.0 + - @backstage/plugin-graphiql@0.2.53-next.0 + - @backstage/plugin-microsoft-calendar@0.1.6-next.1 + - @backstage/plugin-newrelic@0.3.39-next.0 + - @backstage/plugin-shortcuts@0.3.13-next.1 + - @backstage/plugin-stack-overflow@0.1.19-next.1 + - @backstage/plugin-stackstorm@0.1.5-next.0 + - @backstage/plugin-tech-radar@0.6.7-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.16-next.1 + +## example-backend@0.2.86-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-backend@0.18.6-next.2 + - @backstage/plugin-scaffolder-backend@1.15.2-next.2 + - @backstage/plugin-explore-backend@0.0.10-next.2 + - @backstage/plugin-catalog-backend@1.12.0-next.2 + - @backstage/plugin-proxy-backend@0.3.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/plugin-app-backend@0.3.48-next.2 + - @backstage/plugin-linguist-backend@0.4.0-next.2 + - @backstage/plugin-techdocs-backend@1.6.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - example-app@0.2.86-next.2 + - @backstage/plugin-adr-backend@0.3.6-next.2 + - @backstage/plugin-azure-devops-backend@0.3.27-next.2 + - @backstage/plugin-badges-backend@0.2.3-next.2 + - @backstage/plugin-catalog-backend-module-unprocessed@0.2.0-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + - @backstage/plugin-devtools-backend@0.1.3-next.2 + - @backstage/plugin-entity-feedback-backend@0.1.6-next.2 + - @backstage/plugin-events-backend@0.2.9-next.2 + - @backstage/plugin-events-node@0.2.9-next.2 + - @backstage/plugin-kafka-backend@0.2.41-next.2 + - @backstage/plugin-kubernetes-backend@0.11.3-next.2 + - @backstage/plugin-lighthouse-backend@0.2.4-next.2 + - @backstage/plugin-permission-backend@0.5.23-next.2 + - @backstage/plugin-permission-node@0.7.11-next.2 + - @backstage/plugin-search-backend@1.4.0-next.2 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.3-next.2 + - @backstage/plugin-search-backend-module-pg@0.5.9-next.2 + - @backstage/plugin-search-backend-node@1.2.4-next.2 + - @backstage/plugin-todo-backend@0.2.0-next.2 + - @backstage/plugin-tech-insights-backend@0.5.14-next.2 + - @backstage/plugin-tech-insights-node@0.4.6-next.2 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.1-next.2 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.17-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + - @backstage/plugin-azure-sites-backend@0.1.10-next.2 + - @backstage/plugin-code-coverage-backend@0.2.14-next.2 + - @backstage/plugin-graphql-backend@0.1.38-next.2 + - @backstage/plugin-jenkins-backend@0.2.3-next.2 + - @backstage/plugin-nomad-backend@0.1.2-next.2 + - @backstage/plugin-playlist-backend@0.3.4-next.2 + - @backstage/plugin-rollbar-backend@0.1.45-next.2 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.32-next.2 + +## example-backend-next@0.0.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-module-techdocs@0.1.4-next.2 + - @backstage/plugin-search-backend-module-catalog@0.1.4-next.2 + - @backstage/plugin-search-backend-module-explore@0.1.4-next.2 + - @backstage/plugin-scaffolder-backend@1.15.2-next.2 + - @backstage/plugin-catalog-backend@1.12.0-next.2 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/plugin-proxy-backend@0.3.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/plugin-app-backend@0.3.48-next.2 + - @backstage/plugin-linguist-backend@0.4.0-next.2 + - @backstage/plugin-techdocs-backend@1.6.5-next.2 + - @backstage/backend-defaults@0.2.0-next.2 + - @backstage/plugin-adr-backend@0.3.6-next.2 + - @backstage/plugin-azure-devops-backend@0.3.27-next.2 + - @backstage/plugin-badges-backend@0.2.3-next.2 + - @backstage/plugin-catalog-backend-module-unprocessed@0.2.0-next.2 + - @backstage/plugin-devtools-backend@0.1.3-next.2 + - @backstage/plugin-entity-feedback-backend@0.1.6-next.2 + - @backstage/plugin-kubernetes-backend@0.11.3-next.2 + - @backstage/plugin-lighthouse-backend@0.2.4-next.2 + - @backstage/plugin-permission-backend@0.5.23-next.2 + - @backstage/plugin-permission-node@0.7.11-next.2 + - @backstage/plugin-search-backend@1.4.0-next.2 + - @backstage/plugin-search-backend-node@1.2.4-next.2 + - @backstage/plugin-todo-backend@0.2.0-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## e2e-test@0.2.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.4-next.2 + +## techdocs-cli-embedded-app@0.2.85-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.12.1-next.2 + - @backstage/plugin-techdocs@1.6.6-next.2 + - @backstage/cli@0.22.10-next.1 + - @backstage/integration-react@1.1.16-next.1 + +## @internal/plugin-catalog-customized@0.0.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/plugin-catalog@1.12.1-next.2 + +## @internal/plugin-todo-list-backend@1.0.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 diff --git a/docs/releases/v1.17.0.md b/docs/releases/v1.17.0.md new file mode 100644 index 0000000000..36414e6608 --- /dev/null +++ b/docs/releases/v1.17.0.md @@ -0,0 +1,72 @@ +--- +id: v1.17.0 +title: v1.17.0 +description: Backstage Release v1.17.0 +--- + +These are the release notes for the v1.17.0 release of [Backstage](https://backstage.io/). + +A huge thanks to the whole team of maintainers and contributors as well as the amazing Backstage Community for the hard work in getting this release developed and done. + +## Highlights + +### Changes to the New Backend System + +For this release we had another look at the new backend system, in particular how well it fits together with the concept of plugin installation without code modification, and we identified a number of breaking changes that we wanted to make. + +We have removed the ability to define options for plugins and modules, and force them to be optional for services. Options have been moved either to static configuration or extension points, and modules now also have the ability to register extension points. + +Service factories are now considered `BackendFeature`s and are installed via `backend.add(...)` rather than via the `services` option, which has been removed. + +The configuration service has also been renamed to `rootConfig` in order to match other root-scoped services and make space for a potential plugin-scoped configuration service in the future. + +The shared environments concept has been removed. We are still interested in having some way to define reusable presets in the new system, but shared environments were too limited. + +We expect these to be the last broad breaking changes to the new backend system, and are likely to start encouraging use of it in the next release. + +### Catalog Telemetry with Processing Tracing + +The Catalog has been instrumented with some simple OpenTelemetry Spans so you can now dig into the processing loop and see it in action using tracing. + +Contributed by [@mikebryant](https://github.com/mikebryant) in [#17534](https://github.com/backstage/backstage/pull/17534) + +### New `each` property for Scaffolder Actions + +You can now define an `each` iterable in the `steps` for a template, which will run a given action for each entry in the iterable. + +Contributed by [@alexef](https://github.com/alexef) in [#18157](https://github.com/backstage/backstage/pull/18157) + +### Updated proxy configuration + +The shape of the proxy plugin configuration has been changed in order to make space for additional keys. Rather than defining the proxy endpoints directly under `proxy`, they should now be defined at `proxy.endpoints` instead. + +### OpenAPI Support for Backend Plugins + +You can now use OpenAPI specs to generate typed routers for your backend plugins with request validation using `createOpenApiRouter()`. There’s been some movement to support this for some of the plugins in the monorepo like `todo`, `search` and `catalog`. + +Contributed by [@sennyeya](https://github.com/sennyeya) in [#17875](https://github.com/backstage/backstage/pull/17875) + +### New plugin: `@backstage/plugin-catalog-backend-module-gcp` + +Allows ingestion of GKE Clusters as Resources into the Catalog. Contributed by [@mclarke47](https://github.com/mclarke47) in [#18759](https://github.com/backstage/backstage/pull/18759) + +## Security Fixes + +This release does not contain any security fixes. + +## Upgrade path + +We recommend that you keep your Backstage project up to date with this latest release. For more guidance on how to upgrade, check out the documentation for [keeping Backstage updated](https://backstage.io/docs/getting-started/keeping-backstage-updated). + +## Links and References + +Below you can find a list of links and references to help you learn about and start using this new release. + +- [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/) +- [GitHub repository](https://github.com/backstage/backstage) +- Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support +- [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.17.0-changelog.md) +- Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) + +Sign up for our [newsletter](https://info.backstage.spotify.com/newsletter_subscribe) if you want to be informed about what is happening in the world of Backstage. diff --git a/microsite/blog/2023-02-15-backend-system-alpha.mdx b/microsite/blog/2023-02-15-backend-system-alpha.mdx index 2aef5596a0..28ff7bdf6b 100644 --- a/microsite/blog/2023-02-15-backend-system-alpha.mdx +++ b/microsite/blog/2023-02-15-backend-system-alpha.mdx @@ -26,7 +26,6 @@ When we set out on this project, we had a few primary goals. First, we intended - Make it easier to create and maintain backend installations. - Align how plugins provide points of customization and how those customizations are installed. - Make it much easier to maintain plugins, in particular keeping the API stable. -- Simplify the process of splitting plugins out into separate deployments with shared environments. - Improve the local development and testing experience. Prioritizing simplicity is often a guiding principle that we use for designs that span multiple ownership roles. We decide on which parts of the system that we think are the most important to have as simple as possible, or, viewed from the opposite end, where in the system we put necessary complexity. In this case, we optimized for keeping the backend setup as simple as possible, followed by modules and plugins, then libraries, and lastly the framework itself. What this guidance means in practice is that when there is complexity that needs to be added to implement a certain feature, we place as much of it as possible within the framework itself, then libraries, plugins and modules, and if absolutely needed, the backend setup. diff --git a/microsite/blog/2023-07-28-frontside-adopter-post.mdx b/microsite/blog/2023-07-28-frontside-adopter-post.mdx new file mode 100644 index 0000000000..c6f3cba403 --- /dev/null +++ b/microsite/blog/2023-07-28-frontside-adopter-post.mdx @@ -0,0 +1,51 @@ +--- +# prettier-ignore +title: "Five common traits of successful Backstage adopters" +author: Taras Mankovski, CXO, Frontside +--- + +![backstage header](assets/2023-07-28/header.png) + +At [Frontside](https://frontside.com/), our goal is to help cloud-native teams create cohesive development experiences. We've been at the Backstage party since the beginning helping companies adopt and extend Backstage to fit the needs of their unique ecosystems. + +Through our experience, we've uncovered five common traits of organizations that have improved developer experience through successful Backstage implementation and adoption. In this blog, we'll dive into these traits with some thoughts on how you can follow their blueprint. + +{/* truncate */} + +## **1) They take a product-centric approach** + +The biggest factor for successful adopters of Backstage is their approach. There is a high correlation of success within organizations that approach building a developer portal like they're building a product. Some organizations will jump straight into solutioning instead of taking their time to identify what the problems are, how they affect users, and how those issues can be addressed. + +The team building out Backstage should assess or work from existing insights on the core challenges that developers are facing in their organization — both qualitative and quantitative data counts here — and connect those issues to a product roadmap with initial use cases and adoption milestones marked. By doing their research in advance, successful orgs have a clear vision of what they want to accomplish with their Backstage instance. They know exactly what goals need to be met and have pressure-tested potential issues and barriers. + +If you've already started your Backstage adoption journey but haven't mapped a Product Requirements Document (or PRD), don't panic! There is always time to do the foundational knowledge-building necessary to deploy something successful. + +## **2) They tie Backstage to a larger platform journey** + +Platform engineering has emerged in response to the growing complexity of cloud-native software architecture. Backstage has a huge role to play in implementing a platform strategy but its part of a larger story. Having buy-in from both higher ups and the teams tasked with platform goals is an essential step in successful Backstage adoption. Without the support at the top, it can be difficult to implement platforming as a priority within your organization. + +And by "the top", we don't necessarily mean your CTO needs to rubber stamp your Backstage POC. But it's important that higher-level Platform goals have been set among VPs and directors with the understanding that a well-constructed developer portal can be the catalyst to achieving not only better developer experience but broader cultural shifts. + +Having this kind of executive buy-in means more than just getting stakeholders on board with a portal build or clearing pathways towards Backstage adoption; it also means ensuring they understand the realities of your organization's journey. + +## **3) They prioritize developer experience** + +Having a dedicated developer experience or DevOps team tasked not only with building out a Backstage instance — but with leading adoption — is another big factor to success. + +Competing platforms are very common at big companies, with many teams doing different things or serving different parts of a business. But developer experience teams usually have a very clear mandate and are often one of the only commonalities between these competing teams. This team should have the bandwidth available to oversee the adoption process from start to finish, and partner with the right folks (research, design, internal comms and marketing) to create an effective adoption plan tailored specifically for a company's needs. + +If you don't have ‌established developer experience resources in place, then the questions the team leading the Backstage work needs to ask are "what are the common problems to be solved at a platform level?" and "once we've proved our initial use cases, how are we internally evangelizing this amongst our competing teams?" + +## **4) They collaborate with other platform teams** + +A developer experience team can not single-handedly transform an organization's development structures, processes, and culture. It requires collaboration with teams responsible for other aspects of the platform. Successful adopters collaborate with other teams to bring them along on the journey of improving developer experience. They use Backstage as an opportunity to foster their inner-source contribution practice by allowing multiple platform teams to contribute plugins to their portal. + +The developer experience team takes on the role of host in that collaborative process. They support other teams in integrating their features into the portal, provide guidance on best practices, and advocate for the needs of developers. + +## **5) They engage, learn, and grow with the community** + +One of the key benefits of building a developer platform based off an open source framework is leveraging the contributions and best practices from the community. The Backstage community is the largest gathering of developer experience practitioners in the world. There are now [thousands of adopters](https://github.com/backstage/backstage/blob/63aa3a65ec05f638ba76c06878d6635194620b34/ADOPTERS.md#L4) with a wealth of experience and best practices to learn from — and they are excited to share! + +By participating in the community, developer experience leaders can learn from their peers at other companies about strategies that work and can keep up with the latest features of the ever-evolving Backstage platform. They're aware of what solutions exist within the open source framework and plugin marketplace as well as what they may need to build in-house. + +In short, successful Backstage adopters engage within the Backstage community and their peer group to find solutions that fit their common challenges as well as their unique needs. diff --git a/microsite/blog/assets/2023-07-28/header.png b/microsite/blog/assets/2023-07-28/header.png new file mode 100644 index 0000000000..69036b6038 Binary files /dev/null and b/microsite/blog/assets/2023-07-28/header.png differ diff --git a/microsite/data/plugins/3scale.yaml b/microsite/data/plugins/3scale.yaml index c190ed7e9e..fa568c17bf 100644 --- a/microsite/data/plugins/3scale.yaml +++ b/microsite/data/plugins/3scale.yaml @@ -5,6 +5,6 @@ authorUrl: https://redhat.com category: Discovery description: Synchronize 3scale content into the Backstage catalog. documentation: https://janus-idp.io/plugins/3scale -iconUrl: http://janus-idp.io/images/plugins/3scale.svg +iconUrl: https://janus-idp.io/images/plugins/3scale.svg npmPackageName: '@janus-idp/backstage-plugin-3scale-backend' addedDate: '2023-05-15' diff --git a/microsite/data/plugins/api-sdk-generator.yaml b/microsite/data/plugins/api-sdk-generator.yaml new file mode 100644 index 0000000000..5553089807 --- /dev/null +++ b/microsite/data/plugins/api-sdk-generator.yaml @@ -0,0 +1,10 @@ +--- +title: API SDK Generator +author: Konfig +authorUrl: https://konfigthis.com/ +category: Development +description: Generate SDKs for your REST API to accelerate integration +documentation: https://github.com/konfig-dev/backstage-plugin-konfig/tree/main/plugins/backstage-plugin-konfig +iconUrl: https://raw.githubusercontent.com/konfig-dev/backstage-plugin-konfig/main/plugins/backstage-plugin-konfig/docs/logo.png +npmPackageName: 'backstage-plugin-konfig' +addedDate: '2023-08-07' diff --git a/microsite/data/plugins/jfrog-artifactory-libs.yaml b/microsite/data/plugins/jfrog-artifactory-libs.yaml new file mode 100644 index 0000000000..22583cbfbd --- /dev/null +++ b/microsite/data/plugins/jfrog-artifactory-libs.yaml @@ -0,0 +1,13 @@ +--- +title: JFrog Artifactory Libs plugin +author: Vity +authorUrl: https://github.com/Vity01 +category: Discovery +description: + frontend plugin provides a simple way to display generated artifact (library) details like + - group, artifact, repository, what is the latest version, and it simply + allows to copy library definition for the package managers. +documentation: https://github.com/Vity01/backstage-jfrog-artifactory-libs +iconUrl: https://raw.githubusercontent.com/Vity01/backstage-jfrog-artifactory-libs/main/doc/artifactory.svg +npmPackageName: 'backstage-plugin-jfrog-artifactory-libs' +addedDate: '2023-08-14' diff --git a/microsite/data/plugins/jfrog-artifactory.yaml b/microsite/data/plugins/jfrog-artifactory.yaml index 279cbc161e..6765fe3d8d 100644 --- a/microsite/data/plugins/jfrog-artifactory.yaml +++ b/microsite/data/plugins/jfrog-artifactory.yaml @@ -5,6 +5,6 @@ authorUrl: https://redhat.com category: Image description: View container image details from JFrog Artifactory in Backstage. documentation: https://janus-idp.io/plugins/jfrog-artifactory -iconUrl: http://janus-idp.io/images/plugins/jfrog-artifactory.svg +iconUrl: https://janus-idp.io/images/plugins/jfrog-artifactory.svg npmPackageName: '@janus-idp/backstage-plugin-jfrog-artifactory' addedDate: '2023-05-15' diff --git a/microsite/data/plugins/keycloak.yaml b/microsite/data/plugins/keycloak.yaml index ea657c74f2..3da89c3d0a 100644 --- a/microsite/data/plugins/keycloak.yaml +++ b/microsite/data/plugins/keycloak.yaml @@ -5,6 +5,6 @@ authorUrl: https://redhat.com category: Authentication/Authorization description: Load users and groups from Keycloak, enabling use of multiple authentication providers to be applied to Backstage entities. documentation: https://janus-idp.io/plugins/keycloak -iconUrl: http://janus-idp.io/images/plugins/keycloak.svg +iconUrl: https://janus-idp.io/images/plugins/keycloak.svg npmPackageName: '@janus-idp/backstage-plugin-keycloak-backend' addedDate: '2023-05-15' diff --git a/microsite/data/plugins/kiali.yaml b/microsite/data/plugins/kiali.yaml new file mode 100644 index 0000000000..a85aa6444a --- /dev/null +++ b/microsite/data/plugins/kiali.yaml @@ -0,0 +1,10 @@ +--- +title: Kiali Service Mesh +author: Red Hat +authorUrl: https://redhat.com +category: Istio +description: Configure, visualize, validate and troubleshoot your mesh with Istio +documentation: https://janus-idp.io/plugins/kiali +iconUrl: https://janus-idp.io/images/plugins/kiali.svg +npmPackageName: '@janus-idp/backstage-plugin-kiali' +addedDate: '2023-07-25' diff --git a/microsite/data/plugins/ocm.yaml b/microsite/data/plugins/ocm.yaml index 9e9b8ff1b7..6cf77ca678 100644 --- a/microsite/data/plugins/ocm.yaml +++ b/microsite/data/plugins/ocm.yaml @@ -5,6 +5,6 @@ authorUrl: https://redhat.com category: Infrastructure description: View clusters from OCM's MultiClusterHub and MultiCluster Engine in Backstage. documentation: https://janus-idp.io/plugins/ocm -iconUrl: http://janus-idp.io/images/plugins/ocm.svg +iconUrl: https://janus-idp.io/images/plugins/ocm.svg npmPackageName: '@janus-idp/backstage-plugin-ocm' addedDate: '2023-05-15' diff --git a/microsite/data/plugins/quay.yaml b/microsite/data/plugins/quay.yaml index e4aeb1ec1a..79ae1c3408 100644 --- a/microsite/data/plugins/quay.yaml +++ b/microsite/data/plugins/quay.yaml @@ -5,6 +5,6 @@ authorUrl: https://redhat.com category: Image description: View container image details from Quay in Backstage. documentation: https://janus-idp.io/plugins/quay -iconUrl: http://janus-idp.io/images/plugins/quay.svg +iconUrl: https://janus-idp.io/images/plugins/quay.svg npmPackageName: '@janus-idp/backstage-plugin-quay' addedDate: '2023-05-15' diff --git a/microsite/data/plugins/scaffolder-backend-ms-teams.yaml b/microsite/data/plugins/scaffolder-backend-ms-teams.yaml new file mode 100644 index 0000000000..6d16b1300b --- /dev/null +++ b/microsite/data/plugins/scaffolder-backend-ms-teams.yaml @@ -0,0 +1,9 @@ +--- +title: Microsoft Teams Scaffolder Actions +author: Gaurav Pandey +authorUrl: https://github.com/grvpandey11 +category: Scaffolder +description: Interact with Microsoft Teams from Scaffolder templates +documentation: https://github.com/grvpandey11/backstage-plugin-scaffolder-backend-module-ms-teams/tree/main#readme +npmPackageName: '@grvpandey11/backstage-plugin-scaffolder-backend-module-ms-teams' +addedDate: '2023-08-11' diff --git a/microsite/data/plugins/scaffolder-backend-slack.yaml b/microsite/data/plugins/scaffolder-backend-slack.yaml new file mode 100644 index 0000000000..dce7b60eb7 --- /dev/null +++ b/microsite/data/plugins/scaffolder-backend-slack.yaml @@ -0,0 +1,10 @@ +--- +title: Slack Scaffolder Actions +author: Drew Hill +authorUrl: https://github.com/arhill05 +category: Scaffolder +description: Interact with Slack from scaffolder templates +documentation: https://github.com/arhill05/backstage-plugin-scaffolder-backend-module-slack#readme +iconUrl: img/Slack-mark-RGB.png +npmPackageName: '@mdude2314/backstage-plugin-scaffolder-backend-module-slack' +addedDate: '2023-08-04' diff --git a/microsite/data/plugins/tekton.yaml b/microsite/data/plugins/tekton.yaml index fa94b89c35..27540a81d3 100644 --- a/microsite/data/plugins/tekton.yaml +++ b/microsite/data/plugins/tekton.yaml @@ -5,6 +5,6 @@ authorUrl: https://redhat.com category: CI/CD description: Easily view Tekton PipelineRun status for your services in Backstage. documentation: https://janus-idp.io/plugins/tekton -iconUrl: http://janus-idp.io/images/plugins/tekton.svg +iconUrl: https://janus-idp.io/images/plugins/tekton.svg npmPackageName: '@janus-idp/backstage-plugin-tekton' addedDate: '2023-05-15' diff --git a/microsite/data/plugins/topology.yaml b/microsite/data/plugins/topology.yaml index 2f26f7c755..9d3b816bd4 100644 --- a/microsite/data/plugins/topology.yaml +++ b/microsite/data/plugins/topology.yaml @@ -5,6 +5,6 @@ authorUrl: https://redhat.com category: Kubernetes description: Visualize the deployment status and related resources of your applications deployed on any Kubernetes cluster. documentation: https://janus-idp.io/plugins/topology -iconUrl: http://janus-idp.io/images/plugins/topology.svg +iconUrl: https://janus-idp.io/images/plugins/topology.svg npmPackageName: '@janus-idp/backstage-plugin-topology' addedDate: '2023-05-15' diff --git a/microsite/docusaurus.config.js b/microsite/docusaurus.config.js index 23438762cc..a55ad01a35 100644 --- a/microsite/docusaurus.config.js +++ b/microsite/docusaurus.config.js @@ -177,7 +177,7 @@ module.exports = { position: 'left', }, { - to: 'docs/releases/v1.16.0', + to: 'docs/releases/v1.17.0', label: 'Releases', position: 'left', }, diff --git a/microsite/sidebars.json b/microsite/sidebars.json index d9178396e8..0e73bd94f2 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -1,6 +1,7 @@ { "releases": { "Release Notes": [ + "releases/v1.17.0", "releases/v1.16.0", "releases/v1.15.0", "releases/v1.14.0", @@ -331,6 +332,7 @@ "deployment/k8s", "deployment/heroku", "deployment/koyeb", + "deployment/flightcontrol", { "type": "category", "label": "Using Backstage Deploy (alpha)", diff --git a/microsite/src/pages/home/_home.tsx b/microsite/src/pages/home/_home.tsx index 07e05068c6..ddcfed7d03 100644 --- a/microsite/src/pages/home/_home.tsx +++ b/microsite/src/pages/home/_home.tsx @@ -32,27 +32,6 @@ const HomePage = () => { -
-
- CFP is now open for BackstageCon 2023 🚀 -
- -
{!hiddenNewsletterBanner && (
Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { FeatureDiscoveryService } from '@backstage/backend-plugin-api/alpha'; +import { ServiceFactory } from '@backstage/backend-plugin-api'; + +// @alpha (undocumented) +export const featureDiscoveryServiceFactory: () => ServiceFactory< + FeatureDiscoveryService, + 'root' +>; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md index 5f452f9e03..0fa1ff376e 100644 --- a/packages/backend-app-api/api-report.md +++ b/packages/backend-app-api/api-report.md @@ -9,7 +9,6 @@ import type { AppConfig } from '@backstage/config'; import { BackendFeature } from '@backstage/backend-plugin-api'; import { CacheClient } from '@backstage/backend-common'; import { Config } from '@backstage/config'; -import { ConfigService } from '@backstage/backend-plugin-api'; import { CorsOptions } from 'cors'; import { ErrorRequestHandler } from 'express'; import { Express as Express_2 } from 'express'; @@ -30,6 +29,7 @@ import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { RemoteConfigSourceOptions } from '@backstage/config-loader'; import { RequestHandler } from 'express'; import { RequestListener } from 'http'; +import { RootConfigService } from '@backstage/backend-plugin-api'; import { RootHttpRouterService } from '@backstage/backend-plugin-api'; import { RootLifecycleService } from '@backstage/backend-plugin-api'; import { RootLoggerService } from '@backstage/backend-plugin-api'; @@ -43,7 +43,7 @@ import { UrlReader } from '@backstage/backend-common'; // @public (undocumented) export interface Backend { // (undocumented) - add(feature: BackendFeature): void; + add(feature: BackendFeature | (() => BackendFeature)): void; // (undocumented) start(): Promise; // (undocumented) @@ -53,17 +53,6 @@ export interface Backend { // @public (undocumented) export const cacheServiceFactory: () => ServiceFactory; -// @public (undocumented) -export interface ConfigFactoryOptions { - argv?: string[]; - remote?: Pick; -} - -// @public (undocumented) -export const configServiceFactory: ( - options?: ConfigFactoryOptions | undefined, -) => ServiceFactory; - // @public (undocumented) export function createConfigSecretEnumerator(options: { logger: LoggerService; @@ -92,7 +81,7 @@ export function createSpecializedBackend( // @public (undocumented) export interface CreateSpecializedBackendOptions { // (undocumented) - services: ServiceFactoryOrFunction[]; + defaultServiceFactories: ServiceFactoryOrFunction[]; } // @public (undocumented) @@ -224,7 +213,7 @@ export interface MiddlewareFactoryErrorOptions { // @public export interface MiddlewareFactoryOptions { // (undocumented) - config: ConfigService; + config: RootConfigService; // (undocumented) logger: LoggerService; } @@ -244,12 +233,23 @@ export function readHelmetOptions(config?: Config): HelmetOptions; // @public export function readHttpServerOptions(config?: Config): HttpServerOptions; +// @public (undocumented) +export interface RootConfigFactoryOptions { + argv?: string[]; + remote?: Pick; +} + +// @public (undocumented) +export const rootConfigServiceFactory: ( + options?: RootConfigFactoryOptions | undefined, +) => ServiceFactory; + // @public (undocumented) export interface RootHttpRouterConfigureContext { // (undocumented) app: Express_2; // (undocumented) - config: ConfigService; + config: RootConfigService; // (undocumented) lifecycle: LifecycleService; // (undocumented) diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index 6f8a5cf9e8..82e32311aa 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -1,17 +1,30 @@ { "name": "@backstage/backend-app-api", "description": "Core API used by Backstage backend apps", - "version": "0.4.6-next.0", + "version": "0.5.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" }, "backstage": { "role": "node-library" }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.ts" + ], + "package.json": [ + "package.json" + ] + } + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -36,6 +49,7 @@ "@backstage/backend-plugin-api": "workspace:^", "@backstage/backend-tasks": "workspace:^", "@backstage/cli-common": "workspace:^", + "@backstage/cli-node": "workspace:^", "@backstage/config": "workspace:^", "@backstage/config-loader": "workspace:^", "@backstage/errors": "workspace:^", @@ -73,6 +87,7 @@ "@types/node-forge": "^1.3.0", "@types/stoppable": "^1.1.0", "http-errors": "^2.0.0", + "mock-fs": "^5.2.0", "supertest": "^6.1.3" }, "files": [ diff --git a/packages/backend-app-api/src/alpha.ts b/packages/backend-app-api/src/alpha.ts new file mode 100644 index 0000000000..a334214738 --- /dev/null +++ b/packages/backend-app-api/src/alpha.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { featureDiscoveryServiceFactory } from './alpha/featureDiscoveryServiceFactory'; diff --git a/packages/backend-app-api/src/alpha/featureDiscoveryServiceFactory.test.ts b/packages/backend-app-api/src/alpha/featureDiscoveryServiceFactory.test.ts new file mode 100644 index 0000000000..5d4b1fc551 --- /dev/null +++ b/packages/backend-app-api/src/alpha/featureDiscoveryServiceFactory.test.ts @@ -0,0 +1,114 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import mockFs from 'mock-fs'; +import { resolve as resolvePath, dirname } from 'path'; +import { startTestBackend, mockServices } from '@backstage/backend-test-utils'; +import { featureDiscoveryServiceFactory } from './featureDiscoveryServiceFactory'; +import { + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; + +const rootDir = dirname(process.argv[1]); + +describe('featureDiscoveryServiceFactory', () => { + beforeEach(() => { + mockFs({ + [rootDir]: { + 'package.json': JSON.stringify({ + name: 'example-app', + dependencies: { + 'detected-plugin': '0.0.0', + 'detected-module': '0.0.0', + }, + }), + }, + [resolvePath(rootDir, 'node_modules/detected-plugin')]: { + 'package.json': JSON.stringify({ + name: 'detected-plugin', + main: 'index.js', + backstage: { + role: 'backend-plugin', + }, + }), + 'index.js': ` + const { createBackendPlugin, coreServices } = require('@backstage/backend-plugin-api'); + exports.detectedPlugin = createBackendPlugin({ + pluginId: 'detected', + register(env) { + env.registerInit({ + deps: { identity: coreServices.identity }, + async init({ identity }) { + identity.getIdentity('detected-plugin'); + }, + }); + }, + }); + `, + }, + [resolvePath(rootDir, 'node_modules/detected-module')]: { + 'package.json': JSON.stringify({ + name: 'detected-module', + main: 'index.js', + backstage: { + role: 'backend-module', + }, + }), + 'index.js': ` + const { createBackendModule, coreServices } = require('@backstage/backend-plugin-api'); + exports.detectedModuleDerp = createBackendModule({ + pluginId: 'detected', + moduleId: 'derp', + register(env) { + env.registerInit({ + deps: { identity: coreServices.identity }, + async init({ identity }) { + identity.getIdentity('detected-module'); + }, + }); + }, + }); + `, + }, + }); + }); + + afterEach(() => { + mockFs.restore(); + }); + + it('should detect plugin and module packages', async () => { + const fn = jest.fn().mockResolvedValue({}); + + await startTestBackend({ + features: [ + createServiceFactory({ + service: coreServices.identity, + deps: {}, + factory: () => ({ getIdentity: fn }), + }), + featureDiscoveryServiceFactory(), + mockServices.rootConfig.factory({ + data: { backend: { packages: 'all' } }, + }), + ], + }); + + expect(fn).toHaveBeenCalledWith('detected-plugin'); + expect(fn).toHaveBeenCalledWith('detected-module'); + }); +}); diff --git a/packages/backend-app-api/src/alpha/featureDiscoveryServiceFactory.ts b/packages/backend-app-api/src/alpha/featureDiscoveryServiceFactory.ts new file mode 100644 index 0000000000..f9ee7edc5f --- /dev/null +++ b/packages/backend-app-api/src/alpha/featureDiscoveryServiceFactory.ts @@ -0,0 +1,129 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BackendFeature, + RootConfigService, + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; +import { + featureDiscoveryServiceRef, + FeatureDiscoveryService, +} from '@backstage/backend-plugin-api/alpha'; +import { resolve as resolvePath, dirname } from 'path'; +import fs from 'fs-extra'; +import { BackstagePackageJson } from '@backstage/cli-node'; + +const LOADED_PACKAGE_ROLES = ['backend-plugin', 'backend-module']; + +/** @internal */ +async function findClosestPackageDir( + searchDir: string, +): Promise { + let path = searchDir; + + // Some confidence check to avoid infinite loop + for (let i = 0; i < 1000; i++) { + const packagePath = resolvePath(path, 'package.json'); + const exists = await fs.pathExists(packagePath); + if (exists) { + return path; + } + + const newPath = dirname(path); + if (newPath === path) { + return undefined; + } + path = newPath; + } + + throw new Error( + `Iteration limit reached when searching for root package.json at ${searchDir}`, + ); +} + +/** @internal */ +class PackageDiscoveryService implements FeatureDiscoveryService { + constructor(private readonly config: RootConfigService) {} + + async getBackendFeatures(): Promise<{ features: Array }> { + if (this.config.getOptionalString('backend.packages') !== 'all') { + return { features: [] }; + } + + const packageDir = await findClosestPackageDir(process.argv[1]); + if (!packageDir) { + throw new Error('Package discovery failed to find package.json'); + } + const { dependencies } = require(resolvePath( + packageDir, + 'package.json', + )) as BackstagePackageJson; + const dependencyNames = Object.keys(dependencies || {}); + + const features: BackendFeature[] = []; + + for (const name of dependencyNames) { + const depPkg = require(require.resolve(`${name}/package.json`, { + paths: [packageDir], + })) as BackstagePackageJson; + if (!LOADED_PACKAGE_ROLES.includes(depPkg?.backstage?.role ?? '')) { + continue; + } + const depModule = require(require.resolve(name, { paths: [packageDir] })); + for (const exportValue of Object.values(depModule)) { + if (isBackendFeature(exportValue)) { + features.push(exportValue); + } + if (isBackendFeatureFactory(exportValue)) { + features.push(exportValue()); + } + } + } + + return { features }; + } +} + +/** @alpha */ +export const featureDiscoveryServiceFactory = createServiceFactory({ + service: featureDiscoveryServiceRef, + deps: { + config: coreServices.rootConfig, + }, + factory({ config }) { + return new PackageDiscoveryService(config); + }, +}); + +function isBackendFeature(value: unknown): value is BackendFeature { + return ( + !!value && + typeof value === 'object' && + (value as BackendFeature).$$type === '@backstage/BackendFeature' + ); +} + +function isBackendFeatureFactory( + value: unknown, +): value is () => BackendFeature { + return ( + !!value && + typeof value === 'function' && + (value as any).$$type === '@backstage/BackendFeatureFactory' + ); +} diff --git a/packages/backend-app-api/src/config/ObservableConfigProxy.ts b/packages/backend-app-api/src/config/ObservableConfigProxy.ts index dd3334c9a5..8c8d3b553f 100644 --- a/packages/backend-app-api/src/config/ObservableConfigProxy.ts +++ b/packages/backend-app-api/src/config/ObservableConfigProxy.ts @@ -14,12 +14,11 @@ * limitations under the License. */ -import { ConfigService } from '@backstage/backend-plugin-api'; -import { ConfigReader } from '@backstage/config'; +import { Config, ConfigReader } from '@backstage/config'; import { JsonValue } from '@backstage/types'; -export class ObservableConfigProxy implements ConfigService { - private config: ConfigService = new ConfigReader({}); +export class ObservableConfigProxy implements Config { + private config: Config = new ConfigReader({}); private readonly subscribers: (() => void)[] = []; @@ -32,7 +31,7 @@ export class ObservableConfigProxy implements ConfigService { } } - setConfig(config: ConfigService) { + setConfig(config: Config) { if (this.parent) { throw new Error('immutable'); } @@ -62,9 +61,9 @@ export class ObservableConfigProxy implements ConfigService { }; } - private select(required: true): ConfigService; - private select(required: false): ConfigService | undefined; - private select(required: boolean): ConfigService | undefined { + private select(required: true): Config; + private select(required: false): Config | undefined; + private select(required: boolean): Config | undefined { if (this.parent && this.parentKey) { if (required) { return this.parent.select(true).getConfig(this.parentKey); @@ -87,19 +86,19 @@ export class ObservableConfigProxy implements ConfigService { getOptional(key?: string): T | undefined { return this.select(false)?.getOptional(key); } - getConfig(key: string): ConfigService { + getConfig(key: string): Config { return new ObservableConfigProxy(this, key); } - getOptionalConfig(key: string): ConfigService | undefined { + getOptionalConfig(key: string): Config | undefined { if (this.select(false)?.has(key)) { return new ObservableConfigProxy(this, key); } return undefined; } - getConfigArray(key: string): ConfigService[] { + getConfigArray(key: string): Config[] { return this.select(true).getConfigArray(key); } - getOptionalConfigArray(key: string): ConfigService[] | undefined { + getOptionalConfigArray(key: string): Config[] | undefined { return this.select(false)?.getOptionalConfigArray(key); } getNumber(key: string): number { diff --git a/packages/backend-app-api/src/http/MiddlewareFactory.ts b/packages/backend-app-api/src/http/MiddlewareFactory.ts index 774e784d1d..bd78d77045 100644 --- a/packages/backend-app-api/src/http/MiddlewareFactory.ts +++ b/packages/backend-app-api/src/http/MiddlewareFactory.ts @@ -14,7 +14,10 @@ * limitations under the License. */ -import { ConfigService, LoggerService } from '@backstage/backend-plugin-api'; +import { + RootConfigService, + LoggerService, +} from '@backstage/backend-plugin-api'; import { Request, Response, @@ -47,7 +50,7 @@ import { NotImplementedError } from '@backstage/errors'; * @public */ export interface MiddlewareFactoryOptions { - config: ConfigService; + config: RootConfigService; logger: LoggerService; } @@ -78,7 +81,7 @@ export interface MiddlewareFactoryErrorOptions { * @public */ export class MiddlewareFactory { - #config: ConfigService; + #config: RootConfigService; #logger: LoggerService; /** diff --git a/packages/backend-app-api/src/lib/DependencyGraph.test.ts b/packages/backend-app-api/src/lib/DependencyGraph.test.ts new file mode 100644 index 0000000000..65efac0252 --- /dev/null +++ b/packages/backend-app-api/src/lib/DependencyGraph.test.ts @@ -0,0 +1,245 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DependencyGraph } from './DependencyGraph'; + +describe('DependencyGraph', () => { + it('should be empty', async () => { + const empty = DependencyGraph.fromMap({}); + expect(empty.findUnsatisfiedDeps()).toEqual([]); + expect(empty.detectCircularDependency()).toBeUndefined(); + await expect( + empty.parallelTopologicalTraversal(async id => id), + ).resolves.toEqual([]); + }); + + describe('detectCircularDependency', () => { + it('should return undefined with not deps', () => { + expect( + DependencyGraph.fromMap({ + 1: {}, + 2: {}, + 3: {}, + 4: {}, + }).detectCircularDependency(), + ).toBeUndefined(); + }); + + it('should return undefined with no circular deps', async () => { + expect( + DependencyGraph.fromMap({ + 1: { provides: ['a'] }, + 2: { consumes: ['a'], provides: ['b', 'c'] }, + 3: { consumes: ['b'] }, + 4: { consumes: ['c'] }, + }).detectCircularDependency(), + ).toBeUndefined(); + }); + + it('should detect an immediate circular dep', async () => { + expect( + DependencyGraph.fromMap({ + 1: { provides: ['a'], consumes: ['a'] }, + }).detectCircularDependency(), + ).toEqual(['1', '1']); + }); + + it('should detect a small circular dep', async () => { + expect( + DependencyGraph.fromMap({ + 1: { provides: ['a'], consumes: ['b'] }, + 2: { provides: ['b'], consumes: ['a'] }, + }).detectCircularDependency(), + ).toEqual(['1', '2', '1']); + }); + + it('should detect a larger distant circular dep', async () => { + expect( + DependencyGraph.fromMap({ + 1: { provides: ['a'] }, + 2: { provides: ['b'], consumes: ['a', 'e'] }, + 3: { provides: ['c'], consumes: ['b'] }, + 4: { provides: ['d', 'e'], consumes: ['c', 'a'] }, + }).detectCircularDependency(), + ).toEqual(['2', '3', '4', '2']); + }); + }); + + describe('findUnsatisfiedDeps', () => { + it('should return nothing with no deps', () => { + expect( + DependencyGraph.fromMap({ + 1: {}, + 2: {}, + 3: {}, + 4: {}, + }).findUnsatisfiedDeps(), + ).toEqual([]); + }); + + it('should return nothing when all deps are satisfied', async () => { + expect( + DependencyGraph.fromMap({ + 1: { provides: ['a'] }, + 2: { consumes: ['a'], provides: ['b', 'c'] }, + 3: { consumes: ['b'] }, + 4: { consumes: ['c'] }, + }).findUnsatisfiedDeps(), + ).toEqual([]); + }); + + it('should find a single unsatisfied dep', async () => { + expect( + DependencyGraph.fromMap({ + 1: { consumes: ['a'] }, + }).findUnsatisfiedDeps(), + ).toEqual([{ value: '1', unsatisfied: ['a'] }]); + }); + + it('should handle circular dependencies', async () => { + expect( + DependencyGraph.fromMap({ + 1: { consumes: ['a'], provides: ['a'] }, + }).findUnsatisfiedDeps(), + ).toEqual([]); + + expect( + DependencyGraph.fromMap({ + 1: { consumes: ['a'], provides: ['b'] }, + 2: { consumes: ['b'], provides: ['a'] }, + }).findUnsatisfiedDeps(), + ).toEqual([]); + + expect( + DependencyGraph.fromMap({ + 1: { consumes: ['a'] }, + 2: { consumes: ['b'], provides: ['c'] }, + 3: { consumes: ['c'], provides: ['a', 'b'] }, + }).findUnsatisfiedDeps(), + ).toEqual([]); + }); + + it('should find multiple unsatisfied deps for one node', async () => { + expect( + DependencyGraph.fromMap({ + 1: { provides: ['a'], consumes: ['b'] }, + 2: { provides: ['b'], consumes: ['a', 'd', 'e'] }, + }).findUnsatisfiedDeps(), + ).toEqual([{ value: '2', unsatisfied: ['d', 'e'] }]); + }); + + it('should find multiple unsatisfied deps for multiple nodes', async () => { + expect( + DependencyGraph.fromMap({ + 1: { provides: ['a'] }, + 2: { provides: ['b'], consumes: ['a', 'd', 'e'] }, + 3: { provides: [], consumes: ['b'] }, + 4: { provides: [], consumes: ['c', 'a'] }, + }).findUnsatisfiedDeps(), + ).toEqual([ + { value: '2', unsatisfied: ['d', 'e'] }, + { value: '4', unsatisfied: ['c'] }, + ]); + }); + }); + + describe('parallelTopologicalTraversal', () => { + it('should traverse with no deps', async () => { + await expect( + DependencyGraph.fromMap({ + 1: {}, + 2: {}, + 3: {}, + 4: {}, + }).parallelTopologicalTraversal(async id => id), + ).resolves.toEqual(['1', '2', '3', '4']); + }); + + it('should traverse with a few deps', async () => { + await expect( + DependencyGraph.fromMap({ + 1: { provides: ['a'] }, + 2: { consumes: ['a'], provides: ['b', 'c'] }, + 3: { consumes: ['b'] }, + 4: { consumes: ['c'] }, + }).parallelTopologicalTraversal(async id => id), + ).resolves.toEqual(['1', '2', '3', '4']); + }); + + it('should traverse in reverse', async () => { + await expect( + DependencyGraph.fromMap({ + 1: { consumes: ['c'] }, + 2: { provides: ['c'], consumes: ['b'] }, + 3: { provides: ['b'], consumes: ['a'] }, + 4: { provides: ['a'] }, + }).parallelTopologicalTraversal(async id => id), + ).resolves.toEqual(['4', '3', '2', '1']); + }); + + it('should execute in parallel', async () => { + await expect( + DependencyGraph.fromMap({ + 1: { provides: ['a'] }, + 2: { provides: ['b'], consumes: ['a'] }, + 3: { provides: ['c'], consumes: ['a'] }, + 4: { consumes: ['b'] }, + 5: { consumes: ['c'] }, + }).parallelTopologicalTraversal(async id => id), + ).resolves.toEqual(['1', '2', '3', '4', '5']); + + // Same as above, but with 2 being delayed + await expect( + DependencyGraph.fromMap({ + 1: { provides: ['a'] }, + 2: { provides: ['b'], consumes: ['a'] }, + 3: { provides: ['c'], consumes: ['a'] }, + 4: { consumes: ['b'] }, + 5: { consumes: ['c'] }, + }).parallelTopologicalTraversal(async id => { + // When delaying 2 we expect 3 and 5 to complete before 2 and 4 + if (id === '2') { + await new Promise(resolve => setTimeout(resolve, 100)); + } + return id; + }), + ).resolves.toEqual(['1', '3', '5', '2', '4']); + }); + + it('should detect circular dependencies', async () => { + await expect( + DependencyGraph.fromMap({ + 1: { provides: ['a'], consumes: ['a'] }, + }).parallelTopologicalTraversal(async id => id), + ).rejects.toThrow('Circular dependency detected'); + + await expect( + DependencyGraph.fromMap({ + 1: { provides: ['a'], consumes: ['b'] }, + 2: { provides: ['b'], consumes: ['a'] }, + }).parallelTopologicalTraversal(async id => id), + ).rejects.toThrow('Circular dependency detected'); + + await expect( + DependencyGraph.fromMap({ + 1: { provides: ['a'] }, + 2: { provides: ['c'], consumes: ['a', 'b'] }, + 3: { provides: ['b'], consumes: ['a', 'c'] }, + }).parallelTopologicalTraversal(async id => id), + ).rejects.toThrow('Circular dependency detected'); + }); + }); +}); diff --git a/packages/backend-app-api/src/lib/DependencyGraph.ts b/packages/backend-app-api/src/lib/DependencyGraph.ts new file mode 100644 index 0000000000..8fd679f555 --- /dev/null +++ b/packages/backend-app-api/src/lib/DependencyGraph.ts @@ -0,0 +1,197 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +interface NodeInput { + value: T; + consumes?: Iterable; + provides?: Iterable; +} + +/** @internal */ +class Node { + static from(input: NodeInput) { + return new Node( + input.value, + input.consumes ? new Set(input.consumes) : new Set(), + input.provides ? new Set(input.provides) : new Set(), + ); + } + + private constructor( + readonly value: T, + readonly consumes: Set, + readonly provides: Set, + ) {} +} + +/** + * Internal helper to help validate and traverse a dependency graph. + * @internal + */ +export class DependencyGraph { + static fromMap( + nodes: Record, 'value'>>, + ): DependencyGraph { + return this.fromIterable( + Object.entries(nodes).map(([key, node]) => ({ + value: String(key), + ...node, + })), + ); + } + + static fromIterable( + nodeInputs: Iterable>, + ): DependencyGraph { + const nodes = new Array>(); + for (const nodeInput of nodeInputs) { + nodes.push(Node.from(nodeInput)); + } + + return new DependencyGraph(nodes); + } + + #nodes: Array>; + #allProvided: Set; + + private constructor(nodes: Array>) { + this.#nodes = nodes; + this.#allProvided = new Set(); + + for (const node of this.#nodes.values()) { + for (const produced of node.provides) { + this.#allProvided.add(produced); + } + } + } + + // Find all nodes that consume dependencies that are not provided by any other node + findUnsatisfiedDeps(): Array<{ value: T; unsatisfied: string[] }> { + const unsatisfiedDependencies = []; + for (const node of this.#nodes.values()) { + const unsatisfied = Array.from(node.consumes).filter( + id => !this.#allProvided.has(id), + ); + if (unsatisfied.length > 0) { + unsatisfiedDependencies.push({ value: node.value, unsatisfied }); + } + } + return unsatisfiedDependencies; + } + + // Detect circular dependencies within the graph, returning the path of nodes that + // form a cycle, with the same node as the first and last element of the array. + detectCircularDependency(): T[] | undefined { + for (const startNode of this.#nodes) { + const visited = new Set>(); + const stack = new Array<[node: Node, path: T[]]>([ + startNode, + [startNode.value], + ]); + + while (stack.length > 0) { + const [node, path] = stack.pop()!; + if (visited.has(node)) { + continue; + } + visited.add(node); + for (const produced of node.provides) { + const consumerNodes = this.#nodes.filter(other => + other.consumes.has(produced), + ); + for (const consumer of consumerNodes) { + if (consumer === startNode) { + return [...path, startNode.value]; + } + if (!visited.has(consumer)) { + stack.push([consumer, [...path, consumer.value]]); + } + } + } + } + } + return undefined; + } + + /** + * Traverses the dependency graph in topological order, calling the provided + * function for each node and waiting for it to resolve. + * + * The nodes are traversed in parallel, but in such a way that no node is + * visited before all of its dependencies. + * + * Dependencies of nodes that are not produced by any other nodes will be ignored. + */ + async parallelTopologicalTraversal( + fn: (value: T) => Promise, + ): Promise { + const allProvided = this.#allProvided; + const producedSoFar = new Set(); + const waiting = new Set(this.#nodes.values()); + const visited = new Set>(); + const results = new Array(); + let inFlight = 0; // Keep track of how many callbacks are in flight, so that we know if we got stuck + + // Find all nodes that have no dependencies that have not already been produced by visited nodes + async function processMoreNodes() { + if (waiting.size === 0) { + return; + } + const nodesToProcess = []; + for (const node of waiting) { + let ready = true; + for (const consumed of node.consumes) { + if (allProvided.has(consumed) && !producedSoFar.has(consumed)) { + ready = false; + continue; + } + } + if (ready) { + nodesToProcess.push(node); + } + } + + for (const node of nodesToProcess) { + waiting.delete(node); + } + + if (nodesToProcess.length === 0 && inFlight === 0) { + // We expect the caller to check for circular dependencies before + // traversal, so this error should never happen + throw new Error('Circular dependency detected'); + } + + await Promise.all(nodesToProcess.map(processNode)); + } + + // Process an individual node, and then add its produced dependencies to the set of available products + async function processNode(node: Node) { + visited.add(node); + inFlight += 1; + + const result = await fn(node.value); + results.push(result); + + node.provides.forEach(produced => producedSoFar.add(produced)); + inFlight -= 1; + await processMoreNodes(); + } + + await processMoreNodes(); + + return results; + } +} diff --git a/packages/backend-app-api/src/services/implementations/cache/cacheServiceFactory.ts b/packages/backend-app-api/src/services/implementations/cache/cacheServiceFactory.ts index 2208249280..b91356a13a 100644 --- a/packages/backend-app-api/src/services/implementations/cache/cacheServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/cache/cacheServiceFactory.ts @@ -24,7 +24,7 @@ import { export const cacheServiceFactory = createServiceFactory({ service: coreServices.cache, deps: { - config: coreServices.config, + config: coreServices.rootConfig, plugin: coreServices.pluginMetadata, }, async createRootContext({ config }) { diff --git a/packages/backend-app-api/src/services/implementations/config/index.ts b/packages/backend-app-api/src/services/implementations/config/index.ts index 690f1e2d36..1775ef2efc 100644 --- a/packages/backend-app-api/src/services/implementations/config/index.ts +++ b/packages/backend-app-api/src/services/implementations/config/index.ts @@ -14,5 +14,5 @@ * limitations under the License. */ -export { configServiceFactory } from './configServiceFactory'; -export type { ConfigFactoryOptions } from './configServiceFactory'; +export { rootConfigServiceFactory } from './rootConfigServiceFactory'; +export type { RootConfigFactoryOptions } from './rootConfigServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/config/configServiceFactory.ts b/packages/backend-app-api/src/services/implementations/config/rootConfigServiceFactory.ts similarity index 87% rename from packages/backend-app-api/src/services/implementations/config/configServiceFactory.ts rename to packages/backend-app-api/src/services/implementations/config/rootConfigServiceFactory.ts index d3b29ce545..1fa8d792ad 100644 --- a/packages/backend-app-api/src/services/implementations/config/configServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/config/rootConfigServiceFactory.ts @@ -24,7 +24,7 @@ import { } from '@backstage/config-loader'; /** @public */ -export interface ConfigFactoryOptions { +export interface RootConfigFactoryOptions { /** * Process arguments to use instead of the default `process.argv()`. */ @@ -37,9 +37,9 @@ export interface ConfigFactoryOptions { } /** @public */ -export const configServiceFactory = createServiceFactory( - (options?: ConfigFactoryOptions) => ({ - service: coreServices.config, +export const rootConfigServiceFactory = createServiceFactory( + (options?: RootConfigFactoryOptions) => ({ + service: coreServices.rootConfig, deps: {}, async factory() { const source = ConfigSources.default({ diff --git a/packages/backend-app-api/src/services/implementations/database/databaseServiceFactory.ts b/packages/backend-app-api/src/services/implementations/database/databaseServiceFactory.ts index 05e2f1deb9..139609b6c1 100644 --- a/packages/backend-app-api/src/services/implementations/database/databaseServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/database/databaseServiceFactory.ts @@ -25,7 +25,7 @@ import { ConfigReader } from '@backstage/config'; export const databaseServiceFactory = createServiceFactory({ service: coreServices.database, deps: { - config: coreServices.config, + config: coreServices.rootConfig, lifecycle: coreServices.lifecycle, pluginMetadata: coreServices.pluginMetadata, }, diff --git a/packages/backend-app-api/src/services/implementations/discovery/discoveryServiceFactory.ts b/packages/backend-app-api/src/services/implementations/discovery/discoveryServiceFactory.ts index 7e2bb6b21e..6bdc4b4856 100644 --- a/packages/backend-app-api/src/services/implementations/discovery/discoveryServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/discovery/discoveryServiceFactory.ts @@ -24,7 +24,7 @@ import { export const discoveryServiceFactory = createServiceFactory({ service: coreServices.discovery, deps: { - config: coreServices.config, + config: coreServices.rootConfig, }, async factory({ config }) { return HostDiscovery.fromConfig(config); diff --git a/packages/backend-app-api/src/services/implementations/permissions/permissionsServiceFactory.ts b/packages/backend-app-api/src/services/implementations/permissions/permissionsServiceFactory.ts index 38cba73eda..3e5b7da9dd 100644 --- a/packages/backend-app-api/src/services/implementations/permissions/permissionsServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/permissions/permissionsServiceFactory.ts @@ -24,7 +24,7 @@ import { ServerPermissionClient } from '@backstage/plugin-permission-node'; export const permissionsServiceFactory = createServiceFactory({ service: coreServices.permissions, deps: { - config: coreServices.config, + config: coreServices.rootConfig, discovery: coreServices.discovery, tokenManager: coreServices.tokenManager, }, diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterServiceFactory.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterServiceFactory.ts index 5eaf8aa152..4c410e25ea 100644 --- a/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterServiceFactory.ts @@ -15,7 +15,7 @@ */ import { - ConfigService, + RootConfigService, coreServices, createServiceFactory, LifecycleService, @@ -36,7 +36,7 @@ export interface RootHttpRouterConfigureContext { app: Express; middleware: MiddlewareFactory; routes: RequestHandler; - config: ConfigService; + config: RootConfigService; logger: LoggerService; lifecycle: LifecycleService; } @@ -70,7 +70,7 @@ export const rootHttpRouterServiceFactory = createServiceFactory( (options?: RootHttpRouterFactoryOptions) => ({ service: coreServices.rootHttpRouter, deps: { - config: coreServices.config, + config: coreServices.rootConfig, rootLogger: coreServices.rootLogger, lifecycle: coreServices.rootLifecycle, }, diff --git a/packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerServiceFactory.ts b/packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerServiceFactory.ts index 11bbd58050..bd45df383f 100644 --- a/packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerServiceFactory.ts @@ -26,7 +26,7 @@ import { createConfigSecretEnumerator } from '../../../config'; export const rootLoggerServiceFactory = createServiceFactory({ service: coreServices.rootLogger, deps: { - config: coreServices.config, + config: coreServices.rootConfig, }, async factory({ config }) { const logger = WinstonLogger.create({ diff --git a/packages/backend-app-api/src/services/implementations/scheduler/schedulerServiceFactory.test.ts b/packages/backend-app-api/src/services/implementations/scheduler/schedulerServiceFactory.test.ts index 7af9de44da..d771c5dd11 100644 --- a/packages/backend-app-api/src/services/implementations/scheduler/schedulerServiceFactory.test.ts +++ b/packages/backend-app-api/src/services/implementations/scheduler/schedulerServiceFactory.test.ts @@ -61,8 +61,7 @@ describe('schedulerFactory', () => { }); await startTestBackend({ - features: [plugin()], - services: [subject], + features: [plugin(), subject], }); }); }); diff --git a/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.ts b/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.ts index b3726176b6..7417c18e23 100644 --- a/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.ts @@ -24,7 +24,7 @@ import { ServerTokenManager } from '@backstage/backend-common'; export const tokenManagerServiceFactory = createServiceFactory({ service: coreServices.tokenManager, deps: { - config: coreServices.config, + config: coreServices.rootConfig, logger: coreServices.rootLogger, }, createRootContext({ config, logger }) { diff --git a/packages/backend-app-api/src/services/implementations/urlReader/urlReaderServiceFactory.ts b/packages/backend-app-api/src/services/implementations/urlReader/urlReaderServiceFactory.ts index 83e594aa0b..6da71ac0fc 100644 --- a/packages/backend-app-api/src/services/implementations/urlReader/urlReaderServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/urlReader/urlReaderServiceFactory.ts @@ -24,7 +24,7 @@ import { export const urlReaderServiceFactory = createServiceFactory({ service: coreServices.urlReader, deps: { - config: coreServices.config, + config: coreServices.rootConfig, logger: coreServices.logger, }, async factory({ config, logger }) { diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.test.ts b/packages/backend-app-api/src/wiring/BackendInitializer.test.ts index b05194f594..791b9b1c3a 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.test.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.test.ts @@ -20,10 +20,15 @@ import { coreServices, createBackendPlugin, createBackendModule, + createExtensionPoint, } from '@backstage/backend-plugin-api'; import { BackendInitializer } from './BackendInitializer'; -import { ServiceRegistry } from './ServiceRegistry'; -import { rootLifecycleServiceFactory } from '../services/implementations'; + +import { + lifecycleServiceFactory, + loggerServiceFactory, + rootLifecycleServiceFactory, +} from '../services/implementations'; const rootRef = createServiceRef<{ x: number }>({ id: '1', @@ -44,12 +49,23 @@ class MockLogger { } } +const baseFactories = [ + lifecycleServiceFactory(), + rootLifecycleServiceFactory(), + createServiceFactory({ + service: coreServices.rootLogger, + deps: {}, + factory: () => new MockLogger(), + })(), + loggerServiceFactory(), +]; + describe('BackendInitializer', () => { it('should initialize root scoped services', async () => { const rootFactory = jest.fn(); const pluginFactory = jest.fn(); - const registry = new ServiceRegistry([ + const services = [ createServiceFactory({ service: rootRef, deps: {}, @@ -66,17 +82,76 @@ describe('BackendInitializer', () => { deps: {}, factory: () => new MockLogger(), })(), - ]); + ]; - const init = new BackendInitializer(registry); + const init = new BackendInitializer(services); await init.start(); expect(rootFactory).toHaveBeenCalled(); expect(pluginFactory).not.toHaveBeenCalled(); }); + it('should initialize modules with extension points', async () => { + expect.assertions(3); + + const extensionPoint = createExtensionPoint<{ values: string[] }>({ + id: 'a', + }); + const init = new BackendInitializer(baseFactories); + + init.add( + createBackendModule({ + pluginId: 'test', + moduleId: 'modA', + register(reg) { + reg.registerInit({ + deps: { extension: extensionPoint }, + async init({ extension }) { + expect(extension.values).toEqual(['b']); + extension.values.push('a'); + }, + }); + }, + })(), + ); + + init.add( + createBackendModule({ + pluginId: 'test', + moduleId: 'modB', + register(reg) { + const values = ['b']; + reg.registerExtensionPoint(extensionPoint, { values }); + reg.registerInit({ + deps: {}, + async init() { + expect(values).toEqual(['b', 'a', 'c']); + }, + }); + }, + })(), + ); + + init.add( + createBackendModule({ + pluginId: 'test', + moduleId: 'modC', + register(reg) { + reg.registerInit({ + deps: { extension: extensionPoint }, + async init({ extension }) { + expect(extension.values).toEqual(['b', 'a']); + extension.values.push('c'); + }, + }); + }, + })(), + ); + await init.start(); + }); + it('should forward errors when plugins fail to start', async () => { - const init = new BackendInitializer(new ServiceRegistry([])); + const init = new BackendInitializer([]); init.add( createBackendPlugin({ pluginId: 'test', @@ -96,7 +171,7 @@ describe('BackendInitializer', () => { }); it('should forward errors when modules fail to start', async () => { - const init = new BackendInitializer(new ServiceRegistry([])); + const init = new BackendInitializer([]); init.add( createBackendModule({ pluginId: 'test', @@ -117,7 +192,7 @@ describe('BackendInitializer', () => { }); it('should reject duplicate plugins', async () => { - const init = new BackendInitializer(new ServiceRegistry([])); + const init = new BackendInitializer([]); init.add( createBackendPlugin({ pluginId: 'test', @@ -146,7 +221,7 @@ describe('BackendInitializer', () => { }); it('should reject duplicate modules', async () => { - const init = new BackendInitializer(new ServiceRegistry([])); + const init = new BackendInitializer([]); init.add( createBackendModule({ pluginId: 'test', @@ -175,4 +250,78 @@ describe('BackendInitializer', () => { "Module 'mod' for plugin 'test' is already registered", ); }); + + it('should reject modules with circular dependencies', async () => { + const extA = createExtensionPoint({ id: 'a' }); + const extB = createExtensionPoint({ id: 'b' }); + const init = new BackendInitializer([ + rootLifecycleServiceFactory(), + createServiceFactory({ + service: coreServices.rootLogger, + deps: {}, + factory: () => new MockLogger(), + })(), + ]); + init.add( + createBackendModule({ + pluginId: 'test', + moduleId: 'modA', + register(reg) { + reg.registerExtensionPoint(extA, 'a'); + reg.registerInit({ + deps: { ext: extB }, + async init() {}, + }); + }, + })(), + ); + init.add( + createBackendModule({ + pluginId: 'test', + moduleId: 'modB', + register(reg) { + reg.registerExtensionPoint(extB, 'b'); + reg.registerInit({ + deps: { ext: extA }, + async init() {}, + }); + }, + })(), + ); + await expect(init.start()).rejects.toThrow( + "Circular dependency detected for modules of plugin 'test', 'modA' -> 'modB' -> 'modA'", + ); + }); + + it('should reject modules that depend on extension points other plugins', async () => { + const init = new BackendInitializer(baseFactories); + const extA = createExtensionPoint({ id: 'a' }); + init.add( + createBackendPlugin({ + pluginId: 'testA', + register(reg) { + reg.registerExtensionPoint(extA, 'a'); + reg.registerInit({ + deps: {}, + async init() {}, + }); + }, + })(), + ); + init.add( + createBackendModule({ + pluginId: 'testB', + moduleId: 'mod', + register(reg) { + reg.registerInit({ + deps: { ext: extA }, + async init() {}, + }); + }, + })(), + ); + await expect(init.start()).rejects.toThrow( + "Extension point registered for plugin 'testA' may not be used by module for plugin 'testB'", + ); + }); }); diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.ts b/packages/backend-app-api/src/wiring/BackendInitializer.ts index 8c2b75e887..93d2f6942a 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.ts @@ -19,6 +19,7 @@ import { ExtensionPoint, coreServices, ServiceRef, + ServiceFactory, } from '@backstage/backend-plugin-api'; import { BackendLifecycleImpl } from '../services/implementations/rootLifecycle/rootLifecycleServiceFactory'; import { BackendPluginLifecycleImpl } from '../services/implementations/lifecycle/lifecycleServiceFactory'; @@ -26,7 +27,10 @@ import { EnumerableServiceHolder, ServiceOrExtensionPoint } from './types'; // Direct internal import to avoid duplication // eslint-disable-next-line @backstage/no-forbidden-package-imports import { InternalBackendFeature } from '@backstage/backend-plugin-api/src/wiring/types'; -import { ForwardedError } from '@backstage/errors'; +import { ForwardedError, ConflictError } from '@backstage/errors'; +import { featureDiscoveryServiceRef } from '@backstage/backend-plugin-api/alpha'; +import { DependencyGraph } from '../lib/DependencyGraph'; +import { ServiceRegistry } from './ServiceRegistry'; export interface BackendRegisterInit { consumes: Set; @@ -40,11 +44,16 @@ export interface BackendRegisterInit { export class BackendInitializer { #startPromise?: Promise; #features = new Array(); - #extensionPoints = new Map, unknown>(); - #serviceHolder: EnumerableServiceHolder; + #extensionPoints = new Map< + ExtensionPoint, + { impl: unknown; pluginId: string } + >(); + #serviceHolder: EnumerableServiceHolder | undefined; + #providedServiceFactories = new Array(); + #defaultApiFactories: ServiceFactory[]; - constructor(serviceHolder: EnumerableServiceHolder) { - this.#serviceHolder = serviceHolder; + constructor(defaultApiFactories: ServiceFactory[]) { + this.#defaultApiFactories = defaultApiFactories; } async #getInitDeps( @@ -55,13 +64,16 @@ export class BackendInitializer { const missingRefs = new Set(); for (const [name, ref] of Object.entries(deps)) { - const extensionPoint = this.#extensionPoints.get( - ref as ExtensionPoint, - ); - if (extensionPoint) { - result.set(name, extensionPoint); + const ep = this.#extensionPoints.get(ref as ExtensionPoint); + if (ep) { + if (ep.pluginId !== pluginId) { + throw new Error( + `Extension point registered for plugin '${ep.pluginId}' may not be used by module for plugin '${pluginId}'`, + ); + } + result.set(name, ep.impl); } else { - const impl = await this.#serviceHolder.get( + const impl = await this.#serviceHolder!.get( ref as ServiceRef, pluginId, ); @@ -87,18 +99,44 @@ export class BackendInitializer { if (this.#startPromise) { throw new Error('feature can not be added after the backend has started'); } + this.#addFeature(feature); + } + + #addFeature(feature: BackendFeature) { if (feature.$$type !== '@backstage/BackendFeature') { throw new Error( `Failed to add feature, invalid type '${feature.$$type}'`, ); } - const internalFeature = feature as InternalBackendFeature; - if (internalFeature.version !== 'v1') { + + if (isServiceFactory(feature)) { + if (feature.service.id === coreServices.pluginMetadata.id) { + throw new Error( + `The ${coreServices.pluginMetadata.id} service cannot be overridden`, + ); + } + if ( + this.#providedServiceFactories.find( + sf => sf.service.id === feature.service.id, + ) + ) { + throw new Error( + `Duplicate service implementations provided for ${feature.service.id}`, + ); + } + this.#providedServiceFactories.push(feature); + } else if (isInternalBackendFeature(feature)) { + if (feature.version !== 'v1') { + throw new Error( + `Failed to add feature, invalid version '${feature.version}'`, + ); + } + this.#features.push(feature); + } else { throw new Error( - `Failed to add feature, invalid version '${internalFeature.version}'`, + `Failed to add feature, invalid feature ${JSON.stringify(feature)}`, ); } - this.#features.push(internalFeature); } async start(): Promise { @@ -129,6 +167,23 @@ export class BackendInitializer { } async #doStart(): Promise { + this.#serviceHolder = new ServiceRegistry([ + ...this.#defaultApiFactories, + ...this.#providedServiceFactories, + ]); + + const featureDiscovery = await this.#serviceHolder.get( + featureDiscoveryServiceRef, + 'root', + ); + + if (featureDiscovery) { + const { features } = await featureDiscovery.getBackendFeatures(); + for (const feature of features) { + this.#addFeature(feature); + } + } + // Initialize all root scoped services for (const ref of this.#serviceHolder.getServiceRefs()) { if (ref.scope === 'root') { @@ -144,14 +199,17 @@ export class BackendInitializer { for (const r of feature.getRegistrations()) { const provides = new Set>(); - if (r.type === 'plugin') { + if (r.type === 'plugin' || r.type === 'module') { for (const [extRef, extImpl] of r.extensionPoints) { if (this.#extensionPoints.has(extRef)) { throw new Error( `ExtensionPoint with ID '${extRef.id}' is already registered`, ); } - this.#extensionPoints.set(extRef, extImpl); + this.#extensionPoints.set(extRef, { + impl: extImpl, + pluginId: r.pluginId, + }); provides.add(extRef); } } @@ -193,21 +251,41 @@ export class BackendInitializer { await Promise.all( allPluginIds.map(async pluginId => { // Modules are initialized before plugins, so that they can provide extension to the plugin - const modules = moduleInits.get(pluginId) ?? []; - await Promise.all( - Array.from(modules).map(async ([moduleId, moduleInit]) => { - const moduleDeps = await this.#getInitDeps( - moduleInit.init.deps, - pluginId, + const modules = moduleInits.get(pluginId); + if (modules) { + const tree = DependencyGraph.fromIterable( + Array.from(modules).map(([moduleId, moduleInit]) => ({ + value: { moduleId, moduleInit }, + // Relationships are reversed at this point since we're only interested in the extension points. + // If a modules provides extension point A we want it to be initialized AFTER all modules + // that depend on extension point A, so that they can provide their extensions. + consumes: Array.from(moduleInit.provides).map(p => p.id), + provides: Array.from(moduleInit.consumes).map(c => c.id), + })), + ); + const circular = tree.detectCircularDependency(); + if (circular) { + throw new ConflictError( + `Circular dependency detected for modules of plugin '${pluginId}', ${circular + .map(({ moduleId }) => `'${moduleId}'`) + .join(' -> ')}`, ); - await moduleInit.init.func(moduleDeps).catch(error => { - throw new ForwardedError( - `Module '${moduleId}' for plugin '${pluginId}' startup failed`, - error, + } + await tree.parallelTopologicalTraversal( + async ({ moduleId, moduleInit }) => { + const moduleDeps = await this.#getInitDeps( + moduleInit.init.deps, + pluginId, ); - }); - }), - ); + await moduleInit.init.func(moduleDeps).catch(error => { + throw new ForwardedError( + `Module '${moduleId}' for plugin '${pluginId}' startup failed`, + error, + ); + }); + }, + ); + } // Once all modules have been initialized, we can initialize the plugin itself const pluginInit = pluginInits.get(pluginId); @@ -259,7 +337,12 @@ export class BackendInitializer { if (!this.#startPromise) { return; } - await this.#startPromise; + + try { + await this.#startPromise; + } catch (error) { + // The startup failed, but we may still want to do cleanup so we continue silently + } const lifecycleService = await this.#getRootLifecycleImpl(); await lifecycleService.shutdown(); @@ -267,7 +350,7 @@ export class BackendInitializer { // Bit of a hacky way to grab the lifecycle services, potentially find a nicer way to do this async #getRootLifecycleImpl(): Promise { - const lifecycleService = await this.#serviceHolder.get( + const lifecycleService = await this.#serviceHolder!.get( coreServices.rootLifecycle, 'root', ); @@ -280,7 +363,7 @@ export class BackendInitializer { async #getPluginLifecycleImpl( pluginId: string, ): Promise { - const lifecycleService = await this.#serviceHolder.get( + const lifecycleService = await this.#serviceHolder!.get( coreServices.lifecycle, pluginId, ); @@ -290,3 +373,15 @@ export class BackendInitializer { throw new Error('Unexpected plugin lifecycle service implementation'); } } + +function isServiceFactory(feature: BackendFeature): feature is ServiceFactory { + return !!(feature as ServiceFactory).service; +} + +function isInternalBackendFeature( + feature: BackendFeature, +): feature is InternalBackendFeature { + return ( + typeof (feature as InternalBackendFeature).getRegistrations === 'function' + ); +} diff --git a/packages/backend-app-api/src/wiring/BackstageBackend.ts b/packages/backend-app-api/src/wiring/BackstageBackend.ts index c53f47b685..0ea55bc1c7 100644 --- a/packages/backend-app-api/src/wiring/BackstageBackend.ts +++ b/packages/backend-app-api/src/wiring/BackstageBackend.ts @@ -14,22 +14,19 @@ * limitations under the License. */ -import { ServiceFactory, BackendFeature } from '@backstage/backend-plugin-api'; +import { BackendFeature, ServiceFactory } from '@backstage/backend-plugin-api'; import { BackendInitializer } from './BackendInitializer'; -import { ServiceRegistry } from './ServiceRegistry'; import { Backend } from './types'; export class BackstageBackend implements Backend { - #services: ServiceRegistry; #initializer: BackendInitializer; - constructor(apiFactories: ServiceFactory[]) { - this.#services = new ServiceRegistry(apiFactories); - this.#initializer = new BackendInitializer(this.#services); + constructor(defaultServiceFactories: ServiceFactory[]) { + this.#initializer = new BackendInitializer(defaultServiceFactories); } - add(feature: BackendFeature): void { - this.#initializer.add(feature); + add(feature: BackendFeature | (() => BackendFeature)): void { + this.#initializer.add(typeof feature === 'function' ? feature() : feature); } async start(): Promise { diff --git a/packages/backend-app-api/src/wiring/ServiceRegistry.test.ts b/packages/backend-app-api/src/wiring/ServiceRegistry.test.ts index e698ade348..b60a24c8d8 100644 --- a/packages/backend-app-api/src/wiring/ServiceRegistry.test.ts +++ b/packages/backend-app-api/src/wiring/ServiceRegistry.test.ts @@ -31,7 +31,7 @@ const sf1 = createServiceFactory({ async factory() { return { x: 1 }; }, -})(); +}); const ref2 = createServiceRef<{ x: number }>({ scope: 'root', @@ -43,14 +43,14 @@ const sf2 = createServiceFactory({ async factory() { return { x: 2 }; }, -})(); +}); const sf2b = createServiceFactory({ service: ref2, deps: {}, async factory() { return { x: 22 }; }, -})(); +}); const refDefault1 = createServiceRef<{ x: number }>({ id: '1', @@ -61,7 +61,7 @@ const refDefault1 = createServiceRef<{ x: number }>({ async factory() { return { x: 10 }; }, - })(), + }), }); const refDefault2a = createServiceRef<{ x: number }>({ @@ -95,7 +95,7 @@ describe('ServiceRegistry', () => { }); it('should return an implementation for a registered ref', async () => { - const registry = new ServiceRegistry([sf1]); + const registry = new ServiceRegistry([sf1()]); await expect(registry.get(ref1, 'catalog')).resolves.toEqual({ x: 1 }); await expect(registry.get(ref1, 'scaffolder')).resolves.toEqual({ x: 1 }); expect(await registry.get(ref1, 'catalog')).toBe( @@ -110,7 +110,7 @@ describe('ServiceRegistry', () => { }); it('should handle multiple factories with different serviceRefs', async () => { - const registry = new ServiceRegistry([sf1, sf2]); + const registry = new ServiceRegistry([sf1(), sf2()]); await expect(registry.get(ref1, 'catalog')).resolves.toEqual({ x: 1, @@ -131,7 +131,7 @@ describe('ServiceRegistry', () => { return { x: 2 }; }, }); - const registry = new ServiceRegistry([factory(), sf1]); + const registry = new ServiceRegistry([factory(), sf1()]); await expect(registry.get(ref2, 'catalog')).rejects.toThrow( "Failed to instantiate 'root' scoped service '2' because it depends on 'plugin' scoped service '1'.", ); @@ -145,7 +145,7 @@ describe('ServiceRegistry', () => { return { x: rootDep.x }; }, }); - const registry = new ServiceRegistry([factory(), sf2]); + const registry = new ServiceRegistry([factory(), sf2()]); await expect(registry.get(ref1, 'catalog')).resolves.toEqual({ x: 2, }); @@ -160,7 +160,7 @@ describe('ServiceRegistry', () => { return { x: rootDep.x }; }, }); - const registry = new ServiceRegistry([factory(), sf2]); + const registry = new ServiceRegistry([factory(), sf2()]); await expect(registry.get(ref, 'catalog')).resolves.toEqual({ x: 2, }); @@ -182,7 +182,7 @@ describe('ServiceRegistry', () => { }); it('should use the last factory for each ref', async () => { - const registry = new ServiceRegistry([sf2, sf2b]); + const registry = new ServiceRegistry([sf2(), sf2b()]); await expect(registry.get(ref2, 'catalog')).resolves.toEqual({ x: 22, }); @@ -196,7 +196,7 @@ describe('ServiceRegistry', () => { }); it('should not use the defaultFactory from the ref if provided to the registry', async () => { - const registry = new ServiceRegistry([sf1]); + const registry = new ServiceRegistry([sf1()]); await expect(registry.get(refDefault1, 'catalog')).resolves.toEqual({ x: 1, }); diff --git a/packages/backend-app-api/src/wiring/ServiceRegistry.ts b/packages/backend-app-api/src/wiring/ServiceRegistry.ts index b5b55f67cf..b6de05b361 100644 --- a/packages/backend-app-api/src/wiring/ServiceRegistry.ts +++ b/packages/backend-app-api/src/wiring/ServiceRegistry.ts @@ -39,7 +39,7 @@ function toInternalServiceFactory( factory: ServiceFactory, ): InternalServiceFactory { const f = factory as InternalServiceFactory; - if (f.$$type !== '@backstage/ServiceFactory') { + if (f.$$type !== '@backstage/BackendFeature') { throw new Error(`Invalid service factory, bad type '${f.$$type}'`); } if (f.version !== 'v1') { @@ -49,10 +49,10 @@ function toInternalServiceFactory( } const pluginMetadataServiceFactory = createServiceFactory( - (options: { pluginId: string }) => ({ + (options?: { pluginId: string }) => ({ service: coreServices.pluginMetadata, deps: {}, - factory: async () => ({ getId: () => options.pluginId }), + factory: async () => ({ getId: () => options?.pluginId! }), }), ); diff --git a/packages/backend-app-api/src/wiring/createSpecializedBackend.test.ts b/packages/backend-app-api/src/wiring/createSpecializedBackend.test.ts index dc9a0cc085..1fd7fcbbec 100644 --- a/packages/backend-app-api/src/wiring/createSpecializedBackend.test.ts +++ b/packages/backend-app-api/src/wiring/createSpecializedBackend.test.ts @@ -22,13 +22,15 @@ import { createSpecializedBackend } from './createSpecializedBackend'; describe('createSpecializedBackend', () => { it('should create a backend without services', () => { - expect(() => createSpecializedBackend({ services: [] })).not.toThrow(); + expect(() => + createSpecializedBackend({ defaultServiceFactories: [] }), + ).not.toThrow(); }); it('should throw on duplicate service implementations', () => { expect(() => createSpecializedBackend({ - services: [ + defaultServiceFactories: [ createServiceFactory({ service: coreServices.rootLifecycle, deps: {}, @@ -55,7 +57,7 @@ describe('createSpecializedBackend', () => { it('should throw when providing a plugin metadata service implementation', () => { expect(() => createSpecializedBackend({ - services: [ + defaultServiceFactories: [ createServiceFactory({ service: coreServices.pluginMetadata, deps: {}, diff --git a/packages/backend-app-api/src/wiring/createSpecializedBackend.ts b/packages/backend-app-api/src/wiring/createSpecializedBackend.ts index 15e51f7c4c..f5c4d8b152 100644 --- a/packages/backend-app-api/src/wiring/createSpecializedBackend.ts +++ b/packages/backend-app-api/src/wiring/createSpecializedBackend.ts @@ -24,7 +24,7 @@ import { Backend, CreateSpecializedBackendOptions } from './types'; export function createSpecializedBackend( options: CreateSpecializedBackendOptions, ): Backend { - const services = options.services.map(sf => + const services = options.defaultServiceFactories.map(sf => typeof sf === 'function' ? sf() : sf, ); diff --git a/packages/backend-app-api/src/wiring/types.ts b/packages/backend-app-api/src/wiring/types.ts index ffedb40324..552a69a792 100644 --- a/packages/backend-app-api/src/wiring/types.ts +++ b/packages/backend-app-api/src/wiring/types.ts @@ -25,7 +25,7 @@ import { * @public */ export interface Backend { - add(feature: BackendFeature): void; + add(feature: BackendFeature | (() => BackendFeature)): void; start(): Promise; stop(): Promise; } @@ -34,7 +34,7 @@ export interface Backend { * @public */ export interface CreateSpecializedBackendOptions { - services: ServiceFactoryOrFunction[]; + defaultServiceFactories: ServiceFactoryOrFunction[]; } export interface ServiceHolder { diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index 2977d54c01..030223606f 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,56 @@ # @backstage/backend-common +## 0.19.2 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 443afcf7f567: To improve performance, `GerritUrlReader.readTree()` now uses Gitiles to fetch an archive instead of cloning the repository. + If `gitilesBaseUrl` is not configured, `readTree` still uses Git to clone the repository. + + Added `stripFirstDirectory` option to `ReadTreeResponseFactory.fromTarArchive()`, allowing to disable stripping first directory + for `tar` archives. + +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-app-api@0.5.0 + - @backstage/config-loader@1.4.0 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/integration@1.6.0 + - @backstage/integration-aws-node@0.1.5 + - @backstage/backend-dev-utils@0.1.1 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## 0.19.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-app-api@0.5.0-next.2 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/config-loader@1.4.0-next.1 + +## 0.19.2-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/config-loader@1.4.0-next.1 + - @backstage/backend-app-api@0.5.0-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/integration@1.5.1 + - @backstage/integration-aws-node@0.1.5 + - @backstage/backend-dev-utils@0.1.1 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + ## 0.19.2-next.0 ### Patch Changes diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index d40027cba9..f8e535c8a7 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -18,7 +18,6 @@ import { CacheService as CacheClient } from '@backstage/backend-plugin-api'; import { CacheServiceOptions as CacheClientOptions } from '@backstage/backend-plugin-api'; import { CacheServiceSetOptions as CacheClientSetOptions } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; -import { ConfigService } from '@backstage/backend-plugin-api'; import cors from 'cors'; import Docker from 'dockerode'; import { ErrorRequestHandler } from 'express'; @@ -51,6 +50,7 @@ import { ReadTreeResponseFile } from '@backstage/backend-plugin-api'; import { ReadUrlOptions } from '@backstage/backend-plugin-api'; import { ReadUrlResponse } from '@backstage/backend-plugin-api'; import { RequestHandler } from 'express'; +import { RootConfigService } from '@backstage/backend-plugin-api'; import { Router } from 'express'; import { SchedulerService } from '@backstage/backend-plugin-api'; import { SearchOptions } from '@backstage/backend-plugin-api'; @@ -525,7 +525,7 @@ export const legacyPlugin: ( TransformedEnv< { cache: CacheClient; - config: ConfigService; + config: RootConfigService; database: PluginDatabaseManager; discovery: PluginEndpointDiscovery; logger: LoggerService; @@ -610,7 +610,9 @@ export interface ReadTreeResponseFactory { ): Promise; // (undocumented) fromTarArchive( - options: ReadTreeResponseFactoryOptions, + options: ReadTreeResponseFactoryOptions & { + stripFirstDirectory?: boolean; + }, ): Promise; // (undocumented) fromZipArchive( diff --git a/packages/backend-common/config.d.ts b/packages/backend-common/config.d.ts index 3fd886874e..e5b193c543 100644 --- a/packages/backend-common/config.d.ts +++ b/packages/backend-common/config.d.ts @@ -77,17 +77,17 @@ export interface Config { */ connection: | string - | Partial<{ + | { /** * Password that belongs to the client User * @visibility secret */ - password: string; + password?: string; /** * Other connection settings */ [key: string]: unknown; - }>; + }; /** Database name prefix override */ prefix?: string; /** diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 6e561fa564..fd9b9cb0df 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.19.2-next.0", + "version": "0.19.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-common/src/legacy.ts b/packages/backend-common/src/legacy.ts index 408966f3bc..df1030e6b6 100644 --- a/packages/backend-common/src/legacy.ts +++ b/packages/backend-common/src/legacy.ts @@ -108,7 +108,7 @@ export function makeLegacyPlugin< export const legacyPlugin = makeLegacyPlugin( { cache: coreServices.cache, - config: coreServices.config, + config: coreServices.rootConfig, database: coreServices.database, discovery: coreServices.discovery, logger: coreServices.logger, diff --git a/packages/backend-common/src/reading/GerritUrlReader.test.ts b/packages/backend-common/src/reading/GerritUrlReader.test.ts index 4e0b97fc58..9de9aac33d 100644 --- a/packages/backend-common/src/reading/GerritUrlReader.test.ts +++ b/packages/backend-common/src/reading/GerritUrlReader.test.ts @@ -37,14 +37,16 @@ const treeResponseFactory = DefaultReadTreeResponseFactory.create({ config: new ConfigReader({}), }); +const cloneMock = jest.fn(() => Promise.resolve()); jest.mock('../scm', () => ({ Git: { fromAuth: () => ({ - clone: jest.fn(() => Promise.resolve({})), + clone: cloneMock, }), }, })); +// Gerrit processor without a gitilesBaseUrl configured const gerritProcessor = new GerritUrlReader( new GerritIntegration( readGerritIntegrationConfig( @@ -57,6 +59,21 @@ const gerritProcessor = new GerritUrlReader( '/tmp', ); +// Gerrit processor with a gitilesBaseUrl configured. +// Use to test readTree with Gitiles archive download. +const gerritProcessorWithGitiles = new GerritUrlReader( + new GerritIntegration( + readGerritIntegrationConfig( + new ConfigReader({ + host: 'gerrit.com', + gitilesBaseUrl: 'https://gerrit.com/gitiles', + }), + ), + ), + { treeResponseFactory }, + '/tmp', +); + const createReader = (config: JsonObject): UrlReaderPredicateTuple[] => { return GerritUrlReader.factory({ config: new ConfigReader(config), @@ -217,9 +234,17 @@ describe('GerritUrlReader', () => { path.resolve(__dirname, '__fixtures__/gerrit/branch-info-response.txt'), ); const treeUrl = 'https://gerrit.com/app/web/+/refs/heads/master/'; + const treeUrlGitiles = + 'https://gerrit.com/gitiles/app/web/+/refs/heads/master/'; const etag = '52432507a70b677b5674b019c9a46b2e9f29d0a1'; - const mkdocsContent = 'great content'; + const mkdocsContent = 'a repo fetched using git clone'; const mdContent = 'doc'; + const repoArchiveBuffer = fs.readFileSync( + path.resolve(__dirname, '__fixtures__/gerrit/gerrit-master.tar.gz'), + ); + const repoArchiveDocsBuffer = fs.readFileSync( + path.resolve(__dirname, '__fixtures__/gerrit/gerrit-master-docs.tar.gz'), + ); beforeEach(() => { mockFs({ @@ -229,6 +254,35 @@ describe('GerritUrlReader', () => { }); const spy = jest.spyOn(fs, 'mkdtemp'); spy.mockImplementation(() => '/tmp/gerrit-clone-123abc'); + + worker.use( + rest.get( + 'https://gerrit.com/gitiles/app/web/\\+archive/refs/heads/master.tar.gz', + (_, res, ctx) => + res( + ctx.status(200), + ctx.set('Content-Type', 'application/x-gzip'), + ctx.set( + 'content-disposition', + 'attachment; filename=web-refs/heads/master.tar.gz', + ), + ctx.body(repoArchiveBuffer), + ), + ), + rest.get( + 'https://gerrit.com/gitiles/app/web/\\+archive/refs/heads/master/docs.tar.gz', + (_, res, ctx) => + res( + ctx.status(200), + ctx.set('Content-Type', 'application/x-gzip'), + ctx.set( + 'content-disposition', + 'attachment; filename=web-refs/heads/master-docs.tar.gz', + ), + ctx.body(repoArchiveDocsBuffer), + ), + ), + ); }); afterEach(() => { @@ -236,7 +290,32 @@ describe('GerritUrlReader', () => { jest.clearAllMocks(); }); - it('reads the wanted files correctly.', async () => { + it('reads the wanted files correctly using gitiles.', async () => { + worker.use( + rest.get(branchAPIUrl, (_, res, ctx) => { + return res(ctx.status(200), ctx.body(branchAPIresponse)); + }), + ); + + const response = await gerritProcessorWithGitiles.readTree( + treeUrlGitiles, + ); + + expect(response.etag).toBe(etag); + + const files = await response.files(); + expect(files.length).toBe(2); + + const docsYaml = await files[0].content(); + expect(docsYaml.toString()).toBe('# Test\n'); + + const mdFile = await files[1].content(); + expect(mdFile.toString()).toBe('site_name: Test\n'); + + expect(cloneMock).not.toHaveBeenCalled(); + }); + + it('reads the wanted files correctly using git clone.', async () => { worker.use( rest.get(branchAPIUrl, (_, res, ctx) => { return res(ctx.status(200), ctx.body(branchAPIresponse)); @@ -255,6 +334,8 @@ describe('GerritUrlReader', () => { const mdFile = await files[1].content(); expect(mdFile.toString()).toBe(mdContent); + + expect(cloneMock).toHaveBeenCalled(); }); it('throws NotModifiedError for matching etags.', async () => { @@ -291,7 +372,29 @@ describe('GerritUrlReader', () => { await expect(gerritProcessor.readTree(treeUrl)).rejects.toThrow(Error); }); - it('should returns wanted files with a subpath', async () => { + it('should returns wanted files with a subpath using gitiles', async () => { + worker.use( + rest.get(branchAPIUrl, (_, res, ctx) => { + return res(ctx.status(200), ctx.body(branchAPIresponse)); + }), + ); + + const response = await gerritProcessorWithGitiles.readTree( + `${treeUrlGitiles}/docs`, + ); + + expect(response.etag).toBe(etag); + + const files = await response.files(); + expect(files.length).toBe(1); + + const mdFile = await files[0].content(); + expect(mdFile.toString()).toBe('# Test\n'); + + expect(cloneMock).not.toHaveBeenCalled(); + }); + + it('should returns wanted files with a subpath using git clone', async () => { worker.use( rest.get(branchAPIUrl, (_, res, ctx) => { return res(ctx.status(200), ctx.body(branchAPIresponse)); @@ -307,6 +410,8 @@ describe('GerritUrlReader', () => { const mdFile = await files[0].content(); expect(mdFile.toString()).toBe(mdContent); + + expect(cloneMock).toHaveBeenCalled(); }); }); }); diff --git a/packages/backend-common/src/reading/GerritUrlReader.ts b/packages/backend-common/src/reading/GerritUrlReader.ts index 8ac5452a4c..f4a5fdb9f5 100644 --- a/packages/backend-common/src/reading/GerritUrlReader.ts +++ b/packages/backend-common/src/reading/GerritUrlReader.ts @@ -14,16 +14,17 @@ * limitations under the License. */ -import { Git } from '../scm'; import { NotFoundError, NotModifiedError } from '@backstage/errors'; import { GerritIntegration, - getGerritCloneRepoUrl, + ScmIntegrations, + buildGerritGitilesArchiveUrl, getGerritBranchApiUrl, + getGerritCloneRepoUrl, getGerritFileContentsApiUrl, getGerritRequestOptions, - parseGerritJsonResponse, parseGerritGitilesUrl, + parseGerritJsonResponse, } from '@backstage/integration'; import { Base64Decode } from 'base64-stream'; import concatStream from 'concat-stream'; @@ -31,20 +32,20 @@ import fs from 'fs-extra'; import fetch, { Response } from 'node-fetch'; import os from 'os'; import { join as joinPath } from 'path'; +import { Readable, pipeline as pipelineCb } from 'stream'; import tar from 'tar'; -import { pipeline as pipelineCb, Readable } from 'stream'; import { promisify } from 'util'; +import { Git } from '../scm'; import { - ReaderFactory, ReadTreeOptions, ReadTreeResponse, ReadTreeResponseFactory, ReadUrlOptions, ReadUrlResponse, + ReaderFactory, SearchResponse, UrlReader, } from './types'; -import { ScmIntegrations } from '@backstage/integration'; const pipeline = promisify(pipelineCb); @@ -59,6 +60,8 @@ const createTemporaryDirectory = async (workDir: string): Promise => * way we are depending on that there is a Gitiles installation somewhere * that we can link to. It is perfectly possible to integrate Gerrit with * Backstage without Gitiles since all API calls goes directly to Gerrit. + * However if Gitiles is configured, readTree will use it to fetch + * an archive instead of cloning the repository. * * The "host" variable in the config is the Gerrit host. The address where * Gitiles is installed may be on the same host but it could be on a @@ -125,6 +128,7 @@ export class GerritUrlReader implements UrlReader { } catch (e) { throw new Error(`Unable to read gerrit file ${url}, ${e}`); } + if (response.ok) { let responseBody: string; return { @@ -152,7 +156,6 @@ export class GerritUrlReader implements UrlReader { url: string, options?: ReadTreeOptions, ): Promise { - const { filePath } = parseGerritGitilesUrl(this.integration.config, url); const apiUrl = getGerritBranchApiUrl(this.integration.config, url); let response: Response; try { @@ -180,6 +183,30 @@ export class GerritUrlReader implements UrlReader { throw new NotModifiedError(); } + if ( + this.integration.config.gitilesBaseUrl !== this.integration.config.baseUrl + ) { + return this.readTreeFromGitiles(url, branchInfo.revision, options); + } + return this.readTreeFromGitClone(url, branchInfo.revision, options); + } + + async search(): Promise { + throw new Error('GerritReader does not implement search'); + } + + toString() { + const { host, password } = this.integration.config; + return `gerrit{host=${host},authed=${Boolean(password)}}`; + } + + private async readTreeFromGitClone( + url: string, + revision: string, + options?: ReadTreeOptions, + ) { + const { filePath } = parseGerritGitilesUrl(this.integration.config, url); + const git = Git.fromAuth({ username: this.integration.config.username, password: this.integration.config.password, @@ -192,7 +219,7 @@ export class GerritUrlReader implements UrlReader { await git.clone({ url: cloneUrl, dir: joinPath(tempDir, 'repo'), - ref: branchInfo.revision, + ref: revision, depth: 1, }); @@ -206,7 +233,7 @@ export class GerritUrlReader implements UrlReader { return await this.deps.treeResponseFactory.fromTarArchive({ stream: tarArchive, subpath: filePath === '/' ? undefined : filePath, - etag: branchInfo.revision, + etag: revision, filter: options?.filter, }); } catch (error) { @@ -216,12 +243,47 @@ export class GerritUrlReader implements UrlReader { } } - async search(): Promise { - throw new Error('GerritReader does not implement search'); - } + private async readTreeFromGitiles( + url: string, + revision: string, + options?: ReadTreeOptions, + ) { + const { branch, filePath, project } = parseGerritGitilesUrl( + this.integration.config, + url, + ); + const archiveUrl = buildGerritGitilesArchiveUrl( + this.integration.config, + project, + branch, + filePath, + ); + const archiveResponse = await fetch(archiveUrl, { + ...getGerritRequestOptions(this.integration.config), + // TODO(freben): The signal cast is there because pre-3.x versions of + // node-fetch have a very slightly deviating AbortSignal type signature. + // The difference does not affect us in practice however. The cast can + // be removed after we support ESM for CLI dependencies and migrate to + // version 3 of node-fetch. + // https://github.com/backstage/backstage/issues/8242 + signal: options?.signal as any, + }); - toString() { - const { host, password } = this.integration.config; - return `gerrit{host=${host},authed=${Boolean(password)}}`; + if (archiveResponse.status === 404) { + throw new NotFoundError(`Not found: ${archiveUrl}`); + } + + if (!archiveResponse.ok) { + throw new Error( + `${url} could not be read as ${archiveUrl}, ${archiveResponse.status} ${archiveResponse.statusText}`, + ); + } + + return await this.deps.treeResponseFactory.fromTarArchive({ + stream: archiveResponse.body as unknown as Readable, + etag: revision, + filter: options?.filter, + stripFirstDirectory: false, + }); } } diff --git a/packages/backend-common/src/reading/__fixtures__/gerrit/gerrit-master-docs.tar.gz b/packages/backend-common/src/reading/__fixtures__/gerrit/gerrit-master-docs.tar.gz new file mode 100644 index 0000000000..425cf0876b Binary files /dev/null and b/packages/backend-common/src/reading/__fixtures__/gerrit/gerrit-master-docs.tar.gz differ diff --git a/packages/backend-common/src/reading/__fixtures__/gerrit/gerrit-master.tar.gz b/packages/backend-common/src/reading/__fixtures__/gerrit/gerrit-master.tar.gz new file mode 100644 index 0000000000..8a27502734 Binary files /dev/null and b/packages/backend-common/src/reading/__fixtures__/gerrit/gerrit-master.tar.gz differ diff --git a/packages/backend-common/src/reading/tree/ReadTreeResponseFactory.ts b/packages/backend-common/src/reading/tree/ReadTreeResponseFactory.ts index 11a5ef168a..90c58c0efa 100644 --- a/packages/backend-common/src/reading/tree/ReadTreeResponseFactory.ts +++ b/packages/backend-common/src/reading/tree/ReadTreeResponseFactory.ts @@ -37,7 +37,9 @@ export class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory { constructor(private readonly workDir: string) {} async fromTarArchive( - options: ReadTreeResponseFactoryOptions, + options: ReadTreeResponseFactoryOptions & { + stripFirstDirectory?: boolean; + }, ): Promise { return new TarArchiveResponse( options.stream, @@ -45,6 +47,7 @@ export class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory { this.workDir, options.etag, options.filter, + options.stripFirstDirectory ?? true, ); } diff --git a/packages/backend-common/src/reading/tree/TarArchiveResponse.ts b/packages/backend-common/src/reading/tree/TarArchiveResponse.ts index e1529c196a..294ec22609 100644 --- a/packages/backend-common/src/reading/tree/TarArchiveResponse.ts +++ b/packages/backend-common/src/reading/tree/TarArchiveResponse.ts @@ -44,6 +44,7 @@ export class TarArchiveResponse implements ReadTreeResponse { private readonly workDir: string, public readonly etag: string, private readonly filter?: (path: string, info: { size: number }) => boolean, + private readonly stripFirstDirectory: boolean = true, ) { if (subPath) { if (!subPath.endsWith('/')) { @@ -81,7 +82,9 @@ export class TarArchiveResponse implements ReadTreeResponse { // File path relative to the root extracted directory. Will remove the // top level dir name from the path since its name is hard to predetermine. - const relativePath = stripFirstDirectoryFromPath(entry.path); + const relativePath = this.stripFirstDirectory + ? stripFirstDirectoryFromPath(entry.path) + : entry.path; if (this.subPath) { if (!relativePath.startsWith(this.subPath)) { @@ -148,7 +151,10 @@ export class TarArchiveResponse implements ReadTreeResponse { // Equivalent of tar --strip-components=N // When no subPath is given, remove just 1 top level directory - const strip = this.subPath ? this.subPath.split('/').length : 1; + let strip = this.subPath ? this.subPath.split('/').length : 1; + if (!this.stripFirstDirectory) { + strip--; + } let filterError: Error | undefined = undefined; await pipeline( @@ -164,7 +170,9 @@ export class TarArchiveResponse implements ReadTreeResponse { // File path relative to the root extracted directory. Will remove the // top level dir name from the path since its name is hard to predetermine. - const relativePath = stripFirstDirectoryFromPath(path); + const relativePath = this.stripFirstDirectory + ? stripFirstDirectoryFromPath(path) + : path; if (this.subPath && !relativePath.startsWith(this.subPath)) { return false; } diff --git a/packages/backend-common/src/reading/types.ts b/packages/backend-common/src/reading/types.ts index 7f4d407fd0..90a3c6287e 100644 --- a/packages/backend-common/src/reading/types.ts +++ b/packages/backend-common/src/reading/types.ts @@ -116,7 +116,13 @@ export type FromReadableArrayOptions = Array<{ */ export interface ReadTreeResponseFactory { fromTarArchive( - options: ReadTreeResponseFactoryOptions, + options: ReadTreeResponseFactoryOptions & { + /** + * Strip the first parent directory of a tar archive. + * Defaults to true. + */ + stripFirstDirectory?: boolean; + }, ): Promise; fromZipArchive( options: ReadTreeResponseFactoryOptions, diff --git a/packages/backend-defaults/CHANGELOG.md b/packages/backend-defaults/CHANGELOG.md index 1ff580965f..af86313d11 100644 --- a/packages/backend-defaults/CHANGELOG.md +++ b/packages/backend-defaults/CHANGELOG.md @@ -1,5 +1,54 @@ # @backstage/backend-defaults +## 0.2.0 + +### Minor Changes + +- d008aefef808: **BREAKING**: Removing shared environments concept from the new experimental backend system. +- a6d7983f349c: **BREAKING**: Removed the `services` option from `createBackend`. Service factories are now `BackendFeature`s and should be installed with `backend.add(...)` instead. The following should be migrated: + + ```ts + const backend = createBackend({ services: [myCustomServiceFactory] }); + ``` + + To instead pass the service factory via `backend.add(...)`: + + ```ts + const backend = createBackend(); + backend.add(customRootLoggerServiceFactory); + ``` + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-app-api@0.5.0 + - @backstage/backend-plugin-api@0.6.0 + +## 0.2.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-app-api@0.5.0-next.2 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## 0.2.0-next.1 + +### Minor Changes + +- d008aefef808: **BREAKING**: Removing shared environments concept from the new experimental backend system. + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-app-api@0.5.0-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + ## 0.1.13-next.0 ### Patch Changes diff --git a/packages/backend-defaults/api-report.md b/packages/backend-defaults/api-report.md index 07218f610e..ab9cc5775c 100644 --- a/packages/backend-defaults/api-report.md +++ b/packages/backend-defaults/api-report.md @@ -4,17 +4,7 @@ ```ts import { Backend } from '@backstage/backend-app-api'; -import { ServiceFactoryOrFunction } from '@backstage/backend-plugin-api'; -import { SharedBackendEnvironment } from '@backstage/backend-plugin-api'; // @public (undocumented) -export function createBackend(options?: CreateBackendOptions): Backend; - -// @public (undocumented) -export interface CreateBackendOptions { - // (undocumented) - env?: SharedBackendEnvironment; - // (undocumented) - services?: ServiceFactoryOrFunction[]; -} +export function createBackend(): Backend; ``` diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index 318b00c7f2..48464ac81e 100644 --- a/packages/backend-defaults/package.json +++ b/packages/backend-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-defaults", "description": "Backend defaults used by Backstage backend apps", - "version": "0.1.13-next.0", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-defaults/src/CreateBackend.test.ts b/packages/backend-defaults/src/CreateBackend.test.ts index 946de90b2b..0b36b57069 100644 --- a/packages/backend-defaults/src/CreateBackend.test.ts +++ b/packages/backend-defaults/src/CreateBackend.test.ts @@ -16,160 +16,69 @@ import { coreServices, - createBackendPlugin, createServiceFactory, - createServiceRef, - createSharedEnvironment, } from '@backstage/backend-plugin-api'; -import { mockServices } from '@backstage/backend-test-utils'; import { createBackend } from './CreateBackend'; -const fooServiceRef = createServiceRef({ id: 'foo', scope: 'root' }); -const barServiceRef = createServiceRef({ id: 'bar', scope: 'root' }); - describe('createBackend', () => { it('should not throw when overriding a default service implementation', () => { - expect(() => - createBackend({ - services: [ - createServiceFactory({ - service: coreServices.rootLifecycle, - deps: {}, - factory: async () => ({ - addStartupHook: () => {}, - addShutdownHook: () => {}, - }), + const backend = createBackend(); + + expect(() => { + backend.add( + createServiceFactory({ + service: coreServices.rootLifecycle, + deps: {}, + factory: async () => ({ + addStartupHook: () => {}, + addShutdownHook: () => {}, }), - ], - }), - ).not.toThrow(); + }), + ); + }).not.toThrow(); }); it('should throw on duplicate service implementations', () => { - expect(() => - createBackend({ - services: [ - createServiceFactory({ - service: coreServices.rootLifecycle, - deps: {}, - factory: async () => ({ - addStartupHook: () => {}, - addShutdownHook: () => {}, - }), - }), - createServiceFactory({ - service: coreServices.rootLifecycle, - deps: {}, - factory: async () => ({ - addStartupHook: () => {}, - addShutdownHook: () => {}, - }), - }), - ], + const backend = createBackend(); + + backend.add( + createServiceFactory({ + service: coreServices.rootLifecycle, + deps: {}, + factory: async () => ({ + addStartupHook: () => {}, + addShutdownHook: () => {}, + }), }), - ).toThrow( + ); + + expect(() => { + backend.add( + createServiceFactory({ + service: coreServices.rootLifecycle, + deps: {}, + factory: async () => ({ + addStartupHook: () => {}, + addShutdownHook: () => {}, + }), + }), + ); + }).toThrow( 'Duplicate service implementations provided for core.rootLifecycle', ); }); it('should throw when providing a plugin metadata service implementation', () => { + const backend = createBackend(); + expect(() => - createBackend({ - services: [ - createServiceFactory({ - service: coreServices.pluginMetadata, - deps: {}, - factory: async () => ({ getId: () => 'test' }), - }), - ], - }), + backend.add( + createServiceFactory({ + service: coreServices.pluginMetadata, + deps: {}, + factory: async () => ({ getId: () => 'test' }), + }), + ), ).toThrow('The core.pluginMetadata service cannot be overridden'); }); - - it('should throw if an unsupported InternalSharedEnvironment version is passed in', () => { - expect(() => - createBackend({ - env: {} as any, - }), - ).toThrow( - "Shared environment version 'undefined' is invalid or not supported", - ); - expect(() => - createBackend({ - env: { version: {} } as any, - }), - ).toThrow( - "Shared environment version '[object Object]' is invalid or not supported", - ); - expect(() => - createBackend({ - env: { version: 'v2' } as any, - }), - ).toThrow("Shared environment version 'v2' is invalid or not supported"); - }); - - it('should prioritize services correctly', async () => { - const backend = createBackend({ - env: createSharedEnvironment({ - services: [ - createServiceFactory({ - service: coreServices.rootHttpRouter, - deps: {}, - async factory() { - return { - use() {}, - }; - }, - }), - mockServices.config.factory({ - data: { root: 'root-env' }, - }), - createServiceFactory({ - service: fooServiceRef, - deps: {}, - async factory() { - return 'foo-env'; - }, - }), - createServiceFactory({ - service: barServiceRef, - deps: {}, - async factory() { - return 'bar-env'; - }, - }), - ], - })(), - services: [ - createServiceFactory({ - service: fooServiceRef, - deps: {}, - factory: async () => 'foo-backend', - }), - ], - }); - - expect.assertions(3); - backend.add( - createBackendPlugin({ - pluginId: 'test', - register(reg) { - reg.registerInit({ - deps: { - config: coreServices.config, - foo: fooServiceRef, - bar: barServiceRef, - }, - async init({ config, foo, bar }) { - expect(config.get('root')).toBe('root-env'); - expect(foo).toBe('foo-backend'); - expect(bar).toBe('bar-env'); - }, - }); - }, - })(), - ); - - await backend.start(); - }); }); diff --git a/packages/backend-defaults/src/CreateBackend.ts b/packages/backend-defaults/src/CreateBackend.ts index 480f365216..c07d1cc38a 100644 --- a/packages/backend-defaults/src/CreateBackend.ts +++ b/packages/backend-defaults/src/CreateBackend.ts @@ -17,7 +17,7 @@ import { Backend, cacheServiceFactory, - configServiceFactory, + rootConfigServiceFactory, createSpecializedBackend, databaseServiceFactory, discoveryServiceFactory, @@ -33,19 +33,10 @@ import { urlReaderServiceFactory, identityServiceFactory, } from '@backstage/backend-app-api'; -import { - ServiceFactory, - ServiceFactoryOrFunction, - SharedBackendEnvironment, -} from '@backstage/backend-plugin-api'; - -// Internal import of the type to avoid needing to export this. -// eslint-disable-next-line @backstage/no-forbidden-package-imports -import type { InternalSharedBackendEnvironment } from '@backstage/backend-plugin-api/src/wiring/createSharedEnvironment'; export const defaultServiceFactories = [ cacheServiceFactory(), - configServiceFactory(), + rootConfigServiceFactory(), databaseServiceFactory(), discoveryServiceFactory(), httpRouterServiceFactory(), @@ -64,44 +55,6 @@ export const defaultServiceFactories = [ /** * @public */ -export interface CreateBackendOptions { - env?: SharedBackendEnvironment; - services?: ServiceFactoryOrFunction[]; -} - -/** - * @public - */ -export function createBackend(options?: CreateBackendOptions): Backend { - const services = new Array(); - - // Highest priority: Services passed directly to createBackend - const providedServices = (options?.services ?? []).map(sf => - typeof sf === 'function' ? sf() : sf, - ); - services.push(...providedServices); - - // Middle priority: Services from the shared environment - if (options?.env) { - const env = options.env as unknown as InternalSharedBackendEnvironment; - if (env.version !== 'v1') { - throw new Error( - `Shared environment version '${env.version}' is invalid or not supported`, - ); - } - - const environmentServices = - env.services?.filter( - sf => !services.some(({ service }) => sf.service.id === service.id), - ) ?? []; - services.push(...environmentServices); - } - - // Lowest priority: Default services that are not already provided by environment or directly to createBackend - const defaultServices = defaultServiceFactories.filter( - sf => !services.some(({ service }) => service.id === sf.service.id), - ); - services.push(...defaultServices); - - return createSpecializedBackend({ services }); +export function createBackend(): Backend { + return createSpecializedBackend({ defaultServiceFactories }); } diff --git a/packages/backend-defaults/src/index.ts b/packages/backend-defaults/src/index.ts index 833878744e..d3e36cf0fb 100644 --- a/packages/backend-defaults/src/index.ts +++ b/packages/backend-defaults/src/index.ts @@ -25,5 +25,4 @@ // TODO(Rugvip): Remove this once backend-common is no longer used by backend-app-api import '@backstage/backend-common'; -export type { CreateBackendOptions } from './CreateBackend'; export { createBackend } from './CreateBackend'; diff --git a/packages/backend-next/.snyk b/packages/backend-next/.snyk new file mode 100644 index 0000000000..ea5abd653d --- /dev/null +++ b/packages/backend-next/.snyk @@ -0,0 +1,10 @@ +# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. +version: v1.22.1 +# ignores vulnerabilities until expiry date; change duration by modifying expiry date +ignore: + SNYK-JS-ISOLATEDVM-3037320: + - '*': + reason: We do not pass any V8 cache data, and are therefore unaffected by this vulnerability + expires: 2033-07-02T16:55:57.077Z + created: 2023-07-02T16:55:57.077Z +patch: {} diff --git a/packages/backend-next/CHANGELOG.md b/packages/backend-next/CHANGELOG.md index 9a9be3b3e2..2c0fefb9f3 100644 --- a/packages/backend-next/CHANGELOG.md +++ b/packages/backend-next/CHANGELOG.md @@ -1,5 +1,101 @@ # example-backend-next +## 0.0.14 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-module-techdocs@0.1.4 + - @backstage/plugin-search-backend-module-catalog@0.1.4 + - @backstage/plugin-search-backend-module-explore@0.1.4 + - @backstage/plugin-azure-devops-backend@0.3.27 + - @backstage/plugin-kubernetes-backend@0.11.3 + - @backstage/plugin-lighthouse-backend@0.2.4 + - @backstage/plugin-permission-backend@0.5.23 + - @backstage/plugin-scaffolder-backend@1.16.0 + - @backstage/backend-defaults@0.2.0 + - @backstage/plugin-devtools-backend@0.1.3 + - @backstage/plugin-techdocs-backend@1.6.5 + - @backstage/plugin-catalog-backend@1.12.0 + - @backstage/plugin-badges-backend@0.2.3 + - @backstage/plugin-search-backend@1.4.0 + - @backstage/plugin-proxy-backend@0.3.0 + - @backstage/plugin-todo-backend@0.2.0 + - @backstage/plugin-app-backend@0.3.48 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.2.0 + - @backstage/plugin-entity-feedback-backend@0.1.6 + - @backstage/plugin-search-backend-node@1.2.4 + - @backstage/plugin-linguist-backend@0.4.0 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/backend-tasks@0.5.5 + - @backstage/plugin-adr-backend@0.3.6 + - @backstage/plugin-permission-node@0.7.11 + - @backstage/plugin-permission-common@0.7.7 + +## 0.0.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-module-techdocs@0.1.4-next.2 + - @backstage/plugin-search-backend-module-catalog@0.1.4-next.2 + - @backstage/plugin-search-backend-module-explore@0.1.4-next.2 + - @backstage/plugin-scaffolder-backend@1.15.2-next.2 + - @backstage/plugin-catalog-backend@1.12.0-next.2 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/plugin-proxy-backend@0.3.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/plugin-app-backend@0.3.48-next.2 + - @backstage/plugin-linguist-backend@0.4.0-next.2 + - @backstage/plugin-techdocs-backend@1.6.5-next.2 + - @backstage/backend-defaults@0.2.0-next.2 + - @backstage/plugin-adr-backend@0.3.6-next.2 + - @backstage/plugin-azure-devops-backend@0.3.27-next.2 + - @backstage/plugin-badges-backend@0.2.3-next.2 + - @backstage/plugin-catalog-backend-module-unprocessed@0.2.0-next.2 + - @backstage/plugin-devtools-backend@0.1.3-next.2 + - @backstage/plugin-entity-feedback-backend@0.1.6-next.2 + - @backstage/plugin-kubernetes-backend@0.11.3-next.2 + - @backstage/plugin-lighthouse-backend@0.2.4-next.2 + - @backstage/plugin-permission-backend@0.5.23-next.2 + - @backstage/plugin-permission-node@0.7.11-next.2 + - @backstage/plugin-search-backend@1.4.0-next.2 + - @backstage/plugin-search-backend-node@1.2.4-next.2 + - @backstage/plugin-todo-backend@0.2.0-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## 0.0.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-module-techdocs@0.1.4-next.1 + - @backstage/plugin-search-backend-module-catalog@0.1.4-next.1 + - @backstage/plugin-search-backend-module-explore@0.1.4-next.1 + - @backstage/plugin-azure-devops-backend@0.3.27-next.1 + - @backstage/plugin-kubernetes-backend@0.11.3-next.1 + - @backstage/plugin-lighthouse-backend@0.2.4-next.1 + - @backstage/plugin-permission-backend@0.5.23-next.1 + - @backstage/plugin-scaffolder-backend@1.15.2-next.1 + - @backstage/backend-defaults@0.2.0-next.1 + - @backstage/plugin-devtools-backend@0.1.3-next.1 + - @backstage/plugin-techdocs-backend@1.6.5-next.1 + - @backstage/plugin-catalog-backend@1.12.0-next.1 + - @backstage/plugin-badges-backend@0.2.3-next.1 + - @backstage/plugin-search-backend@1.4.0-next.1 + - @backstage/plugin-todo-backend@0.2.0-next.1 + - @backstage/plugin-app-backend@0.3.48-next.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.2.0-next.1 + - @backstage/plugin-entity-feedback-backend@0.1.6-next.1 + - @backstage/plugin-search-backend-node@1.2.4-next.1 + - @backstage/plugin-linguist-backend@0.3.2-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/plugin-adr-backend@0.3.6-next.1 + - @backstage/plugin-permission-node@0.7.11-next.1 + - @backstage/plugin-permission-common@0.7.7 + ## 0.0.14-next.0 ### Patch Changes diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index 3043a96ebd..c2b923ed26 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -1,6 +1,6 @@ { "name": "example-backend-next", - "version": "0.0.14-next.0", + "version": "0.0.14", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", @@ -26,6 +26,7 @@ }, "dependencies": { "@backstage/backend-defaults": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", "@backstage/backend-tasks": "workspace:^", "@backstage/plugin-adr-backend": "workspace:^", "@backstage/plugin-app-backend": "workspace:^", @@ -42,6 +43,7 @@ "@backstage/plugin-permission-backend": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", "@backstage/plugin-permission-node": "workspace:^", + "@backstage/plugin-proxy-backend": "workspace:^", "@backstage/plugin-scaffolder-backend": "workspace:^", "@backstage/plugin-search-backend": "workspace:^", "@backstage/plugin-search-backend-module-catalog": "workspace:^", diff --git a/packages/backend-next/src/index.ts b/packages/backend-next/src/index.ts index fa7561e211..f3b1ea06f8 100644 --- a/packages/backend-next/src/index.ts +++ b/packages/backend-next/src/index.ts @@ -36,13 +36,13 @@ import { badgesPlugin } from '@backstage/plugin-badges-backend'; import { azureDevOpsPlugin } from '@backstage/plugin-azure-devops-backend'; import { linguistPlugin } from '@backstage/plugin-linguist-backend'; import { devtoolsPlugin } from '@backstage/plugin-devtools-backend'; -import { TaskScheduleDefinition } from '@backstage/backend-tasks'; import { adrPlugin } from '@backstage/plugin-adr-backend'; import { lighthousePlugin } from '@backstage/plugin-lighthouse-backend'; +import { proxyPlugin } from '@backstage/plugin-proxy-backend'; const backend = createBackend(); -backend.add(appPlugin({ appPackageName: 'example-app' })); +backend.add(appPlugin()); // Badges backend.add(badgesPlugin()); @@ -57,20 +57,7 @@ backend.add(devtoolsPlugin()); backend.add(entityFeedbackPlugin()); // Linguist -const linguistSchedule: TaskScheduleDefinition = { - frequency: { minutes: 2 }, - timeout: { minutes: 15 }, - initialDelay: { seconds: 15 }, -}; - -backend.add( - linguistPlugin({ - schedule: linguistSchedule, - age: { days: 30 }, - batchSize: 2, - useSourceLocation: false, - }), -); +backend.add(linguistPlugin()); // Todo backend.add(todoPlugin()); @@ -98,6 +85,9 @@ backend.add(kubernetesPlugin()); // Lighthouse backend.add(lighthousePlugin()); +// Proxy +backend.add(proxyPlugin()); + // Permissions backend.add(permissionPlugin()); backend.add(permissionModuleAllowAllPolicy()); diff --git a/packages/backend-openapi-utils/CHANGELOG.md b/packages/backend-openapi-utils/CHANGELOG.md index bd1d7f380a..fc3e52fa92 100644 --- a/packages/backend-openapi-utils/CHANGELOG.md +++ b/packages/backend-openapi-utils/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/backend-openapi-utils +## 0.0.3 + +### Patch Changes + +- ebeb77586975: Add a new `createRouter` method for generating an `express` router that validates against your spec. Also fixes a bug with the query parameters type resolution. +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/errors@1.2.1 + +## 0.0.3-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/errors@1.2.1 + ## 0.0.3-next.0 ### Patch Changes diff --git a/packages/backend-openapi-utils/package.json b/packages/backend-openapi-utils/package.json index 85a1677adb..102d8c36d6 100644 --- a/packages/backend-openapi-utils/package.json +++ b/packages/backend-openapi-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-openapi-utils", "description": "OpenAPI typescript support.", - "version": "0.0.3-next.0", + "version": "0.0.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,12 @@ "module": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/backend-openapi-utils" + }, "backstage": { "role": "node-library" }, diff --git a/packages/backend-plugin-api/CHANGELOG.md b/packages/backend-plugin-api/CHANGELOG.md index a77cdb71eb..9ea8b95c03 100644 --- a/packages/backend-plugin-api/CHANGELOG.md +++ b/packages/backend-plugin-api/CHANGELOG.md @@ -1,5 +1,63 @@ # @backstage/backend-plugin-api +## 0.6.0 + +### Minor Changes + +- c49785f00cab: **BREAKING**: It is no longer possible to declare options as being required with `createServiceFactory`. +- 629cbd194a87: **BREAKING**: Renamed `coreServices.config` to `coreServices.rootConfig`. +- 51987dbdaf87: **BREAKING**: Removed the ability to define options for plugins and modules. Existing options should be migrated to instead use either static configuration or extension points. +- d008aefef808: **BREAKING**: Removing shared environments concept from the new experimental backend system. + +### Patch Changes + +- c7aa4ff1793c: Allow modules to register extension points. +- cc9256a33bcc: Added new experimental `featureDiscoveryServiceRef`, available as an `/alpha` export. +- a6d7983f349c: **BREAKING**: Removed the `services` option from `createBackend`. Service factories are now `BackendFeature`s and should be installed with `backend.add(...)` instead. The following should be migrated: + + ```ts + const backend = createBackend({ services: [myCustomServiceFactory] }); + ``` + + To instead pass the service factory via `backend.add(...)`: + + ```ts + const backend = createBackend(); + backend.add(customRootLoggerServiceFactory); + ``` + +- Updated dependencies + - @backstage/plugin-auth-node@0.2.17 + - @backstage/backend-tasks@0.5.5 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + - @backstage/plugin-permission-common@0.7.7 + +## 0.6.0-next.2 + +### Patch Changes + +- cc9256a33bcc: Added new experimental `featureDiscoveryServiceRef`, available as an `/alpha` export. +- Updated dependencies + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## 0.6.0-next.1 + +### Minor Changes + +- 629cbd194a87: **BREAKING**: Renamed `coreServices.config` to `coreServices.rootConfig`. +- d008aefef808: **BREAKING**: Removing shared environments concept from the new experimental backend system. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + - @backstage/plugin-permission-common@0.7.7 + ## 0.5.5-next.0 ### Patch Changes diff --git a/packages/backend-plugin-api/alpha-api-report.md b/packages/backend-plugin-api/alpha-api-report.md new file mode 100644 index 0000000000..81b378a671 --- /dev/null +++ b/packages/backend-plugin-api/alpha-api-report.md @@ -0,0 +1,24 @@ +## API Report File for "@backstage/backend-plugin-api" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; +import { ServiceRef } from '@backstage/backend-plugin-api'; + +// @alpha (undocumented) +export interface FeatureDiscoveryService { + // (undocumented) + getBackendFeatures(): Promise<{ + features: Array; + }>; +} + +// @alpha +export const featureDiscoveryServiceRef: ServiceRef< + FeatureDiscoveryService, + 'root' +>; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index b3cbef993c..17cc521499 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -31,6 +31,11 @@ export interface BackendModuleConfig { // @public export interface BackendModuleRegistrationPoints { + // (undocumented) + registerExtensionPoint( + ref: ExtensionPoint, + impl: TExtensionPoint, + ): void; // (undocumented) registerInit< Deps extends { @@ -93,13 +98,10 @@ export type CacheServiceSetOptions = { ttl?: number; }; -// @public (undocumented) -export interface ConfigService extends Config {} - // @public export namespace coreServices { const cache: ServiceRef; - const config: ServiceRef; + const rootConfig: ServiceRef; const database: ServiceRef; const discovery: ServiceRef; const httpRouter: ServiceRef; @@ -117,14 +119,14 @@ export namespace coreServices { } // @public -export function createBackendModule( - config: BackendModuleConfig | ((...params: TOptions) => BackendModuleConfig), -): (...params: TOptions) => BackendFeature; +export function createBackendModule( + config: BackendModuleConfig, +): () => BackendFeature; // @public -export function createBackendPlugin( - config: BackendPluginConfig | ((...params: TOptions) => BackendPluginConfig), -): (...params: TOptions) => BackendFeature; +export function createBackendPlugin( + config: BackendPluginConfig, +): () => BackendFeature; // @public export function createExtensionPoint( @@ -155,18 +157,6 @@ export function createServiceFactory< config: (options?: TOpts) => RootServiceFactoryConfig, ): (options?: TOpts) => ServiceFactory; -// @public -export function createServiceFactory< - TService, - TImpl extends TService, - TDeps extends { - [name in string]: ServiceRef; - }, - TOpts extends object | undefined = undefined, ->( - config: (options: TOpts) => RootServiceFactoryConfig, -): (options: TOpts) => ServiceFactory; - // @public export function createServiceFactory< TService, @@ -195,23 +185,6 @@ export function createServiceFactory< ) => PluginServiceFactoryConfig, ): (options?: TOpts) => ServiceFactory; -// @public -export function createServiceFactory< - TService, - TImpl extends TService, - TDeps extends { - [name in string]: ServiceRef; - }, - TContext = undefined, - TOpts extends object | undefined = undefined, ->( - config: - | PluginServiceFactoryConfig - | (( - options: TOpts, - ) => PluginServiceFactoryConfig), -): (options: TOpts) => ServiceFactory; - // @public export function createServiceRef( config: ServiceRefConfig, @@ -222,15 +195,6 @@ export function createServiceRef( config: ServiceRefConfig, ): ServiceRef; -// @public -export function createSharedEnvironment< - TOptions extends [options?: object] = [], ->( - config: - | SharedBackendEnvironmentConfig - | ((...params: TOptions) => SharedBackendEnvironmentConfig), -): (...options: TOptions) => SharedBackendEnvironment; - // @public export interface DatabaseService { getClient(): Promise; @@ -389,6 +353,9 @@ export type ReadUrlResponse = { lastModifiedAt?: Date; }; +// @public (undocumented) +export interface RootConfigService extends Config {} + // @public (undocumented) export interface RootHttpRouterService { use(path: string, handler: Handler): void; @@ -442,9 +409,7 @@ export type SearchResponseFile = { export interface ServiceFactory< TService = unknown, TScope extends 'plugin' | 'root' = 'plugin' | 'root', -> { - // (undocumented) - $$type: '@backstage/ServiceFactory'; +> extends BackendFeature { // (undocumented) service: ServiceRef; } @@ -476,18 +441,6 @@ export interface ServiceRefConfig { scope?: TScope; } -// @public -export interface SharedBackendEnvironment { - // (undocumented) - $$type: '@backstage/SharedBackendEnvironment'; -} - -// @public -export interface SharedBackendEnvironmentConfig { - // (undocumented) - services?: ServiceFactoryOrFunction[]; -} - // @public export interface TokenManagerService { authenticate(token: string): Promise; diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index 91936a4c16..44a9d5c69c 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -1,17 +1,30 @@ { "name": "@backstage/backend-plugin-api", "description": "Core API used by Backstage backend plugins", - "version": "0.5.5-next.0", + "version": "0.6.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" }, "backstage": { "role": "node-library" }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.ts" + ], + "package.json": [ + "package.json" + ] + } + }, "homepage": "https://backstage.io", "repository": { "type": "git", diff --git a/packages/backend-plugin-api/src/alpha.ts b/packages/backend-plugin-api/src/alpha.ts new file mode 100644 index 0000000000..baee739f49 --- /dev/null +++ b/packages/backend-plugin-api/src/alpha.ts @@ -0,0 +1,35 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BackendFeature, + createServiceRef, +} from '@backstage/backend-plugin-api'; + +/** @alpha */ +export interface FeatureDiscoveryService { + getBackendFeatures(): Promise<{ features: Array }>; +} + +/** + * An optional service that can be used to dynamically load in additional BackendFeatures at runtime. + * @alpha + */ +export const featureDiscoveryServiceRef = + createServiceRef({ + id: 'core.featureDiscovery', + scope: 'root', + }); diff --git a/packages/backend-plugin-api/src/index.ts b/packages/backend-plugin-api/src/index.ts index 452fa046f9..8e0b23d20b 100644 --- a/packages/backend-plugin-api/src/index.ts +++ b/packages/backend-plugin-api/src/index.ts @@ -21,4 +21,5 @@ */ export * from './services'; +export type { BackendFeature } from './types'; export * from './wiring'; diff --git a/packages/backend-plugin-api/src/services/definitions/ConfigService.ts b/packages/backend-plugin-api/src/services/definitions/RootConfigService.ts similarity index 92% rename from packages/backend-plugin-api/src/services/definitions/ConfigService.ts rename to packages/backend-plugin-api/src/services/definitions/RootConfigService.ts index db9aa88dda..02343e4ee8 100644 --- a/packages/backend-plugin-api/src/services/definitions/ConfigService.ts +++ b/packages/backend-plugin-api/src/services/definitions/RootConfigService.ts @@ -19,4 +19,4 @@ import { Config } from '@backstage/config'; /** * @public */ -export interface ConfigService extends Config {} +export interface RootConfigService extends Config {} diff --git a/packages/backend-plugin-api/src/services/definitions/coreServices.ts b/packages/backend-plugin-api/src/services/definitions/coreServices.ts index 7dad94cebf..b42795d052 100644 --- a/packages/backend-plugin-api/src/services/definitions/coreServices.ts +++ b/packages/backend-plugin-api/src/services/definitions/coreServices.ts @@ -32,13 +32,13 @@ export namespace coreServices { }); /** - * The service reference for the root scoped {@link ConfigService}. + * The service reference for the root scoped {@link RootConfigService}. * * @public */ - export const config = createServiceRef< - import('./ConfigService').ConfigService - >({ id: 'core.config', scope: 'root' }); + export const rootConfig = createServiceRef< + import('./RootConfigService').RootConfigService + >({ id: 'core.rootConfig', scope: 'root' }); /** * The service reference for the plugin scoped {@link DatabaseService}. diff --git a/packages/backend-plugin-api/src/services/definitions/index.ts b/packages/backend-plugin-api/src/services/definitions/index.ts index ab0f0b84b1..98be8211db 100644 --- a/packages/backend-plugin-api/src/services/definitions/index.ts +++ b/packages/backend-plugin-api/src/services/definitions/index.ts @@ -20,7 +20,7 @@ export type { CacheServiceOptions, CacheServiceSetOptions, } from './CacheService'; -export type { ConfigService } from './ConfigService'; +export type { RootConfigService } from './RootConfigService'; export type { DatabaseService } from './DatabaseService'; export type { DiscoveryService } from './DiscoveryService'; export type { HttpRouterService } from './HttpRouterService'; diff --git a/packages/backend-plugin-api/src/services/system/types.test.ts b/packages/backend-plugin-api/src/services/system/types.test.ts index d3e9b9dd4e..4d0432505e 100644 --- a/packages/backend-plugin-api/src/services/system/types.test.ts +++ b/packages/backend-plugin-api/src/services/system/types.test.ts @@ -26,7 +26,7 @@ interface TestOptions { function unused(..._any: any[]) {} describe('createServiceFactory', () => { - it('should create a sync factory with no options', () => { + it('should create a sync factory', () => { const metaFactory = createServiceFactory({ service: ref, deps: {}, @@ -51,7 +51,7 @@ describe('createServiceFactory', () => { metaFactory(); }); - it('should create a sync root factory with no options', () => { + it('should create a sync root factory', () => { const metaFactory = createServiceFactory({ service: rootDep, deps: {}, @@ -75,7 +75,7 @@ describe('createServiceFactory', () => { metaFactory(); }); - it('should create a factory with no options', () => { + it('should create a factory', () => { const metaFactory = createServiceFactory({ service: ref, deps: {}, @@ -100,7 +100,7 @@ describe('createServiceFactory', () => { metaFactory(); }); - it('should create a factory with optional options', () => { + it('should create a factory with options', () => { const metaFactory = createServiceFactory((_opts?: { x: number }) => ({ service: ref, deps: {}, @@ -124,7 +124,8 @@ describe('createServiceFactory', () => { metaFactory(); }); - it('should create a factory with required options', () => { + it('should not be allowed to require options', () => { + // @ts-expect-error const metaFactory = createServiceFactory((_opts: { x: number }) => ({ service: ref, deps: {}, @@ -134,23 +135,9 @@ describe('createServiceFactory', () => { }, })); expect(metaFactory).toEqual(expect.any(Function)); - - // @ts-expect-error - metaFactory('string'); - // @ts-expect-error - metaFactory({}); - metaFactory({ x: 1 }); - // @ts-expect-error - metaFactory({ x: 1, y: 2 }); - // @ts-expect-error - metaFactory(null); - // @ts-expect-error - metaFactory(undefined); - // @ts-expect-error - metaFactory(); }); - it('should create a factory with optional options as interface', () => { + it('should create a factory with options as interface', () => { const metaFactory = createServiceFactory((_opts?: TestOptions) => ({ service: ref, deps: {}, @@ -174,32 +161,6 @@ describe('createServiceFactory', () => { metaFactory(); }); - it('should create a factory with required options as interface', () => { - const metaFactory = createServiceFactory((_opts: TestOptions) => ({ - service: ref, - deps: {}, - async createRootContext() {}, - async factory() { - return 'x'; - }, - })); - expect(metaFactory).toEqual(expect.any(Function)); - - // @ts-expect-error - metaFactory('string'); - // @ts-expect-error - metaFactory({}); - metaFactory({ x: 1 }); - // @ts-expect-error - metaFactory({ x: 1, y: 2 }); - // @ts-expect-error - metaFactory(null); - // @ts-expect-error - metaFactory(undefined); - // @ts-expect-error - metaFactory(); - }); - it('should create root scoped factory with dependencies', () => { const metaFactory = createServiceFactory({ service: createServiceRef({ id: 'foo', scope: 'root' }), @@ -226,7 +187,7 @@ describe('createServiceFactory', () => { metaFactory(); }); - it('should create root scoped factory with dependencies and optional options', () => { + it('should create root scoped factory with dependencies and options', () => { const metaFactory = createServiceFactory((_options?: TestOptions) => ({ service: createServiceRef({ id: 'foo', scope: 'root' }), deps: { @@ -325,49 +286,7 @@ describe('createServiceFactory', () => { metaFactory(); }); - it('should create factory with required options and dependencies', () => { - const metaFactory = createServiceFactory((_opts: TestOptions) => ({ - service: ref, - deps: { - root: rootDep, - plugin: pluginDep, - }, - async createRootContext({ root }) { - const root1: number = root; - // @ts-expect-error - const root2: string = root; - unused(root1, root2); - return { root }; - }, - async factory({ plugin }, { root }) { - const root1: number = root; - // @ts-expect-error - const root2: string = root; - const plugin3: boolean = plugin; - // @ts-expect-error - const plugin4: number = plugin; - unused(root1, root2, plugin3, plugin4); - return 'x'; - }, - })); - expect(metaFactory).toEqual(expect.any(Function)); - - // @ts-expect-error - metaFactory('string'); - // @ts-expect-error - metaFactory({}); - metaFactory({ x: 1 }); - // @ts-expect-error - metaFactory({ x: 1, y: 2 }); - // @ts-expect-error - metaFactory(null); - // @ts-expect-error - metaFactory(undefined); - // @ts-expect-error - metaFactory(); - }); - - it('should create factory with optional options and dependencies', () => { + it('should create factory with options and dependencies', () => { const metaFactory = createServiceFactory((_opts?: TestOptions) => ({ service: ref, deps: { diff --git a/packages/backend-plugin-api/src/services/system/types.ts b/packages/backend-plugin-api/src/services/system/types.ts index 190ef7c13e..bea53dc1ed 100644 --- a/packages/backend-plugin-api/src/services/system/types.ts +++ b/packages/backend-plugin-api/src/services/system/types.ts @@ -14,6 +14,8 @@ * limitations under the License. */ +import { BackendFeature } from '../../types'; + /** * TODO * @@ -51,9 +53,7 @@ export type ServiceRef< export interface ServiceFactory< TService = unknown, TScope extends 'plugin' | 'root' = 'plugin' | 'root', -> { - $$type: '@backstage/ServiceFactory'; - +> extends BackendFeature { service: ServiceRef; } @@ -191,20 +191,6 @@ export function createServiceFactory< >( config: (options?: TOpts) => RootServiceFactoryConfig, ): (options?: TOpts) => ServiceFactory; -/** - * Creates a root scoped service factory with required options. - * - * @public - * @param config - The service factory configuration. - */ -export function createServiceFactory< - TService, - TImpl extends TService, - TDeps extends { [name in string]: ServiceRef }, - TOpts extends object | undefined = undefined, ->( - config: (options: TOpts) => RootServiceFactoryConfig, -): (options: TOpts) => ServiceFactory; /** * Creates a plugin scoped service factory without options. * @@ -237,25 +223,6 @@ export function createServiceFactory< options?: TOpts, ) => PluginServiceFactoryConfig, ): (options?: TOpts) => ServiceFactory; -/** - * Creates a plugin scoped service factory with required options. - * - * @public - * @param config - The service factory configuration. - */ -export function createServiceFactory< - TService, - TImpl extends TService, - TDeps extends { [name in string]: ServiceRef }, - TContext = undefined, - TOpts extends object | undefined = undefined, ->( - config: - | PluginServiceFactoryConfig - | (( - options: TOpts, - ) => PluginServiceFactoryConfig), -): (options: TOpts) => ServiceFactory; export function createServiceFactory< TService, TImpl extends TService, @@ -281,7 +248,7 @@ export function createServiceFactory< if (anyConf.service.scope === 'root') { const c = anyConf as RootServiceFactoryConfig; return { - $$type: '@backstage/ServiceFactory', + $$type: '@backstage/BackendFeature', version: 'v1', service: c.service, deps: c.deps, @@ -295,7 +262,7 @@ export function createServiceFactory< TDeps >; return { - $$type: '@backstage/ServiceFactory', + $$type: '@backstage/BackendFeature', version: 'v1', service: c.service, ...('createRootContext' in c diff --git a/packages/backend-plugin-api/src/types.ts b/packages/backend-plugin-api/src/types.ts new file mode 100644 index 0000000000..59f1106fab --- /dev/null +++ b/packages/backend-plugin-api/src/types.ts @@ -0,0 +1,29 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @internal */ +export interface BackendFeatureFactory< + TOptions extends [options?: object] = [], +> { + (...options: TOptions): BackendFeature; + $$type: '@backstage/BackendFeatureFactory'; +} + +/** @public */ +export interface BackendFeature { + // NOTE: This type is opaque in order to simplify future API evolution. + $$type: '@backstage/BackendFeature'; +} diff --git a/packages/backend-plugin-api/src/wiring/createSharedEnvironment.test.ts b/packages/backend-plugin-api/src/wiring/createSharedEnvironment.test.ts deleted file mode 100644 index 381a4799d2..0000000000 --- a/packages/backend-plugin-api/src/wiring/createSharedEnvironment.test.ts +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2023 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - createServiceFactory, - createServiceRef, - ServiceFactoryOrFunction, -} from '../services'; -import { - createSharedEnvironment, - InternalSharedBackendEnvironment, -} from './createSharedEnvironment'; - -const fooService = createServiceRef({ id: 'foo', scope: 'root' }); -const fooFactory = createServiceFactory({ - service: fooService, - deps: {}, - async factory() { - return 'foo'; - }, -}); - -const barService = createServiceRef({ id: 'bar', scope: 'root' }); -const barFactory = createServiceFactory({ - service: barService, - deps: {}, - async factory() { - return 0xba5; - }, -}); - -describe('createSharedEnvironment', () => { - it('should create an empty shared environment', () => { - const env = createSharedEnvironment({}); - expect(env).toBeDefined(); - const internalEnv = env() as unknown as InternalSharedBackendEnvironment; - expect(internalEnv).toEqual({ - $$type: '@backstage/SharedBackendEnvironment', - version: 'v1', - services: undefined, - }); - }); - - it('should create a shared environment with services', () => { - const env = createSharedEnvironment({ - services: [fooFactory, barFactory()], - }); - const internalEnv = env() as unknown as InternalSharedBackendEnvironment; - expect(internalEnv.version).toBe('v1'); - expect(internalEnv.services?.length).toBe(2); - expect(internalEnv.services?.[0]?.service.id).toBe('foo'); - expect(internalEnv.services?.[1]?.service.id).toBe('bar'); - }); - - it('should create a shared environment with options', () => { - const env = createSharedEnvironment((options?: { withFoo?: boolean }) => { - const services = new Array(); - if (options?.withFoo) { - services.push(fooFactory()); - } - services.push(barFactory); - return { services }; - }); - const internalEnv1 = env() as unknown as InternalSharedBackendEnvironment; - expect(internalEnv1.version).toBe('v1'); - expect(internalEnv1.services?.length).toBe(1); - expect(internalEnv1.services?.[0]?.service.id).toBe('bar'); - - const internalEnv2 = env({ - withFoo: true, - }) as unknown as InternalSharedBackendEnvironment; - expect(internalEnv2.version).toBe('v1'); - expect(internalEnv2.services?.length).toBe(2); - expect(internalEnv2.services?.[0]?.service.id).toBe('foo'); - expect(internalEnv2.services?.[1]?.service.id).toBe('bar'); - }); - - it('should not allow duplicate service factories', () => { - expect(() => - createSharedEnvironment({ - services: [fooFactory, fooFactory()], - })(), - ).toThrow( - "Duplicate service implementations provided in shared environment for 'foo'", - ); - }); -}); diff --git a/packages/backend-plugin-api/src/wiring/createSharedEnvironment.ts b/packages/backend-plugin-api/src/wiring/createSharedEnvironment.ts deleted file mode 100644 index 57f0533523..0000000000 --- a/packages/backend-plugin-api/src/wiring/createSharedEnvironment.ts +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2023 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { ServiceFactory, ServiceFactoryOrFunction } from '../services'; - -/** - * The configuration options passed to {@link createSharedEnvironment}. - * - * @public - */ -export interface SharedBackendEnvironmentConfig { - services?: ServiceFactoryOrFunction[]; -} - -/** - * An opaque type that represents the contents of a shared backend environment. - * - * @public - */ -export interface SharedBackendEnvironment { - $$type: '@backstage/SharedBackendEnvironment'; - - // NOTE: This type is opaque in order to allow for future API evolution without - // cluttering the external API. For example we might want to add support - // for more powerful callback based backend modifications. - // - // By making this opaque we also ensure that the type doesn't become an input - // type that we need to care about, as it would otherwise be possible to pass - // a custom environment definition to `createBackend`, which we don't want. -} - -/** - * This type is NOT supposed to be used by anyone except internally by the - * backend-app-api package. - * - * @internal - */ -export interface InternalSharedBackendEnvironment { - version: 'v1'; - services?: ServiceFactory[]; -} - -/** - * Creates a shared backend environment which can be used to create multiple - * backends. - * - * @public - */ -export function createSharedEnvironment< - TOptions extends [options?: object] = [], ->( - config: - | SharedBackendEnvironmentConfig - | ((...params: TOptions) => SharedBackendEnvironmentConfig), -): (...options: TOptions) => SharedBackendEnvironment { - const configCallback = typeof config === 'function' ? config : () => config; - - return (...options) => { - const actualConfig = configCallback(...options); - const services = actualConfig?.services?.map(sf => - typeof sf === 'function' ? sf() : sf, - ); - - const exists = new Set(); - const duplicates = new Set(); - for (const { service } of services ?? []) { - if (exists.has(service.id)) { - duplicates.add(service.id); - } else { - exists.add(service.id); - } - } - - if (duplicates.size > 0) { - const dupStr = [...duplicates].map(id => `'${id}'`).join(', '); - throw new Error( - `Duplicate service implementations provided in shared environment for ${dupStr}`, - ); - } - - // Here to ensure type safety in this internal implementation. - const env: SharedBackendEnvironment & InternalSharedBackendEnvironment = { - $$type: '@backstage/SharedBackendEnvironment', - version: 'v1', - services, - }; - return env; - }; -} diff --git a/packages/backend-plugin-api/src/wiring/factories.test.ts b/packages/backend-plugin-api/src/wiring/factories.test.ts index ae199d84e4..1fd05a1605 100644 --- a/packages/backend-plugin-api/src/wiring/factories.test.ts +++ b/packages/backend-plugin-api/src/wiring/factories.test.ts @@ -33,22 +33,19 @@ describe('createExtensionPoint', () => { describe('createBackendPlugin', () => { it('should create a BackendPlugin', () => { - const plugin = createBackendPlugin((_options: { a: string }) => ({ + const plugin = createBackendPlugin({ pluginId: 'x', register(r) { r.registerInit({ deps: {}, async init() {} }); }, - })); + }); expect(plugin).toBeDefined(); - expect(plugin({ a: 'a' })).toBeDefined(); - expect(plugin({ a: 'a' })).toEqual({ + expect(plugin()).toEqual({ $$type: '@backstage/BackendFeature', version: 'v1', getRegistrations: expect.any(Function), }); - expect( - (plugin({ a: 'a' }) as InternalBackendFeature).getRegistrations(), - ).toEqual([ + expect((plugin() as InternalBackendFeature).getRegistrations()).toEqual([ { type: 'plugin', pluginId: 'x', @@ -60,95 +57,32 @@ describe('createBackendPlugin', () => { }, ]); // @ts-expect-error - expect(plugin()).toBeDefined(); - // @ts-expect-error - expect(plugin({ b: 'b' })).toBeDefined(); - }); - - it('should create plugins with optional options', () => { - const plugin = createBackendPlugin((_options?: { a: string }) => ({ - pluginId: 'x', - register() {}, - })); - expect(plugin).toBeDefined(); expect(plugin({ a: 'a' })).toBeDefined(); - expect(plugin()).toBeDefined(); - // @ts-expect-error - expect(plugin({ b: 'b' })).toBeDefined(); - }); - - it('should create plugins without options', () => { - const plugin = createBackendPlugin({ - pluginId: 'x', - register() {}, - }); - expect(plugin).toBeDefined(); - // @ts-expect-error - expect(plugin({ a: 'a' })).toBeDefined(); - // @ts-expect-error - expect(plugin({})).toBeDefined(); - }); - - it('should create a BackendPlugin with options as interface', () => { - interface TestOptions { - a: string; - } - const plugin = createBackendPlugin((_options: TestOptions) => ({ - pluginId: 'x', - register() {}, - })); - expect(plugin).toBeDefined(); - expect(plugin({ a: 'a' })).toBeDefined(); - expect(plugin({ a: 'a' })).toEqual({ - $$type: '@backstage/BackendFeature', - version: 'v1', - getRegistrations: expect.any(Function), - }); - // @ts-expect-error - expect(plugin()).toBeDefined(); - // @ts-expect-error - expect(plugin({ b: 'b' })).toBeDefined(); - }); - - it('should create plugins with optional options as interface', () => { - interface TestOptions { - a: string; - } - const plugin = createBackendPlugin((_options?: TestOptions) => ({ - pluginId: 'x', - register() {}, - })); - expect(plugin).toBeDefined(); - expect(plugin({ a: 'a' })).toBeDefined(); - expect(plugin()).toBeDefined(); - // @ts-expect-error - expect(plugin({ b: 'b' })).toBeDefined(); }); }); describe('createBackendModule', () => { it('should create a BackendModule', () => { - const mod = createBackendModule((_options: { a: string }) => ({ + const mod = createBackendModule({ pluginId: 'x', moduleId: 'y', register(r) { r.registerInit({ deps: {}, async init() {} }); }, - })); + }); expect(mod).toBeDefined(); - expect(mod({ a: 'a' })).toBeDefined(); - expect(mod({ a: 'a' })).toEqual({ + expect(mod()).toBeDefined(); + expect(mod()).toEqual({ $$type: '@backstage/BackendFeature', version: 'v1', getRegistrations: expect.any(Function), }); - expect( - (mod({ a: 'a' }) as InternalBackendFeature).getRegistrations(), - ).toEqual([ + expect((mod() as InternalBackendFeature).getRegistrations()).toEqual([ { type: 'module', pluginId: 'x', moduleId: 'y', + extensionPoints: [], init: { deps: expect.any(Object), func: expect.any(Function), @@ -156,72 +90,6 @@ describe('createBackendModule', () => { }, ]); // @ts-expect-error - expect(mod()).toBeDefined(); - // @ts-expect-error - expect(mod({ b: 'b' })).toBeDefined(); - }); - - it('should create modules with optional options', () => { - const mod = createBackendModule((_options?: { a: string }) => ({ - pluginId: 'x', - moduleId: 'y', - register() {}, - })); - expect(mod).toBeDefined(); expect(mod({ a: 'a' })).toBeDefined(); - expect(mod()).toBeDefined(); - // @ts-expect-error - expect(mod({ b: 'b' })).toBeDefined(); - }); - - it('should create modules without options', () => { - const mod = createBackendModule({ - pluginId: 'x', - moduleId: 'y', - register() {}, - }); - expect(mod).toBeDefined(); - // @ts-expect-error - expect(mod({ a: 'a' })).toBeDefined(); - // @ts-expect-error - expect(mod({})).toBeDefined(); - }); - - it('should create a BackendModule as interface', () => { - interface TestOptions { - a: string; - } - const mod = createBackendModule((_options: TestOptions) => ({ - pluginId: 'x', - moduleId: 'y', - register() {}, - })); - expect(mod).toBeDefined(); - expect(mod({ a: 'a' })).toBeDefined(); - expect(mod({ a: 'a' })).toEqual({ - $$type: '@backstage/BackendFeature', - version: 'v1', - getRegistrations: expect.any(Function), - }); - // @ts-expect-error - expect(mod()).toBeDefined(); - // @ts-expect-error - expect(mod({ b: 'b' })).toBeDefined(); - }); - - it('should create modules with optional options as interface', () => { - interface TestOptions { - a: string; - } - const mod = createBackendModule((_options?: TestOptions) => ({ - pluginId: 'x', - moduleId: 'y', - register() {}, - })); - expect(mod).toBeDefined(); - expect(mod({ a: 'a' })).toBeDefined(); - expect(mod()).toBeDefined(); - // @ts-expect-error - expect(mod({ b: 'b' })).toBeDefined(); }); }); diff --git a/packages/backend-plugin-api/src/wiring/factories.ts b/packages/backend-plugin-api/src/wiring/factories.ts index 928c933af0..9fa0f87bab 100644 --- a/packages/backend-plugin-api/src/wiring/factories.ts +++ b/packages/backend-plugin-api/src/wiring/factories.ts @@ -14,12 +14,11 @@ * limitations under the License. */ +import { BackendFeature, BackendFeatureFactory } from '../types'; import { BackendModuleRegistrationPoints, BackendPluginRegistrationPoints, - BackendFeature, ExtensionPoint, - InternalBackendFeature, InternalBackendModuleRegistration, InternalBackendPluginRegistration, } from './types'; @@ -85,13 +84,10 @@ export interface BackendPluginConfig { * @see {@link https://backstage.io/docs/backend-system/architecture/plugins | The architecture of plugins} * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns} */ -export function createBackendPlugin( - config: BackendPluginConfig | ((...params: TOptions) => BackendPluginConfig), -): (...params: TOptions) => BackendFeature { - const configCallback = typeof config === 'function' ? config : () => config; - return (...options: TOptions): InternalBackendFeature => { - const c = configCallback(...options); - +export function createBackendPlugin( + config: BackendPluginConfig, +): () => BackendFeature { + const factory: BackendFeatureFactory = () => { let registrations: InternalBackendPluginRegistration[]; return { @@ -106,7 +102,7 @@ export function createBackendPlugin( let init: InternalBackendPluginRegistration['init'] | undefined = undefined; - c.register({ + config.register({ registerExtensionPoint(ext, impl) { if (init) { throw new Error( @@ -128,14 +124,14 @@ export function createBackendPlugin( if (!init) { throw new Error( - `registerInit was not called by register in ${c.pluginId}`, + `registerInit was not called by register in ${config.pluginId}`, ); } registrations = [ { type: 'plugin', - pluginId: c.pluginId, + pluginId: config.pluginId, extensionPoints, init, }, @@ -144,6 +140,9 @@ export function createBackendPlugin( }, }; }; + factory.$$type = '@backstage/BackendFeatureFactory'; + + return factory; } /** @@ -155,13 +154,14 @@ export function createBackendPlugin( */ export interface BackendModuleConfig { /** - * The ID of this plugin. + * Should exactly match the `id` of the plugin that the module extends. * * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns} */ pluginId: string; + /** - * Should exactly match the `id` of the plugin that the module extends. + * The ID of this module, used to identify the module and ensure that it is not installed twice. */ moduleId: string; register(reg: BackendModuleRegistrationPoints): void; @@ -174,13 +174,10 @@ export interface BackendModuleConfig { * @see {@link https://backstage.io/docs/backend-system/architecture/modules | The architecture of modules} * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns} */ -export function createBackendModule( - config: BackendModuleConfig | ((...params: TOptions) => BackendModuleConfig), -): (...params: TOptions) => BackendFeature { - const configCallback = typeof config === 'function' ? config : () => config; - return (...options: TOptions): InternalBackendFeature => { - const c = configCallback(...options); - +export function createBackendModule( + config: BackendModuleConfig, +): () => BackendFeature { + const factory: BackendFeatureFactory = () => { let registrations: InternalBackendModuleRegistration[]; return { @@ -190,10 +187,20 @@ export function createBackendModule( if (registrations) { return registrations; } + const extensionPoints: InternalBackendPluginRegistration['extensionPoints'] = + []; let init: InternalBackendModuleRegistration['init'] | undefined = undefined; - c.register({ + config.register({ + registerExtensionPoint(ext, impl) { + if (init) { + throw new Error( + 'registerExtensionPoint called after registerInit', + ); + } + extensionPoints.push([ext, impl]); + }, registerInit(regInit) { if (init) { throw new Error('registerInit must only be called once'); @@ -207,15 +214,16 @@ export function createBackendModule( if (!init) { throw new Error( - `registerInit was not called by register in ${c.moduleId} module for ${c.pluginId}`, + `registerInit was not called by register in ${config.moduleId} module for ${config.pluginId}`, ); } registrations = [ { type: 'module', - pluginId: c.pluginId, - moduleId: c.moduleId, + pluginId: config.pluginId, + moduleId: config.moduleId, + extensionPoints, init, }, ]; @@ -223,4 +231,7 @@ export function createBackendModule( }, }; }; + factory.$$type = '@backstage/BackendFeatureFactory'; + + return factory; } diff --git a/packages/backend-plugin-api/src/wiring/index.ts b/packages/backend-plugin-api/src/wiring/index.ts index 242301ea4d..49f15c0b55 100644 --- a/packages/backend-plugin-api/src/wiring/index.ts +++ b/packages/backend-plugin-api/src/wiring/index.ts @@ -14,11 +14,6 @@ * limitations under the License. */ -export { createSharedEnvironment } from './createSharedEnvironment'; -export type { - SharedBackendEnvironment, - SharedBackendEnvironmentConfig, -} from './createSharedEnvironment'; export type { BackendModuleConfig, BackendPluginConfig, @@ -32,6 +27,5 @@ export { export type { BackendModuleRegistrationPoints, BackendPluginRegistrationPoints, - BackendFeature, ExtensionPoint, } from './types'; diff --git a/packages/backend-plugin-api/src/wiring/types.ts b/packages/backend-plugin-api/src/wiring/types.ts index c81ee3ceb7..55d43ccb7c 100644 --- a/packages/backend-plugin-api/src/wiring/types.ts +++ b/packages/backend-plugin-api/src/wiring/types.ts @@ -15,6 +15,7 @@ */ import { ServiceRef } from '../services/system/types'; +import { BackendFeature } from '../types'; /** * TODO @@ -59,6 +60,10 @@ export interface BackendPluginRegistrationPoints { * @public */ export interface BackendModuleRegistrationPoints { + registerExtensionPoint( + ref: ExtensionPoint, + impl: TExtensionPoint, + ): void; registerInit(options: { deps: { [name in keyof Deps]: ServiceRef | ExtensionPoint; @@ -67,12 +72,6 @@ export interface BackendModuleRegistrationPoints { }): void; } -/** @public */ -export interface BackendFeature { - // NOTE: This type is opaque in order to simplify future API evolution. - $$type: '@backstage/BackendFeature'; -} - /** @internal */ export interface InternalBackendFeature extends BackendFeature { version: 'v1'; @@ -97,6 +96,7 @@ export interface InternalBackendModuleRegistration { pluginId: string; moduleId: string; type: 'module'; + extensionPoints: Array, unknown]>; init: { deps: Record | ExtensionPoint>; func(deps: Record): Promise; diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md index ec1dd319ea..11a039e053 100644 --- a/packages/backend-tasks/CHANGELOG.md +++ b/packages/backend-tasks/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/backend-tasks +## 0.5.5 + +### Patch Changes + +- dfd1b6b2fc33: Make `readTaskScheduleDefinitionFromConfig` properly handle bad inputs +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## 0.5.5-next.2 + +### Patch Changes + +- dfd1b6b2fc33: Make `readTaskScheduleDefinitionFromConfig` properly handle bad inputs +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + +## 0.5.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + ## 0.5.5-next.0 ### Patch Changes diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index 4c0e4fd27e..ca9129078e 100644 --- a/packages/backend-tasks/package.json +++ b/packages/backend-tasks/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-tasks", "description": "Common distributed task management library for Backstage backends", - "version": "0.5.5-next.0", + "version": "0.5.5", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.test.ts b/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.test.ts index fc2a045614..21f51954b5 100644 --- a/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.test.ts +++ b/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.test.ts @@ -76,7 +76,7 @@ describe('readTaskScheduleDefinitionFromConfig', () => { ); }); - it('invalid frequency value', () => { + it('invalid frequency key', () => { const config = new ConfigReader({ frequency: { invalid: 'value', @@ -89,6 +89,19 @@ describe('readTaskScheduleDefinitionFromConfig', () => { ); }); + it('invalid frequency value', () => { + const config = new ConfigReader({ + frequency: { + minutes: 'value', + }, + timeout: 'PT3M', + }); + + expect(() => readTaskScheduleDefinitionFromConfig(config)).toThrow( + "Unable to convert config value for key 'frequency.minutes' in 'mock-config' to a number", + ); + }); + it('frequency value with additional invalid prop', () => { const config = new ConfigReader({ frequency: { diff --git a/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.ts b/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.ts index 1448a328f8..b31cf68f74 100644 --- a/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.ts +++ b/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.ts @@ -15,7 +15,7 @@ */ import { Config } from '@backstage/config'; -import { HumanDuration, JsonObject } from '@backstage/types'; +import { HumanDuration } from '@backstage/types'; import { TaskScheduleDefinition } from './types'; import { Duration } from 'luxon'; @@ -31,29 +31,48 @@ const propsOfHumanDuration = [ ]; function convertToHumanDuration(config: Config, key: string): HumanDuration { - const props = config.getConfig(key).keys(); - if (!props.find(prop => propsOfHumanDuration.includes(prop))) { + // Ensures that the root is an object + const root = config.getConfig(key); + + const result: Record = {}; + let found = false; + for (const prop of propsOfHumanDuration) { + const value = root.getOptionalNumber(prop); + if (value !== undefined) { + result[prop] = value; + found = true; + } + } + + if (!found) { throw new Error( `HumanDuration needs at least one of: ${propsOfHumanDuration}`, ); } - const invalidProps = props.filter( - prop => !propsOfHumanDuration.includes(prop), - ); + const invalidProps = root + .keys() + .filter(prop => !propsOfHumanDuration.includes(prop)); if (invalidProps.length > 0) { throw new Error( `HumanDuration does not contain properties: ${invalidProps}`, ); } - return config.get(key) as HumanDuration; + return result as HumanDuration; } function readDuration(config: Config, key: string): Duration | HumanDuration { - return typeof config.get(key) === 'string' - ? Duration.fromISO(config.getString(key)) - : convertToHumanDuration(config, key); + if (typeof config.get(key) === 'string') { + const value = config.getString(key); + const duration = Duration.fromISO(value); + if (!duration.isValid) { + throw new Error(`Invalid duration: ${value}`); + } + return duration; + } + + return convertToHumanDuration(config, key); } function readCronOrDuration( diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index 2d40873bb9..d6eec9f7ed 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,61 @@ # @backstage/backend-test-utils +## 0.2.0 + +### Minor Changes + +- b9c57a4f857e: **BREAKING**: Renamed `mockServices.config` to `mockServices.rootConfig`. +- a6d7983f349c: **BREAKING**: Removed the `services` option from `createBackend`. Service factories are now `BackendFeature`s and should be installed with `backend.add(...)` instead. The following should be migrated: + + ```ts + const backend = createBackend({ services: [myCustomServiceFactory] }); + ``` + + To instead pass the service factory via `backend.add(...)`: + + ```ts + const backend = createBackend(); + backend.add(customRootLoggerServiceFactory); + ``` + +### Patch Changes + +- ae9304818136: Add needed constants and constructs to support PostgreSQL version 14 as test database +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-app-api@0.5.0 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + +## 0.2.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-app-api@0.5.0-next.2 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## 0.2.0-next.1 + +### Minor Changes + +- b9c57a4f857e: **BREAKING**: Renamed `mockServices.config` to `mockServices.rootConfig`. + +### Patch Changes + +- ae9304818136: Add needed constants and constructs to support PostgreSQL version 14 as test database +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-app-api@0.5.0-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + ## 0.1.40-next.0 ### Patch Changes diff --git a/packages/backend-test-utils/api-report.md b/packages/backend-test-utils/api-report.md index 358b51071f..d086b1d2ae 100644 --- a/packages/backend-test-utils/api-report.md +++ b/packages/backend-test-utils/api-report.md @@ -6,7 +6,6 @@ import { Backend } from '@backstage/backend-app-api'; import { BackendFeature } from '@backstage/backend-plugin-api'; import { CacheService } from '@backstage/backend-plugin-api'; -import { ConfigService } from '@backstage/backend-plugin-api'; import { DatabaseService } from '@backstage/backend-plugin-api'; import { ExtendedHttpServer } from '@backstage/backend-app-api'; import { ExtensionPoint } from '@backstage/backend-plugin-api'; @@ -18,10 +17,10 @@ import { Knex } from 'knex'; import { LifecycleService } from '@backstage/backend-plugin-api'; import { LoggerService } from '@backstage/backend-plugin-api'; import { PermissionsService } from '@backstage/backend-plugin-api'; +import { RootConfigService } from '@backstage/backend-plugin-api'; import { RootLifecycleService } from '@backstage/backend-plugin-api'; import { SchedulerService } from '@backstage/backend-plugin-api'; import { ServiceFactory } from '@backstage/backend-plugin-api'; -import { ServiceRef } from '@backstage/backend-plugin-api'; import { TokenManagerService } from '@backstage/backend-plugin-api'; import { UrlReaderService } from '@backstage/backend-plugin-api'; @@ -36,19 +35,6 @@ export namespace mockServices { factory: () => ServiceFactory; } // (undocumented) - export function config(options?: config.Options): ConfigService; - // (undocumented) - export namespace config { - // (undocumented) - export type Options = { - data?: JsonObject; - }; - const // (undocumented) - factory: ( - options?: Options | undefined, - ) => ServiceFactory; - } - // (undocumented) export namespace database { const // (undocumented) factory: () => ServiceFactory; @@ -83,6 +69,19 @@ export namespace mockServices { factory: () => ServiceFactory; } // (undocumented) + export function rootConfig(options?: rootConfig.Options): RootConfigService; + // (undocumented) + export namespace rootConfig { + // (undocumented) + export type Options = { + data?: JsonObject; + }; + const // (undocumented) + factory: ( + options?: Options | undefined, + ) => ServiceFactory; + } + // (undocumented) export namespace rootLifecycle { const // (undocumented) factory: () => ServiceFactory; @@ -127,11 +126,8 @@ export function setupRequestMockHandlers(worker: { }): void; // @public (undocumented) -export function startTestBackend< - TServices extends any[], - TExtensionPoints extends any[], ->( - options: TestBackendOptions, +export function startTestBackend( + options: TestBackendOptions, ): Promise; // @public (undocumented) @@ -140,10 +136,7 @@ export interface TestBackend extends Backend { } // @public (undocumented) -export interface TestBackendOptions< - TServices extends any[], - TExtensionPoints extends any[], -> { +export interface TestBackendOptions { // (undocumented) extensionPoints?: readonly [ ...{ @@ -154,20 +147,12 @@ export interface TestBackendOptions< }, ]; // (undocumented) - features?: BackendFeature[]; - // (undocumented) - services?: readonly [ - ...{ - [index in keyof TServices]: - | ServiceFactory - | (() => ServiceFactory) - | [ServiceRef, Partial]; - }, - ]; + features?: Array BackendFeature)>; } // @public export type TestDatabaseId = + | 'POSTGRES_14' | 'POSTGRES_13' | 'POSTGRES_12' | 'POSTGRES_11' diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index d9d904357b..02cb1d5cf9 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.40-next.0", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-test-utils/src/database/TestDatabases.test.ts b/packages/backend-test-utils/src/database/TestDatabases.test.ts index be29a42806..d766d38815 100644 --- a/packages/backend-test-utils/src/database/TestDatabases.test.ts +++ b/packages/backend-test-utils/src/database/TestDatabases.test.ts @@ -59,6 +59,37 @@ describe('TestDatabases', () => { describe('each connect', () => { const dbs = TestDatabases.create(); + itIfDocker( + 'obeys a provided connection string for postgres 14', + async () => { + const { host, port, user, password, stop } = + await startPostgresContainer('postgres:14'); + + try { + // Leave a mark + process.env.BACKSTAGE_TEST_DATABASE_POSTGRES14_CONNECTION_STRING = `postgresql://${user}:${password}@${host}:${port}`; + const input = await dbs.init('POSTGRES_14'); + await input.schema.createTable('a', table => + table.string('x').primary(), + ); + await input.insert({ x: 'y' }).into('a'); + + // Look for the mark + const database = input.client.config.connection.database; + const output = knexFactory({ + client: 'pg', + connection: { host, port, user, password, database }, + }); + // eslint-disable-next-line jest/no-standalone-expect + await expect(output.select('x').from('a')).resolves.toEqual([ + { x: 'y' }, + ]); + } finally { + await stop(); + } + }, + ); + itIfDocker( 'obeys a provided connection string for postgres 13', async () => { diff --git a/packages/backend-test-utils/src/database/types.ts b/packages/backend-test-utils/src/database/types.ts index 8c1d6f5193..a7bfdeb12d 100644 --- a/packages/backend-test-utils/src/database/types.ts +++ b/packages/backend-test-utils/src/database/types.ts @@ -24,6 +24,7 @@ import { getDockerImageForName } from '../util/getDockerImageForName'; * @public */ export type TestDatabaseId = + | 'POSTGRES_14' | 'POSTGRES_13' | 'POSTGRES_12' | 'POSTGRES_11' @@ -46,6 +47,13 @@ export type Instance = { export const allDatabases: Record = Object.freeze({ + POSTGRES_14: { + name: 'Postgres 14.x', + driver: 'pg', + dockerImageName: getDockerImageForName('postgres:14'), + connectionStringEnvironmentVariableName: + 'BACKSTAGE_TEST_DATABASE_POSTGRES14_CONNECTION_STRING', + }, POSTGRES_13: { name: 'Postgres 13.x', driver: 'pg', diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts index 8a3125214c..0455b9f1ae 100644 --- a/packages/backend-test-utils/src/next/services/mockServices.ts +++ b/packages/backend-test-utils/src/next/services/mockServices.ts @@ -15,7 +15,7 @@ */ import { - ConfigService, + RootConfigService, coreServices, createServiceFactory, IdentityService, @@ -61,13 +61,13 @@ function simpleFactory< * @public */ export namespace mockServices { - export function config(options?: config.Options): ConfigService { + export function rootConfig(options?: rootConfig.Options): RootConfigService { return new ConfigReader(options?.data, 'mock-config'); } - export namespace config { + export namespace rootConfig { export type Options = { data?: JsonObject }; - export const factory = simpleFactory(coreServices.config, config); + export const factory = simpleFactory(coreServices.rootConfig, rootConfig); } export function rootLogger(options?: rootLogger.Options): LoggerService { diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts index aa93a7dae1..b127712927 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts @@ -31,7 +31,6 @@ import { startTestBackend } from './TestBackend'; let globalTestBackendHasBeenStopped = false; beforeAll(async () => { await startTestBackend({ - services: [], features: [ createBackendModule({ moduleId: 'test.module', @@ -46,7 +45,7 @@ beforeAll(async () => { }, }); }, - })(), + }), ], }); }); @@ -68,17 +67,37 @@ describe('TestBackend', () => { const extensionPoint5 = createExtensionPoint({ id: 'b5' }); await expect( startTestBackend({ - services: [ + features: [ // @ts-expect-error [extensionPoint1, { a: 'a' }], - [serviceRef, { a: 'a' }], - [serviceRef, { a: 'a', b: 'b' }], - // @ts-expect-error - [serviceRef, { c: 'c' }], - // @ts-expect-error - [serviceRef, { a: 'a', c: 'c' }], - // @ts-expect-error - [serviceRef, { a: 'a', b: 'b', c: 'c' }], + createServiceFactory(() => ({ + service: serviceRef, + deps: {}, + // @ts-expect-error + factory: async () => ({ a: 'a' }), + })), + createServiceFactory(() => ({ + service: serviceRef, + deps: {}, + factory: async () => ({ a: 'a', b: 'b' }), + })), + createServiceFactory(() => ({ + service: serviceRef, + deps: {}, + // @ts-expect-error + factory: async () => ({ c: 'c' }), + })), + createServiceFactory(() => ({ + service: serviceRef, + deps: {}, + // @ts-expect-error + factory: async () => ({ a: 'a', c: 'c' }), + })), + createServiceFactory(() => ({ + service: serviceRef, + deps: {}, + factory: async () => ({ a: 'a', b: 'b', c: 'c' }), + })), ], extensionPoints: [ // @ts-expect-error @@ -124,8 +143,7 @@ describe('TestBackend', () => { }); await startTestBackend({ - services: [sf], - features: [testModule()], + features: [testModule(), sf()], }); expect(testFn).toHaveBeenCalledWith('winning'); @@ -150,7 +168,6 @@ describe('TestBackend', () => { }); const backend = await startTestBackend({ - services: [], features: [testModule()], }); @@ -168,7 +185,7 @@ describe('TestBackend', () => { env.registerInit({ deps: { cache: coreServices.cache, - config: coreServices.config, + config: coreServices.rootConfig, database: coreServices.database, discovery: coreServices.discovery, httpRouter: coreServices.httpRouter, @@ -192,7 +209,6 @@ describe('TestBackend', () => { }); await startTestBackend({ - services: [], features: [testPlugin()], }); }); @@ -220,4 +236,89 @@ describe('TestBackend', () => { expect(res.status).toEqual(200); expect(res.body).toEqual({ message: 'pong' }); }); + + it('should provide extension point implementations', async () => { + expect.assertions(3); + + const extensionPointA = createExtensionPoint({ id: 'a' }); + const extensionPointB = createExtensionPoint({ id: 'b' }); + await expect( + startTestBackend({ + extensionPoints: [ + [extensionPointA, 'a'], + [extensionPointB, 'b'], + ], + features: [ + createBackendModule({ + pluginId: 'testA', + moduleId: 'test', + register(reg) { + reg.registerInit({ + deps: { ext: extensionPointA }, + async init({ ext }) { + expect(ext).toBe('a'); + }, + }); + }, + }), + createBackendModule({ + pluginId: 'testB', + moduleId: 'test', + register(reg) { + reg.registerInit({ + deps: { ext: extensionPointB }, + async init({ ext }) { + expect(ext).toBe('b'); + }, + }); + }, + }), + ], + }), + ).resolves.not.toBeUndefined(); + }); + + it('should reject extension point used by multiple plugins', async () => { + const extensionPointA = createExtensionPoint({ id: 'a' }); + await expect( + startTestBackend({ + extensionPoints: [[extensionPointA, 'a']], + features: [ + createBackendModule({ + pluginId: 'testA', + moduleId: 'test', + register(reg) { + reg.registerInit({ + deps: { ext: extensionPointA }, + async init() {}, + }); + }, + }), + createBackendModule({ + pluginId: 'testB', + moduleId: 'test', + register(reg) { + reg.registerInit({ + deps: { ext: extensionPointA }, + async init() {}, + }); + }, + }), + ], + }), + ).rejects.toThrow( + "Extension point registered for plugin 'testA' may not be used by module for plugin 'testB'", + ); + }); + + it('should reject extension point not used by any plugin', async () => { + const extensionPointA = createExtensionPoint({ id: 'a' }); + await expect( + startTestBackend({ + extensionPoints: [[extensionPointA, 'a']], + }), + ).rejects.toThrow( + "Unable to determine the plugin ID of extension point(s) 'a'. Tested extension points must be depended on by one or more tested modules.", + ); + }); }); diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.ts index e8df15862f..97da3543ae 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.ts +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.ts @@ -24,31 +24,21 @@ import { } from '@backstage/backend-app-api'; import { HostDiscovery } from '@backstage/backend-common'; import { - ServiceFactory, - ServiceRef, createServiceFactory, BackendFeature, ExtensionPoint, coreServices, - createBackendPlugin, + createBackendModule, } from '@backstage/backend-plugin-api'; import { mockServices } from '../services'; import { ConfigReader } from '@backstage/config'; import express from 'express'; +// Direct internal import to avoid duplication +// eslint-disable-next-line @backstage/no-forbidden-package-imports +import { InternalBackendFeature } from '@backstage/backend-plugin-api/src/wiring/types'; /** @public */ -export interface TestBackendOptions< - TServices extends any[], - TExtensionPoints extends any[], -> { - services?: readonly [ - ...{ - [index in keyof TServices]: - | ServiceFactory - | (() => ServiceFactory) - | [ServiceRef, Partial]; - }, - ]; +export interface TestBackendOptions { extensionPoints?: readonly [ ...{ [index in keyof TExtensionPoints]: [ @@ -57,7 +47,7 @@ export interface TestBackendOptions< ]; }, ]; - features?: BackendFeature[]; + features?: Array BackendFeature)>; } /** @public */ @@ -73,7 +63,7 @@ export interface TestBackend extends Backend { const defaultServiceFactories = [ mockServices.cache.factory(), - mockServices.config.factory(), + mockServices.rootConfig.factory(), mockServices.database.factory(), mockServices.httpRouter.factory(), mockServices.identity.factory(), @@ -87,28 +77,115 @@ const defaultServiceFactories = [ mockServices.urlReader.factory(), ]; +/** + * Given a set of extension points and plugins, find + * @returns + */ +function createExtensionPointTestModules( + features: Array BackendFeature)>, + extensionPointTuples?: readonly [ + ref: ExtensionPoint, + impl: unknown, + ][], +): Array<() => BackendFeature> { + if (!extensionPointTuples) { + return []; + } + + const registrations = features.flatMap(featureOrFunction => { + const feature = + typeof featureOrFunction === 'function' + ? featureOrFunction() + : featureOrFunction; + + if (feature.$$type !== '@backstage/BackendFeature') { + throw new Error( + `Failed to add feature, invalid type '${feature.$$type}'`, + ); + } + + if (isInternalBackendFeature(feature)) { + if (feature.version !== 'v1') { + throw new Error( + `Failed to add feature, invalid version '${feature.version}'`, + ); + } + return feature.getRegistrations(); + } + return []; + }); + + const extensionPointMap = new Map( + extensionPointTuples.map(ep => [ep[0].id, ep]), + ); + const extensionPointsToSort = new Set(extensionPointMap.keys()); + const extensionPointsByPlugin = new Map(); + + for (const registration of registrations) { + if (registration.type === 'module') { + const testDep = Object.values(registration.init.deps).filter(dep => + extensionPointsToSort.has(dep.id), + ); + if (testDep.length > 0) { + let points = extensionPointsByPlugin.get(registration.pluginId); + if (!points) { + points = []; + extensionPointsByPlugin.set(registration.pluginId, points); + } + for (const { id } of testDep) { + points.push(id); + extensionPointsToSort.delete(id); + } + } + } + } + + if (extensionPointsToSort.size > 0) { + const list = Array.from(extensionPointsToSort) + .map(id => `'${id}'`) + .join(', '); + throw new Error( + `Unable to determine the plugin ID of extension point(s) ${list}. ` + + 'Tested extension points must be depended on by one or more tested modules.', + ); + } + + const modules = []; + + for (const [pluginId, pluginExtensionPointIds] of extensionPointsByPlugin) { + modules.push( + createBackendModule({ + pluginId, + moduleId: 'testExtensionPointRegistration', + register(reg) { + for (const id of pluginExtensionPointIds) { + const tuple = extensionPointMap.get(id)!; + reg.registerExtensionPoint(...tuple); + } + + reg.registerInit({ deps: {}, async init() {} }); + }, + }), + ); + } + + return modules; +} + const backendInstancesToCleanUp = new Array(); /** @public */ -export async function startTestBackend< - TServices extends any[], - TExtensionPoints extends any[], ->( - options: TestBackendOptions, +export async function startTestBackend( + options: TestBackendOptions, ): Promise { - const { - services = [], - extensionPoints = [], - features = [], - ...otherOptions - } = options; + const { extensionPoints, features = [], ...otherOptions } = options; let server: ExtendedHttpServer; const rootHttpRouterFactory = createServiceFactory({ service: coreServices.rootHttpRouter, deps: { - config: coreServices.config, + config: coreServices.rootConfig, lifecycle: coreServices.rootLifecycle, rootLogger: coreServices.rootLogger, }, @@ -157,55 +234,20 @@ export async function startTestBackend< }, }); - const factories = services.map(serviceDef => { - if (Array.isArray(serviceDef)) { - // if type is ExtensionPoint? - // do something differently? - const [ref, impl] = serviceDef; - if (ref.scope === 'plugin') { - return createServiceFactory({ - service: ref as ServiceRef, - deps: {}, - factory: async () => impl, - })(); - } - return createServiceFactory({ - service: ref as ServiceRef, - deps: {}, - factory: async () => impl, - })(); - } - if (typeof serviceDef === 'function') { - return serviceDef(); - } - return serviceDef as ServiceFactory; - }); - - for (const factory of defaultServiceFactories) { - if (!factories.some(f => f.service.id === factory.service.id)) { - factories.push(factory); - } - } - const backend = createSpecializedBackend({ ...otherOptions, - services: [...factories, rootHttpRouterFactory, discoveryFactory], + defaultServiceFactories: [ + ...defaultServiceFactories, + rootHttpRouterFactory, + discoveryFactory, + ], }); backendInstancesToCleanUp.push(backend); - backend.add( - createBackendPlugin({ - pluginId: `---test-extension-point-registrar`, - register(reg) { - for (const [ref, impl] of extensionPoints) { - reg.registerExtensionPoint(ref, impl); - } - - reg.registerInit({ deps: {}, async init() {} }); - }, - })(), - ); + for (const m of createExtensionPointTestModules(features, extensionPoints)) { + backend.add(m); + } for (const feature of features) { backend.add(feature); @@ -248,3 +290,11 @@ function registerTestHooks() { } registerTestHooks(); + +function isInternalBackendFeature( + feature: BackendFeature, +): feature is InternalBackendFeature { + return ( + typeof (feature as InternalBackendFeature).getRegistrations === 'function' + ); +} diff --git a/packages/backend/.snyk b/packages/backend/.snyk new file mode 100644 index 0000000000..ea5abd653d --- /dev/null +++ b/packages/backend/.snyk @@ -0,0 +1,10 @@ +# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. +version: v1.22.1 +# ignores vulnerabilities until expiry date; change duration by modifying expiry date +ignore: + SNYK-JS-ISOLATEDVM-3037320: + - '*': + reason: We do not pass any V8 cache data, and are therefore unaffected by this vulnerability + expires: 2033-07-02T16:55:57.077Z + created: 2023-07-02T16:55:57.077Z +patch: {} diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index d4359d6ece..76ac221f69 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,164 @@ # example-backend +## 0.2.86 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-module-elasticsearch@1.3.3 + - @backstage/plugin-search-backend-module-pg@0.5.9 + - @backstage/plugin-azure-devops-backend@0.3.27 + - @backstage/plugin-kubernetes-backend@0.11.3 + - @backstage/plugin-lighthouse-backend@0.2.4 + - @backstage/plugin-permission-backend@0.5.23 + - @backstage/plugin-scaffolder-backend@1.16.0 + - @backstage/plugin-devtools-backend@0.1.3 + - @backstage/plugin-techdocs-backend@1.6.5 + - @backstage/backend-common@0.19.2 + - @backstage/plugin-catalog-backend@1.12.0 + - @backstage/plugin-badges-backend@0.2.3 + - @backstage/plugin-events-backend@0.2.9 + - @backstage/plugin-search-backend@1.4.0 + - @backstage/plugin-kafka-backend@0.2.41 + - @backstage/plugin-proxy-backend@0.3.0 + - @backstage/plugin-todo-backend@0.2.0 + - @backstage/plugin-app-backend@0.3.48 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.1 + - @backstage/plugin-auth-backend@0.18.6 + - @backstage/plugin-explore-backend@0.0.10 + - @backstage/plugin-catalog-backend-module-unprocessed@0.2.0 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.17 + - @backstage/plugin-entity-feedback-backend@0.1.6 + - @backstage/plugin-code-coverage-backend@0.2.14 + - @backstage/plugin-search-backend-node@1.2.4 + - @backstage/plugin-linguist-backend@0.4.0 + - @backstage/plugin-playlist-backend@0.3.4 + - @backstage/plugin-jenkins-backend@0.2.3 + - @backstage/plugin-nomad-backend@0.1.2 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/plugin-events-node@0.2.9 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - example-app@0.2.86 + - @backstage/plugin-adr-backend@0.3.6 + - @backstage/plugin-azure-sites-backend@0.1.10 + - @backstage/plugin-graphql-backend@0.1.38 + - @backstage/plugin-permission-node@0.7.11 + - @backstage/plugin-rollbar-backend@0.1.45 + - @backstage/plugin-tech-insights-backend@0.5.14 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.32 + - @backstage/plugin-tech-insights-node@0.4.6 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-search-common@1.2.5 + +## 0.2.86-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-backend@0.18.6-next.2 + - @backstage/plugin-scaffolder-backend@1.15.2-next.2 + - @backstage/plugin-explore-backend@0.0.10-next.2 + - @backstage/plugin-catalog-backend@1.12.0-next.2 + - @backstage/plugin-proxy-backend@0.3.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/plugin-app-backend@0.3.48-next.2 + - @backstage/plugin-linguist-backend@0.4.0-next.2 + - @backstage/plugin-techdocs-backend@1.6.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - example-app@0.2.86-next.2 + - @backstage/plugin-adr-backend@0.3.6-next.2 + - @backstage/plugin-azure-devops-backend@0.3.27-next.2 + - @backstage/plugin-badges-backend@0.2.3-next.2 + - @backstage/plugin-catalog-backend-module-unprocessed@0.2.0-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + - @backstage/plugin-devtools-backend@0.1.3-next.2 + - @backstage/plugin-entity-feedback-backend@0.1.6-next.2 + - @backstage/plugin-events-backend@0.2.9-next.2 + - @backstage/plugin-events-node@0.2.9-next.2 + - @backstage/plugin-kafka-backend@0.2.41-next.2 + - @backstage/plugin-kubernetes-backend@0.11.3-next.2 + - @backstage/plugin-lighthouse-backend@0.2.4-next.2 + - @backstage/plugin-permission-backend@0.5.23-next.2 + - @backstage/plugin-permission-node@0.7.11-next.2 + - @backstage/plugin-search-backend@1.4.0-next.2 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.3-next.2 + - @backstage/plugin-search-backend-module-pg@0.5.9-next.2 + - @backstage/plugin-search-backend-node@1.2.4-next.2 + - @backstage/plugin-todo-backend@0.2.0-next.2 + - @backstage/plugin-tech-insights-backend@0.5.14-next.2 + - @backstage/plugin-tech-insights-node@0.4.6-next.2 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.1-next.2 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.17-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + - @backstage/plugin-azure-sites-backend@0.1.10-next.2 + - @backstage/plugin-code-coverage-backend@0.2.14-next.2 + - @backstage/plugin-graphql-backend@0.1.38-next.2 + - @backstage/plugin-jenkins-backend@0.2.3-next.2 + - @backstage/plugin-nomad-backend@0.1.2-next.2 + - @backstage/plugin-playlist-backend@0.3.4-next.2 + - @backstage/plugin-rollbar-backend@0.1.45-next.2 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.32-next.2 + +## 0.2.86-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-module-elasticsearch@1.3.3-next.1 + - @backstage/plugin-search-backend-module-pg@0.5.9-next.1 + - @backstage/plugin-azure-devops-backend@0.3.27-next.1 + - @backstage/plugin-kubernetes-backend@0.11.3-next.1 + - @backstage/plugin-lighthouse-backend@0.2.4-next.1 + - @backstage/plugin-permission-backend@0.5.23-next.1 + - @backstage/plugin-scaffolder-backend@1.15.2-next.1 + - @backstage/plugin-devtools-backend@0.1.3-next.1 + - @backstage/plugin-techdocs-backend@1.6.5-next.1 + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-backend@1.12.0-next.1 + - @backstage/plugin-badges-backend@0.2.3-next.1 + - @backstage/plugin-events-backend@0.2.9-next.1 + - @backstage/plugin-search-backend@1.4.0-next.1 + - @backstage/plugin-kafka-backend@0.2.41-next.1 + - @backstage/plugin-proxy-backend@0.2.42-next.1 + - @backstage/plugin-todo-backend@0.2.0-next.1 + - @backstage/plugin-app-backend@0.3.48-next.1 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.1-next.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.2.0-next.1 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.17-next.1 + - @backstage/plugin-entity-feedback-backend@0.1.6-next.1 + - @backstage/plugin-code-coverage-backend@0.2.14-next.1 + - @backstage/plugin-search-backend-node@1.2.4-next.1 + - @backstage/plugin-linguist-backend@0.3.2-next.1 + - @backstage/plugin-playlist-backend@0.3.4-next.1 + - @backstage/plugin-explore-backend@0.0.10-next.1 + - @backstage/plugin-jenkins-backend@0.2.3-next.1 + - @backstage/plugin-nomad-backend@0.1.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/plugin-events-node@0.2.9-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/plugin-auth-backend@0.18.6-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/plugin-adr-backend@0.3.6-next.1 + - @backstage/plugin-azure-sites-backend@0.1.10-next.1 + - @backstage/plugin-graphql-backend@0.1.38-next.1 + - @backstage/plugin-permission-node@0.7.11-next.1 + - @backstage/plugin-rollbar-backend@0.1.45-next.1 + - @backstage/plugin-tech-insights-backend@0.5.14-next.1 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.32-next.1 + - @backstage/plugin-tech-insights-node@0.4.6-next.1 + - example-app@0.2.86-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-search-common@1.2.5 + ## 0.2.86-next.0 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index 1c99a1bdf3..9e0896233d 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.86-next.0", + "version": "0.2.86", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/cli-node/CHANGELOG.md b/packages/cli-node/CHANGELOG.md index fc2876fa76..8a7af72d8d 100644 --- a/packages/cli-node/CHANGELOG.md +++ b/packages/cli-node/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/cli-node +## 0.1.3 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## 0.1.3-next.0 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + ## 0.1.2 ### Patch Changes diff --git a/packages/cli-node/package.json b/packages/cli-node/package.json index c59a8930c0..589139a141 100644 --- a/packages/cli-node/package.json +++ b/packages/cli-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli-node", "description": "Node.js library for Backstage CLIs", - "version": "0.1.2", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -13,6 +13,12 @@ "backstage": { "role": "node-library" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/cli-node" + }, "scripts": { "build": "backstage-cli package build", "lint": "backstage-cli package lint", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 2652a40bde..9294e55efd 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/cli +## 0.22.10 + +### Patch Changes + +- 3f67cefb4780: Reload the frontend when app config changes +- cebbf8a27f3c: Enable to print the config schema not merged with the `--no-merge` flag +- 5c28ebc79fd6: Updated dependency `esbuild` to `^0.19.0`. +- 971bdd6a4732: Bumped internal `nodemon` dependency. +- Updated dependencies + - @backstage/config-loader@1.4.0 + - @backstage/cli-node@0.1.3 + - @backstage/integration@1.6.0 + - @backstage/catalog-model@1.4.1 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/eslint-plugin@0.1.3 + - @backstage/release-manifests@0.0.9 + - @backstage/types@1.1.0 + +## 0.22.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.4.0-next.1 + - @backstage/cli-node@0.1.3-next.0 + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/eslint-plugin@0.1.3 + - @backstage/release-manifests@0.0.9 + - @backstage/types@1.1.0 + ## 0.22.10-next.0 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 8b78b16900..95095fe78c 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli", "description": "CLI for developing Backstage plugins and apps", - "version": "0.22.10-next.0", + "version": "0.22.10", "publishConfig": { "access": "public" }, @@ -78,7 +78,7 @@ "cross-spawn": "^7.0.3", "css-loader": "^6.5.1", "diff": "^5.0.0", - "esbuild": "^0.18.0", + "esbuild": "^0.19.0", "esbuild-loader": "^2.18.0", "eslint": "^8.6.0", "eslint-config-prettier": "^8.3.0", @@ -167,7 +167,7 @@ "del": "^7.0.0", "mock-fs": "^5.1.0", "msw": "^1.0.0", - "nodemon": "^2.0.2", + "nodemon": "^3.0.1", "ts-node": "^10.0.0", "type-fest": "^2.19.0" }, diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md index 0782876942..909bb71b37 100644 --- a/packages/config-loader/CHANGELOG.md +++ b/packages/config-loader/CHANGELOG.md @@ -1,5 +1,89 @@ # @backstage/config-loader +## 1.4.0 + +### Minor Changes + +- 2f1859585998: Loading invalid TypeScript configuration schemas will now throw an error rather than silently being ignored. + + In particular this includes defining any additional types other than `Config` in the schema file, or use of unsupported types such as `Record` or `Partial`. + +- cd514545d1d0: Adds a new `deepVisibility` schema keyword that sets child visibility recursively to the defined value, respecting preexisting values or child `deepVisibility`. + + Example usage: + + ```ts + export interface Config { + /** + * Enforces a default of `secret` instead of `backend` for this object. + * @deepVisibility secret + */ + mySecretProperty: { + type: 'object'; + properties: { + secretValue: { + type: 'string'; + }; + + verySecretProperty: { + type: 'string'; + }; + }; + }; + } + ``` + + Example of a schema that would not be allowed: + + ```ts + export interface Config { + /** + * Set the top level property to secret, enforcing a default of `secret` instead of `backend` for this object. + * @deepVisibility secret + */ + mySecretProperty: { + type: 'object'; + properties: { + frontendUrl: { + /** + * We can NOT override the visibility to reveal a property to the front end. + * @visibility frontend + */ + type: 'string'; + }; + + verySecretProperty: { + type: 'string'; + }; + }; + }; + } + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## 1.4.0-next.1 + +### Minor Changes + +- 2f1859585998: Loading invalid TypeScript configuration schemas will now throw an error rather than silently being ignored. + + In particular this includes defining any additional types other than `Config` in the schema file, or use of unsupported types such as `Record` or `Partial`. + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + ## 1.4.0-next.0 ### Minor Changes diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index 51a4a5a6cd..7fba2d8acb 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.4.0-next.0", + "version": "1.4.0", "publishConfig": { "access": "public", "main": "dist/index.cjs.js", diff --git a/packages/config-loader/src/schema/collect.ts b/packages/config-loader/src/schema/collect.ts index ac3e4af341..7120c12d90 100644 --- a/packages/config-loader/src/schema/collect.ts +++ b/packages/config-loader/src/schema/collect.ts @@ -15,6 +15,7 @@ */ import fs from 'fs-extra'; +import { EOL } from 'os'; import { resolve as resolvePath, relative as relativePath, @@ -163,7 +164,7 @@ async function compileTsSchemas(paths: string[]) { // Lazy loaded, because this brings up all of TypeScript and we don't // want that eagerly loaded in tests - const { getProgramFromFiles, generateSchema } = await import( + const { getProgramFromFiles, buildGenerator } = await import( 'typescript-json-schema' ); @@ -183,17 +184,40 @@ async function compileTsSchemas(paths: string[]) { const tsSchemas = paths.map(path => { let value; try { - value = generateSchema( + const generator = buildGenerator( program, - // All schemas should export a `Config` symbol - 'Config', // This enables the use of these tags in TSDoc comments { required: true, validationKeywords: ['visibility', 'deepVisibility', 'deprecated'], }, [path.split(sep).join('/')], // Unix paths are expected for all OSes here - ) as JsonObject | null; + ); + + // All schemas should export a `Config` symbol + value = generator?.getSchemaForSymbol('Config') as JsonObject | null; + + // This makes sure that no additional symbols are defined in the schema. We don't allow + // this because they share a global namespace and will be merged together, leading to + // unpredictable behavior. + const userSymbols = new Set(generator?.getUserSymbols()); + userSymbols.delete('Config'); + if (userSymbols.size !== 0) { + const names = Array.from(userSymbols).join("', '"); + throw new Error( + `Invalid configuration schema in ${path}, additional symbol definitions are not allowed, found '${names}'`, + ); + } + + // This makes sure that no unsupported types are used in the schema, for example `Record<,>`. + // The generator will extract these as a schema reference, which will in turn be broken for our usage. + const reffedDefs = Object.keys(generator?.ReffedDefinitions ?? {}); + if (reffedDefs.length !== 0) { + const lines = reffedDefs.join(`${EOL} `); + throw new Error( + `Invalid configuration schema in ${path}, the following definitions are not supported:${EOL}${EOL} ${lines}`, + ); + } } catch (error) { assertError(error); if (error.message !== 'type Config not found') { diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index 1de645fb9e..b09076f773 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/core-app-api +## 1.9.1 + +### Patch Changes + +- 9ae4e7e63836: Fixed a bug that could cause `navigate` analytics events to be misattributed to the plugin mounted on the root route (e.g. the `home` plugin at `/`) when the route that was navigated to wasn't associated with a routable extension. +- Updated dependencies + - @backstage/core-plugin-api@1.5.3 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + - @backstage/version-bridge@1.0.4 + ## 1.9.1-next.0 ### Patch Changes diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index 15dca326e0..ff43d81329 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-app-api", "description": "Core app API used by Backstage apps", - "version": "1.9.1-next.0", + "version": "1.9.1", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index 4ebd92ceb6..af5e2b8d6a 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/core-components +## 0.13.4 + +### Patch Changes + +- 3d86be999fdf: Prefer simple `theme.spacing` without string interpolation +- Updated dependencies + - @backstage/core-plugin-api@1.5.3 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/version-bridge@1.0.4 + ## 0.13.4-next.0 ### Patch Changes diff --git a/packages/core-components/package.json b/packages/core-components/package.json index c9b1584b85..641a4e7270 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-components", "description": "Core components used by Backstage plugins and apps", - "version": "0.13.4-next.0", + "version": "0.13.4", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 9a65a15f98..9ddd48393b 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/create-app +## 0.5.4 + +### Patch Changes + +- b441642fbe0d: Bumped create-app version. +- 572abc7edf55: Bumped create-app version. +- 74f77f151a96: Bumped create-app version. +- 5cc0ac5ef3d1: Bump to a newer version of the `concurrently` library +- 46c9a798e41d: Updated the `app-config.yaml` template to use `proxy.endpoints`. +- 971bdd6a4732: Bumped internal `nodemon` dependency. +- Updated dependencies + - @backstage/cli-common@0.1.12 + +## 0.5.4-next.2 + +### Patch Changes + +- Bumped create-app version. + +## 0.5.4-next.1 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.12 + ## 0.5.4-next.0 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index fb203edf26..4f629d951e 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/create-app", "description": "A CLI that helps you create your own Backstage app", - "version": "0.5.4-next.0", + "version": "0.5.4", "publishConfig": { "access": "public" }, @@ -49,7 +49,7 @@ "@types/node": "^16.11.26", "@types/recursive-readdir": "^2.2.0", "mock-fs": "^5.1.1", - "nodemon": "^2.0.2", + "nodemon": "^3.0.1", "ts-node": "^10.0.0" }, "nodemonConfig": { diff --git a/packages/create-app/templates/default-app/app-config.yaml.hbs b/packages/create-app/templates/default-app/app-config.yaml.hbs index 194549f079..08d2abff59 100644 --- a/packages/create-app/templates/default-app/app-config.yaml.hbs +++ b/packages/create-app/templates/default-app/app-config.yaml.hbs @@ -46,9 +46,10 @@ integrations: proxy: ### Example for how to add a proxy endpoint for the frontend. ### A typical reason to do this is to handle HTTPS and CORS for internal services. - # '/test': - # target: 'https://example.com' - # changeOrigin: true + # endpoints: + # '/test': + # target: 'https://example.com' + # changeOrigin: true # Reference documentation http://backstage.io/docs/features/techdocs/configuration # Note: After experimenting with basic setup, use CI/CD to generate docs diff --git a/packages/create-app/templates/default-app/package.json.hbs b/packages/create-app/templates/default-app/package.json.hbs index 0682114a35..c53ed6970f 100644 --- a/packages/create-app/templates/default-app/package.json.hbs +++ b/packages/create-app/templates/default-app/package.json.hbs @@ -31,7 +31,7 @@ "devDependencies": { "@backstage/cli": "^{{version '@backstage/cli'}}", "@spotify/prettier-config": "^12.0.0", - "concurrently": "^6.0.0", + "concurrently": "^8.0.0", "lerna": "^4.0.0", "node-gyp": "^9.0.0", "prettier": "^2.3.2", diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index 45df686876..99fb4f1372 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/dev-utils +## 1.0.18 + +### Patch Changes + +- 254ad469f053: Removed deprecated calls to `app.getProvider()` and `app.getRouter()` in `DevAppBuilder` +- Updated dependencies + - @backstage/core-app-api@1.9.1 + - @backstage/integration-react@1.1.16 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/app-defaults@1.4.2 + - @backstage/core-plugin-api@1.5.3 + - @backstage/test-utils@1.4.2 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## 1.0.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/integration-react@1.1.16-next.1 + +## 1.0.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.16-next.1 + - @backstage/app-defaults@1.4.2-next.0 + - @backstage/catalog-model@1.4.1 + - @backstage/core-app-api@1.9.1-next.0 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/test-utils@1.4.2-next.0 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + ## 1.0.18-next.0 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index d7e12209c3..44b16b4a62 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.18-next.0", + "version": "1.0.18", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/dev-utils/src/devApp/render.tsx b/packages/dev-utils/src/devApp/render.tsx index 36e87855ed..5f2b21b8d2 100644 --- a/packages/dev-utils/src/devApp/render.tsx +++ b/packages/dev-utils/src/devApp/render.tsx @@ -15,7 +15,7 @@ */ import { createApp } from '@backstage/app-defaults'; -import { FlatRoutes } from '@backstage/core-app-api'; +import { AppRouter, FlatRoutes } from '@backstage/core-app-api'; import { AlertDisplay, OAuthRequestDialog, @@ -195,35 +195,30 @@ export class DevAppBuilder { }, }); - const AppProvider = app.getProvider(); - const AppRouter = app.getRouter(); + const DevApp = ( + <> + + + {this.rootChildren} + + + + + {this.sidebarItems} + + + + + + {this.routes} + } /> + + + + + ); - const DevApp = () => { - return ( - - - - {this.rootChildren} - - - - - {this.sidebarItems} - - - - - - {this.routes} - } /> - - - - - ); - }; - - return DevApp; + return app.createRoot(DevApp); } /** diff --git a/packages/e2e-test/CHANGELOG.md b/packages/e2e-test/CHANGELOG.md index f6f29ff3f2..6bf5527c4b 100644 --- a/packages/e2e-test/CHANGELOG.md +++ b/packages/e2e-test/CHANGELOG.md @@ -1,5 +1,30 @@ # e2e-test +## 0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.4 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.2.1 + +## 0.2.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.4-next.2 + +## 0.2.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.4-next.1 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.2.1 + ## 0.2.6-next.0 ### Patch Changes diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index 48ef90db6f..48d4643394 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -1,7 +1,7 @@ { "name": "e2e-test", "description": "E2E test for verifying Backstage packages", - "version": "0.2.6-next.0", + "version": "0.2.6", "private": true, "backstage": { "role": "cli" @@ -35,7 +35,7 @@ "cross-fetch": "^3.1.5", "fs-extra": "10.1.0", "handlebars": "^4.7.3", - "pgtools": "^0.3.0", + "pgtools": "^1.0.0", "puppeteer": "^17.0.0", "tree-kill": "^1.2.2" }, @@ -44,7 +44,7 @@ "@types/fs-extra": "^9.0.1", "@types/node": "^16.11.26", "@types/puppeteer": "^5.4.4", - "nodemon": "^2.0.2", + "nodemon": "^3.0.1", "ts-node": "^10.0.0" }, "nodemonConfig": { diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index 4f275a8750..9d08c09bd9 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/integration-react +## 1.1.16 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/integration@1.6.0 + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/config@1.0.8 + - @backstage/theme@0.4.1 + +## 1.1.16-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/integration@1.5.1 + - @backstage/config@1.0.8 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + ## 1.1.16-next.0 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index 616826b430..ec68a20f36 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.16-next.0", + "version": "1.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -13,6 +13,12 @@ "backstage": { "role": "web-library" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/integration-react" + }, "scripts": { "build": "backstage-cli package build", "start": "backstage-cli package start", diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md index d1f3f46306..b4b97f579e 100644 --- a/packages/integration/CHANGELOG.md +++ b/packages/integration/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/integration +## 1.6.0 + +### Minor Changes + +- 443afcf7f567: Added `buildGerritGitilesArchiveUrl()` to construct a Gitiles URL to download an archive. + Gitiles URL that uses an authenticated prefix (`/a/`) can now be parsed by the integration. + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + ## 1.5.1 ### Patch Changes diff --git a/packages/integration/api-report.md b/packages/integration/api-report.md index c2501b4ac2..7266950ac4 100644 --- a/packages/integration/api-report.md +++ b/packages/integration/api-report.md @@ -172,6 +172,14 @@ export type BitbucketServerIntegrationConfig = { password?: string; }; +// @public +export function buildGerritGitilesArchiveUrl( + config: GerritIntegrationConfig, + project: string, + branch: string, + filePath: string, +): string; + // @public export class DefaultGithubCredentialsProvider implements GithubCredentialsProvider diff --git a/packages/integration/package.json b/packages/integration/package.json index e02e070266..b0da382abd 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.5.1", + "version": "1.6.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/integration/src/gerrit/core.test.ts b/packages/integration/src/gerrit/core.test.ts index 5a829e88f9..c00bae384f 100644 --- a/packages/integration/src/gerrit/core.test.ts +++ b/packages/integration/src/gerrit/core.test.ts @@ -20,6 +20,7 @@ import fetch from 'cross-fetch'; import { setupRequestMockHandlers } from '../helpers'; import { GerritIntegrationConfig } from './config'; import { + buildGerritGitilesArchiveUrl, buildGerritGitilesUrl, getGerritBranchApiUrl, getGerritCloneRepoUrl, @@ -33,6 +34,41 @@ describe('gerrit core', () => { const worker = setupServer(); setupRequestMockHandlers(worker); + describe('buildGerritGitilesArchiveUrl', () => { + const config: GerritIntegrationConfig = { + host: 'gerrit.com', + gitilesBaseUrl: 'https://gerrit.com/gitiles', + }; + it('can create an archive url for a branch', () => { + expect(buildGerritGitilesArchiveUrl(config, 'repo', 'dev', '')).toEqual( + 'https://gerrit.com/gitiles/repo/+archive/refs/heads/dev.tar.gz', + ); + + expect(buildGerritGitilesArchiveUrl(config, 'repo', 'dev', '/')).toEqual( + 'https://gerrit.com/gitiles/repo/+archive/refs/heads/dev.tar.gz', + ); + }); + it('can create an archive url for a specific directory', () => { + expect( + buildGerritGitilesArchiveUrl(config, 'repo', 'dev', 'docs'), + ).toEqual( + 'https://gerrit.com/gitiles/repo/+archive/refs/heads/dev/docs.tar.gz', + ); + }); + it('can create an authenticated url when auth is enabled', () => { + const authConfig = { + ...config, + username: 'username', + password: 'password', + }; + expect( + buildGerritGitilesArchiveUrl(authConfig, 'repo', 'dev', 'docs'), + ).toEqual( + 'https://gerrit.com/a/gitiles/repo/+archive/refs/heads/dev/docs.tar.gz', + ); + }); + }); + describe('buildGerritGitilesUrl', () => { it('can create an url from arguments', () => { const config: GerritIntegrationConfig = { @@ -86,6 +122,25 @@ describe('gerrit core', () => { ); expect(rootPath).toEqual('/'); }); + it('can parse a valid authenticated gitiles url.', () => { + const config: GerritIntegrationConfig = { + host: 'gerrit.com', + gitilesBaseUrl: 'https://gerrit.com/gitiles', + }; + const { branch, filePath, project } = parseGerritGitilesUrl( + config, + 'https://gerrit.com/a/gitiles/web/project/+/refs/heads/master/README.md', + ); + expect(project).toEqual('web/project'); + expect(branch).toEqual('master'); + expect(filePath).toEqual('README.md'); + + const { filePath: rootPath } = parseGerritGitilesUrl( + config, + 'https://gerrit.com/gitiles/web/project/+/refs/heads/master', + ); + expect(rootPath).toEqual('/'); + }); it('throws on incorrect gitiles urls.', () => { const config: GerritIntegrationConfig = { host: 'gerrit.com', diff --git a/packages/integration/src/gerrit/core.ts b/packages/integration/src/gerrit/core.ts index 0403d8fc75..107d5a4469 100644 --- a/packages/integration/src/gerrit/core.ts +++ b/packages/integration/src/gerrit/core.ts @@ -37,6 +37,7 @@ const GERRIT_BODY_PREFIX = ")]}'"; * * Gitiles url: * https://g.com/optional_path/\{project\}/+/refs/heads/\{branch\}/\{filePath\} + * https://g.com/a/optional_path/\{project\}/+/refs/heads/\{branch\}/\{filePath\} * * * @param url - An URL pointing to a file stored in git. @@ -47,7 +48,17 @@ export function parseGerritGitilesUrl( config: GerritIntegrationConfig, url: string, ): { branch: string; filePath: string; project: string } { - const urlPath = url.replace(config.gitilesBaseUrl!, ''); + const baseUrlParse = new URL(config.gitilesBaseUrl!); + const urlParse = new URL(url); + + // Remove the gerrit authentication prefix '/a/' from the url + // In case of the gitilesBaseUrl is https://review.gerrit.com/plugins/gitiles + // and the url provided is https://review.gerrit.com/a/plugins/gitiles/... + // remove the prefix only if the pathname start with '/a/' + const urlPath = urlParse.pathname + .substring(urlParse.pathname.startsWith('/a/') ? 2 : 0) + .replace(baseUrlParse.pathname, ''); + const parts = urlPath.split('/').filter(p => !!p); const projectEndIndex = parts.indexOf('+'); @@ -91,6 +102,28 @@ export function buildGerritGitilesUrl( }/${project}/+/refs/heads/${branch}/${trimStart(filePath, '/')}`; } +/** + * Build a Gerrit Gitiles archive url that targets a specific branch and path + * + * @param config - A Gerrit provider config. + * @param project - The name of the git project + * @param branch - The branch we will target. + * @param filePath - The absolute file path. + * @public + */ +export function buildGerritGitilesArchiveUrl( + config: GerritIntegrationConfig, + project: string, + branch: string, + filePath: string, +): string { + const archiveName = + filePath === '/' || filePath === '' ? '.tar.gz' : `/${filePath}.tar.gz`; + return `${getGitilesAuthenticationUrl( + config, + )}/${project}/+archive/refs/heads/${branch}${archiveName}`; +} + /** * Return the authentication prefix. * @@ -109,6 +142,26 @@ export function getAuthenticationPrefix( return config.password ? '/a/' : '/'; } +/** + * Return the authentication gitiles url. + * + * @remarks + * + * To authenticate with a password the API url must be prefixed with "/a/". + * If no password is set anonymous access (without the prefix) will + * be used. + * + * @param config - A Gerrit provider config. + */ +export function getGitilesAuthenticationUrl( + config: GerritIntegrationConfig, +): string { + const parsedUrl = new URL(config.gitilesBaseUrl!); + return `${parsedUrl.protocol}//${parsedUrl.host}${getAuthenticationPrefix( + config, + )}${parsedUrl.pathname.substring(1)}`; +} + /** * Return the url to get branch info from the Gerrit API. * diff --git a/packages/integration/src/gerrit/index.ts b/packages/integration/src/gerrit/index.ts index 127c949c4e..6c6295f7a3 100644 --- a/packages/integration/src/gerrit/index.ts +++ b/packages/integration/src/gerrit/index.ts @@ -19,6 +19,7 @@ export { readGerritIntegrationConfigs, } from './config'; export { + buildGerritGitilesArchiveUrl, getGerritBranchApiUrl, getGerritCloneRepoUrl, getGerritFileContentsApiUrl, diff --git a/packages/repo-tools/CHANGELOG.md b/packages/repo-tools/CHANGELOG.md index b8f37f4977..ddebca0746 100644 --- a/packages/repo-tools/CHANGELOG.md +++ b/packages/repo-tools/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/repo-tools +## 0.3.3 + +### Patch Changes + +- 75702e85862a: Bumped `@microsoft/api-extractor` dependency to `^7.36.4`, and `@microsoft/api-documenter` to `^7.22.33`. +- 1f3337ebc707: Introducing a new, experimental command `backstage-repo-tools generate-catalog-info`, which can be used to create standardized `catalog-info.yaml` files for each Backstage package in a Backstage monorepo. It can also be used to automatically fix existing `catalog-info.yaml` files with the correct metadata (including `metadata.name`, `metadata.title`, and `metadata.description` introspected from the package's `package.json`, as well as `spec.owner` introspected from `CODEOWNERS`), e.g. in a post-commit hook. +- ebeb77586975: Update `schema openapi generate` command to now create a default router that can be imported and used directly. +- Updated dependencies + - @backstage/cli-node@0.1.3 + - @backstage/catalog-model@1.4.1 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.2.1 + +## 0.3.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-node@0.1.3-next.0 + - @backstage/cli-common@0.1.12 + - @backstage/errors@1.2.1 + ## 0.3.3-next.0 ### Patch Changes diff --git a/packages/repo-tools/cli-report.md b/packages/repo-tools/cli-report.md index a0df5e721c..9c87bd8dff 100644 --- a/packages/repo-tools/cli-report.md +++ b/packages/repo-tools/cli-report.md @@ -14,6 +14,7 @@ Options: Commands: api-reports [options] [paths...] type-deps + generate-catalog-info [options] schema [command] help [command] ``` @@ -36,6 +37,16 @@ Options: -h, --help ``` +### `backstage-repo-tools generate-catalog-info` + +``` +Usage: backstage-repo-tools generate-catalog-info [options] + +Options: + --dry-run + -h, --help +``` + ### `backstage-repo-tools schema` ``` diff --git a/packages/repo-tools/package.json b/packages/repo-tools/package.json index c05cd30c75..82099ea621 100644 --- a/packages/repo-tools/package.json +++ b/packages/repo-tools/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/repo-tools", "description": "CLI for Backstage repo tooling ", - "version": "0.3.3-next.0", + "version": "0.3.3", "publishConfig": { "access": "public" }, @@ -32,12 +32,13 @@ "dependencies": { "@apidevtools/swagger-parser": "^10.1.0", "@apisyouwonthate/style-guide": "^1.4.0", + "@backstage/catalog-model": "workspace:^", "@backstage/cli-common": "workspace:^", "@backstage/cli-node": "workspace:^", "@backstage/errors": "workspace:^", "@manypkg/get-packages": "^1.1.3", - "@microsoft/api-documenter": "^7.19.27", - "@microsoft/api-extractor": "^7.33.7", + "@microsoft/api-documenter": "^7.22.33", + "@microsoft/api-extractor": "^7.36.4", "@stoplight/spectral-core": "^1.18.0", "@stoplight/spectral-formatters": "^1.1.0", "@stoplight/spectral-functions": "^1.7.2", @@ -46,6 +47,7 @@ "@stoplight/spectral-runtime": "^1.1.2", "@stoplight/types": "^13.14.0", "chalk": "^4.0.0", + "codeowners-utils": "^1.0.2", "commander": "^9.1.0", "fs-extra": "10.1.0", "glob": "^8.0.3", @@ -54,7 +56,8 @@ "lodash": "^4.17.21", "minimatch": "^5.1.1", "p-limit": "^3.0.2", - "ts-node": "^10.0.0" + "ts-node": "^10.0.0", + "yaml-diff-patch": "^2.0.0" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/packages/repo-tools/src/commands/generate-catalog-info/codeowners.ts b/packages/repo-tools/src/commands/generate-catalog-info/codeowners.ts new file mode 100644 index 0000000000..f485e872e9 --- /dev/null +++ b/packages/repo-tools/src/commands/generate-catalog-info/codeowners.ts @@ -0,0 +1,69 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + CodeOwnersEntry, + CODEOWNERS_PATHS, + matchFile as matchCodeowner, + parse as parseCodeowners, +} from 'codeowners-utils'; +import { relative as relativePath, resolve as resolvePath } from 'path'; +import { readFile } from './utils'; + +export async function loadCodeowners(): Promise { + const maybeFiles = await Promise.allSettled( + CODEOWNERS_PATHS.map(async path => + readFile(resolvePath('.', path), { encoding: 'utf-8' }), + ), + ); + const file = maybeFiles.find( + maybeFile => maybeFile.status === 'fulfilled', + ) as PromiseFulfilledResult | undefined; + + if (!file) { + throw new Error( + 'This utility expects a CODEOWNERS file, but no such file was found.', + ); + } + + return parseCodeowners(file.value); +} + +export function getPossibleCodeowners( + codeowners: CodeOwnersEntry[], + relPath: string, +): string[] { + const codeownerMaybe = matchCodeowner(relPath, codeowners); + return codeownerMaybe + ? codeownerMaybe.owners.map( + owner => (owner.match(/(?:\@[^\/]+\/)?([^\@\/]*)$/) || [])[1], + ) + : []; +} + +export function getOwnerFromCodeowners( + codeowners: CodeOwnersEntry[], + absPath: string, +): string { + const relPath = relativePath('.', absPath); + const possibleOwners = getPossibleCodeowners(codeowners, relPath); + const owner = possibleOwners.slice(-1)[0]; + + if (!owner) { + throw new Error(`${relPath} isn't owned by anyone in CODEOWNERS`); + } + + return owner; +} diff --git a/packages/repo-tools/src/commands/generate-catalog-info/generate-catalog-info.ts b/packages/repo-tools/src/commands/generate-catalog-info/generate-catalog-info.ts new file mode 100644 index 0000000000..08f73898c8 --- /dev/null +++ b/packages/repo-tools/src/commands/generate-catalog-info/generate-catalog-info.ts @@ -0,0 +1,200 @@ +/* + * 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 YAML from 'js-yaml'; +import pLimit from 'p-limit'; +import { relative as relativePath, resolve as resolvePath } from 'path'; +import { yamlOverwrite } from 'yaml-diff-patch'; +import chalk from 'chalk'; +import { PackageGraph, PackageRole } from '@backstage/cli-node'; +import { Entity } from '@backstage/catalog-model'; +import { + getOwnerFromCodeowners, + getPossibleCodeowners, + loadCodeowners, +} from './codeowners'; +import { + BackstagePackageJson, + isBackstagePackage, + readFile, + writeFile, +} from './utils'; +import { CodeOwnersEntry } from 'codeowners-utils'; + +type CreateFixPackageInfoYamlsOptions = { + dryRun?: boolean; +}; + +export default async (opts: CreateFixPackageInfoYamlsOptions) => { + const { dryRun = false } = opts; + const packages = await PackageGraph.listTargetPackages(); + const codeowners = await loadCodeowners(); + const limit = pLimit(10); + + const results = await Promise.allSettled( + packages.map(({ packageJson, dir }) => + limit(async () => { + if (!isBackstagePackage(packageJson)) { + return; + } + + // Check if there is already a corresponding catalog-info.yaml + const infoYamlPath = resolvePath(dir, 'catalog-info.yaml'); + let yamlString = ''; + + try { + yamlString = await readFile(infoYamlPath, { encoding: 'utf-8' }); + } catch (e) { + if (e.code === 'ENOENT') { + await createCatalogInfoYaml({ + yamlPath: infoYamlPath, + packageJson, + codeowners, + dryRun, + }); + return; + } + + throw e; + } + + await fixCatalogInfoYaml({ + yamlPath: infoYamlPath, + packageJson, + codeowners, + yamlString, + dryRun, + }); + }), + ), + ); + + const rejects = results.filter( + r => r.status === 'rejected', + ) as PromiseRejectedResult[]; + if (rejects.length > 0) { + // Problems encountered. Print details here. + console.error( + chalk.red('Unable to create or fix catalog-info.yaml files\n'), + ); + rejects.forEach(reject => console.error(` ${reject.reason}`)); + console.error(); + process.exit(1); + } +}; + +type CreateOptions = { + yamlPath: string; + packageJson: BackstagePackageJson; + codeowners: CodeOwnersEntry[]; + dryRun: boolean; +}; + +type FixOptions = CreateOptions & { + yamlString: string; +}; + +type BackstagePackageEntity = Entity & { + spec: { + type: 'backstage-package'; + backstageRole: PackageRole; + lifecycle: string; + owner: string; + [key: string]: any; + }; +}; + +function createCatalogInfoYaml(options: CreateOptions) { + const { codeowners, dryRun, packageJson, yamlPath } = options; + const owner = getOwnerFromCodeowners(codeowners, yamlPath); + const entity = createOrMergeEntity(packageJson, owner); + + return dryRun + ? Promise.resolve(console.error(`Create ${relativePath('.', yamlPath)}`)) + : writeFile(yamlPath, YAML.dump(entity)); +} + +function fixCatalogInfoYaml(options: FixOptions) { + const { codeowners, dryRun, packageJson, yamlPath, yamlString } = options; + const possibleOwners = getPossibleCodeowners( + codeowners, + relativePath('.', yamlPath), + ); + const safeName = packageJson.name + .replace(/[^a-z0-9_\-\.]+/g, '-') + .replace(/^[^a-z0-9]|[^a-z0-9]$/g, ''); + let yamlJson: BackstagePackageEntity; + + try { + yamlJson = YAML.load(yamlString) as BackstagePackageEntity; + } catch (e) { + throw new Error(`Unable to parse ${relativePath('.', yamlPath)}: ${e}`); + } + + const badOwner = !possibleOwners.includes(yamlJson.spec?.owner); + const badTitle = yamlJson.metadata.title !== packageJson.name; + const badName = yamlJson.metadata.name !== safeName; + const badType = + yamlJson.spec?.type !== `backstage-${packageJson.backstage.role}`; + const badDesc = yamlJson.metadata.description !== packageJson.description; + + if (badOwner || badTitle || badName || badType || badDesc) { + const owner = badOwner + ? getOwnerFromCodeowners(codeowners, yamlPath) + : yamlJson.spec?.owner; + const newJson = createOrMergeEntity(packageJson, owner, yamlJson); + return dryRun + ? Promise.resolve(console.error(`Update ${relativePath('.', yamlPath)}`)) + : writeFile(yamlPath, yamlOverwrite(yamlString, newJson)); + } + + return Promise.resolve(); +} + +/** + * Canonical representation on how to create (or update) a backstage-package + * component. + */ +function createOrMergeEntity( + packageJson: BackstagePackageJson, + owner: string, + existingEntity: BackstagePackageEntity | Record = {}, +): BackstagePackageEntity { + const safeEntityName = packageJson.name + .replace(/[^a-z0-9_\-\.]+/g, '-') + .replace(/^[^a-z0-9]|[^a-z0-9]$/g, ''); + + return { + ...existingEntity, + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + ...existingEntity.metadata, + // Provide default name/title/description values. + name: safeEntityName, + title: packageJson.name, + ...(packageJson.description + ? { description: packageJson.description } + : undefined), + }, + spec: { + lifecycle: 'experimental', + ...existingEntity.spec, + type: `backstage-${packageJson.backstage.role}`, + owner, + }, + }; +} diff --git a/packages/repo-tools/src/commands/generate-catalog-info/utils.ts b/packages/repo-tools/src/commands/generate-catalog-info/utils.ts new file mode 100644 index 0000000000..f446f4e867 --- /dev/null +++ b/packages/repo-tools/src/commands/generate-catalog-info/utils.ts @@ -0,0 +1,42 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import fs from 'fs'; +import { Package } from '@manypkg/get-packages'; +import { + BackstagePackageJson as BackstagePackageJsonActual, + PackageRole, +} from '@backstage/cli-node'; +import { promisify } from 'util'; + +export const readFile = promisify(fs.readFile); +export const writeFile = promisify(fs.writeFile); + +export type BackstagePackageJson = BackstagePackageJsonActual & { + description?: string; + backstage: { + role: PackageRole; + }; +}; + +export function isBackstagePackage( + packageJson: Package['packageJson'], +): packageJson is BackstagePackageJson { + return ( + packageJson && + packageJson.hasOwnProperty('backstage') && + (packageJson as any)?.backstage?.role !== 'undefined' + ); +} diff --git a/packages/repo-tools/src/commands/index.ts b/packages/repo-tools/src/commands/index.ts index e19ffde4b8..7aa574d291 100644 --- a/packages/repo-tools/src/commands/index.ts +++ b/packages/repo-tools/src/commands/index.ts @@ -96,6 +96,21 @@ export function registerCommands(program: Command) { .description('Find inconsistencies in types of all packages and plugins') .action(lazy(() => import('./type-deps/type-deps').then(m => m.default))); + program + .command('generate-catalog-info') + .option( + '--dry-run', + 'Shows what would happen without actually writing any yaml.', + ) + .description('Create or fix info yaml files for all backstage packages') + .action( + lazy(() => + import('./generate-catalog-info/generate-catalog-info').then( + m => m.default, + ), + ), + ); + registerSchemaCommand(program); } diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md index 26f2246d13..6728d9de41 100644 --- a/packages/techdocs-cli-embedded-app/CHANGELOG.md +++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md @@ -1,5 +1,53 @@ # techdocs-cli-embedded-app +## 0.2.85 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.9.1 + - @backstage/integration-react@1.1.16 + - @backstage/cli@0.22.10 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog@1.12.1 + - @backstage/app-defaults@1.4.2 + - @backstage/core-plugin-api@1.5.3 + - @backstage/test-utils@1.4.2 + - @backstage/plugin-techdocs@1.6.6 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/theme@0.4.1 + - @backstage/plugin-techdocs-react@1.1.9 + +## 0.2.85-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.12.1-next.2 + - @backstage/plugin-techdocs@1.6.6-next.2 + - @backstage/cli@0.22.10-next.1 + - @backstage/integration-react@1.1.16-next.1 + +## 0.2.85-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.16-next.1 + - @backstage/cli@0.22.10-next.1 + - @backstage/plugin-catalog@1.12.1-next.1 + - @backstage/plugin-techdocs@1.6.6-next.1 + - @backstage/app-defaults@1.4.2-next.0 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/core-app-api@1.9.1-next.0 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/test-utils@1.4.2-next.0 + - @backstage/theme@0.4.1 + - @backstage/plugin-techdocs-react@1.1.9-next.0 + ## 0.2.85-next.0 ### Patch Changes diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index 3bbef65e68..c8097fca3b 100644 --- a/packages/techdocs-cli-embedded-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -1,11 +1,17 @@ { "name": "techdocs-cli-embedded-app", - "version": "0.2.85-next.0", + "version": "0.2.85", "private": true, "backstage": { "role": "frontend" }, "bundled": true, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/techdocs-cli-embedded-app" + }, "dependencies": { "@backstage/app-defaults": "workspace:^", "@backstage/catalog-model": "workspace:^", diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index daefe75e38..8334aa54b6 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,5 +1,36 @@ # @techdocs/cli +## 1.4.5 + +### Patch Changes + +- 971bdd6a4732: Bumped internal `nodemon` dependency. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-techdocs-node@1.7.4 + - @backstage/catalog-model@1.4.1 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + +## 1.4.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-techdocs-node@1.7.4-next.2 + +## 1.4.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-techdocs-node@1.7.4-next.1 + - @backstage/catalog-model@1.4.1 + - @backstage/cli-common@0.1.12 + - @backstage/config@1.0.8 + ## 1.4.5-next.0 ### Patch Changes diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index d59450992b..3dc8eda540 100644 --- a/packages/techdocs-cli/package.json +++ b/packages/techdocs-cli/package.json @@ -1,7 +1,7 @@ { "name": "@techdocs/cli", "description": "Utility CLI for managing TechDocs sites in Backstage.", - "version": "1.4.5-next.0", + "version": "1.4.5", "publishConfig": { "access": "public" }, @@ -46,7 +46,7 @@ "@types/webpack-env": "^1.15.3", "cypress": "^10.0.0", "find-process": "^1.4.5", - "nodemon": "^2.0.2", + "nodemon": "^3.0.1", "techdocs-cli-embedded-app": "link:../techdocs-cli-embedded-app", "ts-node": "^10.0.0" }, diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index a3fb8ba382..d3e28b30d2 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/test-utils +## 1.4.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.9.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/config@1.0.8 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-permission-react@0.4.14 + ## 1.4.2-next.0 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index ef074d13b2..73ef2c5268 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.4.2-next.0", + "version": "1.4.2", "publishConfig": { "access": "public" }, diff --git a/plugins/adr-backend/CHANGELOG.md b/plugins/adr-backend/CHANGELOG.md index c63b8bd687..e038706836 100644 --- a/plugins/adr-backend/CHANGELOG.md +++ b/plugins/adr-backend/CHANGELOG.md @@ -1,5 +1,43 @@ # @backstage/plugin-adr-backend +## 0.3.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/integration@1.6.0 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-adr-common@0.2.12 + - @backstage/plugin-search-common@1.2.5 + +## 0.3.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## 0.3.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-adr-common@0.2.11 + - @backstage/plugin-search-common@1.2.5 + ## 0.3.6-next.0 ### Patch Changes diff --git a/plugins/adr-backend/package.json b/plugins/adr-backend/package.json index e7f390b790..c15eafd6cf 100644 --- a/plugins/adr-backend/package.json +++ b/plugins/adr-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr-backend", - "version": "0.3.6-next.0", + "version": "0.3.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr-common/CHANGELOG.md b/plugins/adr-common/CHANGELOG.md index 9b8d5dbf74..dfe54806fe 100644 --- a/plugins/adr-common/CHANGELOG.md +++ b/plugins/adr-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-adr-common +## 0.2.12 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.6.0 + - @backstage/catalog-model@1.4.1 + - @backstage/plugin-search-common@1.2.5 + ## 0.2.11 ### Patch Changes diff --git a/plugins/adr-common/package.json b/plugins/adr-common/package.json index 2def65cf55..25e02845ef 100644 --- a/plugins/adr-common/package.json +++ b/plugins/adr-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-adr-common", "description": "Common functionalities for the adr plugin", - "version": "0.2.11", + "version": "0.2.12", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr/CHANGELOG.md b/plugins/adr/CHANGELOG.md index fbbf4c13de..e25c80d4d2 100644 --- a/plugins/adr/CHANGELOG.md +++ b/plugins/adr/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-adr +## 0.6.4 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/integration-react@1.1.16 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/plugin-search-react@1.6.4 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-adr-common@0.2.12 + - @backstage/plugin-search-common@1.2.5 + +## 0.6.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/integration-react@1.1.16-next.1 + +## 0.6.4-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/integration-react@1.1.16-next.1 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-adr-common@0.2.11 + - @backstage/plugin-catalog-react@1.8.1-next.0 + - @backstage/plugin-search-common@1.2.5 + - @backstage/plugin-search-react@1.6.4-next.0 + ## 0.6.4-next.0 ### Patch Changes diff --git a/plugins/adr/package.json b/plugins/adr/package.json index 486ea800a2..37bf13619a 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr", - "version": "0.6.4-next.0", + "version": "0.6.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -12,6 +12,12 @@ "backstage": { "role": "frontend-plugin" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/adr" + }, "scripts": { "start": "backstage-cli package start", "build": "backstage-cli package build", diff --git a/plugins/airbrake-backend/CHANGELOG.md b/plugins/airbrake-backend/CHANGELOG.md index c0f695f372..7eea9d8287 100644 --- a/plugins/airbrake-backend/CHANGELOG.md +++ b/plugins/airbrake-backend/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-airbrake-backend +## 0.2.21 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/config@1.0.8 + +## 0.2.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## 0.2.21-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/config@1.0.8 + ## 0.2.21-next.0 ### Patch Changes diff --git a/plugins/airbrake-backend/package.json b/plugins/airbrake-backend/package.json index 06e5183a44..530de9a77a 100644 --- a/plugins/airbrake-backend/package.json +++ b/plugins/airbrake-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake-backend", - "version": "0.2.21-next.0", + "version": "0.2.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -12,6 +12,12 @@ "backstage": { "role": "backend-plugin" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/airbrake-backend" + }, "scripts": { "start": "backstage-cli package start", "build": "backstage-cli package build", diff --git a/plugins/airbrake-backend/src/plugin.ts b/plugins/airbrake-backend/src/plugin.ts index 79850c1272..90e790c05f 100644 --- a/plugins/airbrake-backend/src/plugin.ts +++ b/plugins/airbrake-backend/src/plugin.ts @@ -32,7 +32,7 @@ export const airbrakePlugin = createBackendPlugin({ register(env) { env.registerInit({ deps: { - config: coreServices.config, + config: coreServices.rootConfig, logger: coreServices.logger, httpRouter: coreServices.httpRouter, }, diff --git a/plugins/airbrake/CHANGELOG.md b/plugins/airbrake/CHANGELOG.md index e5b52f1932..b4d5afccdc 100644 --- a/plugins/airbrake/CHANGELOG.md +++ b/plugins/airbrake/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-airbrake +## 0.3.21 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/dev-utils@1.0.18 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/test-utils@1.4.2 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## 0.3.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/dev-utils@1.0.18-next.2 + +## 0.3.21-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/dev-utils@1.0.18-next.1 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/test-utils@1.4.2-next.0 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + ## 0.3.21-next.0 ### Patch Changes diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index 48a825f93b..5ccd8bd076 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake", - "version": "0.3.21-next.0", + "version": "0.3.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -12,6 +12,12 @@ "backstage": { "role": "frontend-plugin" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/airbrake" + }, "scripts": { "build": "backstage-cli package build", "start": "backstage-cli package start", diff --git a/plugins/allure/CHANGELOG.md b/plugins/allure/CHANGELOG.md index caa81f04cf..cd7c7973b5 100644 --- a/plugins/allure/CHANGELOG.md +++ b/plugins/allure/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/plugin-allure +## 0.1.37 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## 0.1.37-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## 0.1.37-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + ## 0.1.37-next.0 ### Patch Changes diff --git a/plugins/allure/package.json b/plugins/allure/package.json index f4809128ff..881d4d0c9d 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.37-next.0", + "version": "0.1.37", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -13,6 +13,12 @@ "backstage": { "role": "frontend-plugin" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/allure" + }, "scripts": { "build": "backstage-cli package build", "start": "backstage-cli package start", diff --git a/plugins/analytics-module-ga/CHANGELOG.md b/plugins/analytics-module-ga/CHANGELOG.md index d7c09cddb1..b6ceb1c28d 100644 --- a/plugins/analytics-module-ga/CHANGELOG.md +++ b/plugins/analytics-module-ga/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-analytics-module-ga +## 0.1.32 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/config@1.0.8 + - @backstage/theme@0.4.1 + +## 0.1.32-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/config@1.0.8 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + ## 0.1.32-next.0 ### Patch Changes diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index 302ee1cd86..434f231545 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.32-next.0", + "version": "0.1.32", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -12,6 +12,12 @@ "backstage": { "role": "frontend-plugin-module" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/analytics-module-ga" + }, "scripts": { "build": "backstage-cli package build", "start": "backstage-cli package start", diff --git a/plugins/analytics-module-ga4/CHANGELOG.md b/plugins/analytics-module-ga4/CHANGELOG.md index 9715015579..bc08d64809 100644 --- a/plugins/analytics-module-ga4/CHANGELOG.md +++ b/plugins/analytics-module-ga4/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-analytics-module-ga4 +## 0.1.3 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/config@1.0.8 + - @backstage/theme@0.4.1 + +## 0.1.3-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/config@1.0.8 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + ## 0.1.3-next.0 ### Patch Changes diff --git a/plugins/analytics-module-ga4/package.json b/plugins/analytics-module-ga4/package.json index 85f34468b1..63f03e440b 100644 --- a/plugins/analytics-module-ga4/package.json +++ b/plugins/analytics-module-ga4/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-ga4", - "version": "0.1.3-next.0", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -12,6 +12,12 @@ "backstage": { "role": "frontend-plugin-module" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/plugins/analytics-module-ga4" + }, "scripts": { "build": "backstage-cli package build", "start": "backstage-cli package start", diff --git a/plugins/analytics-module-newrelic-browser/CHANGELOG.md b/plugins/analytics-module-newrelic-browser/CHANGELOG.md index beea288700..3090cd3fc2 100644 --- a/plugins/analytics-module-newrelic-browser/CHANGELOG.md +++ b/plugins/analytics-module-newrelic-browser/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-analytics-module-newrelic-browser +## 0.0.1 + +### Patch Changes + +- ec7357258853: Introduced the New Relic Browser analytics module. Check out the plugins [README.md](https://github.com/backstage/backstage/tree/master/plugins/analytics-module-newrelic-browser) for more details! +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/config@1.0.8 + ## 0.0.1-next.0 ### Patch Changes diff --git a/plugins/analytics-module-newrelic-browser/package.json b/plugins/analytics-module-newrelic-browser/package.json index 677d3b8e16..ba72a1628b 100644 --- a/plugins/analytics-module-newrelic-browser/package.json +++ b/plugins/analytics-module-newrelic-browser/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-newrelic-browser", - "version": "0.0.1-next.0", + "version": "0.0.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/apache-airflow/CHANGELOG.md b/plugins/apache-airflow/CHANGELOG.md index ef1d34dc23..e23c4a7c0c 100644 --- a/plugins/apache-airflow/CHANGELOG.md +++ b/plugins/apache-airflow/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-apache-airflow +## 0.2.14 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + +## 0.2.14-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + ## 0.2.14-next.0 ### Patch Changes diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index b30abb3bc9..281d49c781 100644 --- a/plugins/apache-airflow/package.json +++ b/plugins/apache-airflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apache-airflow", - "version": "0.2.14-next.0", + "version": "0.2.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -12,6 +12,12 @@ "backstage": { "role": "frontend-plugin" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/apache-airflow" + }, "scripts": { "build": "backstage-cli package build", "start": "backstage-cli package start", diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index 68923046f5..f84d57542b 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-api-docs +## 0.9.7 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog@1.12.1 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## 0.9.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/plugin-catalog@1.12.1-next.2 + +## 0.9.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.12.1-next.1 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + ## 0.9.7-next.0 ### Patch Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 625fbd3138..1fe4133515 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-api-docs", "description": "A Backstage plugin that helps represent API entities in the frontend", - "version": "0.9.7-next.0", + "version": "0.9.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/apollo-explorer/CHANGELOG.md b/plugins/apollo-explorer/CHANGELOG.md index 0051c8a9e7..0833267e83 100644 --- a/plugins/apollo-explorer/CHANGELOG.md +++ b/plugins/apollo-explorer/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-apollo-explorer +## 0.1.14 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + +## 0.1.14-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + ## 0.1.14-next.0 ### Patch Changes diff --git a/plugins/apollo-explorer/package.json b/plugins/apollo-explorer/package.json index 0b43fd63ba..aae09fe19a 100644 --- a/plugins/apollo-explorer/package.json +++ b/plugins/apollo-explorer/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apollo-explorer", - "version": "0.1.14-next.0", + "version": "0.1.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -12,6 +12,12 @@ "backstage": { "role": "frontend-plugin" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/apollo-explorer" + }, "scripts": { "start": "backstage-cli package start", "build": "backstage-cli package build", diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index 7e048ba4d5..2ac0068ccc 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-app-backend +## 0.3.48 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- d564ad142b17: Migrated the alpha `appBackend` export to use static configuration and extension points rather than accepting options. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/config-loader@1.4.0 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-app-node@0.1.0 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + +## 0.3.48-next.2 + +### Patch Changes + +- d564ad142b17: Migrated the alpha `appBackend` export to use static configuration and extension points rather than accepting options. +- Updated dependencies + - @backstage/plugin-app-node@0.1.0-next.0 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/config-loader@1.4.0-next.1 + +## 0.3.48-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/config-loader@1.4.0-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + ## 0.3.48-next.0 ### Patch Changes diff --git a/plugins/app-backend/alpha-api-report.md b/plugins/app-backend/alpha-api-report.md index 20a2902557..5fb0546a79 100644 --- a/plugins/app-backend/alpha-api-report.md +++ b/plugins/app-backend/alpha-api-report.md @@ -4,18 +4,9 @@ ```ts import { BackendFeature } from '@backstage/backend-plugin-api'; -import express from 'express'; // @alpha -export const appPlugin: (options: AppPluginOptions) => BackendFeature; - -// @alpha (undocumented) -export type AppPluginOptions = { - appPackageName?: string; - staticFallbackHandler?: express.Handler; - disableConfigInjection?: boolean; - disableStaticFallbackCache?: boolean; -}; +export const appPlugin: () => BackendFeature; // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/app-backend/config.d.ts b/plugins/app-backend/config.d.ts new file mode 100644 index 0000000000..dc11bc4e0a --- /dev/null +++ b/plugins/app-backend/config.d.ts @@ -0,0 +1,46 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface Config { + app?: { + /** + * The name of the app package (in most Backstage repositories, this is the + * "name" field in `packages/app/package.json`) that content should be served + * from. The same app package should be added as a dependency to the backend + * package in order for it to be accessible at runtime. + * + * In a typical setup with a single app package, this will default to 'app'. + */ + packageName?: string; + + /** + * Disables the configuration injection. This can be useful if you're running in an environment + * with a read-only filesystem, or for some other reason don't want configuration to be injected. + * + * Note that this will cause the configuration used when building the app bundle to be used, unless + * a separate configuration loading strategy is set up. + * + * This also disables configuration injection though `APP_CONFIG_` environment variables. + */ + disableConfigInjection?: boolean; + + /** + * By default the app backend plugin will cache previously deployed static assets in the database. + * If you disable this, it is recommended to set a `staticFallbackHandler` instead. + */ + disableStaticFallbackCache?: boolean; + }; +} diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index 5574c8aba3..05db6bb37d 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.48-next.0", + "version": "0.3.48", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -49,6 +49,7 @@ "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/config-loader": "workspace:^", + "@backstage/plugin-app-node": "workspace:^", "@backstage/types": "workspace:^", "@types/express": "^4.17.6", "express": "^4.17.1", @@ -73,8 +74,10 @@ "node-fetch": "^2.6.7", "supertest": "^6.1.3" }, + "configSchema": "config.d.ts", "files": [ "dist", + "config.d.ts", "migrations/**/*.{js,d.ts}", "static" ] diff --git a/plugins/app-backend/src/alpha.ts b/plugins/app-backend/src/alpha.ts index cc8276b853..edb5c8caf5 100644 --- a/plugins/app-backend/src/alpha.ts +++ b/plugins/app-backend/src/alpha.ts @@ -15,4 +15,3 @@ */ export { appPlugin } from './service/appPlugin'; -export type { AppPluginOptions } from './service/appPlugin'; diff --git a/plugins/app-backend/src/service/appPlugin.test.ts b/plugins/app-backend/src/service/appPlugin.test.ts index 518f56b7f9..b6a972b4c7 100644 --- a/plugins/app-backend/src/service/appPlugin.test.ts +++ b/plugins/app-backend/src/service/appPlugin.test.ts @@ -17,7 +17,7 @@ import mockFs from 'mock-fs'; import { resolve as resolvePath } from 'path'; import fetch from 'node-fetch'; -import { startTestBackend } from '@backstage/backend-test-utils'; +import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; import { appPlugin } from './appPlugin'; describe('appPlugin', () => { @@ -40,9 +40,13 @@ describe('appPlugin', () => { it('boots', async () => { const { server } = await startTestBackend({ features: [ - appPlugin({ - appPackageName: 'app', - disableStaticFallbackCache: true, + appPlugin(), + mockServices.rootConfig.factory({ + data: { + app: { + disableStaticFallbackCache: true, + }, + }, }), ], }); diff --git a/plugins/app-backend/src/service/appPlugin.ts b/plugins/app-backend/src/service/appPlugin.ts index a29f8fd5a8..9ba2ea6d6c 100644 --- a/plugins/app-backend/src/service/appPlugin.ts +++ b/plugins/app-backend/src/service/appPlugin.ts @@ -21,84 +21,49 @@ import { } from '@backstage/backend-plugin-api'; import { createRouter } from './router'; import { loggerToWinstonLogger } from '@backstage/backend-common'; - -/** @alpha */ -export type AppPluginOptions = { - /** - * The name of the app package (in most Backstage repositories, this is the - * "name" field in `packages/app/package.json`) that content should be served - * from. The same app package should be added as a dependency to the backend - * package in order for it to be accessible at runtime. - * - * In a typical setup with a single app package, this will default to 'app'. - */ - appPackageName?: string; - - /** - * A request handler to handle requests for static content that are not present in the app bundle. - * - * This can be used to avoid issues with clients on older deployment versions trying to access lazy - * loaded content that is no longer present. Typically the requests would fall back to a long-term - * object store where all recently deployed versions of the app are present. - * - * Another option is to provide a `database` that will take care of storing the static assets instead. - * - * If both `database` and `staticFallbackHandler` are provided, the `database` will attempt to serve - * static assets first, and if they are not found, the `staticFallbackHandler` will be called. - */ - staticFallbackHandler?: express.Handler; - - /** - * Disables the configuration injection. This can be useful if you're running in an environment - * with a read-only filesystem, or for some other reason don't want configuration to be injected. - * - * Note that this will cause the configuration used when building the app bundle to be used, unless - * a separate configuration loading strategy is set up. - * - * This also disables configuration injection though `APP_CONFIG_` environment variables. - */ - disableConfigInjection?: boolean; - - /** - * By default the app backend plugin will cache previously deployed static assets in the database. - * If you disable this, it is recommended to set a `staticFallbackHandler` instead. - */ - disableStaticFallbackCache?: boolean; -}; +import { staticFallbackHandlerExtensionPoint } from '@backstage/plugin-app-node'; /** * The App plugin is responsible for serving the frontend app bundle and static assets. * @alpha */ -export const appPlugin = createBackendPlugin((options: AppPluginOptions) => ({ +export const appPlugin = createBackendPlugin({ pluginId: 'app', register(env) { + let staticFallbackHandler: express.Handler | undefined; + + env.registerExtensionPoint(staticFallbackHandlerExtensionPoint, { + setStaticFallbackHandler(handler) { + if (staticFallbackHandler) { + throw new Error( + 'Attempted to install a static fallback handler for the app-backend twice', + ); + } + staticFallbackHandler = handler; + }, + }); + env.registerInit({ deps: { logger: coreServices.logger, - config: coreServices.config, + config: coreServices.rootConfig, database: coreServices.database, httpRouter: coreServices.httpRouter, }, async init({ logger, config, database, httpRouter }) { - const { - appPackageName, - staticFallbackHandler, - disableConfigInjection, - disableStaticFallbackCache, - } = options; + const appPackageName = + config.getOptionalString('app.packageName') ?? 'app'; const winstonLogger = loggerToWinstonLogger(logger); const router = await createRouter({ logger: winstonLogger, config, - database: disableStaticFallbackCache ? undefined : database, - appPackageName: appPackageName ?? 'app', + database, + appPackageName, staticFallbackHandler, - disableConfigInjection, }); httpRouter.use(router); }, }); }, -})); +}); diff --git a/plugins/app-backend/src/service/router.ts b/plugins/app-backend/src/service/router.ts index 4e94138439..40e291c19d 100644 --- a/plugins/app-backend/src/service/router.ts +++ b/plugins/app-backend/src/service/router.ts @@ -92,6 +92,13 @@ export async function createRouter( ): Promise { const { config, logger, appPackageName, staticFallbackHandler } = options; + const disableConfigInjection = + options.disableConfigInjection ?? + config.getOptionalBoolean('app.disableConfigInjection'); + const disableStaticFallbackCache = config.getOptionalBoolean( + 'app.disableStaticFallbackCache', + ); + const appDistDir = resolvePackagePath(appPackageName, 'dist'); const staticDir = resolvePath(appDistDir, 'static'); @@ -107,7 +114,7 @@ export async function createRouter( logger.info(`Serving static app content from ${appDistDir}`); - if (!options.disableConfigInjection) { + if (!disableConfigInjection) { const appConfigs = await readConfigs({ config, appDistDir, @@ -131,7 +138,7 @@ export async function createRouter( }), ); - if (options.database) { + if (options.database && !disableStaticFallbackCache) { const store = await StaticAssetsStore.create({ logger, database: options.database, diff --git a/plugins/app-node/.eslintrc.js b/plugins/app-node/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/app-node/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/app-node/CHANGELOG.md b/plugins/app-node/CHANGELOG.md new file mode 100644 index 0000000000..1a2fd84689 --- /dev/null +++ b/plugins/app-node/CHANGELOG.md @@ -0,0 +1,23 @@ +# @backstage/plugin-app-node + +## 0.1.0 + +### Minor Changes + +- 9fbe95ef6503: Added the `app` plugin node library, initially providing an extension point that can be used to configure a static fallback handler. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0 + +## 0.1.0-next.0 + +### Minor Changes + +- 9fbe95ef6503: Added the `app` plugin node library, initially providing an extension point that can be used to configure a static fallback handler. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 diff --git a/plugins/app-node/README.md b/plugins/app-node/README.md new file mode 100644 index 0000000000..5c606540c0 --- /dev/null +++ b/plugins/app-node/README.md @@ -0,0 +1,5 @@ +# @backstage/plugin-app-node + +Welcome to the Node.js library package for the app plugin! + +_This plugin was created through the Backstage CLI_ diff --git a/plugins/app-node/api-report.md b/plugins/app-node/api-report.md new file mode 100644 index 0000000000..504c9d48c1 --- /dev/null +++ b/plugins/app-node/api-report.md @@ -0,0 +1,16 @@ +## API Report File for "@backstage/plugin-app-node" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { ExtensionPoint } from '@backstage/backend-plugin-api'; +import { Handler } from 'express'; + +// @public +export interface StaticFallbackHandlerExtensionPoint { + setStaticFallbackHandler(handler: Handler): void; +} + +// @public +export const staticFallbackHandlerExtensionPoint: ExtensionPoint; +``` diff --git a/plugins/app-node/package.json b/plugins/app-node/package.json new file mode 100644 index 0000000000..842086ecee --- /dev/null +++ b/plugins/app-node/package.json @@ -0,0 +1,35 @@ +{ + "name": "@backstage/plugin-app-node", + "description": "Node.js library for the app plugin", + "version": "0.1.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "node-library" + }, + "scripts": { + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" + }, + "files": [ + "dist" + ], + "dependencies": { + "@backstage/backend-plugin-api": "workspace:^", + "@types/express": "^4.17.6", + "express": "^4.17.1" + } +} diff --git a/plugins/app-node/src/extensions.ts b/plugins/app-node/src/extensions.ts new file mode 100644 index 0000000000..6a75a5b791 --- /dev/null +++ b/plugins/app-node/src/extensions.ts @@ -0,0 +1,52 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createExtensionPoint } from '@backstage/backend-plugin-api'; +import { Handler } from 'express'; + +/** + * The interface for {@link staticFallbackHandlerExtensionPoint}. + * + * @public + */ +export interface StaticFallbackHandlerExtensionPoint { + /** + * Sets the static fallback handler. This can only be done once. + */ + setStaticFallbackHandler(handler: Handler): void; +} + +/** + * An extension point the exposes the ability to configure a static fallback handler for the app backend. + * + * The static fallback handler is a request handler to handle requests for static content that is not + * present in the app bundle. + * + * This can be used to avoid issues with clients on older deployment versions trying to access lazy + * loaded content that is no longer present. Typically the requests would fall back to a long-term + * object store where all recently deployed versions of the app are present. + * + * Another option is to provide a `database` that will take care of storing the static assets instead. + * + * If both `database` and `staticFallbackHandler` are provided, the `database` will attempt to serve + * static assets first, and if they are not found, the `staticFallbackHandler` will be called. + * + * @public + */ +export const staticFallbackHandlerExtensionPoint = + createExtensionPoint({ + id: 'app.staticFallbackHandler', + }); diff --git a/plugins/app-node/src/index.ts b/plugins/app-node/src/index.ts new file mode 100644 index 0000000000..c5189fa8b9 --- /dev/null +++ b/plugins/app-node/src/index.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Node.js library for the app plugin. + * + * @packageDocumentation + */ + +export { + staticFallbackHandlerExtensionPoint, + type StaticFallbackHandlerExtensionPoint, +} from './extensions'; diff --git a/plugins/app-node/src/setupTests.ts b/plugins/app-node/src/setupTests.ts new file mode 100644 index 0000000000..4b9026cde5 --- /dev/null +++ b/plugins/app-node/src/setupTests.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export {}; diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index 60555ef74f..5504f162e6 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-auth-backend +## 0.18.6 + +### Patch Changes + +- 16452cd007ae: Updated `frameHandler` to return `undefined` when using the redirect flow instead of returning `postMessageReponse` which was causing errors +- 9dad4b0e61bd: Updated config schema to match what was being used in code +- bb70a9c3886a: Add frontend visibility to provider objects in `auth` config. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## 0.18.6-next.2 + +### Patch Changes + +- 16452cd007ae: Updated `frameHandler` to return `undefined` when using the redirect flow instead of returning `postMessageReponse` which was causing errors +- bb70a9c3886a: Add frontend visibility to provider objects in `auth` config. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## 0.18.6-next.1 + +### Patch Changes + +- 9dad4b0e61bd: Updated config schema to match what was being used in code +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + ## 0.18.6-next.0 ### Patch Changes diff --git a/plugins/auth-backend/config.d.ts b/plugins/auth-backend/config.d.ts index c6579e08f8..4ebf7c9de1 100644 --- a/plugins/auth-backend/config.d.ts +++ b/plugins/auth-backend/config.d.ts @@ -62,6 +62,7 @@ export interface Config { * @additionalProperties true */ providers?: { + /** @visibility frontend */ google?: { [authEnv: string]: { clientId: string; @@ -72,6 +73,7 @@ export interface Config { callbackUrl?: string; }; }; + /** @visibility frontend */ github?: { [authEnv: string]: { clientId: string; @@ -83,6 +85,7 @@ export interface Config { enterpriseInstanceUrl?: string; }; }; + /** @visibility frontend */ gitlab?: { [authEnv: string]: { clientId: string; @@ -94,6 +97,7 @@ export interface Config { callbackUrl?: string; }; }; + /** @visibility frontend */ saml?: { entryPoint: string; logoutUrl?: string; @@ -117,6 +121,7 @@ export interface Config { digestAlgorithm?: string; acceptedClockSkewMs?: number; }; + /** @visibility frontend */ okta?: { [authEnv: string]: { clientId: string; @@ -130,6 +135,7 @@ export interface Config { callbackUrl?: string; }; }; + /** @visibility frontend */ oauth2?: { [authEnv: string]: { clientId: string; @@ -143,6 +149,7 @@ export interface Config { disableRefresh?: boolean; }; }; + /** @visibility frontend */ oidc?: { [authEnv: string]: { clientId: string; @@ -152,10 +159,13 @@ export interface Config { clientSecret: string; callbackUrl?: string; metadataUrl: string; + tokenEndpointAuthMethod?: string; + tokenSignedResponseAlg?: string; scope?: string; prompt?: string; }; }; + /** @visibility frontend */ auth0?: { [authEnv: string]: { clientId: string; @@ -170,6 +180,7 @@ export interface Config { connectionScope?: string; }; }; + /** @visibility frontend */ microsoft?: { [authEnv: string]: { clientId: string; @@ -181,6 +192,7 @@ export interface Config { callbackUrl?: string; }; }; + /** @visibility frontend */ onelogin?: { [authEnv: string]: { clientId: string; @@ -192,10 +204,12 @@ export interface Config { callbackUrl?: string; }; }; + /** @visibility frontend */ awsalb?: { iss?: string; region: string; }; + /** @visibility frontend */ cfaccess?: { teamName: string; }; diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 4e7f80afaf..be2017e4db 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend", "description": "A Backstage backend plugin that handles authentication", - "version": "0.18.6-next.0", + "version": "0.18.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend/src/lib/flow/authFlowHelpers.test.ts b/plugins/auth-backend/src/lib/flow/authFlowHelpers.test.ts index a0c437815d..a61d51b27b 100644 --- a/plugins/auth-backend/src/lib/flow/authFlowHelpers.test.ts +++ b/plugins/auth-backend/src/lib/flow/authFlowHelpers.test.ts @@ -125,7 +125,7 @@ describe('oauth helpers', () => { postMessageResponse(mockResponse, appOrigin, data); expect(responseBody.match(/.postMessage\(/g)).toHaveLength(2); expect( - responseBody.match(/.postMessage\([a-zA-z.()]*, \'\*\'\)/g), + responseBody.match(/.postMessage\([a-zA-Z.()]*, \'\*\'\)/g), ).toHaveLength(1); const errData: WebMessageResponse = { @@ -135,7 +135,7 @@ describe('oauth helpers', () => { postMessageResponse(mockResponse, appOrigin, errData); expect(responseBody.match(/.postMessage\(/g)).toHaveLength(2); expect( - responseBody.match(/.postMessage\([a-zA-z.()]*, \'\*\'\)/g), + responseBody.match(/.postMessage\([a-zA-Z.()]*, \'\*\'\)/g), ).toHaveLength(1); }); diff --git a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts index 5f51b2d301..fb0750f0cb 100644 --- a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts +++ b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts @@ -187,6 +187,7 @@ export class OAuthAdapter implements AuthProviderRouteHandlers { ); } res.redirect(state.redirectUrl); + return undefined; } // post message back to popup if successful return postMessageResponse(res, appOrigin, responseObj); diff --git a/plugins/auth-node/CHANGELOG.md b/plugins/auth-node/CHANGELOG.md index cb802b9757..30c133338b 100644 --- a/plugins/auth-node/CHANGELOG.md +++ b/plugins/auth-node/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-auth-node +## 0.2.17 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## 0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + +## 0.2.17-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + ## 0.2.17-next.0 ### Patch Changes diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index 07b9adacb4..b5c402367b 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.17-next.0", + "version": "0.2.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -12,6 +12,12 @@ "backstage": { "role": "node-library" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/auth-node" + }, "scripts": { "build": "backstage-cli package build", "lint": "backstage-cli package lint", diff --git a/plugins/azure-devops-backend/CHANGELOG.md b/plugins/azure-devops-backend/CHANGELOG.md index 8aa39659fa..fd9f614d75 100644 --- a/plugins/azure-devops-backend/CHANGELOG.md +++ b/plugins/azure-devops-backend/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-azure-devops-backend +## 0.3.27 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/config@1.0.8 + - @backstage/plugin-azure-devops-common@0.3.0 + +## 0.3.27-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + +## 0.3.27-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/config@1.0.8 + - @backstage/plugin-azure-devops-common@0.3.0 + ## 0.3.27-next.0 ### Patch Changes diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index 0a34ab449b..6868de34fd 100644 --- a/plugins/azure-devops-backend/package.json +++ b/plugins/azure-devops-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops-backend", - "version": "0.3.27-next.0", + "version": "0.3.27", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -12,6 +12,12 @@ "backstage": { "role": "backend-plugin" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/azure-devops-backend" + }, "scripts": { "start": "backstage-cli package start", "build": "backstage-cli package build", diff --git a/plugins/azure-devops-backend/src/plugin.ts b/plugins/azure-devops-backend/src/plugin.ts index 808bdfa248..ea0976a1f2 100644 --- a/plugins/azure-devops-backend/src/plugin.ts +++ b/plugins/azure-devops-backend/src/plugin.ts @@ -31,7 +31,7 @@ export const azureDevOpsPlugin = createBackendPlugin({ register(env) { env.registerInit({ deps: { - config: coreServices.config, + config: coreServices.rootConfig, logger: coreServices.logger, reader: coreServices.urlReader, httpRouter: coreServices.httpRouter, diff --git a/plugins/azure-devops/CHANGELOG.md b/plugins/azure-devops/CHANGELOG.md index 1b405ad870..abf3c3e146 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-azure-devops +## 0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-azure-devops-common@0.3.0 + +## 0.3.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + ## 0.3.3-next.0 ### Patch Changes diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index daaedae825..96674d2cf2 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops", - "version": "0.3.3-next.0", + "version": "0.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites-backend/CHANGELOG.md b/plugins/azure-sites-backend/CHANGELOG.md index 6aa958a860..6e6a662283 100644 --- a/plugins/azure-sites-backend/CHANGELOG.md +++ b/plugins/azure-sites-backend/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-azure-sites-backend +## 0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/config@1.0.8 + - @backstage/plugin-azure-sites-common@0.1.0 + +## 0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + +## 0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/config@1.0.8 + - @backstage/plugin-azure-sites-common@0.1.0 + ## 0.1.10-next.0 ### Patch Changes diff --git a/plugins/azure-sites-backend/package.json b/plugins/azure-sites-backend/package.json index 81d6c434a6..5b6f7ea83f 100644 --- a/plugins/azure-sites-backend/package.json +++ b/plugins/azure-sites-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-sites-backend", - "version": "0.1.10-next.0", + "version": "0.1.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites/CHANGELOG.md b/plugins/azure-sites/CHANGELOG.md index 636c69c76a..6f043950c6 100644 --- a/plugins/azure-sites/CHANGELOG.md +++ b/plugins/azure-sites/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-azure-sites +## 0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-azure-sites-common@0.1.0 + +## 0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + ## 0.1.10-next.0 ### Patch Changes diff --git a/plugins/azure-sites/package.json b/plugins/azure-sites/package.json index 82b1bd1041..a4e50cccea 100644 --- a/plugins/azure-sites/package.json +++ b/plugins/azure-sites/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-sites", - "version": "0.1.10-next.0", + "version": "0.1.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/badges-backend/CHANGELOG.md b/plugins/badges-backend/CHANGELOG.md index 03ba2fa42b..2557b7469a 100644 --- a/plugins/badges-backend/CHANGELOG.md +++ b/plugins/badges-backend/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-badges-backend +## 0.2.3 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## 0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## 0.2.3-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + ## 0.2.3-next.0 ### Patch Changes diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index 02f20826f2..f7acb9308f 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.2.3-next.0", + "version": "0.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/badges-backend/src/plugin.ts b/plugins/badges-backend/src/plugin.ts index ecc03f0c15..3e462e88e9 100644 --- a/plugins/badges-backend/src/plugin.ts +++ b/plugins/badges-backend/src/plugin.ts @@ -31,7 +31,7 @@ export const badgesPlugin = createBackendPlugin({ register(env) { env.registerInit({ deps: { - config: coreServices.config, + config: coreServices.rootConfig, logger: coreServices.logger, discovery: coreServices.discovery, tokenManager: coreServices.tokenManager, diff --git a/plugins/badges/CHANGELOG.md b/plugins/badges/CHANGELOG.md index 5d7527fba4..60e1ecc1be 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-badges +## 0.2.45 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## 0.2.45-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + ## 0.2.45-next.0 ### Patch Changes diff --git a/plugins/badges/package.json b/plugins/badges/package.json index 79add2944c..9146f64de5 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.45-next.0", + "version": "0.2.45", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bazaar-backend/CHANGELOG.md b/plugins/bazaar-backend/CHANGELOG.md index 15059fe6df..2cd3f586c2 100644 --- a/plugins/bazaar-backend/CHANGELOG.md +++ b/plugins/bazaar-backend/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-bazaar-backend +## 0.2.11 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## 0.2.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## 0.2.11-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + ## 0.2.11-next.0 ### Patch Changes diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index 6e960f384c..d97267faf8 100644 --- a/plugins/bazaar-backend/package.json +++ b/plugins/bazaar-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar-backend", - "version": "0.2.11-next.0", + "version": "0.2.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -13,6 +13,12 @@ "backstage": { "role": "backend-plugin" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/bazaar-backend" + }, "scripts": { "start": "backstage-cli package start", "build": "backstage-cli package build --experimental-type-build", diff --git a/plugins/bazaar-backend/src/plugin.ts b/plugins/bazaar-backend/src/plugin.ts index 62622717c8..1c06bda705 100644 --- a/plugins/bazaar-backend/src/plugin.ts +++ b/plugins/bazaar-backend/src/plugin.ts @@ -31,7 +31,7 @@ export const bazaarPlugin = createBackendPlugin({ register(env) { env.registerInit({ deps: { - config: coreServices.config, + config: coreServices.rootConfig, database: coreServices.database, identity: coreServices.identity, logger: coreServices.logger, diff --git a/plugins/bazaar/CHANGELOG.md b/plugins/bazaar/CHANGELOG.md index 7168eaec27..b6bae0f5ed 100644 --- a/plugins/bazaar/CHANGELOG.md +++ b/plugins/bazaar/CHANGELOG.md @@ -1,5 +1,46 @@ # @backstage/plugin-bazaar +## 0.2.12 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/cli@0.22.10 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog@1.12.1 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + +## 0.2.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/plugin-catalog@1.12.1-next.2 + - @backstage/cli@0.22.10-next.1 + +## 0.2.12-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/cli@0.22.10-next.1 + - @backstage/plugin-catalog@1.12.1-next.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + ## 0.2.12-next.0 ### Patch Changes diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index 0536367512..34d7490554 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar", - "version": "0.2.12-next.0", + "version": "0.2.12", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -12,6 +12,12 @@ "backstage": { "role": "frontend-plugin" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/bazaar" + }, "scripts": { "build": "backstage-cli package build", "start": "backstage-cli package start", diff --git a/plugins/bitbucket-cloud-common/CHANGELOG.md b/plugins/bitbucket-cloud-common/CHANGELOG.md index d438d843fd..f1a842f892 100644 --- a/plugins/bitbucket-cloud-common/CHANGELOG.md +++ b/plugins/bitbucket-cloud-common/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-bitbucket-cloud-common +## 0.2.9 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/integration@1.6.0 + +## 0.2.9-next.0 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/integration@1.5.1 + ## 0.2.8 ### Patch Changes diff --git a/plugins/bitbucket-cloud-common/package.json b/plugins/bitbucket-cloud-common/package.json index ffbe670094..2bc9fc3297 100644 --- a/plugins/bitbucket-cloud-common/package.json +++ b/plugins/bitbucket-cloud-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-bitbucket-cloud-common", "description": "Common functionalities for bitbucket-cloud plugins", - "version": "0.2.8", + "version": "0.2.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -14,6 +14,12 @@ "backstage": { "role": "common-library" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/bitbucket-cloud-common" + }, "scripts": { "build": "backstage-cli package build", "lint": "backstage-cli package lint", diff --git a/plugins/bitrise/CHANGELOG.md b/plugins/bitrise/CHANGELOG.md index db09305c36..c44557a51c 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/plugin-bitrise +## 0.1.48 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + +## 0.1.48-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## 0.1.48-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + ## 0.1.48-next.0 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index fe7f1f1591..6d63cb6384 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.48-next.0", + "version": "0.1.48", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -13,6 +13,12 @@ "backstage": { "role": "frontend-plugin" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/bitrise" + }, "scripts": { "build": "backstage-cli package build", "start": "backstage-cli package start", diff --git a/plugins/catalog-backend-module-aws/CHANGELOG.md b/plugins/catalog-backend-module-aws/CHANGELOG.md index 560e1cafb7..b2399d568f 100644 --- a/plugins/catalog-backend-module-aws/CHANGELOG.md +++ b/plugins/catalog-backend-module-aws/CHANGELOG.md @@ -1,5 +1,57 @@ # @backstage/plugin-catalog-backend-module-aws +## 0.2.3 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- b4222908b0c3: Added option to configure AWS `accountId` in `AwsS3EntityProvider` +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - @backstage/integration-aws-node@0.1.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-kubernetes-common@0.6.5 + +## 0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## 0.2.3-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- b4222908b0c3: Added option to configure AWS `accountId` in `AwsS3EntityProvider` +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/integration@1.5.1 + - @backstage/integration-aws-node@0.1.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-kubernetes-common@0.6.5 + ## 0.2.3-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-aws/config.d.ts b/plugins/catalog-backend-module-aws/config.d.ts index b3610ccfc5..4c9c98512e 100644 --- a/plugins/catalog-backend-module-aws/config.d.ts +++ b/plugins/catalog-backend-module-aws/config.d.ts @@ -54,14 +54,19 @@ export interface Config { * @see https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-region.html */ region?: string; + /** + * (Optional) AWS Account id. + * If not set, main account is used. + * @see https://github.com/backstage/backstage/blob/master/packages/integration-aws-node/README.md + */ + accountId?: string; /** * (Optional) TaskScheduleDefinition for the refresh. */ schedule?: TaskScheduleDefinitionConfig; } - | Record< - string, - { + | { + [name: string]: { /** * (Required) AWS S3 Bucket Name */ @@ -77,12 +82,18 @@ export interface Config { * @see https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-region.html */ region?: string; + /** + * (Optional) AWS Account id. + * If not set, main account is used. + * @see https://github.com/backstage/backstage/blob/master/packages/integration-aws-node/README.md + */ + accountId?: string; /** * (Optional) TaskScheduleDefinition for the refresh. */ schedule?: TaskScheduleDefinitionConfig; - } - >; + }; + }; }; }; } diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index d27587a6b3..e593fcf90a 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.2.3-next.0", + "version": "0.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-aws/src/module/catalogModuleAwsS3EntityProvider.test.ts b/plugins/catalog-backend-module-aws/src/module/catalogModuleAwsS3EntityProvider.test.ts index 1475da9e79..c9fea8aa28 100644 --- a/plugins/catalog-backend-module-aws/src/module/catalogModuleAwsS3EntityProvider.test.ts +++ b/plugins/catalog-backend-module-aws/src/module/catalogModuleAwsS3EntityProvider.test.ts @@ -15,13 +15,15 @@ */ import { getVoidLogger } from '@backstage/backend-common'; -import { coreServices } from '@backstage/backend-plugin-api'; +import { + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; import { PluginTaskScheduler, TaskScheduleDefinition, } from '@backstage/backend-tasks'; -import { startTestBackend } from '@backstage/backend-test-utils'; -import { ConfigReader } from '@backstage/config'; +import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { Duration } from 'luxon'; import { catalogModuleAwsS3EntityProvider } from './catalogModuleAwsS3EntityProvider'; @@ -45,7 +47,7 @@ describe('catalogModuleAwsS3EntityProvider', () => { }, } as unknown as PluginTaskScheduler; - const config = new ConfigReader({ + const config = { catalog: { providers: { awsS3: { @@ -57,16 +59,24 @@ describe('catalogModuleAwsS3EntityProvider', () => { }, }, }, - }); + }; await startTestBackend({ extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]], - services: [ - [coreServices.config, config], - [coreServices.logger, getVoidLogger()], - [coreServices.scheduler, scheduler], + features: [ + catalogModuleAwsS3EntityProvider(), + mockServices.rootConfig.factory({ data: config }), + createServiceFactory(() => ({ + service: coreServices.logger, + deps: {}, + factory: getVoidLogger, + }))(), + createServiceFactory(() => ({ + service: coreServices.scheduler, + deps: {}, + factory: () => scheduler, + }))(), ], - features: [catalogModuleAwsS3EntityProvider()], }); expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M')); diff --git a/plugins/catalog-backend-module-aws/src/module/catalogModuleAwsS3EntityProvider.ts b/plugins/catalog-backend-module-aws/src/module/catalogModuleAwsS3EntityProvider.ts index 452284e526..521d61d3d8 100644 --- a/plugins/catalog-backend-module-aws/src/module/catalogModuleAwsS3EntityProvider.ts +++ b/plugins/catalog-backend-module-aws/src/module/catalogModuleAwsS3EntityProvider.ts @@ -33,7 +33,7 @@ export const catalogModuleAwsS3EntityProvider = createBackendModule({ register(env) { env.registerInit({ deps: { - config: coreServices.config, + config: coreServices.rootConfig, catalog: catalogProcessingExtensionPoint, logger: coreServices.logger, scheduler: coreServices.scheduler, diff --git a/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.ts b/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.ts index 4a87a42e75..4df92b58c2 100644 --- a/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.ts +++ b/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.ts @@ -146,20 +146,22 @@ export class AwsS3EntityProvider implements EntityProvider { /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.connect} */ async connect(connection: EntityProviderConnection): Promise { this.connection = connection; - const credProvider = - await this.awsCredentialsManager.getCredentialProvider(); + const { accountId, region, bucketName } = this.config; + const credProvider = await this.awsCredentialsManager.getCredentialProvider( + accountId ? { accountId } : undefined, + ); this.s3 = new S3({ apiVersion: '2006-03-01', credentialDefaultProvider: () => credProvider.sdkCredentialProvider, endpoint: this.integration.config.endpoint, - region: this.config.region, + region, forcePathStyle: this.integration.config.s3ForcePathStyle, }); // https://github.com/aws/aws-sdk-js-v3/issues/4122#issuecomment-1298968804 const endpoint = await getEndpointFromInstructions( { - Bucket: this.config.bucketName, + Bucket: bucketName, }, ListObjectsV2Command, this.s3.config as unknown as Record, diff --git a/plugins/catalog-backend-module-aws/src/providers/config.ts b/plugins/catalog-backend-module-aws/src/providers/config.ts index 5ef2729bf0..1ab52f9fd4 100644 --- a/plugins/catalog-backend-module-aws/src/providers/config.ts +++ b/plugins/catalog-backend-module-aws/src/providers/config.ts @@ -46,6 +46,7 @@ function readAwsS3Config(id: string, config: Config): AwsS3Config { const bucketName = config.getString('bucketName'); const region = config.getOptionalString('region'); const prefix = config.getOptionalString('prefix'); + const accountId = config.getOptionalString('accountId'); const schedule = config.has('schedule') ? readTaskScheduleDefinitionFromConfig(config.getConfig('schedule')) @@ -57,5 +58,6 @@ function readAwsS3Config(id: string, config: Config): AwsS3Config { region, prefix, schedule, + accountId, }; } diff --git a/plugins/catalog-backend-module-aws/src/providers/types.ts b/plugins/catalog-backend-module-aws/src/providers/types.ts index 204fa154c6..8e12b5f096 100644 --- a/plugins/catalog-backend-module-aws/src/providers/types.ts +++ b/plugins/catalog-backend-module-aws/src/providers/types.ts @@ -22,4 +22,5 @@ export type AwsS3Config = { prefix?: string; region?: string; schedule?: TaskScheduleDefinition; + accountId?: string; }; diff --git a/plugins/catalog-backend-module-azure/CHANGELOG.md b/plugins/catalog-backend-module-azure/CHANGELOG.md index 9d60b4a5f2..73b5489600 100644 --- a/plugins/catalog-backend-module-azure/CHANGELOG.md +++ b/plugins/catalog-backend-module-azure/CHANGELOG.md @@ -1,5 +1,51 @@ # @backstage/plugin-catalog-backend-module-azure +## 0.1.19 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + +## 0.1.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## 0.1.19-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + ## 0.1.19-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-azure/config.d.ts b/plugins/catalog-backend-module-azure/config.d.ts index 940695c8ea..757ed2bfd3 100644 --- a/plugins/catalog-backend-module-azure/config.d.ts +++ b/plugins/catalog-backend-module-azure/config.d.ts @@ -16,35 +16,6 @@ import { TaskScheduleDefinitionConfig } from '@backstage/backend-tasks'; -interface AzureDevOpsConfig { - /** - * (Optional) The DevOps host; leave empty for `dev.azure.com`, otherwise set to your self-hosted instance host. - */ - host: string; - /** - * (Required) Your organization slug. - */ - organization: string; - /** - * (Required) Your project slug. - */ - project: string; - /** - * (Optional) The repository name. Wildcards are supported as show on the examples above. - * If not set, all repositories will be searched. - */ - repository?: string; - /** - * (Optional) Where to find catalog-info.yaml files. Wildcards are supported. - * If not set, defaults to /catalog-info.yaml. - */ - path?: string; - /** - * (Optional) TaskScheduleDefinition for the refresh. - */ - schedule?: TaskScheduleDefinitionConfig; -} - export interface Config { catalog?: { /** @@ -54,7 +25,36 @@ export interface Config { /** * AzureDevopsEntityProvider configuration */ - azureDevOps?: Record; + azureDevOps?: { + [name: string]: { + /** + * (Optional) The DevOps host; leave empty for `dev.azure.com`, otherwise set to your self-hosted instance host. + */ + host: string; + /** + * (Required) Your organization slug. + */ + organization: string; + /** + * (Required) Your project slug. + */ + project: string; + /** + * (Optional) The repository name. Wildcards are supported as show on the examples above. + * If not set, all repositories will be searched. + */ + repository?: string; + /** + * (Optional) Where to find catalog-info.yaml files. Wildcards are supported. + * If not set, defaults to /catalog-info.yaml. + */ + path?: string; + /** + * (Optional) TaskScheduleDefinition for the refresh. + */ + schedule?: TaskScheduleDefinitionConfig; + }; + }; }; }; } diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index ac3cdd2b05..eb6a3eadf5 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.19-next.0", + "version": "0.1.19", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-azure/src/module/catalogModuleAzureDevOpsEntityProvider.test.ts b/plugins/catalog-backend-module-azure/src/module/catalogModuleAzureDevOpsEntityProvider.test.ts index fa3b3d865e..3147a0871b 100644 --- a/plugins/catalog-backend-module-azure/src/module/catalogModuleAzureDevOpsEntityProvider.test.ts +++ b/plugins/catalog-backend-module-azure/src/module/catalogModuleAzureDevOpsEntityProvider.test.ts @@ -14,14 +14,15 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; -import { coreServices } from '@backstage/backend-plugin-api'; +import { + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; import { PluginTaskScheduler, TaskScheduleDefinition, } from '@backstage/backend-tasks'; -import { startTestBackend } from '@backstage/backend-test-utils'; -import { ConfigReader } from '@backstage/config'; +import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { Duration } from 'luxon'; import { catalogModuleAzureDevOpsEntityProvider } from './catalogModuleAzureDevOpsEntityProvider'; @@ -45,7 +46,7 @@ describe('catalogModuleAzureDevOpsEntityProvider', () => { }, } as unknown as PluginTaskScheduler; - const config = new ConfigReader({ + const config = { catalog: { providers: { azureDevOps: { @@ -60,16 +61,20 @@ describe('catalogModuleAzureDevOpsEntityProvider', () => { }, }, }, - }); + }; await startTestBackend({ extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]], - services: [ - [coreServices.config, config], - [coreServices.logger, getVoidLogger()], - [coreServices.scheduler, scheduler], + features: [ + catalogModuleAzureDevOpsEntityProvider(), + mockServices.rootConfig.factory({ data: config }), + mockServices.logger.factory(), + createServiceFactory(() => ({ + deps: {}, + service: coreServices.scheduler, + factory: async () => scheduler, + })), ], - features: [catalogModuleAzureDevOpsEntityProvider()], }); expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M')); diff --git a/plugins/catalog-backend-module-azure/src/module/catalogModuleAzureDevOpsEntityProvider.ts b/plugins/catalog-backend-module-azure/src/module/catalogModuleAzureDevOpsEntityProvider.ts index ec8b6441ba..804c0d4712 100644 --- a/plugins/catalog-backend-module-azure/src/module/catalogModuleAzureDevOpsEntityProvider.ts +++ b/plugins/catalog-backend-module-azure/src/module/catalogModuleAzureDevOpsEntityProvider.ts @@ -33,7 +33,7 @@ export const catalogModuleAzureDevOpsEntityProvider = createBackendModule({ register(env) { env.registerInit({ deps: { - config: coreServices.config, + config: coreServices.rootConfig, catalog: catalogProcessingExtensionPoint, logger: coreServices.logger, scheduler: coreServices.scheduler, diff --git a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md index 4aeca8609e..7503ee898e 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,54 @@ # @backstage/plugin-catalog-backend-module-bitbucket-cloud +## 0.1.15 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-bitbucket-cloud-common@0.2.9 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/plugin-events-node@0.2.9 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/plugin-catalog-common@1.0.15 + +## 0.1.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + - @backstage/plugin-events-node@0.2.9-next.2 + +## 0.1.15-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-bitbucket-cloud-common@0.2.9-next.0 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/plugin-events-node@0.2.9-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/plugin-catalog-common@1.0.15 + ## 0.1.15-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-cloud/config.d.ts b/plugins/catalog-backend-module-bitbucket-cloud/config.d.ts index 8fa58413c0..fa7c070042 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/config.d.ts +++ b/plugins/catalog-backend-module-bitbucket-cloud/config.d.ts @@ -45,24 +45,23 @@ export interface Config { */ filters?: { /** - * (Optional) Filter for the repository slug. + * (Optional) Regular expression filter for the repository slug. * @visibility frontend */ - repoSlug?: RegExp; + repoSlug?: string; /** - * (Optional) Filter for the project key. + * (Optional) Regular expression filter for the project key. * @visibility frontend */ - projectKey?: RegExp; + projectKey?: string; }; /** * (Optional) TaskScheduleDefinition for the discovery. */ schedule?: TaskScheduleDefinitionConfig; } - | Record< - string, - { + | { + [name: string]: { /** * (Optional) Path to the catalog file. Default to "/catalog-info.yaml". * @visibility frontend @@ -79,22 +78,22 @@ export interface Config { */ filters?: { /** - * (Optional) Filter for the repository slug. + * (Optional) Regular expression filter for the repository slug. * @visibility frontend */ - repoSlug?: RegExp; + repoSlug?: string; /** - * (Optional) Filter for the project key. + * (Optional) Regular expression filter for the project key. * @visibility frontend */ - projectKey?: RegExp; + projectKey?: string; }; /** * (Optional) TaskScheduleDefinition for the discovery. */ schedule?: TaskScheduleDefinitionConfig; - } - >; + }; + }; }; }; } diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 1baa14f00f..42df54688b 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-cloud", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket Cloud", - "version": "0.1.15-next.0", + "version": "0.1.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-cloud/src/module/catalogModuleBitbucketCloudEntityProvider.test.ts b/plugins/catalog-backend-module-bitbucket-cloud/src/module/catalogModuleBitbucketCloudEntityProvider.test.ts index a34eae3750..83769fc3f5 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/src/module/catalogModuleBitbucketCloudEntityProvider.test.ts +++ b/plugins/catalog-backend-module-bitbucket-cloud/src/module/catalogModuleBitbucketCloudEntityProvider.test.ts @@ -14,7 +14,10 @@ * limitations under the License. */ -import { coreServices } from '@backstage/backend-plugin-api'; +import { + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; import { PluginTaskScheduler, TaskScheduleDefinition, @@ -55,8 +58,9 @@ describe('catalogModuleBitbucketCloudEntityProvider', () => { [catalogProcessingExtensionPoint, catalogExtensionPointImpl], [eventsExtensionPoint, eventsExtensionPointImpl], ], - services: [ - mockServices.config.factory({ + features: [ + catalogModuleBitbucketCloudEntityProvider(), + mockServices.rootConfig.factory({ data: { catalog: { providers: { @@ -71,9 +75,12 @@ describe('catalogModuleBitbucketCloudEntityProvider', () => { }, }, }), - [coreServices.scheduler, scheduler], + createServiceFactory({ + service: coreServices.scheduler, + deps: {}, + factory: async () => scheduler, + }), ], - features: [catalogModuleBitbucketCloudEntityProvider()], }); expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M')); diff --git a/plugins/catalog-backend-module-bitbucket-cloud/src/module/catalogModuleBitbucketCloudEntityProvider.ts b/plugins/catalog-backend-module-bitbucket-cloud/src/module/catalogModuleBitbucketCloudEntityProvider.ts index 7c4f4a30b2..e5e1ad1609 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/src/module/catalogModuleBitbucketCloudEntityProvider.ts +++ b/plugins/catalog-backend-module-bitbucket-cloud/src/module/catalogModuleBitbucketCloudEntityProvider.ts @@ -37,7 +37,7 @@ export const catalogModuleBitbucketCloudEntityProvider = createBackendModule({ deps: { catalog: catalogProcessingExtensionPoint, catalogApi: catalogServiceRef, - config: coreServices.config, + config: coreServices.rootConfig, // TODO(pjungermann): How to make this optional for those which only want the provider without event support? // Do we even want to support this? events: eventsExtensionPoint, diff --git a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md index fa0c443e3a..1b5a65f254 100644 --- a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,47 @@ # @backstage/plugin-catalog-backend-module-bitbucket-server +## 0.1.13 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## 0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## 0.1.13-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + ## 0.1.13-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-server/config.d.ts b/plugins/catalog-backend-module-bitbucket-server/config.d.ts index 67f694d419..57a94550e9 100644 --- a/plugins/catalog-backend-module-bitbucket-server/config.d.ts +++ b/plugins/catalog-backend-module-bitbucket-server/config.d.ts @@ -37,24 +37,23 @@ export interface Config { */ filters?: { /** - * (Optional) Filter for the repository slug. + * (Optional) Regular expression filter for the repository slug. * @visibility frontend */ - repoSlug?: RegExp; + repoSlug?: string; /** - * (Optional) Filter for the project key. + * (Optional) Regular expression filter for the project key. * @visibility frontend */ - projectKey?: RegExp; + projectKey?: string; }; /** * (Optional) TaskScheduleDefinition for the refresh. */ schedule?: TaskScheduleDefinitionConfig; } - | Record< - string, - { + | { + [name: string]: { /** * (Optional) Path to the catalog file. Default to "/catalog-info.yaml". * @visibility frontend @@ -66,22 +65,22 @@ export interface Config { */ filters?: { /** - * (Optional) Filter for the repository slug. + * (Optional) Regular expression filter for the repository slug. * @visibility frontend */ - repoSlug?: RegExp; + repoSlug?: string; /** - * (Optional) Filter for the project key. + * (Optional) Regular expression filter for the project key. * @visibility frontend */ - projectKey?: RegExp; + projectKey?: string; }; /** * (Optional) TaskScheduleDefinition for the refresh. */ schedule?: TaskScheduleDefinitionConfig; - } - >; + }; + }; }; }; } diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index 4b35c8f7d7..7e488e31ff 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-server", - "version": "0.1.13-next.0", + "version": "0.1.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-server/src/module/catalogModuleBitbucketServerEntityProvider.test.ts b/plugins/catalog-backend-module-bitbucket-server/src/module/catalogModuleBitbucketServerEntityProvider.test.ts index d17b4a4c96..ae4a636008 100644 --- a/plugins/catalog-backend-module-bitbucket-server/src/module/catalogModuleBitbucketServerEntityProvider.test.ts +++ b/plugins/catalog-backend-module-bitbucket-server/src/module/catalogModuleBitbucketServerEntityProvider.test.ts @@ -14,14 +14,15 @@ * limitations under the License. */ -import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; -import { coreServices } from '@backstage/backend-plugin-api'; +import { + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; import { PluginTaskScheduler, TaskScheduleDefinition, } from '@backstage/backend-tasks'; -import { startTestBackend } from '@backstage/backend-test-utils'; +import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { catalogModuleBitbucketServerEntityProvider } from './catalogModuleBitbucketServerEntityProvider'; import { Duration } from 'luxon'; @@ -45,7 +46,7 @@ describe('catalogModuleBitbucketServerEntityProvider', () => { }, } as unknown as PluginTaskScheduler; - const config = new ConfigReader({ + const config = { catalog: { providers: { bitbucketServer: { @@ -64,16 +65,20 @@ describe('catalogModuleBitbucketServerEntityProvider', () => { }, ], }, - }); + }; await startTestBackend({ extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]], - services: [ - [coreServices.config, config], - [coreServices.logger, getVoidLogger()], - [coreServices.scheduler, scheduler], + features: [ + catalogModuleBitbucketServerEntityProvider(), + mockServices.rootConfig.factory({ data: config }), + mockServices.logger.factory(), + createServiceFactory({ + service: coreServices.scheduler, + deps: {}, + factory: async () => scheduler, + }), ], - features: [catalogModuleBitbucketServerEntityProvider()], }); expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M')); diff --git a/plugins/catalog-backend-module-bitbucket-server/src/module/catalogModuleBitbucketServerEntityProvider.ts b/plugins/catalog-backend-module-bitbucket-server/src/module/catalogModuleBitbucketServerEntityProvider.ts index 354bce7d6d..ef71df9b06 100644 --- a/plugins/catalog-backend-module-bitbucket-server/src/module/catalogModuleBitbucketServerEntityProvider.ts +++ b/plugins/catalog-backend-module-bitbucket-server/src/module/catalogModuleBitbucketServerEntityProvider.ts @@ -32,7 +32,7 @@ export const catalogModuleBitbucketServerEntityProvider = createBackendModule({ env.registerInit({ deps: { catalog: catalogProcessingExtensionPoint, - config: coreServices.config, + config: coreServices.rootConfig, logger: coreServices.logger, scheduler: coreServices.scheduler, }, diff --git a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md index 9c1da14fba..ef448f6b20 100644 --- a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-catalog-backend-module-bitbucket +## 0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.9 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/integration@1.6.0 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## 0.2.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## 0.2.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-bitbucket-cloud-common@0.2.9-next.0 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + ## 0.2.15-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket/package.json b/plugins/catalog-backend-module-bitbucket/package.json index e968aad343..45ca64dc71 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.15-next.0", + "version": "0.2.15", "deprecated": true, "main": "src/index.ts", "types": "src/index.ts", diff --git a/plugins/catalog-backend-module-gcp/.eslintrc.js b/plugins/catalog-backend-module-gcp/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/catalog-backend-module-gcp/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/catalog-backend-module-gcp/CHANGELOG.md b/plugins/catalog-backend-module-gcp/CHANGELOG.md new file mode 100644 index 0000000000..c30f91fa61 --- /dev/null +++ b/plugins/catalog-backend-module-gcp/CHANGELOG.md @@ -0,0 +1,45 @@ +# @backstage/plugin-catalog-backend-module-gcp + +## 0.1.0 + +### Minor Changes + +- 290eff6692aa: Added GCP catalog plugin with GKE provider + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/backend-tasks@0.5.5 + - @backstage/config@1.0.8 + - @backstage/plugin-kubernetes-common@0.6.5 + +## 0.1.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## 0.1.0-next.0 + +### Minor Changes + +- 290eff6692aa: Added GCP catalog plugin with GKE provider + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/config@1.0.8 + - @backstage/plugin-kubernetes-common@0.6.5 diff --git a/plugins/catalog-backend-module-gcp/README.md b/plugins/catalog-backend-module-gcp/README.md new file mode 100644 index 0000000000..d1ef926310 --- /dev/null +++ b/plugins/catalog-backend-module-gcp/README.md @@ -0,0 +1,41 @@ +# Catalog Backend Module for GCP + +This is an extension module to the plugin-catalog-backend plugin, containing catalog processors and providers to ingest GCP resources as `Resource` kind entities. + +## installation + +Register the plugin in `catalog.ts`` + +```typescript +import { GkeEntityProvider } from '@backstage/plugin-catalog-backend-module-gcp'; + +... + +builder.addEntityProvider( + GkeEntityProvider.fromConfig({ + logger: env.logger, + scheduler: env.scheduler, + config: env.config + }) +); +``` + +Update `app-config.yaml` as follows: + +```yaml +catalog: + providers: + gcp: + gke: + parents: + # consult https://cloud.google.com/kubernetes-engine/docs/ for valid values + # list all clusters in the project + - 'projects/some-project/locations/-' + # list all clusters in the region, in the project + - 'projects/some-other-project/locations/some-region' + schedule: # optional; same options as in TaskScheduleDefinition + # supports cron, ISO duration, "human duration" as used in code + frequency: { minutes: 30 } + # supports ISO duration, "human duration" as used in code + timeout: { minutes: 3 } +``` diff --git a/plugins/catalog-backend-module-gcp/alpha-api-report.md b/plugins/catalog-backend-module-gcp/alpha-api-report.md new file mode 100644 index 0000000000..6e6f0427e9 --- /dev/null +++ b/plugins/catalog-backend-module-gcp/alpha-api-report.md @@ -0,0 +1,7 @@ +## API Report File for "@backstage/plugin-catalog-backend-module-gcp" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +``` diff --git a/plugins/catalog-backend-module-gcp/api-report.md b/plugins/catalog-backend-module-gcp/api-report.md new file mode 100644 index 0000000000..6f963ed51d --- /dev/null +++ b/plugins/catalog-backend-module-gcp/api-report.md @@ -0,0 +1,48 @@ +## API Report File for "@backstage/plugin-catalog-backend-module-gcp" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; +import { Config } from '@backstage/config'; +import * as container from '@google-cloud/container'; +import { EntityProvider } from '@backstage/plugin-catalog-node'; +import { EntityProviderConnection } from '@backstage/plugin-catalog-node'; +import { Logger } from 'winston'; +import { SchedulerService } from '@backstage/backend-plugin-api'; + +// @public +export const catalogModuleGcpGkeEntityProvider: () => BackendFeature; + +// @public +export class GkeEntityProvider implements EntityProvider { + // (undocumented) + connect(connection: EntityProviderConnection): Promise; + // (undocumented) + static fromConfig({ + logger, + scheduler, + config, + }: { + logger: Logger; + scheduler: SchedulerService; + config: Config; + }): GkeEntityProvider; + // (undocumented) + static fromConfigWithClient({ + logger, + scheduler, + config, + clusterManagerClient, + }: { + logger: Logger; + scheduler: SchedulerService; + config: Config; + clusterManagerClient: container.v1.ClusterManagerClient; + }): GkeEntityProvider; + // (undocumented) + getProviderName(): string; + // (undocumented) + refresh(): Promise; +} +``` diff --git a/plugins/catalog-backend-module-gcp/config.d.ts b/plugins/catalog-backend-module-gcp/config.d.ts new file mode 100644 index 0000000000..d6884d32ce --- /dev/null +++ b/plugins/catalog-backend-module-gcp/config.d.ts @@ -0,0 +1,45 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { TaskScheduleDefinitionConfig } from '@backstage/backend-tasks'; + +export interface Config { + catalog?: { + /** + * List of provider-specific options and attributes + */ + providers?: { + /** + * GCPCatalogModuleConfig configuration + */ + gcp?: { + /** + * Config for GKE clusters + */ + gke?: { + /** + * Locations to list clusters from + */ + parents: string[]; + /** + * (Optional) TaskScheduleDefinition for the refresh. + */ + schedule: TaskScheduleDefinitionConfig; + }; + }; + }; + }; +} diff --git a/plugins/catalog-backend-module-gcp/package.json b/plugins/catalog-backend-module-gcp/package.json new file mode 100644 index 0000000000..dcff6662dd --- /dev/null +++ b/plugins/catalog-backend-module-gcp/package.json @@ -0,0 +1,66 @@ +{ + "name": "@backstage/plugin-catalog-backend-module-gcp", + "description": "A Backstage catalog backend module that helps integrate towards GCP", + "version": "0.1.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.ts" + ], + "package.json": [ + "package.json" + ] + } + }, + "backstage": { + "role": "backend-plugin-module" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/catalog-backend-module-gcp" + }, + "keywords": [ + "backstage" + ], + "scripts": { + "start": "backstage-cli package start", + "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": { + "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", + "@backstage/backend-tasks": "workspace:^", + "@backstage/config": "workspace:^", + "@backstage/plugin-catalog-node": "workspace:^", + "@backstage/plugin-kubernetes-common": "workspace:^", + "@google-cloud/container": "^4.15.0", + "winston": "^3.2.1" + }, + "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^" + }, + "files": [ + "config.d.ts", + "dist" + ], + "configSchema": "config.d.ts" +} diff --git a/plugins/catalog-backend-module-gcp/src/alpha.ts b/plugins/catalog-backend-module-gcp/src/alpha.ts new file mode 100644 index 0000000000..9eec69e76f --- /dev/null +++ b/plugins/catalog-backend-module-gcp/src/alpha.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * A Backstage catalog backend module that helps integrate towards GCP + * + * @packageDocumentation + */ + +export {}; diff --git a/plugins/catalog-backend-module-gcp/src/index.ts b/plugins/catalog-backend-module-gcp/src/index.ts new file mode 100644 index 0000000000..fb3984a04d --- /dev/null +++ b/plugins/catalog-backend-module-gcp/src/index.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * A Backstage catalog backend module that helps integrate towards GCP + * + * @packageDocumentation + */ + +export * from './providers'; +export * from './module'; diff --git a/plugins/catalog-backend-module-gcp/src/module/catalogModuleGcpGkeEntityProvider.ts b/plugins/catalog-backend-module-gcp/src/module/catalogModuleGcpGkeEntityProvider.ts new file mode 100644 index 0000000000..7f93bddbfe --- /dev/null +++ b/plugins/catalog-backend-module-gcp/src/module/catalogModuleGcpGkeEntityProvider.ts @@ -0,0 +1,52 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { loggerToWinstonLogger } from '@backstage/backend-common'; +import { + coreServices, + createBackendModule, +} from '@backstage/backend-plugin-api'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; +import { GkeEntityProvider } from '../providers/GkeEntityProvider'; + +/** + * Registers the GcpGkeEntityProvider with the catalog processing extension point. + * + * @public + */ +export const catalogModuleGcpGkeEntityProvider = createBackendModule({ + pluginId: 'catalog', + moduleId: 'gcpGkeEntityProvider', + register(env) { + env.registerInit({ + deps: { + config: coreServices.rootConfig, + catalog: catalogProcessingExtensionPoint, + logger: coreServices.logger, + scheduler: coreServices.scheduler, + }, + async init({ config, catalog, logger, scheduler }) { + catalog.addEntityProvider( + GkeEntityProvider.fromConfig({ + logger: loggerToWinstonLogger(logger), + scheduler, + config, + }), + ); + }, + }); + }, +}); diff --git a/plugins/catalog-backend-module-gcp/src/module/index.ts b/plugins/catalog-backend-module-gcp/src/module/index.ts new file mode 100644 index 0000000000..c7cd310c97 --- /dev/null +++ b/plugins/catalog-backend-module-gcp/src/module/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { catalogModuleGcpGkeEntityProvider } from './catalogModuleGcpGkeEntityProvider'; diff --git a/plugins/catalog-backend-module-gcp/src/providers/GkeEntityProvider.test.ts b/plugins/catalog-backend-module-gcp/src/providers/GkeEntityProvider.test.ts new file mode 100644 index 0000000000..20e91a85bf --- /dev/null +++ b/plugins/catalog-backend-module-gcp/src/providers/GkeEntityProvider.test.ts @@ -0,0 +1,251 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { GkeEntityProvider } from './GkeEntityProvider'; +import { TaskRunner } from '@backstage/backend-tasks'; +import { + ANNOTATION_KUBERNETES_API_SERVER, + ANNOTATION_KUBERNETES_API_SERVER_CA, + ANNOTATION_KUBERNETES_AUTH_PROVIDER, +} from '@backstage/plugin-kubernetes-common'; +import * as container from '@google-cloud/container'; +import { ConfigReader } from '@backstage/config'; + +describe('GkeEntityProvider', () => { + const clusterManagerClientMock = { + listClusters: jest.fn(), + }; + const connectionMock = { + applyMutation: jest.fn(), + refresh: jest.fn(), + }; + const taskRunner = { + createScheduleFn: jest.fn(), + run: jest.fn(), + } as TaskRunner; + const schedulerMock = { + createScheduledTaskRunner: jest.fn(), + } as any; + const logger = { + info: jest.fn(), + error: jest.fn(), + }; + let gkeEntityProvider: GkeEntityProvider; + + beforeEach(async () => { + jest.resetAllMocks(); + schedulerMock.createScheduledTaskRunner.mockReturnValue(taskRunner); + gkeEntityProvider = GkeEntityProvider.fromConfigWithClient({ + logger: logger as any, + config: new ConfigReader({ + catalog: { + providers: { + gcp: { + gke: { + parents: ['parent1', 'parent2'], + schedule: { + frequency: { + minutes: 3, + }, + timeout: { + minutes: 3, + }, + }, + }, + }, + }, + }, + }), + scheduler: schedulerMock, + clusterManagerClient: clusterManagerClientMock as any, + }); + await gkeEntityProvider.connect(connectionMock); + }); + + it('should return clusters as Resources', async () => { + clusterManagerClientMock.listClusters.mockImplementation(req => { + if (req.parent === 'parent1') { + return [ + { + clusters: [ + { + name: 'some-cluster', + endpoint: 'http://127.0.0.1:1234', + location: 'some-location', + selfLink: 'http://127.0.0.1/some-link', + masterAuth: { + clusterCaCertificate: 'abcdefg', + }, + }, + ], + }, + ]; + } else if (req.parent === 'parent2') { + return [ + { + clusters: [ + { + name: 'some-other-cluster', + endpoint: 'http://127.0.0.1:5678', + location: 'some-other-location', + selfLink: 'http://127.0.0.1/some-other-link', + masterAuth: { + // no CA cert is ok + }, + }, + ], + }, + ]; + } + + throw new Error(`unexpected parent ${req.parent}`); + }); + await gkeEntityProvider.refresh(); + expect(connectionMock.applyMutation).toHaveBeenCalledWith({ + type: 'full', + entities: [ + { + locationKey: 'gcp-gke:some-location', + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Resource', + metadata: { + annotations: { + [ANNOTATION_KUBERNETES_API_SERVER]: 'http://127.0.0.1:1234', + [ANNOTATION_KUBERNETES_API_SERVER_CA]: 'abcdefg', + [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'google', + 'backstage.io/managed-by-location': 'gcp-gke:some-location', + 'backstage.io/managed-by-origin-location': + 'gcp-gke:some-location', + }, + name: 'some-cluster', + namespace: 'default', + }, + spec: { + type: 'kubernetes-cluster', + owner: 'unknown', + }, + }, + }, + { + locationKey: 'gcp-gke:some-other-location', + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Resource', + metadata: { + annotations: { + [ANNOTATION_KUBERNETES_API_SERVER]: 'http://127.0.0.1:5678', + [ANNOTATION_KUBERNETES_API_SERVER_CA]: '', + [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'google', + 'backstage.io/managed-by-location': + 'gcp-gke:some-other-location', + 'backstage.io/managed-by-origin-location': + 'gcp-gke:some-other-location', + }, + name: 'some-other-cluster', + namespace: 'default', + }, + spec: { + type: 'kubernetes-cluster', + owner: 'unknown', + }, + }, + }, + ], + }); + }); + + const ignoredPartialClustersTests: [ + string, + container.protos.google.container.v1.ICluster, + ][] = [ + [ + 'no-cluster-name', + { + endpoint: 'http://127.0.0.1:1234', + location: 'some-location', + selfLink: 'http://127.0.0.1/some-link', + masterAuth: { + clusterCaCertificate: 'abcdefg', + }, + }, + ], + [ + 'no-self-link', + { + // no selfLink + name: 'some-name', + endpoint: 'http://127.0.0.1:1234', + location: 'some-location', + masterAuth: { + clusterCaCertificate: 'abcdefg', + }, + }, + ], + [ + 'no-endpoint', + { + name: 'some-name', + location: 'some-location', + selfLink: 'http://127.0.0.1/some-link', + masterAuth: { + clusterCaCertificate: 'abcdefg', + }, + }, + ], + [ + 'no-location', + { + name: 'some-name', + endpoint: 'http://127.0.0.1:1234', + selfLink: 'http://127.0.0.1/some-link', + masterAuth: { + clusterCaCertificate: 'abcdefg', + }, + }, + ], + ]; + + it.each(ignoredPartialClustersTests)( + 'ignore cluster - %s', + async (_name, ignoredCluster) => { + clusterManagerClientMock.listClusters.mockImplementation(req => { + if (req.parent === 'parent1') { + return [ignoredCluster]; + } + return [ + { + clusters: [], + }, + ]; + }); + await gkeEntityProvider.refresh(); + expect(connectionMock.applyMutation).toHaveBeenCalledWith({ + type: 'full', + entities: [], + }); + }, + ); + + it('should log GKE API errors', async () => { + clusterManagerClientMock.listClusters.mockRejectedValue( + new Error('some-error'), + ); + await gkeEntityProvider.refresh(); + expect(connectionMock.applyMutation).toHaveBeenCalledTimes(0); + expect(logger.error).toHaveBeenCalledTimes(1); + }); +}); diff --git a/plugins/catalog-backend-module-gcp/src/providers/GkeEntityProvider.ts b/plugins/catalog-backend-module-gcp/src/providers/GkeEntityProvider.ts new file mode 100644 index 0000000000..0130955737 --- /dev/null +++ b/plugins/catalog-backend-module-gcp/src/providers/GkeEntityProvider.ts @@ -0,0 +1,223 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + TaskRunner, + readTaskScheduleDefinitionFromConfig, +} from '@backstage/backend-tasks'; +import { + DeferredEntity, + EntityProvider, + EntityProviderConnection, +} from '@backstage/plugin-catalog-node'; + +import { Logger } from 'winston'; +import * as container from '@google-cloud/container'; +import { + ANNOTATION_KUBERNETES_API_SERVER, + ANNOTATION_KUBERNETES_API_SERVER_CA, + ANNOTATION_KUBERNETES_AUTH_PROVIDER, +} from '@backstage/plugin-kubernetes-common'; +import { Config } from '@backstage/config'; +import { SchedulerService } from '@backstage/backend-plugin-api'; + +/** + * Catalog provider to ingest GKE clusters + * + * @public + */ +export class GkeEntityProvider implements EntityProvider { + private readonly logger: Logger; + private readonly scheduleFn: () => Promise; + private readonly gkeParents: string[]; + private readonly clusterManagerClient: container.v1.ClusterManagerClient; + private connection?: EntityProviderConnection; + + private constructor( + logger: Logger, + taskRunner: TaskRunner, + gkeParents: string[], + clusterManagerClient: container.v1.ClusterManagerClient, + ) { + this.logger = logger; + this.scheduleFn = this.createScheduleFn(taskRunner); + this.gkeParents = gkeParents; + this.clusterManagerClient = clusterManagerClient; + } + + public static fromConfig({ + logger, + scheduler, + config, + }: { + logger: Logger; + scheduler: SchedulerService; + config: Config; + }) { + return GkeEntityProvider.fromConfigWithClient({ + logger, + scheduler: scheduler, + config, + clusterManagerClient: new container.v1.ClusterManagerClient(), + }); + } + + public static fromConfigWithClient({ + logger, + scheduler, + config, + clusterManagerClient, + }: { + logger: Logger; + scheduler: SchedulerService; + config: Config; + clusterManagerClient: container.v1.ClusterManagerClient; + }) { + const gkeProviderConfig = config.getConfig('catalog.providers.gcp.gke'); + const schedule = readTaskScheduleDefinitionFromConfig( + gkeProviderConfig.getConfig('schedule'), + ); + return new GkeEntityProvider( + logger, + scheduler.createScheduledTaskRunner(schedule), + gkeProviderConfig.getStringArray('parents'), + clusterManagerClient, + ); + } + + getProviderName(): string { + return `gcp-gke`; + } + + async connect(connection: EntityProviderConnection): Promise { + this.connection = connection; + await this.scheduleFn(); + } + + private filterOutUndefinedDeferredEntity( + e: DeferredEntity | undefined, + ): e is DeferredEntity { + return e !== undefined; + } + + private filterOutUndefinedCluster( + c: container.protos.google.container.v1.ICluster | null | undefined, + ): c is container.protos.google.container.v1.ICluster { + return c !== undefined && c !== null; + } + + private clusterToResource( + cluster: container.protos.google.container.v1.ICluster, + ): DeferredEntity | undefined { + const location = `${this.getProviderName()}:${cluster.location}`; + + if (!cluster.name || !cluster.selfLink || !location || !cluster.endpoint) { + this.logger.warn( + `ignoring partial cluster, one of name=${cluster.name}, endpoint=${cluster.endpoint}, selfLink=${cluster.selfLink} or location=${cluster.location} is missing`, + ); + return undefined; + } + + // TODO fix location type + return { + locationKey: location, + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Resource', + metadata: { + annotations: { + [ANNOTATION_KUBERNETES_API_SERVER]: cluster.endpoint, + [ANNOTATION_KUBERNETES_API_SERVER_CA]: + cluster.masterAuth?.clusterCaCertificate || '', + [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'google', + 'backstage.io/managed-by-location': location, + 'backstage.io/managed-by-origin-location': location, + }, + name: cluster.name, + namespace: 'default', + }, + spec: { + type: 'kubernetes-cluster', + owner: 'unknown', + }, + }, + }; + } + + private createScheduleFn(taskRunner: TaskRunner): () => Promise { + return async () => { + const taskId = `${this.getProviderName()}:refresh`; + return taskRunner.run({ + id: taskId, + fn: async () => { + try { + await this.refresh(); + } catch (error) { + this.logger.error(error); + } + }, + }); + }; + } + + private async getClusters(): Promise< + container.protos.google.container.v1.ICluster[] + > { + const clusters = await Promise.all( + this.gkeParents.map(async parent => { + const request = { + parent: parent, + }; + const [response] = await this.clusterManagerClient.listClusters( + request, + ); + return response.clusters?.filter(this.filterOutUndefinedCluster) ?? []; + }), + ); + return clusters.flat(); + } + + async refresh() { + if (!this.connection) { + throw new Error('Not initialized'); + } + + this.logger.info('Discovering GKE clusters'); + + let clusters: container.protos.google.container.v1.ICluster[]; + + try { + clusters = await this.getClusters(); + } catch (e) { + this.logger.error('error fetching GKE clusters', e); + return; + } + const resources = + clusters + .map(c => this.clusterToResource(c)) + .filter(this.filterOutUndefinedDeferredEntity) ?? []; + + this.logger.info( + `Ingesting GKE clusters [${resources + .map(r => r.entity.metadata.name) + .join(', ')}]`, + ); + + await this.connection.applyMutation({ + type: 'full', + entities: resources, + }); + } +} diff --git a/plugins/catalog-backend-module-gcp/src/providers/index.ts b/plugins/catalog-backend-module-gcp/src/providers/index.ts new file mode 100644 index 0000000000..7846afc3ed --- /dev/null +++ b/plugins/catalog-backend-module-gcp/src/providers/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 { GkeEntityProvider } from './GkeEntityProvider'; diff --git a/plugins/catalog-backend-module-gcp/src/setupTests.ts b/plugins/catalog-backend-module-gcp/src/setupTests.ts new file mode 100644 index 0000000000..aa70772592 --- /dev/null +++ b/plugins/catalog-backend-module-gcp/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export {}; diff --git a/plugins/catalog-backend-module-gerrit/CHANGELOG.md b/plugins/catalog-backend-module-gerrit/CHANGELOG.md index 09df93f029..3bb53b864b 100644 --- a/plugins/catalog-backend-module-gerrit/CHANGELOG.md +++ b/plugins/catalog-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,47 @@ # @backstage/plugin-catalog-backend-module-gerrit +## 0.1.16 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + +## 0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## 0.1.16-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + ## 0.1.16-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-gerrit/config.d.ts b/plugins/catalog-backend-module-gerrit/config.d.ts index d8b48d2967..a246662b0a 100644 --- a/plugins/catalog-backend-module-gerrit/config.d.ts +++ b/plugins/catalog-backend-module-gerrit/config.d.ts @@ -25,9 +25,8 @@ export interface Config { * * Maps provider id with configuration. */ - gerrit?: Record< - string, - { + gerrit?: { + [name: string]: { /** * (Required) The host of the Gerrit integration to use. */ @@ -42,8 +41,8 @@ export interface Config { * The branch where the provider will try to find entities. Defaults to "master". */ branch?: string; - } - >; + }; + }; }; }; } diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index aa0fc95907..99e9ed5e12 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.16-next.0", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-gerrit/src/module/catalogModuleGerritEntityProvider.test.ts b/plugins/catalog-backend-module-gerrit/src/module/catalogModuleGerritEntityProvider.test.ts index 0511aa7b4c..9807814f61 100644 --- a/plugins/catalog-backend-module-gerrit/src/module/catalogModuleGerritEntityProvider.test.ts +++ b/plugins/catalog-backend-module-gerrit/src/module/catalogModuleGerritEntityProvider.test.ts @@ -14,14 +14,15 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; -import { coreServices } from '@backstage/backend-plugin-api'; +import { + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; import { PluginTaskScheduler, TaskScheduleDefinition, } from '@backstage/backend-tasks'; -import { startTestBackend } from '@backstage/backend-test-utils'; -import { ConfigReader } from '@backstage/config'; +import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { Duration } from 'luxon'; import { catalogModuleGerritEntityProvider } from './catalogModuleGerritEntityProvider'; @@ -45,7 +46,7 @@ describe('catalogModuleGerritEntityProvider', () => { }, } as unknown as PluginTaskScheduler; - const config = new ConfigReader({ + const config = { catalog: { providers: { gerrit: { @@ -70,16 +71,20 @@ describe('catalogModuleGerritEntityProvider', () => { }, ], }, - }); + }; await startTestBackend({ extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]], - services: [ - [coreServices.config, config], - [coreServices.logger, getVoidLogger()], - [coreServices.scheduler, scheduler], + features: [ + catalogModuleGerritEntityProvider(), + mockServices.rootConfig.factory({ data: config }), + mockServices.logger.factory(), + createServiceFactory({ + service: coreServices.scheduler, + deps: {}, + factory: async () => scheduler, + }), ], - features: [catalogModuleGerritEntityProvider()], }); expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M')); diff --git a/plugins/catalog-backend-module-gerrit/src/module/catalogModuleGerritEntityProvider.ts b/plugins/catalog-backend-module-gerrit/src/module/catalogModuleGerritEntityProvider.ts index 814259fb40..bb29ce6eef 100644 --- a/plugins/catalog-backend-module-gerrit/src/module/catalogModuleGerritEntityProvider.ts +++ b/plugins/catalog-backend-module-gerrit/src/module/catalogModuleGerritEntityProvider.ts @@ -32,7 +32,7 @@ export const catalogModuleGerritEntityProvider = createBackendModule({ env.registerInit({ deps: { catalog: catalogProcessingExtensionPoint, - config: coreServices.config, + config: coreServices.rootConfig, logger: coreServices.logger, scheduler: coreServices.scheduler, }, diff --git a/plugins/catalog-backend-module-github/CHANGELOG.md b/plugins/catalog-backend-module-github/CHANGELOG.md index 3743f035c4..4d14c2ce5a 100644 --- a/plugins/catalog-backend-module-github/CHANGELOG.md +++ b/plugins/catalog-backend-module-github/CHANGELOG.md @@ -1,5 +1,60 @@ # @backstage/plugin-catalog-backend-module-github +## 0.3.3 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- 81c231c9c9ee: Fixed a bug where the visibility filter was case sensitive and casting was inconsistent. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-catalog-backend@1.12.0 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/plugin-events-node@0.2.9 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + +## 0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.12.0-next.2 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + - @backstage/plugin-events-node@0.2.9-next.2 + +## 0.3.3-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-backend@1.12.0-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/plugin-events-node@0.2.9-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + ## 0.3.3-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-github/config.d.ts b/plugins/catalog-backend-module-github/config.d.ts index 5a699e745f..9755504ee2 100644 --- a/plugins/catalog-backend-module-github/config.d.ts +++ b/plugins/catalog-backend-module-github/config.d.ts @@ -118,9 +118,8 @@ export interface Config { */ schedule?: TaskScheduleDefinitionConfig; } - | Record< - string, - { + | { + [name: string]: { /** * (Optional) The hostname of your GitHub Enterprise instance. * Default: `github.com`. @@ -182,8 +181,8 @@ export interface Config { * (Optional) TaskScheduleDefinition for the refresh. */ schedule?: TaskScheduleDefinitionConfig; - } - >; + }; + }; }; }; } diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index 2e64d39638..101c0f54f0 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.3.3-next.0", + "version": "0.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-github/src/lib/util.ts b/plugins/catalog-backend-module-github/src/lib/util.ts index bb91e9dd2a..58ae8d6551 100644 --- a/plugins/catalog-backend-module-github/src/lib/util.ts +++ b/plugins/catalog-backend-module-github/src/lib/util.ts @@ -107,5 +107,10 @@ export function satisfiesVisibilityFilter( if (!visibilities.length) { return true; } - return visibilities.includes(visibility); + const lowerCaseVisibilities = visibilities.map(v => + v.toLocaleLowerCase('en-US'), + ); + const lowerCaseVisibility = visibility.toLocaleLowerCase('en-US'); + + return lowerCaseVisibilities.includes(lowerCaseVisibility); } diff --git a/plugins/catalog-backend-module-github/src/module/catalogModuleGithubEntityProvider.test.ts b/plugins/catalog-backend-module-github/src/module/catalogModuleGithubEntityProvider.test.ts index 82a5552dba..9e36966eec 100644 --- a/plugins/catalog-backend-module-github/src/module/catalogModuleGithubEntityProvider.test.ts +++ b/plugins/catalog-backend-module-github/src/module/catalogModuleGithubEntityProvider.test.ts @@ -14,18 +14,19 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; -import { coreServices } from '@backstage/backend-plugin-api'; import { PluginTaskScheduler, TaskScheduleDefinition, } from '@backstage/backend-tasks'; -import { startTestBackend } from '@backstage/backend-test-utils'; -import { ConfigReader } from '@backstage/config'; +import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { Duration } from 'luxon'; import { catalogModuleGithubEntityProvider } from './catalogModuleGithubEntityProvider'; import { GithubEntityProvider } from '../providers/GithubEntityProvider'; +import { + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; describe('catalogModuleGithubEntityProvider', () => { it('should register provider at the catalog extension point', async () => { @@ -45,7 +46,7 @@ describe('catalogModuleGithubEntityProvider', () => { }, } as unknown as PluginTaskScheduler; - const config = new ConfigReader({ + const config = { catalog: { providers: { github: { @@ -57,16 +58,19 @@ describe('catalogModuleGithubEntityProvider', () => { }, }, }, - }); + }; await startTestBackend({ extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]], - services: [ - [coreServices.config, config], - [coreServices.logger, getVoidLogger()], - [coreServices.scheduler, scheduler], + features: [ + catalogModuleGithubEntityProvider(), + mockServices.rootConfig.factory({ data: config }), + createServiceFactory({ + service: coreServices.scheduler, + deps: {}, + factory: async () => scheduler, + }), ], - features: [catalogModuleGithubEntityProvider()], }); expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M')); diff --git a/plugins/catalog-backend-module-github/src/module/catalogModuleGithubEntityProvider.ts b/plugins/catalog-backend-module-github/src/module/catalogModuleGithubEntityProvider.ts index 997da3023b..8e052bd0a0 100644 --- a/plugins/catalog-backend-module-github/src/module/catalogModuleGithubEntityProvider.ts +++ b/plugins/catalog-backend-module-github/src/module/catalogModuleGithubEntityProvider.ts @@ -34,7 +34,7 @@ export const catalogModuleGithubEntityProvider = createBackendModule({ env.registerInit({ deps: { catalog: catalogProcessingExtensionPoint, - config: coreServices.config, + config: coreServices.rootConfig, logger: coreServices.logger, scheduler: coreServices.scheduler, }, diff --git a/plugins/catalog-backend-module-gitlab/CHANGELOG.md b/plugins/catalog-backend-module-gitlab/CHANGELOG.md index 2fcba33d47..0f860bb050 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,53 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.2.4 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- e6c721439f37: Added option to skip forked repos in GitlabDiscoveryEntityProvider +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- 2fe1f5973ff7: Filter Gitlab archived projects through APIs +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## 0.2.4-next.2 + +### Patch Changes + +- 2fe1f5973ff7: Filter Gitlab archived projects through APIs +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## 0.2.4-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- e6c721439f37: Added option to skip forked repos in GitlabDiscoveryEntityProvider +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + ## 0.2.4-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/config.d.ts b/plugins/catalog-backend-module-gitlab/config.d.ts index f5afc71093..7d183b6e58 100644 --- a/plugins/catalog-backend-module-gitlab/config.d.ts +++ b/plugins/catalog-backend-module-gitlab/config.d.ts @@ -22,9 +22,8 @@ export interface Config { /** * GitlabDiscoveryEntityProvider configuration */ - gitlab?: Record< - string, - { + gitlab?: { + [name: string]: { /** * (Required) Gitlab's host name. */ @@ -51,21 +50,21 @@ export interface Config { /** * (Optional) RegExp for the Project Name Pattern */ - projectPattern?: RegExp; + projectPattern?: string; /** * (Optional) RegExp for the User Name Pattern */ - userPattern?: RegExp; + userPattern?: string; /** * (Optional) RegExp for the Group Name Pattern */ - groupPattern?: RegExp; + groupPattern?: string; /** * (Optional) Skip forked repository */ skipForkedRepos?: boolean; - } - >; + }; + }; }; }; } diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index 1a3f0245eb..3f31ffdf1d 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab", "description": "A Backstage catalog backend module that helps integrate towards GitLab", - "version": "0.2.4-next.0", + "version": "0.2.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-gitlab/src/GitLabDiscoveryProcessor.test.ts b/plugins/catalog-backend-module-gitlab/src/GitLabDiscoveryProcessor.test.ts index 6333184ea8..a56c229105 100644 --- a/plugins/catalog-backend-module-gitlab/src/GitLabDiscoveryProcessor.test.ts +++ b/plugins/catalog-backend-module-gitlab/src/GitLabDiscoveryProcessor.test.ts @@ -56,6 +56,7 @@ function setupFakeServer( listProjectsCallback: (request: { page: number; include_subgroups: boolean; + archived: boolean; }) => { data: GitLabProject[]; nextPage?: number; @@ -74,20 +75,24 @@ function setupFakeServer( } const page = req.url.searchParams.get('page'); const include_subgroups = req.url.searchParams.get('include_subgroups'); + const archived = req.url.searchParams.get('archived'); const response = listProjectsCallback({ page: parseInt(page!, 10), include_subgroups: include_subgroups === 'true', + archived: archived === 'true', }); // Filter the fake results based on the `last_activity_after` parameter const last_activity_after = req.url.searchParams.get( 'last_activity_after', ); - const filteredData = response.data.filter( - v => - !last_activity_after || - Date.parse(v.last_activity_at) >= Date.parse(last_activity_after), - ); + const filteredData = response.data + .filter( + v => + !last_activity_after || + Date.parse(v.last_activity_at) >= Date.parse(last_activity_after), + ) + .filter(v => archived || !v.archived); return res( ctx.set('x-next-page', response.nextPage?.toString() ?? ''), @@ -250,6 +255,7 @@ describe('GitlabDiscoveryProcessor', () => { }, ], }; + default: throw new Error('Invalid request'); } diff --git a/plugins/catalog-backend-module-gitlab/src/GitLabDiscoveryProcessor.ts b/plugins/catalog-backend-module-gitlab/src/GitLabDiscoveryProcessor.ts index c9bd4d9187..02b1b1cb51 100644 --- a/plugins/catalog-backend-module-gitlab/src/GitLabDiscoveryProcessor.ts +++ b/plugins/catalog-backend-module-gitlab/src/GitLabDiscoveryProcessor.ts @@ -109,6 +109,7 @@ export class GitLabDiscoveryProcessor implements CatalogProcessor { const lastActivity = (await this.cache.get(this.getCacheKey())) as string; const opts = { + archived: false, group, page: 1, // We check for the existence of lastActivity and only set it if it's present to ensure @@ -125,10 +126,6 @@ export class GitLabDiscoveryProcessor implements CatalogProcessor { for await (const project of projects) { res.scanned++; - if (project.archived) { - continue; - } - if (branch === '*' && project.default_branch === undefined) { continue; } diff --git a/plugins/catalog-backend-module-gitlab/src/lib/client.ts b/plugins/catalog-backend-module-gitlab/src/lib/client.ts index f0e169d8df..41b99e1c5b 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/client.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/client.ts @@ -30,6 +30,7 @@ export type CommonListOptions = { }; interface ListProjectOptions extends CommonListOptions { + archived?: boolean; group?: string; } diff --git a/plugins/catalog-backend-module-gitlab/src/module/catalogModuleGitlabDiscoveryEntityProvider.test.ts b/plugins/catalog-backend-module-gitlab/src/module/catalogModuleGitlabDiscoveryEntityProvider.test.ts index 7a3d0a0e0d..22759cafa0 100644 --- a/plugins/catalog-backend-module-gitlab/src/module/catalogModuleGitlabDiscoveryEntityProvider.test.ts +++ b/plugins/catalog-backend-module-gitlab/src/module/catalogModuleGitlabDiscoveryEntityProvider.test.ts @@ -14,14 +14,15 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; -import { coreServices } from '@backstage/backend-plugin-api'; +import { + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; import { PluginTaskScheduler, TaskScheduleDefinition, } from '@backstage/backend-tasks'; -import { startTestBackend } from '@backstage/backend-test-utils'; -import { ConfigReader } from '@backstage/config'; +import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { Duration } from 'luxon'; import { catalogModuleGitlabDiscoveryEntityProvider } from './catalogModuleGitlabDiscoveryEntityProvider'; @@ -45,7 +46,7 @@ describe('catalogModuleGitlabDiscoveryEntityProvider', () => { }, } as unknown as PluginTaskScheduler; - const config = new ConfigReader({ + const config = { integrations: { gitlab: [ { @@ -69,16 +70,20 @@ describe('catalogModuleGitlabDiscoveryEntityProvider', () => { }, }, }, - }); + }; await startTestBackend({ extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]], - services: [ - [coreServices.config, config], - [coreServices.logger, getVoidLogger()], - [coreServices.scheduler, scheduler], + features: [ + catalogModuleGitlabDiscoveryEntityProvider(), + mockServices.rootConfig.factory({ data: config }), + mockServices.logger.factory(), + createServiceFactory({ + deps: {}, + service: coreServices.scheduler, + factory: async () => scheduler, + }), ], - features: [catalogModuleGitlabDiscoveryEntityProvider()], }); expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M')); diff --git a/plugins/catalog-backend-module-gitlab/src/module/catalogModuleGitlabDiscoveryEntityProvider.ts b/plugins/catalog-backend-module-gitlab/src/module/catalogModuleGitlabDiscoveryEntityProvider.ts index ffae233319..d192e8f3a5 100644 --- a/plugins/catalog-backend-module-gitlab/src/module/catalogModuleGitlabDiscoveryEntityProvider.ts +++ b/plugins/catalog-backend-module-gitlab/src/module/catalogModuleGitlabDiscoveryEntityProvider.ts @@ -33,7 +33,7 @@ export const catalogModuleGitlabDiscoveryEntityProvider = createBackendModule({ register(env) { env.registerInit({ deps: { - config: coreServices.config, + config: coreServices.rootConfig, catalog: catalogProcessingExtensionPoint, logger: coreServices.logger, scheduler: coreServices.scheduler, diff --git a/plugins/catalog-backend-module-gitlab/src/providers/GitlabDiscoveryEntityProvider.ts b/plugins/catalog-backend-module-gitlab/src/providers/GitlabDiscoveryEntityProvider.ts index 08d2fe48a7..ce7a304746 100644 --- a/plugins/catalog-backend-module-gitlab/src/providers/GitlabDiscoveryEntityProvider.ts +++ b/plugins/catalog-backend-module-gitlab/src/providers/GitlabDiscoveryEntityProvider.ts @@ -155,6 +155,7 @@ export class GitlabDiscoveryEntityProvider implements EntityProvider { const projects = paginated( options => client.listProjects(options), { + archived: false, group: this.config.group, page: 1, per_page: 50, @@ -173,10 +174,6 @@ export class GitlabDiscoveryEntityProvider implements EntityProvider { res.scanned++; - if (project.archived) { - continue; - } - if ( this.config.skipForkedRepos && project.hasOwnProperty('forked_from_project') diff --git a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md index 583458667d..7fa5ac3c11 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md +++ b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md @@ -1,5 +1,52 @@ # @backstage/plugin-catalog-backend-module-incremental-ingestion +## 0.4.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- e2b6396a1274: Export new alpha `incrementalIngestionProvidersExtensionPoint` for registering incremental providers, rather than the providers being passed as options to the backend module. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-catalog-backend@1.12.0 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/plugin-events-node@0.2.9 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-permission-common@0.7.7 + +## 0.4.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.12.0-next.2 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + - @backstage/plugin-events-node@0.2.9-next.2 + +## 0.4.1-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-backend@1.12.0-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/plugin-events-node@0.2.9-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-permission-common@0.7.7 + ## 0.4.1-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-incremental-ingestion/alpha-api-report.md b/plugins/catalog-backend-module-incremental-ingestion/alpha-api-report.md index b11ec43cf5..995c6e4893 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/alpha-api-report.md +++ b/plugins/catalog-backend-module-incremental-ingestion/alpha-api-report.md @@ -4,16 +4,23 @@ ```ts import { BackendFeature } from '@backstage/backend-plugin-api'; +import { ExtensionPoint } from '@backstage/backend-plugin-api'; import { IncrementalEntityProvider } from '@backstage/plugin-catalog-backend-module-incremental-ingestion'; import { IncrementalEntityProviderOptions } from '@backstage/plugin-catalog-backend-module-incremental-ingestion'; // @alpha -export const catalogModuleIncrementalIngestionEntityProvider: (options: { - providers: { - provider: IncrementalEntityProvider; +export const catalogModuleIncrementalIngestionEntityProvider: () => BackendFeature; + +// @alpha +export interface IncrementalIngestionProviderExtensionPoint { + addProvider(config: { options: IncrementalEntityProviderOptions; - }[]; -}) => BackendFeature; + provider: IncrementalEntityProvider; + }): void; +} + +// @alpha +export const incrementalIngestionProvidersExtensionPoint: ExtensionPoint; // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index a6a947c93c..30a64c20b2 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-incremental-ingestion", "description": "An entity provider for streaming large asset sources into the catalog", - "version": "0.4.1-next.0", + "version": "0.4.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/module/WrapperProviders.ts b/plugins/catalog-backend-module-incremental-ingestion/src/module/WrapperProviders.ts index 4738893c95..cc2954ea05 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/module/WrapperProviders.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/module/WrapperProviders.ts @@ -15,7 +15,7 @@ */ import { - ConfigService, + RootConfigService, LoggerService, SchedulerService, } from '@backstage/backend-plugin-api'; @@ -49,7 +49,7 @@ export class WrapperProviders { constructor( private readonly options: { - config: ConfigService; + config: RootConfigService; logger: LoggerService; client: Knex; scheduler: SchedulerService; diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/module/catalogModuleIncrementalIngestionEntityProvider.test.ts b/plugins/catalog-backend-module-incremental-ingestion/src/module/catalogModuleIncrementalIngestionEntityProvider.test.ts index ef07b4cb10..ed0c776fa8 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/module/catalogModuleIncrementalIngestionEntityProvider.test.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/module/catalogModuleIncrementalIngestionEntityProvider.test.ts @@ -14,13 +14,18 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; -import { coreServices } from '@backstage/backend-plugin-api'; +import { + coreServices, + createBackendModule, + createServiceFactory, +} from '@backstage/backend-plugin-api'; import { startTestBackend } from '@backstage/backend-test-utils'; -import { ConfigReader } from '@backstage/config'; import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { IncrementalEntityProvider } from '../types'; -import { catalogModuleIncrementalIngestionEntityProvider } from './catalogModuleIncrementalIngestionEntityProvider'; +import { + catalogModuleIncrementalIngestionEntityProvider, + incrementalIngestionProvidersExtensionPoint, +} from './catalogModuleIncrementalIngestionEntityProvider'; describe('catalogModuleIncrementalIngestionEntityProvider', () => { it('should register provider at the catalog extension point', async () => { @@ -37,37 +42,35 @@ describe('catalogModuleIncrementalIngestionEntityProvider', () => { const addEntityProvider = jest.fn(); const httpRouterUse = jest.fn(); - const scheduler = {}; - const database = { - getClient: jest.fn(), - }; - const httpRouter = { - use: httpRouterUse, - }; - await startTestBackend({ extensionPoints: [ [catalogProcessingExtensionPoint, { addEntityProvider }], ], - services: [ - [coreServices.config, new ConfigReader({})], - [coreServices.database, database], - [coreServices.httpRouter, httpRouter], - [coreServices.logger, getVoidLogger()], - [coreServices.scheduler, scheduler], - ], features: [ - catalogModuleIncrementalIngestionEntityProvider({ - providers: [ - { - provider: provider1, - options: { - burstInterval: { seconds: 1 }, - burstLength: { seconds: 1 }, - restLength: { seconds: 1 }, + createServiceFactory({ + service: coreServices.httpRouter, + deps: {}, + factory: () => ({ use: httpRouterUse }), + }), + catalogModuleIncrementalIngestionEntityProvider(), + createBackendModule({ + pluginId: 'catalog', + moduleId: 'incrementalTest', + register(env) { + env.registerInit({ + deps: { extension: incrementalIngestionProvidersExtensionPoint }, + async init({ extension }) { + extension.addProvider({ + provider: provider1, + options: { + burstInterval: { seconds: 1 }, + burstLength: { seconds: 1 }, + restLength: { seconds: 1 }, + }, + }); }, - }, - ], + }); + }, }), ], }); diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/module/catalogModuleIncrementalIngestionEntityProvider.ts b/plugins/catalog-backend-module-incremental-ingestion/src/module/catalogModuleIncrementalIngestionEntityProvider.ts index 19d5742b46..4e94088ef6 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/module/catalogModuleIncrementalIngestionEntityProvider.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/module/catalogModuleIncrementalIngestionEntityProvider.ts @@ -17,6 +17,7 @@ import { coreServices, createBackendModule, + createExtensionPoint, } from '@backstage/backend-plugin-api'; import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { @@ -25,56 +26,111 @@ import { } from '@backstage/plugin-catalog-backend-module-incremental-ingestion'; import { WrapperProviders } from './WrapperProviders'; +/** + * @alpha + * Interface for {@link incrementalIngestionProvidersExtensionPoint}. + */ +export interface IncrementalIngestionProviderExtensionPoint { + /** Adds a new incremental entity provider */ + addProvider(config: { + options: IncrementalEntityProviderOptions; + provider: IncrementalEntityProvider; + }): void; +} + +/** + * @alpha + * + * Extension point for registering incremental ingestion providers. + * The `catalogModuleIncrementalIngestionEntityProvider` must be installed for these providers to work. + * + * @example + * + * ```ts + * backend.add(createBackendModule({ + * pluginId: 'catalog', + * moduleId: 'myIncrementalProvider', + * register(env) { + * env.registerInit({ + * deps: { + * extension: incrementalIngestionProvidersExtensionPoint, + * }, + * async init({ extension }) { + * extension.addProvider({ + * burstInterval: ..., + * burstLength: ..., + * restLength: ..., + * }, { + * next(context, cursor) { + * ... + * }, + * ... + * }) + * }) + * }) + * } + * })) + * ``` + */ +export const incrementalIngestionProvidersExtensionPoint = + createExtensionPoint({ + id: 'catalog.incrementalIngestionProvider.providers', + }); + /** * Registers the incremental entity provider with the catalog processing extension point. * * @alpha */ export const catalogModuleIncrementalIngestionEntityProvider = - createBackendModule( - (options: { - providers: Array<{ + createBackendModule({ + pluginId: 'catalog', + moduleId: 'incrementalIngestionEntityProvider', + register(env) { + const addedProviders = new Array<{ provider: IncrementalEntityProvider; options: IncrementalEntityProviderOptions; - }>; - }) => ({ - pluginId: 'catalog', - moduleId: 'incrementalIngestionEntityProvider', - register(env) { - env.registerInit({ - deps: { - catalog: catalogProcessingExtensionPoint, - config: coreServices.config, - database: coreServices.database, - httpRouter: coreServices.httpRouter, - logger: coreServices.logger, - scheduler: coreServices.scheduler, - }, - async init({ - catalog, + }>(); + + env.registerExtensionPoint(incrementalIngestionProvidersExtensionPoint, { + addProvider({ options, provider }) { + addedProviders.push({ options, provider }); + }, + }); + + env.registerInit({ + deps: { + catalog: catalogProcessingExtensionPoint, + config: coreServices.rootConfig, + database: coreServices.database, + httpRouter: coreServices.httpRouter, + logger: coreServices.logger, + scheduler: coreServices.scheduler, + }, + async init({ + catalog, + config, + database, + httpRouter, + logger, + scheduler, + }) { + const client = await database.getClient(); + + const providers = new WrapperProviders({ config, - database, - httpRouter, logger, + client, scheduler, - }) { - const client = await database.getClient(); + }); - const providers = new WrapperProviders({ - config, - logger, - client, - scheduler, - }); + for (const entry of addedProviders) { + const wrapped = providers.wrap(entry.provider, entry.options); + catalog.addEntityProvider(wrapped); + } - for (const entry of options.providers) { - const wrapped = providers.wrap(entry.provider, entry.options); - catalog.addEntityProvider(wrapped); - } - - httpRouter.use(await providers.adminRouter()); - }, - }); - }, - }), - ); + httpRouter.use(await providers.adminRouter()); + }, + }); + }, + }); diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/module/index.ts b/plugins/catalog-backend-module-incremental-ingestion/src/module/index.ts index 9fcee99e01..37ecf60f7c 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/module/index.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/module/index.ts @@ -14,4 +14,8 @@ * limitations under the License. */ -export { catalogModuleIncrementalIngestionEntityProvider } from './catalogModuleIncrementalIngestionEntityProvider'; +export { + catalogModuleIncrementalIngestionEntityProvider, + incrementalIngestionProvidersExtensionPoint, + type IncrementalIngestionProviderExtensionPoint, +} from './catalogModuleIncrementalIngestionEntityProvider'; diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts index f94c988237..cfb4c20def 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts @@ -20,12 +20,16 @@ import { createBackend } from '@backstage/backend-defaults'; import { coreServices, + createBackendModule, createServiceFactory, } from '@backstage/backend-plugin-api'; import { ConfigReader } from '@backstage/config'; import { catalogPlugin } from '@backstage/plugin-catalog-backend/alpha'; import { IncrementalEntityProvider } from '.'; -import { catalogModuleIncrementalIngestionEntityProvider } from './alpha'; +import { + catalogModuleIncrementalIngestionEntityProvider, + incrementalIngestionProvidersExtensionPoint, +} from './alpha'; const provider: IncrementalEntityProvider = { getProviderName: () => 'test-provider', @@ -51,29 +55,36 @@ async function main() { }, }; - const backend = createBackend({ - services: [ - createServiceFactory({ - service: coreServices.config, - deps: {}, - factory: () => new ConfigReader(config), - }), - ], - }); + const backend = createBackend(); - backend.add(catalogPlugin()); backend.add( - catalogModuleIncrementalIngestionEntityProvider({ - providers: [ - { - provider: provider, - options: { - burstInterval: { seconds: 1 }, - burstLength: { seconds: 10 }, - restLength: { seconds: 10 }, + createServiceFactory({ + service: coreServices.rootConfig, + deps: {}, + factory: () => new ConfigReader(config), + }), + ); + backend.add(catalogPlugin()); + backend.add(catalogModuleIncrementalIngestionEntityProvider()); + backend.add( + createBackendModule({ + pluginId: 'catalog', + moduleId: 'incrementalTestProvider', + register(reg) { + reg.registerInit({ + deps: { extension: incrementalIngestionProvidersExtensionPoint }, + async init({ extension }) { + extension.addProvider({ + provider: provider, + options: { + burstInterval: { seconds: 1 }, + burstLength: { seconds: 10 }, + restLength: { seconds: 10 }, + }, + }); }, - }, - ], + }); + }, }), ); diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index 4e9cabb577..9db8a14c9f 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.5.15 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + +## 0.5.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## 0.5.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + ## 0.5.15-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index 742065735d..8d3a6277c3 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.15-next.0", + "version": "0.5.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-msgraph/CHANGELOG.md b/plugins/catalog-backend-module-msgraph/CHANGELOG.md index 0edda3b91d..383ceffe0e 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,46 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.5.7 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- fb93323201bf: The alpha `catalogModuleMicrosoftGraphOrgEntityProvider` export no longer accepts options. Transformers are now instead configured via the `microsoftGraphOrgEntityProviderTransformExtensionPoint`. +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/plugin-catalog-common@1.0.15 + +## 0.5.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## 0.5.7-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/plugin-catalog-common@1.0.15 + ## 0.5.7-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-msgraph/alpha-api-report.md b/plugins/catalog-backend-module-msgraph/alpha-api-report.md index 0fa093a1bc..6d877ba713 100644 --- a/plugins/catalog-backend-module-msgraph/alpha-api-report.md +++ b/plugins/catalog-backend-module-msgraph/alpha-api-report.md @@ -4,6 +4,7 @@ ```ts import { BackendFeature } from '@backstage/backend-plugin-api'; +import { ExtensionPoint } from '@backstage/backend-plugin-api'; import { GroupTransformer } from '@backstage/plugin-catalog-backend-module-msgraph'; import { OrganizationTransformer } from '@backstage/plugin-catalog-backend-module-msgraph'; import { UserTransformer } from '@backstage/plugin-catalog-backend-module-msgraph'; @@ -12,12 +13,21 @@ import { UserTransformer } from '@backstage/plugin-catalog-backend-module-msgrap export const catalogModuleMicrosoftGraphOrgEntityProvider: () => BackendFeature; // @alpha -export interface CatalogModuleMicrosoftGraphOrgEntityProviderOptions { - groupTransformer?: GroupTransformer | Record; - organizationTransformer?: - | OrganizationTransformer - | Record; - userTransformer?: UserTransformer | Record; +export const microsoftGraphOrgEntityProviderTransformExtensionPoint: ExtensionPoint; + +// @alpha +export interface MicrosoftGraphOrgEntityProviderTransformsExtensionPoint { + setGroupTransformer( + transformer: GroupTransformer | Record, + ): void; + setOrganizationTransformer( + transformer: + | OrganizationTransformer + | Record, + ): void; + setUserTransformer( + transformer: UserTransformer | Record, + ): void; } // (No @packageDocumentation comment for this package) diff --git a/plugins/catalog-backend-module-msgraph/config.d.ts b/plugins/catalog-backend-module-msgraph/config.d.ts index 904ce1f646..9d341215cd 100644 --- a/plugins/catalog-backend-module-msgraph/config.d.ts +++ b/plugins/catalog-backend-module-msgraph/config.d.ts @@ -209,9 +209,8 @@ export interface Config { */ schedule?: TaskScheduleDefinitionConfig; } - | Record< - string, - { + | { + [name: string]: { /** * The prefix of the target that this matches on, e.g. * "https://graph.microsoft.com/v1.0", with no trailing slash. @@ -296,8 +295,8 @@ export interface Config { * (Optional) TaskScheduleDefinition for the refresh. */ schedule?: TaskScheduleDefinitionConfig; - } - >; + }; + }; }; }; } diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index c802b15d16..5d2afe69bf 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-msgraph", "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph", - "version": "0.5.7-next.0", + "version": "0.5.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-msgraph/src/module/catalogModuleMicrosoftGraphOrgEntityProvider.test.ts b/plugins/catalog-backend-module-msgraph/src/module/catalogModuleMicrosoftGraphOrgEntityProvider.test.ts index 3362c75c95..96fec41cbe 100644 --- a/plugins/catalog-backend-module-msgraph/src/module/catalogModuleMicrosoftGraphOrgEntityProvider.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/module/catalogModuleMicrosoftGraphOrgEntityProvider.test.ts @@ -14,14 +14,15 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; -import { coreServices } from '@backstage/backend-plugin-api'; +import { + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; import { PluginTaskScheduler, TaskScheduleDefinition, } from '@backstage/backend-tasks'; -import { startTestBackend } from '@backstage/backend-test-utils'; -import { ConfigReader } from '@backstage/config'; +import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { Duration } from 'luxon'; import { catalogModuleMicrosoftGraphOrgEntityProvider } from './catalogModuleMicrosoftGraphOrgEntityProvider'; @@ -45,7 +46,7 @@ describe('catalogModuleMicrosoftGraphOrgEntityProvider', () => { }, } as unknown as PluginTaskScheduler; - const config = new ConfigReader({ + const config = { catalog: { providers: { microsoftGraphOrg: { @@ -62,16 +63,19 @@ describe('catalogModuleMicrosoftGraphOrgEntityProvider', () => { }, }, }, - }); + }; await startTestBackend({ extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]], - services: [ - [coreServices.config, config], - [coreServices.logger, getVoidLogger()], - [coreServices.scheduler, scheduler], + features: [ + catalogModuleMicrosoftGraphOrgEntityProvider(), + mockServices.rootConfig.factory({ data: config }), + createServiceFactory(() => ({ + deps: {}, + service: coreServices.scheduler, + factory: async () => scheduler, + })), ], - features: [catalogModuleMicrosoftGraphOrgEntityProvider()], }); expect(usedSchedule?.frequency).toEqual(Duration.fromISO('PT30M')); diff --git a/plugins/catalog-backend-module-msgraph/src/module/catalogModuleMicrosoftGraphOrgEntityProvider.ts b/plugins/catalog-backend-module-msgraph/src/module/catalogModuleMicrosoftGraphOrgEntityProvider.ts index 7cd8b65f0b..b0d22ab0f4 100644 --- a/plugins/catalog-backend-module-msgraph/src/module/catalogModuleMicrosoftGraphOrgEntityProvider.ts +++ b/plugins/catalog-backend-module-msgraph/src/module/catalogModuleMicrosoftGraphOrgEntityProvider.ts @@ -17,6 +17,7 @@ import { coreServices, createBackendModule, + createExtensionPoint, } from '@backstage/backend-plugin-api'; import { loggerToWinstonLogger } from '@backstage/backend-common'; import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; @@ -28,32 +29,50 @@ import { import { MicrosoftGraphOrgEntityProvider } from '../processors'; /** - * Options for {@link catalogModuleMicrosoftGraphOrgEntityProvider}. + * Interface for {@link microsoftGraphOrgEntityProviderTransformExtensionPoint}. * * @alpha */ -export interface CatalogModuleMicrosoftGraphOrgEntityProviderOptions { +export interface MicrosoftGraphOrgEntityProviderTransformsExtensionPoint { /** - * The function that transforms a user entry in msgraph to an entity. + * Set the function that transforms a user entry in msgraph to an entity. * Optionally, you can pass separate transformers per provider ID. */ - userTransformer?: UserTransformer | Record; + setUserTransformer( + transformer: UserTransformer | Record, + ): void; /** - * The function that transforms a group entry in msgraph to an entity. + * Set the function that transforms a group entry in msgraph to an entity. * Optionally, you can pass separate transformers per provider ID. */ - groupTransformer?: GroupTransformer | Record; + setGroupTransformer( + transformer: GroupTransformer | Record, + ): void; /** - * The function that transforms an organization entry in msgraph to an entity. + * Set the function that transforms an organization entry in msgraph to an entity. * Optionally, you can pass separate transformers per provider ID. */ - organizationTransformer?: - | OrganizationTransformer - | Record; + setOrganizationTransformer( + transformer: + | OrganizationTransformer + | Record, + ): void; } +/** + * Extension point used to customize the transforms used by the {@link catalogModuleMicrosoftGraphOrgEntityProvider}. + * + * @alpha + */ +export const microsoftGraphOrgEntityProviderTransformExtensionPoint = + createExtensionPoint( + { + id: 'catalog.microsoftGraphOrgEntityProvider.transforms', + }, + ); + /** * Registers the MicrosoftGraphOrgEntityProvider with the catalog processing extension point. * @@ -63,25 +82,59 @@ export const catalogModuleMicrosoftGraphOrgEntityProvider = createBackendModule( { pluginId: 'catalog', moduleId: 'microsoftGraphOrgEntityProvider', - register( - env, - options?: CatalogModuleMicrosoftGraphOrgEntityProviderOptions, - ) { + register(env) { + let userTransformer: + | UserTransformer + | Record + | undefined; + let groupTransformer: + | GroupTransformer + | Record + | undefined; + let organizationTransformer: + | OrganizationTransformer + | Record + | undefined; + + env.registerExtensionPoint( + microsoftGraphOrgEntityProviderTransformExtensionPoint, + { + setUserTransformer(transformer) { + if (userTransformer) { + throw new Error('User transformer may only be set once'); + } + userTransformer = transformer; + }, + setGroupTransformer(transformer) { + if (groupTransformer) { + throw new Error('Group transformer may only be set once'); + } + groupTransformer = transformer; + }, + setOrganizationTransformer(transformer) { + if (organizationTransformer) { + throw new Error('Organization transformer may only be set once'); + } + organizationTransformer = transformer; + }, + }, + ); + env.registerInit({ deps: { catalog: catalogProcessingExtensionPoint, - config: coreServices.config, + config: coreServices.rootConfig, logger: coreServices.logger, scheduler: coreServices.scheduler, }, async init({ catalog, config, logger, scheduler }) { catalog.addEntityProvider( MicrosoftGraphOrgEntityProvider.fromConfig(config, { - groupTransformer: options?.groupTransformer, logger: loggerToWinstonLogger(logger), - organizationTransformer: options?.organizationTransformer, scheduler, - userTransformer: options?.userTransformer, + userTransformer: userTransformer, + groupTransformer: groupTransformer, + organizationTransformer: organizationTransformer, }), ); }, diff --git a/plugins/catalog-backend-module-msgraph/src/module/index.ts b/plugins/catalog-backend-module-msgraph/src/module/index.ts index f53f41141c..ef45c6a135 100644 --- a/plugins/catalog-backend-module-msgraph/src/module/index.ts +++ b/plugins/catalog-backend-module-msgraph/src/module/index.ts @@ -14,5 +14,8 @@ * limitations under the License. */ -export { catalogModuleMicrosoftGraphOrgEntityProvider } from './catalogModuleMicrosoftGraphOrgEntityProvider'; -export type { CatalogModuleMicrosoftGraphOrgEntityProviderOptions } from './catalogModuleMicrosoftGraphOrgEntityProvider'; +export { + catalogModuleMicrosoftGraphOrgEntityProvider, + microsoftGraphOrgEntityProviderTransformExtensionPoint, + type MicrosoftGraphOrgEntityProviderTransformsExtensionPoint, +} from './catalogModuleMicrosoftGraphOrgEntityProvider'; diff --git a/plugins/catalog-backend-module-openapi/CHANGELOG.md b/plugins/catalog-backend-module-openapi/CHANGELOG.md index 8b6a4c3162..7a7bf51087 100644 --- a/plugins/catalog-backend-module-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-openapi/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-catalog-backend-module-openapi +## 0.1.14 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/plugin-catalog-backend@1.12.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/integration@1.6.0 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + +## 0.1.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.12.0-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## 0.1.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-backend@1.12.0-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + ## 0.1.14-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index cbc42851d9..f9c5fe88a1 100644 --- a/plugins/catalog-backend-module-openapi/package.json +++ b/plugins/catalog-backend-module-openapi/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-openapi", "description": "A Backstage catalog backend module that helps with OpenAPI specifications", - "version": "0.1.14-next.0", + "version": "0.1.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md index d7606911e3..31fbe07360 100644 --- a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md +++ b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md @@ -1,5 +1,47 @@ # @backstage/plugin-catalog-backend-module-puppetdb +## 0.1.5 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/backend-tasks@0.5.5 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + +## 0.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + +## 0.1.5-next.1 + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- 4b82382ed8c2: Fixed invalid configuration schema. The configuration schema may be more strict as a result. +- Updated dependencies + - @backstage/backend-common@0.19.2-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + ## 0.1.5-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-puppetdb/config.d.ts b/plugins/catalog-backend-module-puppetdb/config.d.ts index edd7ab3889..8aab239047 100644 --- a/plugins/catalog-backend-module-puppetdb/config.d.ts +++ b/plugins/catalog-backend-module-puppetdb/config.d.ts @@ -46,9 +46,8 @@ export interface Config { */ schedule?: TaskScheduleDefinition; } - | Record< - string, - { + | { + [name: string]: { /** * (Required) The base URL of PuppetDB API instance. */ @@ -61,8 +60,8 @@ export interface Config { * (Optional) Task schedule definition for the refresh. */ schedule?: TaskScheduleDefinition; - } - >; + }; + }; }; }; } diff --git a/plugins/catalog-backend-module-puppetdb/package.json b/plugins/catalog-backend-module-puppetdb/package.json index 8adbd65941..9cd16fd3c3 100644 --- a/plugins/catalog-backend-module-puppetdb/package.json +++ b/plugins/catalog-backend-module-puppetdb/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-puppetdb", "description": "A Backstage catalog backend module that helps integrate towards PuppetDB", - "version": "0.1.5-next.0", + "version": "0.1.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-puppetdb/src/module/catalogModulePuppetDbEntityProvider.test.ts b/plugins/catalog-backend-module-puppetdb/src/module/catalogModulePuppetDbEntityProvider.test.ts index e2745e9268..3ea54d8c8f 100644 --- a/plugins/catalog-backend-module-puppetdb/src/module/catalogModulePuppetDbEntityProvider.test.ts +++ b/plugins/catalog-backend-module-puppetdb/src/module/catalogModulePuppetDbEntityProvider.test.ts @@ -14,14 +14,15 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; -import { coreServices } from '@backstage/backend-plugin-api'; +import { + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; import { PluginTaskScheduler, TaskScheduleDefinition, } from '@backstage/backend-tasks'; -import { startTestBackend } from '@backstage/backend-test-utils'; -import { ConfigReader } from '@backstage/config'; +import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { catalogModulePuppetDbEntityProvider } from './catalogModulePuppetDbEntityProvider'; import { PuppetDbEntityProvider } from '../providers/PuppetDbEntityProvider'; @@ -44,7 +45,7 @@ describe('catalogModulePuppetDbEntityProvider', () => { }, } as unknown as PluginTaskScheduler; - const config = new ConfigReader({ + const config = { catalog: { providers: { puppetdb: { @@ -56,16 +57,19 @@ describe('catalogModulePuppetDbEntityProvider', () => { }, }, }, - }); + }; await startTestBackend({ extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]], - services: [ - [coreServices.config, config], - [coreServices.logger, getVoidLogger()], - [coreServices.scheduler, scheduler], + features: [ + catalogModulePuppetDbEntityProvider(), + mockServices.rootConfig.factory({ data: config }), + createServiceFactory(() => ({ + deps: {}, + service: coreServices.scheduler, + factory: async () => scheduler, + })), ], - features: [catalogModulePuppetDbEntityProvider()], }); expect(usedSchedule?.frequency).toEqual({ minutes: 10 }); diff --git a/plugins/catalog-backend-module-puppetdb/src/module/catalogModulePuppetDbEntityProvider.ts b/plugins/catalog-backend-module-puppetdb/src/module/catalogModulePuppetDbEntityProvider.ts index 9a7d279cd3..5546b5283b 100644 --- a/plugins/catalog-backend-module-puppetdb/src/module/catalogModulePuppetDbEntityProvider.ts +++ b/plugins/catalog-backend-module-puppetdb/src/module/catalogModulePuppetDbEntityProvider.ts @@ -34,7 +34,7 @@ export const catalogModulePuppetDbEntityProvider = createBackendModule({ env.registerInit({ deps: { catalog: catalogProcessingExtensionPoint, - config: coreServices.config, + config: coreServices.rootConfig, logger: coreServices.logger, scheduler: coreServices.scheduler, }, diff --git a/plugins/catalog-backend-module-unprocessed/CHANGELOG.md b/plugins/catalog-backend-module-unprocessed/CHANGELOG.md index 999c7cf85f..96228acefd 100644 --- a/plugins/catalog-backend-module-unprocessed/CHANGELOG.md +++ b/plugins/catalog-backend-module-unprocessed/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-catalog-backend-module-unprocessed +## 0.2.0 + +### Minor Changes + +- 5156a94c2e2a: **BREAKING**: Fixing typo in exported module. You will have to rename the import to the correct spelling. `UnprocessedEntites` -> `UnprocessedEntities` + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/catalog-model@1.4.1 + +## 0.2.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## 0.2.0-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/catalog-model@1.4.1 + ## 0.2.0-next.0 ### Minor Changes diff --git a/plugins/catalog-backend-module-unprocessed/package.json b/plugins/catalog-backend-module-unprocessed/package.json index 9f3f2f0b11..8f303b9667 100644 --- a/plugins/catalog-backend-module-unprocessed/package.json +++ b/plugins/catalog-backend-module-unprocessed/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-unprocessed", "description": "Backstage Catalog module to view unprocessed entities", - "version": "0.2.0-next.0", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -13,6 +13,12 @@ "backstage": { "role": "backend-plugin-module" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/catalog-backend-module-unprocessed" + }, "scripts": { "build": "backstage-cli package build", "lint": "backstage-cli package lint", diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 0c0f3c7be8..e1fd4e43ab 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,86 @@ # @backstage/plugin-catalog-backend +## 1.12.0 + +### Minor Changes + +- b8cccd8ee858: Support configuring applicable kinds for `AnnotateScmSlugEntityProcessor` +- f32252cdf631: Added OpenTelemetry spans for catalog processing +- ebeb77586975: Now performs request validation based on OpenAPI schema through `@backstage/backend-openapi-utils`. Error responses for invalid input, like `"a"` instead of a number, may have changed. + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- b8d6b22acd57: Internal refactor for load test +- Updated dependencies + - @backstage/plugin-search-backend-module-catalog@0.1.4 + - @backstage/backend-common@0.19.2 + - @backstage/backend-plugin-api@0.6.0 + - @backstage/backend-openapi-utils@0.0.3 + - @backstage/plugin-catalog-node@1.4.1 + - @backstage/plugin-events-node@0.2.9 + - @backstage/plugin-auth-node@0.2.17 + - @backstage/integration@1.6.0 + - @backstage/backend-tasks@0.5.5 + - @backstage/plugin-scaffolder-common@1.4.0 + - @backstage/plugin-permission-node@0.7.11 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-search-common@1.2.5 + +## 1.12.0-next.2 + +### Minor Changes + +- b8cccd8ee858: Support configuring applicable kinds for `AnnotateScmSlugEntityProcessor` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-module-catalog@0.1.4-next.2 + - @backstage/backend-plugin-api@0.6.0-next.2 + - @backstage/backend-tasks@0.5.5-next.2 + - @backstage/backend-common@0.19.2-next.2 + - @backstage/plugin-catalog-node@1.4.1-next.2 + - @backstage/plugin-events-node@0.2.9-next.2 + - @backstage/plugin-permission-node@0.7.11-next.2 + - @backstage/plugin-auth-node@0.2.17-next.2 + +## 1.12.0-next.1 + +### Minor Changes + +- f32252cdf631: Added OpenTelemetry spans for catalog processing + +### Patch Changes + +- 629cbd194a87: Use `coreServices.rootConfig` instead of `coreService.config` +- Updated dependencies + - @backstage/plugin-search-backend-module-catalog@0.1.4-next.1 + - @backstage/backend-common@0.19.2-next.1 + - @backstage/backend-openapi-utils@0.0.3-next.1 + - @backstage/plugin-catalog-node@1.4.1-next.1 + - @backstage/plugin-events-node@0.2.9-next.1 + - @backstage/plugin-auth-node@0.2.17-next.1 + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/backend-tasks@0.5.5-next.1 + - @backstage/plugin-permission-node@0.7.11-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-scaffolder-common@1.3.2 + - @backstage/plugin-search-common@1.2.5 + ## 1.12.0-next.0 ### Minor Changes diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index 84d8de4753..345874d919 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -91,9 +91,17 @@ export class AnnotateLocationEntityProcessor implements CatalogProcessor_2 { // @public (undocumented) export class AnnotateScmSlugEntityProcessor implements CatalogProcessor_2 { - constructor(opts: { scmIntegrationRegistry: ScmIntegrationRegistry }); + constructor(opts: { + scmIntegrationRegistry: ScmIntegrationRegistry; + kinds?: string[]; + }); // (undocumented) - static fromConfig(config: Config): AnnotateScmSlugEntityProcessor; + static fromConfig( + config: Config, + options?: { + kinds?: string[]; + }, + ): AnnotateScmSlugEntityProcessor; // (undocumented) getProcessorName(): string; // (undocumented) diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 8b4edcbc20..0082898ffc 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.12.0-next.0", + "version": "1.12.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend/src/index.ts b/plugins/catalog-backend/src/index.ts index 345102adcd..55c1c672d3 100644 --- a/plugins/catalog-backend/src/index.ts +++ b/plugins/catalog-backend/src/index.ts @@ -36,13 +36,13 @@ import { /** * @public - * @deprecated import from `@backstage/search-backend-module-catalog` instead + * @deprecated import from `@backstage/plugin-search-backend-module-catalog` instead */ export const DefaultCatalogCollatorFactory = _DefaultCatalogCollatorFactory; /** * @public - * @deprecated import from `@backstage/search-backend-module-catalog` instead + * @deprecated import from `@backstage/plugin-search-backend-module-catalog` instead */ export const defaultCatalogCollatorEntityTransformer = _defaultCatalogCollatorEntityTransformer; @@ -54,14 +54,14 @@ import type { /** * @public - * @deprecated import from `@backstage/search-backend-module-catalog` instead + * @deprecated import from `@backstage/plugin-search-backend-module-catalog` instead */ export type DefaultCatalogCollatorFactoryOptions = _DefaultCatalogCollatorFactoryOptions; /** * @public - * @deprecated import from `@backstage/search-backend-module-catalog` instead + * @deprecated import from `@backstage/plugin-search-backend-module-catalog` instead */ export type CatalogCollatorEntityTransformer = _CatalogCollatorEntityTransformer; diff --git a/plugins/catalog-backend/src/modules/core/AnnotateScmSlugEntityProcessor.test.ts b/plugins/catalog-backend/src/modules/core/AnnotateScmSlugEntityProcessor.test.ts index bafac6e3ac..0cde9417db 100644 --- a/plugins/catalog-backend/src/modules/core/AnnotateScmSlugEntityProcessor.test.ts +++ b/plugins/catalog-backend/src/modules/core/AnnotateScmSlugEntityProcessor.test.ts @@ -109,6 +109,73 @@ describe('AnnotateScmSlugEntityProcessor', () => { }, }); }); + + it('should only process applicable kinds', async () => { + const component: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'my-component', + }, + }; + + const api: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'API', + metadata: { + name: 'my-component', + }, + }; + + const system: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'System', + metadata: { + name: 'my-component', + }, + }; + + const location: LocationSpec = { + type: 'url', + target: + 'https://github.com/backstage/backstage/blob/master/catalog-info.yaml', + }; + + const processor = AnnotateScmSlugEntityProcessor.fromConfig( + new ConfigReader({}), + { kinds: ['API', 'System'] }, + ); + + expect(await processor.preProcessEntity(component, location)).toEqual({ + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'my-component', + }, + }); + + expect(await processor.preProcessEntity(api, location)).toEqual({ + apiVersion: 'backstage.io/v1alpha1', + kind: 'API', + metadata: { + name: 'my-component', + annotations: { + 'github.com/project-slug': 'backstage/backstage', + }, + }, + }); + + expect(await processor.preProcessEntity(system, location)).toEqual({ + apiVersion: 'backstage.io/v1alpha1', + kind: 'System', + metadata: { + name: 'my-component', + annotations: { + 'github.com/project-slug': 'backstage/backstage', + }, + }, + }); + }); }); describe('gitlab', () => { it('adds annotation', async () => { diff --git a/plugins/catalog-backend/src/modules/core/AnnotateScmSlugEntityProcessor.ts b/plugins/catalog-backend/src/modules/core/AnnotateScmSlugEntityProcessor.ts index 2c18ba1d7d..241a27433e 100644 --- a/plugins/catalog-backend/src/modules/core/AnnotateScmSlugEntityProcessor.ts +++ b/plugins/catalog-backend/src/modules/core/AnnotateScmSlugEntityProcessor.ts @@ -31,16 +31,23 @@ const GITLAB_ACTIONS_ANNOTATION = 'gitlab.com/project-slug'; /** @public */ export class AnnotateScmSlugEntityProcessor implements CatalogProcessor { constructor( - private readonly opts: { scmIntegrationRegistry: ScmIntegrationRegistry }, + private readonly opts: { + scmIntegrationRegistry: ScmIntegrationRegistry; + kinds?: string[]; + }, ) {} getProcessorName(): string { return 'AnnotateScmSlugEntityProcessor'; } - static fromConfig(config: Config): AnnotateScmSlugEntityProcessor { + static fromConfig( + config: Config, + options?: { kinds?: string[] }, + ): AnnotateScmSlugEntityProcessor { return new AnnotateScmSlugEntityProcessor({ scmIntegrationRegistry: ScmIntegrations.fromConfig(config), + kinds: options?.kinds, }); } @@ -48,7 +55,13 @@ export class AnnotateScmSlugEntityProcessor implements CatalogProcessor { entity: Entity, location: LocationSpec, ): Promise { - if (entity.kind !== 'Component' || location.type !== 'url') { + const applicableKinds = (this.opts.kinds ?? ['Component']).map(k => + k.toLocaleLowerCase('en-US'), + ); + if ( + !applicableKinds.includes(entity.kind.toLocaleLowerCase('en-US')) || + location.type !== 'url' + ) { return entity; } diff --git a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts index 8e2f8b2f6f..bed1fe6f50 100644 --- a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts @@ -23,7 +23,7 @@ import { assertError, serializeError, stringifyError } from '@backstage/errors'; import { Hash } from 'crypto'; import stableStringify from 'fast-json-stable-stringify'; import { Logger } from 'winston'; -import { metrics } from '@opentelemetry/api'; +import { metrics, trace } from '@opentelemetry/api'; import { ProcessingDatabase, RefreshStateItem } from '../database/types'; import { createCounterMetric, createSummaryMetric } from '../util/metrics'; import { @@ -35,9 +35,16 @@ import { Stitcher } from '../stitching/Stitcher'; import { startTaskPipeline } from './TaskPipeline'; import { PluginTaskScheduler } from '@backstage/backend-tasks'; import { Config } from '@backstage/config'; +import { + addEntityAttributes, + TRACER_ID, + withActiveSpan, +} from '../util/opentelemetry'; const CACHE_TTL = 5; +const tracer = trace.getTracer(TRACER_ID); + export type ProgressTracker = ReturnType; export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { @@ -131,177 +138,181 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { } }, processTask: async item => { - const track = this.tracker.processStart(item, this.logger); + await withActiveSpan(tracer, 'ProcessingRun', async span => { + const track = this.tracker.processStart(item, this.logger); + addEntityAttributes(span, item.unprocessedEntity); - try { - const { - id, - state, - unprocessedEntity, - entityRef, - locationKey, - resultHash: previousResultHash, - } = item; - const result = await this.orchestrator.process({ - entity: unprocessedEntity, - state, - }); + try { + const { + id, + state, + unprocessedEntity, + entityRef, + locationKey, + resultHash: previousResultHash, + } = item; + const result = await this.orchestrator.process({ + entity: unprocessedEntity, + state, + }); - track.markProcessorsCompleted(result); + track.markProcessorsCompleted(result); - if (result.ok) { - const { ttl: _, ...stateWithoutTtl } = state ?? {}; - if ( - stableStringify(stateWithoutTtl) !== stableStringify(result.state) - ) { + if (result.ok) { + const { ttl: _, ...stateWithoutTtl } = state ?? {}; + if ( + stableStringify(stateWithoutTtl) !== + stableStringify(result.state) + ) { + await this.processingDatabase.transaction(async tx => { + await this.processingDatabase.updateEntityCache(tx, { + id, + state: { + ttl: CACHE_TTL, + ...result.state, + }, + }); + }); + } + } else { + const maybeTtl = state?.ttl; + const ttl = Number.isInteger(maybeTtl) ? (maybeTtl as number) : 0; await this.processingDatabase.transaction(async tx => { await this.processingDatabase.updateEntityCache(tx, { id, - state: { - ttl: CACHE_TTL, - ...result.state, - }, + state: ttl > 0 ? { ...state, ttl: ttl - 1 } : {}, }); }); } - } else { - const maybeTtl = state?.ttl; - const ttl = Number.isInteger(maybeTtl) ? (maybeTtl as number) : 0; - await this.processingDatabase.transaction(async tx => { - await this.processingDatabase.updateEntityCache(tx, { - id, - state: ttl > 0 ? { ...state, ttl: ttl - 1 } : {}, + + const location = + unprocessedEntity?.metadata?.annotations?.[ANNOTATION_LOCATION]; + for (const error of result.errors) { + this.logger.warn(error.message, { + entity: entityRef, + location, }); - }); - } + } + const errorsString = JSON.stringify( + result.errors.map(e => serializeError(e)), + ); - const location = - unprocessedEntity?.metadata?.annotations?.[ANNOTATION_LOCATION]; - for (const error of result.errors) { - this.logger.warn(error.message, { - entity: entityRef, - location, - }); - } - const errorsString = JSON.stringify( - result.errors.map(e => serializeError(e)), - ); + let hashBuilder = this.createHash().update(errorsString); - let hashBuilder = this.createHash().update(errorsString); - - if (result.ok) { - const { entityRefs: parents } = - await this.processingDatabase.transaction(tx => - this.processingDatabase.listParents(tx, { - entityRef, - }), - ); - - hashBuilder = hashBuilder - .update(stableStringify({ ...result.completedEntity })) - .update(stableStringify([...result.deferredEntities])) - .update(stableStringify([...result.relations])) - .update(stableStringify([...result.refreshKeys])) - .update(stableStringify([...parents])); - } - - const resultHash = hashBuilder.digest('hex'); - if (resultHash === previousResultHash) { - // If nothing changed in our produced outputs, we cannot have any - // significant effect on our surroundings; therefore, we just abort - // without any updates / stitching. - track.markSuccessfulWithNoChanges(); - return; - } - - // If the result was marked as not OK, it signals that some part of the - // processing pipeline threw an exception. This can happen both as part of - // non-catastrophic things such as due to validation errors, as well as if - // something fatal happens inside the processing for other reasons. In any - // case, this means we can't trust that anything in the output is okay. So - // just store the errors and trigger a stich so that they become visible to - // the outside. - if (!result.ok) { - // notify the error listener if the entity can not be processed. - Promise.resolve(undefined) - .then(() => - this.onProcessingError?.({ - unprocessedEntity, - errors: result.errors, - }), - ) - .catch(error => { - this.logger.debug( - `Processing error listener threw an exception, ${stringifyError( - error, - )}`, + if (result.ok) { + const { entityRefs: parents } = + await this.processingDatabase.transaction(tx => + this.processingDatabase.listParents(tx, { + entityRef, + }), ); - }); + hashBuilder = hashBuilder + .update(stableStringify({ ...result.completedEntity })) + .update(stableStringify([...result.deferredEntities])) + .update(stableStringify([...result.relations])) + .update(stableStringify([...result.refreshKeys])) + .update(stableStringify([...parents])); + } + + const resultHash = hashBuilder.digest('hex'); + if (resultHash === previousResultHash) { + // If nothing changed in our produced outputs, we cannot have any + // significant effect on our surroundings; therefore, we just abort + // without any updates / stitching. + track.markSuccessfulWithNoChanges(); + return; + } + + // If the result was marked as not OK, it signals that some part of the + // processing pipeline threw an exception. This can happen both as part of + // non-catastrophic things such as due to validation errors, as well as if + // something fatal happens inside the processing for other reasons. In any + // case, this means we can't trust that anything in the output is okay. So + // just store the errors and trigger a stich so that they become visible to + // the outside. + if (!result.ok) { + // notify the error listener if the entity can not be processed. + Promise.resolve(undefined) + .then(() => + this.onProcessingError?.({ + unprocessedEntity, + errors: result.errors, + }), + ) + .catch(error => { + this.logger.debug( + `Processing error listener threw an exception, ${stringifyError( + error, + )}`, + ); + }); + + await this.processingDatabase.transaction(async tx => { + await this.processingDatabase.updateProcessedEntityErrors(tx, { + id, + errors: errorsString, + resultHash, + }); + }); + await this.stitcher.stitch( + new Set([stringifyEntityRef(unprocessedEntity)]), + ); + track.markSuccessfulWithErrors(); + return; + } + + result.completedEntity.metadata.uid = id; + let oldRelationSources: Map; await this.processingDatabase.transaction(async tx => { - await this.processingDatabase.updateProcessedEntityErrors(tx, { - id, - errors: errorsString, - resultHash, - }); + const { previous } = + await this.processingDatabase.updateProcessedEntity(tx, { + id, + processedEntity: result.completedEntity, + resultHash, + errors: errorsString, + relations: result.relations, + deferredEntities: result.deferredEntities, + locationKey, + refreshKeys: result.refreshKeys, + }); + oldRelationSources = new Map( + previous.relations.map(r => [ + `${r.source_entity_ref}:${r.type}`, + r.source_entity_ref, + ]), + ); }); - await this.stitcher.stitch( - new Set([stringifyEntityRef(unprocessedEntity)]), + + const newRelationSources = new Map( + result.relations.map(relation => { + const sourceEntityRef = stringifyEntityRef(relation.source); + return [`${sourceEntityRef}:${relation.type}`, sourceEntityRef]; + }), ); - track.markSuccessfulWithErrors(); - return; + + const setOfThingsToStitch = new Set([ + stringifyEntityRef(result.completedEntity), + ]); + newRelationSources.forEach((sourceEntityRef, uniqueKey) => { + if (!oldRelationSources.has(uniqueKey)) { + setOfThingsToStitch.add(sourceEntityRef); + } + }); + oldRelationSources!.forEach((sourceEntityRef, uniqueKey) => { + if (!newRelationSources.has(uniqueKey)) { + setOfThingsToStitch.add(sourceEntityRef); + } + }); + + await this.stitcher.stitch(setOfThingsToStitch); + + track.markSuccessfulWithChanges(setOfThingsToStitch.size); + } catch (error) { + assertError(error); + track.markFailed(error); } - - result.completedEntity.metadata.uid = id; - let oldRelationSources: Map; - await this.processingDatabase.transaction(async tx => { - const { previous } = - await this.processingDatabase.updateProcessedEntity(tx, { - id, - processedEntity: result.completedEntity, - resultHash, - errors: errorsString, - relations: result.relations, - deferredEntities: result.deferredEntities, - locationKey, - refreshKeys: result.refreshKeys, - }); - oldRelationSources = new Map( - previous.relations.map(r => [ - `${r.source_entity_ref}:${r.type}`, - r.source_entity_ref, - ]), - ); - }); - - const newRelationSources = new Map( - result.relations.map(relation => { - const sourceEntityRef = stringifyEntityRef(relation.source); - return [`${sourceEntityRef}:${relation.type}`, sourceEntityRef]; - }), - ); - - const setOfThingsToStitch = new Set([ - stringifyEntityRef(result.completedEntity), - ]); - newRelationSources.forEach((sourceEntityRef, uniqueKey) => { - if (!oldRelationSources.has(uniqueKey)) { - setOfThingsToStitch.add(sourceEntityRef); - } - }); - oldRelationSources!.forEach((sourceEntityRef, uniqueKey) => { - if (!newRelationSources.has(uniqueKey)) { - setOfThingsToStitch.add(sourceEntityRef); - } - }); - - await this.stitcher.stitch(setOfThingsToStitch); - - track.markSuccessfulWithChanges(setOfThingsToStitch.size); - } catch (error) { - assertError(error); - track.markFailed(error); - } + }); }, }); } diff --git a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.test.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.test.ts index ceb6992d7a..fc6855f6df 100644 --- a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.test.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.test.ts @@ -194,10 +194,12 @@ describe('DefaultCatalogProcessingOrchestrator', () => { it('runs all processor validations when asked to', async () => { const validate = jest.fn(async () => true); - const processor1: Partial = { + const processor1: CatalogProcessor = { + getProcessorName: () => 'processor1', validateEntityKind: validate, }; - const processor2: Partial = { + const processor2: CatalogProcessor = { + getProcessorName: () => 'processor2', validateEntityKind: validate, }; diff --git a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts index d177a7d4a8..c5eaacbc68 100644 --- a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { Span, trace } from '@opentelemetry/api'; import { Entity, EntityPolicy, @@ -55,6 +56,13 @@ import { } from './util'; import { CatalogRulesEnforcer } from '../ingestion/CatalogRules'; import { ProcessorCacheManager } from './ProcessorCacheManager'; +import { + addEntityAttributes, + TRACER_ID, + withActiveSpan, +} from '../util/opentelemetry'; + +const tracer = trace.getTracer(TRACER_ID); type Context = { entityRef: string; @@ -64,6 +72,18 @@ type Context = { cache: ProcessorCacheManager; }; +function addProcessorAttributes( + span: Span, + stage: string, + processor: CatalogProcessor, +) { + span.setAttribute('backstage.catalog.processor.stage', stage); + span.setAttribute( + 'backstage.catalog.processor.name', + processor.getProcessorName(), + ); +} + /** @public */ export class DefaultCatalogProcessingOrchestrator implements CatalogProcessingOrchestrator @@ -179,54 +199,71 @@ export class DefaultCatalogProcessingOrchestrator entity: Entity, context: Context, ): Promise { - let res = entity; + return await withActiveSpan(tracer, 'ProcessingStage', async stageSpan => { + addEntityAttributes(stageSpan, entity); + stageSpan.setAttribute('backstage.catalog.processor.stage', 'preProcess'); + let res = entity; - for (const processor of this.options.processors) { - if (processor.preProcessEntity) { - try { - res = await processor.preProcessEntity( - res, - context.location, - context.collector.forProcessor(processor), - context.originLocation, - context.cache.forProcessor(processor), - ); - } catch (e) { - throw new InputError( - `Processor ${processor.constructor.name} threw an error while preprocessing`, - e, - ); + for (const processor of this.options.processors) { + if (processor.preProcessEntity) { + let innerRes = res; + res = await withActiveSpan(tracer, 'ProcessingStep', async span => { + addEntityAttributes(span, entity); + addProcessorAttributes(span, 'preProcessEntity', processor); + try { + innerRes = await processor.preProcessEntity!( + innerRes, + context.location, + context.collector.forProcessor(processor), + context.originLocation, + context.cache.forProcessor(processor), + ); + } catch (e) { + throw new InputError( + `Processor ${processor.constructor.name} threw an error while preprocessing`, + e, + ); + } + return innerRes; + }); } } - } - return res; + return res; + }); } /** * Enforce entity policies making sure that entities conform to a general schema */ private async runPolicyStep(entity: Entity): Promise { - let policyEnforcedEntity: Entity | undefined; - - try { - policyEnforcedEntity = await this.options.policy.enforce(entity); - } catch (e) { - throw new InputError( - `Policy check failed for ${stringifyEntityRef(entity)}`, - e, + return await withActiveSpan(tracer, 'ProcessingStage', async stageSpan => { + addEntityAttributes(stageSpan, entity); + stageSpan.setAttribute( + 'backstage.catalog.processor.stage', + 'enforcePolicy', ); - } + let policyEnforcedEntity: Entity | undefined; - if (!policyEnforcedEntity) { - throw new Error( - `Policy unexpectedly returned no data for ${stringifyEntityRef( - entity, - )}`, - ); - } + try { + policyEnforcedEntity = await this.options.policy.enforce(entity); + } catch (e) { + throw new InputError( + `Policy check failed for ${stringifyEntityRef(entity)}`, + e, + ); + } - return policyEnforcedEntity; + if (!policyEnforcedEntity) { + throw new Error( + `Policy unexpectedly returned no data for ${stringifyEntityRef( + entity, + )}`, + ); + } + + return policyEnforcedEntity; + }); } /** @@ -236,50 +273,62 @@ export class DefaultCatalogProcessingOrchestrator entity: Entity, context: Context, ): Promise { - // Double check that none of the previous steps tried to change something - // related to the entity ref, which would break downstream - if (stringifyEntityRef(entity) !== context.entityRef) { - throw new ConflictError( - 'Fatal: The entity kind, namespace, or name changed during processing', - ); - } + return await withActiveSpan(tracer, 'ProcessingStage', async stageSpan => { + addEntityAttributes(stageSpan, entity); + stageSpan.setAttribute('backstage.catalog.processor.stage', 'validate'); + // Double check that none of the previous steps tried to change something + // related to the entity ref, which would break downstream + if (stringifyEntityRef(entity) !== context.entityRef) { + throw new ConflictError( + 'Fatal: The entity kind, namespace, or name changed during processing', + ); + } - // Validate that the end result is a valid Entity at all - try { - validateEntity(entity); - } catch (e) { - throw new ConflictError( - `Entity envelope for ${context.entityRef} failed validation after preprocessing`, - e, - ); - } + // Validate that the end result is a valid Entity at all + try { + validateEntity(entity); + } catch (e) { + throw new ConflictError( + `Entity envelope for ${context.entityRef} failed validation after preprocessing`, + e, + ); + } - let valid = false; + let valid = false; - for (const processor of this.options.processors) { - if (processor.validateEntityKind) { - try { - const thisValid = await processor.validateEntityKind(entity); - if (thisValid) { - valid = true; - if (this.options.legacySingleProcessorValidation) { - break; + for (const processor of this.options.processors) { + if (processor.validateEntityKind) { + try { + const thisValid = await withActiveSpan( + tracer, + 'ProcessingStep', + async span => { + addEntityAttributes(span, entity); + addProcessorAttributes(span, 'validateEntityKind', processor); + return await processor.validateEntityKind!(entity); + }, + ); + if (thisValid) { + valid = true; + if (this.options.legacySingleProcessorValidation) { + break; + } } + } catch (e) { + throw new InputError( + `Processor ${processor.constructor.name} threw an error while validating the entity ${context.entityRef}`, + e, + ); } - } catch (e) { - throw new InputError( - `Processor ${processor.constructor.name} threw an error while validating the entity ${context.entityRef}`, - e, - ); } } - } - if (!valid) { - throw new InputError( - `No processor recognized the entity ${context.entityRef} as valid, possibly caused by a foreign kind or apiVersion`, - ); - } + if (!valid) { + throw new InputError( + `No processor recognized the entity ${context.entityRef} as valid, possibly caused by a foreign kind or apiVersion`, + ); + } + }); } /** @@ -289,65 +338,81 @@ export class DefaultCatalogProcessingOrchestrator entity: LocationEntity, context: Context, ): Promise { - const { type = context.location.type, presence = 'required' } = entity.spec; - const targets = new Array(); - if (entity.spec.target) { - targets.push(entity.spec.target); - } - if (entity.spec.targets) { - targets.push(...entity.spec.targets); - } - - for (const maybeRelativeTarget of targets) { - if (type === 'file' && maybeRelativeTarget.endsWith(path.sep)) { - context.collector.generic()( - processingResult.inputError( - context.location, - `LocationEntityProcessor cannot handle ${type} type location with target ${context.location.target} that ends with a path separator`, - ), - ); - continue; - } - const target = toAbsoluteUrl( - this.options.integrations, - context.location, - type, - maybeRelativeTarget, + return await withActiveSpan(tracer, 'ProcessingStage', async stageSpan => { + addEntityAttributes(stageSpan, entity); + stageSpan.setAttribute( + 'backstage.catalog.processor.stage', + 'readLocation', ); + const { type = context.location.type, presence = 'required' } = + entity.spec; + const targets = new Array(); + if (entity.spec.target) { + targets.push(entity.spec.target); + } + if (entity.spec.targets) { + targets.push(...entity.spec.targets); + } - let didRead = false; - for (const processor of this.options.processors) { - if (processor.readLocation) { - try { - const read = await processor.readLocation( - { - type, - target, - presence, - }, - presence === 'optional', - context.collector.forProcessor(processor), - this.options.parser, - context.cache.forProcessor(processor, target), - ); - if (read) { - didRead = true; - break; + for (const maybeRelativeTarget of targets) { + if (type === 'file' && maybeRelativeTarget.endsWith(path.sep)) { + context.collector.generic()( + processingResult.inputError( + context.location, + `LocationEntityProcessor cannot handle ${type} type location with target ${context.location.target} that ends with a path separator`, + ), + ); + continue; + } + const target = toAbsoluteUrl( + this.options.integrations, + context.location, + type, + maybeRelativeTarget, + ); + + let didRead = false; + for (const processor of this.options.processors) { + if (processor.readLocation) { + try { + const read = await withActiveSpan( + tracer, + 'ProcessingStep', + async span => { + addEntityAttributes(span, entity); + addProcessorAttributes(span, 'readLocation', processor); + return await processor.readLocation!( + { + type, + target, + presence, + }, + presence === 'optional', + context.collector.forProcessor(processor), + this.options.parser, + context.cache.forProcessor(processor, target), + ); + }, + ); + if (read) { + didRead = true; + break; + } + } catch (e) { + throw new InputError( + `Processor ${processor.constructor.name} threw an error while reading ${type}:${target}`, + e, + ); } - } catch (e) { - throw new InputError( - `Processor ${processor.constructor.name} threw an error while reading ${type}:${target}`, - e, - ); } } + if (!didRead) { + throw new InputError( + `No processor was able to handle reading of ${type}:${target}`, + ); + } } - if (!didRead) { - throw new InputError( - `No processor was able to handle reading of ${type}:${target}`, - ); - } - } + }); } /** @@ -357,26 +422,39 @@ export class DefaultCatalogProcessingOrchestrator entity: Entity, context: Context, ): Promise { - let res = entity; + return await withActiveSpan(tracer, 'ProcessingStage', async stageSpan => { + addEntityAttributes(stageSpan, entity); + stageSpan.setAttribute( + 'backstage.catalog.processor.stage', + 'postProcessEntity', + ); + let res = entity; - for (const processor of this.options.processors) { - if (processor.postProcessEntity) { - try { - res = await processor.postProcessEntity( - res, - context.location, - context.collector.forProcessor(processor), - context.cache.forProcessor(processor), - ); - } catch (e) { - throw new InputError( - `Processor ${processor.constructor.name} threw an error while postprocessing`, - e, - ); + for (const processor of this.options.processors) { + if (processor.postProcessEntity) { + let innerRes = res; + res = await withActiveSpan(tracer, 'ProcessingStep', async span => { + addEntityAttributes(span, entity); + addProcessorAttributes(span, 'postProcessEntity', processor); + try { + innerRes = await processor.postProcessEntity!( + innerRes, + context.location, + context.collector.forProcessor(processor), + context.cache.forProcessor(processor), + ); + } catch (e) { + throw new InputError( + `Processor ${processor.constructor.name} threw an error while postprocessing`, + e, + ); + } + return innerRes; + }); } } - } - return res; + return res; + }); } } diff --git a/plugins/catalog-backend/src/service/CatalogPlugin.ts b/plugins/catalog-backend/src/service/CatalogPlugin.ts index d77b034517..b8d5bdbeda 100644 --- a/plugins/catalog-backend/src/service/CatalogPlugin.ts +++ b/plugins/catalog-backend/src/service/CatalogPlugin.ts @@ -84,7 +84,7 @@ export const catalogPlugin = createBackendPlugin({ env.registerInit({ deps: { logger: coreServices.logger, - config: coreServices.config, + config: coreServices.rootConfig, reader: coreServices.urlReader, permissions: coreServices.permissions, database: coreServices.database, diff --git a/plugins/catalog-backend/src/tests/performance/lib/catalogModuleSyntheticLoadEntities.ts b/plugins/catalog-backend/src/tests/performance/lib/catalogModuleSyntheticLoadEntities.ts index 4d38b28bcf..7925b0b552 100644 --- a/plugins/catalog-backend/src/tests/performance/lib/catalogModuleSyntheticLoadEntities.ts +++ b/plugins/catalog-backend/src/tests/performance/lib/catalogModuleSyntheticLoadEntities.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import { createBackendModule } from '@backstage/backend-plugin-api'; import { Entity } from '@backstage/catalog-model'; import { LocationSpec } from '@backstage/plugin-catalog-common'; import { @@ -26,7 +25,6 @@ import { EntityProviderConnection, processingResult, } from '@backstage/plugin-catalog-node'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; /** * Options for a fixed initial load of entities. @@ -143,12 +141,15 @@ export const common = { /** * The entity provider that drives the initial base entity injection + * @internal */ -class SyntheticLoadEntitiesProvider implements EntityProvider { +export class SyntheticLoadEntitiesProvider implements EntityProvider { constructor( private readonly load: SyntheticLoadOptions, private readonly events: SyntheticLoadEvents, - ) {} + ) { + validateSyntheticLoadOptions(load); + } getProviderName(): string { return 'SyntheticLoadEntitiesProvider'; @@ -180,9 +181,12 @@ class SyntheticLoadEntitiesProvider implements EntityProvider { /** * Supporting processor for emitting children and relations + * @internal */ -class SyntheticLoadEntitiesProcessor implements CatalogProcessor { - constructor(private readonly load: SyntheticLoadOptions) {} +export class SyntheticLoadEntitiesProcessor implements CatalogProcessor { + constructor(private readonly load: SyntheticLoadOptions) { + validateSyntheticLoadOptions(load); + } getProcessorName(): string { return 'SyntheticLoadEntitiesProcessor'; @@ -231,27 +235,3 @@ class SyntheticLoadEntitiesProcessor implements CatalogProcessor { return entity; } } - -export const catalogModuleSyntheticLoadEntities = createBackendModule( - (options: { load: SyntheticLoadOptions; events?: SyntheticLoadEvents }) => ({ - moduleId: 'syntheticLoadEntities', - pluginId: 'catalog', - register(reg) { - reg.registerInit({ - deps: { - catalog: catalogProcessingExtensionPoint, - }, - async init({ catalog }) { - const { load, events = {} } = options; - - validateSyntheticLoadOptions(load); - const provider = new SyntheticLoadEntitiesProvider(load, events); - const processor = new SyntheticLoadEntitiesProcessor(load); - - catalog.addEntityProvider(provider); - catalog.addProcessor(processor); - }, - }); - }, - }), -); diff --git a/plugins/catalog-backend/src/tests/performance/stitchingPerformance.test.ts b/plugins/catalog-backend/src/tests/performance/stitchingPerformance.test.ts index 2f32fcd907..fb2bd06b96 100644 --- a/plugins/catalog-backend/src/tests/performance/stitchingPerformance.test.ts +++ b/plugins/catalog-backend/src/tests/performance/stitchingPerformance.test.ts @@ -16,16 +16,19 @@ import { coreServices, + createBackendModule, createServiceFactory, } from '@backstage/backend-plugin-api'; import { TestDatabases, startTestBackend } from '@backstage/backend-test-utils'; import { catalogPlugin } from '@backstage/plugin-catalog-backend/alpha'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { Knex } from 'knex'; import { applyDatabaseMigrations } from '../../database/migrations'; import { SyntheticLoadEvents, SyntheticLoadOptions, - catalogModuleSyntheticLoadEntities, + SyntheticLoadEntitiesProvider, + SyntheticLoadEntitiesProcessor, } from './lib/catalogModuleSyntheticLoadEntities'; import { describePerformanceTest, performanceTraceEnabled } from './lib/env'; @@ -177,13 +180,28 @@ describePerformanceTest('stitchingPerformance', () => { const tracker = new Tracker(knex, load); const backend = await startTestBackend({ - services: [staticDatabase(knex)], features: [ catalogPlugin(), - catalogModuleSyntheticLoadEntities({ - load, - events: tracker.events(), + createBackendModule({ + moduleId: 'syntheticLoadEntities', + pluginId: 'catalog', + register(reg) { + reg.registerInit({ + deps: { + catalog: catalogProcessingExtensionPoint, + }, + async init({ catalog }) { + catalog.addEntityProvider( + new SyntheticLoadEntitiesProvider(load, tracker.events()), + ); + catalog.addProcessor( + new SyntheticLoadEntitiesProcessor(load), + ); + }, + }); + }, }), + staticDatabase(knex), ], }); diff --git a/plugins/catalog-backend/src/util/opentelemetry.ts b/plugins/catalog-backend/src/util/opentelemetry.ts new file mode 100644 index 0000000000..3fb83d7909 --- /dev/null +++ b/plugins/catalog-backend/src/util/opentelemetry.ts @@ -0,0 +1,101 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Span, SpanOptions, SpanStatusCode, Tracer } from '@opentelemetry/api'; +import { Entity } from '@backstage/catalog-model'; + +export const TRACER_ID = 'backstage-plugin-catalog-backend'; + +function setAttributeIfDefined(span: Span, attribute: string, value?: string) { + if (value !== null && value !== undefined) { + span.setAttribute(attribute, value); + } +} + +export function addEntityAttributes(span: Span, entity: Entity) { + setAttributeIfDefined(span, 'backstage.entity.apiVersion', entity.apiVersion); + setAttributeIfDefined(span, 'backstage.entity.kind', entity.kind); + setAttributeIfDefined( + span, + 'backstage.entity.metadata.namespace', + entity.metadata?.namespace, + ); + setAttributeIfDefined( + span, + 'backstage.entity.metadata.name', + entity.metadata?.name, + ); +} + +// Adapted from https://github.com/open-telemetry/opentelemetry-js/blob/359fbcc40a859057a02b14e84599eac399b8dba7/api/src/trace/SugaredTracer.ts +// While waiting for something like https://github.com/open-telemetry/opentelemetry-js/pull/3317 to land upstream + +const onException = (e: Error, span: Span) => { + span.recordException(e); + span.setStatus({ + code: SpanStatusCode.ERROR, + }); +}; + +function isPromiseLike(obj: PromiseLike | S): obj is PromiseLike { + return ( + !!obj && + (typeof obj === 'object' || typeof obj === 'function') && + 'then' in obj && + typeof obj.then === 'function' + ); +} + +function handleFn ReturnType>( + span: Span, + fn: F, +): ReturnType { + try { + const ret = fn(span); + + // if fn is an async function attach a recordException and spanEnd callback to the promise + if (isPromiseLike(ret)) { + ret.then( + () => { + span.end(); + }, + e => { + onException(e, span); + span.end(); + }, + ); + } else { + span.end(); + } + + return ret; + } catch (e) { + onException(e, span); + span.end(); + throw e; + } +} + +export function withActiveSpan ReturnType>( + tracer: Tracer, + name: string, + fn: F, + spanOptions: SpanOptions = {}, +): ReturnType { + return tracer.startActiveSpan(name, spanOptions, (span: Span) => { + return handleFn(span, fn); + }); +} diff --git a/plugins/catalog-customized/CHANGELOG.md b/plugins/catalog-customized/CHANGELOG.md index 6b573ac4d3..2c98b37be3 100644 --- a/plugins/catalog-customized/CHANGELOG.md +++ b/plugins/catalog-customized/CHANGELOG.md @@ -1,5 +1,29 @@ # @internal/plugin-catalog-customized +## 0.0.13 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.12.1 + - @backstage/plugin-catalog-react@1.8.1 + +## 0.0.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/plugin-catalog@1.12.1-next.2 + +## 0.0.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.12.1-next.1 + - @backstage/plugin-catalog-react@1.8.1-next.0 + ## 0.0.13-next.0 ### Patch Changes diff --git a/plugins/catalog-customized/package.json b/plugins/catalog-customized/package.json index b745c43aca..bb298bf0ae 100644 --- a/plugins/catalog-customized/package.json +++ b/plugins/catalog-customized/package.json @@ -1,7 +1,7 @@ { "name": "@internal/plugin-catalog-customized", "description": "The internal Backstage Customizable plugin for browsing the Backstage catalog", - "version": "0.0.13-next.0", + "version": "0.0.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index 4e04cac514..f36eadb464 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,43 @@ # @backstage/plugin-catalog-graph +## 0.2.33 + +### Patch Changes + +- 64ee2c0c7ca5: Propagate entity spec to EntityNode so that spec info such as type can be used for graph node customization +- 62dc7a2b1ad1: Added maximum depth parameter to the catalogGraphParams in CatalogGraphCard. +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + +## 0.2.33-next.2 + +### Patch Changes + +- 62dc7a2b1ad1: Added maximum depth parameter to the catalogGraphParams in CatalogGraphCard. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + +## 0.2.33-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-react@1.8.1-next.0 + ## 0.2.33-next.0 ### Patch Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 73cdb47d07..b1a1abe6ba 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.33-next.0", + "version": "0.2.33", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -12,6 +12,12 @@ "backstage": { "role": "frontend-plugin" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/catalog-graph" + }, "scripts": { "build": "backstage-cli package build", "start": "backstage-cli package start", diff --git a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx index adee03e298..cdd55e300f 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx @@ -133,7 +133,7 @@ describe('', () => { expect(button).toBeInTheDocument(); expect(button.closest('a')).toHaveAttribute( 'href', - '/catalog-graph?rootEntityRefs%5B%5D=b%3Ad%2Fc&unidirectional=true&mergeRelations=true&direction=LR', + '/catalog-graph?rootEntityRefs%5B%5D=b%3Ad%2Fc&maxDepth=1&unidirectional=true&mergeRelations=true&direction=LR', ); }); @@ -157,7 +157,7 @@ describe('', () => { expect(button).toBeInTheDocument(); expect(button.closest('a')).toHaveAttribute( 'href', - '/catalog-graph?rootEntityRefs%5B%5D=b%3Ad%2Fc&unidirectional=true&mergeRelations=false&direction=LR', + '/catalog-graph?rootEntityRefs%5B%5D=b%3Ad%2Fc&maxDepth=2&unidirectional=true&mergeRelations=false&direction=LR', ); }); diff --git a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx index ae4ad850a4..7976fa66bb 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx @@ -108,6 +108,7 @@ export const CatalogGraphCard = ( const catalogGraphParams = qs.stringify( { rootEntityRefs: [stringifyEntityRef(entity)], + maxDepth: maxDepth, unidirectional, mergeRelations, selectedKinds: kinds, diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 47b286216e..8a44026997 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-catalog-import +## 0.9.11 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.16 + - @backstage/integration@1.6.0 + - @backstage/core-components@0.13.4 + - @backstage/plugin-catalog-react@1.8.1 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/errors@1.2.1 + - @backstage/plugin-catalog-common@1.0.15 + +## 0.9.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.1-next.1 + - @backstage/integration-react@1.1.16-next.1 + +## 0.9.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.16-next.1 + - @backstage/integration@1.5.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/config@1.0.8 + - @backstage/core-components@0.13.4-next.0 + - @backstage/core-plugin-api@1.5.3 + - @backstage/errors@1.2.1 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-catalog-react@1.8.1-next.0 + ## 0.9.11-next.0 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 19d475d94e..fe9ef62251 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-import", "description": "A Backstage plugin the helps you import entities into your catalog", - "version": "0.9.11-next.0", + "version": "0.9.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-node/CHANGELOG.md b/plugins/catalog-node/CHANGELOG.md index 633d39d4d5..4e7b43ae7c 100644 --- a/plugins/catalog-node/CHANGELOG.md +++ b/plugins/catalog-node/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-catalog-node +## 1.4.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + +## 1.4.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.2 + +## 1.4.1-next.1 + +### Patch Changes + +- 12a8c94eda8d: Add package repository and homepage metadata +- Updated dependencies + - @backstage/backend-plugin-api@0.6.0-next.1 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/types@1.1.0 + - @backstage/plugin-catalog-common@1.0.15 + ## 1.4.1-next.0 ### Patch Changes diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index 426f8e3297..7c6e21d62c 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-node", "description": "The plugin-catalog-node module for @backstage/plugin-catalog-backend", - "version": "1.4.1-next.0", + "version": "1.4.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -26,6 +26,12 @@ "backstage": { "role": "node-library" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/catalog-node" + }, "scripts": { "start": "backstage-cli package start", "build": "backstage-cli package build", diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index 6ae43f297c..953438ae7d 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-catalog-react +## 1.8.1 + +### Patch Changes + +- aa3feedce10a: Allow specifying screen size when catalog filters are hidden in drawer +- Updated dependencies + - @backstage/integration@1.6.0 + - @backstage/core-components@0.13.4 + - @backstage/core-plugin-api@1.5.3 + - @backstage/catalog-client@1.4.3 + - @backstage/catalog-model@1.4.1 + - @backstage/errors@1.2.1 + - @backstage/theme@0.4.1 + - @backstage/types@1.1.0 + - @backstage/version-bridge@1.0.4 + - @backstage/plugin-catalog-common@1.0.15 + - @backstage/plugin-permission-common@0.7.7 + - @backstage/plugin-permission-react@0.4.14 + +## 1.8.1-next.1 + +### Patch Changes + +- aa3feedce10a: Allow specifying screen size when catalog filters are hidden in drawer + ## 1.8.1-next.0 ### Patch Changes diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md index 9bf87778dd..b5ab8b6c7f 100644 --- a/plugins/catalog-react/api-report.md +++ b/plugins/catalog-react/api-report.md @@ -63,7 +63,13 @@ export const catalogApiRef: ApiRef; // @public (undocumented) export const CatalogFilterLayout: { (props: { children: React_2.ReactNode }): JSX.Element; - Filters: (props: { children: React_2.ReactNode }) => JSX.Element; + Filters: (props: { + children: React_2.ReactNode; + options?: { + drawerBreakpoint?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | number; + drawerAnchor?: 'left' | 'right' | 'top' | 'bottom'; + }; + }) => JSX.Element; Content: (props: { children: React_2.ReactNode }) => JSX.Element; }; diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 67a3409830..9853935353 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.8.1-next.0", + "version": "1.8.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-react/src/components/CatalogFilterLayout/CatalogFilterLayout.tsx b/plugins/catalog-react/src/components/CatalogFilterLayout/CatalogFilterLayout.tsx index 751eb35f1d..1a1404edf2 100644 --- a/plugins/catalog-react/src/components/CatalogFilterLayout/CatalogFilterLayout.tsx +++ b/plugins/catalog-react/src/components/CatalogFilterLayout/CatalogFilterLayout.tsx @@ -28,14 +28,20 @@ import FilterListIcon from '@material-ui/icons/FilterList'; import { BackstageTheme } from '@backstage/theme'; /** @public */ -export const Filters = (props: { children: React.ReactNode }) => { - const isMidSizeScreen = useMediaQuery(theme => - theme.breakpoints.down('md'), +export const Filters = (props: { + children: React.ReactNode; + options?: { + drawerBreakpoint?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | number; + drawerAnchor?: 'left' | 'right' | 'top' | 'bottom'; + }; +}) => { + const isScreenSmallerThanBreakpoint = useMediaQuery(theme => + theme.breakpoints.down(props.options?.drawerBreakpoint ?? 'md'), ); const theme = useTheme(); const [filterDrawerOpen, setFilterDrawerOpen] = useState(false); - return isMidSizeScreen ? ( + return isScreenSmallerThanBreakpoint ? ( <>