From 094eaa367bae8a091089c16a16d12bf5f2bfb91d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 28 Aug 2024 11:21:14 +0200 Subject: [PATCH] remove backend-common MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/light-rats-travel.md | 54 + .../workflows/verify_e2e-kubernetes-noop.yml | 30 - .github/workflows/verify_e2e-kubernetes.yml | 47 - package.json | 2 +- packages/backend-app-api/package.json | 2 +- packages/backend-common/.eslintrc.js | 1 - packages/backend-common/CHANGELOG.md | 3894 ----------------- packages/backend-common/README.md | 42 - packages/backend-common/api-report-alpha.md | 32 - .../backend-common/api-report-testUtils.md | 21 - packages/backend-common/api-report.md | 561 --- packages/backend-common/catalog-info.yaml | 10 - packages/backend-common/config.d.ts | 265 -- packages/backend-common/knip-report.md | 24 - packages/backend-common/package.json | 157 - packages/backend-common/src/alpha.ts | 17 - .../auth/createLegacyAuthAdapters.test.ts | 145 - .../compat/auth/createLegacyAuthAdapters.ts | 356 -- .../backend-common/src/compat/auth/index.ts | 17 - .../compat/cache/cacheToPluginCacheManager.ts | 35 - .../backend-common/src/compat/cache/index.ts | 17 - packages/backend-common/src/compat/index.ts | 20 - .../backend-common/src/compat/legacy/index.ts | 18 - .../src/compat/legacy/legacy.test.ts | 170 - .../src/compat/legacy/legacy.ts | 254 -- .../src/compat/logging/index.ts | 17 - .../compat/logging/loggerToWinstonLogger.ts | 67 - .../config/ObservableConfigProxy.test.ts | 128 - .../config/ObservableConfigProxy.ts | 128 - .../src/deprecated/config/config.test.ts | 74 - .../src/deprecated/config/config.ts | 133 - .../src/deprecated/config/index.ts | 17 - .../src/deprecated/config/urls.test.ts | 34 - .../src/deprecated/config/urls.ts | 25 - .../deprecated/context/AbortContext.test.ts | 344 -- .../src/deprecated/context/AbortContext.ts | 132 - .../src/deprecated/context/Contexts.test.ts | 89 - .../src/deprecated/context/Contexts.ts | 114 - .../deprecated/context/RootContext.test.ts | 27 - .../src/deprecated/context/RootContext.ts | 50 - .../deprecated/context/ValueContext.test.ts | 44 - .../src/deprecated/context/ValueContext.ts | 45 - .../src/deprecated/context/index.ts | 18 - .../src/deprecated/context/types.ts | 44 - packages/backend-common/src/deprecated/hot.ts | 128 - .../backend-common/src/deprecated/index.ts | 282 -- .../deprecated/logging/createRootLogger.ts | 137 - .../src/deprecated/logging/globalLoggers.ts | 69 - .../src/deprecated/logging/index.ts | 22 - .../middleware/errorHandler.test.ts | 252 -- .../src/deprecated/middleware/errorHandler.ts | 78 - .../src/deprecated/middleware/index.ts | 20 - .../middleware/notFoundHandler.test.ts | 33 - .../deprecated/middleware/notFoundHandler.ts | 38 - .../middleware/requestLoggingHandler.test.ts | 46 - .../middleware/requestLoggingHandler.ts | 37 - .../middleware/statusCheckHandler.test.ts | 55 - .../middleware/statusCheckHandler.ts | 66 - .../src/deprecated/scm/git.test.ts | 606 --- .../backend-common/src/deprecated/scm/git.ts | 357 -- .../src/deprecated/scm/index.ts | 18 - .../service/createServiceBuilder.ts | 27 - .../service/createStatusCheckRouter.test.ts | 56 - .../service/createStatusCheckRouter.ts | 57 - .../src/deprecated/service/index.ts | 19 - .../service/lib/ServiceBuilderImpl.test.ts | 60 - .../service/lib/ServiceBuilderImpl.ts | 215 - .../src/deprecated/service/types.ts | 135 - .../tokens/ServerTokenManager.test.ts | 392 -- .../deprecated/tokens/ServerTokenManager.ts | 249 -- .../src/deprecated/tokens/index.ts | 19 - .../src/deprecated/tokens/types.ts | 38 - .../src/deprecated/util/ContainerRunner.ts | 69 - .../util/DockerContainerRunner.test.ts | 238 - .../deprecated/util/DockerContainerRunner.ts | 140 - .../util/KubernetesContainerRunner.test.ts | 310 -- .../util/KubernetesContainerRunner.ts | 386 -- .../src/deprecated/util/index.ts | 27 - packages/backend-common/src/index.ts | 27 - packages/backend-common/src/setupTests.ts | 17 - packages/backend-common/src/testUtils.ts | 43 - packages/backend-defaults/package.json | 6 +- .../package.json | 2 +- packages/backend-legacy/package.json | 2 +- .../cli-node/src/monorepo/Lockfile.test.ts | 4 +- packages/cli/package.json | 2 +- packages/cli/src/lib/version.ts | 2 - plugins/app-backend/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- plugins/auth-backend/package.json | 2 +- .../providers/cloudflare-access/provider.ts | 6 +- plugins/auth-node/package.json | 2 +- .../package.json | 3 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- plugins/catalog-backend/package.json | 2 +- plugins/devtools-backend/package.json | 2 +- .../package.json | 2 - plugins/events-backend/package.json | 3 +- plugins/events-node/package.json | 2 +- .../example-todo-list-backend/package.json | 2 +- plugins/kubernetes-backend/package.json | 2 +- plugins/kubernetes-node/package.json | 2 +- .../package.json | 2 +- plugins/notifications-backend/package.json | 2 +- plugins/notifications-node/package.json | 2 +- plugins/permission-backend/package.json | 2 +- plugins/permission-node/package.json | 2 +- plugins/proxy-backend/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- plugins/scaffolder-backend/package.json | 2 +- .../scaffolder-node-test-utils/package.json | 2 +- plugins/scaffolder-node/package.json | 2 +- .../package.json | 4 +- .../package.json | 2 - .../package.json | 2 +- plugins/search-backend-module-pg/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- plugins/search-backend-node/package.json | 2 +- plugins/search-backend/package.json | 2 +- plugins/signals-backend/package.json | 2 +- plugins/signals-node/package.json | 2 +- plugins/techdocs-backend/package.json | 2 +- yarn.lock | 174 +- 136 files changed, 193 insertions(+), 12592 deletions(-) create mode 100644 .changeset/light-rats-travel.md delete mode 100644 .github/workflows/verify_e2e-kubernetes-noop.yml delete mode 100644 .github/workflows/verify_e2e-kubernetes.yml delete mode 100644 packages/backend-common/.eslintrc.js delete mode 100644 packages/backend-common/CHANGELOG.md delete mode 100644 packages/backend-common/README.md delete mode 100644 packages/backend-common/api-report-alpha.md delete mode 100644 packages/backend-common/api-report-testUtils.md delete mode 100644 packages/backend-common/api-report.md delete mode 100644 packages/backend-common/catalog-info.yaml delete mode 100644 packages/backend-common/config.d.ts delete mode 100644 packages/backend-common/knip-report.md delete mode 100644 packages/backend-common/package.json delete mode 100644 packages/backend-common/src/alpha.ts delete mode 100644 packages/backend-common/src/compat/auth/createLegacyAuthAdapters.test.ts delete mode 100644 packages/backend-common/src/compat/auth/createLegacyAuthAdapters.ts delete mode 100644 packages/backend-common/src/compat/auth/index.ts delete mode 100644 packages/backend-common/src/compat/cache/cacheToPluginCacheManager.ts delete mode 100644 packages/backend-common/src/compat/cache/index.ts delete mode 100644 packages/backend-common/src/compat/index.ts delete mode 100644 packages/backend-common/src/compat/legacy/index.ts delete mode 100644 packages/backend-common/src/compat/legacy/legacy.test.ts delete mode 100644 packages/backend-common/src/compat/legacy/legacy.ts delete mode 100644 packages/backend-common/src/compat/logging/index.ts delete mode 100644 packages/backend-common/src/compat/logging/loggerToWinstonLogger.ts delete mode 100644 packages/backend-common/src/deprecated/config/ObservableConfigProxy.test.ts delete mode 100644 packages/backend-common/src/deprecated/config/ObservableConfigProxy.ts delete mode 100644 packages/backend-common/src/deprecated/config/config.test.ts delete mode 100644 packages/backend-common/src/deprecated/config/config.ts delete mode 100644 packages/backend-common/src/deprecated/config/index.ts delete mode 100644 packages/backend-common/src/deprecated/config/urls.test.ts delete mode 100644 packages/backend-common/src/deprecated/config/urls.ts delete mode 100644 packages/backend-common/src/deprecated/context/AbortContext.test.ts delete mode 100644 packages/backend-common/src/deprecated/context/AbortContext.ts delete mode 100644 packages/backend-common/src/deprecated/context/Contexts.test.ts delete mode 100644 packages/backend-common/src/deprecated/context/Contexts.ts delete mode 100644 packages/backend-common/src/deprecated/context/RootContext.test.ts delete mode 100644 packages/backend-common/src/deprecated/context/RootContext.ts delete mode 100644 packages/backend-common/src/deprecated/context/ValueContext.test.ts delete mode 100644 packages/backend-common/src/deprecated/context/ValueContext.ts delete mode 100644 packages/backend-common/src/deprecated/context/index.ts delete mode 100644 packages/backend-common/src/deprecated/context/types.ts delete mode 100644 packages/backend-common/src/deprecated/hot.ts delete mode 100644 packages/backend-common/src/deprecated/index.ts delete mode 100644 packages/backend-common/src/deprecated/logging/createRootLogger.ts delete mode 100644 packages/backend-common/src/deprecated/logging/globalLoggers.ts delete mode 100644 packages/backend-common/src/deprecated/logging/index.ts delete mode 100644 packages/backend-common/src/deprecated/middleware/errorHandler.test.ts delete mode 100644 packages/backend-common/src/deprecated/middleware/errorHandler.ts delete mode 100644 packages/backend-common/src/deprecated/middleware/index.ts delete mode 100644 packages/backend-common/src/deprecated/middleware/notFoundHandler.test.ts delete mode 100644 packages/backend-common/src/deprecated/middleware/notFoundHandler.ts delete mode 100644 packages/backend-common/src/deprecated/middleware/requestLoggingHandler.test.ts delete mode 100644 packages/backend-common/src/deprecated/middleware/requestLoggingHandler.ts delete mode 100644 packages/backend-common/src/deprecated/middleware/statusCheckHandler.test.ts delete mode 100644 packages/backend-common/src/deprecated/middleware/statusCheckHandler.ts delete mode 100644 packages/backend-common/src/deprecated/scm/git.test.ts delete mode 100644 packages/backend-common/src/deprecated/scm/git.ts delete mode 100644 packages/backend-common/src/deprecated/scm/index.ts delete mode 100644 packages/backend-common/src/deprecated/service/createServiceBuilder.ts delete mode 100644 packages/backend-common/src/deprecated/service/createStatusCheckRouter.test.ts delete mode 100644 packages/backend-common/src/deprecated/service/createStatusCheckRouter.ts delete mode 100644 packages/backend-common/src/deprecated/service/index.ts delete mode 100644 packages/backend-common/src/deprecated/service/lib/ServiceBuilderImpl.test.ts delete mode 100644 packages/backend-common/src/deprecated/service/lib/ServiceBuilderImpl.ts delete mode 100644 packages/backend-common/src/deprecated/service/types.ts delete mode 100644 packages/backend-common/src/deprecated/tokens/ServerTokenManager.test.ts delete mode 100644 packages/backend-common/src/deprecated/tokens/ServerTokenManager.ts delete mode 100644 packages/backend-common/src/deprecated/tokens/index.ts delete mode 100644 packages/backend-common/src/deprecated/tokens/types.ts delete mode 100644 packages/backend-common/src/deprecated/util/ContainerRunner.ts delete mode 100644 packages/backend-common/src/deprecated/util/DockerContainerRunner.test.ts delete mode 100644 packages/backend-common/src/deprecated/util/DockerContainerRunner.ts delete mode 100644 packages/backend-common/src/deprecated/util/KubernetesContainerRunner.test.ts delete mode 100644 packages/backend-common/src/deprecated/util/KubernetesContainerRunner.ts delete mode 100644 packages/backend-common/src/deprecated/util/index.ts delete mode 100644 packages/backend-common/src/index.ts delete mode 100644 packages/backend-common/src/setupTests.ts delete mode 100644 packages/backend-common/src/testUtils.ts diff --git a/.changeset/light-rats-travel.md b/.changeset/light-rats-travel.md new file mode 100644 index 0000000000..de497567ef --- /dev/null +++ b/.changeset/light-rats-travel.md @@ -0,0 +1,54 @@ +--- +'@backstage/plugin-scaffolder-backend-module-confluence-to-markdown': patch +'@backstage/plugin-search-backend-module-stack-overflow-collator': patch +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +'@backstage/plugin-scaffolder-backend-module-notifications': patch +'@backstage/plugin-catalog-backend-module-bitbucket-cloud': patch +'@backstage/plugin-scaffolder-backend-module-cookiecutter': patch +'@backstage/plugin-auth-backend-module-aws-alb-provider': patch +'@backstage/plugin-search-backend-module-elasticsearch': patch +'@backstage/plugin-auth-backend-module-guest-provider': patch +'@backstage/plugin-catalog-backend-module-unprocessed': patch +'@backstage/plugin-notifications-backend-module-email': patch +'@backstage/plugin-auth-backend-module-oidc-provider': patch +'@backstage/plugin-catalog-backend-module-gitlab-org': patch +'@backstage/backend-dynamic-feature-service': patch +'@backstage/plugin-scaffolder-backend-module-github': patch +'@backstage/plugin-scaffolder-backend-module-gitlab': patch +'@backstage/plugin-scaffolder-backend-module-yeoman': patch +'@backstage/plugin-scaffolder-backend-module-rails': patch +'@backstage/plugin-catalog-backend-module-openapi': patch +'@backstage/plugin-search-backend-module-techdocs': patch +'@backstage/plugin-catalog-backend-module-github': patch +'@backstage/plugin-events-backend-module-aws-sqs': patch +'@backstage/plugin-search-backend-module-catalog': patch +'@backstage/plugin-search-backend-module-explore': patch +'@backstage/plugin-scaffolder-node-test-utils': patch +'@backstage/plugin-search-backend-module-pg': patch +'@backstage/plugin-notifications-backend': patch +'@backstage/plugin-search-backend-node': patch +'@backstage/plugin-kubernetes-backend': patch +'@backstage/plugin-notifications-node': patch +'@backstage/plugin-permission-backend': patch +'@backstage/plugin-scaffolder-backend': patch +'@backstage/backend-defaults': patch +'@backstage/backend-app-api': patch +'@backstage/plugin-devtools-backend': patch +'@backstage/plugin-techdocs-backend': patch +'@backstage/plugin-catalog-backend': patch +'@backstage/plugin-kubernetes-node': patch +'@backstage/plugin-permission-node': patch +'@backstage/plugin-scaffolder-node': patch +'@backstage/plugin-signals-backend': patch +'@backstage/plugin-events-backend': patch +'@backstage/plugin-search-backend': patch +'@backstage/plugin-proxy-backend': patch +'@backstage/plugin-auth-backend': patch +'@backstage/plugin-signals-node': patch +'@backstage/plugin-app-backend': patch +'@backstage/plugin-events-node': patch +'@backstage/plugin-auth-node': patch +'@backstage/cli': patch +--- + +Remove references to in-repo backend-common diff --git a/.github/workflows/verify_e2e-kubernetes-noop.yml b/.github/workflows/verify_e2e-kubernetes-noop.yml deleted file mode 100644 index 753d602381..0000000000 --- a/.github/workflows/verify_e2e-kubernetes-noop.yml +++ /dev/null @@ -1,30 +0,0 @@ -# NO-OP placeholder that always passes for other paths -# This is here so that we're able to set the status check as required - -name: E2E Kubernetes Void -on: - pull_request: - paths-ignore: - - 'yarn.lock' - - '.github/workflows/verify_e2e-kubernetes.yml' - - 'packages/backend-common/src/**' - -permissions: - contents: read - -jobs: - verify: - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [18.x, 20.x] - - name: Kubernetes ${{ matrix.node-version }} - steps: - - name: Harden Runner - uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 - with: - egress-policy: audit - - - run: echo NOOP diff --git a/.github/workflows/verify_e2e-kubernetes.yml b/.github/workflows/verify_e2e-kubernetes.yml deleted file mode 100644 index e716a6c8a9..0000000000 --- a/.github/workflows/verify_e2e-kubernetes.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: E2E Kubernetes -on: - # NOTE: If you change these you must update verify_kubernetes-noop.yml as well - pull_request: - paths: - - 'yarn.lock' - - '.github/workflows/verify_e2e-kubernetes.yml' - - 'packages/backend-common/src/**' - -jobs: - verify: - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [18.x, 20.x] - - env: - CI: true - KUBERNETES_TESTS: true - - name: Kubernetes ${{ matrix.node-version }} - steps: - - name: Harden Runner - uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 - with: - egress-policy: audit - - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 - with: - node-version: ${{ matrix.node-version }} - registry-url: https://registry.npmjs.org/ # Needed for auth - - - name: yarn install - uses: backstage/actions/yarn-install@25145dd4117d50e1da9330e9ed2893bc6b75373e # v0.6.15 - with: - cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - - - name: bootstrap kind - uses: helm/kind-action@0025e74a8c7512023d06dc019c617aa3cf561fde # v1.10.0 - - - name: kubernetes test - working-directory: packages/backend-common - run: yarn test:kubernetes diff --git a/package.json b/package.json index 8e7edd8417..346739959a 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "build:all": "backstage-cli repo build --all", "build:api-docs": "LANG=en_EN yarn build:api-reports --docs --exclude 'plugins/@(adr|adr-backend|adr-common|airbrake|airbrake-backend|allure|analytics-module-ga|analytics-module-ga4|analytics-module-newrelic-browser|apache-airflow|api-docs|api-docs-module-protoc-gen-doc|apollo-explorer|app-visualizer|azure-devops|azure-devops-backend|azure-devops-common|azure-sites|azure-sites-backend|azure-sites-common|badges|badges-backend|bazaar|bazaar-backend|bitbucket-cloud-common|bitrise|catalog-graph|catalog-graphql|catalog-import|catalog-unprocessed-entities|cicd-statistics|cicd-statistics-module-gitlab|circleci|cloudbuild|code-climate|code-coverage|code-coverage-backend|codescene|config-schema|cost-insights|cost-insights-common|dynatrace|entity-feedback|entity-feedback-backend|entity-feedback-common|entity-validation|example-todo-list|example-todo-list-backend|example-todo-list-common|firehydrant|fossa|gcalendar|gcp-projects|git-release-manager|github-actions|github-deployments|github-issues|github-pull-requests-board|gitops-profiles|gocd|graphiql|graphql-backend|graphql-voyager|ilert|jenkins|jenkins-backend|jenkins-common|kafka|kafka-backend|lighthouse|lighthouse-backend|lighthouse-common|linguist|linguist-backend|linguist-common|microsoft-calendar|newrelic|newrelic-dashboard|nomad|nomad-backend|octopus-deploy|opencost|pagerduty|periskop|periskop-backend|playlist|playlist-backend|playlist-common|proxy-backend|puppetdb|rollbar|rollbar-backend|sentry|shortcuts|splunk-on-call|stack-overflow|stack-overflow-backend|stackstorm|tech-radar|tech-radar-2|todo|todo-backend|xcmetrics)'", "build:api-reports": "yarn build:api-reports:only --tsc", - "build:api-reports:only": "NODE_OPTIONS=--max-old-space-size=8192 backstage-repo-tools api-reports --allow-warnings 'packages/backend-app-api,packages/backend-common,packages/core-components,plugins/+(catalog|catalog-import|git-release-manager|jenkins|kubernetes)' -o ae-wrong-input-file-type --validate-release-tags", + "build:api-reports:only": "NODE_OPTIONS=--max-old-space-size=8192 backstage-repo-tools api-reports --allow-warnings 'packages/backend-app-api,packages/core-components,plugins/+(catalog|catalog-import|git-release-manager|jenkins|kubernetes)' -o ae-wrong-input-file-type --validate-release-tags", "build:backend": "yarn workspace example-backend build", "build:knip-reports": "backstage-repo-tools knip-reports", "build:plugins-report": "node ./scripts/build-plugins-report", diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index 80be6ecae5..5e9291a884 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -50,7 +50,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/cli-common": "workspace:^", "@backstage/config": "workspace:^", diff --git a/packages/backend-common/.eslintrc.js b/packages/backend-common/.eslintrc.js deleted file mode 100644 index e2a53a6ad2..0000000000 --- a/packages/backend-common/.eslintrc.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md deleted file mode 100644 index d58efb9c33..0000000000 --- a/packages/backend-common/CHANGELOG.md +++ /dev/null @@ -1,3894 +0,0 @@ -# @backstage/backend-common - -## 0.25.0 - -### Minor Changes - -- a4bac3c: **BREAKING**: You can no longer supply a `basePath` option to the host discovery implementation. In the new backend system, the ability to choose this path has been removed anyway at the plugin router level. -- 988c145: **BREAKING**: Simplifications and cleanup as part of the Backend System 1.0 work. - - - The deprecated `dropDatabase` function has now been removed, without replacement. - -- d425fc4: **BREAKING**: The return values from `createBackendPlugin`, `createBackendModule`, and `createServiceFactory` are now simply `BackendFeature` and `ServiceFactory`, instead of the previously deprecated form of a function that returns them. For this reason, `createServiceFactory` also no longer accepts the callback form where you provide direct options to the service. This also affects all `coreServices.*` service refs. - - This may in particular affect tests; if you were effectively doing `createBackendModule({...})()` (note the parentheses), you can now remove those extra parentheses at the end. You may encounter cases of this in your `packages/backend/src/index.ts` too, where you add plugins, modules, and services. If you were using `createServiceFactory` with a function as its argument for the purpose of passing in options, this pattern has been deprecated for a while and is no longer supported. You may want to explore the new multiton patterns to achieve your goals, or moving settings to app-config. - - As part of this change, the `IdentityFactoryOptions` type was removed, and can no longer be used to tweak that service. The identity service was also deprecated some time ago, and you will want to [migrate to the new auth system](https://backstage.io/docs/tutorials/auth-service-migration) if you still rely on it. - -### Patch Changes - -- 6ed9264: chore(deps): bump `path-to-regexp` from 6.2.2 to 8.0.0 -- 8ba77ed: The `legacyPlugin` and `makeLegacyPlugin` helpers now provide their own shim implementation of the identity and token manager services, as these services are being removed from the new backend system. -- d425fc4: Modules, plugins, and services are now `BackendFeature`, not a function that returns a feature. -- 2e9ec14: Add `pg-format` as a dependency -- 82539fe: Updated dependency `archiver` to `^7.0.0`. -- c2b63ab: Updated dependency `supertest` to `^7.0.0`. -- 3606843: Internal fixes to match `testcontainers` update -- 19ff127: Internal refactor to re-declare the token manager service which was removed from `@backstage/backend-plugin-api`, but is still supported in this package for backwards compatibility. -- 66dbf0a: Allow the cache service to accept the human duration format for TTL -- 0b2a402: Updates to the config schema to match reality -- Updated dependencies - - @backstage/backend-plugin-api@1.0.0 - - @backstage/plugin-auth-node@0.5.2 - - @backstage/integration@1.15.0 - - @backstage/config-loader@1.9.1 - - @backstage/backend-dev-utils@0.1.5 - - @backstage/cli-common@0.1.14 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration-aws-node@0.1.12 - - @backstage/types@1.1.1 - -## 0.25.0-next.2 - -### Patch Changes - -- 6ed9264: chore(deps): bump `path-to-regexp` from 6.2.2 to 8.0.0 -- c2b63ab: Updated dependency `supertest` to `^7.0.0`. -- 3606843: Internal fixes to match `testcontainers` update -- Updated dependencies - - @backstage/plugin-auth-node@0.5.2-next.2 - - @backstage/backend-plugin-api@1.0.0-next.2 - - @backstage/integration@1.15.0-next.0 - - @backstage/config-loader@1.9.1-next.0 - - @backstage/backend-dev-utils@0.1.5 - - @backstage/cli-common@0.1.14 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration-aws-node@0.1.12 - - @backstage/types@1.1.1 - -## 0.25.0-next.1 - -### Minor Changes - -- a4bac3c: **BREAKING**: You can no longer supply a `basePath` option to the host discovery implementation. In the new backend system, the ability to choose this path has been removed anyway at the plugin router level. -- 988c145: **BREAKING**: Simplifications and cleanup as part of the Backend System 1.0 work. - - - The deprecated `dropDatabase` function has now been removed, without replacement. - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-auth-node@0.5.2-next.1 - - @backstage/backend-dev-utils@0.1.5 - - @backstage/backend-plugin-api@0.9.0-next.1 - - @backstage/cli-common@0.1.14 - - @backstage/config@1.2.0 - - @backstage/config-loader@1.9.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.14.0 - - @backstage/integration-aws-node@0.1.12 - - @backstage/types@1.1.1 - -## 0.25.0-next.0 - -### Minor Changes - -- d425fc4: **BREAKING**: The return values from `createBackendPlugin`, `createBackendModule`, and `createServiceFactory` are now simply `BackendFeature` and `ServiceFactory`, instead of the previously deprecated form of a function that returns them. For this reason, `createServiceFactory` also no longer accepts the callback form where you provide direct options to the service. This also affects all `coreServices.*` service refs. - - This may in particular affect tests; if you were effectively doing `createBackendModule({...})()` (note the parentheses), you can now remove those extra parentheses at the end. You may encounter cases of this in your `packages/backend/src/index.ts` too, where you add plugins, modules, and services. If you were using `createServiceFactory` with a function as its argument for the purpose of passing in options, this pattern has been deprecated for a while and is no longer supported. You may want to explore the new multiton patterns to achieve your goals, or moving settings to app-config. - - As part of this change, the `IdentityFactoryOptions` type was removed, and can no longer be used to tweak that service. The identity service was also deprecated some time ago, and you will want to [migrate to the new auth system](https://backstage.io/docs/tutorials/auth-service-migration) if you still rely on it. - -### Patch Changes - -- 8ba77ed: The `legacyPlugin` and `makeLegacyPlugin` helpers now provide their own shim implementation of the identity and token manager services, as these services are being removed from the new backend system. -- d425fc4: Modules, plugins, and services are now `BackendFeature`, not a function that returns a feature. -- 2e9ec14: Add `pg-format` as a dependency -- 19ff127: Internal refactor to re-declare the token manager service which was removed from `@backstage/backend-plugin-api`, but is still supported in this package for backwards compatibility. -- 66dbf0a: Allow the cache service to accept the human duration format for TTL -- 0b2a402: Updates to the config schema to match reality -- Updated dependencies - - @backstage/backend-plugin-api@0.9.0-next.0 - - @backstage/plugin-auth-node@0.5.2-next.0 - - @backstage/backend-dev-utils@0.1.5 - - @backstage/cli-common@0.1.14 - - @backstage/config@1.2.0 - - @backstage/config-loader@1.9.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.14.0 - - @backstage/integration-aws-node@0.1.12 - - @backstage/types@1.1.1 - -## 0.24.0 - -### Minor Changes - -- 389f5a4: **BREAKING**: Removed the following `Url Reader` deprecated exports: - - - UrlReader: Use `UrlReaderService` from `@backstage/backend-plugin-api` instead; - - AzureUrlReader: Import from `@backstage/backend-defaults/urlReader` instead; - - BitbucketUrlReader: Import from `@backstage/backend-defaults/urlReader` instead; - - BitbucketCloudUrlReader: Import from `@backstage/backend-defaults/urlReader` instead; - - BitbucketServerUrlReader: Import from `@backstage/backend-defaults/urlReader` instead; - - GithubUrlReader: Import from `@backstage/backend-defaults/urlReader` instead; - - GitlabUrlReader: Import from `@backstage/backend-defaults/urlReader` instead; - - GerritUrlReader: Import from `@backstage/backend-defaults/urlReader` instead; - - GiteaUrlReader: Import from `@backstage/backend-defaults/urlReader` instead; - - HarnessUrlReader: Import from `@backstage/backend-defaults/urlReader` instead; - - AwsS3UrlReader: Import from `@backstage/backend-defaults/urlReader` instead; - - FetchUrlReader: Import from `@backstage/backend-defaults/urlReader` instead; - - UrlReaders: Import from `@backstage/backend-defaults/urlReader` instead; - - UrlReadersOptions: Import from `@backstage/backend-defaults/urlReader` instead; - - UrlReaderPredicateTuple: Import from `@backstage/backend-defaults/urlReader` instead; - - FromReadableArrayOptions: Import from `@backstage/backend-defaults/urlReader` instead; - - ReaderFactory: Import from `@backstage/backend-defaults/urlReader` instead; - - ReadUrlOptions:Use `UrlReaderServiceReadUrlOptions` from `@backstage/backend-plugin-api` instead; - - ReadUrlResponse: Use `UrlReaderServiceReadUrlResponse` from `@backstage/backend-plugin-api` instead; - - ReadUrlResponseFactory: Import from `@backstage/backend-defaults/urlReader` instead; - - ReadUrlResponseFactoryFromStreamOptions: Import from `@backstage/backend-defaults/urlReader` instead; - - ReadTreeOptions: Use `UrlReaderServiceReadTreeOptions` from `@backstage/backend-plugin-api` instead; - - ReadTreeResponse: Use `UrlReaderServiceReadTreeResponse` from `@backstage/backend-plugin-api` instead; - - ReadTreeResponseFile: Use `UrlReaderServiceReadTreeResponseFile` from `@backstage/backend-plugin-api` instead; - - ReadTreeResponseDirOptions: Use `UrlReaderServiceReadTreeResponseDirOptions` from `@backstage/backend-plugin-api` instead; - - ReadTreeResponseFactory: Import from `@backstage/backend-defaults/urlReader` instead; - - ReadTreeResponseFactoryOptions: Import from `@backstage/backend-defaults/urlReader` instead; - - SearchOptions: Use `UrlReaderServiceSearchOptions` from `@backstage/backend-plugin-api` instead; - - SearchResponse: Use `UrlReaderServiceSearchResponse` from `@backstage/backend-plugin-api` instead; - - SearchResponseFile: Use `UrlReaderServiceSearchResponseFile` from `@backstage/backend-plugin-api` instead. - -### Patch Changes - -- ba8571e: Setup user agent header for AWS sdk clients, this enables users to better track API calls made from Backstage to AWS APIs through things like CloudTrail. -- 93095ee: Make sure node-fetch is version 2.7.0 or greater -- 6795e33: This package is marked as `deprecated` and will be removed in a near future, please follow the deprecated instructions for the exports you still use. -- 7e13b7a: The remaining exports in the package have now been deprecated: - - - `cacheToPluginCacheManager` - - `createLegacyAuthAdapters` - - `LegacyCreateRouter` - - `legacyPlugin` - - `loggerToWinstonLogger` - - `makeLegacyPlugin` - - Users of these export should fully [migrate to the new backend system](https://backstage.io/docs/backend-system/building-backends/migrating). - -- ddde5fe: Internal type refactor. -- b63d378: export `createConfigSecretEnumerator` from `@backstage/backend-common` instead of `@backstage/backend-app-api`. -- Updated dependencies - - @backstage/backend-plugin-api@0.8.0 - - @backstage/config-loader@1.9.0 - - @backstage/plugin-auth-node@0.5.0 - - @backstage/backend-dev-utils@0.1.5 - - @backstage/integration@1.14.0 - - @backstage/cli-common@0.1.14 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration-aws-node@0.1.12 - - @backstage/types@1.1.1 - -## 0.23.4-next.3 - -### Patch Changes - -- ddde5fe: Internal type refactor. -- Updated dependencies - - @backstage/backend-plugin-api@0.8.0-next.3 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/cli-common@0.1.14 - - @backstage/config@1.2.0 - - @backstage/config-loader@1.9.0-next.2 - - @backstage/errors@1.2.4 - - @backstage/integration@1.14.0-next.0 - - @backstage/integration-aws-node@0.1.12 - - @backstage/types@1.1.1 - - @backstage/plugin-auth-node@0.5.0-next.3 - -## 0.23.4-next.2 - -### Patch Changes - -- 93095ee: Make sure node-fetch is version 2.7.0 or greater -- Updated dependencies - - @backstage/backend-plugin-api@0.8.0-next.2 - - @backstage/config-loader@1.9.0-next.2 - - @backstage/plugin-auth-node@0.5.0-next.2 - - @backstage/integration@1.14.0-next.0 - - @backstage/integration-aws-node@0.1.12 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/cli-common@0.1.14 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/types@1.1.1 - -## 0.23.4-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/config-loader@1.9.0-next.1 - - @backstage/backend-plugin-api@0.7.1-next.1 - - @backstage/integration@1.14.0-next.0 - - @backstage/integration-aws-node@0.1.12 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/cli-common@0.1.14 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/types@1.1.1 - - @backstage/plugin-auth-node@0.4.18-next.1 - -## 0.23.4-next.0 - -### Patch Changes - -- ba8571e: Setup user agent header for AWS sdk clients, this enables users to better track API calls made from Backstage to AWS APIs through things like CloudTrail. -- 7e13b7a: The remaining exports in the package have now been deprecated: - - - `cacheToPluginCacheManager` - - `createLegacyAuthAdapters` - - `LegacyCreateRouter` - - `legacyPlugin` - - `loggerToWinstonLogger` - - `makeLegacyPlugin` - - Users of these export should fully [migrate to the new backend system](https://backstage.io/docs/backend-system/building-backends/migrating). - -- Updated dependencies - - @backstage/integration@1.14.0-next.0 - - @backstage/config-loader@1.8.2-next.0 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/backend-plugin-api@0.7.1-next.0 - - @backstage/cli-common@0.1.14 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration-aws-node@0.1.12 - - @backstage/types@1.1.1 - - @backstage/plugin-auth-node@0.4.18-next.0 - -## 0.23.3 - -### Patch Changes - -- 8c09c97: Deprecate legacy status check factory, handler and types. -- d228862: Update default backend plugin created by the cli to use non-deprecated error handling middleware -- c964a3d: Add dependencies that are needed by cross-imports from backend-defaults -- b60db08: Fixing exporting of classes properly from new packages -- b9ed1bb: bumped better-sqlite3 from ^9.0.0 to ^11.0.0 -- Updated dependencies - - @backstage/backend-plugin-api@0.7.0 - - @backstage/integration@1.13.0 - - @backstage/plugin-auth-node@0.4.17 - - @backstage/config-loader@1.8.1 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/cli-common@0.1.14 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration-aws-node@0.1.12 - - @backstage/types@1.1.1 - -## 0.23.3-next.1 - -### Patch Changes - -- b9ed1bb: bumped better-sqlite3 from ^9.0.0 to ^11.0.0 -- Updated dependencies - - @backstage/backend-dev-utils@0.1.4 - - @backstage/backend-plugin-api@0.6.22-next.1 - - @backstage/cli-common@0.1.14 - - @backstage/config@1.2.0 - - @backstage/config-loader@1.8.1 - - @backstage/errors@1.2.4 - - @backstage/integration@1.13.0-next.0 - - @backstage/integration-aws-node@0.1.12 - - @backstage/types@1.1.1 - - @backstage/plugin-auth-node@0.4.17-next.1 - -## 0.23.2-next.0 - -### Patch Changes - -- 8c09c97: Deprecate legacy status check factory, handler and types. -- d228862: Update default backend plugin created by the cli to use non-deprecated error handling middleware -- c964a3d: Add dependencies that are needed by cross-imports from backend-defaults -- b60db08: Fixing exporting of classes properly from new packages -- Updated dependencies - - @backstage/backend-plugin-api@0.6.21-next.0 - - @backstage/integration@1.13.0-next.0 - - @backstage/plugin-auth-node@0.4.16-next.0 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/cli-common@0.1.14 - - @backstage/config@1.2.0 - - @backstage/config-loader@1.8.1 - - @backstage/errors@1.2.4 - - @backstage/integration-aws-node@0.1.12 - - @backstage/types@1.1.1 - -## 0.23.0 - -### Minor Changes - -- 395b973: Implemented `readTree` for Harness provider to support TechDocs functionality -- 02103be: Deprecated and moved over core services to `@backstage/backend-defaults` - -### Patch Changes - -- 9539a0b: Import utility functions from `backend-defaults` instead of `backend-app-api` -- b2c4607: Removed accents on deprecation note -- c6c0919: Updated configuration schema to include the `useRedisSets` cache config option. -- ed3074e: The `database` types, helpers and implementations were moved to the package `@backstage/backend-defaults` and deprecated from the package `@backstage/backend-commons`. -- 9cca724: The `TokenManager` has been deprecated in preparation for the [stable release of the New Backend System](https://github.com/backstage/backstage/issues/24493). Please [migrate](https://backstage.io/docs/tutorials/auth-service-migration) to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead. -- 1779188: In preparation to the new backend system stable release, the `isDatabaseConflictError` helper have been moved to the `@backstage/backend-plugin-api` package and deprecated from `@backstage/backend-common`. -- 78a0b08: Internal refactor to handle `BackendFeature` contract change. -- e171620: Move `cache` implementation and types to the `@backstage/backend-defaults` package. -- 1a6f38a: `ContainerRunner`, `DockerContainerRunner` and `KubernetesContainerRunner` are now deprecated -- 8869b8e: We are deprecating the legacy `createServiceBuilder` factory, so if you are still using it, please checkout the migration guide and [migrate](https://backstage.io/docs/backend-system/building-plugins-and-modules/migrating) your plugin to use the new backend system. -- 0634fdc: Deprecated `dropDatabase` -- b2ee7f3: Moved over all URL reader functionality from `@backstage/backend-common` to `@backstage/backend-defaults/urlReader`. Please update your imports. -- d94a477: Removed the circular dependency on `@backstage/backend-app-api` -- 3bd04bb: We are deprecating the legacy router handlers and contexts in preparation for the new backend system stable release. -- 23ee9ab: Fix AWS CodeCommit integration by allowing to change the host -- e9a03c9: Finalizes the deprecation of legacy backend utilities. Deprecated utilities include the `ServiceBuilder` type, `notFoundHandler` and `redactWintonLogLine` functions. -- 6a576dc: Deprecate legacy service logger helpers and stop using `getVoidLogger` in tests. -- 032a7a6: Deprecate the legacy error and request logging handler types, respectively: `ErrorHandlerOptions` and `RequestLoggingHandlerFactory`. -- Updated dependencies - - @backstage/backend-plugin-api@0.6.19 - - @backstage/plugin-auth-node@0.4.14 - - @backstage/integration@1.12.0 - - @backstage/cli-common@0.1.14 - - @backstage/config-loader@1.8.1 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration-aws-node@0.1.12 - - @backstage/types@1.1.1 - -## 0.23.0-next.3 - -### Patch Changes - -- b2ee7f3: Moved over all URL reader functionality from `@backstage/backend-common` to `@backstage/backend-defaults/urlReader`. Please update your imports. -- 23ee9ab: Fix AWS CodeCommit integration by allowing to change the host -- Updated dependencies - - @backstage/backend-plugin-api@0.6.19-next.3 - - @backstage/plugin-auth-node@0.4.14-next.3 - - @backstage/integration@1.12.0-next.1 - - @backstage/cli-common@0.1.14-next.0 - - @backstage/backend-app-api@0.7.6-next.3 - - @backstage/config-loader@1.8.1-next.0 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration-aws-node@0.1.12 - - @backstage/types@1.1.1 - -## 0.23.0-next.2 - -### Minor Changes - -- 395b973: Implemented `readTree` for Harness provider to support TechDocs functionality - -### Patch Changes - -- 0634fdc: Deprecated `dropDatabase` -- Updated dependencies - - @backstage/backend-plugin-api@0.6.19-next.2 - - @backstage/integration@1.12.0-next.0 - - @backstage/backend-app-api@0.7.6-next.2 - - @backstage/plugin-auth-node@0.4.14-next.2 - - @backstage/config-loader@1.8.0 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration-aws-node@0.1.12 - - @backstage/types@1.1.1 - -## 0.23.0-next.1 - -### Minor Changes - -- 02103be: Deprecated and moved over core services to `@backstage/backend-defaults` - -### Patch Changes - -- Updated dependencies - - @backstage/backend-app-api@0.7.6-next.1 - - @backstage/backend-plugin-api@0.6.19-next.1 - - @backstage/config-loader@1.8.0 - - @backstage/plugin-auth-node@0.4.14-next.1 - -## 0.22.1-next.0 - -### Patch Changes - -- c6c0919: Updated configuration schema to include the `useRedisSets` cache config option. -- 1779188: In preparation to the new backend system stable release, the `isDatabaseConflictError` helper have been moved to the `@backstage/backend-plugin-api` package and deprecated from `@backstage/backend-common`. -- 8869b8e: We are deprecating the legacy `createServiceBuilder` factory, so if you are still using it, please checkout the migration guide and [migrate](https://backstage.io/docs/backend-system/building-plugins-and-modules/migrating) your plugin to use the new backend system. -- 3bd04bb: We are deprecating the legacy router handlers and contexts in preparation for the new backend system stable release. -- 6a576dc: Deprecate legacy service logger helpers and stop using `getVoidLogger` in tests. -- Updated dependencies - - @backstage/backend-app-api@0.7.6-next.0 - - @backstage/backend-plugin-api@0.6.19-next.0 - - @backstage/plugin-auth-node@0.4.14-next.0 - - @backstage/config-loader@1.8.0 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.11.0 - - @backstage/integration-aws-node@0.1.12 - - @backstage/types@1.1.1 - -## 0.22.0 - -### Minor Changes - -- ed83f85: Internal refactor of the database code. - - **BREAKING**: The helper functions `createDatabaseClient` and `ensureDatabaseExists` have been removed from the public interface, since they have no usage within the repository and never were suitable for calling from the outside. Please consider using `coreServices.database` or `DatabaseManager` directly wherever possible instead. - -### Patch Changes - -- 2cc750d: Added `HarnessURLReader` with `readUrl` support. -- 57f692e: Preparing for a stable new backend system release, we are deprecating utilities in the `backend-common` that are not used by the core framework, such as the isomorphic `Git` class. As we will no longer support the isomorphic `Git` utility in the framework packages, we recommend plugins that start maintaining their own implementation of this class. -- 0ec0796: Plugins created through the `legacyPlugin` helper are now able to authenticate requests from plugins that are fully implemented using the new backend system. This fixes the `Key for the ES256 algorithm must be one of type KeyObject or CryptoKey. Received an instance of Uint8Array` error. -- d229dc4: Move path utilities from `backend-common` to the `backend-plugin-api` package. -- ccc8851: Added config prop `ensureSchemaExists` to support postgres instances where user can create schemas but not databases. -- f66bbb4: Only create a single actual connection to memcache/redis, even in cases where many `CacheService` instances are made -- ba0b8b4: Added option to `ServerTokenManager.fromConfig` that allows it to be instantiated in production without any configured keys. -- Updated dependencies - - @backstage/backend-app-api@0.7.3 - - @backstage/backend-plugin-api@0.6.18 - - @backstage/plugin-auth-node@0.4.13 - - @backstage/integration@1.11.0 - -## 0.22.0-next.2 - -### Patch Changes - -- 2cc750d: Added `HarnessURLReader` with `readUrl` support. -- ccc8851: Added config prop `ensureSchemaExists` to support postgres instances where user can create schemas but not databases. -- Updated dependencies - - @backstage/integration@1.11.0-next.0 - -## 0.22.0-next.1 - -### Minor Changes - -- ed83f85: Internal refactor of the database code. - - **BREAKING**: The helper functions `createDatabaseClient` and `ensureDatabaseExists` have been removed from the public interface, since they have no usage within the repository and never were suitable for calling from the outside. Please consider using `coreServices.database` or `DatabaseManager` directly wherever possible instead. - -### Patch Changes - -- Updated dependencies - - @backstage/backend-app-api@0.7.2-next.1 - - @backstage/plugin-auth-node@0.4.13-next.1 - - @backstage/config-loader@1.8.0 - - @backstage/backend-plugin-api@0.6.18-next.1 - -## 0.21.8-next.0 - -### Patch Changes - -- ba0b8b4: Added option to `ServerTokenManager.fromConfig` that allows it to be instantiated in production without any configured keys. -- Updated dependencies - - @backstage/backend-app-api@0.7.1-next.0 - - @backstage/plugin-auth-node@0.4.13-next.0 - - @backstage/backend-plugin-api@0.6.18-next.0 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.2.0 - - @backstage/config-loader@1.8.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.10.0 - - @backstage/integration-aws-node@0.1.12 - - @backstage/types@1.1.1 - -## 0.21.7 - -### Patch Changes - -- 007e7ea: Added placeholder for `listPublicServiceKeys()` in the `AuthService` returned by `createLegacyAuthAdapters`. -- 00fca28: Ensure that `ServerTokenManager` also reads the new `backend.auth.externalAccess` settings -- 25ea3d2: Minor internal restructuring -- e31bacc: Added `pullOptions` to `DockerContainerRunner#runContainer` method to pass down options when pulling an image. -- 7b11422: Add AWS CodeCommit URL Reader/Integration -- 75a53b8: KubernetesContainerRunner.runContainer no longer closes the `logStream` it receives as input. -- Updated dependencies - - @backstage/config-loader@1.8.0 - - @backstage/backend-app-api@0.7.0 - - @backstage/backend-plugin-api@0.6.17 - - @backstage/plugin-auth-node@0.4.12 - - @backstage/integration@1.10.0 - - @backstage/integration-aws-node@0.1.12 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/types@1.1.1 - -## 0.21.7-next.1 - -### Patch Changes - -- 007e7ea: Added placeholder for `listPublicServiceKeys()` in the `AuthService` returned by `createLegacyAuthAdapters`. -- 75a53b8: KubernetesContainerRunner.runContainer no longer closes the `logStream` it receives as input. -- Updated dependencies - - @backstage/backend-app-api@0.7.0-next.1 - - @backstage/backend-plugin-api@0.6.17-next.1 - - @backstage/plugin-auth-node@0.4.12-next.1 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.2.0 - - @backstage/config-loader@1.8.0-next.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.10.0-next.0 - - @backstage/integration-aws-node@0.1.12 - - @backstage/types@1.1.1 - -## 0.21.7-next.0 - -### Patch Changes - -- 7b11422: Add AWS CodeCommit URL Reader/Integration -- Updated dependencies - - @backstage/backend-app-api@0.6.3-next.0 - - @backstage/integration@1.10.0-next.0 - - @backstage/config-loader@1.8.0-next.0 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/backend-plugin-api@0.6.17-next.0 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration-aws-node@0.1.12 - - @backstage/types@1.1.1 - - @backstage/plugin-auth-node@0.4.12-next.0 - -## 0.21.6 - -### Patch Changes - -- 81a995f: Updated dependency `aws-sdk-client-mock` to `^4.0.0`. -- Updated dependencies - - @backstage/backend-app-api@0.6.2 - - @backstage/plugin-auth-node@0.4.11 - - @backstage/integration-aws-node@0.1.12 - - @backstage/backend-plugin-api@0.6.16 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.2.0 - - @backstage/config-loader@1.7.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.9.1 - - @backstage/types@1.1.1 - -## 0.21.5 - -### Patch Changes - -- 81a995f: Updated dependency `aws-sdk-client-mock` to `^4.0.0`. -- Updated dependencies - - @backstage/backend-app-api@0.6.1 - - @backstage/integration-aws-node@0.1.11 - - @backstage/plugin-auth-node@0.4.10 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/backend-plugin-api@0.6.15 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.2.0 - - @backstage/config-loader@1.7.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.9.1 - - @backstage/types@1.1.1 - -## 0.21.4 - -### Patch Changes - -- 7422430: Resolve the `basePath` before constructing the target path -- 999224f: Bump dependency `minimatch` to v9 -- e0b997c: Fix issue where `resolveSafeChildPath` path would incorrectly resolve when operating on a symlink -- 9802004: Added the `UserInfoApi` as both an optional input and as an output for `createLegacyAuthAdapters` -- 2af5354: Bump dependency `jose` to v5 -- ff40ada: Updated dependency `mysql2` to `^3.0.0`. -- 0fb419b: Updated dependency `uuid` to `^9.0.0`. - Updated dependency `@types/uuid` to `^9.0.0`. -- 568881f: Updated dependency `yauzl` to `^3.0.0`. -- 4a3d434: Added a `createLegacyAuthAdapters` function that can be used as a compatibility adapter for backend plugins who want to start using the new [`auth`](https://backstage.io/docs/backend-system/core-services/auth/) and [`httpAuth`](https://backstage.io/docs/backend-system/core-services/http-auth) services that were created as part of [BEP-0003](https://github.com/backstage/backstage/tree/master/beps/0003-auth-architecture-evolution). - - See the [Auth Service Migration tutorial](https://backstage.io/docs/tutorials/auth-service-migration) for more information on the usage of this adapter. - -- Updated dependencies - - @backstage/integration@1.9.1 - - @backstage/plugin-auth-node@0.4.9 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/backend-plugin-api@0.6.14 - - @backstage/backend-app-api@0.6.0 - - @backstage/config-loader@1.7.0 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/cli-common@0.1.13 - - @backstage/integration-aws-node@0.1.10 - - @backstage/types@1.1.1 - -## 0.21.4-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/integration@1.9.1-next.2 - - @backstage/backend-app-api@0.6.0-next.2 - - @backstage/plugin-auth-node@0.4.9-next.2 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/backend-plugin-api@0.6.14-next.2 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.2.0-next.1 - - @backstage/config-loader@1.7.0-next.1 - - @backstage/errors@1.2.4-next.0 - - @backstage/integration-aws-node@0.1.10-next.1 - - @backstage/types@1.1.1 - -## 0.21.4-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/config@1.2.0-next.1 - - @backstage/config-loader@1.7.0-next.1 - - @backstage/backend-app-api@0.6.0-next.1 - - @backstage/backend-plugin-api@0.6.14-next.1 - - @backstage/integration@1.9.1-next.1 - - @backstage/integration-aws-node@0.1.10-next.1 - - @backstage/plugin-auth-node@0.4.9-next.1 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/cli-common@0.1.13 - - @backstage/errors@1.2.4-next.0 - - @backstage/types@1.1.1 - -## 0.21.3-next.0 - -### Patch Changes - -- 7422430: Resolve the `basePath` before constructing the target path -- 999224f: Bump dependency `minimatch` to v9 -- e0b997c: Fix issue where `resolveSafeChildPath` path would incorrectly resolve when operating on a symlink -- 9802004: Added the `UserInfoApi` as both an optional input and as an output for `createLegacyAuthAdapters` -- 2af5354: Bump dependency `jose` to v5 -- ff40ada: Updated dependency `mysql2` to `^3.0.0`. -- 0fb419b: Updated dependency `uuid` to `^9.0.0`. - Updated dependency `@types/uuid` to `^9.0.0`. -- 568881f: Updated dependency `yauzl` to `^3.0.0`. -- 4a3d434: Added a `createLegacyAuthAdapters` function that can be used as a compatibility adapter for backend plugins who want to start using the new [`auth`](https://backstage.io/docs/backend-system/core-services/auth/) and [`httpAuth`](https://backstage.io/docs/backend-system/core-services/http-auth) services that were created as part of [BEP-0003](https://github.com/backstage/backstage/tree/master/beps/0003-auth-architecture-evolution). - - See the [Auth Service Migration tutorial](https://backstage.io/docs/tutorials/auth-service-migration) for more information on the usage of this adapter. - -- Updated dependencies - - @backstage/plugin-auth-node@0.4.8-next.0 - - @backstage/errors@1.2.4-next.0 - - @backstage/backend-plugin-api@0.6.13-next.0 - - @backstage/backend-app-api@0.6.0-next.0 - - @backstage/config-loader@1.6.3-next.0 - - @backstage/config@1.1.2-next.0 - - @backstage/integration@1.9.1-next.0 - - @backstage/integration-aws-node@0.1.10-next.0 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/cli-common@0.1.13 - - @backstage/types@1.1.1 - -## 0.21.0 - -### Minor Changes - -- bbe374e: **BREAKING**: `A gitilesBaseUrl` must be provided for the Gerrit integration to work. - You can disable this check by setting `DISABLE_GERRIT_GITILES_REQUIREMENT=1` but - this will be removed in a future release. If you are not able to use the Gitiles - Gerrit plugin, please open an issue towards `https://github.com/backstage/backstage` -- e85aa98: drop databases after unit tests if the database instance is not running in docker - -### Patch Changes - -- 6707216: Added a new `LegacyRootDatabaseService` interface that can be used to avoid direct dependencies on the `DatabaseManager`. -- 842171a: Fix a bug with S3 Fetch that caused all objects to be flattened within a single folder on the local file system. -- 3489d05: `FetchUrlReader#readUrl()` now supports passing an optional `token` to authenticate requests. -- 9aac2b0: Use `--cwd` as the first `yarn` argument -- ece5a8f: Add a User-Agent header for calls towards Google Cloud Storage. -- 1f020fe: Support `token` in `readTree`, `readUrl` and `search` -- 6bb6f3e: Updated dependency `fs-extra` to `^11.2.0`. - Updated dependency `@types/fs-extra` to `^11.0.0`. -- d2e3ab9: Updated dependency `dockerode` to `^4.0.0`. -- 1cae748: Updated dependency `git-url-parse` to `^14.0.0`. -- e27b7f3: Fix rate limit detection by looking for HTTP status code 429 and updating the header `x-ratelimit-remaining` to look for in case of a 403 code is returned -- 7fb7a79: Add a config declaration for `workingDirectory` -- Updated dependencies - - @backstage/backend-app-api@0.5.11 - - @backstage/backend-plugin-api@0.6.10 - - @backstage/backend-dev-utils@0.1.4 - - @backstage/integration-aws-node@0.1.9 - - @backstage/integration@1.9.0 - - @backstage/config-loader@1.6.2 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.1.1 - - @backstage/errors@1.2.3 - - @backstage/types@1.1.1 - -## 0.21.0-next.3 - -### Minor Changes - -- bbe374e: **BREAKING**: `A gitilesBaseUrl` must be provided for the Gerrit integration to work. - You can disable this check by setting `DISABLE_GERRIT_GITILES_REQUIREMENT=1` but - this will be removed in a future release. If you are not able to use the Gitiles - Gerrit plugin, please open an issue towards `https://github.com/backstage/backstage` - -### Patch Changes - -- 6707216: Added a new `LegacyRootDatabaseService` interface that can be used to avoid direct dependencies on the `DatabaseManager`. -- 842171a: Fix a bug with S3 Fetch that caused all objects to be flattened within a single folder on the local file system. -- ece5a8f: Add a User-Agent header for calls towards Google Cloud Storage. -- 1cae748: Updated dependency `git-url-parse` to `^14.0.0`. -- Updated dependencies - - @backstage/integration-aws-node@0.1.9-next.0 - - @backstage/integration@1.9.0-next.1 - - @backstage/backend-app-api@0.5.11-next.3 - - @backstage/config-loader@1.6.2-next.0 - - @backstage/backend-dev-utils@0.1.4-next.0 - - @backstage/backend-plugin-api@0.6.10-next.3 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.1.1 - - @backstage/errors@1.2.3 - - @backstage/types@1.1.1 - -## 0.21.0-next.2 - -### Patch Changes - -- 3489d05: `FetchUrlReader#readUrl()` now supports passing an optional `token` to authenticate requests. -- 9aac2b0: Use `--cwd` as the first `yarn` argument -- 7fb7a79: Add a config declaration for `workingDirectory` -- Updated dependencies - - @backstage/backend-plugin-api@0.6.10-next.2 - - @backstage/backend-dev-utils@0.1.4-next.0 - - @backstage/backend-app-api@0.5.11-next.2 - - @backstage/config@1.1.1 - - @backstage/integration-aws-node@0.1.8 - - @backstage/cli-common@0.1.13 - - @backstage/config-loader@1.6.1 - - @backstage/errors@1.2.3 - - @backstage/integration@1.9.0-next.0 - - @backstage/types@1.1.1 - -## 0.21.0-next.1 - -### Patch Changes - -- 1f020fe: Support `token` in `readTree`, `readUrl` and `search` -- e27b7f3: Fix rate limit detection by looking for HTTP status code 429 and updating the header `x-ratelimit-remaining` to look for in case of a 403 code is returned -- Updated dependencies - - @backstage/backend-plugin-api@0.6.10-next.1 - - @backstage/integration@1.9.0-next.0 - - @backstage/backend-app-api@0.5.11-next.1 - - @backstage/backend-dev-utils@0.1.3 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.1.1 - - @backstage/config-loader@1.6.1 - - @backstage/errors@1.2.3 - - @backstage/integration-aws-node@0.1.8 - - @backstage/types@1.1.1 - -## 0.21.0-next.0 - -### Minor Changes - -- e85aa98: drop databases after unit tests if the database instance is not running in docker - -### Patch Changes - -- Updated dependencies - - @backstage/backend-app-api@0.5.11-next.0 - - @backstage/config-loader@1.6.1 - - @backstage/backend-dev-utils@0.1.3 - - @backstage/backend-plugin-api@0.6.10-next.0 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.1.1 - - @backstage/errors@1.2.3 - - @backstage/integration@1.8.0 - - @backstage/integration-aws-node@0.1.8 - - @backstage/types@1.1.1 - -## 0.20.1 - -### Patch Changes - -- 3b24eae: Adding support for removing file from git index -- 454d17c: Do not call fetch directly but rather use `fetchResponse` facility -- b6b15b2: Use sha256 instead of md5 for hash key calculation in caches - - This can have a side effect of invalidating caches (when cache key was >250 characters) - This improves compliance with FIPS nodejs - -- Updated dependencies - - @backstage/config-loader@1.6.1 - - @backstage/backend-plugin-api@0.6.9 - - @backstage/backend-dev-utils@0.1.3 - - @backstage/backend-app-api@0.5.10 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.1.1 - - @backstage/errors@1.2.3 - - @backstage/integration@1.8.0 - - @backstage/integration-aws-node@0.1.8 - - @backstage/types@1.1.1 - -## 0.20.1-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@0.6.9-next.2 - - @backstage/backend-dev-utils@0.1.3-next.0 - - @backstage/backend-app-api@0.5.10-next.2 - - @backstage/config-loader@1.6.1-next.0 - -## 0.20.1-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/config-loader@1.6.1-next.0 - - @backstage/backend-app-api@0.5.10-next.1 - - @backstage/integration@1.8.0 - - @backstage/integration-aws-node@0.1.8 - - @backstage/config@1.1.1 - - @backstage/backend-dev-utils@0.1.2 - - @backstage/backend-plugin-api@0.6.9-next.1 - - @backstage/cli-common@0.1.13 - - @backstage/errors@1.2.3 - - @backstage/types@1.1.1 - -## 0.20.1-next.0 - -### Patch Changes - -- b6b15b2: Use sha256 instead of md5 for hash key calculation in caches - - This can have a side effect of invalidating caches (when cache key was >250 characters) - This improves compliance with FIPS nodejs - -- Updated dependencies - - @backstage/backend-app-api@0.5.10-next.0 - - @backstage/backend-dev-utils@0.1.2 - - @backstage/backend-plugin-api@0.6.9-next.0 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.1.1 - - @backstage/config-loader@1.6.0 - - @backstage/errors@1.2.3 - - @backstage/integration@1.8.0 - - @backstage/integration-aws-node@0.1.8 - - @backstage/types@1.1.1 - -## 0.20.0 - -### Minor Changes - -- 870db76: Implemented `readTree` for Gitea provider to support TechDocs functionality - -### Patch Changes - -- 7f04128: Allow a default cache TTL to be set through the app config -- 1ad8906: Use `Readable.from` to fix some of the stream issues -- d86a007: Fixed the AwsS3UrlReader host regex and host to allow the S3 reading for CN AWS domain -- bc67498: Updated dependency `archiver` to `^6.0.0`. - Updated dependency `@types/archiver` to `^6.0.0`. -- 706fc3a: Updated dependency `@kubernetes/client-node` to `0.20.0`. -- 2666675: Updated dependency `@google-cloud/storage` to `^7.0.0`. -- d15d483: Add command `--runAsDefaultUser` for `@techdocs/cli generate` to bypass running the docker builds as host user for macOS and Linux. -- d1e00aa: Expose an `onAuth` handler for `git` actions to provide custom credentials -- Updated dependencies - - @backstage/config-loader@1.6.0 - - @backstage/backend-app-api@0.5.9 - - @backstage/integration@1.8.0 - - @backstage/backend-dev-utils@0.1.2 - - @backstage/backend-plugin-api@0.6.8 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.1.1 - - @backstage/errors@1.2.3 - - @backstage/integration-aws-node@0.1.8 - - @backstage/types@1.1.1 - -## 0.20.0-next.3 - -### Patch Changes - -- d86a007: Fixed the AwsS3UrlReader host regex and host to allow the S3 reading for CN AWS domain -- Updated dependencies - - @backstage/backend-app-api@0.5.9-next.3 - - @backstage/backend-dev-utils@0.1.2 - - @backstage/backend-plugin-api@0.6.8-next.3 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.1.1 - - @backstage/config-loader@1.6.0-next.0 - - @backstage/errors@1.2.3 - - @backstage/integration@1.8.0-next.1 - - @backstage/integration-aws-node@0.1.8 - - @backstage/types@1.1.1 - -## 0.20.0-next.2 - -### Patch Changes - -- bc67498: Updated dependency `archiver` to `^6.0.0`. - Updated dependency `@types/archiver` to `^6.0.0`. -- Updated dependencies - - @backstage/config-loader@1.6.0-next.0 - - @backstage/backend-app-api@0.5.9-next.2 - - @backstage/backend-dev-utils@0.1.2 - - @backstage/backend-plugin-api@0.6.8-next.2 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.1.1 - - @backstage/errors@1.2.3 - - @backstage/integration@1.8.0-next.1 - - @backstage/integration-aws-node@0.1.8 - - @backstage/types@1.1.1 - -## 0.20.0-next.1 - -### Patch Changes - -- 2666675457: Updated dependency `@google-cloud/storage` to `^7.0.0`. -- Updated dependencies - - @backstage/backend-app-api@0.5.9-next.1 - - @backstage/integration@1.8.0-next.1 - - @backstage/backend-dev-utils@0.1.2 - - @backstage/backend-plugin-api@0.6.8-next.1 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.1.1 - - @backstage/config-loader@1.5.3 - - @backstage/errors@1.2.3 - - @backstage/integration-aws-node@0.1.8 - - @backstage/types@1.1.1 - -## 0.20.0-next.0 - -### Minor Changes - -- 870db76a45: Implemented `readTree` for Gitea provider to support TechDocs functionality - -### Patch Changes - -- 7f04128bbc: Allow a default cache TTL to be set through the app config -- 1ad8906a9e: Use `Readable.from` to fix some of the stream issues -- 706fc3a7e1: Updated dependency `@kubernetes/client-node` to `0.20.0`. -- d15d483a49: Add command `--runAsDefaultUser` for `@techdocs/cli generate` to bypass running the docker builds as host user for macOS and Linux. -- d1e00aa17a: Expose an `onAuth` handler for `git` actions to provide custom credentials -- Updated dependencies - - @backstage/integration@1.8.0-next.0 - - @backstage/backend-app-api@0.5.9-next.0 - - @backstage/backend-plugin-api@0.6.8-next.0 - - @backstage/backend-dev-utils@0.1.2 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.1.1 - - @backstage/config-loader@1.5.3 - - @backstage/errors@1.2.3 - - @backstage/integration-aws-node@0.1.8 - - @backstage/types@1.1.1 - -## 0.19.9 - -### Patch Changes - -- aa13482090: Limit the database creation concurrency to one, defensively -- 013611b42e: `knex` has been bumped to major version 3 and `better-sqlite3` to major version 9, which deprecate node 16 support. -- 3d043526f4: Updated dependency `aws-sdk-client-mock` to `^3.0.0`. -- Updated dependencies - - @backstage/config-loader@1.5.3 - - @backstage/integration@1.7.2 - - @backstage/backend-plugin-api@0.6.7 - - @backstage/integration-aws-node@0.1.8 - - @backstage/backend-app-api@0.5.8 - - @backstage/backend-dev-utils@0.1.2 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.1.1 - - @backstage/errors@1.2.3 - - @backstage/types@1.1.1 - -## 0.19.9-next.2 - -### Patch Changes - -- [#20570](https://github.com/backstage/backstage/pull/20570) [`013611b42e`](https://github.com/backstage/backstage/commit/013611b42ed457fefa9bb85fddf416cf5e0c1f76) Thanks [@freben](https://github.com/freben)! - `knex` has been bumped to major version 3 and `better-sqlite3` to major version 9, which deprecate node 16 support. - -- Updated dependencies - - @backstage/backend-plugin-api@0.6.7-next.2 - - @backstage/backend-app-api@0.5.8-next.2 - - @backstage/config-loader@1.5.3-next.0 - -## 0.19.9-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/integration@1.7.2-next.0 - - @backstage/backend-app-api@0.5.8-next.1 - - @backstage/config-loader@1.5.3-next.0 - - @backstage/backend-dev-utils@0.1.2 - - @backstage/backend-plugin-api@0.6.7-next.1 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.1.1 - - @backstage/errors@1.2.3 - - @backstage/integration-aws-node@0.1.7 - - @backstage/types@1.1.1 - -## 0.19.9-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/config-loader@1.5.2-next.0 - - @backstage/backend-app-api@0.5.8-next.0 - - @backstage/integration@1.7.1 - - @backstage/integration-aws-node@0.1.7 - - @backstage/backend-dev-utils@0.1.2 - - @backstage/backend-plugin-api@0.6.7-next.0 - - @backstage/cli-common@0.1.13 - - @backstage/config@1.1.1 - - @backstage/errors@1.2.3 - - @backstage/types@1.1.1 - -## 0.19.8 - -### Patch Changes - -- 74491c9602: The `HostDiscovery` export has been deprecated, import it from `@backstage/backend-app-api` instead. -- b95d66d4ea: Properly close write stream when writing temporary archive for processing zip-based `.readTree()` responses. -- b94f32271e: Added the ability to fetch git tags through the `Git` class. This is useful for scaffolder actions that want to take action based on tag versions in a cloned repository -- 0b55f773a7: Removed some unused dependencies -- 4c39e38f1e: Added `/testUtils` entry point, with a utility for mocking resolve package paths as returned by `resolvePackagePath`. -- 9101c0d1b6: Updated dependency `@kubernetes/client-node` to `0.19.0`. -- a250ad775f: Removed `mock-fs` dev dependency. -- 2a40cd46a8: Adds the optional flag for useRedisSets for the Redis cache to the config. -- 1c3d6fa2b2: The `useHotCleanup` and `useHotMemoize` helpers are now deprecated, since hot module reloads for backend are being phased out. -- Updated dependencies - - @backstage/integration@1.7.1 - - @backstage/backend-dev-utils@0.1.2 - - @backstage/config-loader@1.5.1 - - @backstage/errors@1.2.3 - - @backstage/cli-common@0.1.13 - - @backstage/backend-app-api@0.5.6 - - @backstage/backend-plugin-api@0.6.6 - - @backstage/config@1.1.1 - - @backstage/integration-aws-node@0.1.7 - - @backstage/types@1.1.1 - -## 0.19.8-next.2 - -### Patch Changes - -- 74491c9602: The `HostDiscovery` export has been deprecated, import it from `@backstage/backend-app-api` instead. -- b95d66d4ea: Properly close write stream when writing temporary archive for processing zip-based `.readTree()` responses. -- 0b55f773a7: Removed some unused dependencies -- 4c39e38f1e: Added `/testUtils` entry point, with a utility for mocking resolve package paths as returned by `resolvePackagePath`. -- a250ad775f: Removed `mock-fs` dev dependency. -- Updated dependencies - - @backstage/config-loader@1.5.1-next.1 - - @backstage/integration@1.7.1-next.1 - - @backstage/errors@1.2.3-next.0 - - @backstage/backend-app-api@0.5.6-next.2 - - @backstage/backend-dev-utils@0.1.2-next.0 - - @backstage/backend-plugin-api@0.6.6-next.2 - - @backstage/cli-common@0.1.13-next.0 - - @backstage/config@1.1.1-next.0 - - @backstage/integration-aws-node@0.1.7-next.0 - - @backstage/types@1.1.1 - -## 0.19.7-next.1 - -### Patch Changes - -- b94f32271e: Added the ability to fetch git tags through the `Git` class. This is useful for scaffolder actions that want to take action based on tag versions in a cloned repository -- Updated dependencies - - @backstage/backend-dev-utils@0.1.2-next.0 - - @backstage/backend-app-api@0.5.5-next.1 - - @backstage/backend-plugin-api@0.6.5-next.1 - - @backstage/config@1.1.0 - - @backstage/integration-aws-node@0.1.6 - - @backstage/cli-common@0.1.13-next.0 - - @backstage/config-loader@1.5.1-next.0 - - @backstage/errors@1.2.2 - - @backstage/integration@1.7.1-next.0 - - @backstage/types@1.1.1 - -## 0.19.7-next.0 - -### Patch Changes - -- 1c3d6fa2b2: The `useHotCleanup` and `useHotMemoize` helpers are now deprecated, since hot module reloads for backend are being phased out. -- Updated dependencies - - @backstage/integration@1.7.1-next.0 - - @backstage/config-loader@1.5.1-next.0 - - @backstage/cli-common@0.1.13-next.0 - - @backstage/config@1.1.0 - - @backstage/integration-aws-node@0.1.6 - - @backstage/backend-app-api@0.5.5-next.0 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/backend-plugin-api@0.6.5-next.0 - - @backstage/errors@1.2.2 - - @backstage/types@1.1.1 - -## 0.19.5 - -### Patch Changes - -- 6847cd6225d6: Avoid starting database keepalive loop in tests. -- fd3fdd0e3338: The root logger is now initialized lazily, fixing a circular dependency issue with `@backstage/backend-app-api` that would result in `Cannot read properties of undefined (reading 'redacter')`. -- 5f1a92b9f19f: Use `DefaultAzureDevOpsCredentialsProvider` to retrieve credentials for Azure DevOps. -- 19a140418cc8: Added retries for initial database creation, as well as set minimum connection pool size for the database creation client to 0 and lowered the connection acquisition timeout. -- 05508a9757d2: Minor internal refactor -- cfc3ca6ce060: Changes needed to support MySQL -- Updated dependencies - - @backstage/backend-app-api@0.5.3 - - @backstage/config@1.1.0 - - @backstage/errors@1.2.2 - - @backstage/integration@1.7.0 - - @backstage/types@1.1.1 - - @backstage/backend-plugin-api@0.6.3 - - @backstage/config-loader@1.5.0 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/cli-common@0.1.12 - - @backstage/integration-aws-node@0.1.6 - -## 0.19.5-next.3 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-app-api@0.5.3-next.3 - - @backstage/config@1.1.0-next.2 - - @backstage/errors@1.2.2-next.0 - - @backstage/integration@1.7.0-next.3 - - @backstage/types@1.1.1-next.0 - - @backstage/backend-plugin-api@0.6.3-next.3 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/cli-common@0.1.12 - - @backstage/config-loader@1.5.0-next.3 - - @backstage/integration-aws-node@0.1.6-next.2 - -## 0.19.5-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-app-api@0.5.3-next.2 - - @backstage/config-loader@1.5.0-next.2 - - @backstage/config@1.1.0-next.1 - - @backstage/integration@1.7.0-next.2 - - @backstage/integration-aws-node@0.1.6-next.1 - - @backstage/backend-plugin-api@0.6.3-next.2 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/cli-common@0.1.12 - - @backstage/errors@1.2.1 - - @backstage/types@1.1.0 - -## 0.19.5-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/config@1.1.0-next.0 - - @backstage/integration@1.7.0-next.1 - - @backstage/backend-app-api@0.5.3-next.1 - - @backstage/backend-plugin-api@0.6.3-next.1 - - @backstage/config-loader@1.5.0-next.1 - - @backstage/integration-aws-node@0.1.6-next.0 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/cli-common@0.1.12 - - @backstage/errors@1.2.1 - - @backstage/types@1.1.0 - -## 0.19.4-next.0 - -### Patch Changes - -- 5f1a92b9f19f: Use `DefaultAzureDevOpsCredentialsProvider` to retrieve credentials for Azure DevOps. -- cfc3ca6ce060: Changes needed to support MySQL -- Updated dependencies - - @backstage/integration@1.7.0-next.0 - - @backstage/config-loader@1.5.0-next.0 - - @backstage/backend-app-api@0.5.2-next.0 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/backend-plugin-api@0.6.2-next.0 - - @backstage/cli-common@0.1.12 - - @backstage/config@1.0.8 - - @backstage/errors@1.2.1 - - @backstage/integration-aws-node@0.1.5 - - @backstage/types@1.1.0 - -## 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 - -- Updated dependencies - - @backstage/config-loader@1.4.0-next.0 - - @backstage/backend-app-api@0.4.6-next.0 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/backend-plugin-api@0.5.5-next.0 - - @backstage/cli-common@0.1.12 - - @backstage/config@1.0.8 - - @backstage/errors@1.2.1 - - @backstage/integration@1.5.1 - - @backstage/integration-aws-node@0.1.5 - - @backstage/types@1.1.0 - -## 0.19.1 - -### Patch Changes - -- 787ddcc5ef99: use `Readable.from` to explicitly convert the `buffer` from `node-fetch` to a `Readable` stream -- Updated dependencies - - @backstage/errors@1.2.1 - - @backstage/backend-app-api@0.4.5 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/backend-plugin-api@0.5.4 - - @backstage/cli-common@0.1.12 - - @backstage/config@1.0.8 - - @backstage/config-loader@1.3.2 - - @backstage/integration@1.5.1 - - @backstage/integration-aws-node@0.1.5 - - @backstage/types@1.1.0 - -## 0.19.1-next.0 - -### Patch Changes - -- 787ddcc5ef99: use `Readable.from` to explicitly convert the `buffer` from `node-fetch` to a `Readable` stream -- Updated dependencies - - @backstage/errors@1.2.1-next.0 - - @backstage/backend-app-api@0.4.5-next.0 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/backend-plugin-api@0.5.4-next.0 - - @backstage/cli-common@0.1.12 - - @backstage/config@1.0.8 - - @backstage/config-loader@1.3.2-next.0 - - @backstage/integration@1.5.1-next.0 - - @backstage/integration-aws-node@0.1.5-next.0 - - @backstage/types@1.1.0 - -## 0.19.0 - -### Minor Changes - -- c7f848bcea3c: Support authentication with a service principal or managed identity for Azure DevOps - - Azure DevOps recently released support, in public preview, for authenticating with a service principal or managed identity instead of a personal access token (PAT): https://devblogs.microsoft.com/devops/introducing-service-principal-and-managed-identity-support-on-azure-devops/. With this change the Azure integration now supports service principals and managed identities for Azure AD backed Azure DevOps organizations. Service principal and managed identity authentication is not supported on Azure DevOps Server (on-premises) organizations. - -### Patch Changes - -- 4ef91ab46732: Updated the backend database connection configuration schema to set the password visibility to secret -- 52d599817680: Changed the default backend CacheClient to an in-memory cache when not explicitly configured. - - Explicit configuration of an **in-memory cache** can be removed from `app-config.yaml`, as this is now the default: - - ```diff - backend: - - cache: - - store: memory - ``` - -- 5f2c38c70f5b: Fix SNYK-JS-FASTXMLPARSER-5668858 (`fast-xml-parser`) by upgrading aws-sdk to at least the current latest version. -- eeb3f801fddf: `HostDiscovery` now strips trailing slashes in the `backend.baseUrl` config. -- 9f47a743632c: Fixed typo in HostDiscovery's JSDoc -- 810c6de51604: Remove unused dev dependency `aws-sdk-mock`. -- Updated dependencies - - @backstage/types@1.1.0 - - @backstage/integration-aws-node@0.1.4 - - @backstage/config-loader@1.3.1 - - @backstage/integration@1.5.0 - - @backstage/errors@1.2.0 - - @backstage/backend-app-api@0.4.4 - - @backstage/backend-plugin-api@0.5.3 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/cli-common@0.1.12 - - @backstage/config@1.0.8 - -## 0.19.0-next.2 - -### Patch Changes - -- 5f2c38c70f5b: Fix SNYK-JS-FASTXMLPARSER-5668858 (`fast-xml-parser`) by upgrading aws-sdk to at least the current latest version. -- Updated dependencies - - @backstage/integration-aws-node@0.1.4-next.1 - - @backstage/backend-app-api@0.4.4-next.2 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/backend-plugin-api@0.5.3-next.2 - - @backstage/cli-common@0.1.12 - - @backstage/config@1.0.7 - - @backstage/config-loader@1.3.1-next.1 - - @backstage/errors@1.2.0-next.0 - - @backstage/integration@1.5.0-next.0 - - @backstage/types@1.0.2 - -## 0.19.0-next.1 - -### Minor Changes - -- c7f848bcea3c: Support authentication with a service principal or managed identity for Azure DevOps - - Azure DevOps recently released support, in public preview, for authenticating with a service principal or managed identity instead of a personal access token (PAT): https://devblogs.microsoft.com/devops/introducing-service-principal-and-managed-identity-support-on-azure-devops/. With this change the Azure integration now supports service principals and managed identities for Azure AD backed Azure DevOps organizations. Service principal and managed identity authentication is not supported on Azure DevOps Server (on-premises) organizations. - -### Patch Changes - -- 4ef91ab46732: Updated the backend database connection configuration schema to set the password visibility to secret -- 9f47a743632c: Fixed typo in HostDiscovery's JSDoc -- Updated dependencies - - @backstage/integration@1.5.0-next.0 - - @backstage/errors@1.2.0-next.0 - - @backstage/backend-app-api@0.4.4-next.1 - - @backstage/backend-plugin-api@0.5.3-next.1 - - @backstage/config-loader@1.3.1-next.1 - - @backstage/integration-aws-node@0.1.4-next.0 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/cli-common@0.1.12 - - @backstage/config@1.0.7 - - @backstage/types@1.0.2 - -## 0.18.6-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/config-loader@1.3.1-next.0 - - @backstage/backend-app-api@0.4.4-next.0 - - @backstage/integration@1.4.5 - - @backstage/integration-aws-node@0.1.3 - - @backstage/config@1.0.7 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/backend-plugin-api@0.5.3-next.0 - - @backstage/cli-common@0.1.12 - - @backstage/errors@1.1.5 - - @backstage/types@1.0.2 - -## 0.18.5 - -### Patch Changes - -- 0297f7a54af: Remove the direct dependency on deprecated "request" library -- 284db225083: Updated the `DatabaseManager` to include the plugin id in the Postgres application name of the database connections created for each plugin. -- 3659c71c5d9: Standardize `@aws-sdk` v3 versions -- 42d817e76ab: Added `HostDiscovery` to supersede deprecated `SingleHostDiscovery` (deprecated due to name) -- Updated dependencies - - @backstage/config-loader@1.3.0 - - @backstage/integration@1.4.5 - - @backstage/integration-aws-node@0.1.3 - - @backstage/backend-app-api@0.4.3 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/backend-plugin-api@0.5.2 - - @backstage/cli-common@0.1.12 - - @backstage/config@1.0.7 - - @backstage/errors@1.1.5 - - @backstage/types@1.0.2 - -## 0.18.5-next.1 - -### Patch Changes - -- 0297f7a54af: Remove the direct dependency on deprecated "request" library -- Updated dependencies - - @backstage/backend-app-api@0.4.3-next.1 - - @backstage/backend-plugin-api@0.5.2-next.1 - - @backstage/config-loader@1.3.0-next.0 - - @backstage/config@1.0.7 - - @backstage/integration-aws-node@0.1.2 - -## 0.18.5-next.0 - -### Patch Changes - -- 284db225083: Updated the `DatabaseManager` to include the plugin id in the Postgres application name of the database connections created for each plugin. -- 42d817e76ab: Added `HostDiscovery` to supersede deprecated `SingleHostDiscovery` (deprecated due to name) -- Updated dependencies - - @backstage/integration@1.4.5-next.0 - - @backstage/backend-app-api@0.4.3-next.0 - - @backstage/config-loader@1.3.0-next.0 - - @backstage/integration-aws-node@0.1.2 - - @backstage/backend-plugin-api@0.5.2-next.0 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/cli-common@0.1.12 - - @backstage/config@1.0.7 - - @backstage/errors@1.1.5 - - @backstage/types@1.0.2 - -## 0.18.4 - -### Patch Changes - -- a1002df2dc2: Support commit hashes at `GithubUrlReader.readTree/search` additionally to branch names. - - Additionally, this will reduce the number of API calls from 2 to 1 for retrieving the "repo details" - for all cases besides when the default branch has to be resolved and used - (e.g., repo URL without any branch or commit hash). - -- 5c7ce585824: Allow an additionalConfig to be provided to loadBackendConfig that fetches config values during runtime. -- 2b15cb4aa0a: The dependency isomorphic-git is now on version 1.23.0 -- 34167270b31: Renamed the `loadBackendConfig` option `additionalConfig` to `additionalConfigs` as an array, and ensured that they get passed on properly. - - This is technically breaking, but the [original addition](https://github.com/backstage/backstage/pull/16643) hasn't been released in mainline yet so we are taking this step now as a `patch` change. - -- 420164593cf: Improve GitlabUrlReader to only load requested sub-path -- Updated dependencies - - @backstage/config-loader@1.2.0 - - @backstage/backend-app-api@0.4.2 - - @backstage/integration@1.4.4 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/backend-plugin-api@0.5.1 - - @backstage/cli-common@0.1.12 - - @backstage/config@1.0.7 - - @backstage/errors@1.1.5 - - @backstage/integration-aws-node@0.1.2 - - @backstage/types@1.0.2 - -## 0.18.4-next.2 - -### Patch Changes - -- 5c7ce585824: Allow an additionalConfig to be provided to loadBackendConfig that fetches config values during runtime. -- Updated dependencies - - @backstage/backend-app-api@0.4.2-next.2 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/backend-plugin-api@0.5.1-next.2 - - @backstage/cli-common@0.1.12 - - @backstage/config@1.0.7 - - @backstage/config-loader@1.1.9 - - @backstage/errors@1.1.5 - - @backstage/integration@1.4.4-next.0 - - @backstage/integration-aws-node@0.1.2 - - @backstage/types@1.0.2 - -## 0.18.4-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/integration@1.4.4-next.0 - - @backstage/backend-app-api@0.4.2-next.1 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/backend-plugin-api@0.5.1-next.1 - - @backstage/cli-common@0.1.12 - - @backstage/config@1.0.7 - - @backstage/config-loader@1.1.9 - - @backstage/errors@1.1.5 - - @backstage/integration-aws-node@0.1.2 - - @backstage/types@1.0.2 - -## 0.18.4-next.0 - -### Patch Changes - -- 420164593cf: Improve GitlabUrlReader to only load requested sub-path -- Updated dependencies - - @backstage/backend-app-api@0.4.2-next.0 - - @backstage/config@1.0.7 - - @backstage/integration@1.4.3 - - @backstage/integration-aws-node@0.1.2 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/backend-plugin-api@0.5.1-next.0 - - @backstage/cli-common@0.1.12 - - @backstage/config-loader@1.1.9 - - @backstage/errors@1.1.5 - - @backstage/types@1.0.2 - -## 0.18.3 - -### Patch Changes - -- f75097868a7: Adds config option `backend.database.role` to set ownership for newly created schemas and tables in Postgres - - The example config below connects to the database as user `v-backstage-123` but sets the ownership of - the create schemas and tables to `backstage` - - ```yaml - backend: - database: - client: pg - pluginDivisionMode: schema - role: backstage - connection: - user: v-backstage-123 - ... - ``` - -- 928a12a9b3e: Internal refactor of `/alpha` exports. -- 52b0022dab7: Updated dependency `msw` to `^1.0.0`. -- 87f0bbec175: AwsS3UrlReader upgraded to use aws-sdk v3 -- c1ee073a82b: Added `lastModifiedAt` field on `UrlReaderService` responses and a `lastModifiedAfter` option to `UrlReaderService.readUrl`. -- 482dae5de1c: Updated link to docs. -- Updated dependencies - - @backstage/errors@1.1.5 - - @backstage/backend-plugin-api@0.5.0 - - @backstage/backend-app-api@0.4.1 - - @backstage/config-loader@1.1.9 - - @backstage/integration@1.4.3 - - @backstage/backend-dev-utils@0.1.1 - - @backstage/cli-common@0.1.12 - - @backstage/config@1.0.7 - - @backstage/integration-aws-node@0.1.2 - - @backstage/types@1.0.2 - -## 0.18.3-next.2 - -### Patch Changes - -- f75097868a7: Adds config option `backend.database.role` to set ownership for newly created schemas and tables in Postgres - - The example config below connects to the database as user `v-backstage-123` but sets the ownership of - the create schemas and tables to `backstage` - - ```yaml - backend: - database: - client: pg - pluginDivisionMode: schema - role: backstage - connection: - user: v-backstage-123 - ... - ``` - -- 87f0bbec175: AwsS3UrlReader upgraded to use aws-sdk v3 -- Updated dependencies - - @backstage/backend-app-api@0.4.1-next.2 - - @backstage/backend-plugin-api@0.4.1-next.2 - - @backstage/config@1.0.7-next.0 - - @backstage/integration@1.4.3-next.0 - - @backstage/integration-aws-node@0.1.2-next.0 - -## 0.18.3-next.1 - -### Patch Changes - -- 52b0022dab7: Updated dependency `msw` to `^1.0.0`. -- 482dae5de1c: Updated link to docs. -- Updated dependencies - - @backstage/errors@1.1.5-next.0 - - @backstage/config-loader@1.1.9-next.0 - - @backstage/integration@1.4.3-next.0 - - @backstage/backend-plugin-api@0.4.1-next.1 - - @backstage/backend-dev-utils@0.1.1-next.0 - - @backstage/backend-app-api@0.4.1-next.1 - - @backstage/cli-common@0.1.12-next.0 - - @backstage/config@1.0.7-next.0 - - @backstage/types@1.0.2 - -## 0.18.3-next.0 - -### Patch Changes - -- 928a12a9b3: Internal refactor of `/alpha` exports. -- Updated dependencies - - @backstage/backend-plugin-api@0.4.1-next.0 - - @backstage/backend-app-api@0.4.1-next.0 - - @backstage/backend-dev-utils@0.1.0 - - @backstage/cli-common@0.1.11 - - @backstage/config@1.0.6 - - @backstage/config-loader@1.1.8 - - @backstage/errors@1.1.4 - - @backstage/integration@1.4.2 - - @backstage/types@1.0.2 - -## 0.18.2 - -### Patch Changes - -- 5febb216fe: **BREAKING**: The `CacheClient` interface must now also implement the `withOptions` method. The `.get()` method has also received a type parameter that helps ensure that `undefined` in the event of a cache miss is handled. - - Added a `cacheToPluginCacheManager` helper that converts a `CacheService` into a legacy `PluginCacheManager` instance. - -- 5febb216fe: Updated to match the new `CacheService` interface. -- e716946103: Updated usage of the lifecycle service. -- d31d8e00b3: Updated to work with the new `type: 'pem'` with `createHttpServer` from `@backstage/backend-app-api` -- 0ff03319be: Updated usage of `createBackendPlugin`. -- f60cca9da1: The `DatabaseManager.forPlugin` method now accepts additional service dependencies. There is no need to update existing code to pass these dependencies. -- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`. -- Updated dependencies - - @backstage/backend-app-api@0.4.0 - - @backstage/backend-plugin-api@0.4.0 - - @backstage/backend-dev-utils@0.1.0 - - @backstage/cli-common@0.1.11 - - @backstage/config@1.0.6 - - @backstage/config-loader@1.1.8 - - @backstage/errors@1.1.4 - - @backstage/integration@1.4.2 - - @backstage/types@1.0.2 - -## 0.18.2-next.2 - -### Patch Changes - -- e716946103: Updated usage of the lifecycle service. -- d31d8e00b3: Updated to work with the new `type: 'pem'` with `createHttpServer` from `@backstage/backend-app-api` -- 0ff03319be: Updated usage of `createBackendPlugin`. -- f60cca9da1: The `DatabaseManager.forPlugin` method now accepts additional service dependencies. There is no need to update existing code to pass these dependencies. -- Updated dependencies - - @backstage/backend-app-api@0.4.0-next.2 - - @backstage/backend-plugin-api@0.4.0-next.2 - - @backstage/backend-dev-utils@0.1.0-next.0 - - @backstage/cli-common@0.1.11 - - @backstage/config@1.0.6 - - @backstage/config-loader@1.1.8 - - @backstage/errors@1.1.4 - - @backstage/integration@1.4.2 - - @backstage/types@1.0.2 - -## 0.18.2-next.1 - -### Patch Changes - -- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`. -- Updated dependencies - - @backstage/backend-plugin-api@0.3.2-next.1 - - @backstage/backend-app-api@0.3.2-next.1 - - @backstage/cli-common@0.1.11 - - @backstage/config@1.0.6 - - @backstage/config-loader@1.1.8 - - @backstage/errors@1.1.4 - - @backstage/integration@1.4.2 - - @backstage/types@1.0.2 - -## 0.18.2-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-app-api@0.3.2-next.0 - - @backstage/backend-plugin-api@0.3.2-next.0 - -## 0.18.0 - -### Minor Changes - -- 5e2cebe9a3: **BREAKING**: Removed deprecated `read` method from the `UrlReader` interface. All implementations should use the `readUrl` method instead. - - Migrated `UrlReader` and related types to `backend/backend-plugin-api`, types remain re-exported from `backend-common` for now. - -### Patch Changes - -- 0e63aab311: Internal refactor of the logger and configuration loading implementations. -- 31e2309c8c: Added `legacyPlugin` and the lower level `makeLegacyPlugin` wrappers that convert legacy plugins to the new backend system. This will be used to ease the future migration to the new backend system, but we discourage use of it for now. -- 8e06f3cf00: Added `loggerToWinstonLogger`, which was moved from `@backstage/backend-plugin-api`. -- 2b1554cebf: Replaced dependencies on the `Logger` type from `winston` with `LoggerService` from `@backstage/backend-plugin-api`. This is not a breaking change as the `LoggerService` is a subset of the `Logger` interface. -- 5437fe488f: Migrated types related to `TokenManagerService`, `CacheService` and `DatabaseService` into backend-plugin-api. -- 6f02d23b01: Moved `PluginEndpointDiscovery` type from backend-common to backend-plugin-api. -- d592ec4f51: Updated the logger created by `createRootLogger` to make it possible to override the default `service` log label. -- b99c030f1b: Refactor to rely on `@backstage/backend-app-api` for the implementation of `createServiceBuilder`. -- f23eef3aa2: Updated dependency `better-sqlite3` to `^8.0.0`. -- Updated dependencies - - @backstage/backend-plugin-api@0.3.0 - - @backstage/backend-app-api@0.3.0 - - @backstage/config@1.0.6 - - @backstage/cli-common@0.1.11 - - @backstage/config-loader@1.1.8 - - @backstage/errors@1.1.4 - - @backstage/integration@1.4.2 - - @backstage/types@1.0.2 - -## 0.18.0-next.1 - -### Patch Changes - -- 8e06f3cf00: Added `loggerToWinstonLogger`, which was moved from `@backstage/backend-plugin-api`. -- 2b1554cebf: Replaced dependencies on the `Logger` type from `winston` with `LoggerService` from `@backstage/backend-plugin-api`. This is not a breaking change as the `LoggerService` is a subset of the `Logger` interface. -- 5437fe488f: Migrated types related to `TokenManagerService`, `CacheService` and `DatabaseService` into backend-plugin-api. -- d592ec4f51: Updated the logger created by `createRootLogger` to make it possible to override the default `service` log label. -- b99c030f1b: Refactor to rely on `@backstage/backend-app-api` for the implementation of `createServiceBuilder`. -- f23eef3aa2: Updated dependency `better-sqlite3` to `^8.0.0`. -- Updated dependencies - - @backstage/backend-app-api@0.3.0-next.1 - - @backstage/backend-plugin-api@0.3.0-next.1 - - @backstage/cli-common@0.1.11 - - @backstage/config@1.0.6-next.0 - - @backstage/config-loader@1.1.8-next.0 - - @backstage/errors@1.1.4 - - @backstage/integration@1.4.2-next.0 - - @backstage/types@1.0.2 - -## 0.18.0-next.0 - -### Minor Changes - -- 5e2cebe9a3: **BREAKING**: Removed deprecated `read` method from the `UrlReader` interface. All implementations should use the `readUrl` method instead. - - Migrated `UrlReader` and related types to `backend/backend-plugin-api`, types remain re-exported from `backend-common` for now. - -### Patch Changes - -- 6f02d23b01: Moved `PluginEndpointDiscovery` type from backend-common to backend-plugin-api. -- Updated dependencies - - @backstage/backend-plugin-api@0.2.1-next.0 - - @backstage/config@1.0.6-next.0 - - @backstage/cli-common@0.1.11 - - @backstage/config-loader@1.1.8-next.0 - - @backstage/errors@1.1.4 - - @backstage/integration@1.4.2-next.0 - - @backstage/types@1.0.2 - -## 0.17.0 - -### Minor Changes - -- de8a975911: Changed to use native `AbortController` and `AbortSignal` from Node.js, instead - of the one from `node-abort-controller`. This is possible now that the minimum - supported Node.js version of the project is 16. - - Note that their interfaces are very slightly different, but typically not in a - way that matters to consumers. If you see any typescript errors as a direct - result from this, they are compatible with each other in the ways that we - interact with them, and should be possible to type-cast across without ill - effects. - -### Patch Changes - -- d3fea4ae0a: Internal fixes to avoid implicit usage of globals -- 98776e638a: Fixed GitlabUrlReader to include api tokens in API calls -- 1f2b2de3fe: exported KubernetesContainerRunner, KubernetesContainerRunnerOptions, KubernetesContainerRunnerMountBase -- 840f2113c6: Fix `GitlabUrlReader.readTree` bug when there were no matching commits -- 20a5161f04: Adds MySQL support for the catalog-backend -- 3280711113: Updated dependency `msw` to `^0.49.0`. -- 9ce7866ecd: Updated dependency `@kubernetes/client-node` to `0.18.0`. -- 3c1302c07d: Updated dependency `@types/http-errors` to `^2.0.0`. -- 6b82598bd8: Added the ability to understand Job Artifact URLs to the GitLab integration -- dfc8edf9c5: Internal refactor to avoid usage of deprecated symbols. -- 8015ff1258: Tweaked wording to use inclusive terminology -- 8646067e07: Fixed `SingleHostDiscovery` so that it properly handles single-string `backend.listen` configurations such as `:80`. -- Updated dependencies - - @backstage/errors@1.1.4 - - @backstage/config-loader@1.1.7 - - @backstage/integration@1.4.1 - - @backstage/types@1.0.2 - - @backstage/cli-common@0.1.11 - - @backstage/config@1.0.5 - -## 0.17.0-next.3 - -### Patch Changes - -- 840f2113c6: Fix `GitlabUrlReader.readTree` bug when there were no matching commits -- Updated dependencies - - @backstage/cli-common@0.1.11-next.0 - - @backstage/config@1.0.5-next.1 - - @backstage/config-loader@1.1.7-next.2 - - @backstage/errors@1.1.4-next.1 - - @backstage/integration@1.4.1-next.1 - - @backstage/types@1.0.2-next.1 - -## 0.17.0-next.2 - -### Patch Changes - -- 98776e638a: Fixed GitlabUrlReader to include api tokens in API calls -- 20a5161f04: Adds MySQL support for the catalog-backend -- 3c1302c07d: Updated dependency `@types/http-errors` to `^2.0.0`. -- 8015ff1258: Tweaked wording to use inclusive terminology -- Updated dependencies - - @backstage/cli-common@0.1.11-next.0 - - @backstage/config@1.0.5-next.1 - - @backstage/config-loader@1.1.7-next.2 - - @backstage/errors@1.1.4-next.1 - - @backstage/integration@1.4.1-next.1 - - @backstage/types@1.0.2-next.1 - -## 0.17.0-next.1 - -### Minor Changes - -- de8a975911: Changed to use native `AbortController` and `AbortSignal` from Node.js, instead - of the one from `node-abort-controller`. This is possible now that the minimum - supported Node.js version of the project is 16. - - Note that their interfaces are very slightly different, but typically not in a - way that matters to consumers. If you see any typescript errors as a direct - result from this, they are compatible with each other in the ways that we - interact with them, and should be possible to type-cast across without ill - effects. - -### Patch Changes - -- d3fea4ae0a: Internal fixes to avoid implicit usage of globals -- 1f2b2de3fe: exported KubernetesContainerRunner, KubernetesContainerRunnerOptions, KubernetesContainerRunnerMountBase -- 6b82598bd8: Added the ability to understand Job Artifact URLs to the GitLab integration -- 8646067e07: Fixed `SingleHostDiscovery` so that it properly handles single-string `backend.listen` configurations such as `:80`. -- Updated dependencies - - @backstage/types@1.0.2-next.1 - - @backstage/config-loader@1.1.7-next.1 - - @backstage/config@1.0.5-next.1 - - @backstage/integration@1.4.1-next.1 - - @backstage/cli-common@0.1.10 - - @backstage/errors@1.1.4-next.1 - -## 0.16.1-next.0 - -### Patch Changes - -- 3280711113: Updated dependency `msw` to `^0.49.0`. -- dfc8edf9c5: Internal refactor to avoid usage of deprecated symbols. -- Updated dependencies - - @backstage/config-loader@1.1.7-next.0 - - @backstage/integration@1.4.1-next.0 - - @backstage/types@1.0.2-next.0 - - @backstage/cli-common@0.1.10 - - @backstage/config@1.0.5-next.0 - - @backstage/errors@1.1.4-next.0 - -## 0.16.0 - -### Minor Changes - -- a7607b5413: **BREAKING CHANGE**: The `UrlReader` interface has been updated to require that `readUrl` is implemented. `readUrl` has previously been optional to implement but a warning has been logged when calling its predecessor `read`. - The `read` method is now deprecated and will be removed in a future release. - -### Patch Changes - -- 88f99b8b13: Bumped `tar` dependency to `^6.1.12` in order to ensure Node.js v18 compatibility. -- 55227712dd: Generated development HTTPS backend certificate is now checked for expiration date instead of file age. -- d05e1841ce: This patch adds GiteaURLReader to the available classes. It currently only reads single files via gitea's public repos api -- e6ced2446a: Change to using `@keyv/memcache` now that `keyv-memcache` is deprecated -- 210a3b5668: Small update to fix compatibility with newer versions of the `keyv` library -- cfb30b700c: Pin `@kubernetes/client-node` version to `0.17.0`. -- c1784a4980: Replaces in-code uses of `GitHub` with `Github` and deprecates old versions. -- Updated dependencies - - @backstage/integration@1.4.0 - - @backstage/types@1.0.1 - - @backstage/cli-common@0.1.10 - - @backstage/config@1.0.4 - - @backstage/config-loader@1.1.6 - - @backstage/errors@1.1.3 - -## 0.16.0-next.1 - -### Patch Changes - -- 88f99b8b13: Bumped `tar` dependency to `^6.1.12` in order to ensure Node.js v18 compatibility. -- cfb30b700c: Pin `@kubernetes/client-node` version to `0.17.0`. -- Updated dependencies - - @backstage/cli-common@0.1.10 - - @backstage/config@1.0.4-next.0 - - @backstage/config-loader@1.1.6-next.0 - - @backstage/errors@1.1.3-next.0 - - @backstage/integration@1.4.0-next.0 - - @backstage/types@1.0.1-next.0 - -## 0.16.0-next.0 - -### Minor Changes - -- a7607b5413: **BREAKING CHANGE**: The `UrlReader` interface has been updated to require that `readUrl` is implemented. `readUrl` has previously been optional to implement but a warning has been logged when calling its predecessor `read`. - The `read` method is now deprecated and will be removed in a future release. - -### Patch Changes - -- 55227712dd: Generated development HTTPS backend certificate is now checked for expiration date instead of file age. -- d05e1841ce: This patch adds GiteaURLReader to the available classes. It currently only reads single files via gitea's public repos api -- 210a3b5668: Small update to fix compatibility with newer versions of the `keyv` library -- c1784a4980: Replaces in-code uses of `GitHub` with `Github` and deprecates old versions. -- Updated dependencies - - @backstage/integration@1.4.0-next.0 - - @backstage/types@1.0.1-next.0 - - @backstage/cli-common@0.1.10 - - @backstage/config@1.0.4-next.0 - - @backstage/config-loader@1.1.6-next.0 - - @backstage/errors@1.1.3-next.0 - -## 0.15.2 - -### Patch Changes - -- e8d7976413: Added back support for when no branch is provided for the Bitbucket Server `UrlReader` -- c44cf412de: Fix BitBucket server integration -- c31f7cdfbc: Fixed an issue where `getClient()` for a `pluginId` would return different clients and not share them -- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` -- Updated dependencies - - @backstage/cli-common@0.1.10 - - @backstage/config@1.0.3 - - @backstage/config-loader@1.1.5 - - @backstage/errors@1.1.2 - - @backstage/integration@1.3.2 - - @backstage/types@1.0.0 - -## 0.15.2-next.2 - -### Patch Changes - -- c44cf412de: Fix BitBucket server integration -- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` -- Updated dependencies - - @backstage/cli-common@0.1.10 - - @backstage/config@1.0.3-next.2 - - @backstage/config-loader@1.1.5-next.2 - - @backstage/errors@1.1.2-next.2 - - @backstage/integration@1.3.2-next.2 - - @backstage/types@1.0.0 - -## 0.15.2-next.1 - -### Patch Changes - -- c31f7cdfbc: Fixed an issue where `getClient()` for a `pluginId` would return different clients and not share them -- Updated dependencies - - @backstage/cli-common@0.1.10 - - @backstage/config@1.0.3-next.1 - - @backstage/config-loader@1.1.5-next.1 - - @backstage/errors@1.1.2-next.1 - - @backstage/integration@1.3.2-next.1 - - @backstage/types@1.0.0 - -## 0.15.2-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/cli-common@0.1.10 - - @backstage/config@1.0.3-next.0 - - @backstage/config-loader@1.1.5-next.0 - - @backstage/errors@1.1.2-next.0 - - @backstage/integration@1.3.2-next.0 - - @backstage/types@1.0.0 - -## 0.15.1 - -### Patch Changes - -- 399286d7dd: Workaround support for `swc` instead of `sucrase` -- eadf56bbbf: Bump `git-url-parse` version to `^13.0.0` -- c3c90280be: Added a keep-alive refresh loop to the `DatabaseManager`, keeping the connection - pool up. -- c3c90280be: The options part of `DatabaseManager.fromConfig` now accepts an optional logger - field. -- 3d4f5daadf: Remove use of deprecated trimLeft/trimRight -- bf3cc134eb: Implemented KubernetesContainerRunner: a ContainerRunner implementation that leverages Jobs on a kubernetes cluster - - ```ts - const kubeConfig = new KubeConfig(); - kubeConfig.loadFromDefault(); - - const options: KubernetesContainerRunnerOptions = { - kubeConfig, - // namespace where Jobs will be created - namespace: 'default', - // Jobs name will be prefixed with this name - name: 'my-runner', - // An existing Kubernetes volume that will be used - // as base for mounts - mountBase: { - volumeName: 'workdir', - // Every mount must start with the base path - // see example below - basePath: '/workdir', - }, - // Define a Pod template for the Jobs. It has to include - // a volume definition named as the mountBase volumeName - podTemplate: { - spec: { - containers: [], - volumes: [ - { - name: 'workdir', - persistentVolumeClaim: { - claimName: 'workdir-claim', - }, - }, - ], - }, - }, - }; - const containerRunner = new KubernetesContainerRunner(options); - - const runOptions: RunContainerOptions = { - imageName: 'golang:1.17', - args: ['echo', 'hello world'], - mountDirs: { - '/workdir/app': '/app', - }, - }; - containerRunner.runContainer(runOptions); - ``` - -- e3b1993788: Added port ranges in allowed hosts: - - ```yaml - reading: - allow: - - host: *.examples.org:900-1000 - ``` - -- 2f52e74b49: Got rid of usages of the uppercase String type -- 60b85d8ade: Updated dependency `helmet` to `^6.0.0`. - - Please note that these policies are no longer applied by default: - - helmet.contentSecurityPolicy no longer sets block-all-mixed-content directive by default - helmet.expectCt is no longer set by default. It can, however, be explicitly enabled. It will be removed in Helmet 7. - -- 667d917488: Updated dependency `msw` to `^0.47.0`. -- 87ec2ba4d6: Updated dependency `msw` to `^0.46.0`. -- bf5e9030eb: Updated dependency `msw` to `^0.45.0`. -- 709f468330: The `branch` command has been added to the `isomorphic-git` wrapper. -- 0c780278e0: Fix for entries being skipped or incomplete when reading large zip archives. -- 96689fbdcb: Workaround for a rare race condition in tests. -- Updated dependencies - - @backstage/integration@1.3.1 - - @backstage/config-loader@1.1.4 - - @backstage/cli-common@0.1.10 - - @backstage/config@1.0.2 - - @backstage/errors@1.1.1 - -## 0.15.1-next.3 - -### Patch Changes - -- 96689fbdcb: Workaround for a rare race condition in tests. -- Updated dependencies - - @backstage/config-loader@1.1.4-next.2 - - @backstage/cli-common@0.1.10-next.0 - - @backstage/config@1.0.2-next.0 - - @backstage/errors@1.1.1-next.0 - - @backstage/integration@1.3.1-next.2 - -## 0.15.1-next.2 - -### Patch Changes - -- eadf56bbbf: Bump `git-url-parse` version to `^13.0.0` -- 3d4f5daadf: Remove use of deprecated trimLeft/trimRight -- bf3cc134eb: Implemented KubernetesContainerRunner: a ContainerRunner implementation that leverages Jobs on a kubernetes cluster - - ```ts - const kubeConfig = new KubeConfig(); - kubeConfig.loadFromDefault(); - - const options: KubernetesContainerRunnerOptions = { - kubeConfig, - // namespace where Jobs will be created - namespace: 'default', - // Jobs name will be prefixed with this name - name: 'my-runner', - // An existing Kubernetes volume that will be used - // as base for mounts - mountBase: { - volumeName: 'workdir', - // Every mount must start with the base path - // see example below - basePath: '/workdir', - }, - // Define a Pod template for the Jobs. It has to include - // a volume definition named as the mountBase volumeName - podTemplate: { - spec: { - containers: [], - volumes: [ - { - name: 'workdir', - persistentVolumeClaim: { - claimName: 'workdir-claim', - }, - }, - ], - }, - }, - }; - const containerRunner = new KubernetesContainerRunner(options); - - const runOptions: RunContainerOptions = { - imageName: 'golang:1.17', - args: ['echo', 'hello world'], - mountDirs: { - '/workdir/app': '/app', - }, - }; - containerRunner.runContainer(runOptions); - ``` - -- e3b1993788: Added port ranges in allowed hosts: - - ```yaml - reading: - allow: - - host: *.examples.org:900-1000 - ``` - -- 2f52e74b49: Got rid of usages of the uppercase String type -- 667d917488: Updated dependency `msw` to `^0.47.0`. -- 87ec2ba4d6: Updated dependency `msw` to `^0.46.0`. -- Updated dependencies - - @backstage/integration@1.3.1-next.1 - - @backstage/config-loader@1.1.4-next.1 - -## 0.15.1-next.1 - -### Patch Changes - -- c3c90280be: Added a keep-alive refresh loop to the `DatabaseManager`, keeping the connection - pool up. -- c3c90280be: The options part of `DatabaseManager.fromConfig` now accepts an optional logger - field. -- 60b85d8ade: Updated dependency `helmet` to `^6.0.0`. - - Please note that these policies are no longer applied by default: - - helmet.contentSecurityPolicy no longer sets block-all-mixed-content directive by default - helmet.expectCt is no longer set by default. It can, however, be explicitly enabled. It will be removed in Helmet 7. - -## 0.15.1-next.0 - -### Patch Changes - -- 399286d7dd: Workaround support for `swc` instead of `sucrase` -- bf5e9030eb: Updated dependency `msw` to `^0.45.0`. -- Updated dependencies - - @backstage/config-loader@1.1.4-next.0 - - @backstage/integration@1.3.1-next.0 - -## 0.15.0 - -### Minor Changes - -- 12e9b54f0e: Added back support for when no branch is provided to the `UrlReader` for Bitbucket Server -- 30012e7d8c: - Added `force` and `remoteRef` option to `push` method in `git` actions - - Added `addRemote` and `deleteRemote` methods to `git` actions - -### Patch Changes - -- fc8a5f797b: Improve `scm/git` wrapper around `isomorphic-git` library : - - - Add `checkout` function, - - Add optional `remoteRef` parameter in the `push` function. - -- 5e4dc173f7: Added a second validation to the `dir()` method of ZIP archive responses returned from `readTree()` that ensures that extracted files do not fall outside the target directory. -- 1732a18a7a: Exported `redactLogLine` function to be able to use it in custom loggers and renamed it to `redactWinstonLogLine`. -- 3b7930b3e5: Add support for Bearer Authorization header / token-based auth at Git commands. -- cfa078e255: The `ZipArchiveResponse` now correctly handles corrupt ZIP archives. - - Before this change, certain corrupt ZIP archives either cause the inflater to throw (as expected), or will hang the parser indefinitely. - - By switching out the `zip` parsing library, we now write to a temporary directory, and load from disk which should ensure that the parsing of the `.zip` files are done correctly because `streaming` of `zip` paths is technically impossible without being able to parse the headers at the end of the file. - -- 770d3f92c4: The config prop `ensureExists` now applies to schema creation when `pluginDivisionMode` is set to `schema`. This means schemas will no longer accidentally be automatically created when `ensureExists` is set to `false`. -- 29f782eb37: Updated dependency `@types/luxon` to `^3.0.0`. -- Updated dependencies - - @backstage/integration@1.3.0 - -## 0.15.0-next.2 - -### Patch Changes - -- 5e4dc173f7: Added a second validation to the `dir()` method of ZIP archive responses returned from `readTree()` that ensures that extracted files do not fall outside the target directory. - -## 0.15.0-next.1 - -### Patch Changes - -- 1732a18a7a: Exported `redactLogLine` function to be able to use it in custom loggers and renamed it to `redactWinstonLogLine`. -- Updated dependencies - - @backstage/integration@1.3.0-next.1 - -## 0.15.0-next.0 - -### Minor Changes - -- 12e9b54f0e: Added back support for when no branch is provided to the `UrlReader` for Bitbucket Server -- 30012e7d8c: - Added `force` and `remoteRef` option to `push` method in `git` actions - - Added `addRemote` and `deleteRemote` methods to `git` actions - -### Patch Changes - -- fc8a5f797b: Improve `scm/git` wrapper around `isomorphic-git` library : - - - Add `checkout` function, - - Add optional `remoteRef` parameter in the `push` function. - -- 3b7930b3e5: Add support for Bearer Authorization header / token-based auth at Git commands. -- cfa078e255: The `ZipArchiveResponse` now correctly handles corrupt ZIP archives. - - Before this change, certain corrupt ZIP archives either cause the inflater to throw (as expected), or will hang the parser indefinitely. - - By switching out the `zip` parsing library, we now write to a temporary directory, and load from disk which should ensure that the parsing of the `.zip` files are done correctly because `streaming` of `zip` paths is technically impossible without being able to parse the headers at the end of the file. - -- 770d3f92c4: The config prop `ensureExists` now applies to schema creation when `pluginDivisionMode` is set to `schema`. This means schemas will no longer accidentally be automatically created when `ensureExists` is set to `false`. -- 29f782eb37: Updated dependency `@types/luxon` to `^3.0.0`. -- Updated dependencies - - @backstage/integration@1.3.0-next.0 - -## 0.14.1 - -### Patch Changes - -- b1edb5cfd9: Fix parsing of S3 URLs for the default region. -- c3cfc83af2: Updated JSDoc to be MDX compatible. -- e57180e45e: Added some more information to the error messages for `isomorphic-git` errors -- 1f75dfac29: Fix edge case bug when gitlab relativePath is repeated in the target URL. -- 90c87f28e8: Moving from Bitbucket Server endpoint from https://docs.atlassian.com/bitbucket-server/rest/7.9.0/bitbucket-rest.html#idp222 to https://docs.atlassian.com/bitbucket-server/rest/7.9.0/bitbucket-rest.html#idp224, to have the last commit in function of different branch, and not only the list of default branch -- 9de15a41d7: Upgrade @octokit/rest to 19.0.3 -- 0fc57887e8: Improve plural handling in logging output for secrets -- a70869e775: Updated dependency `msw` to `^0.43.0`. -- 4e9a90e307: Updated dependency `luxon` to `^3.0.0`. -- 8006d0f9bf: Updated dependency `msw` to `^0.44.0`. -- 679b32172e: Updated dependency `knex` to `^2.0.0`. -- e2d7b76f43: Upgrade git-url-parse to 12.0.0. - - Motivation for upgrade is transitively upgrading parse-url which is vulnerable - to several CVEs detected by Snyk. - - - SNYK-JS-PARSEURL-2935944 - - SNYK-JS-PARSEURL-2935947 - - SNYK-JS-PARSEURL-2936249 - -- 954a94f52f: Support self-hosted gitlab installations with relative URL. -- Updated dependencies - - @backstage/config-loader@1.1.3 - - @backstage/integration@1.2.2 - - @backstage/errors@1.1.0 - -## 0.14.1-next.3 - -### Patch Changes - -- 90c87f28e8: Moving from Bitbucket Server endpoint from https://docs.atlassian.com/bitbucket-server/rest/7.9.0/bitbucket-rest.html#idp222 to https://docs.atlassian.com/bitbucket-server/rest/7.9.0/bitbucket-rest.html#idp224, to have the last commit in function of different branch, and not only the list of default branch -- a70869e775: Updated dependency `msw` to `^0.43.0`. -- 4e9a90e307: Updated dependency `luxon` to `^3.0.0`. -- Updated dependencies - - @backstage/config-loader@1.1.3-next.1 - - @backstage/integration@1.2.2-next.3 - -## 0.14.1-next.2 - -### Patch Changes - -- 679b32172e: Updated dependency `knex` to `^2.0.0`. -- e2d7b76f43: Upgrade git-url-parse to 12.0.0. - - Motivation for upgrade is transitively upgrading parse-url which is vulnerable - to several CVEs detected by Snyk. - - - SNYK-JS-PARSEURL-2935944 - - SNYK-JS-PARSEURL-2935947 - - SNYK-JS-PARSEURL-2936249 - -- Updated dependencies - - @backstage/integration@1.2.2-next.2 - -## 0.14.1-next.1 - -### Patch Changes - -- 0fc57887e8: Improve plural handling in logging output for secrets -- Updated dependencies - - @backstage/errors@1.1.0-next.0 - - @backstage/integration@1.2.2-next.1 - - @backstage/config-loader@1.1.3-next.0 - -## 0.14.1-next.0 - -### Patch Changes - -- b1edb5cfd9: Fix parsing of S3 URLs for the default region. -- c3cfc83af2: Updated JSDoc to be MDX compatible. -- Updated dependencies - - @backstage/integration@1.2.2-next.0 - -## 0.14.0 - -### Minor Changes - -- 55647ec7df: **BREAKING**: Server-to-server tokens that are authenticated by the `ServerTokenManager` now must have an `exp` claim that has not expired. Tokens where the `exp` claim is in the past or missing are considered invalid and will throw an error. This is a followup to the deprecation from the `1.2` release of Backstage where perpetual tokens were deprecated. Be sure to update any usage of the `getToken()` method to have it be called every time a token is needed. Do not store tokens for later use. - -### Patch Changes - -- f72a6b8c62: Applied the `luxon` dependency fix from the `0.13.4` patch release. -- 5b22a8c97f: Applied the AWS S3 reading patch from the `0.13.5` patch release. -- f5283a42e2: Updated dependency `@google-cloud/storage` to `^6.0.0`. -- 8f7b1835df: Updated dependency `msw` to `^0.41.0`. -- Updated dependencies - - @backstage/integration@1.2.1 - - @backstage/config-loader@1.1.2 - -## 0.14.0-next.2 - -### Minor Changes - -- 55647ec7df: **BREAKING**: Server-to-server tokens that are authenticated by the `ServerTokenManager` now must have an `exp` claim that has not expired. Tokens where the `exp` claim is in the past or missing are considered invalid and will throw an error. This is a followup to the deprecation from the `1.2` release of Backstage where perpetual tokens were deprecated. Be sure to update any usage of the `getToken()` method to have it be called every time a token is needed. Do not store tokens for later use. - -### Patch Changes - -- Updated dependencies - - @backstage/integration@1.2.1-next.2 - -## 0.13.6-next.1 - -### Patch Changes - -- 8f7b1835df: Updated dependency `msw` to `^0.41.0`. -- Updated dependencies - - @backstage/config-loader@1.1.2-next.0 - - @backstage/integration@1.2.1-next.1 - -## 0.13.6-next.0 - -### Patch Changes - -- f72a6b8c62: Applied the `luxon` dependency fix from the `0.13.4` patch release. -- 5b22a8c97f: Applied the AWS S3 reading patch from the `0.13.5` patch release. -- Updated dependencies - - @backstage/integration@1.2.1-next.0 - -## 0.13.5 - -### Patch Changes - -- 667d2ed6f8: Fix a bug in the URL Reading towards AWS S3 where it would hang indefinitely. - -## 0.13.4 - -### Patch Changes - -- 739be2b079: Fixed potential crash by bumping the `luxon` dependency to `^2.3.1`. - -## 0.13.3 - -### Patch Changes - -- e0a6360b80: Added a `stream()` method to complement the `buffer()` method on `ReadUrlResponse`. A `ReadUrlResponseFactory` utility class is now also available, providing a simple, consistent way to provide a valid `ReadUrlResponse`. - - This method, though optional for now, will be required on the responses of `UrlReader.readUrl()` implementations in a future release. - -- 4b811aafce: Implemented the `UrlReader.search()` method for Google Cloud Storage. Due to limitations in the underlying storage API, only prefix-based searches are supported right now (for example, `https://storage.cloud.google.com/your-bucket/some-path/*`). -- 6673babab9: Gerrit integration: Added optional `cloneUrl` string to config. -- 75bf9e1da9: Split BitbucketUrlReader into BitbucketCloudUrlReader and BitbucketServerUrlReader. Backwards compatible. -- 28b0e4ddef: Update types to match the new version of `@keyv/redis` -- 5fcbd86960: **DEPRECATION**: Server-to-server authentication tokens issued from a - `TokenManager` (specifically, `ServerTokenManager`) now has an expiry time set, - for one hour in the future from when issued. This improves security. The ability - to pass in and validate tokens that either have a missing `exp` claim, or an - `exp` claim that expired in the past, is now deprecated. Trying to do so will - lead to logged warnings, and in a future release will instead lead to errors. - - It was always the case that users of this interface were expected to call its - `getToken()` method for every outgoing call and never hold on to any given token - for reuse. But this now has become even more important advice to heed, and you - should verify that you do not hold on to and reuse tokens such as these in your - own code. - -- cfc0f19699: Updated dependency `fs-extra` to `10.1.0`. -- 9ec4e0613e: Update to `jose` 4.6.0 -- Updated dependencies - - @backstage/integration@1.2.0 - - @backstage/cli-common@0.1.9 - - @backstage/config@1.0.1 - - @backstage/config-loader@1.1.1 - -## 0.13.3-next.2 - -### Patch Changes - -- e0a6360b80: Added a `stream()` method to complement the `buffer()` method on `ReadUrlResponse`. A `ReadUrlResponseFactory` utility class is now also available, providing a simple, consistent way to provide a valid `ReadUrlResponse`. - - This method, though optional for now, will be required on the responses of `UrlReader.readUrl()` implementations in a future release. - -- 4b811aafce: Implemented the `UrlReader.search()` method for Google Cloud Storage. Due to limitations in the underlying storage API, only prefix-based searches are supported right now (for example, `https://storage.cloud.google.com/your-bucket/some-path/*`). -- Updated dependencies - - @backstage/cli-common@0.1.9-next.0 - - @backstage/config@1.0.1-next.0 - - @backstage/config-loader@1.1.1-next.1 - - @backstage/integration@1.2.0-next.1 - -## 0.13.3-next.1 - -### Patch Changes - -- 28b0e4ddef: Update types to match the new version of `@keyv/redis` - -## 0.13.3-next.0 - -### Patch Changes - -- 6673babab9: Gerrit integration: Added optional `cloneUrl` string to config. -- 75bf9e1da9: Split BitbucketUrlReader into BitbucketCloudUrlReader and BitbucketServerUrlReader. Backwards compatible. -- cfc0f19699: Updated dependency `fs-extra` to `10.1.0`. -- 9ec4e0613e: Update to `jose` 4.6.0 -- Updated dependencies - - @backstage/integration@1.2.0-next.0 - - @backstage/config-loader@1.1.1-next.0 - -## 0.13.2 - -### Patch Changes - -- 19f6c6c32a: The backend will no longer fail to start up when configured secrets do not match the configuration schema. -- b7436743cb: Added the GerritUrlReader that implements "readUrl". -- 3ef123bbf0: Support external ID when assuming roles in S3 integration - - In order to assume a role created by a 3rd party as external - ID is needed. This change adds an optional field to the s3 - integration configuration and consumes that in the AwsS3UrlReader. - -- bae9359032: The logger returned from `getVoidLogger` is now uses a silenced console transport instead. -- 3ff0e79654: Tweaked the `UrlReader` multiplexer so that it uses the more helpful `NotAllowedError` messaging for all methods. -- 12608f8ba8: Add `@types/webpack-env` to dependencies. -- f9f512559b: Updated the visibility of database connection fields in config to be secret -- Updated dependencies - - @backstage/integration@1.1.0 - - @backstage/config-loader@1.1.0 - -## 0.13.2-next.2 - -### Patch Changes - -- 19f6c6c32a: The backend will no longer fail to start up when configured secrets do not match the configuration schema. -- Updated dependencies - - @backstage/config-loader@1.1.0-next.1 - - @backstage/integration@1.1.0-next.2 - -## 0.13.2-next.1 - -### Patch Changes - -- b7436743cb: Added the GerritUrlReader that implements "readUrl". -- bae9359032: The logger returned from `getVoidLogger` is now uses a silenced console transport instead. -- Updated dependencies - - @backstage/integration@1.1.0-next.1 - -## 0.13.2-next.0 - -### Patch Changes - -- 3ef123bbf0: Support external ID when assuming roles in S3 integration - - In order to assume a role created by a 3rd party as external - ID is needed. This change adds an optional field to the s3 - integration configuration and consumes that in the AwsS3UrlReader. - -- f9f512559b: Updated the visibility of database connection fields in config to be secret -- Updated dependencies - - @backstage/config-loader@1.0.1-next.0 - - @backstage/integration@1.0.1-next.0 - -## 0.13.1 - -### Patch Changes - -- efc73db10c: Use `better-sqlite3` instead of `@vscode/sqlite3` -- f24ef7864e: Minor typo fixes -- b66f70180f: Fix handling of bucket names with dots, in `AwsS3UrlReader` -- Updated dependencies - - @backstage/config-loader@1.0.0 - - @backstage/integration@1.0.0 - - @backstage/config@1.0.0 - - @backstage/errors@1.0.0 - - @backstage/types@1.0.0 - -## 0.13.0 - -### Minor Changes - -- ae9d6fb3df: **BREAKING**: - - - Removed the (since way back) deprecated `createDatabase` export, please use `createDatabaseClient` instead. - - Removed the (since way back) deprecated `SingleConnectionDatabaseManager` export, please use `DatabaseManager` instead. - -### Patch Changes - -- ab7cd7d70e: Do some groundwork for supporting the `better-sqlite3` driver, to maybe eventually replace `@vscode/sqlite3` (#9912) -- e0a69ba49f: build(deps): bump `fs-extra` from 9.1.0 to 10.0.1 -- aefca2a7e9: add support for ETag at `BitbucketUrlReader.readUrl` -- 3c2bc73901: Use `setupRequestMockHandlers` from `@backstage/backend-test-utils` -- b1aacbf96a: Applied the fix for the `/alpha` entry point resolution that was part of the `v0.70.1` release of Backstage. -- Updated dependencies - - @backstage/config-loader@0.9.7 - -## 0.13.0-next.0 - -### Minor Changes - -- ae9d6fb3df: **BREAKING**: - - - Removed the (since way back) deprecated `createDatabase` export, please use `createDatabaseClient` instead. - - Removed the (since way back) deprecated `SingleConnectionDatabaseManager` export, please use `DatabaseManager` instead. - -### Patch Changes - -- ab7cd7d70e: Do some groundwork for supporting the `better-sqlite3` driver, to maybe eventually replace `@vscode/sqlite3` (#9912) -- e0a69ba49f: build(deps): bump `fs-extra` from 9.1.0 to 10.0.1 -- aefca2a7e9: add support for ETag at `BitbucketUrlReader.readUrl` -- 3c2bc73901: Use `setupRequestMockHandlers` from `@backstage/backend-test-utils` -- b1aacbf96a: Applied the fix for the `/alpha` entry point resolution that was part of the `v0.70.1` release of Backstage. -- Updated dependencies - - @backstage/config-loader@0.9.7-next.0 - -## 0.12.1 - -### Patch Changes - -- Fixed runtime resolution of the `/alpha` entry point. - -## 0.12.0 - -### Minor Changes - -- 9a0510144f: **BREAKING**: The connection string for `redis` cache store now requires a protocol prefix. - - ```diff - backend: - cache: - store: redis - - connection: user:pass@cache.example.com:6379 - + connection: redis://user:pass@cache.example.com:6379 - ``` - -### Patch Changes - -- 0df6077ab5: DockerContainerRunner.runContainer now automatically removes the container when its execution terminates -- 34af86517c: ensure `apiBaseUrl` being set for Bitbucket integrations, replace hardcoded defaults -- b838717e92: Export FetchUrlReader to facilitate more flexible configuration of the backend. -- Updated dependencies - - @backstage/integration@0.8.0 - -## 0.11.0 - -### Minor Changes - -- 7d12e4cf32: feat(backend-common): add Redis backed cache store - -### Patch Changes - -- b2f8bb99d3: Make backend.auth.keys optional in config schema. Previously backend.auth was optional but keys was not, which meant that if another plugin introduced additional properties under backend.auth, it would implicitly make backend.auth.keys mandatory. -- d64b8d3678: chore(deps): bump `minimatch` from 3.0.4 to 5.0.0 -- Updated dependencies - - @backstage/config-loader@0.9.6 - - @backstage/integration@0.7.5 - -## 0.10.9 - -### Patch Changes - -- Fix for the previous release with missing type declarations. -- Updated dependencies - - @backstage/cli-common@0.1.8 - - @backstage/config@0.1.15 - - @backstage/config-loader@0.9.5 - - @backstage/errors@0.2.2 - - @backstage/integration@0.7.4 - - @backstage/types@0.1.3 - -## 0.10.8 - -### Patch Changes - -- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 -- c77c5c7eb6: Added `backstage.role` to `package.json` -- 0107c9aa08: chore(deps): bump `helmet` from 4.4.1 to 5.0.2 -- b590e9b58d: Updated `isDatabaseConflictError` to handle modern sqlite conflict errors -- Updated dependencies - - @backstage/config-loader@0.9.4 - - @backstage/errors@0.2.1 - - @backstage/integration@0.7.3 - - @backstage/cli-common@0.1.7 - - @backstage/config@0.1.14 - - @backstage/types@0.1.2 - -## 0.10.7 - -### Patch Changes - -- 2441d1cf59: chore(deps): bump `knex` from 0.95.6 to 1.0.2 - - This also replaces `sqlite3` with `@vscode/sqlite3` 5.0.7 - -- 599f3dfa83: chore(deps-dev): bump `@types/concat-stream` from 1.6.1 to 2.0.0 -- c3868458d8: Removed unnecessary `get-port` dependency -- 04398e946e: Bump `selfsigned` to 2.0.0 - -## 0.10.7-next.0 - -### Patch Changes - -- 2441d1cf59: chore(deps): bump `knex` from 0.95.6 to 1.0.2 - - This also replaces `sqlite3` with `@vscode/sqlite3` 5.0.7 - -- 599f3dfa83: chore(deps-dev): bump `@types/concat-stream` from 1.6.1 to 2.0.0 -- c3868458d8: Removed unnecessary `get-port` dependency - -## 0.10.6 - -### Patch Changes - -- 50d039577a: Added a `Context` type for the backend, that can propagate an abort signal, a - deadline, and contextual values through the call stack. The main entrypoint is - the `Contexts` utility class that provides a root context creator and commonly - used decorators. - - These are marked as `@alpha` for now, and are therefore only accessible via - `@backstage/backend-common/alpha`. - -## 0.10.6-next.0 - -### Patch Changes - -- 50d039577a: Added a `Context` type for the backend, that can propagate an abort signal, a - deadline, and contextual values through the call stack. The main entrypoint is - the `Contexts` utility class that provides a root context creator and commonly - used decorators. - - These are marked as `@alpha` for now, and are therefore only accessible via - `@backstage/backend-common/alpha`. - -## 0.10.5 - -### Patch Changes - -- de9d7eba63: Fixed configuration schema incorrectly declaring `backend.listen.address` to exist, rather than `backend.listen.host`, which is the correct key. - -## 0.10.4 - -### Patch Changes - -- f685e1398f: Loading of app configurations now reference the `@deprecated` construct from - JSDoc to determine if a property in-use has been deprecated. Users are notified - of deprecated keys in the format: - - ```txt - The configuration key 'catalog.processors.githubOrg' of app-config.yaml is deprecated and may be removed soon. Configure a GitHub integration instead. - ``` - - When the `withDeprecatedKeys` option is set to `true` in the `process` method - of `loadConfigSchema`, the user will be notified that deprecated keys have been - identified in their app configuration. - - The `backend-common` and `plugin-app-backend` packages have been updated to set - `withDeprecatedKeys` to true so that users are notified of deprecated settings - by default. - -- Updated dependencies - - @backstage/integration@0.7.2 - - @backstage/config@0.1.13 - - @backstage/config-loader@0.9.3 - -## 0.10.4-next.0 - -### Patch Changes - -- f685e1398f: Loading of app configurations now reference the `@deprecated` construct from - JSDoc to determine if a property in-use has been deprecated. Users are notified - of deprecated keys in the format: - - ```txt - The configuration key 'catalog.processors.githubOrg' of app-config.yaml is deprecated and may be removed soon. Configure a GitHub integration instead. - ``` - - When the `withDeprecatedKeys` option is set to `true` in the `process` method - of `loadConfigSchema`, the user will be notified that deprecated keys have been - identified in their app configuration. - - The `backend-common` and `plugin-app-backend` packages have been updated to set - `withDeprecatedKeys` to true so that users are notified of deprecated settings - by default. - -- Updated dependencies - - @backstage/config@0.1.13-next.0 - - @backstage/config-loader@0.9.3-next.0 - - @backstage/integration@0.7.2-next.0 - -## 0.10.3 - -### Patch Changes - -- 5b406daabe: build(deps-dev): bump `http-errors` from 1.8.0 to 2.0.0 -- 5333451def: Cleaned up API exports -- db5310e25e: bump `logform` to use fixed version of `color` dependency -- 7946418729: Switched to using `@manypkg/get-packages` to list monorepo packages, which provides better support for different kind of monorepo setups. -- 3b4d8caff6: The GithubUrlReader is switched to use the DefaultGithubCredentialsProvider -- f77bd5c8ff: Clean up API reports -- Updated dependencies - - @backstage/config@0.1.12 - - @backstage/integration@0.7.1 - - @backstage/errors@0.2.0 - - @backstage/config-loader@0.9.2 - -## 0.10.2 - -### Patch Changes - -- 21ae56168e: Updated the Git class with the following: - - - Added `depth` and `noCheckout` options to Git clone, using these you can create a bare clone that includes just the git history - - New `log` function which you can use to view the commit history of a git repo - -- eacc582473: Reverted the default CSP configuration to include `'unsafe-eval'` again, which was mistakenly removed in the previous version. - -## 0.10.1 - -### Patch Changes - -- 94cdf5d1bd: In-memory cache clients instantiated from the same cache manager now share the same memory space. -- 916b2f1f3e: Use the default CSP policy provided by `helmet` directly rather than a copy. -- 7d4b4e937c: Uptake changes to the GitHub Credentials Provider interface. -- 995e4c7d9d: Added support for non-"amazonaws.com" hosts (for example when testing with LocalStack) in AwsS3UrlReader. -- Updated dependencies - - @backstage/integration@0.7.0 - - @backstage/config-loader@0.9.1 - -## 0.10.0 - -### Minor Changes - -- 2f8a9b665f: Auto-generate secrets for backend-to-backend auth in local development environments. - - When NODE_ENV is 'development', the ServerTokenManager will now generate a secret for backend-to-backend auth to make it simpler to work locally on Backstage instances that use backend-to-backend auth. For production deployments, a secret must still be manually configured as described in [the backend-to-backend auth tutorial](https://backstage.io/docs/tutorials/backend-to-backend-auth). - - After the change, the static `fromConfig` method on the `ServerTokenManager` requires a logger. - - ```diff - - const tokenManager = ServerTokenManager.fromConfig(config); - + const tokenManager = ServerTokenManager.fromConfig(config, { logger: root }); - ``` - -### Patch Changes - -- 776180b740: Fixed bug in backend-common to allow passing of remote option in order to enable passing remote url in --config option. The remote option should be passed along with reloadIntervalSeconds from packages/backend/src/index.ts (Updated the file as well) - - These changes are needed in `packages/backend/src/index.ts` if remote URLs are desired to be passed in --config option and read and watch remote files for config. - - ```diff - @@ -86,7 +86,11 @@ async function main() { - const config = await loadBackendConfig({ - argv: process.argv, - logger, - + remote: { - + reloadIntervalSeconds: 60 * 10 // Check remote config changes every 10 minutes. Change to your desired interval in seconds - + } - }); - + - const createEnv = makeCreateEnv(config); - - const healthcheckEnv = useHotMemoize(module, () => createEnv('healthcheck')); - ``` - -- 2462b9e275: Ensure temporary directories are cleaned up if an error is thrown in the `filter` callback of the `UrlReader.readTree` options. -- 2f6d8ec3b6: Updated the `ReadTreeResponse` documentation to clarify that the caller of `dir()` is responsible for removing the directory after use. -- Updated dependencies - - @backstage/config-loader@0.9.0 - -## 0.9.14 - -### Patch Changes - -- fe24bc9a32: Each plugin now saves to a separate sqlite database file when `connection.filename` is provided in the sqlite config. - Any existing sqlite database files will be ignored. - -## 0.9.13 - -### Patch Changes - -- dcd1a0c3f4: Minor improvement to the API reports, by not unpacking arguments directly -- 5a008576c4: Add possibility to use custom error handler -- 98a9c35f0c: Add options argument to support additional database migrations configuration -- 6298de32dd: Add knexConfig config section - -## 0.9.12 - -### Patch Changes - -- 905dd952ac: Create a `TokenManager` interface and `ServerTokenManager` implementation to generate and validate server tokens for authenticated backend-to-backend API requests. -- 6b500622d5: Move to using node-fetch internally instead of cross-fetch -- 54989b671d: Fixed a potential crash in the log redaction code -- Updated dependencies - - @backstage/integration@0.6.10 - - @backstage/config-loader@0.8.1 - -## 0.9.11 - -### Patch Changes - -- bab752e2b3: Change default port of backend from 7000 to 7007. - - This is due to the AirPlay Receiver process occupying port 7000 and preventing local Backstage instances on MacOS to start. - - You can change the port back to 7000 or any other value by providing an `app-config.yaml` with the following values: - - ``` - backend: - listen: 0.0.0.0:7123 - baseUrl: http://localhost:7123 - ``` - - More information can be found here: https://backstage.io/docs/conf/writing - -- Updated dependencies - - @backstage/errors@0.1.5 - -## 0.9.10 - -### Patch Changes - -- d7c1e0e34a: Added the `isDatabaseConflictError` function. -- e21e3c6102: Bumping minimum requirements for `dockerode` and `testcontainers` -- 1e99c73c75: Update internal usage of `configLoader.loadConfig` that now returns an object instead of an array of configs. -- 1daada3a06: Paths can be specified in backend.reading.allow to further restrict allowed targets -- 7ad9a07b27: Adding config prop `pluginDivisionMode` to allow plugins using the `pg` client to create their own management schemas in the db. This allows `pg` client plugins to work in separate schemas in the same db. -- 01f74aa878: Add `AbortSignal` support to `UrlReader` -- a8732a1200: Make sure that server builder `start()` propagates errors (such as failing to bind to the required port) properly and doesn't resolve the promise prematurely. - - After this change, the backend logger will be able to actually capture the error as it happens: - - ``` - 2021-11-11T10:54:21.334Z backstage info Initializing http server - 2021-11-11T10:54:21.335Z backstage error listen EADDRINUSE: address already in use :::7000 code=EADDRINUSE errno=-48 syscall=listen address=:: port=7000 - ``` - -- 26b5da1c1a: Do not redact empty or one-character strings. These imply that it's just a test or local dev, and unnecessarily ruin the log output. -- Updated dependencies - - @backstage/config-loader@0.8.0 - - @backstage/cli-common@0.1.6 - -## 0.9.9 - -### Patch Changes - -- 8c4cad0bf2: AWSS3UrlReader now throws a `NotModifiedError` (exported from @backstage/backend-common) when s3 returns a 304 response. -- 0611f3b3e2: Reading app config from a remote server -- Updated dependencies - - @backstage/config-loader@0.7.2 - -## 0.9.8 - -### Patch Changes - -- 96cfa561eb: Adjusted some API exports -- 10615525f3: Switch to use the json and observable types from `@backstage/types` -- 1be8d2abdb: Any set configurations which have been tagged with a visibility 'secret', are now redacted from log lines. -- Updated dependencies - - @backstage/config@0.1.11 - - @backstage/cli-common@0.1.5 - - @backstage/errors@0.1.4 - - @backstage/integration@0.6.9 - - @backstage/config-loader@0.7.1 - -## 0.9.7 - -### Patch Changes - -- be59619212: Add "rate limit exceeded" to error from GithubUrlReader if that is the cause of a read failure -- 36e67d2f24: Internal updates to apply more strict checks to throw errors. -- Updated dependencies - - @backstage/config-loader@0.7.0 - - @backstage/errors@0.1.3 - -## 0.9.6 - -### Patch Changes - -- 8f969d5a56: Correct error message typo -- a31afc5b62: Replace slash stripping regexp with trimEnd to remove CodeQL warning -- d7055285de: Add glob patterns support to config CORS options. It's possible to send patterns like: - - ```yaml - backend: - cors: - origin: - - https://*.my-domain.com - - http://localhost:700[0-9] - - https://sub-domain-+([0-9]).my-domain.com - ``` - -- Updated dependencies - - @backstage/config-loader@0.6.10 - - @backstage/integration@0.6.7 - - @backstage/cli-common@0.1.4 - -## 0.9.5 - -### Patch Changes - -- 8bb3c0a578: The `subscribe` method on the `Config` returned by `loadBackendConfig` is now forwarded through `getConfig` and `getOptionalConfig`. -- 0c8a59e293: Fix an issue where filtering in search doesn't work correctly for Bitbucket. -- Updated dependencies - - @backstage/integration@0.6.6 - - @backstage/config-loader@0.6.9 - -## 0.9.4 - -### Patch Changes - -- febddedcb2: Bump `lodash` to remediate `SNYK-JS-LODASH-590103` security vulnerability -- Updated dependencies - - @backstage/integration@0.6.5 - - @backstage/config@0.1.10 - -## 0.9.3 - -### Patch Changes - -- fab79adde1: Add AWS S3 Discovery Processor. Add readTree() to AwsS3UrlReader. Add ReadableArrayResponse type that implements ReadTreeResponse to use in AwsS3UrlReader's readTree() -- f7ad3a8925: Fix Azure `readTree` and `search` handling to properly support paths. -- 96fef17a18: Upgrade git-parse-url to v11.6.0 -- Updated dependencies - - @backstage/integration@0.6.4 - -## 0.9.2 - -### Patch Changes - -- 9e5ed27ec: Properly export all used types. -- Updated dependencies - - @backstage/cli-common@0.1.3 - - @backstage/config-loader@0.6.8 - - @backstage/errors@0.1.2 - - @backstage/config@0.1.9 - -## 0.9.1 - -### Patch Changes - -- 714a2a918: Export type that are needed to implement a new `UrlReader` -- Updated dependencies - - @backstage/integration@0.6.3 - -## 0.9.0 - -### Minor Changes - -- a365f1faf: The `ZipArchiveResponse` class now accepts an optional `stripFirstDirectory` parameter. Note that its default value is `false`, which leads to a breaking change in behaviour to previous versions of the class. If you use this class explicitly and want to retain the old behaviour, add a `true` parameter value to its constructor. - -### Patch Changes - -- Updated dependencies - - @backstage/integration@0.6.2 - - @backstage/config@0.1.8 - -## 0.8.10 - -### Patch Changes - -- 8543d9890: Add an optional `info` parameter to the `readTree` filter option with a `size` property. -- 4d909268c: Read responses in `UrlReader#read()` as array buffer instead of as text to allow reading non-text locations such as images. -- 9b4604b38: Add support for watching configuration by implementing the `subscribe` method in the configuration returned by `loadBackendConfig`. -- b8cb12009: Add AWS S3 URL Reader -- Updated dependencies - - @backstage/config@0.1.7 - - @backstage/config-loader@0.6.7 - - @backstage/integration@0.6.1 - -## 0.8.9 - -### Patch Changes - -- f7ce7c565: Use a more informative error message when URL reading isn't allowed due to no reader matching the target URL. -- ce1958021: Pass on credentials to the integrations package, so that it can properly pick the API route when using GitHub apps based auth -- Updated dependencies - - @backstage/integration@0.6.0 - -## 0.8.8 - -### Patch Changes - -- 6aa7c3db7: bump node-tar version to the latest -- Updated dependencies - - @backstage/config@0.1.6 - - @backstage/integration@0.5.9 - - @backstage/config-loader@0.6.6 - -## 0.8.7 - -### Patch Changes - -- f25357273: Implement the etag functionality in the `readUrl` method of `FetchUrlReader`. -- bdd6ab5f1: It's possible to customize the request logging handler when building the service. For example in your `backend` - - ``` - const service = createServiceBuilder(module) - .loadConfig(config) - .setRequestLoggingHandler((logger?: Logger): RequestHandler => { - const actualLogger = (logger || getRootLogger()).child({ - type: 'incomingRequest', - }); - return expressWinston.logger({ ... - ``` - -## 0.8.6 - -### Patch Changes - -- 5f6f2fd96: Support a `ensureExists` config option to skip ensuring a configured database exists. This allows deployment scenarios where - limited permissions are given for provisioned databases without privileges to create new databases. If set to `false`, the - database connection will not be validated prior to use which means the backend will not attempt to create the database if it - doesn't exist. You can configure this in your app-config.yaml: - - ```yaml - backend: - database: - ensureExists: false - ``` - - This defaults to `true` if unspecified. You can also configure this per plugin connection and will override the base option. - -- ad93bb035: Document the default behavior of `statusCheck` option in `createStatusCheckRouter`. -- ae84b20cf: Revert the upgrade to `fs-extra@10.0.0` as that seemed to have broken all installs inexplicably. -- Updated dependencies - - @backstage/config-loader@0.6.5 - -## 0.8.5 - -### Patch Changes - -- 09d3eb684: Added a `readUrl` method to the `UrlReader` interface that allows for complex response objects and is intended to replace the `read` method. This new method is currently optional to implement which allows for a soft migration to `readUrl` instead of `read` in the future. - - The main use case for `readUrl` returning an object instead of solely a read buffer is to allow for additional metadata such as ETag, which is a requirement for more efficient catalog processing. - - The `GithubUrlReader` and `GitlabUrlReader` readers fully implement `readUrl`. The other existing readers implement the new method but do not propagate or return ETags. - - While the `readUrl` method is not yet required, it will be in the future, and we already log deprecation warnings when custom `UrlReader` implementations that do not implement `readUrl` are used. We therefore recommend that any existing custom implementations are migrated to implement `readUrl`. - - The old `read` and the new `readUrl` methods can easily be implemented using one another, but we recommend moving the chunk of the implementation to the new `readUrl` method as `read` is being removed, for example this: - - ```ts - class CustomUrlReader implements UrlReader { - read(url: string): Promise { - const res = await fetch(url); - - if (!res.ok) { - // error handling ... - } - - return Buffer.from(await res.text()); - } - } - ``` - - Can be migrated to something like this: - - ```ts - class CustomUrlReader implements UrlReader { - read(url: string): Promise { - const res = await this.readUrl(url); - return res.buffer(); - } - - async readUrl( - url: string, - _options?: ReadUrlOptions, - ): Promise { - const res = await fetch(url); - - if (!res.ok) { - // error handling ... - } - - const buffer = Buffer.from(await res.text()); - return { buffer: async () => buffer }; - } - } - ``` - - While there is no usage of the ETag capability yet in the main Backstage packages, you can already add it to your custom implementations. To do so, refer to the documentation of the `readUrl` method and surrounding types, and the existing implementation in `packages/backend-common/src/reading/GithubUrlReader.ts`. - -- 6841e0113: fix minor version of git-url-parse as 11.5.x introduced a bug for Bitbucket Server -- c2db794f5: add defaultBranch property for publish GitHub action -- Updated dependencies - - @backstage/integration@0.5.8 - -## 0.8.4 - -### Patch Changes - -- 88d742eb8: Download archives as compressed tar files for GitLab to fix the `readTree` bug in TODO Plugin. -- ab5cc376f: Add new `isChildPath` and `resolveSafeChildPath` exports -- Updated dependencies - - @backstage/cli-common@0.1.2 - - @backstage/integration@0.5.7 - -## 0.8.3 - -### Patch Changes - -- e5cdf0560: Provide a more clear error message when database connection fails. -- 772dbdb51: Deprecates `SingleConnectionDatabaseManager` and provides an API compatible database - connection manager, `DatabaseManager`, which allows developers to configure database - connections on a per plugin basis. - - The `backend.database` config path allows you to set `prefix` to use an - alternate prefix for automatically generated database names, the default is - `backstage_plugin_`. Use `backend.database.plugin.` to set plugin - specific database connection configuration, e.g. - - ```yaml - backend: - database: - client: 'pg', - prefix: 'custom_prefix_' - connection: - host: 'localhost' - user: 'foo' - password: 'bar' - plugin: - catalog: - connection: - database: 'database_name_overriden' - scaffolder: - client: 'sqlite3' - connection: ':memory:' - ``` - - Migrate existing backstage installations by swapping out the database manager in the - `packages/backend/src/index.ts` file as shown below: - - ```diff - import { - - SingleConnectionDatabaseManager, - + DatabaseManager, - } from '@backstage/backend-common'; - - // ... - - function makeCreateEnv(config: Config) { - // ... - - const databaseManager = SingleConnectionDatabaseManager.fromConfig(config); - + const databaseManager = DatabaseManager.fromConfig(config); - // ... - } - ``` - -- Updated dependencies - - @backstage/config-loader@0.6.4 - -## 0.8.2 - -### Patch Changes - -- 92963779b: Omits the `upgrade-insecure-requests` Content-Security-Policy directive by default, to prevent automatic HTTPS request upgrading for HTTP-deployed Backstage sites. - - If you previously disabled this using `false` in your `app-config.yaml`, this line is no longer necessary: - - ```diff - backend: - csp: - - upgrade-insecure-requests: false - ``` - - To keep the existing behavior of `upgrade-insecure-requests` Content-Security-Policy being _enabled_, add the key with an empty array as the value in your `app-config.yaml`: - - ```diff - backend: - + csp: - + upgrade-insecure-requests: [] - ``` - - Read more on [upgrade-insecure-requests here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/upgrade-insecure-requests). - -- eda9dbd5f: Download archives as compressed tar files for Bitbucket to keep executable permissions. -- Updated dependencies [eda9dbd5f] - - @backstage/integration@0.5.6 - -## 0.8.1 - -### Patch Changes - -- c7dad9218: All cache-related connection errors are now handled and logged by the cache manager. App Integrators may provide an optional error handler when instantiating the cache manager if custom error handling is needed. - - ```typescript - // Providing an error handler - const cacheManager = CacheManager.fromConfig(config, { - onError: e => { - if (isSomehowUnrecoverable(e)) { - gracefullyShutThingsDown(); - process.exit(1); - } - }, - }); - ``` - -- 65e6c4541: Remove circular dependencies -- 5001de908: Change GitlabUrlReader to SHA timestamp compare using only commits that modify given file path, if file path given -- Updated dependencies [65e6c4541] -- Updated dependencies [290405276] - - @backstage/integration@0.5.3 - - @backstage/config-loader@0.6.2 - -## 0.8.0 - -### Minor Changes - -- 22fd8ce2a: Introducing: a standard API for App Integrators to configure cache stores and Plugin Developers to interact with them. - - Two cache stores are currently supported. - - - `memory`, which is a very simple in-memory key/value store, intended for local development. - - `memcache`, which can be used to connect to a memcache host. - - Configuring and working with cache stores is very similar to the process for database connections. - - ```yaml - backend: - cache: - store: memcache - connection: user:pass@cache.example.com:11211 - ``` - - ```typescript - import { CacheManager } from '@backstage/backend-common'; - - // Instantiating a cache client for a plugin. - const cacheManager = CacheManager.fromConfig(config); - const somePluginCache = cacheManager.forPlugin('somePlugin'); - const cacheClient = somePluginCache.getClient(); - - // Using the cache client: - const cachedValue = await cacheClient.get('someKey'); - if (cachedValue) { - return cachedValue; - } else { - const someValue = await someExpensiveProcess(); - await cacheClient.set('someKey', someValue); - } - await cacheClient.delete('someKey'); - ``` - - Cache clients deal with TTLs in milliseconds. A TTL can be provided as a defaultTtl when getting a client, or may be passed when setting specific objects. If no TTL is provided, data will be persisted indefinitely. - - ```typescript - // Getting a client with a default TTL - const cacheClient = somePluginCache.getClient({ - defaultTtl: 3600000, - }); - - // Setting a TTL on a per-object basis. - cacheClient.set('someKey', data, { ttl: 3600000 }); - ``` - - Configuring a cache store is optional. Even when no cache store is configured, the cache manager will dutifully pass plugins a manager that resolves a cache client that does not actually write or read any data. - -### Patch Changes - -- f9fb4a205: Prep work for mysql support in backend-common - -## 0.7.0 - -### Minor Changes - -- e0bfd3d44: Refactor the `runDockerContainer(…)` function to an interface-based api. - This gives the option to replace the docker runtime in the future. - - Packages and plugins that previously used the `dockerode` as argument should be migrated to use the new `ContainerRunner` interface instead. - - ```diff - import { - - runDockerContainer, - + ContainerRunner, - PluginEndpointDiscovery, - } from '@backstage/backend-common'; - - import Docker from 'dockerode'; - - type RouterOptions = { - // ... - - dockerClient: Docker, - + containerRunner: ContainerRunner; - }; - - export async function createRouter({ - // ... - - dockerClient, - + containerRunner, - }: RouterOptions): Promise { - // ... - - + await containerRunner.runContainer({ - - await runDockerContainer({ - image: 'docker', - // ... - - dockerClient, - }); - - // ... - } - ``` - - To keep the `dockerode` based runtime, use the `DockerContainerRunner` implementation: - - ```diff - + import { - + ContainerRunner, - + DockerContainerRunner - + } from '@backstage/backend-common'; - - import { runDockerContainer } from '@backstage/backend-common'; - - + const containerRunner: ContainerRunner = new DockerContainerRunner({dockerClient}); - + await containerRunner.runContainer({ - - await runDockerContainer({ - image: 'docker', - // ... - - dockerClient, - }); - ``` - -### Patch Changes - -- 38ca05168: The default `@octokit/rest` dependency was bumped to `"^18.5.3"`. -- Updated dependencies [38ca05168] -- Updated dependencies [d8b81fd28] - - @backstage/integration@0.5.2 - - @backstage/config-loader@0.6.1 - - @backstage/config@0.1.5 - -## 0.6.3 - -### Patch Changes - -- d367f63b5: remove use of deprecated type HelmetOptions -- b42531cfe: Support configuration of file storage for SQLite databases. Every plugin has its - own database file at the specified path. - -## 0.6.2 - -### Patch Changes - -- b779b5fee: Add UrlReader for Google Cloud Storage -- Updated dependencies [82c66b8cd] - - @backstage/config-loader@0.6.0 - -## 0.6.1 - -### Patch Changes - -- 37e3a69f5: Export `ReadTreeResponseFile` and `SearchResponseFile`. - -## 0.6.0 - -### Minor Changes - -- 8686eb38c: Encode thrown errors in the backend as a JSON payload. This is technically a breaking change, since the response format even of errors are part of the contract. If you relied on the response being text, you will now have some extra JSON "noise" in it. It should still be readable by end users though. - - Before: - - ``` - NotFoundError: No entity named 'tara.macgovern2' found, with kind 'user' in namespace 'default' - at eval (webpack-internal:///../../plugins/catalog-backend/src/service/router.ts:117:17) - ``` - - After: - - ```json - { - "error": { - "name": "NotFoundError", - "message": "No entity named 'tara.macgovern2' found, with kind 'user' in namespace 'default'", - "stack": "NotFoundError: No entity named 'tara.macgovern2' found, with kind 'user' in namespace 'default'\n at eval (webpack-internal:///../../plugins/catalog-backend/src/service/router.ts:117:17)" - }, - "request": { - "method": "GET", - "url": "/entities/by-name/user/default/tara.macgovern2" - }, - "response": { - "statusCode": 404 - } - } - ``` - -- 8686eb38c: Removed the custom error types (e.g. `NotFoundError`). Those are now instead in the new `@backstage/errors` package. This is a breaking change, and you will have to update your imports if you were using these types. - - ```diff - -import { NotFoundError } from '@backstage/backend-common'; - +import { NotFoundError } from '@backstage/errors'; - ``` - -### Patch Changes - -- Updated dependencies [0434853a5] - - @backstage/config@0.1.4 - -## 0.5.6 - -### Patch Changes - -- d7245b733: Add a utility function runDockerContainer used to run a docker container (currently used by Scaffolder and TechDocs for their 'generate' processes) -- 761698831: Bump to the latest version of the Knex library. - - You will most likely want to bump your own `packages/backend/package.json` as well: - - ```diff - - "knex": "^0.21.18", - + "knex": "^0.95.1", - ``` - - Note that the recent versions of the Knex library have some changes that may affect your internal plugins' database migration files. Importantly, they now support `ALTER TABLE` on SQLite, and no longer accidentally remove indices when making some modifications. It now also exports the `Knex` typescript type as a named export. - - ```ts - import { Knex } from 'knex'; - ``` - -- Updated dependencies [277644e09] -- Updated dependencies [52f613030] -- Updated dependencies [905cbfc96] -- Updated dependencies [d4e77ec5f] - - @backstage/integration@0.5.1 - -## 0.5.5 - -### Patch Changes - -- 497859088: Add optional `logClientErrors` to errorHandler to log 4XX errors -- 8adb48df4: Change debug log format to print as color grey - -## 0.5.4 - -### Patch Changes - -- 16fb1d03a: pass registered logger to requestLoggingHandler -- 491f3a0ec: Implement `UrlReader.search` for the other providers (Azure, Bitbucket, GitLab) as well. - - The `UrlReader` subclasses now are implemented in terms of the respective `Integration` class. - -- 434b4e81a: Support globs in `FileReaderProcessor`. -- fb28da212: Switched to using `'x-access-token'` for authenticating Git over HTTPS towards GitHub. -- Updated dependencies [491f3a0ec] - - @backstage/integration@0.5.0 - -## 0.5.3 - -### Patch Changes - -- ffffea8e6: Minor updates to reflect the changes in `@backstage/integration` that made the fields `apiBaseUrl` and `apiUrl` mandatory. -- 82b2c11b6: Set explicit content-type in error handler responses. -- 965e200c6: Slight refactoring in support of a future search implementation in `UrlReader`. Mostly moving code around. -- 5a5163519: Implement `UrlReader.search` which implements glob matching. -- Updated dependencies [ffffea8e6] - - @backstage/integration@0.4.0 - -## 0.5.2 - -### Patch Changes - -- 2430ee7c2: Updated the `rootLogger` in `@backstage/backend-common` to support custom logging options. This is useful when you want to make some changes without re-implementing the entire logger and calling `setRootLogger` or `logger.configure`. For example you can add additional `defaultMeta` tags to each log entry. The following changes are included: - - - Added `createRootLogger` which accepts winston `LoggerOptions`. These options allow overriding the default keys. - - Example Usage: - - ```ts - // Create the logger - const logger = createRootLogger({ - defaultMeta: { appName: 'backstage', appEnv: 'prod' }, - }); - - // Add a custom logger transport - logger.add(new MyCustomTransport()); - - const config = await loadBackendConfig({ - argv: process.argv, - logger: getRootLogger(), // already set to new logger instance - }); - ``` - -- Updated dependencies [c4abcdb60] -- Updated dependencies [062df71db] -- Updated dependencies [064c513e1] -- Updated dependencies [e9aab60c7] -- Updated dependencies [3149bfe63] -- Updated dependencies [2e62aea6f] - - @backstage/integration@0.3.2 - - @backstage/config-loader@0.5.1 - -## 0.5.1 - -### Patch Changes - -- 26a3a6cf0: Honor the branch ref in the url when cloning. - - This fixes a bug in the scaffolder prepare stage where a non-default branch - was specified in the scaffolder URL but the default branch was cloned. - For example, even though the `other` branch is specified in this example, the - `master` branch was actually cloned: - - ```yaml - catalog: - locations: - - type: url - target: https://github.com/backstage/backstage/blob/other/plugins/scaffolder-backend/sample-templates/docs-template/template.yaml - ``` - - This also fixes a 404 in the prepare stage for GitLab URLs. - -- 664dd08c9: URL Reader's readTree: Fix bug with github.com URLs. -- 9dd057662: Upgrade [git-url-parse](https://www.npmjs.com/package/git-url-parse) to [v11.4.4](https://github.com/IonicaBizau/git-url-parse/pull/125) which fixes parsing an Azure DevOps branch ref. -- Updated dependencies [6800da78d] -- Updated dependencies [9dd057662] -- Updated dependencies [ef7957be4] -- Updated dependencies [ef7957be4] -- Updated dependencies [ef7957be4] - - @backstage/integration@0.3.1 - - @backstage/config-loader@0.5.0 - -## 0.5.0 - -### Minor Changes - -- 5345a1f98: Remove fallback option from `UrlReaders.create` and `UrlReaders.default`, as well as the default fallback reader. - - To be able to read data from endpoints outside of the configured integrations, you now need to explicitly allow it by - adding an entry in the `backend.reading.allow` list. For example: - - ```yml - backend: - baseUrl: ... - reading: - allow: - - host: example.com - - host: '*.examples.org' - ``` - - Apart from adding the above configuration, most projects should not need to take any action to migrate existing code. If you do happen to have your own fallback reader configured, this needs to be replaced with a reader factory that selects a specific set of URLs to work with. If you where wrapping the existing fallback reader, the new one that handles the allow list is created using `FetchUrlReader.factory`. - -- 09a370426: Remove support for HTTPS certificate generation parameters. Use `backend.https = true` instead. - -### Patch Changes - -- 0b135e7e0: Add support for GitHub Apps authentication for backend plugins. - - `GithubCredentialsProvider` requests and caches GitHub credentials based on a repository or organization url. - - The `GithubCredentialsProvider` class should be considered stateful since tokens will be cached internally. - Consecutive calls to get credentials will return the same token, tokens older than 50 minutes will be considered expired and reissued. - `GithubCredentialsProvider` will default to the configured access token if no GitHub Apps are configured. - - More information on how to create and configure a GitHub App to use with backstage can be found in the documentation. - - Usage: - - ```javascript - const credentialsProvider = new GithubCredentialsProvider(config); - const { token, headers } = await credentialsProvider.getCredentials({ - url: 'https://github.com/', - }); - ``` - - Updates `GithubUrlReader` to use the `GithubCredentialsProvider`. - -- 294a70cab: 1. URL Reader's `readTree` method now returns an `etag` in the response along with the blob. The etag is an identifier of the blob and will only change if the blob is modified on the target. Usually it is set to the latest commit SHA on the target. - - `readTree` also takes an optional `etag` in its options and throws a `NotModifiedError` if the etag matches with the etag of the resource. - - So, the `etag` can be used in building a cache when working with URL Reader. - - An example - - - ```ts - const response = await reader.readTree( - 'https://github.com/backstage/backstage', - ); - - const etag = response.etag; - - // Will throw a new NotModifiedError (exported from @backstage/backstage-common) - await reader.readTree('https://github.com/backstage/backstage', { - etag, - }); - ``` - - 2. URL Reader's readTree method can now detect the default branch. So, `url:https://github.com/org/repo/tree/master` can be replaced with `url:https://github.com/org/repo` in places like `backstage.io/techdocs-ref`. - -- 0ea032763: URL Reader: Use API response headers for archive filename in readTree. Fixes bug for users with hosted Bitbucket. -- Updated dependencies [0b135e7e0] -- Updated dependencies [fa8ba330a] -- Updated dependencies [ed6baab66] - - @backstage/integration@0.3.0 - -## 0.4.3 - -### Patch Changes - -- Updated dependencies [466354aaa] - - @backstage/integration@0.2.0 - -## 0.4.2 - -### Patch Changes - -- 5ecd50f8a: Fix HTTPS certificate generation and add new config switch, enabling it simply by setting `backend.https = true`. Also introduces caching of generated certificates in order to avoid having to add a browser override every time the backend is restarted. -- 00042e73c: Moving the Git actions to isomorphic-git instead of the node binding version of nodegit -- 0829ff126: Tweaked development log formatter to include extra fields at the end of each log line -- 036a84373: Provide support for on-prem azure devops -- Updated dependencies [ad5c56fd9] -- Updated dependencies [036a84373] - - @backstage/config-loader@0.4.1 - - @backstage/integration@0.1.5 - -## 0.4.1 - -### Patch Changes - -- 1d1c2860f: Implement readTree on BitBucketUrlReader and getBitbucketDownloadUrl -- 4eafdec4a: Introduce readTree method for GitLab URL Reader -- Updated dependencies [1d1c2860f] -- Updated dependencies [4eafdec4a] -- Updated dependencies [178e09323] - - @backstage/integration@0.1.4 - -## 0.4.0 - -### Minor Changes - -- 12bbd748c: Removes the Prometheus integration from `backend-common`. - - Rational behind this change is to keep the metrics integration of Backstage - generic. Instead of directly relying on Prometheus, Backstage will expose - metrics in a generic way. Integrators can then export the metrics in their - desired format. For example using Prometheus. - - To keep the existing behavior, you need to integrate Prometheus in your - backend: - - First, add a dependency on `express-prom-bundle` and `prom-client` to your backend. - - ```diff - // packages/backend/package.json - "dependencies": { - + "express-prom-bundle": "^6.1.0", - + "prom-client": "^12.0.0", - ``` - - Then, add a handler for metrics and a simple instrumentation for the endpoints. - - ```typescript - // packages/backend/src/metrics.ts - import { useHotCleanup } from '@backstage/backend-common'; - import { RequestHandler } from 'express'; - import promBundle from 'express-prom-bundle'; - import prom from 'prom-client'; - import * as url from 'url'; - - const rootRegEx = new RegExp('^/([^/]*)/.*'); - const apiRegEx = new RegExp('^/api/([^/]*)/.*'); - - export function normalizePath(req: any): string { - const path = url.parse(req.originalUrl || req.url).pathname || '/'; - - // Capture /api/ and the plugin name - if (apiRegEx.test(path)) { - return path.replace(apiRegEx, '/api/$1'); - } - - // Only the first path segment at root level - return path.replace(rootRegEx, '/$1'); - } - - /** - * Adds a /metrics endpoint, register default runtime metrics and instrument the router. - */ - export function metricsHandler(): RequestHandler { - // We can only initialize the metrics once and have to clean them up between hot reloads - useHotCleanup(module, () => prom.register.clear()); - - return promBundle({ - includeMethod: true, - includePath: true, - // Using includePath alone is problematic, as it will include path labels with high - // cardinality (e.g. path params). Instead we would have to template them. However, this - // is difficult, as every backend plugin might use different routes. Instead we only take - // the first directory of the path, to have at least an idea how each plugin performs: - normalizePath, - promClient: { collectDefaultMetrics: {} }, - }); - } - ``` - - Last, extend your router configuration with the `metricsHandler`: - - ```diff - +import { metricsHandler } from './metrics'; - - ... - - const service = createServiceBuilder(module) - .loadConfig(config) - .addRouter('', await healthcheck(healthcheckEnv)) - + .addRouter('', metricsHandler()) - .addRouter('/api', apiRouter); - ``` - - Your Prometheus metrics will be available at the `/metrics` endpoint. - -### Patch Changes - -- 38e24db00: Move the core url and auth logic to integration for the four major providers -- Updated dependencies [38e24db00] -- Updated dependencies [b8ecf6f48] -- Updated dependencies [e3bd9fc2f] -- Updated dependencies [e3bd9fc2f] - - @backstage/integration@0.1.3 - - @backstage/config@0.1.2 - -## 0.3.3 - -### Patch Changes - -- 612368274: Allow the `backend.listen.port` config to be both a number or a string. -- Updated dependencies [4e7091759] -- Updated dependencies [b4488ddb0] - - @backstage/config-loader@0.4.0 - -## 0.3.2 - -### Patch Changes - -- 3aa7efb3f: Added support for passing false as a CSP field value, to drop it from the defaults in the backend -- b3d4e4e57: Move the frontend visibility declarations of integrations config from @backstage/backend-common to @backstage/integration -- Updated dependencies [b3d4e4e57] - - @backstage/integration@0.1.2 - -## 0.3.1 - -### Patch Changes - -- bff3305aa: Added readTree support to AzureUrlReader -- b47dce06f: Make integration host and url configurations visible in the frontend - -## 0.3.0 - -### Minor Changes - -- 1722cb53c: Added support for loading and validating configuration schemas, as well as declaring config visibility through schemas. - - The new `loadConfigSchema` function exported by `@backstage/config-loader` allows for the collection and merging of configuration schemas from all nearby dependencies of the project. - - A configuration schema is declared using the `https://backstage.io/schema/config-v1` JSON Schema meta schema, which is based on draft07. The only difference to the draft07 schema is the custom `visibility` keyword, which is used to indicate whether the given config value should be visible in the frontend or not. The possible values are `frontend`, `backend`, and `secret`, where `backend` is the default. A visibility of `secret` has the same scope at runtime, but it will be treated with more care in certain contexts, and defining both `frontend` and `secret` for the same value in two different schemas will result in an error during schema merging. - - Packages that wish to contribute configuration schema should declare it in a root `"configSchema"` field in `package.json`. The field can either contain an inlined JSON schema, or a relative path to a schema file. Schema files can be in either `.json` or `.d.ts` format. - - TypeScript configuration schema files should export a single `Config` type, for example: - - ```ts - export interface Config { - app: { - /** - * Frontend root URL - * @visibility frontend - */ - baseUrl: string; - }; - } - ``` - -- 8e2effb53: Refactored UrlReader.readTree to be required and accept (url, options) - -### Patch Changes - -- 1722cb53c: Added configuration schema -- 7b37e6834: Added the integration package -- Updated dependencies [1722cb53c] -- Updated dependencies [7b37e6834] - - @backstage/config-loader@0.3.0 - - @backstage/integration@0.1.1 - - @backstage/test-utils@0.1.3 - -## 0.2.1 - -### Patch Changes - -- 33b7300eb: Capture plugin name under the /api/ prefix for http metrics - -## 0.2.0 - -### Minor Changes - -- 5249594c5: Add service discovery interface and implement for single host deployments - - Fixes #1847, #2596 - - Went with an interface similar to the frontend DiscoveryApi, since it's dead simple but still provides a lot of flexibility in the implementation. - - Also ended up with two different methods, one for internal endpoint discovery and one for external. The two use-cases are explained a bit more in the docs, but basically it's service-to-service vs callback URLs. - - This did get me thinking about uniqueness and that we're heading towards a global namespace for backend plugin IDs. That's probably fine, but if we're happy with that we should leverage it a bit more to simplify the backend setup. For example we'd have each plugin provide its own ID and not manually mount on paths in the backend. - - Draft until we're happy with the implementation, then I can add more docs and changelog entry. Also didn't go on a thorough hunt for places where discovery can be used, but I don't think there are many since it's been pretty awkward to do service-to-service communication. - -- 56e4eb589: Make CSP configurable to fix app-backend served app not being able to fetch - - See discussion [here on discord](https://discordapp.com/channels/687207715902193673/687235481154617364/758721460163575850) - -- e37c0a005: Use localhost to fall back to IPv4 if IPv6 isn't available -- f00ca3cb8: Auto-create plugin databases - - Relates to #1598. - - This creates databases for plugins before handing off control to plugins. - - The list of plugins currently need to be hard-coded depending on the installed plugins. A later PR will properly refactor the code to provide a factory pattern where plugins specify what they need, and Knex instances will be provided based on the input. - -- 6579769df: Add the ability to import components from Bitbucket Server to the service catalog -- 8c2b76e45: **BREAKING CHANGE** - - The existing loading of additional config files like `app-config.development.yaml` using APP_ENV or NODE_ENV has been removed. - Instead, the CLI and backend process now accept one or more `--config` flags to load config files. - - Without passing any flags, `app-config.yaml` and, if it exists, `app-config.local.yaml` will be loaded. - If passing any `--config ` flags, only those files will be loaded, **NOT** the default `app-config.yaml` one. - - The old behaviour of for example `APP_ENV=development` can be replicated using the following flags: - - ```bash - --config ../../app-config.yaml --config ../../app-config.development.yaml - ``` - -- 8afce088a: Use APP_ENV before NODE_ENV for determining what config to load -- 7bbeb049f: Change loadBackendConfig to return the config directly - -### Patch Changes - -- 440a17b39: Added new UrlReader interface for reading opaque data from URLs with different providers. - - This new URL reading system is intended as a replacement for the various integrations towards - external systems in the catalog, scaffolder, and techdocs. It is configured via a new top-level - config section called 'integrations'. - - Along with the UrlReader interface is a new UrlReaders class, which exposes static factory - methods for instantiating readers that can read from many different integrations simultaneously. - -- Updated dependencies [8c2b76e45] -- Updated dependencies [ce5512bc0] - - @backstage/config-loader@0.2.0 - - @backstage/test-utils@0.1.2 diff --git a/packages/backend-common/README.md b/packages/backend-common/README.md deleted file mode 100644 index e9f2f43e83..0000000000 --- a/packages/backend-common/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# @backstage/backend-common - -> [!CAUTION] -> This package is deprecated and will be removed in a near future, so please follow the deprecated instructions for the exports you still use. - -Common functionality library for Backstage backends, implementing logging, -error handling and similar. - -## Usage - -Add the library to your backend package: - -```bash -# From your Backstage root directory -yarn --cwd packages/backend add @backstage/backend-common -``` - -then make use of the handlers and logger as necessary: - -```typescript -import { - errorHandler, - getRootLogger, - notFoundHandler, - requestLoggingHandler, -} from '@backstage/backend-common'; - -const app = express(); -app.use(requestLoggingHandler()); -app.use('/home', myHomeRouter); -app.use(notFoundHandler()); -app.use(errorHandler()); - -app.listen(PORT, () => { - getRootLogger().info(`Listening on port ${PORT}`); -}); -``` - -## Documentation - -- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) -- [Backstage Documentation](https://backstage.io/docs) diff --git a/packages/backend-common/api-report-alpha.md b/packages/backend-common/api-report-alpha.md deleted file mode 100644 index 046e8264fb..0000000000 --- a/packages/backend-common/api-report-alpha.md +++ /dev/null @@ -1,32 +0,0 @@ -## API Report File for "@backstage/backend-common" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -import { Duration } from 'luxon'; - -// @alpha @deprecated -export interface Context { - readonly abortSignal: AbortSignal; - readonly deadline: Date | undefined; - value(key: string): T | undefined; -} - -// @alpha @deprecated -export class Contexts { - static root(): Context; - static withAbort( - parentCtx: Context, - source: AbortController | AbortSignal, - ): Context; - static withTimeoutDuration(parentCtx: Context, timeout: Duration): Context; - static withTimeoutMillis(parentCtx: Context, timeout: number): Context; - static withValue( - parentCtx: Context, - key: string, - value: unknown | ((previous: unknown | undefined) => unknown), - ): Context; -} - -// (No @packageDocumentation comment for this package) -``` diff --git a/packages/backend-common/api-report-testUtils.md b/packages/backend-common/api-report-testUtils.md deleted file mode 100644 index d53748234e..0000000000 --- a/packages/backend-common/api-report-testUtils.md +++ /dev/null @@ -1,21 +0,0 @@ -## API Report File for "@backstage/backend-common" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -import { overridePackagePathResolution as overridePackagePathResolution_2 } from '@backstage/backend-plugin-api/testUtils'; -import { OverridePackagePathResolutionOptions as OverridePackagePathResolutionOptions_2 } from '@backstage/backend-plugin-api/testUtils'; -import { PackagePathResolutionOverride as PackagePathResolutionOverride_2 } from '@backstage/backend-plugin-api/testUtils'; - -// @public @deprecated (undocumented) -export const overridePackagePathResolution: typeof overridePackagePathResolution_2; - -// @public @deprecated (undocumented) -export type OverridePackagePathResolutionOptions = - OverridePackagePathResolutionOptions_2; - -// @public @deprecated (undocumented) -export type PackagePathResolutionOverride = PackagePathResolutionOverride_2; - -// (No @packageDocumentation comment for this package) -``` diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md deleted file mode 100644 index 1a67d4877f..0000000000 --- a/packages/backend-common/api-report.md +++ /dev/null @@ -1,561 +0,0 @@ -## API Report File for "@backstage/backend-common" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -/// -/// - -import { AppConfig } from '@backstage/config'; -import { AuthCallback } from 'isomorphic-git'; -import { AuthService } from '@backstage/backend-plugin-api'; -import { BackendFeature } from '@backstage/backend-plugin-api'; -import { CacheService } from '@backstage/backend-plugin-api'; -import { CacheServiceOptions } from '@backstage/backend-plugin-api'; -import { CacheServiceSetOptions } from '@backstage/backend-plugin-api'; -import { Config } from '@backstage/config'; -import { ConfigSchema } from '@backstage/config-loader'; -import cors from 'cors'; -import { DatabaseService } from '@backstage/backend-plugin-api'; -import { DiscoveryService } from '@backstage/backend-plugin-api'; -import Docker from 'dockerode'; -import { ErrorRequestHandler } from 'express'; -import express from 'express'; -import { HttpAuthService } from '@backstage/backend-plugin-api'; -import { isChildPath as isChildPath_2 } from '@backstage/backend-plugin-api'; -import { isDatabaseConflictError as isDatabaseConflictError_2 } from '@backstage/backend-plugin-api'; -import { KubeConfig } from '@kubernetes/client-node'; -import { LifecycleService } from '@backstage/backend-plugin-api'; -import { LoadConfigOptionsRemote } from '@backstage/config-loader'; -import { Logger } from 'winston'; -import { LoggerService } from '@backstage/backend-plugin-api'; -import { MergeResult } from 'isomorphic-git'; -import { PermissionsService } from '@backstage/backend-plugin-api'; -import { PluginMetadataService } from '@backstage/backend-plugin-api'; -import { PushResult } from 'isomorphic-git'; -import { ReadCommitResult } from 'isomorphic-git'; -import { Request as Request_2 } from 'express'; -import { RequestHandler } from 'express'; -import { resolvePackagePath as resolvePackagePath_2 } from '@backstage/backend-plugin-api'; -import { resolveSafeChildPath as resolveSafeChildPath_2 } from '@backstage/backend-plugin-api'; -import { RootConfigService } from '@backstage/backend-plugin-api'; -import { Router } from 'express'; -import { SchedulerService } from '@backstage/backend-plugin-api'; -import { Server } from 'http'; -import { ServiceRef } from '@backstage/backend-plugin-api'; -import { TransportStreamOptions } from 'winston-transport'; -import { UrlReaderService } from '@backstage/backend-plugin-api'; -import { UserInfoService } from '@backstage/backend-plugin-api'; -import { V1PodTemplateSpec } from '@kubernetes/client-node'; -import * as winston from 'winston'; -import { Writable } from 'stream'; - -// @public @deprecated -export type AuthCallbackOptions = { - onAuth: AuthCallback; - logger?: LoggerService; -}; - -// @public @deprecated (undocumented) -export type CacheClient = CacheService; - -// @public @deprecated (undocumented) -export type CacheClientOptions = CacheServiceOptions; - -// @public @deprecated (undocumented) -export type CacheClientSetOptions = CacheServiceSetOptions; - -// @public @deprecated (undocumented) -export class CacheManager { - // (undocumented) - forPlugin(pluginId: string): PluginCacheManager; - static fromConfig( - config: RootConfigService, - options?: CacheManagerOptions, - ): CacheManager; -} - -// Warning: (ae-forgotten-export) The symbol "CacheManagerOptions_2" needs to be exported by the entry point index.d.ts -// -// @public @deprecated (undocumented) -export type CacheManagerOptions = CacheManagerOptions_2; - -// @public @deprecated -export function cacheToPluginCacheManager(cache: CacheService): { - getClient(options?: CacheServiceOptions): CacheService; -}; - -// @public @deprecated -export const coloredFormat: winston.Logform.Format; - -// @public @deprecated -export interface ContainerRunner { - runContainer(opts: RunContainerOptions): Promise; -} - -// Warning: (ae-forgotten-export) The symbol "createConfigSecretEnumerator_2" needs to be exported by the entry point index.d.ts -// -// @public @deprecated (undocumented) -export const createConfigSecretEnumerator: typeof createConfigSecretEnumerator_2; - -// @public @deprecated -export function createLegacyAuthAdapters< - TOptions extends { - auth?: AuthService; - httpAuth?: HttpAuthService; - userInfo?: UserInfoService; - identity?: LegacyIdentityService; - tokenManager?: TokenManager; - discovery: PluginEndpointDiscovery; - }, - TAdapters = (TOptions extends { - auth?: AuthService; - } - ? { - auth: AuthService; - } - : {}) & - (TOptions extends { - httpAuth?: HttpAuthService; - } - ? { - httpAuth: HttpAuthService; - } - : {}) & - (TOptions extends { - userInfo?: UserInfoService; - } - ? { - userInfo: UserInfoService; - } - : {}), ->(options: TOptions): TAdapters; - -// @public @deprecated -export function createRootLogger( - options?: winston.LoggerOptions, - env?: NodeJS.ProcessEnv, -): winston.Logger; - -// @public @deprecated -export function createServiceBuilder(_module: NodeModule): ServiceBuilder; - -// @public @deprecated -export function createStatusCheckRouter(options: { - logger: LoggerService; - path?: string; - statusCheck?: StatusCheck; -}): Promise; - -// @public @deprecated (undocumented) -export class DatabaseManager implements LegacyRootDatabaseService { - // (undocumented) - forPlugin( - pluginId: string, - deps?: - | { - lifecycle: LifecycleService; - pluginMetadata: PluginMetadataService; - } - | undefined, - ): PluginDatabaseManager; - // (undocumented) - static fromConfig( - config: Config, - options?: { - migrations?: DatabaseService['migrations']; - logger?: LoggerService; - }, - ): DatabaseManager; -} - -// Warning: (ae-forgotten-export) The symbol "DatabaseManagerOptions_2" needs to be exported by the entry point index.d.ts -// -// @public @deprecated (undocumented) -export type DatabaseManagerOptions = DatabaseManagerOptions_2; - -// @public @deprecated -export class DockerContainerRunner implements ContainerRunner { - constructor(options: { dockerClient: Docker }); - // (undocumented) - runContainer(options: RunContainerOptions): Promise; -} - -// @public @deprecated -export function errorHandler( - options?: ErrorHandlerOptions, -): ErrorRequestHandler; - -// @public @deprecated -export type ErrorHandlerOptions = { - showStackTraces?: boolean; - logger?: LoggerService; - logClientErrors?: boolean; -}; - -// @public @deprecated -export function getRootLogger(): winston.Logger; - -// @public @deprecated -export function getVoidLogger(): winston.Logger; - -// @public @deprecated -export class Git { - // (undocumented) - add(options: { dir: string; filepath: string }): Promise; - // (undocumented) - addRemote(options: { - dir: string; - remote: string; - url: string; - force?: boolean; - }): Promise; - // (undocumented) - branch(options: { dir: string; ref: string }): Promise; - // (undocumented) - checkout(options: { dir: string; ref: string }): Promise; - clone(options: { - url: string; - dir: string; - ref?: string; - depth?: number; - noCheckout?: boolean; - }): Promise; - // (undocumented) - commit(options: { - dir: string; - message: string; - author: { - name: string; - email: string; - }; - committer: { - name: string; - email: string; - }; - }): Promise; - currentBranch(options: { - dir: string; - fullName?: boolean; - }): Promise; - // (undocumented) - deleteRemote(options: { dir: string; remote: string }): Promise; - fetch(options: { - dir: string; - remote?: string; - tags?: boolean; - }): Promise; - // (undocumented) - static fromAuth: (options: StaticAuthOptions | AuthCallbackOptions) => Git; - // (undocumented) - init(options: { dir: string; defaultBranch?: string }): Promise; - log(options: { dir: string; ref?: string }): Promise; - merge(options: { - dir: string; - theirs: string; - ours?: string; - author: { - name: string; - email: string; - }; - committer: { - name: string; - email: string; - }; - }): Promise; - // (undocumented) - push(options: { - dir: string; - remote: string; - remoteRef?: string; - force?: boolean; - }): Promise; - readCommit(options: { dir: string; sha: string }): Promise; - remove(options: { dir: string; filepath: string }): Promise; - resolveRef(options: { dir: string; ref: string }): Promise; -} - -// @public @deprecated -class HostDiscovery implements DiscoveryService { - static fromConfig(config: Config): HostDiscovery; - // (undocumented) - getBaseUrl(pluginId: string): Promise; - // (undocumented) - getExternalBaseUrl(pluginId: string): Promise; -} -export { HostDiscovery }; -export { HostDiscovery as SingleHostDiscovery }; - -// @public @deprecated (undocumented) -export const isChildPath: typeof isChildPath_2; - -// @public @deprecated (undocumented) -export const isDatabaseConflictError: typeof isDatabaseConflictError_2; - -// @public @deprecated -export class KubernetesContainerRunner implements ContainerRunner { - constructor(options: KubernetesContainerRunnerOptions); - // (undocumented) - runContainer(options: RunContainerOptions): Promise; -} - -// @public @deprecated -export type KubernetesContainerRunnerMountBase = { - volumeName: string; - basePath: string; -}; - -// @public @deprecated -export type KubernetesContainerRunnerOptions = { - kubeConfig: KubeConfig; - name: string; - namespace?: string; - mountBase?: KubernetesContainerRunnerMountBase; - podTemplate?: V1PodTemplateSpec; - timeoutMs?: number; -}; - -// @public @deprecated (undocumented) -export type LegacyCreateRouter = (deps: TEnv) => Promise; - -// @public @deprecated -export interface LegacyIdentityService { - // (undocumented) - getIdentity(options: { request: Request_2 }): Promise< - | { - expiresInSeconds?: number; - token: string; - identity: { - type: 'user'; - userEntityRef: string; - ownershipEntityRefs: string[]; - }; - } - | undefined - >; -} - -// @public @deprecated -export const legacyPlugin: ( - name: string, - createRouterImport: Promise<{ - default: LegacyCreateRouter< - TransformedEnv< - { - cache: CacheService; - config: RootConfigService; - database: DatabaseService; - discovery: DiscoveryService; - logger: LoggerService; - permissions: PermissionsService; - scheduler: SchedulerService; - reader: UrlReaderService; - }, - { - logger: (log: LoggerService) => Logger; - cache: (cache: CacheService) => { - getClient(options?: CacheServiceOptions | undefined): CacheService; - }; - } - > & { - tokenManager: TokenManager; - identity: LegacyIdentityService; - } - >; - }>, -) => BackendFeature; - -// @public @deprecated (undocumented) -export type LegacyRootDatabaseService = { - forPlugin(pluginId: string): DatabaseService; -}; - -// @public @deprecated -export function loadBackendConfig(options: { - logger: LoggerService; - remote?: LoadConfigOptionsRemote; - additionalConfigs?: AppConfig[]; - argv: string[]; - watch?: boolean; -}): Promise; - -// @public @deprecated (undocumented) -export function loggerToWinstonLogger( - logger: LoggerService, - opts?: TransportStreamOptions, -): Logger; - -// @public @deprecated -export function makeLegacyPlugin< - TEnv extends Record, - TEnvTransforms extends { - [key in keyof TEnv]?: (dep: TEnv[key]) => unknown; - }, ->( - envMapping: { - [key in keyof TEnv]: ServiceRef; - }, - envTransforms: TEnvTransforms, -): ( - name: string, - createRouterImport: Promise<{ - default: LegacyCreateRouter< - TransformedEnv & { - tokenManager: TokenManager; - identity: LegacyIdentityService; - } - >; - }>, -) => BackendFeature; - -// @public @deprecated -export function notFoundHandler(): RequestHandler; - -// @public @deprecated (undocumented) -export type PluginCacheManager = { - getClient(options?: CacheServiceOptions): CacheService; -}; - -// @public @deprecated (undocumented) -export type PluginDatabaseManager = DatabaseService; - -// @public @deprecated (undocumented) -export type PluginEndpointDiscovery = DiscoveryService; - -// @public @deprecated -export interface PullOptions { - // (undocumented) - [key: string]: unknown; - // (undocumented) - authconfig?: { - username?: string; - password?: string; - auth?: string; - email?: string; - serveraddress?: string; - [key: string]: unknown; - }; -} - -// @public @deprecated -export function redactWinstonLogLine( - info: winston.Logform.TransformableInfo, -): winston.Logform.TransformableInfo; - -// @public @deprecated -export function requestLoggingHandler(logger?: LoggerService): RequestHandler; - -// @public @deprecated -export type RequestLoggingHandlerFactory = ( - logger?: LoggerService, -) => RequestHandler; - -// @public @deprecated (undocumented) -export const resolvePackagePath: typeof resolvePackagePath_2; - -// @public @deprecated (undocumented) -export const resolveSafeChildPath: typeof resolveSafeChildPath_2; - -// @public @deprecated -export type RunContainerOptions = { - imageName: string; - command?: string | string[]; - args: string[]; - logStream?: Writable; - mountDirs?: Record; - workingDir?: string; - envVars?: Record; - pullImage?: boolean; - defaultUser?: boolean; - pullOptions?: PullOptions; -}; - -// @public @deprecated -export class ServerTokenManager implements TokenManager { - // (undocumented) - authenticate(token: string): Promise; - // (undocumented) - static fromConfig( - config: Config, - options: ServerTokenManagerOptions, - ): TokenManager; - // (undocumented) - getToken(): Promise<{ - token: string; - }>; - static noop(): TokenManager; -} - -// @public @deprecated -export interface ServerTokenManagerOptions { - allowDisabledTokenManager?: boolean; - logger: LoggerService; -} - -// @public @deprecated -export type ServiceBuilder = { - loadConfig(config: Config): ServiceBuilder; - setPort(port: number): ServiceBuilder; - setHost(host: string): ServiceBuilder; - setLogger(logger: LoggerService): ServiceBuilder; - enableCors(options: cors.CorsOptions): ServiceBuilder; - setHttpsSettings(settings: { - certificate: - | { - key: string; - cert: string; - } - | { - hostname: string; - }; - }): ServiceBuilder; - addRouter(root: string, router: Router | RequestHandler): ServiceBuilder; - setRequestLoggingHandler( - requestLoggingHandler: RequestLoggingHandlerFactory, - ): ServiceBuilder; - setErrorHandler(errorHandler: ErrorRequestHandler): ServiceBuilder; - disableDefaultErrorHandler(): ServiceBuilder; - start(): Promise; -}; - -// @public @deprecated -export function setRootLogger(newLogger: winston.Logger): void; - -// @public @deprecated -export type StaticAuthOptions = { - username?: string; - password?: string; - token?: string; - logger?: LoggerService; -}; - -// @public @deprecated -export type StatusCheck = () => Promise; - -// @public @deprecated -export function statusCheckHandler( - options?: StatusCheckHandlerOptions, -): Promise; - -// @public @deprecated -export interface StatusCheckHandlerOptions { - statusCheck?: StatusCheck; -} - -// @public @deprecated (undocumented) -export interface TokenManager { - authenticate(token: string): Promise; - getToken(): Promise<{ - token: string; - }>; -} - -// @public @deprecated -export function useHotCleanup( - _module: NodeModule, - cancelEffect: () => void, -): void; - -// @public @deprecated -export function useHotMemoize(_module: NodeModule, valueFactory: () => T): T; -``` diff --git a/packages/backend-common/catalog-info.yaml b/packages/backend-common/catalog-info.yaml deleted file mode 100644 index ff38a4df75..0000000000 --- a/packages/backend-common/catalog-info.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: backstage-backend-common - title: '@backstage/backend-common' - description: Common functionality library for Backstage backends -spec: - lifecycle: experimental - type: backstage-node-library - owner: maintainers diff --git a/packages/backend-common/config.d.ts b/packages/backend-common/config.d.ts deleted file mode 100644 index 6146adfe83..0000000000 --- a/packages/backend-common/config.d.ts +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { HumanDuration } from '@backstage/types'; - -export interface Config { - app: { - baseUrl: string; // defined in core, but repeated here without doc - }; - - backend: { - /** Backend configuration for when request authentication is enabled */ - auth?: { - /** Keys shared by all backends for signing and validating backend tokens. */ - keys?: { - /** - * Secret for generating tokens. Should be a base64 string, recommended - * length is 24 bytes. - * - * @visibility secret - */ - secret: string; - }[]; - }; - - baseUrl: string; // defined in core, but repeated here without doc - - /** Address that the backend should listen to. */ - listen: - | string - | { - /** Address of the interface that the backend should bind to. */ - host?: string; - /** Port that the backend should listen to. */ - port?: string | number; - }; - - /** - * HTTPS configuration for the backend. If omitted the backend will serve HTTP. - * - * Setting this to `true` will cause self-signed certificates to be generated, which - * can be useful for local development or other non-production scenarios. - */ - https?: - | true - | { - /** Certificate configuration */ - certificate?: { - /** PEM encoded certificate. Use $file to load in a file */ - cert: string; - /** - * PEM encoded certificate key. Use $file to load in a file. - * @visibility secret - */ - key: string; - }; - }; - - /** - * An absolute path to a directory that can be used as a working dir, for - * example as scratch space for large operations. - * - * @remarks - * - * Note that this must be an absolute path. - * - * If not set, the operating system's designated temporary directory is - * commonly used, but that is implementation defined per plugin. - * - * Plugins are encouraged to heed this config setting if present, to allow - * deployment in severely locked-down or limited environments. - */ - workingDirectory?: string; - - /** Database connection configuration, select base database type using the `client` field */ - database: { - /** Default database client to use */ - client: 'better-sqlite3' | 'sqlite3' | 'pg'; - /** - * Base database connection string, or object with individual connection properties - * @visibility secret - */ - connection: - | string - | { - /** - * Password that belongs to the client User - * @visibility secret - */ - password?: string; - /** - * Other connection settings - */ - [key: string]: unknown; - }; - /** Database name prefix override */ - prefix?: string; - /** - * Whether to ensure the given database exists by creating it if it does not. - * Defaults to true if unspecified. - */ - ensureExists?: boolean; - /** - * Whether to ensure the given database schema exists by creating it if it does not. - * Defaults to false if unspecified. - * - * NOTE: Currently only supported by the `pg` client when pluginDivisionMode: schema - */ - ensureSchemaExists?: boolean; - /** - * How plugins databases are managed/divided in the provided database instance. - * - * `database` -> Plugins are each given their own database to manage their schemas/tables. - * - * `schema` -> Plugins will be given their own schema (in the specified/default database) - * to manage their tables. - * - * NOTE: Currently only supported by the `pg` client. - * - * @default database - */ - pluginDivisionMode?: 'database' | 'schema'; - /** Configures the ownership of newly created schemas in pg databases. */ - role?: string; - /** - * Arbitrary config object to pass to knex when initializing - * (https://knexjs.org/#Installation-client). Most notable is the debug - * and asyncStackTraces booleans - */ - knexConfig?: object; - /** Plugin specific database configuration and client override */ - plugin?: { - [pluginId: string]: { - /** Database client override */ - client?: 'better-sqlite3' | 'sqlite3' | 'pg'; - /** - * Database connection string or Knex object override - * @visibility secret - */ - connection?: string | object; - /** - * Whether to ensure the given database exists by creating it if it does not. - * Defaults to base config if unspecified. - */ - ensureExists?: boolean; - /** - * Whether to ensure the given database schema exists by creating it if it does not. - * Defaults to false if unspecified. - * - * NOTE: Currently only supported by the `pg` client when pluginDivisionMode: schema - */ - ensureSchemaExists?: boolean; - /** - * Arbitrary config object to pass to knex when initializing - * (https://knexjs.org/#Installation-client). Most notable is the - * debug and asyncStackTraces booleans. - * - * This is merged recursively into the base knexConfig - */ - knexConfig?: object; - /** Configures the ownership of newly created schemas in pg databases. */ - role?: string; - }; - }; - }; - - /** Cache connection configuration, select cache type using the `store` field */ - cache?: - | { - store: 'memory'; - /** An optional default TTL (in milliseconds). */ - defaultTtl?: number | HumanDuration; - } - | { - store: 'redis'; - /** - * A redis connection string in the form `redis://user:pass@host:port`. - * @visibility secret - */ - connection: string; - /** An optional default TTL (in milliseconds). */ - defaultTtl?: number | HumanDuration; - /** - * Whether or not [useRedisSets](https://github.com/jaredwray/keyv/tree/main/packages/redis#useredissets) should be configured to this redis cache. - * Defaults to true if unspecified. - */ - useRedisSets?: boolean; - } - | { - store: 'memcache'; - /** - * A memcache connection string in the form `user:pass@host:port`. - * @visibility secret - */ - connection: string; - /** An optional default TTL (in milliseconds). */ - defaultTtl?: number | HumanDuration; - }; - - /** - * Properties returned upon CORS requests to the backend, including the app-backend. - */ - cors?: { - origin?: string | string[]; - methods?: string | string[]; - allowedHeaders?: string | string[]; - exposedHeaders?: string | string[]; - credentials?: boolean; - maxAge?: number; - preflightContinue?: boolean; - optionsSuccessStatus?: number; - }; - - /** - * Content Security Policy options. - * - * The keys are the plain policy ID, e.g. "upgrade-insecure-requests". The - * values are on the format that the helmet library expects them, as an - * array of strings. There is also the special value false, which means to - * remove the default value that Backstage puts in place for that policy. - */ - csp?: { [policyId: string]: string[] | false }; - - /** - * Configuration related to URL reading, used for example for reading catalog info - * files, scaffolder templates, and techdocs content. - */ - reading?: { - /** - * A list of targets to allow outgoing requests to. Users will be able to make - * requests on behalf of the backend to the targets that are allowed by this list. - */ - allow?: Array<{ - /** - * A host to allow outgoing requests to, being either a full host or - * a subdomain wildcard pattern with a leading `*`. For example `example.com` - * and `*.example.com` are valid values, `prod.*.example.com` is not. - * The host may also contain a port, for example `example.com:8080`. - */ - host: string; - - /** - * An optional list of paths. In case they are present only targets matching - * any of them will are allowed. You can use trailing slashes to make sure only - * subdirectories are allowed, for example `/mydir/` will allow targets with - * paths like `/mydir/a` but will block paths like `/mydir2`. - */ - paths?: string[]; - }>; - }; - }; -} diff --git a/packages/backend-common/knip-report.md b/packages/backend-common/knip-report.md deleted file mode 100644 index ae0fd612a9..0000000000 --- a/packages/backend-common/knip-report.md +++ /dev/null @@ -1,24 +0,0 @@ -# Knip report - -## Unused dependencies (3) - -| Name | Location | Severity | -| :-------------------- | :----------- | :------- | -| @manypkg/get-packages | package.json | error | -| @types/webpack-env | package.json | error | -| mysql2 | package.json | error | - -## Unused devDependencies (3) - -| Name | Location | Severity | -| :----------------- | :----------- | :------- | -| @types/webpack-env | package.json | error | -| better-sqlite3 | package.json | error | -| mysql2 | package.json | error | - -## Referenced optional peerDependencies (1) - -| Name | Location | Severity | -| :------------------- | :----------- | :------- | -| pg-connection-string | package.json | error | - diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json deleted file mode 100644 index 34b990d8cd..0000000000 --- a/packages/backend-common/package.json +++ /dev/null @@ -1,157 +0,0 @@ -{ - "name": "@backstage/backend-common", - "version": "0.25.0", - "description": "Common functionality library for Backstage backends", - "backstage": { - "role": "node-library" - }, - "publishConfig": { - "access": "public" - }, - "keywords": [ - "backstage" - ], - "homepage": "https://backstage.io", - "repository": { - "type": "git", - "url": "https://github.com/backstage/backstage", - "directory": "packages/backend-common" - }, - "license": "Apache-2.0", - "exports": { - ".": "./src/index.ts", - "./alpha": "./src/alpha.ts", - "./testUtils": "./src/testUtils.ts", - "./package.json": "./package.json" - }, - "main": "src/index.ts", - "types": "src/index.ts", - "typesVersions": { - "*": { - "alpha": [ - "src/alpha.ts" - ], - "testUtils": [ - "src/testUtils.ts" - ], - "package.json": [ - "package.json" - ] - } - }, - "files": [ - "dist", - "config.d.ts" - ], - "scripts": { - "build": "backstage-cli package build", - "clean": "backstage-cli package clean", - "lint": "backstage-cli package lint", - "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack", - "start": "backstage-cli package start", - "test": "backstage-cli package test", - "test:kubernetes": "backstage-cli package test -t KubernetesContainerRunner --no-watch" - }, - "dependencies": { - "@aws-sdk/abort-controller": "^3.347.0", - "@aws-sdk/client-codecommit": "^3.350.0", - "@aws-sdk/client-s3": "^3.350.0", - "@aws-sdk/credential-providers": "^3.350.0", - "@aws-sdk/types": "^3.347.0", - "@backstage/backend-dev-utils": "workspace:^", - "@backstage/backend-plugin-api": "workspace:^", - "@backstage/cli-common": "workspace:^", - "@backstage/config": "workspace:^", - "@backstage/config-loader": "workspace:^", - "@backstage/errors": "workspace:^", - "@backstage/integration": "workspace:^", - "@backstage/integration-aws-node": "workspace:^", - "@backstage/plugin-auth-node": "workspace:^", - "@backstage/types": "workspace:^", - "@google-cloud/storage": "^7.0.0", - "@keyv/memcache": "^1.3.5", - "@keyv/redis": "^2.5.3", - "@kubernetes/client-node": "0.20.0", - "@manypkg/get-packages": "^1.1.3", - "@octokit/rest": "^19.0.3", - "@types/cors": "^2.8.6", - "@types/dockerode": "^3.3.0", - "@types/express": "^4.17.6", - "@types/luxon": "^3.0.0", - "@types/webpack-env": "^1.15.2", - "archiver": "^7.0.0", - "base64-stream": "^1.0.0", - "compression": "^1.7.4", - "concat-stream": "^2.0.0", - "cors": "^2.8.5", - "dockerode": "^4.0.0", - "express": "^4.17.1", - "express-promise-router": "^4.1.0", - "fs-extra": "^11.2.0", - "git-url-parse": "^14.0.0", - "helmet": "^6.0.0", - "isomorphic-git": "^1.23.0", - "jose": "^5.0.0", - "keyv": "^4.5.2", - "knex": "^3.0.0", - "lodash": "^4.17.21", - "logform": "^2.3.2", - "luxon": "^3.0.0", - "minimatch": "^9.0.0", - "minimist": "^1.2.5", - "morgan": "^1.10.0", - "mysql2": "^3.0.0", - "node-fetch": "^2.7.0", - "node-forge": "^1.3.1", - "p-limit": "^3.1.0", - "path-to-regexp": "^8.0.0", - "pg": "^8.11.3", - "pg-format": "^1.0.4", - "raw-body": "^2.4.1", - "selfsigned": "^2.0.0", - "stoppable": "^1.1.0", - "tar": "^6.1.12", - "triple-beam": "^1.4.1", - "uuid": "^9.0.0", - "winston": "^3.2.1", - "winston-transport": "^4.5.0", - "yauzl": "^3.0.0", - "yn": "^4.0.0" - }, - "devDependencies": { - "@aws-sdk/util-stream-node": "^3.350.0", - "@backstage/backend-test-utils": "workspace:^", - "@backstage/cli": "workspace:^", - "@types/archiver": "^6.0.0", - "@types/base64-stream": "^1.0.2", - "@types/compression": "^1.7.0", - "@types/concat-stream": "^2.0.0", - "@types/fs-extra": "^11.0.0", - "@types/http-errors": "^2.0.0", - "@types/morgan": "^1.9.0", - "@types/node-forge": "^1.3.0", - "@types/pg": "^8.6.6", - "@types/stoppable": "^1.1.0", - "@types/supertest": "^2.0.8", - "@types/tar": "^6.1.1", - "@types/webpack-env": "^1.15.2", - "@types/yauzl": "^2.10.0", - "aws-sdk-client-mock": "^4.0.0", - "better-sqlite3": "^11.0.0", - "http-errors": "^2.0.0", - "msw": "^1.0.0", - "mysql2": "^3.0.0", - "supertest": "^7.0.0" - }, - "peerDependencies": { - "pg-connection-string": "^2.3.0" - }, - "peerDependenciesMeta": { - "pg-connection-string": { - "optional": true - } - }, - "configSchema": "config.d.ts", - "deprecated": "This package is deprecated, please follow the deprecation instructions for the exports you still use" -} diff --git a/packages/backend-common/src/alpha.ts b/packages/backend-common/src/alpha.ts deleted file mode 100644 index 0fd15459fe..0000000000 --- a/packages/backend-common/src/alpha.ts +++ /dev/null @@ -1,17 +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. - */ - -export * from './deprecated/context'; diff --git a/packages/backend-common/src/compat/auth/createLegacyAuthAdapters.test.ts b/packages/backend-common/src/compat/auth/createLegacyAuthAdapters.test.ts deleted file mode 100644 index 49494761bf..0000000000 --- a/packages/backend-common/src/compat/auth/createLegacyAuthAdapters.test.ts +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { createLegacyAuthAdapters } from './createLegacyAuthAdapters'; -import { Request } from 'express'; -import { TokenManager } from '../../deprecated'; - -const mockTokenManager: TokenManager = { - async getToken(): Promise<{ token: string }> { - return { token: 'mock-token' }; - }, - async authenticate(token: string): Promise { - if (token !== 'mock-token') { - throw new Error('Invalid token'); - } - }, -}; - -describe('createLegacyAuthAdapters', () => { - it('should pass through auth if only auth is provided', () => { - const auth = {}; - const ret = createLegacyAuthAdapters({ - auth: auth as any, - tokenManager: mockTokenManager, - discovery: {} as any, - }); - - expect(ret.auth).toBe(auth); - }); - - it('should pass through httpAuth if only httpAuth is provided', () => { - const httpAuth = {}; - const ret = createLegacyAuthAdapters({ - httpAuth: httpAuth as any, - tokenManager: mockTokenManager, - discovery: {} as any, - }); - - expect(ret.httpAuth).toBe(httpAuth); - }); - - it('should pass through both auth and httpAuth if both are provided', () => { - const auth = {}; - const httpAuth = {}; - const ret = createLegacyAuthAdapters({ - auth: auth as any, - httpAuth: httpAuth as any, - tokenManager: mockTokenManager, - discovery: {} as any, - }); - - expect(ret.auth).toBe(auth); - expect(ret.httpAuth).toBe(httpAuth); - }); - - it('should pass through userInfo if it is provided', () => { - const auth = {}; - const userInfo = {}; - const ret = createLegacyAuthAdapters({ - auth: auth as any, - userInfo: userInfo as any, - tokenManager: mockTokenManager, - discovery: {} as any, - }); - - expect(ret.auth).toBe(auth); - expect(ret.userInfo).toBe(userInfo); - }); - - it('should adapt all services if none are provided', () => { - const ret = createLegacyAuthAdapters({ - auth: undefined, - httpAuth: undefined, - tokenManager: mockTokenManager, - discovery: {} as any, - }); - - expect(ret).toEqual({ - auth: expect.any(Object), - httpAuth: expect.any(Object), - userInfo: expect.any(Object), - }); - }); - - it('should forward tokens if no token manager is provided', async () => { - const { auth, httpAuth } = createLegacyAuthAdapters({ - auth: undefined, - httpAuth: undefined, - discovery: {} as any, - }); - - const credentials = await httpAuth.credentials({ - headers: { - authorization: 'Bearer my-token', - }, - } as Request); - - await expect( - auth.getPluginRequestToken({ - onBehalfOf: credentials, - targetPluginId: 'test', - }), - ).resolves.toEqual({ token: 'my-token' }); - }); - - it('should issue a new token if a token manager is provided', async () => { - const { auth, httpAuth } = createLegacyAuthAdapters({ - auth: undefined, - httpAuth: undefined, - tokenManager: { - ...mockTokenManager, - async getToken() { - return { token: 'new-token' }; - }, - }, - discovery: {} as any, - }); - - const credentials = await httpAuth.credentials({ - headers: { - authorization: 'Bearer mock-token', - }, - } as Request); - - await expect( - auth.getPluginRequestToken({ - onBehalfOf: credentials, - targetPluginId: 'test', - }), - ).resolves.toEqual({ token: 'new-token' }); - }); -}); diff --git a/packages/backend-common/src/compat/auth/createLegacyAuthAdapters.ts b/packages/backend-common/src/compat/auth/createLegacyAuthAdapters.ts deleted file mode 100644 index fc02d936d1..0000000000 --- a/packages/backend-common/src/compat/auth/createLegacyAuthAdapters.ts +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - AuthService, - BackstageCredentials, - BackstageNonePrincipal, - BackstagePrincipalTypes, - BackstageServicePrincipal, - BackstageUserInfo, - BackstageUserPrincipal, - HttpAuthService, - UserInfoService, -} from '@backstage/backend-plugin-api'; -import { AuthenticationError, NotAllowedError } from '@backstage/errors'; -import type { Request, Response } from 'express'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { - createCredentialsWithServicePrincipal, - createCredentialsWithUserPrincipal, - createCredentialsWithNonePrincipal, - toInternalBackstageCredentials, -} from '../../../../backend-defaults/src/entrypoints/auth/helpers'; -// TODO is this circular thingy a problem? Test in e2e -import { - type IdentityApiGetIdentityRequest, - DefaultIdentityClient, -} from '@backstage/plugin-auth-node'; -import { decodeJwt } from 'jose'; -import { TokenManager, PluginEndpointDiscovery } from '../../deprecated'; -import { JsonObject } from '@backstage/types'; -import { LegacyIdentityService } from '../legacy'; - -class AuthCompat implements AuthService { - constructor( - private readonly identity: LegacyIdentityService, - private readonly tokenManager?: TokenManager, - ) {} - - isPrincipal( - credentials: BackstageCredentials, - type: TType, - ): credentials is BackstageCredentials { - const principal = credentials.principal as - | BackstageUserPrincipal - | BackstageServicePrincipal; - - if (principal.type !== type) { - return false; - } - - return true; - } - - async getNoneCredentials(): Promise< - BackstageCredentials - > { - return createCredentialsWithNonePrincipal(); - } - - async getOwnServiceCredentials(): Promise< - BackstageCredentials - > { - return createCredentialsWithServicePrincipal('external:backstage-plugin'); - } - - async authenticate(token: string): Promise { - // Defensively check whether it seems token-like first, just to support - // custom TokenManager implementations that don't emit JWTs specifically. - const payload = - token.split('.').length === 3 ? decodeJwt(token) : undefined; - - if (payload?.aud === 'backstage') { - // User Backstage token - const identity = await this.identity.getIdentity({ - request: { - headers: { authorization: `Bearer ${token}` }, - }, - } as IdentityApiGetIdentityRequest); - - if (!identity) { - throw new AuthenticationError('Invalid user token'); - } - - return createCredentialsWithUserPrincipal( - identity.identity.userEntityRef, - token, - this.#getJwtExpiration(token), - ); - } - - await this.tokenManager?.authenticate(token); - - return createCredentialsWithServicePrincipal( - 'external:backstage-plugin', - token, - ); - } - - async getPluginRequestToken(options: { - onBehalfOf: BackstageCredentials; - targetPluginId: string; - }): Promise<{ token: string }> { - const internalForward = toInternalBackstageCredentials(options.onBehalfOf); - const { type } = internalForward.principal; - - switch (type) { - // TODO: Check whether the principal is ourselves - case 'service': { - if (this.tokenManager) { - return this.tokenManager.getToken(); - } - return { token: internalForward.token ?? '' }; - } - case 'user': - if (!internalForward.token) { - throw new Error('User credentials is unexpectedly missing token'); - } - return { token: internalForward.token }; - // NOTE: this is not the behavior of this service in the new backend system, it only applies - // here since we'll need to accept and forward requests without authentication. - case 'none': - return { token: '' }; - default: - throw new AuthenticationError( - `Refused to issue service token for credential type '${type}'`, - ); - } - } - - async getLimitedUserToken( - credentials: BackstageCredentials, - ): Promise<{ token: string; expiresAt: Date }> { - const internalCredentials = toInternalBackstageCredentials(credentials); - - const { token } = internalCredentials; - - if (!token) { - throw new AuthenticationError( - 'User credentials is unexpectedly missing token', - ); - } - - return { token, expiresAt: this.#getJwtExpiration(token) }; - } - - #getJwtExpiration(token: string) { - const { exp } = decodeJwt(token); - if (!exp) { - throw new AuthenticationError('User token is missing expiration'); - } - return new Date(exp * 1000); - } - - listPublicServiceKeys(): Promise<{ keys: JsonObject[] }> { - throw new Error('Not implemented'); - } -} - -function getTokenFromRequest(req: Request) { - // TODO: support multiple auth headers (iterate rawHeaders) - const authHeader = req.headers.authorization; - if (typeof authHeader === 'string') { - const matches = authHeader.match(/^Bearer[ ]+(\S+)$/i); - const token = matches?.[1]; - if (token) { - return token; - } - } - - return undefined; -} - -const credentialsSymbol = Symbol('backstage-credentials'); - -type RequestWithCredentials = Request & { - [credentialsSymbol]?: Promise; -}; - -class HttpAuthCompat implements HttpAuthService { - #auth: AuthService; - - constructor(auth: AuthService) { - this.#auth = auth; - } - - async #extractCredentialsFromRequest(req: Request) { - const token = getTokenFromRequest(req); - if (!token) { - return this.#auth.getNoneCredentials(); - } - - return this.#auth.authenticate(token); - } - - async #getCredentials(req: RequestWithCredentials) { - return (req[credentialsSymbol] ??= - this.#extractCredentialsFromRequest(req)); - } - - async credentials( - req: Request, - options?: { - allow?: Array; - allowLimitedAccess?: boolean; - }, - ): Promise> { - const credentials = await this.#getCredentials(req); - - const allowed = options?.allow; - if (!allowed) { - return credentials as any; - } - - if (this.#auth.isPrincipal(credentials, 'none')) { - if (allowed.includes('none' as TAllowed)) { - return credentials as any; - } - - throw new AuthenticationError('Missing credentials'); - } else if (this.#auth.isPrincipal(credentials, 'user')) { - if (allowed.includes('user' as TAllowed)) { - return credentials as any; - } - - throw new NotAllowedError( - `This endpoint does not allow 'user' credentials`, - ); - } else if (this.#auth.isPrincipal(credentials, 'service')) { - if (allowed.includes('service' as TAllowed)) { - return credentials as any; - } - - throw new NotAllowedError( - `This endpoint does not allow 'service' credentials`, - ); - } - - throw new NotAllowedError( - 'Unknown principal type, this should never happen', - ); - } - - async issueUserCookie(_res: Response): Promise<{ expiresAt: Date }> { - return { expiresAt: new Date(Date.now() + 3600_000) }; - } -} - -export class UserInfoCompat implements UserInfoService { - async getUserInfo( - credentials: BackstageCredentials, - ): Promise { - const internalCredentials = toInternalBackstageCredentials(credentials); - if (internalCredentials.principal.type !== 'user') { - throw new Error('Only user credentials are supported'); - } - if (!internalCredentials.token) { - throw new Error('User credentials is unexpectedly missing token'); - } - const { sub: userEntityRef, ent: ownershipEntityRefs = [] } = decodeJwt( - internalCredentials.token, - ); - - if (typeof userEntityRef !== 'string') { - throw new Error('User entity ref must be a string'); - } - if ( - !Array.isArray(ownershipEntityRefs) || - ownershipEntityRefs.some(ref => typeof ref !== 'string') - ) { - throw new Error('Ownership entity refs must be an array of strings'); - } - - return { userEntityRef, ownershipEntityRefs }; - } -} - -/** - * An adapter that ensures presence of the auth and/or httpAuth services. - * @public - * @deprecated Migrate to use the new backend system and auth services instead. - */ -export function createLegacyAuthAdapters< - TOptions extends { - auth?: AuthService; - httpAuth?: HttpAuthService; - userInfo?: UserInfoService; - identity?: LegacyIdentityService; - tokenManager?: TokenManager; - discovery: PluginEndpointDiscovery; - }, - TAdapters = (TOptions extends { auth?: AuthService } - ? { auth: AuthService } - : {}) & - (TOptions extends { httpAuth?: HttpAuthService } - ? { httpAuth: HttpAuthService } - : {}) & - (TOptions extends { userInfo?: UserInfoService } - ? { userInfo: UserInfoService } - : {}), ->(options: TOptions): TAdapters { - const { - auth, - httpAuth, - userInfo = new UserInfoCompat(), - discovery, - } = options; - - if (auth && httpAuth) { - return { - auth, - httpAuth, - userInfo, - } as TAdapters; - } - - if (auth) { - return { - auth, - userInfo, - } as TAdapters; - } - - if (httpAuth) { - return { - httpAuth, - userInfo, - } as TAdapters; - } - - const identity = - options.identity ?? DefaultIdentityClient.create({ discovery }); - - const authImpl = new AuthCompat(identity, options.tokenManager); - - const httpAuthImpl = new HttpAuthCompat(authImpl); - - return { - auth: authImpl, - httpAuth: httpAuthImpl, - userInfo, - } as TAdapters; -} diff --git a/packages/backend-common/src/compat/auth/index.ts b/packages/backend-common/src/compat/auth/index.ts deleted file mode 100644 index c92ecdce25..0000000000 --- a/packages/backend-common/src/compat/auth/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { createLegacyAuthAdapters } from './createLegacyAuthAdapters'; diff --git a/packages/backend-common/src/compat/cache/cacheToPluginCacheManager.ts b/packages/backend-common/src/compat/cache/cacheToPluginCacheManager.ts deleted file mode 100644 index 2ae55b016f..0000000000 --- a/packages/backend-common/src/compat/cache/cacheToPluginCacheManager.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - CacheService, - CacheServiceOptions, -} from '@backstage/backend-plugin-api'; - -/** - * Compatibility wrapper for going from a new-backend cache service to the - * old-backend plugin cache manager. - * - * @public - * @deprecated Migrate to use the new CacheService instead. - */ -export function cacheToPluginCacheManager(cache: CacheService): { - getClient(options?: CacheServiceOptions): CacheService; -} { - return { - getClient: (opts: CacheServiceOptions) => cache.withOptions(opts), - }; -} diff --git a/packages/backend-common/src/compat/cache/index.ts b/packages/backend-common/src/compat/cache/index.ts deleted file mode 100644 index bdd857037b..0000000000 --- a/packages/backend-common/src/compat/cache/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { cacheToPluginCacheManager } from './cacheToPluginCacheManager'; diff --git a/packages/backend-common/src/compat/index.ts b/packages/backend-common/src/compat/index.ts deleted file mode 100644 index d702772335..0000000000 --- a/packages/backend-common/src/compat/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export * from './legacy'; -export * from './auth'; -export * from './cache'; -export * from './logging'; diff --git a/packages/backend-common/src/compat/legacy/index.ts b/packages/backend-common/src/compat/legacy/index.ts deleted file mode 100644 index 7e0646342f..0000000000 --- a/packages/backend-common/src/compat/legacy/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { legacyPlugin, makeLegacyPlugin } from './legacy'; -export type { LegacyCreateRouter, LegacyIdentityService } from './legacy'; diff --git a/packages/backend-common/src/compat/legacy/legacy.test.ts b/packages/backend-common/src/compat/legacy/legacy.test.ts deleted file mode 100644 index b7a5ff1a78..0000000000 --- a/packages/backend-common/src/compat/legacy/legacy.test.ts +++ /dev/null @@ -1,170 +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 { - coreServices, - createBackendPlugin, -} from '@backstage/backend-plugin-api'; -import { - mockCredentials, - mockServices, - startTestBackend, -} from '@backstage/backend-test-utils'; -import { EventEmitter } from 'events'; -import { Router } from 'express'; -import request from 'supertest'; -import { createLegacyAuthAdapters } from '..'; -import { legacyPlugin } from './legacy'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { authServiceFactory } from '../../../../backend-defaults/src/entrypoints/auth'; - -describe('legacyPlugin', () => { - it('can auth across the new and old systems', async () => { - const emitter = new EventEmitter(); - - const done = new Promise(resolve => { - emitter.once('done', () => { - emitter.once('done', resolve); - }); - }); - - await startTestBackend({ - features: [ - authServiceFactory, - mockServices.rootConfig.factory({ - data: { - backend: { - auth: { - keys: [ - { - secret: 'test', - }, - ], - }, - }, - }, - }), - createBackendPlugin({ - pluginId: 'new', - register(reg) { - reg.registerInit({ - deps: { - auth: coreServices.auth, - discovery: coreServices.discovery, - }, - async init({ auth }) { - emitter.once('legacy-token', async otherToken => { - const credentials = await auth.authenticate(otherToken); - expect(credentials.principal).toEqual({ - type: 'service', - subject: 'external:backstage-plugin', - }); - emitter.emit('done'); - }); - - const { token } = await auth.getPluginRequestToken({ - onBehalfOf: await auth.getOwnServiceCredentials(), - targetPluginId: 'old', - }); - emitter.emit('new-token', token); - }, - }); - }, - }), - legacyPlugin( - 'old', - Promise.resolve({ - async default({ tokenManager, identity, discovery }) { - const { auth } = createLegacyAuthAdapters({ - tokenManager, - identity, - discovery, - auth: undefined as any as typeof coreServices.auth.T, - httpAuth: undefined as any as typeof coreServices.httpAuth.T, - }); - - emitter.once('new-token', async otherToken => { - const credentials = await auth.authenticate(otherToken); - expect(credentials.principal).toEqual({ - type: 'service', - subject: 'external:backstage-plugin', - }); - emitter.emit('done'); - }); - - const { token } = await tokenManager.getToken(); - emitter.emit('legacy-token', token); - - return Router(); - }, - }), - ), - ], - }); - - await done; - }); - - it('can auth users with the identity service shim', async () => { - const backend = await startTestBackend({ - features: [ - mockServices.rootConfig.factory({ - data: { - backend: { - auth: { - keys: [ - { - secret: 'test', - }, - ], - }, - }, - }, - }), - legacyPlugin( - 'test', - Promise.resolve({ - async default({ identity }) { - const router = Router(); - - router.get('/', async (req, res) => { - const user = await identity.getIdentity({ request: req }); - res.json(user); - }); - - return router; - }, - }), - ), - ], - }); - - const res = await request(backend.server) - .get('/api/test') - .set('authorization', mockCredentials.user.header()); - - const mockUserRef = mockCredentials.user().principal.userEntityRef; - expect(res.status).toBe(200); - expect(res.body).toEqual({ - token: mockCredentials.user.token(), - identity: { - type: 'user', - userEntityRef: mockUserRef, - ownershipEntityRefs: [mockUserRef], - }, - }); - }); -}); diff --git a/packages/backend-common/src/compat/legacy/legacy.ts b/packages/backend-common/src/compat/legacy/legacy.ts deleted file mode 100644 index bf051f3040..0000000000 --- a/packages/backend-common/src/compat/legacy/legacy.ts +++ /dev/null @@ -1,254 +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 { - AuthService, - coreServices, - createBackendPlugin, - LoggerService, - RootConfigService, - ServiceRef, - UserInfoService, -} from '@backstage/backend-plugin-api'; -import { RequestHandler } from 'express'; -import { cacheToPluginCacheManager } from '../cache'; -import { loggerToWinstonLogger } from '../logging'; -import { ServerTokenManager, TokenManager } from '../../deprecated'; -import { Request } from 'express'; - -/** - * @public - * @deprecated Fully use the new backend system instead. - */ -export type LegacyCreateRouter = (deps: TEnv) => Promise; - -/** @ignore */ -type TransformedEnv< - TEnv extends Record, - TEnvTransforms extends { [key in keyof TEnv]?: (dep: TEnv[key]) => unknown }, -> = { - [key in keyof TEnv]: TEnvTransforms[key] extends (dep: TEnv[key]) => infer R - ? R - : TEnv[key]; -}; - -// Since the plugin will be using the new system our callers will expect us to support the -// new plugin tokens, which we'll also be signaling by supporting the JWKS endpoint through -// the http router. -// This makes sure that we accept the new plugin tokens as valid tokens, but otherwise fall -// back to the legacy token manager. -function createTokenManagerShim( - auth: AuthService, - config: RootConfigService, - logger: LoggerService, -): TokenManager { - const tokenManager = ServerTokenManager.fromConfig(config, { logger }); - return { - async getToken() { - return tokenManager.getToken(); - }, - async authenticate(token) { - if (token) { - // Unless it's a valid service token, we'll let the token manager do - // validation. We'll throw if we for example receive an invalid user - // token here, but that's what the token manager does too. - const credentials = await auth.authenticate(token); - if (auth.isPrincipal(credentials, 'service')) { - return; - } - } - await tokenManager.authenticate(token); - }, - }; -} - -/** - * Originally IdentityApi from `@backstage/plugin-auth-node`, re-declared here for backwards compatibility - * @public - * @deprecated Only relevant for legacy plugins, which are deprecated. - */ -export interface LegacyIdentityService { - getIdentity(options: { request: Request }): Promise< - | { - expiresInSeconds?: number; - - token: string; - identity: { - type: 'user'; - userEntityRef: string; - ownershipEntityRefs: string[]; - }; - } - | undefined - >; -} - -// This doesn't use DefaultIdentityClient because we will be removing it and break support for ownershipEntityRefs -function createIdentityServiceShim( - auth: AuthService, - userInfo: UserInfoService, -): LegacyIdentityService { - return { - async getIdentity(options) { - const authHeader = options.request.headers.authorization; - if (typeof authHeader !== 'string') { - return undefined; - } - - const token = authHeader.match(/^Bearer[ ]+(\S+)$/i)?.[1]; - if (!token) { - return undefined; - } - - const credentials = await auth.authenticate(token); - if (!auth.isPrincipal(credentials, 'user')) { - return undefined; - } - - const info = await userInfo.getUserInfo(credentials); - - return { - token, - identity: { - type: 'user', - userEntityRef: info.userEntityRef, - ownershipEntityRefs: info.ownershipEntityRefs, - }, - }; - }, - }; -} - -/** - * Creates a new custom plugin compatibility wrapper. - * - * @public - * @deprecated Fully use the new backend system instead. - * @remarks - * - * Usually you can use {@link legacyPlugin} directly instead, but you might - * need to use this if you have customized the plugin environment in your backend. - */ -export function makeLegacyPlugin< - TEnv extends Record, - TEnvTransforms extends { [key in keyof TEnv]?: (dep: TEnv[key]) => unknown }, ->( - envMapping: { [key in keyof TEnv]: ServiceRef }, - envTransforms: TEnvTransforms, -) { - return ( - name: string, - createRouterImport: Promise<{ - default: LegacyCreateRouter< - TransformedEnv & { - tokenManager: TokenManager; - identity: LegacyIdentityService; - } - >; - }>, - ) => { - return createBackendPlugin({ - pluginId: name, - register(env) { - env.registerInit({ - deps: { - ...envMapping, - $$router: coreServices.httpRouter, - $$auth: coreServices.auth, - $$userInfo: coreServices.userInfo, - $$config: coreServices.rootConfig, - $$logger: coreServices.logger, - }, - async init({ - $$auth, - $$config, - $$logger, - $$router, - $$userInfo, - ...envDeps - }) { - const { default: createRouter } = await createRouterImport; - const pluginEnv = Object.fromEntries( - Object.entries(envDeps).map(([key, dep]) => { - const transform = envTransforms[key]; - if (transform) { - return [key, transform(dep)]; - } - return [key, dep]; - }), - ); - - const auth = $$auth as typeof coreServices.auth.T; - const config = $$config as typeof coreServices.rootConfig.T; - const logger = $$logger as typeof coreServices.logger.T; - const router = $$router as typeof coreServices.httpRouter.T; - const userInfo = $$userInfo as typeof coreServices.userInfo.T; - - // Token manager and identity services are no longer supported in the new backend system, so we provide shims for them. - pluginEnv.tokenManager = createTokenManagerShim( - auth, - config, - logger, - ); - pluginEnv.identity = createIdentityServiceShim(auth, userInfo); - - const pluginRouter = await createRouter( - pluginEnv as TransformedEnv & { - tokenManager: TokenManager; - identity: LegacyIdentityService; - }, - ); - router.use(pluginRouter); - }, - }); - }, - }); - }; -} - -/** - * Helper function to create a plugin from a legacy createRouter function and - * register it with the http router based on the plugin id. - * - * @public - * @deprecated Fully use the new backend system instead. - * @remarks - * - * This is intended to be used by plugin authors to ease the transition to the - * new backend system. - * - * @example - * - *```ts - *backend.add(legacyPlugin('kafka', import('./plugins/kafka'))); - *``` - */ -export const legacyPlugin = makeLegacyPlugin( - { - cache: coreServices.cache, - config: coreServices.rootConfig, - database: coreServices.database, - discovery: coreServices.discovery, - logger: coreServices.logger, - permissions: coreServices.permissions, - scheduler: coreServices.scheduler, - reader: coreServices.urlReader, - }, - { - logger: log => loggerToWinstonLogger(log), - cache: cache => cacheToPluginCacheManager(cache), - }, -); diff --git a/packages/backend-common/src/compat/logging/index.ts b/packages/backend-common/src/compat/logging/index.ts deleted file mode 100644 index 10f949050c..0000000000 --- a/packages/backend-common/src/compat/logging/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { loggerToWinstonLogger } from './loggerToWinstonLogger'; diff --git a/packages/backend-common/src/compat/logging/loggerToWinstonLogger.ts b/packages/backend-common/src/compat/logging/loggerToWinstonLogger.ts deleted file mode 100644 index 83871f48e3..0000000000 --- a/packages/backend-common/src/compat/logging/loggerToWinstonLogger.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2022 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { LoggerService } from '@backstage/backend-plugin-api'; -import { JsonObject } from '@backstage/types'; -import { Logger as WinstonLogger, createLogger } from 'winston'; -import Transport, { TransportStreamOptions } from 'winston-transport'; - -class BackstageLoggerTransport extends Transport { - constructor( - private readonly backstageLogger: LoggerService, - opts?: TransportStreamOptions, - ) { - super(opts); - } - - log(info: unknown, callback: VoidFunction) { - if (typeof info !== 'object' || info === null) { - callback(); - return; - } - const { level, message, ...meta } = info as JsonObject; - switch (level) { - case 'error': - this.backstageLogger.error(String(message), meta); - break; - case 'warn': - this.backstageLogger.warn(String(message), meta); - break; - case 'info': - this.backstageLogger.info(String(message), meta); - break; - case 'debug': - this.backstageLogger.debug(String(message), meta); - break; - default: - this.backstageLogger.info(String(message), meta); - } - callback(); - } -} - -/** - * @public - * @deprecated Migrate to use the new LoggerService instead. - */ -export function loggerToWinstonLogger( - logger: LoggerService, - opts?: TransportStreamOptions, -): WinstonLogger { - return createLogger({ - transports: [new BackstageLoggerTransport(logger, opts)], - }); -} diff --git a/packages/backend-common/src/deprecated/config/ObservableConfigProxy.test.ts b/packages/backend-common/src/deprecated/config/ObservableConfigProxy.test.ts deleted file mode 100644 index 876f5ac7d3..0000000000 --- a/packages/backend-common/src/deprecated/config/ObservableConfigProxy.test.ts +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { ConfigReader } from '@backstage/config'; -import { ObservableConfigProxy } from './ObservableConfigProxy'; - -describe('ObservableConfigProxy', () => { - it('should notify subscribers', () => { - const config = new ObservableConfigProxy(); - - const fn = jest.fn(); - const sub = config.subscribe(fn); - expect(config.getOptionalNumber('x')).toBe(undefined); - - config.setConfig(new ConfigReader({})); - expect(fn).toHaveBeenCalledTimes(1); - expect(config.getOptionalNumber('x')).toBe(undefined); - - config.setConfig(new ConfigReader({ x: 1 })); - expect(fn).toHaveBeenCalledTimes(2); - expect(config.getOptionalNumber('x')).toBe(1); - - config.setConfig(new ConfigReader({ x: 3 })); - expect(fn).toHaveBeenCalledTimes(3); - sub.unsubscribe(); - expect(config.getOptionalNumber('x')).toBe(3); - - config.setConfig(new ConfigReader({ x: 5 })); - expect(fn).toHaveBeenCalledTimes(3); - expect(config.getOptionalNumber('x')).toBe(5); - }); - - it('should forward subscriptions', () => { - const config1 = new ObservableConfigProxy(); - - const fn1 = jest.fn(); - const fn2 = jest.fn(); - const fn3 = jest.fn(); - const config2 = config1.getConfig('a'); - const config3 = config2.getConfig('b'); - const sub1 = config1.subscribe(fn1); - const sub2 = config2.subscribe!(fn2); - const sub3 = config3.subscribe!(fn3); - expect(config1.getOptionalNumber('x')).toBe(undefined); - expect(config2.getOptionalNumber('x')).toBe(undefined); - expect(config3.getOptionalNumber('x')).toBe(undefined); - - config1.setConfig(new ConfigReader({})); - expect(fn1).toHaveBeenCalledTimes(1); - expect(fn2).toHaveBeenCalledTimes(1); - expect(fn3).toHaveBeenCalledTimes(1); - expect(config1.getOptionalNumber('x')).toBe(undefined); - expect(config2.getOptionalNumber('x')).toBe(undefined); - expect(config3.getOptionalNumber('x')).toBe(undefined); - - config1.setConfig(new ConfigReader({ x: 1, a: { x: 2, b: { x: 3 } } })); - expect(fn1).toHaveBeenCalledTimes(2); - expect(fn2).toHaveBeenCalledTimes(2); - expect(fn3).toHaveBeenCalledTimes(2); - expect(config1.getNumber('x')).toBe(1); - expect(config2.getNumber('x')).toBe(2); - expect(config3.getNumber('x')).toBe(3); - - sub1.unsubscribe(); - sub2.unsubscribe(); - sub3.unsubscribe(); - - config1.setConfig(new ConfigReader({ x: 4, a: { x: 5, b: { x: 6 } } })); - expect(fn1).toHaveBeenCalledTimes(2); - expect(fn2).toHaveBeenCalledTimes(2); - expect(fn3).toHaveBeenCalledTimes(2); - expect(config1.getNumber('x')).toBe(4); - expect(config2.getNumber('x')).toBe(5); - expect(config3.getNumber('x')).toBe(6); - - config1.setConfig(new ConfigReader({})); - expect(() => config1.getNumber('x')).toThrow( - "Missing required config value at 'x'", - ); - expect(() => config2.getNumber('x')).toThrow( - "Missing required config value at 'a'", - ); - expect(() => config3.getNumber('x')).toThrow( - "Missing required config value at 'a'", - ); - - config1.setConfig( - new ConfigReader({ x: 's', a: { x: 's', b: { x: 's' } } }), - ); - expect(() => config1.getNumber('x')).toThrow( - "Unable to convert config value for key 'x' in 'mock-config' to a number", - ); - expect(() => config2.getNumber('x')).toThrow( - "Unable to convert config value for key 'a.x' in 'mock-config' to a number", - ); - expect(() => config3.getNumber('x')).toThrow( - "Unable to convert config value for key 'a.b.x' in 'mock-config' to a number", - ); - }); - - it('should make sub configs available as expected', () => { - const config = new ObservableConfigProxy(); - - config.setConfig(new ConfigReader({ a: { x: 1 } })); - - expect(config.getConfig('a')).toBeDefined(); - expect(config.getConfig('a').getNumber('x')).toBe(1); - expect(config.getConfig('a').getOptionalNumber('x')).toBe(1); - expect(config.getOptionalConfig('a')?.getNumber('x')).toBe(1); - expect(config.getOptionalConfig('a')?.getOptionalNumber('x')).toBe(1); - expect(config.getOptionalConfig('b')).toBeUndefined(); - expect(() => config.getConfig('b')).toBeDefined(); - expect(() => config.getConfig('b').get()).toThrow(); - }); -}); diff --git a/packages/backend-common/src/deprecated/config/ObservableConfigProxy.ts b/packages/backend-common/src/deprecated/config/ObservableConfigProxy.ts deleted file mode 100644 index 8c8d3b553f..0000000000 --- a/packages/backend-common/src/deprecated/config/ObservableConfigProxy.ts +++ /dev/null @@ -1,128 +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 { Config, ConfigReader } from '@backstage/config'; -import { JsonValue } from '@backstage/types'; - -export class ObservableConfigProxy implements Config { - private config: Config = new ConfigReader({}); - - private readonly subscribers: (() => void)[] = []; - - constructor( - private readonly parent?: ObservableConfigProxy, - private parentKey?: string, - ) { - if (parent && !parentKey) { - throw new Error('parentKey is required if parent is set'); - } - } - - setConfig(config: Config) { - if (this.parent) { - throw new Error('immutable'); - } - this.config = config; - for (const subscriber of this.subscribers) { - try { - subscriber(); - } catch (error) { - console.error(`Config subscriber threw error, ${error}`); - } - } - } - - subscribe(onChange: () => void): { unsubscribe: () => void } { - if (this.parent) { - return this.parent.subscribe(onChange); - } - - this.subscribers.push(onChange); - return { - unsubscribe: () => { - const index = this.subscribers.indexOf(onChange); - if (index >= 0) { - this.subscribers.splice(index, 1); - } - }, - }; - } - - 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); - } - return this.parent.select(false)?.getOptionalConfig(this.parentKey); - } - - return this.config; - } - - has(key: string): boolean { - return this.select(false)?.has(key) ?? false; - } - keys(): string[] { - return this.select(false)?.keys() ?? []; - } - get(key?: string): T { - return this.select(true).get(key); - } - getOptional(key?: string): T | undefined { - return this.select(false)?.getOptional(key); - } - getConfig(key: string): Config { - return new ObservableConfigProxy(this, key); - } - getOptionalConfig(key: string): Config | undefined { - if (this.select(false)?.has(key)) { - return new ObservableConfigProxy(this, key); - } - return undefined; - } - getConfigArray(key: string): Config[] { - return this.select(true).getConfigArray(key); - } - getOptionalConfigArray(key: string): Config[] | undefined { - return this.select(false)?.getOptionalConfigArray(key); - } - getNumber(key: string): number { - return this.select(true).getNumber(key); - } - getOptionalNumber(key: string): number | undefined { - return this.select(false)?.getOptionalNumber(key); - } - getBoolean(key: string): boolean { - return this.select(true).getBoolean(key); - } - getOptionalBoolean(key: string): boolean | undefined { - return this.select(false)?.getOptionalBoolean(key); - } - getString(key: string): string { - return this.select(true).getString(key); - } - getOptionalString(key: string): string | undefined { - return this.select(false)?.getOptionalString(key); - } - getStringArray(key: string): string[] { - return this.select(true).getStringArray(key); - } - getOptionalStringArray(key: string): string[] | undefined { - return this.select(false)?.getOptionalStringArray(key); - } -} diff --git a/packages/backend-common/src/deprecated/config/config.test.ts b/packages/backend-common/src/deprecated/config/config.test.ts deleted file mode 100644 index 865b1b4d60..0000000000 --- a/packages/backend-common/src/deprecated/config/config.test.ts +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { loadConfigSchema } from '@backstage/config-loader'; -import { mockServices } from '@backstage/backend-test-utils'; -import { createConfigSecretEnumerator } from './config'; - -describe('createConfigSecretEnumerator', () => { - it('should enumerate secrets', async () => { - const logger = mockServices.logger.mock(); - - const enumerate = await createConfigSecretEnumerator({ - logger, - }); - const secrets = enumerate( - mockServices.rootConfig({ - data: { - backend: { auth: { keys: [{ secret: 'my-secret-password' }] } }, - }, - }), - ); - expect(Array.from(secrets)).toEqual(['my-secret-password']); - }, 20_000); // Bit higher timeout since we're loading all config schemas in the repo - - it('should enumerate secrets with explicit schema', async () => { - const logger = mockServices.logger.mock(); - - const enumerate = await createConfigSecretEnumerator({ - logger, - schema: await loadConfigSchema({ - serialized: { - schemas: [ - { - value: { - type: 'object', - properties: { - secret: { - visibility: 'secret', - type: 'string', - }, - }, - }, - path: '/mock', - }, - ], - backstageConfigSchemaVersion: 1, - }, - }), - }); - - const secrets = enumerate( - mockServices.rootConfig({ - data: { - secret: 'my-secret', - other: 'not-secret', - }, - }), - ); - expect(Array.from(secrets)).toEqual(['my-secret']); - }); -}); diff --git a/packages/backend-common/src/deprecated/config/config.ts b/packages/backend-common/src/deprecated/config/config.ts deleted file mode 100644 index d50476a9f2..0000000000 --- a/packages/backend-common/src/deprecated/config/config.ts +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { LoggerService } from '@backstage/backend-plugin-api'; -import { AppConfig, Config } from '@backstage/config'; -import { setRootLoggerRedactionList } from '../logging/createRootLogger'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { createConfigSecretEnumerator as _createConfigSecretEnumerator } from '../../../../backend-defaults/src/entrypoints/rootConfig/createConfigSecretEnumerator'; - -import { resolve as resolvePath } from 'path'; -import parseArgs from 'minimist'; -import { findPaths } from '@backstage/cli-common'; -import { - loadConfig, - ConfigTarget, - LoadConfigOptionsRemote, -} from '@backstage/config-loader'; -import { ConfigReader } from '@backstage/config'; -import { ObservableConfigProxy } from './ObservableConfigProxy'; -import { isValidUrl } from './urls'; - -/** - * @public - * @deprecated Please migrate to the new backend system and use `coreServices.rootConfig` instead, or the {@link @backstage/config-loader#ConfigSources} facilities if required. - */ -export const createConfigSecretEnumerator = _createConfigSecretEnumerator; - -/** - * Load configuration for a Backend. - * - * This function should only be called once, during the initialization of the backend. - * - * @public - * @deprecated Please migrate to the new backend system and use `coreServices.rootConfig` instead, or the {@link @backstage/config-loader#ConfigSources} facilities if required. - */ -export async function loadBackendConfig(options: { - logger: LoggerService; - // process.argv or any other overrides - remote?: LoadConfigOptionsRemote; - additionalConfigs?: AppConfig[]; - argv: string[]; - watch?: boolean; -}): Promise { - const secretEnumerator = await createConfigSecretEnumerator({ - logger: options.logger, - }); - const { config } = await newLoadBackendConfig(options); - - setRootLoggerRedactionList(secretEnumerator(config)); - config.subscribe?.(() => - setRootLoggerRedactionList(secretEnumerator(config)), - ); - - return config; -} - -async function newLoadBackendConfig(options: { - remote?: LoadConfigOptionsRemote; - argv: string[]; - additionalConfigs?: AppConfig[]; - watch?: boolean; -}): Promise<{ config: Config }> { - const args = parseArgs(options.argv); - - const configTargets: ConfigTarget[] = [args.config ?? []] - .flat() - .map(arg => (isValidUrl(arg) ? { url: arg } : { path: resolvePath(arg) })); - - /* eslint-disable-next-line no-restricted-syntax */ - const paths = findPaths(__dirname); - - let currentCancelFunc: (() => void) | undefined = undefined; - - const config = new ObservableConfigProxy(); - const { appConfigs } = await loadConfig({ - configRoot: paths.targetRoot, - configTargets: configTargets, - remote: options.remote, - watch: - options.watch ?? true - ? { - onChange(newConfigs) { - console.info( - `Reloaded config from ${newConfigs - .map(c => c.context) - .join(', ')}`, - ); - const configsToMerge = [...newConfigs]; - if (options.additionalConfigs) { - configsToMerge.push(...options.additionalConfigs); - } - config.setConfig(ConfigReader.fromConfigs(configsToMerge)); - }, - stopSignal: new Promise(resolve => { - if (currentCancelFunc) { - currentCancelFunc(); - } - currentCancelFunc = resolve; - - // TODO(Rugvip): We keep this here for now to avoid breaking the old system - // since this is re-used in backend-common - if (module.hot) { - module.hot.addDisposeHandler(resolve); - } - }), - } - : undefined, - }); - console.info( - `Loaded config from ${appConfigs.map(c => c.context).join(', ')}`, - ); - - const finalAppConfigs = [...appConfigs]; - if (options.additionalConfigs) { - finalAppConfigs.push(...options.additionalConfigs); - } - config.setConfig(ConfigReader.fromConfigs(finalAppConfigs)); - - return { config }; -} diff --git a/packages/backend-common/src/deprecated/config/index.ts b/packages/backend-common/src/deprecated/config/index.ts deleted file mode 100644 index c87193876c..0000000000 --- a/packages/backend-common/src/deprecated/config/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { loadBackendConfig, createConfigSecretEnumerator } from './config'; diff --git a/packages/backend-common/src/deprecated/config/urls.test.ts b/packages/backend-common/src/deprecated/config/urls.test.ts deleted file mode 100644 index c2a67fb849..0000000000 --- a/packages/backend-common/src/deprecated/config/urls.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { isValidUrl } from './urls'; - -describe('isValidUrl', () => { - it('should return true for url', () => { - const validUrl = isValidUrl('http://some.valid.url'); - expect(validUrl).toBe(true); - }); - - it('should return false for absolute path', () => { - const validUrl = isValidUrl('/some/absolute/path'); - expect(validUrl).toBe(false); - }); - - it('should return false for relative path', () => { - const validUrl = isValidUrl('../some/relative/path'); - expect(validUrl).toBe(false); - }); -}); diff --git a/packages/backend-common/src/deprecated/config/urls.ts b/packages/backend-common/src/deprecated/config/urls.ts deleted file mode 100644 index 848cea25d9..0000000000 --- a/packages/backend-common/src/deprecated/config/urls.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export function isValidUrl(url: string): boolean { - try { - // eslint-disable-next-line no-new - new URL(url); - return true; - } catch { - return false; - } -} diff --git a/packages/backend-common/src/deprecated/context/AbortContext.test.ts b/packages/backend-common/src/deprecated/context/AbortContext.test.ts deleted file mode 100644 index a6c522ffcf..0000000000 --- a/packages/backend-common/src/deprecated/context/AbortContext.test.ts +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbortContext } from './AbortContext'; -import { RootContext } from './RootContext'; - -describe('AbortContext', () => { - afterEach(() => { - jest.useRealTimers(); - }); - - describe('forTimeoutMillis', () => { - it('can abort on a timeout', async () => { - jest.useFakeTimers(); - const timeout = 200; - const deadline = Date.now() + timeout; - - const root = new RootContext(); - - const child = AbortContext.forTimeoutMillis(root, timeout); - const childListener = jest.fn(); - child.abortSignal.addEventListener('abort', childListener); - - expect(child.abortSignal.aborted).toBe(false); - expect(Math.abs(+child.deadline! - deadline)).toBeLessThan(50); - expect(childListener).toHaveBeenCalledTimes(0); - - jest.advanceTimersByTime(timeout + 1); - - expect(child.abortSignal.aborted).toBe(true); - expect(childListener).toHaveBeenCalledTimes(1); - }); - - it('results in minimum deadline when parent triggers sooner', async () => { - jest.useFakeTimers(); - const parentTimeout = 200; - const childTimeout = 300; - const parentDeadline = Date.now() + parentTimeout; - const childDeadline = parentDeadline; // clamped - - const root = new RootContext(); - - const parent = AbortContext.forTimeoutMillis(root, parentTimeout); - const parentListener = jest.fn(); - parent.abortSignal.addEventListener('abort', parentListener); - - const child = AbortContext.forTimeoutMillis(parent, childTimeout); - const childListener = jest.fn(); - child.abortSignal.addEventListener('abort', childListener); - - expect(parent.abortSignal.aborted).toBe(false); - expect(child.abortSignal.aborted).toBe(false); - expect(Math.abs(+parent.deadline! - parentDeadline)).toBeLessThan(50); - expect(Math.abs(+child.deadline! - childDeadline)).toBeLessThan(50); - expect(parentListener).toHaveBeenCalledTimes(0); - expect(childListener).toHaveBeenCalledTimes(0); - - jest.advanceTimersByTime(parentTimeout + 1); - - expect(parent.abortSignal.aborted).toBe(true); - expect(child.abortSignal.aborted).toBe(true); - expect(parentListener).toHaveBeenCalledTimes(1); - expect(childListener).toHaveBeenCalledTimes(1); - }); - - it('results in minimum deadline when child triggers sooner', async () => { - jest.useFakeTimers(); - const parentTimeout = 300; - const childTimeout = 200; - const parentDeadline = Date.now() + parentTimeout; - const childDeadline = Date.now() + childTimeout; - - const root = new RootContext(); - - const parent = AbortContext.forTimeoutMillis(root, parentTimeout); - const parentListener = jest.fn(); - parent.abortSignal.addEventListener('abort', parentListener); - - const child = AbortContext.forTimeoutMillis(parent, childTimeout); - const childListener = jest.fn(); - child.abortSignal.addEventListener('abort', childListener); - - expect(parent.abortSignal.aborted).toBe(false); - expect(child.abortSignal.aborted).toBe(false); - expect(Math.abs(+parent.deadline! - parentDeadline)).toBeLessThan(50); - expect(Math.abs(+child.deadline! - childDeadline)).toBeLessThan(50); - expect(parentListener).toHaveBeenCalledTimes(0); - expect(childListener).toHaveBeenCalledTimes(0); - - jest.advanceTimersByTime(childTimeout + 1); - - expect(parent.abortSignal.aborted).toBe(false); - expect(child.abortSignal.aborted).toBe(true); - expect(parentListener).toHaveBeenCalledTimes(0); - expect(childListener).toHaveBeenCalledTimes(1); - - jest.advanceTimersByTime(parentTimeout - childTimeout + 1); - - expect(parent.abortSignal.aborted).toBe(true); - expect(child.abortSignal.aborted).toBe(true); - expect(parentListener).toHaveBeenCalledTimes(1); - expect(childListener).toHaveBeenCalledTimes(1); - }); - - it('child carries over parent signal state if parent was already aborted and had no deadline', async () => { - jest.useFakeTimers(); - const childTimeout = 200; - const childDeadline = Date.now() + childTimeout; - - const root = new RootContext(); - - const parentController = new AbortController(); - const parent = AbortContext.forSignal(root, parentController.signal); - - parentController.abort(); - - const child = AbortContext.forTimeoutMillis(parent, childTimeout); - const childListener = jest.fn(); - child.abortSignal.addEventListener('abort', childListener); - - expect(child.abortSignal.aborted).toBe(true); - expect(childListener).toHaveBeenCalledTimes(0); - expect(Math.abs(+child.deadline! - childDeadline)).toBeLessThan(50); - - jest.advanceTimersByTime(childTimeout + 1); - - expect(child.abortSignal.aborted).toBe(true); - expect(childListener).toHaveBeenCalledTimes(0); // still - }); - - it('child carries over parent signal state if parent was already aborted and had a deadline', async () => { - jest.useFakeTimers(); - const first = new RootContext(); - - const secondController = new AbortController(); - const second = AbortContext.forSignal(first, secondController.signal); - secondController.abort(); - - const third = AbortContext.forTimeoutMillis(second, 200); - const fourth = AbortContext.forTimeoutMillis(third, 300); - - expect(third.abortSignal.aborted).toBe(true); - expect(fourth.abortSignal.aborted).toBe(true); - expect(Math.abs(+fourth.deadline! - Date.now() - 200)).toBeLessThan(50); - }); - }); - - describe('forController', () => { - it('signals child when parent is aborted', () => { - const root = new RootContext(); - - const parentController = new AbortController(); - const parent = AbortContext.forController(root, parentController); - const parentListener = jest.fn(); - parent.abortSignal.addEventListener('abort', parentListener); - - const childController = new AbortController(); - const child = AbortContext.forController(parent, childController); - const childListener = jest.fn(); - child.abortSignal.addEventListener('abort', childListener); - - expect(parent.abortSignal.aborted).toBe(false); - expect(child.abortSignal.aborted).toBe(false); - expect(parentListener).toHaveBeenCalledTimes(0); - expect(childListener).toHaveBeenCalledTimes(0); - - parentController.abort(); - - expect(parent.abortSignal.aborted).toBe(true); - expect(child.abortSignal.aborted).toBe(true); - expect(parentListener).toHaveBeenCalledTimes(1); - expect(childListener).toHaveBeenCalledTimes(1); - }); - - it('does not signal parent when child is aborted', async () => { - const root = new RootContext(); - - const parentController = new AbortController(); - const parent = AbortContext.forController(root, parentController); - const parentListener = jest.fn(); - parent.abortSignal.addEventListener('abort', parentListener); - - const childController = new AbortController(); - const child = AbortContext.forController(parent, childController); - const childListener = jest.fn(); - child.abortSignal.addEventListener('abort', childListener); - - expect(parent.abortSignal.aborted).toBe(false); - expect(child.abortSignal.aborted).toBe(false); - expect(parentListener).toHaveBeenCalledTimes(0); - expect(childListener).toHaveBeenCalledTimes(0); - - childController.abort(); - - expect(parent.abortSignal.aborted).toBe(false); - expect(child.abortSignal.aborted).toBe(true); - expect(parentListener).toHaveBeenCalledTimes(0); - expect(childListener).toHaveBeenCalledTimes(1); - }); - - it('child carries over parent signal state if parent was already aborted', async () => { - const root = new RootContext(); - - const parentController = new AbortController(); - const parent = AbortContext.forController(root, parentController); - - parentController.abort(); - - const childController = new AbortController(); - const child = AbortContext.forController(parent, childController); - const childListener = jest.fn(); - child.abortSignal.addEventListener('abort', childListener); - - expect(parent.abortSignal.aborted).toBe(true); - expect(child.abortSignal.aborted).toBe(true); - expect(childListener).toHaveBeenCalledTimes(0); - - childController.abort(); - - expect(parent.abortSignal.aborted).toBe(true); - expect(child.abortSignal.aborted).toBe(true); - expect(childListener).toHaveBeenCalledTimes(0); - }); - - it('child carries over given signal state if it was already aborted', async () => { - const root = new RootContext(); - - const childController = new AbortController(); - childController.abort(); - - const child = AbortContext.forController(root, childController); - const childListener = jest.fn(); - child.abortSignal.addEventListener('abort', childListener); - - expect(child.abortSignal.aborted).toBe(true); - expect(childListener).toHaveBeenCalledTimes(0); - }); - }); - - describe('forSignal', () => { - it('signals child when parent is aborted', async () => { - const root = new RootContext(); - - const parentController = new AbortController(); - const parent = AbortContext.forSignal(root, parentController.signal); - const parentListener = jest.fn(); - parent.abortSignal.addEventListener('abort', parentListener); - - const childController = new AbortController(); - const child = AbortContext.forSignal(parent, childController.signal); - const childListener = jest.fn(); - child.abortSignal.addEventListener('abort', childListener); - - expect(parent.abortSignal.aborted).toBe(false); - expect(child.abortSignal.aborted).toBe(false); - expect(parentListener).toHaveBeenCalledTimes(0); - expect(childListener).toHaveBeenCalledTimes(0); - - parentController.abort(); - - expect(parent.abortSignal.aborted).toBe(true); - expect(child.abortSignal.aborted).toBe(true); - expect(parentListener).toHaveBeenCalledTimes(1); - expect(childListener).toHaveBeenCalledTimes(1); - }); - - it('does not signal parent when child is aborted', async () => { - const root = new RootContext(); - - const parentController = new AbortController(); - const parent = AbortContext.forSignal(root, parentController.signal); - const parentListener = jest.fn(); - parent.abortSignal.addEventListener('abort', parentListener); - - const childController = new AbortController(); - const child = AbortContext.forSignal(parent, childController.signal); - const childListener = jest.fn(); - child.abortSignal.addEventListener('abort', childListener); - - expect(parent.abortSignal.aborted).toBe(false); - expect(child.abortSignal.aborted).toBe(false); - expect(parentListener).toHaveBeenCalledTimes(0); - expect(childListener).toHaveBeenCalledTimes(0); - - childController.abort(); - - expect(parent.abortSignal.aborted).toBe(false); - expect(child.abortSignal.aborted).toBe(true); - expect(parentListener).toHaveBeenCalledTimes(0); - expect(childListener).toHaveBeenCalledTimes(1); - }); - - it('child carries over parent signal state if parent was already aborted', async () => { - const root = new RootContext(); - - const parentController = new AbortController(); - const parent = AbortContext.forSignal(root, parentController.signal); - - parentController.abort(); - - const childController = new AbortController(); - const child = AbortContext.forSignal(parent, childController.signal); - const childListener = jest.fn(); - child.abortSignal.addEventListener('abort', childListener); - - expect(parent.abortSignal.aborted).toBe(true); - expect(child.abortSignal.aborted).toBe(true); - expect(childListener).toHaveBeenCalledTimes(0); - - childController.abort(); - - expect(parent.abortSignal.aborted).toBe(true); - expect(child.abortSignal.aborted).toBe(true); - expect(childListener).toHaveBeenCalledTimes(0); - }); - - it('child carries over given signal state if it was already aborted', async () => { - const root = new RootContext(); - - const childController = new AbortController(); - childController.abort(); - - const child = AbortContext.forSignal(root, childController.signal); - const childListener = jest.fn(); - child.abortSignal.addEventListener('abort', childListener); - - expect(child.abortSignal.aborted).toBe(true); - expect(childListener).toHaveBeenCalledTimes(0); - }); - }); -}); diff --git a/packages/backend-common/src/deprecated/context/AbortContext.ts b/packages/backend-common/src/deprecated/context/AbortContext.ts deleted file mode 100644 index 92735fbcc6..0000000000 --- a/packages/backend-common/src/deprecated/context/AbortContext.ts +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Context } from './types'; - -/** - * A context that implements various abort related functionality. - */ -export class AbortContext implements Context { - /** - * Abort either when the parent aborts, or after the given timeout has - * expired. - * - * @param ctx - The parent context - * @param timeout - A timeout value, in milliseconds - * @returns A new context - */ - static forTimeoutMillis(ctx: Context, timeout: number): Context { - const desiredDeadline = new Date(Date.now() + timeout); - const actualDeadline = - ctx.deadline && ctx.deadline < desiredDeadline - ? ctx.deadline - : desiredDeadline; - - if (ctx.abortSignal.aborted) { - if (ctx.deadline && desiredDeadline === actualDeadline) { - return ctx; - } - return new AbortContext(ctx, ctx.abortSignal, actualDeadline); - } - - const controller = new AbortController(); - const timeoutHandle = setTimeout(abort, timeout); - ctx.abortSignal.addEventListener('abort', abort); - - function abort() { - ctx.abortSignal.removeEventListener('abort', abort); - clearTimeout(timeoutHandle!); - controller.abort(); - } - - return new AbortContext(ctx, controller.signal, actualDeadline); - } - - /** - * Abort either when the parent aborts, or when the given controller is - * triggered. - * - * @remarks - * - * If you have access to the controller, this function is more efficient than - * {@link AbortContext#forSignal}. - * - * @param ctx - The parent context - * @param controller - An abort controller - * @returns A new context - */ - static forController(ctx: Context, controller: AbortController): Context { - // Already aborted context / signal are fine to reuse as-is - if (ctx.abortSignal.aborted) { - return ctx; - } else if (controller.signal.aborted) { - return new AbortContext(ctx, controller.signal, ctx.deadline); - } - - function abort() { - ctx.abortSignal.removeEventListener('abort', abort); - controller.abort(); - } - - ctx.abortSignal.addEventListener('abort', abort); - - return new AbortContext(ctx, controller.signal, ctx.deadline); - } - - /** - * Abort either when the parent aborts, or when the given signal is triggered. - * - * @remarks - * - * If you have access to the controller and not just the signal, - * {@link AbortContext#forController} is slightly more efficient to use. - * - * @param ctx - The parent context - * @param signal - An abort signal - * @returns A new context - */ - static forSignal(ctx: Context, signal: AbortSignal): Context { - // Already aborted context / signal are fine to reuse as-is - if (ctx.abortSignal.aborted) { - return ctx; - } else if (signal.aborted) { - return new AbortContext(ctx, signal, ctx.deadline); - } - - const controller = new AbortController(); - - function abort() { - ctx.abortSignal.removeEventListener('abort', abort); - signal.removeEventListener('abort', abort); - controller.abort(); - } - - ctx.abortSignal.addEventListener('abort', abort); - signal.addEventListener('abort', abort); - - return new AbortContext(ctx, controller.signal, ctx.deadline); - } - - private constructor( - private readonly parent: Context, - readonly abortSignal: AbortSignal, - readonly deadline: Date | undefined, - ) {} - - value(key: string): T | undefined { - return this.parent.value(key); - } -} diff --git a/packages/backend-common/src/deprecated/context/Contexts.test.ts b/packages/backend-common/src/deprecated/context/Contexts.test.ts deleted file mode 100644 index c895b3bb49..0000000000 --- a/packages/backend-common/src/deprecated/context/Contexts.test.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Duration } from 'luxon'; -import { Contexts } from './Contexts'; - -describe('Contexts', () => { - afterEach(() => { - jest.useRealTimers(); - }); - - describe('root', () => { - it('can create a root', () => { - const ctx = Contexts.root(); - expect(ctx.abortSignal).toBeDefined(); - expect(ctx.deadline).toBeUndefined(); - }); - }); - - describe('setAbort', () => { - it('works for controllers', () => { - const controller = new AbortController(); - const parent = Contexts.root(); - const child = Contexts.withAbort(parent, controller); - expect(child.abortSignal.aborted).toBe(false); - controller.abort(); - expect(child.abortSignal.aborted).toBe(true); - }); - - it('works for signals', () => { - const controller = new AbortController(); - const parent = Contexts.root(); - const child = Contexts.withAbort(parent, controller.signal); - expect(child.abortSignal.aborted).toBe(false); - controller.abort(); - expect(child.abortSignal.aborted).toBe(true); - }); - }); - - describe('setTimeoutDuration', () => { - it('works', () => { - jest.useFakeTimers(); - const parent = Contexts.root(); - const child = Contexts.withTimeoutDuration( - parent, - Duration.fromMillis(200), - ); - expect(child.abortSignal.aborted).toBe(false); - jest.advanceTimersByTime(100); - expect(child.abortSignal.aborted).toBe(false); - jest.advanceTimersByTime(101); - expect(child.abortSignal.aborted).toBe(true); - }); - }); - - describe('setTimeoutMillis', () => { - it('works', () => { - jest.useFakeTimers(); - const parent = Contexts.root(); - const child = Contexts.withTimeoutMillis(parent, 200); - expect(child.abortSignal.aborted).toBe(false); - jest.advanceTimersByTime(100); - expect(child.abortSignal.aborted).toBe(false); - jest.advanceTimersByTime(101); - expect(child.abortSignal.aborted).toBe(true); - }); - }); - - describe('setValue', () => { - it('works', () => { - const parent = Contexts.root(); - const child = Contexts.withValue(parent, 'k', 'v'); - expect(child.value('k')).toBe('v'); - }); - }); -}); diff --git a/packages/backend-common/src/deprecated/context/Contexts.ts b/packages/backend-common/src/deprecated/context/Contexts.ts deleted file mode 100644 index 026e3ce4e0..0000000000 --- a/packages/backend-common/src/deprecated/context/Contexts.ts +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Duration } from 'luxon'; -import { AbortContext } from './AbortContext'; -import { RootContext } from './RootContext'; -import { Context } from './types'; -import { ValueContext } from './ValueContext'; - -/** - * Common context decorators. - * - * @alpha - * @deprecated This class is not used in the new Backend system, so it is going to be removed in a near future. - */ -export class Contexts { - /** - * Creates a root context. - * - * @remarks - * - * This should normally only be called near the root of an application. The - * created context is meant to be passed down into deeper levels, which may or - * may not make derived contexts out of it. - */ - static root(): Context { - return new RootContext(); - } - - /** - * Creates a derived context, which signals to abort operations either when - * any parent context signals, or when the given source is aborted. - * - * @remarks - * - * If the parent context was already aborted, then it is returned as-is. - * - * If the given source was already aborted, then a new already-aborted context - * is returned. - * - * @param parentCtx - A parent context that shall be used as a base - * @param source - An abort controller or signal that you intend to perhaps - * trigger at some later point in time. - * @returns A new {@link Context} - */ - static withAbort( - parentCtx: Context, - source: AbortController | AbortSignal, - ): Context { - return 'aborted' in source - ? AbortContext.forSignal(parentCtx, source) - : AbortContext.forController(parentCtx, source); - } - - /** - * Creates a derived context, which signals to abort operations either when - * any parent context signals, or when the given amount of time has passed. - * This may affect the deadline. - * - * @param parentCtx - A parent context that shall be used as a base - * @param timeout - The duration of time, after which the derived context will - * signal to abort. - * @returns A new {@link Context} - */ - static withTimeoutDuration(parentCtx: Context, timeout: Duration): Context { - return AbortContext.forTimeoutMillis(parentCtx, timeout.as('milliseconds')); - } - - /** - * Creates a derived context, which signals to abort operations either when - * any parent context signals, or when the given amount of time has passed. - * This may affect the deadline. - * - * @param parentCtx - A parent context that shall be used as a base - * @param timeout - The number of milliseconds, after which the derived - * context will signal to abort. - * @returns A new {@link Context} - */ - static withTimeoutMillis(parentCtx: Context, timeout: number): Context { - return AbortContext.forTimeoutMillis(parentCtx, timeout); - } - - /** - * Creates a derived context, which has a specific key-value pair set as well - * as all key-value pairs that were set in the original context. - * - * @param parentCtx - A parent context that shall be used as a base - * @param key - The key of the value to set - * @param value - The value, or a function that accepts the previous value (or - * undefined if not set yet) and computes the new value - * @returns A new {@link Context} - */ - static withValue( - parentCtx: Context, - key: string, - value: unknown | ((previous: unknown | undefined) => unknown), - ): Context { - const v = typeof value === 'function' ? value(parentCtx.value(key)) : value; - return ValueContext.forConstantValue(parentCtx, key, v); - } -} diff --git a/packages/backend-common/src/deprecated/context/RootContext.test.ts b/packages/backend-common/src/deprecated/context/RootContext.test.ts deleted file mode 100644 index 395786e3dc..0000000000 --- a/packages/backend-common/src/deprecated/context/RootContext.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { RootContext } from './RootContext'; - -describe('RootContext', () => { - it('returns empty values', async () => { - const ctx = new RootContext(); - expect(ctx.abortSignal).toBeDefined(); - expect(ctx.abortSignal.aborted).toBe(false); - expect(ctx.deadline).toBeUndefined(); - expect(ctx.value('a')).toBeUndefined(); - }); -}); diff --git a/packages/backend-common/src/deprecated/context/RootContext.ts b/packages/backend-common/src/deprecated/context/RootContext.ts deleted file mode 100644 index fd3690a945..0000000000 --- a/packages/backend-common/src/deprecated/context/RootContext.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Context } from './types'; - -/** - * Since the root context can never abort, and since nobody is ever meant to - * dispatch events through it, we can use a static fake instance for efficiency. - * - * The reason that this was initially made for the root context is that due to - * the way that we always chain contexts off of it, sometimes a huge number of - * listeners want to add themselves to something that effectively never can be - * aborted in the first place. This triggered warnings that the max listeners - * limit was exceeded. - */ -class FakeAbortSignal implements AbortSignal { - readonly aborted = false; - readonly reason = undefined; - onabort() {} - throwIfAborted() {} - addEventListener() {} - removeEventListener() {} - dispatchEvent() { - return true; - } -} - -/** - * An empty root context. - */ -export class RootContext implements Context { - readonly abortSignal = new FakeAbortSignal(); - readonly deadline = undefined; - value(_key: string): T | undefined { - return undefined; - } -} diff --git a/packages/backend-common/src/deprecated/context/ValueContext.test.ts b/packages/backend-common/src/deprecated/context/ValueContext.test.ts deleted file mode 100644 index 6a216d4548..0000000000 --- a/packages/backend-common/src/deprecated/context/ValueContext.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { RootContext } from './RootContext'; -import { ValueContext } from './ValueContext'; - -describe('ValueContext', () => { - it('returns its own values, or delegates to the parent', async () => { - const root = new RootContext(); - const a = ValueContext.forConstantValue(root, 'a', 1); - const b = ValueContext.forConstantValue(a, 'x', 2); - const c = ValueContext.forConstantValue(b, 'a', 3); - const d = ValueContext.forConstantValue(c, 'b', 4); - - expect(a.value('a')).toBe(1); - expect(a.value('b')).toBeUndefined(); - expect(a.value('x')).toBeUndefined(); - - expect(b.value('a')).toBe(1); - expect(b.value('b')).toBeUndefined(); - expect(b.value('x')).toBe(2); - - expect(c.value('a')).toBe(3); - expect(c.value('b')).toBeUndefined(); - expect(c.value('x')).toBe(2); - - expect(d.value('a')).toBe(3); - expect(d.value('b')).toBe(4); - expect(d.value('x')).toBe(2); - }); -}); diff --git a/packages/backend-common/src/deprecated/context/ValueContext.ts b/packages/backend-common/src/deprecated/context/ValueContext.ts deleted file mode 100644 index c8e4426d05..0000000000 --- a/packages/backend-common/src/deprecated/context/ValueContext.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Context } from './types'; - -/** - * A context that just holds a single value, and delegates the rest to its - * parent. - */ -export class ValueContext implements Context { - static forConstantValue(ctx: Context, key: string, value: unknown): Context { - return new ValueContext(ctx, key, value); - } - - constructor( - private readonly _parent: Context, - private readonly _key: string, - private readonly _value: unknown, - ) {} - - get abortSignal(): AbortSignal { - return this._parent.abortSignal; - } - - get deadline(): Date | undefined { - return this._parent.deadline; - } - - value(key: string): T | undefined { - return key === this._key ? (this._value as T) : this._parent.value(key); - } -} diff --git a/packages/backend-common/src/deprecated/context/index.ts b/packages/backend-common/src/deprecated/context/index.ts deleted file mode 100644 index 37a6e29c8c..0000000000 --- a/packages/backend-common/src/deprecated/context/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { Contexts } from './Contexts'; -export type { Context } from './types'; diff --git a/packages/backend-common/src/deprecated/context/types.ts b/packages/backend-common/src/deprecated/context/types.ts deleted file mode 100644 index d980f54e43..0000000000 --- a/packages/backend-common/src/deprecated/context/types.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * A context that is meant to be passed as a ctx variable down the call chain, - * to pass along scoped information and abort signals. - * - * @alpha - * @deprecated This type is not used in the new Backend system, so it is going to be removed in a near future. - */ -export interface Context { - /** - * Returns an abort signal that triggers when the current context or any of - * its parents signal for it. - */ - readonly abortSignal: AbortSignal; - - /** - * The point in time when the current context shall time out and abort, if - * applicable. - */ - readonly deadline: Date | undefined; - - /** - * Attempts to get a stored value by key from the context. - * - * @param key - The key of the value to get - * @returns The associated value, or undefined if not set - */ - value(key: string): T | undefined; -} diff --git a/packages/backend-common/src/deprecated/hot.ts b/packages/backend-common/src/deprecated/hot.ts deleted file mode 100644 index 94ebf52307..0000000000 --- a/packages/backend-common/src/deprecated/hot.ts +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// Find all active hot module APIs of all ancestors of a module, including the module itself -function findAllAncestors(_module: NodeModule): NodeModule[] { - const ancestors = new Array(); - const parentIds = new Set(); - - function add(id: string | number, m: NodeModule) { - if (parentIds.has(id)) { - return; - } - parentIds.add(id); - ancestors.push(m); - - for (const parentId of (m as any).parents) { - const parent = require.cache[parentId]; - if (parent) { - add(parentId, parent); - } - } - } - - add(_module.id, _module); - - return ancestors; -} - -/** - * useHotCleanup allows cleanup of ongoing effects when a module is - * hot-reloaded during development. The cleanup function will be called - * whenever the module itself or any of its parent modules is hot-reloaded. - * - * Useful for cleaning intervals, timers, requests etc - * - * @public - * @deprecated Hot module reloading is no longer supported for backends. - * @example - * ```ts - * const intervalId = setInterval(doStuff, 1000); - * useHotCleanup(module, () => clearInterval(intervalId)); - * ``` - * @param _module - Reference to the current module where you invoke the fn - * @param cancelEffect - Fn that cleans up the ongoing effects - */ -export function useHotCleanup(_module: NodeModule, cancelEffect: () => void) { - if (_module.hot) { - const ancestors = findAllAncestors(_module); - let cancelled = false; - - const handler = () => { - if (!cancelled) { - cancelled = true; - cancelEffect(); - } - }; - - for (const m of ancestors) { - m.hot?.addDisposeHandler(handler); - } - } -} - -const CURRENT_HOT_MEMOIZE_INDEX_KEY = 'backstage.io/hmr-memoize-key'; - -/** - * Memoizes a generated value across hot-module reloads. This is useful for - * stateful parts of the backend, e.g. to retain a database. - * - * @public - * @deprecated Hot module reloading is no longer supported for backends. - * @example - * ```ts - * const db = useHotMemoize(module, () => createDB(dbParams)); - * ``` - * - * **NOTE:** Do not use inside conditionals or loops, - * same rules as for hooks apply (https://reactjs.org/docs/hooks-rules.html) - * - * @param _module - Reference to the current module where you invoke the fn - * @param valueFactory - Fn that returns the value you want to memoize - */ -export function useHotMemoize( - _module: NodeModule, - valueFactory: () => T, -): T { - if (!_module.hot) { - return valueFactory(); - } - - // When starting blank, reset the counter - if (!_module.hot.data?.[CURRENT_HOT_MEMOIZE_INDEX_KEY]) { - for (const ancestor of findAllAncestors(_module)) { - ancestor.hot?.addDisposeHandler(data => { - data[CURRENT_HOT_MEMOIZE_INDEX_KEY] = 1; - }); - } - - _module.hot.data = { - ..._module.hot.data, - [CURRENT_HOT_MEMOIZE_INDEX_KEY]: 1, - }; - } - - // Store data per module, based on the order of the code invocation - const index = _module.hot.data[CURRENT_HOT_MEMOIZE_INDEX_KEY]++; - const value = _module.hot.data[index] ?? valueFactory(); - - // Always add a handler that, upon a HMR event, reinstates the value. - _module.hot.addDisposeHandler(data => { - data[index] = value; - }); - - return value; -} diff --git a/packages/backend-common/src/deprecated/index.ts b/packages/backend-common/src/deprecated/index.ts deleted file mode 100644 index f769d4db09..0000000000 --- a/packages/backend-common/src/deprecated/index.ts +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Config } from '@backstage/config'; - -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { HostDiscovery as _HostDiscovery } from '../../../backend-defaults/src/entrypoints/discovery/HostDiscovery'; - -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { CacheManager as _CacheManager } from '../../../backend-defaults/src/entrypoints/cache/CacheManager'; - -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { type CacheManagerOptions as _CacheManagerOptions } from '../../../backend-defaults/src/entrypoints/cache/types'; - -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { - DatabaseManager as _DatabaseManager, - type DatabaseManagerOptions as _DatabaseManagerOptions, -} from '../../../backend-defaults/src/entrypoints/database/DatabaseManager'; - -import { - DiscoveryService, - CacheService, - CacheServiceOptions, - CacheServiceSetOptions, - DatabaseService as _PluginDatabaseManager, - isDatabaseConflictError as _isDatabaseConflictError, - resolvePackagePath as _resolvePackagePath, - resolveSafeChildPath as _resolveSafeChildPath, - isChildPath as _isChildPath, - LifecycleService, - PluginMetadataService, - DatabaseService, - LoggerService, - RootConfigService, -} from '@backstage/backend-plugin-api'; - -export * from './hot'; -export * from './config'; -export * from './scm'; -export * from './tokens'; -export * from './logging'; -export * from './service'; -export * from './middleware'; -export * from './util'; - -/** - * @public - * @deprecated Use `DiscoveryService` from `@backstage/backend-plugin-api` instead - */ -export type PluginEndpointDiscovery = DiscoveryService; - -/** - * HostDiscovery is a basic PluginEndpointDiscovery implementation - * that can handle plugins that are hosted in a single or multiple deployments. - * - * The deployment may be scaled horizontally, as long as the external URL - * is the same for all instances. However, internal URLs will always be - * resolved to the same host, so there won't be any balancing of internal traffic. - * - * @public - * @deprecated Please import from `@backstage/backend-defaults/discovery` instead. - */ -export class HostDiscovery implements DiscoveryService { - /** - * Creates a new HostDiscovery discovery instance by reading - * from the `backend` config section, specifically the `.baseUrl` for - * discovering the external URL, and the `.listen` and `.https` config - * for the internal one. - * - * Can be overridden in config by providing a target and corresponding plugins in `discovery.endpoints`. - * eg. - * ```yaml - * discovery: - * endpoints: - * - target: https://internal.example.com/internal-catalog - * plugins: [catalog] - * - target: https://internal.example.com/secure/api/{{pluginId}} - * plugins: [auth, permission] - * - target: - * internal: https://internal.example.com/search - * external: https://example.com/search - * plugins: [search] - * ``` - * - * The fixed base path is `/api`, meaning the default full internal - * path for the `catalog` plugin will be `http://localhost:7007/api/catalog`. - */ - static fromConfig(config: Config) { - return new HostDiscovery(_HostDiscovery.fromConfig(config)); - } - - private constructor(private readonly impl: _HostDiscovery) {} - - async getBaseUrl(pluginId: string): Promise { - return this.impl.getBaseUrl(pluginId); - } - - async getExternalBaseUrl(pluginId: string): Promise { - return this.impl.getExternalBaseUrl(pluginId); - } -} - -/** - * SingleHostDiscovery is a basic PluginEndpointDiscovery implementation - * that assumes that all plugins are hosted in a single deployment. - * - * The deployment may be scaled horizontally, as long as the external URL - * is the same for all instances. However, internal URLs will always be - * resolved to the same host, so there won't be any balancing of internal traffic. - * - * @public - * @deprecated Use `HostDiscovery` from `@backstage/backend-defaults/discovery` instead - */ -export { HostDiscovery as SingleHostDiscovery }; - -/** - * @public - * @deprecated Use `CacheManager` from the `@backstage/backend-defaults` package instead - */ -export class CacheManager { - /** - * Creates a new {@link CacheManager} instance by reading from the `backend` - * config section, specifically the `.cache` key. - * - * @param config - The loaded application configuration. - */ - static fromConfig( - config: RootConfigService, - options: CacheManagerOptions = {}, - ): CacheManager { - return new CacheManager(_CacheManager.fromConfig(config, options)); - } - - private constructor(private readonly _impl: _CacheManager) {} - - forPlugin(pluginId: string): PluginCacheManager { - return { - getClient: options => { - const result = this._impl.forPlugin(pluginId); - return options ? result.withOptions(options) : result; - }, - }; - } -} - -/** - * @public - * @deprecated Use `CacheManagerOptions` from the `@backstage/backend-defaults` package instead - */ -export type CacheManagerOptions = _CacheManagerOptions; - -/** - * @public - * @deprecated Use `PluginCacheManager` from the `@backstage/backend-defaults` package instead - */ -export type PluginCacheManager = { - getClient(options?: CacheServiceOptions): CacheService; -}; - -/** - * @public - * @deprecated Use `CacheService` from the `@backstage/backend-plugin-api` package instead - */ -export type CacheClient = CacheService; - -/** - * @public - * @deprecated Use `CacheServiceSetOptions` from the `@backstage/backend-plugin-api` package instead - */ -export type CacheClientSetOptions = CacheServiceSetOptions; - -/** - * @public - * @deprecated Use `CacheServiceOptions` from the `@backstage/backend-plugin-api` package instead - */ -export type CacheClientOptions = CacheServiceOptions; - -/** - * @public - * @deprecated Use `DatabaseManager` from the `@backstage/backend-defaults` package instead - */ -export class DatabaseManager implements LegacyRootDatabaseService { - private constructor( - private readonly _databaseManager: _DatabaseManager, - private readonly logger?: LoggerService, - ) {} - - static fromConfig( - config: Config, - options?: { - migrations?: DatabaseService['migrations']; - logger?: LoggerService; - }, - ): DatabaseManager { - const _databaseManager = _DatabaseManager.fromConfig(config, options); - return new DatabaseManager(_databaseManager, options?.logger); - } - - forPlugin( - pluginId: string, - deps?: - | { lifecycle: LifecycleService; pluginMetadata: PluginMetadataService } - | undefined, - ): PluginDatabaseManager { - const logger: LoggerService = this.logger ?? { - debug() {}, - info() {}, - warn() {}, - error() {}, - child() { - return this; - }, - }; - const lifecycle: LifecycleService = deps?.lifecycle ?? { - addShutdownHook() {}, - addStartupHook() {}, - }; - return this._databaseManager.forPlugin(pluginId, { logger, lifecycle }); - } -} - -/** - * @public - * @deprecated Use `DatabaseManagerOptions` from the `@backstage/backend-defaults` package instead - */ -export type DatabaseManagerOptions = _DatabaseManagerOptions; - -/** - * @public - * @deprecated Use `DatabaseService` from the `@backstage/backend-plugin-api` package instead - */ -export type PluginDatabaseManager = _PluginDatabaseManager; - -/** - * @public - * @deprecated Use `DatabaseManager` from `@backstage/backend-defaults/database` instead, or migrate to the new backend system and use `coreServices.database` - */ -export type LegacyRootDatabaseService = { - forPlugin(pluginId: string): DatabaseService; -}; - -/** - * @public - * @deprecated This function is deprecated and will be removed in a future release, see https://github.com/backstage/backstage/issues/24493. - * Please use the `isDatabaseConflictError` function from the `@backstage/backend-plugin-api` package instead. - */ -export const isDatabaseConflictError = _isDatabaseConflictError; - -/** - * @public - * @deprecated This function is deprecated and will be removed in a future release, see https://github.com/backstage/backstage/issues/24493. - * Please use the `resolvePackagePath` function from the `@backstage/backend-plugin-api` package instead. - */ -export const resolvePackagePath = _resolvePackagePath; - -/** - * @public - * @deprecated This function is deprecated and will be removed in a future release, see https://github.com/backstage/backstage/issues/24493. - * Please use the `resolveSafeChildPath` function from the `@backstage/backend-plugin-api` package instead. - */ -export const resolveSafeChildPath = _resolveSafeChildPath; - -/** - * @public - * @deprecated This function is deprecated and will be removed in a future release, see https://github.com/backstage/backstage/issues/24493. - * Please use the `isChildPath` function from the `@backstage/cli-common` package instead. - */ -export const isChildPath = _isChildPath; diff --git a/packages/backend-common/src/deprecated/logging/createRootLogger.ts b/packages/backend-common/src/deprecated/logging/createRootLogger.ts deleted file mode 100644 index 04b3799381..0000000000 --- a/packages/backend-common/src/deprecated/logging/createRootLogger.ts +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { WinstonLogger } from '../../../../backend-defaults/src/entrypoints/rootLogger/WinstonLogger'; -import { merge } from 'lodash'; -import * as winston from 'winston'; -import { format, LoggerOptions } from 'winston'; -import { TransformableInfo } from 'logform'; -import { setRootLogger } from './globalLoggers'; - -const getRedacter = (() => { - let redacter: ReturnType | undefined = - undefined; - return () => { - if (!redacter) { - redacter = WinstonLogger.redacter(); - } - return redacter; - }; -})(); - -export const setRootLoggerRedactionList = ( - redactions: Iterable, -): void => { - getRedacter().add(redactions); -}; - -/** - * A winston formatting function that finds occurrences of filteredKeys - * and replaces them with the corresponding identifier. - * - * @public - * @deprecated This utility is being deprecated along with the {@link https://github.com/backstage/backstage/issues/24493 |legacy backend system}. - * Migrate your {@link https://backstage.io/docs/backend-system/building-backends/migrating | backend} and {@link https://backstage.io/docs/backend-system/building-plugins-and-modules/migrating | plugin} to the new system and use the {@link https://github.com/backstage/backstage/pull/24730 | RedactionsService} for customization instead. - */ -export function redactWinstonLogLine( - info: winston.Logform.TransformableInfo, -): winston.Logform.TransformableInfo { - return getRedacter().format.transform( - info, - ) as winston.Logform.TransformableInfo; -} - -const colorizer = format.colorize(); - -// NOTE: This is a copy of the WinstonLogger.colorFormat to avoid a circular dependency -/** - * Creates a pretty printed winston log formatter. - * - * @public - * @deprecated As we are going to deprecate the legacy backend, this formatter utility will be removed in the future. - * If you need to format logs in the new system, please use the `WinstonLogger.colorFormat()` from `@backstage/backend-app-api` instead. - */ -export const coloredFormat = format.combine( - format.timestamp(), - format.colorize({ - colors: { - timestamp: 'dim', - prefix: 'blue', - field: 'cyan', - debug: 'grey', - }, - }), - format.printf((info: TransformableInfo) => { - const { timestamp, level, message, plugin, service, ...fields } = info; - const prefix = plugin || service; - const timestampColor = colorizer.colorize('timestamp', timestamp); - const prefixColor = colorizer.colorize('prefix', prefix); - - const extraFields = Object.entries(fields) - .map( - ([key, value]) => `${colorizer.colorize('field', `${key}`)}=${value}`, - ) - .join(' '); - - return `${timestampColor} ${prefixColor} ${level} ${message} ${extraFields}`; - }), -); - -/** - * Creates a default "root" logger. This also calls {@link setRootLogger} under - * the hood. - * - * @remarks - * - * This is the logger instance that will be the foundation for all other logger - * instances passed to plugins etc, in a given backend. - * - * @public - * @deprecated As we are going to deprecate the legacy backend, this function will be removed in the future. - * If you need to create the root logger in the new system, please check out this documentation: - * https://backstage.io/docs/backend-system/core-services/logger - */ -export function createRootLogger( - options: winston.LoggerOptions = {}, - env = process.env, -): winston.Logger { - const logger = winston - .createLogger( - merge( - { - level: env.LOG_LEVEL || 'info', - format: winston.format.combine( - getRedacter().format, - env.NODE_ENV === 'production' - ? winston.format.json() - : WinstonLogger.colorFormat(), - ), - transports: [ - new winston.transports.Console({ - silent: env.JEST_WORKER_ID !== undefined && !env.LOG_LEVEL, - }), - ], - }, - options, - ), - ) - .child({ service: 'backstage' }); - - setRootLogger(logger); - - return logger; -} diff --git a/packages/backend-common/src/deprecated/logging/globalLoggers.ts b/packages/backend-common/src/deprecated/logging/globalLoggers.ts deleted file mode 100644 index cbd5279d29..0000000000 --- a/packages/backend-common/src/deprecated/logging/globalLoggers.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import * as winston from 'winston'; -import { createRootLogger } from './createRootLogger'; - -/** - * A logger that just throws away all messages. - * - * @public - * @deprecated As we are going to deprecate the legacy backend, this function will be removed in the future. - * If you need to mock the root logger in the new system, please use `mockServices.logger.mock()` from `@backstage/test-utils` instead. - */ -export function getVoidLogger(): winston.Logger { - return winston.createLogger({ - transports: [new winston.transports.Console({ silent: true })], - }); -} - -let rootLogger: winston.Logger; - -/** - * Gets the current root logger. - * - * @public - * @deprecated As we are going to deprecate the legacy backend, this function will be removed in the future. - * If you need to get the root logger in the new system, please check out this documentation: - * https://backstage.io/docs/backend-system/core-services/logger - */ -export function getRootLogger(): winston.Logger { - if (!rootLogger) { - rootLogger = createRootLogger(); - } - return rootLogger; -} - -/** - * Sets a completely custom default "root" logger. - * - * @remarks - * - * This is the logger instance that will be the foundation for all other logger - * instances passed to plugins etc, in a given backend. - * - * Only use this if you absolutely need to make a completely custom logger. - * Normally if you want to make light adaptations to the default logger - * behavior, you would instead call {@link createRootLogger}. - * - * @public - * @deprecated As we are going to deprecate the legacy backend, this function will be removed in the future. - * If you need to set the root logger in the new system, please check out this documentation: - * https://backstage.io/docs/backend-system/core-services/logger - */ -export function setRootLogger(newLogger: winston.Logger) { - rootLogger = newLogger; -} diff --git a/packages/backend-common/src/deprecated/logging/index.ts b/packages/backend-common/src/deprecated/logging/index.ts deleted file mode 100644 index b223f5c946..0000000000 --- a/packages/backend-common/src/deprecated/logging/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { getRootLogger, getVoidLogger, setRootLogger } from './globalLoggers'; -export { - createRootLogger, - redactWinstonLogLine, - coloredFormat, -} from './createRootLogger'; diff --git a/packages/backend-common/src/deprecated/middleware/errorHandler.test.ts b/packages/backend-common/src/deprecated/middleware/errorHandler.test.ts deleted file mode 100644 index 2544a0a863..0000000000 --- a/packages/backend-common/src/deprecated/middleware/errorHandler.test.ts +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import express from 'express'; -import { STATUS_CODES } from 'http'; -import createError from 'http-errors'; -import request from 'supertest'; -import { - AuthenticationError, - ConflictError, - InputError, - NotAllowedError, - NotFoundError, - NotModifiedError, - ResponseError, -} from '@backstage/errors'; -import { errorHandler } from './errorHandler'; - -describe('errorHandler', () => { - it('gives default code and message', async () => { - const app = express(); - app.use('/breaks', () => { - throw new Error('some message'); - }); - app.use(errorHandler()); - - const response = await request(app).get('/breaks'); - - expect(response.status).toBe(500); - expect(response.body).toEqual({ - error: expect.objectContaining({ - name: 'Error', - message: 'some message', - }), - request: { method: 'GET', url: '/breaks' }, - response: { statusCode: 500 }, - }); - }); - - it('does not try to send the response again if its already been sent', async () => { - const app = express(); - const mockSend = jest.fn(); - - app.use('/works_with_async_fail', (_, res) => { - res.status(200).send('hello'); - - // mutate the response object to test the middleware. - // it's hard to catch errors inside middleware from the outside. - res.send = mockSend; - throw new Error('some message'); - }); - - app.use(errorHandler()); - const response = await request(app).get('/works_with_async_fail'); - - expect(response.status).toBe(200); - expect(response.text).toBe('hello'); - - expect(mockSend).not.toHaveBeenCalled(); - }); - - it('takes code from http-errors library errors', async () => { - const app = express(); - app.use('/breaks', () => { - throw createError(432, 'Some Message'); - }); - app.use(errorHandler()); - - const response = await request(app).get('/breaks'); - - expect(response.status).toBe(432); - expect(response.body).toEqual({ - error: { - expose: true, - name: 'BadRequestError', - message: 'Some Message', - status: 432, - statusCode: 432, - }, - request: { - method: 'GET', - url: '/breaks', - }, - response: { statusCode: 432 }, - }); - }); - - it('handles well-known error classes', async () => { - const app = express(); - app.use('/NotModifiedError', () => { - throw new NotModifiedError(); - }); - app.use('/InputError', () => { - throw new InputError(); - }); - app.use('/AuthenticationError', () => { - throw new AuthenticationError(); - }); - app.use('/NotAllowedError', () => { - throw new NotAllowedError(); - }); - app.use('/NotFoundError', () => { - throw new NotFoundError(); - }); - app.use('/ConflictError', () => { - throw new ConflictError(); - }); - app.use('/ResponseErrorBackstagePlugin', async (_req, _res, next) => { - const mockedResponse = { - status: jest.fn(() => mockedResponse), - json: jest.fn(() => mockedResponse), - } as unknown as jest.Mocked; - - // serialize AuthenticationError in mockedResponse - errorHandler()( - new AuthenticationError('an error'), - { method: 'GET', url: '' } as express.Request, - mockedResponse, - jest.fn(), - ); - - const status = mockedResponse.status.mock.calls[0][0]; - next( - await ResponseError.fromResponse({ - headers: new Headers({ - 'content-type': 'application/json', - }), - ok: false, - redirected: false, - status, - statusText: STATUS_CODES[status]!, - type: 'default', - url: '', - text: async () => - JSON.stringify(mockedResponse.json.mock.calls[0][0]), - }), - ); - }); - app.use('/ResponseError', async (_req, _res, next) => { - next( - await ResponseError.fromResponse({ - headers: new Headers({ - 'content-type': 'application/json', - }), - ok: false, - redirected: false, - status: 403, - statusText: STATUS_CODES[403]!, - type: 'default', - url: '', - text: async () => JSON.stringify({}), - }), - ); - }); - app.use(errorHandler()); - - const r = request(app); - expect((await r.get('/NotModifiedError')).status).toBe(304); - expect((await r.get('/InputError')).status).toBe(400); - expect((await r.get('/InputError')).body.error.name).toBe('InputError'); - expect((await r.get('/AuthenticationError')).status).toBe(401); - expect((await r.get('/AuthenticationError')).body.error.name).toBe( - 'AuthenticationError', - ); - expect((await r.get('/NotAllowedError')).status).toBe(403); - expect((await r.get('/NotAllowedError')).body.error.name).toBe( - 'NotAllowedError', - ); - expect((await r.get('/NotFoundError')).status).toBe(404); - expect((await r.get('/NotFoundError')).body.error.name).toBe( - 'NotFoundError', - ); - expect((await r.get('/ConflictError')).status).toBe(409); - expect((await r.get('/ConflictError')).body.error.name).toBe( - 'ConflictError', - ); - expect((await r.get('/ResponseErrorBackstagePlugin')).status).toBe(401); - expect((await r.get('/ResponseErrorBackstagePlugin')).body.error.name).toBe( - 'ResponseError', - ); - expect((await r.get('/ResponseError')).status).toBe(403); - expect((await r.get('/ResponseError')).body.error.name).toBe( - 'ResponseError', - ); - }); - - it('logs all 500 errors', async () => { - const app = express(); - - const mockLogger = { child: jest.fn(), error: jest.fn() }; - mockLogger.child.mockImplementation(() => mockLogger as any); - - const thrownError = new Error('some error'); - - app.use('/breaks', () => { - throw thrownError; - }); - app.use(errorHandler({ logger: mockLogger as any })); - - await request(app).get('/breaks'); - - expect(mockLogger.error).toHaveBeenCalledWith( - 'Request failed with status 500', - thrownError, - ); - }); - - it('does not log 400 errors', async () => { - const app = express(); - - const mockLogger = { child: jest.fn(), error: jest.fn() }; - mockLogger.child.mockImplementation(() => mockLogger as any); - - app.use('/NotFound', () => { - throw new NotFoundError(); - }); - app.use(errorHandler({ logger: mockLogger as any })); - - await request(app).get('/NotFound'); - - expect(mockLogger.error).not.toHaveBeenCalled(); - }); - - it('log 400 errors when logClientErrors is true', async () => { - const app = express(); - - const mockLogger = { child: jest.fn(), error: jest.fn() }; - mockLogger.child.mockImplementation(() => mockLogger as any); - - app.use('/NotFound', () => { - throw new NotFoundError(); - }); - app.use(errorHandler({ logger: mockLogger as any, logClientErrors: true })); - - await request(app).get('/NotFound'); - - expect(mockLogger.error).toHaveBeenCalled(); - }); -}); diff --git a/packages/backend-common/src/deprecated/middleware/errorHandler.ts b/packages/backend-common/src/deprecated/middleware/errorHandler.ts deleted file mode 100644 index b4f07b9320..0000000000 --- a/packages/backend-common/src/deprecated/middleware/errorHandler.ts +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { ErrorRequestHandler } from 'express'; -import { LoggerService } from '@backstage/backend-plugin-api'; -import { ConfigReader } from '@backstage/config'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { MiddlewareFactory } from '../../../../backend-defaults/src/entrypoints/rootHttpRouter/http/MiddlewareFactory'; -import { getRootLogger } from '../logging'; - -/** - * Options passed to the {@link errorHandler} middleware. - * - * @public - * @deprecated This type is being deprecated along with the {@link @backstage/backend-common#errorHandler} function. - */ -export type ErrorHandlerOptions = { - /** - * Whether error response bodies should show error stack traces or not. - * - * If not specified, by default shows stack traces only in development mode. - */ - showStackTraces?: boolean; - - /** - * Logger instance to log errors. - * - * If not specified, the root logger will be used. - */ - logger?: LoggerService; - - /** - * Whether any 4xx errors should be logged or not. - * - * If not specified, default to only logging 5xx errors. - */ - logClientErrors?: boolean; -}; - -/** - * Express middleware to handle errors during request processing. - * - * This is commonly the very last middleware in the chain. - * - * Its primary purpose is not to do translation of business logic exceptions, - * but rather to be a global catch-all for uncaught "fatal" errors that are - * expected to result in a 500 error. However, it also does handle some common - * error types (such as http-error exceptions) and returns the enclosed status - * code accordingly. - * - * @public - * @returns An Express error request handler - * @deprecated Use {@link @backstage/backend-defaults/rootHttpRouter#MiddlewareFactory.create.error} instead - */ -export function errorHandler( - options: ErrorHandlerOptions = {}, -): ErrorRequestHandler { - return MiddlewareFactory.create({ - config: new ConfigReader({}), - logger: options.logger ?? getRootLogger(), - }).error({ - logAllErrors: options.logClientErrors, - showStackTraces: options.showStackTraces, - }); -} diff --git a/packages/backend-common/src/deprecated/middleware/index.ts b/packages/backend-common/src/deprecated/middleware/index.ts deleted file mode 100644 index f4f4fcde0b..0000000000 --- a/packages/backend-common/src/deprecated/middleware/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export * from './errorHandler'; -export * from './notFoundHandler'; -export * from './requestLoggingHandler'; -export * from './statusCheckHandler'; diff --git a/packages/backend-common/src/deprecated/middleware/notFoundHandler.test.ts b/packages/backend-common/src/deprecated/middleware/notFoundHandler.test.ts deleted file mode 100644 index b49e275a69..0000000000 --- a/packages/backend-common/src/deprecated/middleware/notFoundHandler.test.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import express from 'express'; -import request from 'supertest'; -import { notFoundHandler } from './notFoundHandler'; - -describe('notFoundHandler', () => { - it('handles only missing routes', async () => { - const app = express(); - app.use('/exists', (_, res) => res.status(200).end()); - app.use(notFoundHandler()); - - const existsResponse = await request(app).get('/exists'); - const doesNotExistResponse = await request(app).get('/doesNotExist'); - - expect(existsResponse.status).toBe(200); - expect(doesNotExistResponse.status).toBe(404); - }); -}); diff --git a/packages/backend-common/src/deprecated/middleware/notFoundHandler.ts b/packages/backend-common/src/deprecated/middleware/notFoundHandler.ts deleted file mode 100644 index bb9504a9ec..0000000000 --- a/packages/backend-common/src/deprecated/middleware/notFoundHandler.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { MiddlewareFactory } from '../../../../backend-defaults/src/entrypoints/rootHttpRouter/http/MiddlewareFactory'; -import { ConfigReader } from '@backstage/config'; -import { RequestHandler } from 'express'; -import { getRootLogger } from '../logging'; - -/** - * Express middleware to handle requests for missing routes. - * - * Should be used as the very last handler in the chain, as it unconditionally - * returns a 404 status. - * - * @public - * @returns An Express request handler - * @deprecated Use {@link @backstage/backend-app-api#MiddlewareFactory.create.notFound} instead - */ -export function notFoundHandler(): RequestHandler { - return MiddlewareFactory.create({ - config: new ConfigReader({}), - logger: getRootLogger(), - }).notFound(); -} diff --git a/packages/backend-common/src/deprecated/middleware/requestLoggingHandler.test.ts b/packages/backend-common/src/deprecated/middleware/requestLoggingHandler.test.ts deleted file mode 100644 index ed24f2050b..0000000000 --- a/packages/backend-common/src/deprecated/middleware/requestLoggingHandler.test.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import express from 'express'; -import request from 'supertest'; -import * as winston from 'winston'; -import { requestLoggingHandler } from './requestLoggingHandler'; - -describe('requestLoggingHandler', () => { - it('emits logs for each request', async () => { - const logger = winston.createLogger(); - jest.spyOn(logger, 'info').mockReturnValue(logger); - - const app = express(); - app.use(requestLoggingHandler(logger)); - app.use('/exists1', (_, res) => res.status(200).end()); - app.use('/exists2', (_, res) => res.status(201).end()); - - const r = request(app); - await r.get('/exists1'); - await r.get('/exists2'); - - expect(logger.info).toHaveBeenCalledTimes(2); - expect(logger.info).toHaveBeenNthCalledWith( - 1, - expect.stringContaining('200'), - ); - expect(logger.info).toHaveBeenNthCalledWith( - 2, - expect.stringContaining('201'), - ); - }); -}); diff --git a/packages/backend-common/src/deprecated/middleware/requestLoggingHandler.ts b/packages/backend-common/src/deprecated/middleware/requestLoggingHandler.ts deleted file mode 100644 index f30f2de659..0000000000 --- a/packages/backend-common/src/deprecated/middleware/requestLoggingHandler.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { MiddlewareFactory } from '../../../../backend-defaults/src/entrypoints/rootHttpRouter/http/MiddlewareFactory'; -import { RequestHandler } from 'express'; -import { ConfigReader } from '@backstage/config'; -import { LoggerService } from '@backstage/backend-plugin-api'; -import { getRootLogger } from '../logging'; - -/** - * Logs incoming requests. - * - * @public - * @param logger - An optional logger to use. If not specified, the root logger will be used. - * @returns An Express request handler - * @deprecated Use {@link @backstage/backend-app-api#MiddlewareFactory.create.logging} instead - */ -export function requestLoggingHandler(logger?: LoggerService): RequestHandler { - return MiddlewareFactory.create({ - config: new ConfigReader({}), - logger: logger ?? getRootLogger(), - }).logging(); -} diff --git a/packages/backend-common/src/deprecated/middleware/statusCheckHandler.test.ts b/packages/backend-common/src/deprecated/middleware/statusCheckHandler.test.ts deleted file mode 100644 index 7393276045..0000000000 --- a/packages/backend-common/src/deprecated/middleware/statusCheckHandler.test.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import express from 'express'; -import request from 'supertest'; -import { statusCheckHandler } from './statusCheckHandler'; - -describe('statusCheckHandler', () => { - it('gives status 200 when using default', async () => { - const app = express(); - app.use('/healthcheck', await statusCheckHandler()); - - const response = await request(app).get('/healthcheck'); - - expect(response.status).toBe(200); - expect(response.text).toBe(JSON.stringify({ status: 'ok' })); - }); - - it('gives status 200 when status function returns true', async () => { - const app = express(); - const status = { foo: 'bar' }; - const statusCheck = () => Promise.resolve(status); - app.use('/healthcheck', await statusCheckHandler({ statusCheck })); - - const response = await request(app).get('/healthcheck'); - - expect(response.status).toBe(200); - expect(response.text).toBe(JSON.stringify(status)); - }); - - it('gives status 500 when status check throws an error', async () => { - const app = express(); - const statusCheck = () => { - throw Error('error!'); - }; - app.use('/healthcheck', await statusCheckHandler({ statusCheck })); - - const response = await request(app).get('/healthcheck'); - - expect(response.status).toBe(500); - }); -}); diff --git a/packages/backend-common/src/deprecated/middleware/statusCheckHandler.ts b/packages/backend-common/src/deprecated/middleware/statusCheckHandler.ts deleted file mode 100644 index ebaf84c1b9..0000000000 --- a/packages/backend-common/src/deprecated/middleware/statusCheckHandler.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { NextFunction, Request, Response, RequestHandler } from 'express'; - -/** - * A custom status checking function, passed to {@link statusCheckHandler} and - * {@link createStatusCheckRouter}. - * - * @public - * @deprecated Migrate to the {@link https://backstage.io/docs/backend-system/ | new backend system} and use the {@link https://backstage.io/docs/backend-system/core-services/root-health | Root Health Service} instead. - */ -export type StatusCheck = () => Promise; - -/** - * Options passed to {@link statusCheckHandler}. - * - * @public - * @deprecated Migrate to the {@link https://backstage.io/docs/backend-system/ | new backend system} and use the {@link https://backstage.io/docs/backend-system/core-services/root-health | Root Health Service} instead. - */ -export interface StatusCheckHandlerOptions { - /** - * Optional status function which returns a message. - */ - statusCheck?: StatusCheck; -} - -/** - * Express middleware for status checks. - * - * This is commonly used to implement healthcheck and readiness routes. - * - * @public - * @param options - An optional configuration object. - * @returns An Express error request handler - * @deprecated Migrate to the {@link https://backstage.io/docs/backend-system/ | new backend system} and use the {@link https://backstage.io/docs/backend-system/core-services/root-health | Root Health Service} instead. - */ -export async function statusCheckHandler( - options: StatusCheckHandlerOptions = {}, -): Promise { - const statusCheck: StatusCheck = options.statusCheck - ? options.statusCheck - : () => Promise.resolve({ status: 'ok' }); - - return async (_request: Request, response: Response, next: NextFunction) => { - try { - const status = await statusCheck(); - response.status(200).json(status); - } catch (err) { - next(err); - } - }; -} diff --git a/packages/backend-common/src/deprecated/scm/git.test.ts b/packages/backend-common/src/deprecated/scm/git.test.ts deleted file mode 100644 index 1c07dfb917..0000000000 --- a/packages/backend-common/src/deprecated/scm/git.test.ts +++ /dev/null @@ -1,606 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -jest.mock('isomorphic-git'); -jest.mock('isomorphic-git/http/node'); -jest.mock('fs-extra'); - -import * as isomorphic from 'isomorphic-git'; -import { Git } from './git'; -import http from 'isomorphic-git/http/node'; -import fs from 'fs-extra'; - -describe('Git', () => { - beforeEach(() => { - jest.resetAllMocks(); - }); - - describe('add', () => { - it('should call isomorphic-git add with the correct arguments', async () => { - const git = Git.fromAuth({}); - const dir = 'mockdirectory'; - const filepath = 'mockfile/path'; - - await git.add({ dir, filepath }); - - expect(isomorphic.add).toHaveBeenCalledWith({ - fs, - dir, - filepath, - }); - }); - }); - - describe('addRemote', () => { - it('should call isomorphic-git with the correct arguments', async () => { - const git = Git.fromAuth({}); - const dir = 'mockdirectory'; - const remote = 'origin'; - const url = 'git@github.com/something/sads'; - const force = true; - - await git.addRemote({ dir, remote, url, force }); - - expect(isomorphic.addRemote).toHaveBeenCalledWith({ - fs, - dir, - remote, - url, - force, - }); - }); - }); - - describe('remove', () => { - it('should call isomorphic-git remove with the correct arguments', async () => { - const git = Git.fromAuth({}); - const dir = 'mockdirectory'; - const filepath = 'mockfile/path'; - - await git.remove({ dir, filepath }); - - expect(isomorphic.remove).toHaveBeenCalledWith({ - fs, - dir, - filepath, - }); - }); - }); - - describe('deleteRemote', () => { - it('should call isomorphic-git with the correct arguments', async () => { - const git = Git.fromAuth({}); - const dir = 'mockdirectory'; - const remote = 'origin'; - - await git.deleteRemote({ dir, remote }); - - expect(isomorphic.deleteRemote).toHaveBeenCalledWith({ - fs, - dir, - remote, - }); - }); - }); - - describe('checkout', () => { - it('should call isomorphic-git with the correct arguments', async () => { - const git = Git.fromAuth({}); - const dir = 'mockdirectory'; - const ref = 'master'; - - await git.checkout({ dir, ref }); - - expect(isomorphic.checkout).toHaveBeenCalledWith({ - fs, - dir, - ref, - }); - }); - }); - - describe('branch', () => { - it('should call isomorphic-git with the correct arguments', async () => { - const git = Git.fromAuth({}); - const dir = 'mockdirectory'; - const ref = 'master'; - - await git.branch({ dir, ref }); - - expect(isomorphic.branch).toHaveBeenCalledWith({ - fs, - dir, - ref, - }); - }); - }); - - describe('commit', () => { - it('should call isomorphic-git with the correct arguments', async () => { - const git = Git.fromAuth({}); - const dir = 'mockdirectory'; - const message = 'Inital Commit'; - const author = { - name: 'author', - email: 'test@backstage.io', - }; - const committer = { - name: 'comitter', - email: 'test@backstage.io', - }; - - await git.commit({ dir, message, author, committer }); - - expect(isomorphic.commit).toHaveBeenCalledWith({ - fs, - dir, - message, - author, - committer, - }); - }); - }); - - describe('clone', () => { - it('should call isomorphic-git with the correct arguments', async () => { - const url = 'http://github.com/some/repo'; - const dir = '/some/mock/dir'; - const auth = { - username: 'blob', - password: 'hunter2', - }; - const git = Git.fromAuth(auth); - - await git.clone({ url, dir }); - - expect(isomorphic.clone).toHaveBeenCalledWith({ - fs, - http, - url, - dir, - singleBranch: true, - depth: 1, - onProgress: expect.any(Function), - headers: { - 'user-agent': 'git/@isomorphic-git', - }, - onAuth: expect.any(Function), - }); - }); - - it('should call isomorphic-git with the correct arguments (Bearer)', async () => { - const url = 'http://github.com/some/repo'; - const dir = '/some/mock/dir'; - const auth = { - token: 'test', - }; - const git = Git.fromAuth(auth); - - await git.clone({ url, dir }); - - expect(isomorphic.clone).toHaveBeenCalledWith({ - fs, - http, - url, - dir, - singleBranch: true, - depth: 1, - onProgress: expect.any(Function), - headers: { - Authorization: 'Bearer test', - 'user-agent': 'git/@isomorphic-git', - }, - onAuth: expect.any(Function), - }); - }); - - it('should pass a function that returns the authorization as the onAuth handler when username and password are specified', async () => { - const url = 'http://github.com/some/repo'; - const dir = '/some/mock/dir'; - const auth = { - username: 'blob', - password: 'hunter2', - }; - const git = Git.fromAuth(auth); - - await git.clone({ url, dir }); - - const { onAuth } = ( - isomorphic.clone as unknown as jest.Mock<(typeof isomorphic)['clone']> - ).mock.calls[0][0]!; - - expect(onAuth()).toEqual(auth); - }); - - it('should pass the provided callback as the onAuth handler when on auth is specified', async () => { - const url = 'http://github.com/some/repo'; - const dir = '/some/mock/dir'; - const auth = { - username: 'from', - password: 'callback', - }; - - const git = Git.fromAuth({ onAuth: () => auth }); - - await git.clone({ url, dir }); - - const { onAuth } = ( - isomorphic.clone as unknown as jest.Mock<(typeof isomorphic)['clone']> - ).mock.calls[0][0]!; - - expect(onAuth()).toEqual(auth); - }); - - it('should propagate the data from the error handler', async () => { - const url = 'http://github.com/some/repo'; - const dir = '/some/mock/dir'; - const auth = { - username: 'blob', - password: 'hunter2', - }; - const git = Git.fromAuth(auth); - - (isomorphic.clone as jest.Mock).mockImplementation(() => { - const error: Error & { data?: unknown } = new Error('mock error'); - error.data = { some: 'more information here' }; - - throw error; - }); - - await expect(git.clone({ url, dir })).rejects.toThrow( - 'more information here', - ); - }); - }); - - describe('currentBranch', () => { - it('should call isomorphic-git with the correct arguments', async () => { - const dir = '/some/mock/dir'; - const fullName = true; - const git = Git.fromAuth({}); - - await git.currentBranch({ dir, fullName }); - - expect(isomorphic.currentBranch).toHaveBeenCalledWith({ - fs, - dir, - fullname: true, - }); - - await git.currentBranch({ dir }); - - expect(isomorphic.currentBranch).toHaveBeenCalledWith({ - fs, - dir, - fullname: false, - }); - }); - }); - - describe('fetch', () => { - it('should call isomorphic-git with the correct arguments', async () => { - const remote = 'http://github.com/some/repo'; - const dir = '/some/mock/dir'; - const auth = { - username: 'blob', - password: 'hunter2', - }; - const git = Git.fromAuth(auth); - - await git.fetch({ remote, dir, tags: true }); - - expect(isomorphic.fetch).toHaveBeenCalledWith({ - fs, - http, - remote, - dir, - tags: true, - onProgress: expect.any(Function), - headers: { - 'user-agent': 'git/@isomorphic-git', - }, - onAuth: expect.any(Function), - }); - }); - - it('should call isomorphic-git with the correct arguments (Bearer)', async () => { - const remote = 'http://github.com/some/repo'; - const dir = '/some/mock/dir'; - const auth = { - token: 'test', - }; - const git = Git.fromAuth(auth); - - await git.fetch({ remote, dir }); - - expect(isomorphic.fetch).toHaveBeenCalledWith({ - fs, - http, - remote, - dir, - tags: false, - onProgress: expect.any(Function), - headers: { - Authorization: 'Bearer test', - 'user-agent': 'git/@isomorphic-git', - }, - onAuth: expect.any(Function), - }); - }); - - it('should pass a function that returns the authorization as the onAuth handler', async () => { - const remote = 'http://github.com/some/repo'; - const dir = '/some/mock/dir'; - const auth = { - username: 'blob', - password: 'hunter2', - }; - const git = Git.fromAuth(auth); - - await git.fetch({ remote, dir }); - - const { onAuth } = ( - isomorphic.fetch as unknown as jest.Mock<(typeof isomorphic)['fetch']> - ).mock.calls[0][0]!; - - expect(onAuth()).toEqual(auth); - }); - - it('should propagate the data from the error handler', async () => { - const remote = 'http://github.com/some/repo'; - const dir = '/some/mock/dir'; - const auth = { - username: 'blob', - password: 'hunter2', - }; - const git = Git.fromAuth(auth); - - (isomorphic.fetch as jest.Mock).mockImplementation(() => { - const error: Error & { data?: unknown } = new Error('mock error'); - error.data = { some: 'more information here' }; - - throw error; - }); - - await expect(git.fetch({ remote, dir })).rejects.toThrow( - 'more information here', - ); - }); - }); - - describe('init', () => { - it('should call isomorphic-git with the correct arguments', async () => { - const dir = '/some/mock/dir'; - const defaultBranch = 'master'; - - const git = Git.fromAuth({}); - - await git.init({ dir, defaultBranch }); - - expect(isomorphic.init).toHaveBeenCalledWith({ - fs, - dir, - defaultBranch, - }); - }); - }); - - describe('merge', () => { - it('should call isomorphic-git with the correct arguments', async () => { - const dir = '/some/mock/dir'; - const author = { - name: 'author', - email: 'test@backstage.io', - }; - const committer = { - name: 'comitter', - email: 'test@backstage.io', - }; - const theirs = 'master'; - const ours = 'production'; - - const git = Git.fromAuth({}); - - await git.merge({ dir, theirs, ours, author, committer }); - - expect(isomorphic.merge).toHaveBeenCalledWith({ - fs, - dir, - ours, - theirs, - author, - committer, - }); - }); - }); - - describe('push', () => { - it('should call isomorphic-git with the correct arguments', async () => { - const remote = 'origin'; - const dir = '/some/mock/dir'; - const auth = { - username: 'blob', - password: 'hunter2', - }; - const git = Git.fromAuth(auth); - const remoteRef = 'master'; - const force = true; - - await git.push({ dir, remote, remoteRef, force }); - - expect(isomorphic.push).toHaveBeenCalledWith({ - fs, - http, - remote, - dir, - remoteRef, - force, - onProgress: expect.any(Function), - headers: { - 'user-agent': 'git/@isomorphic-git', - }, - onAuth: expect.any(Function), - }); - }); - - it('should call isomorphic-git with the correct arguments (Bearer)', async () => { - const remote = 'origin'; - const dir = '/some/mock/dir'; - const auth = { - token: 'test', - }; - const git = Git.fromAuth(auth); - const remoteRef = 'master'; - const force = true; - - await git.push({ dir, remote, remoteRef, force }); - - expect(isomorphic.push).toHaveBeenCalledWith({ - fs, - http, - remote, - dir, - remoteRef, - force, - onProgress: expect.any(Function), - headers: { - Authorization: 'Bearer test', - 'user-agent': 'git/@isomorphic-git', - }, - onAuth: expect.any(Function), - }); - }); - - it('should call isomorphic-git with remoteRef parameter', async () => { - const remote = 'origin'; - const remoteRef = 'refs/for/master'; - const dir = '/some/mock/dir'; - const auth = { - username: 'blob', - password: 'hunter2', - }; - const git = Git.fromAuth(auth); - - await git.push({ dir, remote, remoteRef }); - - expect(isomorphic.push).toHaveBeenCalledWith({ - fs, - http, - remote, - remoteRef, - dir, - onProgress: expect.any(Function), - headers: { - 'user-agent': 'git/@isomorphic-git', - }, - onAuth: expect.any(Function), - }); - }); - - it('should pass a function that returns the authorization as the onAuth handler', async () => { - const remote = 'origin'; - const dir = '/some/mock/dir'; - const auth = { - username: 'blob', - password: 'hunter2', - }; - const git = Git.fromAuth(auth); - const remoteRef = 'master'; - const force = true; - - await git.push({ remote, dir, remoteRef, force }); - - const { onAuth } = ( - isomorphic.push as unknown as jest.Mock<(typeof isomorphic)['push']> - ).mock.calls[0][0]!; - - expect(onAuth()).toEqual(auth); - }); - - it('should propagate the data from the error handler', async () => { - const remote = 'origin'; - const dir = '/some/mock/dir'; - const auth = { - username: 'blob', - password: 'hunter2', - }; - const git = Git.fromAuth(auth); - const remoteRef = 'master'; - const force = true; - - (isomorphic.push as jest.Mock).mockImplementation(() => { - const error: Error & { data?: unknown } = new Error('mock error'); - error.data = { some: 'more information here' }; - - throw error; - }); - - await expect(git.push({ remote, dir, remoteRef, force })).rejects.toThrow( - 'more information here', - ); - }); - }); - - describe('readCommit', () => { - it('should call isomorphic-git with the correct arguments', async () => { - const dir = '/some/mock/dir'; - const sha = 'as43bd7'; - - const git = Git.fromAuth({}); - - await git.readCommit({ dir, sha }); - - expect(isomorphic.readCommit).toHaveBeenCalledWith({ - fs, - dir, - oid: sha, - }); - }); - }); - - describe('resolveRef', () => { - it('should call isomorphic-git with the correct arguments', async () => { - const dir = '/some/mock/dir'; - const ref = 'as43bd7'; - - const git = Git.fromAuth({}); - - await git.resolveRef({ dir, ref }); - - expect(isomorphic.resolveRef).toHaveBeenCalledWith({ - fs, - dir, - ref, - }); - }); - }); - - describe('log', () => { - it('should call isomorphic-git with the correct arguments', async () => { - const dir = '/some/mock/dir'; - const ref = 'as43bd7'; - - const git = Git.fromAuth({}); - - await git.log({ dir, ref }); - - expect(isomorphic.log).toHaveBeenCalledWith({ - fs, - dir, - ref, - }); - }); - }); -}); diff --git a/packages/backend-common/src/deprecated/scm/git.ts b/packages/backend-common/src/deprecated/scm/git.ts deleted file mode 100644 index 1a182e6f4d..0000000000 --- a/packages/backend-common/src/deprecated/scm/git.ts +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import git, { - ProgressCallback, - MergeResult, - ReadCommitResult, - AuthCallback, -} from 'isomorphic-git'; -import http from 'isomorphic-git/http/node'; -import fs from 'fs-extra'; -import { LoggerService } from '@backstage/backend-plugin-api'; - -function isAuthCallbackOptions( - options: StaticAuthOptions | AuthCallbackOptions, -): options is AuthCallbackOptions { - return 'onAuth' in options; -} - -/** - * Configure static credential for authentication - * @public - * @deprecated This type is deprecated and will be removed in a future release, see https://github.com/backstage/backstage/issues/24493. - */ -export type StaticAuthOptions = { - username?: string; - password?: string; - token?: string; - logger?: LoggerService; -}; - -/** - * Configure an authentication callback that can provide credentials on demand - * @public - * @deprecated This type is deprecated and will be removed in a future release, see https://github.com/backstage/backstage/issues/24493. - */ -export type AuthCallbackOptions = { - onAuth: AuthCallback; - logger?: LoggerService; -}; - -/* -provider username password -Azure 'notempty' token -Bitbucket Cloud 'x-token-auth' token -Bitbucket Server username password or token -GitHub 'x-access-token' token -GitLab 'oauth2' token - -From : https://isomorphic-git.org/docs/en/onAuth with fix for GitHub - -Or token provided as `token` for Bearer auth header -instead of Basic Auth (e.g., Bitbucket Server). -*/ - -/** - * A convenience wrapper around the `isomorphic-git` library. - * @public - * @deprecated This class is deprecated and will be removed in a future release, see https://github.com/backstage/backstage/issues/24493. - */ - -export class Git { - private readonly headers: { - [x: string]: string; - }; - - private constructor( - private readonly config: { - onAuth: AuthCallback; - token?: string; - logger?: LoggerService; - }, - ) { - this.onAuth = config.onAuth; - - this.headers = { - 'user-agent': 'git/@isomorphic-git', - ...(config.token ? { Authorization: `Bearer ${config.token}` } : {}), - }; - } - - async add(options: { dir: string; filepath: string }): Promise { - const { dir, filepath } = options; - this.config.logger?.info(`Adding file {dir=${dir},filepath=${filepath}}`); - - return git.add({ fs, dir, filepath }); - } - - async addRemote(options: { - dir: string; - remote: string; - url: string; - force?: boolean; - }): Promise { - const { dir, url, remote, force } = options; - this.config.logger?.info( - `Creating new remote {dir=${dir},remote=${remote},url=${url}}`, - ); - return git.addRemote({ fs, dir, remote, url, force }); - } - - async deleteRemote(options: { dir: string; remote: string }): Promise { - const { dir, remote } = options; - this.config.logger?.info(`Deleting remote {dir=${dir},remote=${remote}}`); - return git.deleteRemote({ fs, dir, remote }); - } - - async checkout(options: { dir: string; ref: string }): Promise { - const { dir, ref } = options; - this.config.logger?.info(`Checking out branch {dir=${dir},ref=${ref}}`); - - return git.checkout({ fs, dir, ref }); - } - - async branch(options: { dir: string; ref: string }): Promise { - const { dir, ref } = options; - this.config.logger?.info(`Creating branch {dir=${dir},ref=${ref}`); - - return git.branch({ fs, dir, ref }); - } - - async commit(options: { - dir: string; - message: string; - author: { name: string; email: string }; - committer: { name: string; email: string }; - }): Promise { - const { dir, message, author, committer } = options; - this.config.logger?.info( - `Committing file to repo {dir=${dir},message=${message}}`, - ); - return git.commit({ fs, dir, message, author, committer }); - } - - /** https://isomorphic-git.org/docs/en/clone */ - async clone(options: { - url: string; - dir: string; - ref?: string; - depth?: number; - noCheckout?: boolean; - }): Promise { - const { url, dir, ref, depth, noCheckout } = options; - this.config.logger?.info(`Cloning repo {dir=${dir},url=${url}}`); - - try { - return await git.clone({ - fs, - http, - url, - dir, - ref, - singleBranch: true, - depth: depth ?? 1, - noCheckout, - onProgress: this.onProgressHandler(), - headers: this.headers, - onAuth: this.onAuth, - }); - } catch (ex) { - this.config.logger?.error(`Failed to clone repo {dir=${dir},url=${url}}`); - if (ex.data) { - throw new Error(`${ex.message} {data=${JSON.stringify(ex.data)}}`); - } - throw ex; - } - } - - /** https://isomorphic-git.org/docs/en/currentBranch */ - async currentBranch(options: { - dir: string; - fullName?: boolean; - }): Promise { - const { dir, fullName = false } = options; - return git.currentBranch({ fs, dir, fullname: fullName }) as Promise< - string | undefined - >; - } - - /** https://isomorphic-git.org/docs/en/fetch */ - async fetch(options: { - dir: string; - remote?: string; - tags?: boolean; - }): Promise { - const { dir, remote = 'origin', tags = false } = options; - this.config.logger?.info( - `Fetching remote=${remote} for repository {dir=${dir}}`, - ); - - try { - await git.fetch({ - fs, - http, - dir, - remote, - tags, - onProgress: this.onProgressHandler(), - headers: this.headers, - onAuth: this.onAuth, - }); - } catch (ex) { - this.config.logger?.error( - `Failed to fetch repo {dir=${dir},remote=${remote}}`, - ); - if (ex.data) { - throw new Error(`${ex.message} {data=${JSON.stringify(ex.data)}}`); - } - throw ex; - } - } - - async init(options: { dir: string; defaultBranch?: string }): Promise { - const { dir, defaultBranch = 'master' } = options; - this.config.logger?.info(`Init git repository {dir=${dir}}`); - - return git.init({ - fs, - dir, - defaultBranch, - }); - } - - /** https://isomorphic-git.org/docs/en/merge */ - async merge(options: { - dir: string; - theirs: string; - ours?: string; - author: { name: string; email: string }; - committer: { name: string; email: string }; - }): Promise { - const { dir, theirs, ours, author, committer } = options; - this.config.logger?.info( - `Merging branch '${theirs}' into '${ours}' for repository {dir=${dir}}`, - ); - - // If ours is undefined, current branch is used. - return git.merge({ - fs, - dir, - ours, - theirs, - author, - committer, - }); - } - - async push(options: { - dir: string; - remote: string; - remoteRef?: string; - force?: boolean; - }) { - const { dir, remote, remoteRef, force } = options; - this.config.logger?.info( - `Pushing directory to remote {dir=${dir},remote=${remote}}`, - ); - try { - return await git.push({ - fs, - dir, - http, - onProgress: this.onProgressHandler(), - remoteRef, - force, - headers: this.headers, - remote, - onAuth: this.onAuth, - }); - } catch (ex) { - this.config.logger?.error( - `Failed to push to repo {dir=${dir}, remote=${remote}}`, - ); - if (ex.data) { - throw new Error(`${ex.message} {data=${JSON.stringify(ex.data)}}`); - } - throw ex; - } - } - - /** https://isomorphic-git.org/docs/en/readCommit */ - async readCommit(options: { - dir: string; - sha: string; - }): Promise { - const { dir, sha } = options; - return git.readCommit({ fs, dir, oid: sha }); - } - - /** https://isomorphic-git.org/docs/en/remove */ - async remove(options: { dir: string; filepath: string }): Promise { - const { dir, filepath } = options; - this.config.logger?.info( - `Removing file from git index {dir=${dir},filepath=${filepath}}`, - ); - return git.remove({ fs, dir, filepath }); - } - - /** https://isomorphic-git.org/docs/en/resolveRef */ - async resolveRef(options: { dir: string; ref: string }): Promise { - const { dir, ref } = options; - return git.resolveRef({ fs, dir, ref }); - } - - /** https://isomorphic-git.org/docs/en/log */ - async log(options: { - dir: string; - ref?: string; - }): Promise { - const { dir, ref } = options; - return git.log({ - fs, - dir, - ref: ref ?? 'HEAD', - }); - } - - private onAuth: AuthCallback; - - private onProgressHandler = (): ProgressCallback => { - let currentPhase = ''; - - return event => { - if (currentPhase !== event.phase) { - currentPhase = event.phase; - this.config.logger?.info(event.phase); - } - const total = event.total - ? `${Math.round((event.loaded / event.total) * 100)}%` - : event.loaded; - this.config.logger?.debug(`status={${event.phase},total={${total}}}`); - }; - }; - - static fromAuth = (options: StaticAuthOptions | AuthCallbackOptions) => { - if (isAuthCallbackOptions(options)) { - const { onAuth, logger } = options; - return new Git({ onAuth, logger }); - } - - const { username, password, token, logger } = options; - return new Git({ onAuth: () => ({ username, password }), token, logger }); - }; -} diff --git a/packages/backend-common/src/deprecated/scm/index.ts b/packages/backend-common/src/deprecated/scm/index.ts deleted file mode 100644 index f9c59e99eb..0000000000 --- a/packages/backend-common/src/deprecated/scm/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { Git } from './git'; -export type { StaticAuthOptions, AuthCallbackOptions } from './git'; diff --git a/packages/backend-common/src/deprecated/service/createServiceBuilder.ts b/packages/backend-common/src/deprecated/service/createServiceBuilder.ts deleted file mode 100644 index e731056f72..0000000000 --- a/packages/backend-common/src/deprecated/service/createServiceBuilder.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { ServiceBuilderImpl } from './lib/ServiceBuilderImpl'; -import { ServiceBuilder } from './types'; - -/** - * Creates a new service builder. - * @public - * @deprecated We are going to deprecated this old way of creating services in a near future, if you are using this service helper, please checkout the {@link https://backstage.io/docs/backend-system/building-backends/migrating | backend} and {@link https://backstage.io/docs/backend-system/building-plugins-and-modules/migrating | plugin} migration guides. - */ -export function createServiceBuilder(_module: NodeModule): ServiceBuilder { - return new ServiceBuilderImpl(_module); -} diff --git a/packages/backend-common/src/deprecated/service/createStatusCheckRouter.test.ts b/packages/backend-common/src/deprecated/service/createStatusCheckRouter.test.ts deleted file mode 100644 index 604a1eb12f..0000000000 --- a/packages/backend-common/src/deprecated/service/createStatusCheckRouter.test.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import express from 'express'; -import * as winston from 'winston'; -import request from 'supertest'; -import { createStatusCheckRouter } from './createStatusCheckRouter'; - -describe('createStatusCheckRouter', () => { - const logger = winston.createLogger(); - - it('gives status 200 when using default path', async () => { - const app = express(); - app.use('', await createStatusCheckRouter({ logger })); - - const response = await request(app).get('/healthcheck'); - - expect(response.status).toBe(200); - expect(response.text).toBe(JSON.stringify({ status: 'ok' })); - }); - - it('gives status 200 when using custom path', async () => { - const app = express(); - app.use('', await createStatusCheckRouter({ logger, path: '/ready' })); - - const response = await request(app).get('/ready'); - - expect(response.status).toBe(200); - expect(response.text).toBe(JSON.stringify({ status: 'ok' })); - }); - - it('gives status 500 when status check throws an error', async () => { - const app = express(); - const statusCheck = () => { - throw Error('error!'); - }; - app.use('', await createStatusCheckRouter({ logger, statusCheck })); - - const response = await request(app).get('/healthcheck'); - - expect(response.status).toBe(500); - }); -}); diff --git a/packages/backend-common/src/deprecated/service/createStatusCheckRouter.ts b/packages/backend-common/src/deprecated/service/createStatusCheckRouter.ts deleted file mode 100644 index fdece10ec5..0000000000 --- a/packages/backend-common/src/deprecated/service/createStatusCheckRouter.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { LoggerService } from '@backstage/backend-plugin-api'; -import Router from 'express-promise-router'; -import express from 'express'; -import { errorHandler, statusCheckHandler, StatusCheck } from '..'; - -/** - * Creates a default status checking router, that you can add to your express - * app. - * - * @remarks - * - * This adds a `/healthcheck` route (or any other path, if given as an - * argument), which your infra can call to see if the service is ready to serve - * requests. - * - * @public - * @deprecated Migrate to the {@link https://backstage.io/docs/backend-system/ | new backend system} and use the {@link https://backstage.io/docs/backend-system/core-services/root-health | Root Health Service} instead. - */ -export async function createStatusCheckRouter(options: { - logger: LoggerService; - /** - * The path (including a leading slash) that the health check should be - * mounted on. - * - * @defaultValue '/healthcheck' - */ - path?: string; - /** - * If not implemented, the default express middleware always returns 200. - * Override this to implement your own logic for a health check. - */ - statusCheck?: StatusCheck; -}): Promise { - const router = Router(); - const { path = '/healthcheck', statusCheck } = options; - - router.use(path, await statusCheckHandler({ statusCheck })); - router.use(errorHandler()); - - return router; -} diff --git a/packages/backend-common/src/deprecated/service/index.ts b/packages/backend-common/src/deprecated/service/index.ts deleted file mode 100644 index d01f25fad3..0000000000 --- a/packages/backend-common/src/deprecated/service/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { createServiceBuilder } from './createServiceBuilder'; -export { createStatusCheckRouter } from './createStatusCheckRouter'; -export type { ServiceBuilder, RequestLoggingHandlerFactory } from './types'; diff --git a/packages/backend-common/src/deprecated/service/lib/ServiceBuilderImpl.test.ts b/packages/backend-common/src/deprecated/service/lib/ServiceBuilderImpl.test.ts deleted file mode 100644 index 6229cbb683..0000000000 --- a/packages/backend-common/src/deprecated/service/lib/ServiceBuilderImpl.test.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { NextFunction, Request, Response } from 'express'; -import { applyCspDirectives, ServiceBuilderImpl } from './ServiceBuilderImpl'; - -describe('ServiceBuilderImpl', () => { - describe('applyCspDirectives', () => { - it('copies actual values', () => { - const result = applyCspDirectives({ key: ['value'] }); - expect(result).toEqual( - expect.objectContaining({ - 'default-src': ["'self'"], - key: ['value'], - }), - ); - }); - - it('removes false value keys', () => { - const result = applyCspDirectives({ 'upgrade-insecure-requests': false }); - expect(result!['upgrade-insecure-requests']).toBeUndefined(); - }); - }); - - describe('setCustomErrorHandler', () => { - it('check if custom error handler is undefined', () => { - const serviceBuilder = new ServiceBuilderImpl(module); - const serviceBuilderProto = Object.getPrototypeOf(serviceBuilder); - expect(serviceBuilderProto.errorHandler).toBeUndefined(); - }); - - it('adds custom error handler', () => { - const serviceBuilder = new ServiceBuilderImpl(module); - const serviceBuilderProto = Object.getPrototypeOf(serviceBuilder); - const customErrorHandler = ( - error: Error, - _req: Request, - _res: Response, - next: NextFunction, - ) => { - next(error); - }; - serviceBuilderProto.setErrorHandler(customErrorHandler); - expect(serviceBuilderProto.errorHandler).toEqual(customErrorHandler); - }); - }); -}); diff --git a/packages/backend-common/src/deprecated/service/lib/ServiceBuilderImpl.ts b/packages/backend-common/src/deprecated/service/lib/ServiceBuilderImpl.ts deleted file mode 100644 index b338eb20b1..0000000000 --- a/packages/backend-common/src/deprecated/service/lib/ServiceBuilderImpl.ts +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Config } from '@backstage/config'; -import compression from 'compression'; -import cors from 'cors'; -import express, { Router, ErrorRequestHandler } from 'express'; -import helmet, { HelmetOptions } from 'helmet'; -import { ContentSecurityPolicyOptions } from 'helmet/dist/types/middlewares/content-security-policy'; -import * as http from 'http'; -import { LoggerService } from '@backstage/backend-plugin-api'; -import { useHotCleanup } from '../../hot'; -import { getRootLogger } from '../../logging'; -import { - errorHandler as defaultErrorHandler, - notFoundHandler, - requestLoggingHandler as defaultRequestLoggingHandler, -} from '../../middleware'; -import { RequestLoggingHandlerFactory, ServiceBuilder } from '../types'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { - readCorsOptions, - readHelmetOptions, - readHttpServerOptions, - HttpServerOptions, - createHttpServer, -} from '../../../../../backend-defaults/src/entrypoints/rootHttpRouter/http'; - -export type CspOptions = Record; - -export class ServiceBuilderImpl implements ServiceBuilder { - private logger: LoggerService | undefined; - private serverOptions: HttpServerOptions; - private helmetOptions: HelmetOptions; - private corsOptions: cors.CorsOptions; - private routers: [string, Router][]; - private requestLoggingHandler: RequestLoggingHandlerFactory | undefined; - private errorHandler: ErrorRequestHandler | undefined; - private useDefaultErrorHandler: boolean; - // Reference to the module where builder is created - needed for hot module - // reloading - private module: NodeModule; - - constructor(moduleRef: NodeModule) { - this.routers = []; - this.module = moduleRef; - this.useDefaultErrorHandler = true; - - this.serverOptions = readHttpServerOptions(); - this.corsOptions = readCorsOptions(); - this.helmetOptions = readHelmetOptions(); - } - - loadConfig(config: Config): ServiceBuilder { - const backendConfig = config.getOptionalConfig('backend'); - - this.serverOptions = readHttpServerOptions(backendConfig); - this.corsOptions = readCorsOptions(backendConfig); - this.helmetOptions = readHelmetOptions(backendConfig); - - return this; - } - - setPort(port: number): ServiceBuilder { - this.serverOptions.listen.port = port; - return this; - } - - setHost(host: string): ServiceBuilder { - this.serverOptions.listen.host = host; - return this; - } - - setLogger(logger: LoggerService): ServiceBuilder { - this.logger = logger; - return this; - } - - setHttpsSettings(settings: { - certificate: { key: string; cert: string } | { hostname: string }; - }): ServiceBuilder { - if ('hostname' in settings.certificate) { - this.serverOptions.https = { - certificate: { - ...settings.certificate, - type: 'generated', - }, - }; - } else { - this.serverOptions.https = { - certificate: { - ...settings.certificate, - type: 'pem', - }, - }; - } - return this; - } - - enableCors(options: cors.CorsOptions): ServiceBuilder { - this.corsOptions = options; - return this; - } - - setCsp(options: CspOptions): ServiceBuilder { - const csp = this.helmetOptions.contentSecurityPolicy; - this.helmetOptions.contentSecurityPolicy = { - ...(typeof csp === 'object' ? csp : {}), - directives: applyCspDirectives(options), - }; - return this; - } - - addRouter(root: string, router: Router): ServiceBuilder { - this.routers.push([root, router]); - return this; - } - - setRequestLoggingHandler( - requestLoggingHandler: RequestLoggingHandlerFactory, - ) { - this.requestLoggingHandler = requestLoggingHandler; - return this; - } - - setErrorHandler(errorHandler: ErrorRequestHandler) { - this.errorHandler = errorHandler; - return this; - } - - disableDefaultErrorHandler() { - this.useDefaultErrorHandler = false; - return this; - } - - async start(): Promise { - const app = express(); - const logger = this.logger ?? getRootLogger(); - - app.use(helmet(this.helmetOptions)); - app.use(cors(this.corsOptions)); - app.use(compression()); - app.use( - (this.requestLoggingHandler ?? defaultRequestLoggingHandler)(logger), - ); - for (const [root, route] of this.routers) { - app.use(root, route); - } - app.use(notFoundHandler()); - - if (this.errorHandler) { - app.use(this.errorHandler); - } - - if (this.useDefaultErrorHandler) { - app.use(defaultErrorHandler()); - } - - const server = await createHttpServer(app, this.serverOptions, { logger }); - - useHotCleanup(this.module, () => - server.stop().catch(error => { - console.error(error); - }), - ); - - await server.start(); - - return server; - } -} - -// TODO(Rugvip): This is a duplicate of the same logic over in backend-app-api. -// It's needed as we don't want to export this helper from there, but need -// It to implement the setCsp method here. -export function applyCspDirectives( - directives: Record | undefined, -): ContentSecurityPolicyOptions['directives'] { - const result: ContentSecurityPolicyOptions['directives'] = - helmet.contentSecurityPolicy.getDefaultDirectives(); - - // TODO(Rugvip): We currently use non-precompiled AJV for validation in the frontend, which uses eval. - // It should be replaced by any other solution that doesn't require unsafe-eval. - result['script-src'] = ["'self'", "'unsafe-eval'"]; - - // TODO(Rugvip): This is removed so that we maintained backwards compatibility - // when bumping to helmet v5, we could remove this as well as - // skip setting `useDefaults: false` in the future. - delete result['form-action']; - - if (directives) { - for (const [key, value] of Object.entries(directives)) { - if (value === false) { - delete result[key]; - } else { - result[key] = value; - } - } - } - - return result; -} diff --git a/packages/backend-common/src/deprecated/service/types.ts b/packages/backend-common/src/deprecated/service/types.ts deleted file mode 100644 index ace0712d2f..0000000000 --- a/packages/backend-common/src/deprecated/service/types.ts +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Config } from '@backstage/config'; -import cors from 'cors'; -import { Router, RequestHandler, ErrorRequestHandler } from 'express'; -import { Server } from 'http'; -import { LoggerService } from '@backstage/backend-plugin-api'; - -/** - * A helper for building backend service instances. - * - * @public - * @deprecated This type is being deprecated along with the {@link @backstage/backend-common#createServiceBuilder} function. - */ -export type ServiceBuilder = { - /** - * Sets the service parameters based on configuration. - * - * @param config - The configuration to read - */ - loadConfig(config: Config): ServiceBuilder; - - /** - * Sets the port to listen on. - * - * If no port is specified, the service will first look for an environment - * variable named PORT and use that if present, otherwise it picks a default - * port (7007). - * - * @param port - The port to listen on - */ - setPort(port: number): ServiceBuilder; - - /** - * Sets the host to listen on. - * - * '' is express default, which listens to all interfaces. - * - * @param host - The host to listen on - */ - setHost(host: string): ServiceBuilder; - - /** - * Sets the logger to use for service-specific logging. - * - * If no logger is given, the default root logger is used. - * - * @param logger - A winston logger - */ - setLogger(logger: LoggerService): ServiceBuilder; - - /** - * Enables CORS handling using the given settings. - * - * If this method is not called, the resulting service will not have any - * built in CORS handling. - * - * @param options - Standard CORS options - */ - enableCors(options: cors.CorsOptions): ServiceBuilder; - - /** - * Configure self-signed certificate generation options. - * - * If this method is not called, the resulting service will use sensible defaults - * - * @param options - Standard certificate options - */ - setHttpsSettings(settings: { - certificate: { key: string; cert: string } | { hostname: string }; - }): ServiceBuilder; - - /** - * Adds a router (similar to the express .use call) to the service. - * - * @param root - The root URL to bind to (e.g. "/api/function1") - * @param router - An express router - */ - addRouter(root: string, router: Router | RequestHandler): ServiceBuilder; - - /** - * Set the request logging handler - * - * If no handler is given the default one is used - * - * @param requestLoggingHandler - a factory function that given a logger returns an handler - */ - setRequestLoggingHandler( - requestLoggingHandler: RequestLoggingHandlerFactory, - ): ServiceBuilder; - - /** - * Sets an additional errorHandler to run before the defaultErrorHandler. - * - * For execution of only the custom error handler make sure to also invoke disableDefaultErrorHandler() - * otherwise the defaultErrorHandler is executed at the end of the error middleware chain. - * - * @param errorHandler - an error handler - */ - setErrorHandler(errorHandler: ErrorRequestHandler): ServiceBuilder; - - /** - * Disables the default error handler - */ - disableDefaultErrorHandler(): ServiceBuilder; - - /** - * Starts the server using the given settings. - */ - start(): Promise; -}; - -/** - * A factory for request loggers. - * - * @public - * @deprecated This type is being deprecated along with the {@link @backstage/backend-common#createServiceBuilder} function. - */ -export type RequestLoggingHandlerFactory = ( - logger?: LoggerService, -) => RequestHandler; diff --git a/packages/backend-common/src/deprecated/tokens/ServerTokenManager.test.ts b/packages/backend-common/src/deprecated/tokens/ServerTokenManager.test.ts deleted file mode 100644 index 2f99164ec1..0000000000 --- a/packages/backend-common/src/deprecated/tokens/ServerTokenManager.test.ts +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { ConfigReader } from '@backstage/config'; -import * as jose from 'jose'; -import { ServerTokenManager } from './ServerTokenManager'; -import { TokenManager } from './types'; -import { DateTime } from 'luxon'; -import { mockServices } from '@backstage/backend-test-utils'; - -const emptyConfig = new ConfigReader({}); -const configWithSecret = new ConfigReader({ - backend: { auth: { keys: [{ secret: 'a-secret-key' }] } }, -}); -const env = process.env; -const logger = mockServices.logger.mock(); - -describe('ServerTokenManager', () => { - beforeEach(() => { - process.env = { ...env }; - }); - - afterEach(() => { - process.env = env; - jest.useRealTimers(); - }); - - describe('getToken', () => { - it('should return a token', async () => { - const tokenManager = ServerTokenManager.fromConfig(configWithSecret, { - logger, - }); - expect((await tokenManager.getToken()).token).toBeDefined(); - }); - - it('should return a token string if using a noop TokenManager', async () => { - const tokenManager = ServerTokenManager.noop(); - expect((await tokenManager.getToken()).token).toBeDefined(); - }); - }); - - describe('authenticate', () => { - it('should not throw if token is valid', async () => { - const tokenManager = ServerTokenManager.fromConfig(configWithSecret, { - logger, - }); - const { token } = await tokenManager.getToken(); - await expect(tokenManager.authenticate(token)).resolves.not.toThrow(); - }); - - it('should throw if token is invalid', async () => { - const tokenManager = ServerTokenManager.fromConfig(configWithSecret, { - logger, - }); - await expect(tokenManager.authenticate('random-string')).rejects.toThrow( - /invalid server token/i, - ); - }); - - it('should validate server tokens created by a different instance using the same secret', async () => { - const tokenManager1 = ServerTokenManager.fromConfig(configWithSecret, { - logger, - }); - const tokenManager2 = ServerTokenManager.fromConfig(configWithSecret, { - logger, - }); - - const { token } = await tokenManager1.getToken(); - - await expect(tokenManager2.authenticate(token)).resolves.not.toThrow(); - }); - - it('should validate server tokens created using any of the secrets', async () => { - const tokenManager1 = ServerTokenManager.fromConfig( - new ConfigReader({ - backend: { auth: { keys: [{ secret: 'a1b2c3' }] } }, - }), - { logger }, - ); - const tokenManager2 = ServerTokenManager.fromConfig( - new ConfigReader({ - backend: { auth: { keys: [{ secret: 'd4e5f6' }] } }, - }), - { logger }, - ); - const tokenManager3 = ServerTokenManager.fromConfig( - new ConfigReader({ - backend: { - auth: { keys: [{ secret: 'a1b2c3' }, { secret: 'd4e5f6' }] }, - }, - }), - { logger }, - ); - - const { token: token1 } = await tokenManager1.getToken(); - await expect(tokenManager3.authenticate(token1)).resolves.not.toThrow(); - - const { token: token2 } = await tokenManager2.getToken(); - await expect(tokenManager3.authenticate(token2)).resolves.not.toThrow(); - }); - - it('should throw for server tokens created using a different secret', async () => { - const tokenManager1 = ServerTokenManager.fromConfig( - new ConfigReader({ - backend: { auth: { keys: [{ secret: 'a1b2c3' }] } }, - }), - { logger }, - ); - const tokenManager2 = ServerTokenManager.fromConfig( - new ConfigReader({ - backend: { auth: { keys: [{ secret: 'd4e5f6' }] } }, - }), - { logger }, - ); - - const { token } = await tokenManager1.getToken(); - - await expect(tokenManager2.authenticate(token)).rejects.toThrow( - /invalid server token/i, - ); - }); - - it('should throw for server tokens created using a noop TokenManager', async () => { - const noopTokenManager = ServerTokenManager.noop(); - const tokenManager = ServerTokenManager.fromConfig( - new ConfigReader({ - backend: { auth: { keys: [{ secret: 'a1b2c3' }] } }, - }), - { logger }, - ); - - const { token } = await noopTokenManager.getToken(); - - await expect(tokenManager.authenticate(token)).rejects.toThrow( - /invalid server token/i, - ); - }); - - it('should throw for server tokens created by a different generated secret', async () => { - (process.env as any).NODE_ENV = 'development'; - const tokenManager1 = ServerTokenManager.fromConfig( - new ConfigReader({ - backend: { auth: { keys: [{ secret: 'a1b2c3' }] } }, - }), - { logger }, - ); - const tokenManager2 = ServerTokenManager.fromConfig(emptyConfig, { - logger, - }); - - const { token } = await tokenManager2.getToken(); - - await expect(tokenManager1.authenticate(token)).rejects.toThrow( - /invalid server token/i, - ); - }); - - it('should throw for expired tokens, and re-issue new ones', async () => { - jest.useFakeTimers(); - - const tokenManager = ServerTokenManager.fromConfig(configWithSecret, { - logger, - }); - - const { token: token1 } = await tokenManager.getToken(); - await expect(tokenManager.authenticate(token1)).resolves.not.toThrow(); - - // Right before the reissue timeout, it still returns the same token - jest.advanceTimersByTime(9 * 60 * 1000); - const { token: token1Again } = await tokenManager.getToken(); - expect(token1).toEqual(token1Again); - await expect(tokenManager.authenticate(token1)).resolves.not.toThrow(); - - // Right after the reissue timeout, the old ones are still valid but returning a new token - jest.advanceTimersByTime(2 * 60 * 1000); - const { token: token2 } = await tokenManager.getToken(); - expect(token1).not.toEqual(token2); - await expect(tokenManager.authenticate(token1)).resolves.not.toThrow(); - await expect(tokenManager.authenticate(token2)).resolves.not.toThrow(); - - // After expiry of the first one, it gets warnings but the newest one is still valid - jest.advanceTimersByTime(52 * 60 * 1000); - await expect(tokenManager.authenticate(token1)).rejects.toThrow( - 'Invalid server token; caused by JWTExpired: "exp" claim timestamp check failed', - ); - await expect(tokenManager.authenticate(token2)).resolves.not.toThrow(); - }); - - it('should work with a manually crafted JWT', async () => { - const secret = 'a1b2c3'; - const token = await new jose.SignJWT({}) - .setProtectedHeader({ alg: 'HS256' }) - .setSubject('backstage-server') - .setExpirationTime(Date.now() + 1000 * 60 * 60) - .sign(jose.base64url.decode(secret)); - - const tokenManager = ServerTokenManager.fromConfig( - new ConfigReader({ - backend: { auth: { keys: [{ secret }] } }, - }), - { logger }, - ); - await expect(tokenManager.authenticate(token)).resolves.toBeUndefined(); - }); - - it('should reject tokens without exp claim', async () => { - const secret = 'a1b2c3'; - const token = await new jose.SignJWT({}) - .setProtectedHeader({ alg: 'HS256' }) - .setSubject('backstage-server') - .sign(jose.base64url.decode(secret)); - - const tokenManager = ServerTokenManager.fromConfig( - new ConfigReader({ - backend: { auth: { keys: [{ secret }] } }, - }), - { logger }, - ); - await expect(tokenManager.authenticate(token)).rejects.toThrow( - 'Invalid server token; caused by AuthenticationError: Server-to-server token had no exp claim', - ); - }); - - it('loads both old and new config', async () => { - const oldSecret = jose.base64url.encode('old'); - const newSecret = jose.base64url.encode('new'); - - const tokenManager = ServerTokenManager.fromConfig( - new ConfigReader({ - backend: { - auth: { - keys: [{ secret: oldSecret }], - externalAccess: [ - { type: 'legacy', options: { secret: newSecret } }, - ], - }, - }, - }), - { logger }, - ); - - const oldToken = await new jose.SignJWT({}) - .setProtectedHeader({ alg: 'HS256' }) - .setSubject('backstage-server') - .setExpirationTime(DateTime.now().plus({ minutes: 1 }).toUnixInteger()) - .sign(jose.base64url.decode(oldSecret)); - const newToken = await new jose.SignJWT({}) - .setProtectedHeader({ alg: 'HS256' }) - .setSubject('backstage-server') - .setExpirationTime(DateTime.now().plus({ minutes: 1 }).toUnixInteger()) - .sign(jose.base64url.decode(newSecret)); - - await expect(tokenManager.authenticate(oldToken)).resolves.not.toThrow(); - await expect(tokenManager.authenticate(newToken)).resolves.not.toThrow(); - }); - }); - - describe('fromConfig', () => { - describe('NODE_ENV === production', () => { - it('should throw if backend auth configuration is missing', () => { - expect(() => - ServerTokenManager.fromConfig(emptyConfig, { logger }), - ).toThrow(); - }); - - it('should throw if no keys are included in the configuration', () => { - expect(() => - ServerTokenManager.fromConfig( - new ConfigReader({ - backend: { auth: { keys: [] } }, - }), - { logger }, - ), - ).toThrow(); - }); - - it('should throw if any key is missing a secret property', () => { - expect(() => - ServerTokenManager.fromConfig( - new ConfigReader({ - backend: { - auth: { - keys: [{ secret: '123' }, {}, { secret: '789' }], - }, - }, - }), - { logger }, - ), - ).toThrow(); - }); - - it('should throw errors when disabled', async () => { - const manager = ServerTokenManager.fromConfig(new ConfigReader({}), { - logger, - allowDisabledTokenManager: true, - }); - - await expect(manager.getToken()).rejects.toThrow( - 'Unable to generate legacy token', - ); - await expect(manager.authenticate('nah')).rejects.toThrow( - 'Unable to authenticate legacy token', - ); - }); - }); - - describe('NODE_ENV === development', () => { - const generateSecretSpy = jest.spyOn(jose, 'generateSecret'); - - beforeEach(() => { - (process.env as any).NODE_ENV = 'development'; - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - it('should generate a key if no config is provided', async () => { - const tokenManager = ServerTokenManager.fromConfig(emptyConfig, { - logger, - }); - const token = await tokenManager.getToken(); - expect(token).toBeDefined(); - expect(generateSecretSpy).toHaveBeenCalledWith('HS256'); - }); - - it('should generate a key if no keys are provided in the configuration', async () => { - const tokenManager = ServerTokenManager.fromConfig( - new ConfigReader({ - backend: { auth: { keys: [] } }, - }), - { logger }, - ); - const token = await tokenManager.getToken(); - expect(token).toBeDefined(); - expect(generateSecretSpy).toHaveBeenCalledWith('HS256'); - }); - - it('should use provided secrets if config is provided', () => { - ServerTokenManager.fromConfig(configWithSecret, { logger }); - expect(generateSecretSpy).not.toHaveBeenCalled(); - }); - }); - }); - - describe('noop', () => { - let noopTokenManager: TokenManager; - - beforeEach(() => { - noopTokenManager = ServerTokenManager.noop(); - }); - - it('should accept tokens it generates', async () => { - const { token } = await noopTokenManager.getToken(); - - await expect(noopTokenManager.authenticate(token)).resolves.not.toThrow(); - }); - - it('should accept tokens generated by other noop token managers', async () => { - const noopTokenManager2 = ServerTokenManager.noop(); - await expect( - noopTokenManager.authenticate( - ( - await noopTokenManager2.getToken() - ).token, - ), - ).resolves.not.toThrow(); - }); - - it('should accept signed tokens', async () => { - const tokenManager = ServerTokenManager.fromConfig(configWithSecret, { - logger, - }); - await expect( - noopTokenManager.authenticate((await tokenManager.getToken()).token), - ).resolves.not.toThrow(); - }); - }); -}); diff --git a/packages/backend-common/src/deprecated/tokens/ServerTokenManager.ts b/packages/backend-common/src/deprecated/tokens/ServerTokenManager.ts deleted file mode 100644 index a9dee0f67a..0000000000 --- a/packages/backend-common/src/deprecated/tokens/ServerTokenManager.ts +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Config } from '@backstage/config'; -import { AuthenticationError } from '@backstage/errors'; -import { base64url, exportJWK, generateSecret, jwtVerify, SignJWT } from 'jose'; -import { DateTime, Duration } from 'luxon'; -import { LoggerService } from '@backstage/backend-plugin-api'; -import { TokenManager } from './types'; - -const TOKEN_ALG = 'HS256'; -const TOKEN_SUB = 'backstage-server'; -const TOKEN_EXPIRY_AFTER = Duration.fromObject({ hours: 1 }); -const TOKEN_REISSUE_AFTER = Duration.fromObject({ minutes: 10 }); - -/** - * A token manager that issues static fake tokens and never fails - * authentication. This can be useful for testing. - */ -class NoopTokenManager implements TokenManager { - public readonly isInsecureServerTokenManager: boolean = true; - - async getToken() { - return { token: '' }; - } - - async authenticate() {} -} - -/** - * A token manager that throws an error when trying to generate or authenticate tokens. - */ -class DisabledTokenManager implements TokenManager { - async getToken(): Promise<{ token: string }> { - throw new Error( - "Unable to generate legacy token, no legacy keys are configured in 'backend.auth.keys' or 'backend.auth.externalAccess'", - ); - } - - async authenticate() { - throw new AuthenticationError( - "Unable to authenticate legacy token, no legacy keys are configured in 'backend.auth.keys' or 'backend.auth.externalAccess'", - ); - } -} - -/** - * Options for {@link ServerTokenManager}. - * - * @public - * @deprecated Please {@link https://backstage.io/docs/tutorials/auth-service-migration | migrate} to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead. - */ -export interface ServerTokenManagerOptions { - /** - * The logger to use. - */ - logger: LoggerService; - - /** - * Whether to disable the token manager if no keys are configured. - */ - allowDisabledTokenManager?: boolean; -} - -/** - * Creates and validates tokens for use during service-to-service - * authentication. - * - * @public - * @deprecated Please {@link https://backstage.io/docs/tutorials/auth-service-migration | migrate} to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead. - */ -export class ServerTokenManager implements TokenManager { - private readonly options: ServerTokenManagerOptions; - private readonly verificationKeys: Uint8Array[]; - private signingKey: Uint8Array; - private privateKeyPromise: Promise | undefined; - private currentTokenPromise: Promise<{ token: string }> | undefined; - - /** - * Creates a token manager that issues static fake tokens and never fails - * authentication. This can be useful for testing. - */ - static noop(): TokenManager { - return new NoopTokenManager(); - } - - static fromConfig( - config: Config, - options: ServerTokenManagerOptions, - ): TokenManager { - const oldSecrets = config - .getOptionalConfigArray('backend.auth.keys') - ?.map(c => c.getString('secret')); - const newSecrets = config - .getOptionalConfigArray('backend.auth.externalAccess') - ?.filter(c => c.getString('type') === 'legacy') - .map(c => c.getString('options.secret')); - const secrets = [...(oldSecrets ?? []), ...(newSecrets ?? [])]; - - if (secrets.length) { - return new ServerTokenManager(secrets, options); - } - - // When using the new backend system with new auth services we instead rely - // on the new plugin auth and external access configurations. If no legacy - // keys are configured we disable the token manager completely, rather than - // requiring users to configure legacy keys. - if (options.allowDisabledTokenManager) { - return new DisabledTokenManager(); - } - - if (process.env.NODE_ENV !== 'development') { - throw new Error( - 'You must configure at least one key in backend.auth.keys for production.', - ); - } - - // For development, if a secret has not been configured, we auto generate a secret instead of throwing. - options.logger.warn( - 'Generated a secret for service-to-service authentication: DEVELOPMENT USE ONLY.', - ); - return new ServerTokenManager([], options); - } - - private constructor(secrets: string[], options: ServerTokenManagerOptions) { - if (!secrets.length && process.env.NODE_ENV !== 'development') { - throw new Error( - 'No secrets provided when constructing ServerTokenManager', - ); - } - this.options = options; - this.verificationKeys = secrets.map(s => base64url.decode(s)); - this.signingKey = this.verificationKeys[0]; - } - - // Called when no keys have been generated yet in the dev environment - private async generateKeys(): Promise { - if (process.env.NODE_ENV !== 'development') { - throw new Error( - 'Key generation is not supported outside of the dev environment', - ); - } - - if (this.privateKeyPromise) { - return this.privateKeyPromise; - } - - const promise = (async () => { - const secret = await generateSecret(TOKEN_ALG); - const jwk = await exportJWK(secret); - this.verificationKeys.push(base64url.decode(jwk.k ?? '')); - this.signingKey = this.verificationKeys[0]; - return; - })(); - - try { - this.privateKeyPromise = promise; - await promise; - } catch (error) { - // If we fail to generate a new key, we need to clear the state so that - // the next caller will try to generate another key. - this.options.logger.error(`Failed to generate new key, ${error}`); - delete this.privateKeyPromise; - } - - return promise; - } - - async getToken(): Promise<{ token: string }> { - if (!this.verificationKeys.length) { - await this.generateKeys(); - } - - if (this.currentTokenPromise) { - return this.currentTokenPromise; - } - - const result = Promise.resolve().then(async () => { - const jwt = await new SignJWT({}) - .setProtectedHeader({ alg: TOKEN_ALG }) - .setSubject(TOKEN_SUB) - .setExpirationTime( - DateTime.now().plus(TOKEN_EXPIRY_AFTER).toUnixInteger(), - ) - .sign(this.signingKey); - return { token: jwt }; - }); - - this.currentTokenPromise = result; - - result - .then(() => { - setTimeout(() => { - this.currentTokenPromise = undefined; - }, TOKEN_REISSUE_AFTER.toMillis()); - }) - .catch(() => { - this.currentTokenPromise = undefined; - }); - - return result; - } - - async authenticate(token: string): Promise { - let verifyError = undefined; - - for (const key of this.verificationKeys) { - try { - const { - protectedHeader: { alg }, - payload: { sub, exp }, - } = await jwtVerify(token, key); - - if (alg !== TOKEN_ALG) { - throw new AuthenticationError(`Illegal alg "${alg}"`); - } - - if (sub !== TOKEN_SUB) { - throw new AuthenticationError(`Illegal sub "${sub}"`); - } - - if (typeof exp !== 'number') { - throw new AuthenticationError( - 'Server-to-server token had no exp claim', - ); - } - return; - } catch (e) { - // Catch the verify exception and continue - verifyError = e; - } - } - - throw new AuthenticationError('Invalid server token', verifyError); - } -} diff --git a/packages/backend-common/src/deprecated/tokens/index.ts b/packages/backend-common/src/deprecated/tokens/index.ts deleted file mode 100644 index fe1b56df80..0000000000 --- a/packages/backend-common/src/deprecated/tokens/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { ServerTokenManager } from './ServerTokenManager'; -export type { ServerTokenManagerOptions } from './ServerTokenManager'; -export type { TokenManager } from './types'; diff --git a/packages/backend-common/src/deprecated/tokens/types.ts b/packages/backend-common/src/deprecated/tokens/types.ts deleted file mode 100644 index 41a2000868..0000000000 --- a/packages/backend-common/src/deprecated/tokens/types.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @public - * @deprecated Please {@link https://backstage.io/docs/tutorials/auth-service-migration | migrate} to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead. - */ -export interface TokenManager { - /** - * Fetches a valid token. - * - * @remarks - * - * Tokens are valid for roughly one hour; the actual deadline is set in the - * payload `exp` claim. Never hold on to tokens for reuse; always ask for a - * new one for each outgoing request. This ensures that you always get a - * valid, fresh one. - */ - getToken(): Promise<{ token: string }>; - - /** - * Validates a given token. - */ - authenticate(token: string): Promise; -} diff --git a/packages/backend-common/src/deprecated/util/ContainerRunner.ts b/packages/backend-common/src/deprecated/util/ContainerRunner.ts deleted file mode 100644 index 92081cea16..0000000000 --- a/packages/backend-common/src/deprecated/util/ContainerRunner.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Writable } from 'stream'; - -/** - * Allows defining access credentials for a registry - * Follows dockerode auth configuration: - * {@link https://github.com/apocas/dockerode?tab=readme-ov-file#pull-from-private-repos} - * - * @public - * @deprecated This interface is deprecated and will be removed in a future release. - */ -export interface PullOptions { - authconfig?: { - username?: string; - password?: string; - auth?: string; - email?: string; - serveraddress?: string; - [key: string]: unknown; - }; - [key: string]: unknown; -} - -/** - * Options passed to the {@link ContainerRunner.runContainer} method. - * - * @public - * @deprecated This type is deprecated and will be removed in a future release. - */ -export type RunContainerOptions = { - imageName: string; - command?: string | string[]; - args: string[]; - logStream?: Writable; - mountDirs?: Record; - workingDir?: string; - envVars?: Record; - pullImage?: boolean; - defaultUser?: boolean; - pullOptions?: PullOptions; -}; - -/** - * Handles the running of containers, on behalf of others. - * - * @public - * @deprecated This interface is deprecated and will be removed in a future release. - */ -export interface ContainerRunner { - /** - * Runs a container image to completion. - */ - runContainer(opts: RunContainerOptions): Promise; -} diff --git a/packages/backend-common/src/deprecated/util/DockerContainerRunner.test.ts b/packages/backend-common/src/deprecated/util/DockerContainerRunner.test.ts deleted file mode 100644 index f5d0e18480..0000000000 --- a/packages/backend-common/src/deprecated/util/DockerContainerRunner.test.ts +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import fs from 'fs-extra'; -import Docker from 'dockerode'; -import Stream, { PassThrough } from 'stream'; -import { ContainerRunner } from './ContainerRunner'; -import { DockerContainerRunner, UserOptions } from './DockerContainerRunner'; -import { createMockDirectory } from '@backstage/backend-test-utils'; - -const mockDocker = new Docker() as jest.Mocked; - -describe('DockerContainerRunner', () => { - let containerTaskApi: ContainerRunner; - - const inputDir = createMockDirectory(); - const outputDir = createMockDirectory(); - - beforeEach(() => { - inputDir.clear(); - outputDir.clear(); - - jest.spyOn(mockDocker, 'pull').mockImplementation((async ( - _image: string, - _something: any, - handler: (err: Error | undefined, stream: PassThrough) => void, - ) => { - const mockStream = new PassThrough(); - handler(undefined, mockStream); - mockStream.end(); - }) as any); - - jest - .spyOn(mockDocker, 'run') - .mockResolvedValue([{ Error: null, StatusCode: 0 }]); - - jest - .spyOn(mockDocker, 'ping') - .mockResolvedValue(Buffer.from('OK', 'utf-8')); - - containerTaskApi = new DockerContainerRunner({ dockerClient: mockDocker }); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - const imageName = 'dockerOrg/image'; - const args = ['bash', '-c', 'echo test']; - const mountDirs = { - [inputDir.path]: '/input', - [outputDir.path]: '/output', - }; - const workingDir = inputDir.path; - const envVars = { HOME: '/tmp', LOG_LEVEL: 'debug' }; - const envVarsArray = ['HOME=/tmp', 'LOG_LEVEL=debug']; - - it('should pull the docker container', async () => { - await containerTaskApi.runContainer({ - imageName, - args, - }); - - expect(mockDocker.pull).toHaveBeenCalledWith( - imageName, - {}, - expect.any(Function), - ); - - expect(mockDocker.run).toHaveBeenCalled(); - }); - - it('should pull the docker container with authentication', async () => { - await containerTaskApi.runContainer({ - imageName, - args, - pullOptions: { - authconfig: { - auth: 'aaaaaaaaa', - }, - }, - }); - - expect(mockDocker.pull).toHaveBeenCalledWith( - imageName, - { - authconfig: { - auth: 'aaaaaaaaa', - }, - }, - expect.any(Function), - ); - - expect(mockDocker.run).toHaveBeenCalled(); - }); - - it('should not pull the docker container when pullImage is false', async () => { - await containerTaskApi.runContainer({ - imageName, - args, - pullImage: false, - }); - - expect(mockDocker.pull).not.toHaveBeenCalled(); - expect(mockDocker.run).toHaveBeenCalled(); - }); - - it('should call the dockerClient run command with the correct arguments passed through', async () => { - await containerTaskApi.runContainer({ - imageName, - args, - mountDirs, - envVars, - workingDir, - }); - - expect(mockDocker.run).toHaveBeenCalledWith( - imageName, - args, - expect.any(Stream), - expect.objectContaining({ - Env: envVarsArray, - WorkingDir: workingDir, - HostConfig: { - AutoRemove: true, - Binds: expect.arrayContaining([ - `${await fs.realpath(inputDir.path)}:/input`, - `${await fs.realpath(outputDir.path)}:/output`, - ]), - }, - Volumes: { - '/input': {}, - '/output': {}, - }, - }), - ); - }); - - it('should ping docker to test availability', async () => { - await containerTaskApi.runContainer({ - imageName, - args, - }); - - expect(mockDocker.ping).toHaveBeenCalled(); - }); - - it('should pass through the user and group id from the host machine and set the home dir', async () => { - await containerTaskApi.runContainer({ - imageName, - args, - }); - - const userOptions: UserOptions = {}; - if (process.getuid && process.getgid) { - userOptions.User = `${process.getuid()}:${process.getgid()}`; - } - - expect(mockDocker.run).toHaveBeenCalledWith( - imageName, - args, - expect.any(Stream), - expect.objectContaining({ - ...userOptions, - }), - ); - }); - - it('throws a correct error if the command fails in docker', async () => { - mockDocker.run.mockResolvedValueOnce([ - { - Error: new Error('Something went wrong with docker'), - StatusCode: 0, - }, - ]); - - await expect( - containerTaskApi.runContainer({ - imageName, - args, - }), - ).rejects.toThrow(/Something went wrong with docker/); - }); - - describe('where docker is unavailable', () => { - const dockerError = 'a docker error'; - - beforeEach(() => { - jest.spyOn(mockDocker, 'ping').mockImplementationOnce(() => { - throw new Error(dockerError); - }); - }); - - it('should throw with a descriptive error message including the docker error message', async () => { - await expect( - containerTaskApi.runContainer({ - imageName, - args, - }), - ).rejects.toThrow(new RegExp(`.+: ${dockerError}`)); - }); - }); - - it('should pass through the log stream to the docker client', async () => { - const logStream = new PassThrough(); - await containerTaskApi.runContainer({ - imageName, - args, - logStream, - }); - - expect(mockDocker.run).toHaveBeenCalledWith( - imageName, - args, - logStream, - expect.objectContaining({ - HostConfig: { - AutoRemove: true, - Binds: [], - }, - Volumes: {}, - }), - ); - }); -}); diff --git a/packages/backend-common/src/deprecated/util/DockerContainerRunner.ts b/packages/backend-common/src/deprecated/util/DockerContainerRunner.ts deleted file mode 100644 index a9f5fb0432..0000000000 --- a/packages/backend-common/src/deprecated/util/DockerContainerRunner.ts +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import Docker from 'dockerode'; -import fs from 'fs-extra'; -import { ForwardedError } from '@backstage/errors'; -import { PassThrough } from 'stream'; -import { ContainerRunner, RunContainerOptions } from './ContainerRunner'; - -export type UserOptions = { - User?: string; -}; - -/** - * A {@link ContainerRunner} for Docker containers. - * - * @public - * @deprecated This class is deprecated and will be removed in a future release. - */ -export class DockerContainerRunner implements ContainerRunner { - private readonly dockerClient: Docker; - - constructor(options: { dockerClient: Docker }) { - this.dockerClient = options.dockerClient; - } - - async runContainer(options: RunContainerOptions) { - const { - imageName, - command, - args, - logStream = new PassThrough(), - mountDirs = {}, - workingDir, - envVars = {}, - pullImage = true, - defaultUser = false, - pullOptions = {}, - } = options; - - // Show a better error message when Docker is unavailable. - try { - await this.dockerClient.ping(); - } catch (e) { - throw new ForwardedError( - 'This operation requires Docker. Docker does not appear to be available. Docker.ping() failed with', - e, - ); - } - - if (pullImage) { - await new Promise((resolve, reject) => { - this.dockerClient.pull(imageName, pullOptions, (err, stream) => { - if (err) { - reject(err); - } else if (!stream) { - reject( - new Error( - 'Unexpeected error: no stream returned from Docker while pulling image', - ), - ); - } else { - stream.pipe(logStream, { end: false }); - stream.on('end', () => resolve()); - stream.on('error', (error: Error) => reject(error)); - } - }); - }); - } - - const userOptions: UserOptions = {}; - if (!defaultUser && process.getuid && process.getgid) { - // Files that are created inside the Docker container will be owned by - // root on the host system on non Mac systems, because of reasons. Mainly the fact that - // volume sharing is done using NFS on Mac and actual mounts in Linux world. - // So we set the user in the container as the same user and group id as the host. - // On Windows we don't have process.getuid nor process.getgid - userOptions.User = `${process.getuid()}:${process.getgid()}`; - } - - // Initialize volumes to mount based on mountDirs map - const Volumes: { [T: string]: object } = {}; - for (const containerDir of Object.values(mountDirs)) { - Volumes[containerDir] = {}; - } - - // Create bind volumes - const Binds: string[] = []; - for (const [hostDir, containerDir] of Object.entries(mountDirs)) { - // Need to use realpath here as Docker mounting does not like - // symlinks for binding volumes - const realHostDir = await fs.realpath(hostDir); - Binds.push(`${realHostDir}:${containerDir}`); - } - - // Create docker environment variables array - const Env = new Array(); - for (const [key, value] of Object.entries(envVars)) { - Env.push(`${key}=${value}`); - } - - const [{ Error: error, StatusCode: statusCode }] = - await this.dockerClient.run(imageName, args, logStream, { - Volumes, - HostConfig: { - AutoRemove: true, - Binds, - }, - ...(workingDir ? { WorkingDir: workingDir } : {}), - Entrypoint: command, - Env, - ...userOptions, - } as Docker.ContainerCreateOptions); - - if (error) { - throw new Error( - `Docker failed to run with the following error message: ${error}`, - ); - } - - if (statusCode !== 0) { - throw new Error( - `Docker container returned a non-zero exit code (${statusCode})`, - ); - } - } -} diff --git a/packages/backend-common/src/deprecated/util/KubernetesContainerRunner.test.ts b/packages/backend-common/src/deprecated/util/KubernetesContainerRunner.test.ts deleted file mode 100644 index 706b78c4ae..0000000000 --- a/packages/backend-common/src/deprecated/util/KubernetesContainerRunner.test.ts +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - CoreV1Api, - KubeConfig, - RbacAuthorizationV1Api, -} from '@kubernetes/client-node'; -import { - KubernetesContainerRunner, - KubernetesContainerRunnerOptions, -} from './KubernetesContainerRunner'; -import { RunContainerOptions } from './ContainerRunner'; -import { PassThrough } from 'stream'; - -// This ensures E2E tests that require a Kubernetes cluster are only run -// where KUBERNETES_TESTS environment variable is true -const describeIfKubernetes = Boolean(process.env.KUBERNETES_TESTS) - ? describe - : describe.skip; - -jest.setTimeout(10 * 1000); - -describeIfKubernetes('KubernetesContainerRunner', () => { - const kubeConfig = new KubeConfig(); - kubeConfig.loadFromDefault(); - const name = 'kube-runner'; - - it('should throw error when no namespace is configured', () => { - const testConfig = new KubeConfig(); - testConfig.loadFromDefault(); - testConfig.addContext({ - name: 'test', - cluster: kubeConfig.getCurrentCluster()!.name, - user: kubeConfig.getCurrentUser()!.name, - }); - testConfig.setCurrentContext('test'); - const test = () => - new KubernetesContainerRunner({ - kubeConfig: testConfig, - name, - }); - expect(test).toThrow( - /Cannot read current namespace from Kubernetes cluster/, - ); - }); - - it('should throw error when mountBase is provided and podTemplate is invalid', () => { - const error = /A Pod template containing the volume .+ is required/; - const options: KubernetesContainerRunnerOptions = { - kubeConfig, - name, - namespace: 'default', - mountBase: { - basePath: '/workdir', - volumeName: 'workdir', - }, - }; - const test = () => { - return new KubernetesContainerRunner(options); - }; - expect(test).toThrow(error); - options.podTemplate = {}; - expect(test).toThrow(error); - options.podTemplate.spec = { containers: [] }; - expect(test).toThrow(error); - options.podTemplate.spec.volumes = []; - expect(test).toThrow(error); - }); - - it('should not run the container when the mounts are not subdirectories of the basePath', async () => { - const options: KubernetesContainerRunnerOptions = { - kubeConfig, - name, - namespace: 'default', - mountBase: { - basePath: '/workdir', - volumeName: 'workdir', - }, - podTemplate: { - spec: { - containers: [], - volumes: [ - { - name: 'workdir', - }, - ], - }, - }, - }; - const containerRunner = new KubernetesContainerRunner(options); - const logStream = new PassThrough(); - const runOptions: RunContainerOptions = { - imageName: 'golang:1.17', - args: ['echo', 'hello world'], - logStream, - mountDirs: { - '/notWorkdir/app': '/app', - }, - }; - await expect(containerRunner.runContainer(runOptions)).rejects.toThrow( - `Mounted '/notWorkdir/app' dir should be subdirectories of '${ - options!.mountBase!.basePath - }'`, - ); - }); - - it('should succeed when the container command returns a 0 exit code', async () => { - const options: KubernetesContainerRunnerOptions = { - kubeConfig, - name, - namespace: 'default', - }; - const containerRunner = new KubernetesContainerRunner(options); - const logStream = new PassThrough(); - const chunks: any[] = []; - logStream.on('data', chunk => chunks.push(Buffer.from(chunk))); - const runOptions: RunContainerOptions = { - imageName: 'alpine', - args: ['echo', 'hello world'], - logStream, - }; - await containerRunner.runContainer(runOptions); - const result = Buffer.concat(chunks).toString('utf8'); - expect(result).toBe('hello world\n'); - }); - - it('should fail when container run time exceeds the timeout', async () => { - const options: KubernetesContainerRunnerOptions = { - kubeConfig, - name, - namespace: 'default', - timeoutMs: 5000, - }; - const containerRunner = new KubernetesContainerRunner(options); - const runOptions: RunContainerOptions = { - imageName: 'alpine', - args: ['sleep', '10'], - }; - await expect(containerRunner.runContainer(runOptions)).rejects.toThrow( - `Failed to complete in ${options.timeoutMs} ms`, - ); - }); - - it('should fail when container command returns a non 0 exit code', async () => { - const options: KubernetesContainerRunnerOptions = { - kubeConfig, - name, - namespace: 'default', - }; - const containerRunner = new KubernetesContainerRunner(options); - const runOptions: RunContainerOptions = { - imageName: 'alpine', - args: ['fake'], - }; - await expect(containerRunner.runContainer(runOptions)).rejects.toThrow( - `Container execution failed`, - ); - }); - - it('should fail when job creation fails', async () => { - const options: KubernetesContainerRunnerOptions = { - kubeConfig, - name, - namespace: 'fake', - }; - const containerRunner = new KubernetesContainerRunner(options); - const runOptions: RunContainerOptions = { - imageName: 'golang:1.17', - args: ['echo', 'hello world'], - }; - await expect(containerRunner.runContainer(runOptions)).rejects.toThrow( - 'Kubernetes Job creation failed with the following error message: namespaces "fake" not found', - ); - }); - - it('should not close the original log stream', async () => { - const options: KubernetesContainerRunnerOptions = { - kubeConfig, - name, - namespace: 'default', - }; - const containerRunner = new KubernetesContainerRunner(options); - const logStream = new PassThrough(); - const runOptions: RunContainerOptions = { - imageName: 'alpine', - args: ['echo', 'hello world'], - logStream, - }; - - await containerRunner.runContainer(runOptions); - - expect(logStream.writableEnded).toBe(false); - expect(logStream.destroyed).toBe(false); - }); - - describe('with namespace test', () => { - let api: CoreV1Api; - let authApi: RbacAuthorizationV1Api; - - beforeAll(async () => { - api = kubeConfig.makeApiClient(CoreV1Api); - authApi = kubeConfig.makeApiClient(RbacAuthorizationV1Api); - await api.createNamespace({ - metadata: { - name: 'test', - }, - }); - }); - afterAll(async () => { - await api.deleteNamespace('test'); - }); - - it('should fail when watch fails', async () => { - const testConfig = await givenAServiceAccountThatCannotWatchPods( - api, - authApi, - kubeConfig, - ); - const options: KubernetesContainerRunnerOptions = { - kubeConfig: testConfig, - name, - namespace: 'test', - }; - const containerRunner = new KubernetesContainerRunner(options); - const runOptions: RunContainerOptions = { - imageName: 'golang:1.17', - args: ['echo', 'hello world'], - }; - await expect(containerRunner.runContainer(runOptions)).rejects.toThrow( - 'Kubernetes watch request failed with the following error message: Error: Forbidden', - ); - }); - }); -}); - -async function givenAServiceAccountThatCannotWatchPods( - api: CoreV1Api, - authApi: RbacAuthorizationV1Api, - kubeConfig: KubeConfig, -) { - await Promise.all([ - api.createNamespacedServiceAccount('test', { - metadata: { - name: 'test', - }, - }), - authApi.createNamespacedRole('test', { - metadata: { - name: 'test', - }, - rules: [ - { - apiGroups: ['batch'], - verbs: ['create'], - resources: ['jobs'], - }, - ], - }), - authApi.createNamespacedRoleBinding('test', { - metadata: { - name: 'test', - }, - subjects: [ - { - kind: 'ServiceAccount', - name: 'test', - }, - ], - roleRef: { - apiGroup: 'rbac.authorization.k8s.io', - kind: 'Role', - name: 'test', - }, - }), - ]); - const token = ( - await api.createNamespacedServiceAccountToken('test', 'test', { - spec: { - audiences: [], - }, - }) - ).body.status?.token; - const testConfig = new KubeConfig(); - testConfig.loadFromDefault(); - testConfig.addUser({ - name: 'test', - token, - }); - testConfig.addContext({ - name: 'test', - cluster: kubeConfig.getCurrentCluster()!.name, - user: 'test', - }); - testConfig.setCurrentContext('test'); - return testConfig; -} diff --git a/packages/backend-common/src/deprecated/util/KubernetesContainerRunner.ts b/packages/backend-common/src/deprecated/util/KubernetesContainerRunner.ts deleted file mode 100644 index 0402f70079..0000000000 --- a/packages/backend-common/src/deprecated/util/KubernetesContainerRunner.ts +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { PassThrough, Writable } from 'stream'; -import { ContainerRunner, RunContainerOptions } from './ContainerRunner'; -import { - KubeConfig, - BatchV1Api, - V1Job, - V1EnvVar, - Log, - HttpError, - V1Status, - V1VolumeMount, - V1PodTemplateSpec, - V1Pod, - Watch, -} from '@kubernetes/client-node'; -import { v4 as uuid } from 'uuid'; - -/** - * An existing Kubernetes volume that will be used as base for mounts. - * - * Every mount must start with the 'basePath'. - * - * @public - * @deprecated This type is deprecated and will be removed in a future release. - */ -export type KubernetesContainerRunnerMountBase = { - volumeName: string; - basePath: string; -}; - -/** - * Options to create a {@link KubernetesContainerRunner} - * - * Kubernetes Jobs will be created on the provided 'namespace' - * and their names will be prefixed with the provided 'name'. - * - * 'podTemplate' defines a Pod template for the Jobs. It has to include - * a volume definition named as the {@link KubernetesContainerRunnerMountBase} 'volumeName'. - * - * @public - * @deprecated This type is deprecated and will be removed in a future release. - */ -export type KubernetesContainerRunnerOptions = { - kubeConfig: KubeConfig; - name: string; - namespace?: string; - mountBase?: KubernetesContainerRunnerMountBase; - podTemplate?: V1PodTemplateSpec; - timeoutMs?: number; -}; - -/** - * A {@link ContainerRunner} for Kubernetes. - * - * Runs containers leveraging Jobs on a Kubernetes cluster - * - * @public - * @deprecated This class is deprecated and will be removed in a future release. - */ -export class KubernetesContainerRunner implements ContainerRunner { - private readonly kubeConfig: KubeConfig; - private readonly batchV1Api: BatchV1Api; - private readonly log: Log; - private readonly name: string; - private readonly namespace: string; - private readonly mountBase?: KubernetesContainerRunnerMountBase; - private readonly podTemplate?: V1PodTemplateSpec; - private readonly timeoutMs: number; - private readonly containerName = 'executor'; - - private getNamespace(kubeConfig: KubeConfig, namespace?: string): string { - let _namespace = namespace; - if (!_namespace) { - _namespace = kubeConfig.getContextObject( - kubeConfig.currentContext, - )?.namespace; - } - if (!_namespace) { - throw new Error('Cannot read current namespace from Kubernetes cluster'); - } - return _namespace; - } - - private validateMountBase( - mountBase: KubernetesContainerRunnerMountBase, - podTemplate?: V1PodTemplateSpec, - ): KubernetesContainerRunnerMountBase { - if ( - !podTemplate?.spec?.volumes?.filter(v => v.name === mountBase.volumeName) - .length - ) { - throw new Error( - `A Pod template containing the volume ${mountBase.volumeName} is required`, - ); - } - if (!mountBase.basePath.endsWith('/')) { - mountBase.basePath += '/'; - } - return mountBase; - } - - constructor(options: KubernetesContainerRunnerOptions) { - const { kubeConfig, name, namespace, mountBase, podTemplate, timeoutMs } = - options; - this.kubeConfig = kubeConfig; - this.batchV1Api = kubeConfig.makeApiClient(BatchV1Api); - this.log = new Log(kubeConfig); - this.name = name; - this.namespace = this.getNamespace(kubeConfig, namespace); - if (mountBase) { - this.mountBase = this.validateMountBase(mountBase, podTemplate); - } - this.podTemplate = podTemplate; - this.timeoutMs = timeoutMs || 120 * 1000; - } - - async runContainer(options: RunContainerOptions) { - const { - imageName, - command, - args, - logStream, - mountDirs = {}, - workingDir, - envVars = {}, - } = options; - - const containerLogStream = new PassThrough(); - if (logStream) { - containerLogStream.pipe(logStream, { end: false }); - } - - const commandArr = typeof command === 'string' ? [command] : command; - - const volumeMounts: V1VolumeMount[] = []; - for (const [hostDir, containerDir] of Object.entries(mountDirs)) { - if (!this.mountBase) { - throw new Error( - 'A volumeName and a basePath must be configured to bind mount directories', - ); - } - if (!hostDir.startsWith(this.mountBase.basePath)) { - throw new Error( - `Mounted '${hostDir}' dir should be subdirectories of '${this.mountBase.basePath}'`, - ); - } - volumeMounts.push({ - name: this.mountBase.volumeName, - mountPath: containerDir, - subPath: hostDir.slice(this.mountBase.basePath.length), - }); - } - - const env = []; - for (const [key, value] of Object.entries(envVars)) { - env.push({ - name: key, - value: value, - } as V1EnvVar); - } - - const taskId = uuid(); - - // TODO find a way to merge recursively - const mergedPodTemplate: V1PodTemplateSpec = { - metadata: { - ...{ - labels: { - task: taskId, - }, - }, - ...this.podTemplate?.metadata, - }, - spec: { - ...{ - containers: [ - { - name: this.containerName, - image: imageName, - command: commandArr, - args: args, - env: env, - workingDir: workingDir, - volumeMounts: volumeMounts, - }, - ], - restartPolicy: 'Never', - }, - ...this.podTemplate?.spec, - }, - }; - - const jobSpec: V1Job = { - metadata: { - generateName: `${this.name}-`, - }, - spec: { - backoffLimit: 0, - ttlSecondsAfterFinished: 60, - template: mergedPodTemplate, - }, - }; - - await this.runJob(jobSpec, taskId, containerLogStream); - } - - private handleError(err: any, errorCallback: (reason: any) => void) { - if (err.code !== 'ECONNRESET' && err.message !== 'aborted') { - errorCallback( - handleKubernetesError( - 'Kubernetes watch request failed with the following error message:', - err, - ), - ); - } - } - - private watchPod( - taskId: string, - callback: (pod: V1Pod) => void, - errorCallback: (reason: any) => void, - ): Promise<{ abort: () => void }> { - const watch = new Watch(this.kubeConfig); - const labelSelector = `task=${taskId}`; - return watch.watch( - `/api/v1/namespaces/${this.namespace}/pods`, - { - labelSelector, - }, - (_, pod) => { - callback(pod); - }, - err => { - if (err) { - this.handleError(err, errorCallback); - } - }, - ); - } - - private tailLogs( - taskId: string, - logStream: Writable, - ): { promise: Promise; close: () => Promise } { - let log: Promise<{ abort: () => void }>; - let req: Promise<{ abort: () => void }>; - const watchPromise = new Promise((_, reject) => { - req = this.watchPod( - taskId, - pod => { - if ( - log === undefined && - (pod.status?.phase === 'Running' || - pod.status?.phase === 'Succeeded' || - pod.status?.phase === 'Failed') - ) { - log = this.log.log( - this.namespace, - pod.metadata?.name!, - this.containerName, - logStream, - { follow: true }, - ); - } - }, - reject, - ); - }); - const logPromise = new Promise((resolve, _) => { - if (!logStream.writableFinished) { - logStream.on('finish', () => { - resolve(); - }); - } else { - resolve(); - } - }); - const close = async () => { - if (req) { - (await req).abort(); - } - if (log) { - (await log).abort(); - } - }; - return { promise: Promise.race([watchPromise, logPromise]), close }; - } - - private waitPod(taskId: string): { - promise: Promise; - close: () => Promise; - } { - let req: Promise<{ abort: () => void }>; - const promise = new Promise(async (resolve, reject) => { - req = this.watchPod( - taskId, - pod => { - if (pod.status?.phase === 'Succeeded') { - resolve(); - } - if (pod.status?.phase === 'Failed') { - reject(new Error('Container execution failed')); - } - }, - reject, - ); - }); - const close = async () => { - if (req) { - (await req).abort(); - } - }; - return { promise, close }; - } - - private async createJob(jobSpec: V1Job): Promise { - return this.batchV1Api - .createNamespacedJob(this.namespace, jobSpec) - .catch(err => { - throw handleKubernetesError( - 'Kubernetes Job creation failed with the following error message:', - err, - ); - }); - } - - private async runJob( - jobSpec: V1Job, - taskId: string, - logStream: Writable, - ): Promise { - let timeout: NodeJS.Timeout; - const timeoutPromise = new Promise((_, reject) => { - timeout = setTimeout( - reject, - this.timeoutMs, - new Error(`Failed to complete in ${this.timeoutMs} ms`), - ); - }); - - const { promise: waitPromise, close: waitClose } = this.waitPod(taskId); - const { promise: tailPromise, close: tailClose } = this.tailLogs( - taskId, - logStream, - ); - - const taskPromise = Promise.all([ - waitPromise, - tailPromise, - this.createJob(jobSpec), - ]).finally(() => { - clearTimeout(timeout); - }); - - return Promise.race([timeoutPromise, taskPromise]) - .finally(() => { - return waitClose(); - }) - .finally(() => { - return tailClose(); - }); - } -} - -function handleKubernetesError(message: string, err: Error): Error { - if (err instanceof HttpError) { - return new Error(`${message} ${(err.body as V1Status).message}`); - } - return new Error(`${message} ${err}`); -} diff --git a/packages/backend-common/src/deprecated/util/index.ts b/packages/backend-common/src/deprecated/util/index.ts deleted file mode 100644 index 39bade08be..0000000000 --- a/packages/backend-common/src/deprecated/util/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export type { - ContainerRunner, - RunContainerOptions, - PullOptions, -} from './ContainerRunner'; -export { DockerContainerRunner } from './DockerContainerRunner'; -export type { - KubernetesContainerRunnerOptions, - KubernetesContainerRunnerMountBase, -} from './KubernetesContainerRunner'; -export { KubernetesContainerRunner } from './KubernetesContainerRunner'; diff --git a/packages/backend-common/src/index.ts b/packages/backend-common/src/index.ts deleted file mode 100644 index e08bef3048..0000000000 --- a/packages/backend-common/src/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Common functionality library for Backstage backends - * - * @remarks - * This package is deprecated and will be removed in a near future, so please follow the deprecated instructions for the exports you still use. - * - * @packageDocumentation - */ - -export * from './deprecated'; -export * from './compat'; diff --git a/packages/backend-common/src/setupTests.ts b/packages/backend-common/src/setupTests.ts deleted file mode 100644 index d3232290a7..0000000000 --- a/packages/backend-common/src/setupTests.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export {}; diff --git a/packages/backend-common/src/testUtils.ts b/packages/backend-common/src/testUtils.ts deleted file mode 100644 index 397d97f20e..0000000000 --- a/packages/backend-common/src/testUtils.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - overridePackagePathResolution as _overridePackagePathResolution, - OverridePackagePathResolutionOptions as _OverridePackagePathResolutionOptions, - PackagePathResolutionOverride as _PackagePathResolutionOverride, -} from '@backstage/backend-plugin-api/testUtils'; - -/** - * @public - * @deprecated This function is deprecated and will be removed in future release, see https://github.com/backstage/backstage/issues/24493. - * Please use the `overridePackagePathResolution` function from the `@backstage/backend-plugin-api/testUtils` package instead. - */ -export const overridePackagePathResolution = _overridePackagePathResolution; - -/** - * @public - * @deprecated This type is deprecated and will be removed in a future release, see https://github.com/backstage/backstage/issues/24493. - * Please use the `OverridePackagePathResolutionOptions` type from the `@backstage/backend-plugin-api/testUtils` package instead. - */ -export type OverridePackagePathResolutionOptions = - _OverridePackagePathResolutionOptions; - -/** - * @public - * @deprecated This type is deprecated and will be removed in a future release, see https://github.com/backstage/backstage/issues/24493. - * Please use the `PackagePathResolutionOverride` type from the `@backstage/backend-plugin-api/testUtils` package instead. - */ -export type PackagePathResolutionOverride = _PackagePathResolutionOverride; diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index d80cc76d8e..f096bd573e 100644 --- a/packages/backend-defaults/package.json +++ b/packages/backend-defaults/package.json @@ -120,7 +120,7 @@ "@aws-sdk/credential-providers": "^3.350.0", "@aws-sdk/types": "^3.347.0", "@backstage/backend-app-api": "workspace:^", - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-dev-utils": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/cli-common": "workspace:^", @@ -190,11 +190,15 @@ "@backstage/backend-plugin-api": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@types/archiver": "^6.0.0", + "@types/base64-stream": "^1.0.2", + "@types/concat-stream": "^2.0.0", "@types/http-errors": "^2.0.0", "@types/morgan": "^1.9.0", "@types/node-forge": "^1.3.0", "@types/pg-format": "^1.0.5", "@types/stoppable": "^1.1.0", + "@types/yauzl": "^2.10.0", "aws-sdk-client-mock": "^4.0.0", "http-errors": "^2.0.0", "msw": "^1.0.0", diff --git a/packages/backend-dynamic-feature-service/package.json b/packages/backend-dynamic-feature-service/package.json index c3764e1dff..5a1cfc0e7d 100644 --- a/packages/backend-dynamic-feature-service/package.json +++ b/packages/backend-dynamic-feature-service/package.json @@ -46,7 +46,7 @@ }, "dependencies": { "@backstage/backend-app-api": "workspace:^", - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-defaults": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/cli-common": "workspace:^", diff --git a/packages/backend-legacy/package.json b/packages/backend-legacy/package.json index c15254de48..b9fa12ef02 100644 --- a/packages/backend-legacy/package.json +++ b/packages/backend-legacy/package.json @@ -28,7 +28,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-defaults": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", diff --git a/packages/cli-node/src/monorepo/Lockfile.test.ts b/packages/cli-node/src/monorepo/Lockfile.test.ts index 41beeb4408..4bc7a6d96e 100644 --- a/packages/cli-node/src/monorepo/Lockfile.test.ts +++ b/packages/cli-node/src/monorepo/Lockfile.test.ts @@ -277,7 +277,7 @@ d@^1: version: 0.0.0-use.local resolution: "@backstage/backend-app-api@workspace:packages/backend-app-api" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": "^0.25.0" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-tasks": "workspace:^" "@backstage/cli": "workspace:^" @@ -330,7 +330,7 @@ d@^1: version: 0.0.0-use.local resolution: "@backstage/backend-app-api@workspace:packages/backend-app-api" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": "^0.25.0" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-tasks": "workspace:^" "@backstage/cli": "workspace:^" diff --git a/packages/cli/package.json b/packages/cli/package.json index 6090bf7a7b..8a7ba7843a 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -157,7 +157,7 @@ "zod": "^3.22.4" }, "devDependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/config": "workspace:^", diff --git a/packages/cli/src/lib/version.ts b/packages/cli/src/lib/version.ts index fb777f7502..b2b3ae23cf 100644 --- a/packages/cli/src/lib/version.ts +++ b/packages/cli/src/lib/version.ts @@ -32,7 +32,6 @@ This does not create an actual dependency on these packages and does not bring i Rollup will extract the value of the version field in each package at build time without leaving any imports in place. */ -import { version as backendCommon } from '../../../../packages/backend-common/package.json'; import { version as backendPluginApi } from '../../../../packages/backend-plugin-api/package.json'; import { version as backendTestUtils } from '../../../../packages/backend-test-utils/package.json'; import { version as cli } from '../../../../packages/cli/package.json'; @@ -49,7 +48,6 @@ import { version as theme } from '../../../../packages/theme/package.json'; import { version as backendDefaults } from '../../../../packages/backend-defaults/package.json'; export const packageVersions: Record = { - '@backstage/backend-common': backendCommon, '@backstage/backend-defaults': backendDefaults, '@backstage/backend-plugin-api': backendPluginApi, '@backstage/backend-test-utils': backendTestUtils, diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index 0f1818b176..29803243cd 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -57,7 +57,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/config-loader": "workspace:^", diff --git a/plugins/auth-backend-module-aws-alb-provider/package.json b/plugins/auth-backend-module-aws-alb-provider/package.json index 58f9c135f3..b65f1de631 100644 --- a/plugins/auth-backend-module-aws-alb-provider/package.json +++ b/plugins/auth-backend-module-aws-alb-provider/package.json @@ -37,7 +37,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/plugin-auth-backend": "workspace:^", diff --git a/plugins/auth-backend-module-guest-provider/package.json b/plugins/auth-backend-module-guest-provider/package.json index 8b39a9d2b2..58134742f8 100644 --- a/plugins/auth-backend-module-guest-provider/package.json +++ b/plugins/auth-backend-module-guest-provider/package.json @@ -34,7 +34,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/errors": "workspace:^", diff --git a/plugins/auth-backend-module-oidc-provider/package.json b/plugins/auth-backend-module-oidc-provider/package.json index f3b0bde460..d4c6fc3530 100644 --- a/plugins/auth-backend-module-oidc-provider/package.json +++ b/plugins/auth-backend-module-oidc-provider/package.json @@ -34,7 +34,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/plugin-auth-backend": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 392afc5ab7..d725eb4816 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -43,7 +43,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", diff --git a/plugins/auth-backend/src/providers/cloudflare-access/provider.ts b/plugins/auth-backend/src/providers/cloudflare-access/provider.ts index 78036ee0cd..cbc9a99517 100644 --- a/plugins/auth-backend/src/providers/cloudflare-access/provider.ts +++ b/plugins/auth-backend/src/providers/cloudflare-access/provider.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import { CacheClient } from '@backstage/backend-common'; import { cloudflareAccessSignInResolvers, createCloudflareAccessAuthenticator, @@ -25,6 +24,7 @@ import { } from '@backstage/plugin-auth-node'; import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; import { AuthHandler } from '../types'; +import { CacheService } from '@backstage/backend-plugin-api'; /** * CloudflareAccessClaims @@ -145,10 +145,10 @@ export const cfAccess = createAuthProviderIntegration({ }; /** - * CacheClient object that was configured for the Backstage backend, + * Cache service object that was configured for the Backstage backend, * should be provided via the backend auth plugin. */ - cache?: CacheClient; + cache?: CacheService; }) { return createProxyAuthProviderFactory({ authenticator: createCloudflareAccessAuthenticator({ diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index ef2288ddef..3149536bf6 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -37,7 +37,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 43e5261ebf..76daa74ba9 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -51,7 +51,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", @@ -64,7 +64,6 @@ "uuid": "^9.0.0" }, "devDependencies": { - "@backstage/backend-common": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@backstage/plugin-events-backend-test-utils": "workspace:^", diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index 3eaca4a573..cdd91ee0ef 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -51,7 +51,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", diff --git a/plugins/catalog-backend-module-gitlab-org/package.json b/plugins/catalog-backend-module-gitlab-org/package.json index b905148747..fcf680e2a2 100644 --- a/plugins/catalog-backend-module-gitlab-org/package.json +++ b/plugins/catalog-backend-module-gitlab-org/package.json @@ -33,7 +33,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/plugin-catalog-backend-module-gitlab": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index cf66a1db1a..e10ec5479e 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -51,7 +51,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index fa9bdec0ee..79079ef637 100644 --- a/plugins/catalog-backend-module-openapi/package.json +++ b/plugins/catalog-backend-module-openapi/package.json @@ -38,7 +38,7 @@ }, "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.0.6", - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", diff --git a/plugins/catalog-backend-module-unprocessed/package.json b/plugins/catalog-backend-module-unprocessed/package.json index b88bce0335..4ebe703500 100644 --- a/plugins/catalog-backend-module-unprocessed/package.json +++ b/plugins/catalog-backend-module-unprocessed/package.json @@ -33,7 +33,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/errors": "workspace:^", diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index ae44071c97..c46cd1c2cc 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -61,7 +61,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-openapi-utils": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", diff --git a/plugins/devtools-backend/package.json b/plugins/devtools-backend/package.json index 6ac30a4ed1..4b7044d2d8 100644 --- a/plugins/devtools-backend/package.json +++ b/plugins/devtools-backend/package.json @@ -38,7 +38,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/cli-common": "workspace:^", "@backstage/config": "workspace:^", diff --git a/plugins/events-backend-module-aws-sqs/package.json b/plugins/events-backend-module-aws-sqs/package.json index ff307ceef4..8c90791520 100644 --- a/plugins/events-backend-module-aws-sqs/package.json +++ b/plugins/events-backend-module-aws-sqs/package.json @@ -48,7 +48,6 @@ }, "dependencies": { "@aws-sdk/client-sqs": "^3.350.0", - "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/plugin-events-node": "workspace:^", @@ -57,7 +56,6 @@ }, "devDependencies": { "@aws-sdk/types": "^3.347.0", - "@backstage/backend-common": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@backstage/plugin-events-backend-test-utils": "workspace:^", diff --git a/plugins/events-backend/package.json b/plugins/events-backend/package.json index 44ae0d45e2..34f64d05e0 100644 --- a/plugins/events-backend/package.json +++ b/plugins/events-backend/package.json @@ -51,7 +51,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/plugin-events-node": "workspace:^", @@ -61,7 +61,6 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-common": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@backstage/plugin-events-backend-test-utils": "workspace:^", diff --git a/plugins/events-node/package.json b/plugins/events-node/package.json index f0771143b1..6795c13441 100644 --- a/plugins/events-node/package.json +++ b/plugins/events-node/package.json @@ -54,7 +54,7 @@ "@backstage/backend-plugin-api": "workspace:^" }, "devDependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^" } diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index a0607e1345..189bb4b192 100644 --- a/plugins/example-todo-list-backend/package.json +++ b/plugins/example-todo-list-backend/package.json @@ -38,7 +38,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index ba0d8cb39f..68abc77498 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -62,7 +62,7 @@ "@aws-sdk/credential-providers": "^3.350.0", "@aws-sdk/signature-v4": "^3.347.0", "@azure/identity": "^4.0.0", - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", diff --git a/plugins/kubernetes-node/package.json b/plugins/kubernetes-node/package.json index e6afa4e5a3..01413cf777 100644 --- a/plugins/kubernetes-node/package.json +++ b/plugins/kubernetes-node/package.json @@ -48,7 +48,7 @@ }, "devDependencies": { "@backstage/backend-app-api": "workspace:^", - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-defaults": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", diff --git a/plugins/notifications-backend-module-email/package.json b/plugins/notifications-backend-module-email/package.json index 7eed82e410..6e80dc5e0b 100644 --- a/plugins/notifications-backend-module-email/package.json +++ b/plugins/notifications-backend-module-email/package.json @@ -36,7 +36,7 @@ "dependencies": { "@aws-sdk/client-ses": "^3.550.0", "@aws-sdk/types": "^3.347.0", - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", diff --git a/plugins/notifications-backend/package.json b/plugins/notifications-backend/package.json index 1413404cff..434cc01ae6 100644 --- a/plugins/notifications-backend/package.json +++ b/plugins/notifications-backend/package.json @@ -38,7 +38,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", diff --git a/plugins/notifications-node/package.json b/plugins/notifications-node/package.json index 97767314b0..bc762515bf 100644 --- a/plugins/notifications-node/package.json +++ b/plugins/notifications-node/package.json @@ -37,7 +37,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index 764a71c130..2fb7fa06e9 100644 --- a/plugins/permission-backend/package.json +++ b/plugins/permission-backend/package.json @@ -51,7 +51,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index 22a2df9aeb..74a1ca062e 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -56,7 +56,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 0d141a1aba..7dc5701ba6 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -53,7 +53,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/types": "workspace:^", diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/package.json b/plugins/scaffolder-backend-module-confluence-to-markdown/package.json index 1ccb26b59c..4c537ab275 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/package.json +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/package.json @@ -45,7 +45,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index 10f0d34d9d..848f9b29dc 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/package.json +++ b/plugins/scaffolder-backend-module-cookiecutter/package.json @@ -43,7 +43,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-defaults": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", diff --git a/plugins/scaffolder-backend-module-github/package.json b/plugins/scaffolder-backend-module-github/package.json index 117cd35e5b..52eb430f2d 100644 --- a/plugins/scaffolder-backend-module-github/package.json +++ b/plugins/scaffolder-backend-module-github/package.json @@ -42,7 +42,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", diff --git a/plugins/scaffolder-backend-module-gitlab/package.json b/plugins/scaffolder-backend-module-gitlab/package.json index 7014bdeb3a..e5f1364675 100644 --- a/plugins/scaffolder-backend-module-gitlab/package.json +++ b/plugins/scaffolder-backend-module-gitlab/package.json @@ -45,7 +45,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", diff --git a/plugins/scaffolder-backend-module-notifications/package.json b/plugins/scaffolder-backend-module-notifications/package.json index 6e35078dcc..3adcff6701 100644 --- a/plugins/scaffolder-backend-module-notifications/package.json +++ b/plugins/scaffolder-backend-module-notifications/package.json @@ -33,7 +33,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/plugin-notifications-common": "workspace:^", "@backstage/plugin-notifications-node": "workspace:^", diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index 6c718e64b0..65879c4407 100644 --- a/plugins/scaffolder-backend-module-rails/package.json +++ b/plugins/scaffolder-backend-module-rails/package.json @@ -43,7 +43,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index dcac377d54..254a472243 100644 --- a/plugins/scaffolder-backend-module-yeoman/package.json +++ b/plugins/scaffolder-backend-module-yeoman/package.json @@ -51,7 +51,7 @@ "yeoman-environment": "^3.9.1" }, "devDependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/cli": "workspace:^" } } diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index fa8c4a404e..61e08340d9 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -61,7 +61,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-defaults": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", diff --git a/plugins/scaffolder-node-test-utils/package.json b/plugins/scaffolder-node-test-utils/package.json index c005caf853..5339803ea4 100644 --- a/plugins/scaffolder-node-test-utils/package.json +++ b/plugins/scaffolder-node-test-utils/package.json @@ -40,7 +40,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-test-utils": "workspace:^", "@backstage/plugin-scaffolder-node": "workspace:^", "@backstage/types": "workspace:^" diff --git a/plugins/scaffolder-node/package.json b/plugins/scaffolder-node/package.json index 7a2bb3643b..164da18a7a 100644 --- a/plugins/scaffolder-node/package.json +++ b/plugins/scaffolder-node/package.json @@ -54,7 +54,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/errors": "workspace:^", diff --git a/plugins/search-backend-module-catalog/package.json b/plugins/search-backend-module-catalog/package.json index 6bf4acb7d6..c648136262 100644 --- a/plugins/search-backend-module-catalog/package.json +++ b/plugins/search-backend-module-catalog/package.json @@ -48,7 +48,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", @@ -61,7 +61,7 @@ "@backstage/plugin-search-common": "workspace:^" }, "devDependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "msw": "^1.0.0" diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index 954c30da22..c0efa43628 100644 --- a/plugins/search-backend-module-elasticsearch/package.json +++ b/plugins/search-backend-module-elasticsearch/package.json @@ -48,7 +48,6 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/integration-aws-node": "workspace:^", @@ -62,7 +61,6 @@ "uuid": "^9.0.0" }, "devDependencies": { - "@backstage/backend-common": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@elastic/elasticsearch-mock": "^1.0.0", diff --git a/plugins/search-backend-module-explore/package.json b/plugins/search-backend-module-explore/package.json index 2eb0f9e40c..a31ff60e4d 100644 --- a/plugins/search-backend-module-explore/package.json +++ b/plugins/search-backend-module-explore/package.json @@ -49,7 +49,7 @@ }, "dependencies": { "@backstage-community/plugin-explore-common": "^0.0.5", - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/plugin-search-backend-node": "workspace:^", diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index 6fa43d7fd4..6b1f94779a 100644 --- a/plugins/search-backend-module-pg/package.json +++ b/plugins/search-backend-module-pg/package.json @@ -49,7 +49,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/plugin-search-backend-node": "workspace:^", diff --git a/plugins/search-backend-module-stack-overflow-collator/package.json b/plugins/search-backend-module-stack-overflow-collator/package.json index 9745138795..1321930001 100644 --- a/plugins/search-backend-module-stack-overflow-collator/package.json +++ b/plugins/search-backend-module-stack-overflow-collator/package.json @@ -35,7 +35,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/plugin-search-backend-node": "workspace:^", diff --git a/plugins/search-backend-module-techdocs/package.json b/plugins/search-backend-module-techdocs/package.json index 73748ac401..bf64d8eb0f 100644 --- a/plugins/search-backend-module-techdocs/package.json +++ b/plugins/search-backend-module-techdocs/package.json @@ -48,7 +48,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index 949ff3be74..748d004377 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -66,7 +66,7 @@ "uuid": "^9.0.0" }, "devDependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/ndjson": "^2.0.1" diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index 16ba2270fa..e4e01e90c5 100644 --- a/plugins/search-backend/package.json +++ b/plugins/search-backend/package.json @@ -56,7 +56,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-defaults": "workspace:^", "@backstage/backend-openapi-utils": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", diff --git a/plugins/signals-backend/package.json b/plugins/signals-backend/package.json index b233f80a30..e9f4b1cc7c 100644 --- a/plugins/signals-backend/package.json +++ b/plugins/signals-backend/package.json @@ -37,7 +37,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", diff --git a/plugins/signals-node/package.json b/plugins/signals-node/package.json index 7e086ce765..67c728f96c 100644 --- a/plugins/signals-node/package.json +++ b/plugins/signals-node/package.json @@ -37,7 +37,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index 88a02a6a0e..f3c8dbb139 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -58,7 +58,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-common": "^0.25.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", diff --git a/yarn.lock b/yarn.lock index 6bda1d50a9..c352ecf166 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3463,7 +3463,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/backend-app-api@workspace:packages/backend-app-api" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -3511,56 +3511,38 @@ __metadata: languageName: unknown linkType: soft -"@backstage/backend-common@workspace:^, @backstage/backend-common@workspace:packages/backend-common": - version: 0.0.0-use.local - resolution: "@backstage/backend-common@workspace:packages/backend-common" +"@backstage/backend-common@npm:^0.25.0": + version: 0.25.0 + resolution: "@backstage/backend-common@npm:0.25.0" dependencies: "@aws-sdk/abort-controller": ^3.347.0 "@aws-sdk/client-codecommit": ^3.350.0 "@aws-sdk/client-s3": ^3.350.0 "@aws-sdk/credential-providers": ^3.350.0 "@aws-sdk/types": ^3.347.0 - "@aws-sdk/util-stream-node": ^3.350.0 - "@backstage/backend-dev-utils": "workspace:^" - "@backstage/backend-plugin-api": "workspace:^" - "@backstage/backend-test-utils": "workspace:^" - "@backstage/cli": "workspace:^" - "@backstage/cli-common": "workspace:^" - "@backstage/config": "workspace:^" - "@backstage/config-loader": "workspace:^" - "@backstage/errors": "workspace:^" - "@backstage/integration": "workspace:^" - "@backstage/integration-aws-node": "workspace:^" - "@backstage/plugin-auth-node": "workspace:^" - "@backstage/types": "workspace:^" + "@backstage/backend-dev-utils": ^0.1.5 + "@backstage/backend-plugin-api": ^1.0.0 + "@backstage/cli-common": ^0.1.14 + "@backstage/config": ^1.2.0 + "@backstage/config-loader": ^1.9.1 + "@backstage/errors": ^1.2.4 + "@backstage/integration": ^1.15.0 + "@backstage/integration-aws-node": ^0.1.12 + "@backstage/plugin-auth-node": ^0.5.2 + "@backstage/types": ^1.1.1 "@google-cloud/storage": ^7.0.0 "@keyv/memcache": ^1.3.5 "@keyv/redis": ^2.5.3 "@kubernetes/client-node": 0.20.0 "@manypkg/get-packages": ^1.1.3 "@octokit/rest": ^19.0.3 - "@types/archiver": ^6.0.0 - "@types/base64-stream": ^1.0.2 - "@types/compression": ^1.7.0 - "@types/concat-stream": ^2.0.0 "@types/cors": ^2.8.6 "@types/dockerode": ^3.3.0 "@types/express": ^4.17.6 - "@types/fs-extra": ^11.0.0 - "@types/http-errors": ^2.0.0 "@types/luxon": ^3.0.0 - "@types/morgan": ^1.9.0 - "@types/node-forge": ^1.3.0 - "@types/pg": ^8.6.6 - "@types/stoppable": ^1.1.0 - "@types/supertest": ^2.0.8 - "@types/tar": ^6.1.1 "@types/webpack-env": ^1.15.2 - "@types/yauzl": ^2.10.0 archiver: ^7.0.0 - aws-sdk-client-mock: ^4.0.0 base64-stream: ^1.0.0 - better-sqlite3: ^11.0.0 compression: ^1.7.4 concat-stream: ^2.0.0 cors: ^2.8.5 @@ -3570,7 +3552,6 @@ __metadata: fs-extra: ^11.2.0 git-url-parse: ^14.0.0 helmet: ^6.0.0 - http-errors: ^2.0.0 isomorphic-git: ^1.23.0 jose: ^5.0.0 keyv: ^4.5.2 @@ -3581,7 +3562,6 @@ __metadata: minimatch: ^9.0.0 minimist: ^1.2.5 morgan: ^1.10.0 - msw: ^1.0.0 mysql2: ^3.0.0 node-fetch: ^2.7.0 node-forge: ^1.3.1 @@ -3592,7 +3572,6 @@ __metadata: raw-body: ^2.4.1 selfsigned: ^2.0.0 stoppable: ^1.1.0 - supertest: ^7.0.0 tar: ^6.1.12 triple-beam: ^1.4.1 uuid: ^9.0.0 @@ -3605,8 +3584,9 @@ __metadata: peerDependenciesMeta: pg-connection-string: optional: true - languageName: unknown - linkType: soft + checksum: 34d2b92b5fd7f6d8f25975d121634079586d022665a51b676ba47053050e0f22556f80d59a75a10e0a8f1803a718448b7aed4bd1dcd6f1d348785c97cf5a8c9d + languageName: node + linkType: hard "@backstage/backend-defaults@workspace:^, @backstage/backend-defaults@workspace:packages/backend-defaults": version: 0.0.0-use.local @@ -3619,7 +3599,7 @@ __metadata: "@aws-sdk/types": ^3.347.0 "@aws-sdk/util-stream-node": ^3.350.0 "@backstage/backend-app-api": "workspace:^" - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-dev-utils": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -3641,6 +3621,9 @@ __metadata: "@manypkg/get-packages": ^1.1.3 "@octokit/rest": ^19.0.3 "@opentelemetry/api": ^1.3.0 + "@types/archiver": ^6.0.0 + "@types/base64-stream": ^1.0.2 + "@types/concat-stream": ^2.0.0 "@types/cors": ^2.8.6 "@types/express": ^4.17.6 "@types/http-errors": ^2.0.0 @@ -3648,6 +3631,7 @@ __metadata: "@types/node-forge": ^1.3.0 "@types/pg-format": ^1.0.5 "@types/stoppable": ^1.1.0 + "@types/yauzl": ^2.10.0 archiver: ^7.0.0 aws-sdk-client-mock: ^4.0.0 base64-stream: ^1.0.0 @@ -3698,7 +3682,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/backend-dev-utils@workspace:^, @backstage/backend-dev-utils@workspace:packages/backend-dev-utils": +"@backstage/backend-dev-utils@^0.1.5, @backstage/backend-dev-utils@workspace:^, @backstage/backend-dev-utils@workspace:packages/backend-dev-utils": version: 0.0.0-use.local resolution: "@backstage/backend-dev-utils@workspace:packages/backend-dev-utils" dependencies: @@ -3711,7 +3695,7 @@ __metadata: resolution: "@backstage/backend-dynamic-feature-service@workspace:packages/backend-dynamic-feature-service" dependencies: "@backstage/backend-app-api": "workspace:^" - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -3763,7 +3747,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/backend-plugin-api@workspace:^, @backstage/backend-plugin-api@workspace:packages/backend-plugin-api": +"@backstage/backend-plugin-api@^1.0.0, @backstage/backend-plugin-api@workspace:^, @backstage/backend-plugin-api@workspace:packages/backend-plugin-api": version: 0.0.0-use.local resolution: "@backstage/backend-plugin-api@workspace:packages/backend-plugin-api" dependencies: @@ -3851,7 +3835,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-common@workspace:^, @backstage/cli-common@workspace:packages/cli-common": +"@backstage/cli-common@^0.1.14, @backstage/cli-common@workspace:^, @backstage/cli-common@workspace:packages/cli-common": version: 0.0.0-use.local resolution: "@backstage/cli-common@workspace:packages/cli-common" dependencies: @@ -3881,7 +3865,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/cli@workspace:packages/cli" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-model": "workspace:^" @@ -4062,7 +4046,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/config-loader@workspace:^, @backstage/config-loader@workspace:packages/config-loader": +"@backstage/config-loader@^1.9.1, @backstage/config-loader@workspace:^, @backstage/config-loader@workspace:packages/config-loader": version: 0.0.0-use.local resolution: "@backstage/config-loader@workspace:packages/config-loader" dependencies: @@ -4549,7 +4533,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/integration-aws-node@workspace:^, @backstage/integration-aws-node@workspace:packages/integration-aws-node": +"@backstage/integration-aws-node@^0.1.12, @backstage/integration-aws-node@workspace:^, @backstage/integration-aws-node@workspace:packages/integration-aws-node": version: 0.0.0-use.local resolution: "@backstage/integration-aws-node@workspace:packages/integration-aws-node" dependencies: @@ -4592,7 +4576,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/integration@workspace:^, @backstage/integration@workspace:packages/integration": +"@backstage/integration@^1.15.0, @backstage/integration@workspace:^, @backstage/integration@workspace:packages/integration": version: 0.0.0-use.local resolution: "@backstage/integration@workspace:packages/integration" dependencies: @@ -4674,7 +4658,7 @@ __metadata: resolution: "@backstage/plugin-app-backend@workspace:plugins/app-backend" dependencies: "@backstage/backend-app-api": "workspace:^" - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -4800,7 +4784,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-aws-alb-provider@workspace:plugins/auth-backend-module-aws-alb-provider" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" @@ -4958,7 +4942,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-guest-provider@workspace:plugins/auth-backend-module-guest-provider" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-model": "workspace:^" @@ -5025,7 +5009,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-oidc-provider@workspace:plugins/auth-backend-module-oidc-provider" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -5127,7 +5111,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend@workspace:plugins/auth-backend" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -5203,11 +5187,11 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-node@workspace:^, @backstage/plugin-auth-node@workspace:plugins/auth-node": +"@backstage/plugin-auth-node@^0.5.2, @backstage/plugin-auth-node@workspace:^, @backstage/plugin-auth-node@workspace:plugins/auth-node": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-node@workspace:plugins/auth-node" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-client": "workspace:^" @@ -5342,7 +5326,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-bitbucket-cloud@workspace:plugins/catalog-backend-module-bitbucket-cloud" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-client": "workspace:^" @@ -5435,7 +5419,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-github@workspace:plugins/catalog-backend-module-github" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-client": "workspace:^" @@ -5464,7 +5448,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-gitlab-org@workspace:plugins/catalog-backend-module-gitlab-org" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" @@ -5506,7 +5490,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-incremental-ingestion@workspace:plugins/catalog-backend-module-incremental-ingestion" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -5591,7 +5575,7 @@ __metadata: resolution: "@backstage/plugin-catalog-backend-module-openapi@workspace:plugins/catalog-backend-module-openapi" dependencies: "@apidevtools/json-schema-ref-parser": ^9.0.6 - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-model": "workspace:^" @@ -5647,7 +5631,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-unprocessed@workspace:plugins/catalog-backend-module-unprocessed" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" @@ -5666,7 +5650,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend@workspace:plugins/catalog-backend" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-openapi-utils": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" @@ -5990,7 +5974,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-devtools-backend@workspace:plugins/devtools-backend" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -6065,7 +6049,6 @@ __metadata: dependencies: "@aws-sdk/client-sqs": ^3.350.0 "@aws-sdk/types": ^3.347.0 - "@backstage/backend-common": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" @@ -6154,7 +6137,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-events-backend@workspace:plugins/events-backend" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" @@ -6173,7 +6156,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-events-node@workspace:plugins/events-node" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" @@ -6252,7 +6235,7 @@ __metadata: "@aws-sdk/signature-v4": ^3.347.0 "@azure/identity": ^4.0.0 "@backstage/backend-app-api": "workspace:^" - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -6352,7 +6335,7 @@ __metadata: resolution: "@backstage/plugin-kubernetes-node@workspace:plugins/kubernetes-node" dependencies: "@backstage/backend-app-api": "workspace:^" - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -6451,7 +6434,7 @@ __metadata: dependencies: "@aws-sdk/client-ses": ^3.550.0 "@aws-sdk/types": ^3.347.0 - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-client": "workspace:^" @@ -6474,7 +6457,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-notifications-backend@workspace:plugins/notifications-backend" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -6521,7 +6504,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-notifications-node@workspace:plugins/notifications-node" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-client": "workspace:^" @@ -6657,7 +6640,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-permission-backend@workspace:plugins/permission-backend" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" @@ -6701,7 +6684,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-permission-node@workspace:plugins/permission-node" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" @@ -6745,7 +6728,7 @@ __metadata: resolution: "@backstage/plugin-proxy-backend@workspace:plugins/proxy-backend" dependencies: "@backstage/backend-app-api": "workspace:^" - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -6852,7 +6835,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown@workspace:plugins/scaffolder-backend-module-confluence-to-markdown" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" @@ -6874,7 +6857,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend-module-cookiecutter@workspace:plugins/scaffolder-backend-module-cookiecutter" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -6951,7 +6934,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend-module-github@workspace:plugins/scaffolder-backend-module-github" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-client": "workspace:^" @@ -6977,7 +6960,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend-module-gitlab@workspace:plugins/scaffolder-backend-module-gitlab" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" @@ -7000,7 +6983,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend-module-notifications@workspace:plugins/scaffolder-backend-module-notifications" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/plugin-notifications-common": "workspace:^" @@ -7016,7 +6999,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend-module-rails@workspace:plugins/scaffolder-backend-module-rails" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" @@ -7058,7 +7041,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend-module-yeoman@workspace:plugins/scaffolder-backend-module-yeoman" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" @@ -7075,7 +7058,7 @@ __metadata: resolution: "@backstage/plugin-scaffolder-backend@workspace:plugins/scaffolder-backend" dependencies: "@backstage/backend-app-api": "workspace:^" - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -7156,7 +7139,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-node-test-utils@workspace:plugins/scaffolder-node-test-utils" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" @@ -7169,7 +7152,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-node@workspace:plugins/scaffolder-node" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-model": "workspace:^" @@ -7326,7 +7309,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-search-backend-module-catalog@workspace:plugins/search-backend-module-catalog" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-client": "workspace:^" @@ -7347,7 +7330,6 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-search-backend-module-elasticsearch@workspace:plugins/search-backend-module-elasticsearch" dependencies: - "@backstage/backend-common": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" @@ -7371,7 +7353,7 @@ __metadata: resolution: "@backstage/plugin-search-backend-module-explore@workspace:plugins/search-backend-module-explore" dependencies: "@backstage-community/plugin-explore-common": ^0.0.5 - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" @@ -7387,7 +7369,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-search-backend-module-pg@workspace:plugins/search-backend-module-pg" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" @@ -7404,7 +7386,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-search-backend-module-stack-overflow-collator@workspace:plugins/search-backend-module-stack-overflow-collator" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" @@ -7421,7 +7403,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-search-backend-module-techdocs@workspace:plugins/search-backend-module-techdocs" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-client": "workspace:^" @@ -7445,7 +7427,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-search-backend-node@workspace:plugins/search-backend-node" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -7467,7 +7449,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-search-backend@workspace:plugins/search-backend" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-openapi-utils": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" @@ -7576,7 +7558,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-signals-backend@workspace:plugins/signals-backend" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -7609,7 +7591,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-signals-node@workspace:plugins/signals-node" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-plugin-api": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" @@ -7697,7 +7679,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-techdocs-backend@workspace:plugins/techdocs-backend" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -9891,7 +9873,7 @@ __metadata: version: 0.0.0-use.local resolution: "@internal/plugin-todo-list-backend@workspace:plugins/example-todo-list-backend" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -17891,7 +17873,7 @@ __metadata: languageName: node linkType: hard -"@types/pg@npm:*, @types/pg@npm:^8.6.6": +"@types/pg@npm:*": version: 8.11.10 resolution: "@types/pg@npm:8.11.10" dependencies: @@ -26304,7 +26286,7 @@ __metadata: version: 0.0.0-use.local resolution: "example-backend-legacy@workspace:packages/backend-legacy" dependencies: - "@backstage/backend-common": "workspace:^" + "@backstage/backend-common": ^0.25.0 "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/catalog-client": "workspace:^"