From 2384a499629320e59cc492958f5c2614074ec6bd Mon Sep 17 00:00:00 2001 From: Steven Billington Date: Wed, 24 Apr 2024 14:29:33 -0400 Subject: [PATCH 01/46] Making docs updates for software templates. Signed-off-by: Steven Billington --- .../software-templates/input-examples.md | 20 ++++++++++- .../writing-custom-actions.md | 34 +++++++++++++++++-- .../software-templates/writing-templates.md | 29 +++++++++++++++- 3 files changed, 78 insertions(+), 5 deletions(-) diff --git a/docs/features/software-templates/input-examples.md b/docs/features/software-templates/input-examples.md index a95cee24f4..50495b1784 100644 --- a/docs/features/software-templates/input-examples.md +++ b/docs/features/software-templates/input-examples.md @@ -181,9 +181,11 @@ parameters: ## Use parameters as condition in steps +Conditions use Javascript equality operators. + ```yaml - name: Only development environments - if: ${{ parameters.environment === "staging" and parameters.environment === "development" }} + if: ${{ parameters.environment === "staging" or parameters.environment === "development" }} action: debug:log input: message: 'development step' @@ -193,6 +195,12 @@ parameters: action: debug:log input: message: 'production step' + +- name: Non-production environments + if: ${{ parameters.environment !== "prod" and parameters.environment !== "production" }} + action: debug:log + input: + message: 'non-production step' ``` ## Use parameters as conditional for fields @@ -218,10 +226,15 @@ parameters: lastName: title: Last Name type: string + # You can use additional fields of parameters within conditional parameters such as required. + required: + - lastName ``` ## Conditionally set parameters +The `if` keyword within the parameter uses [nunjucks templating](https://mozilla.github.io/nunjucks/templating.html#if). The `not` keyword is unavailable; instead, use javascript equality. + ```yaml spec: parameters: @@ -237,4 +250,9 @@ spec: action: fetch:template input: url: ${{ parameters.path if parameters.path else '/root' }} + - id: fetch_not_example + name: Fetch template not example + action: fetch:template + input: + url: ${{ '/root' if parameters.path !== true else parameters.path }} ``` diff --git a/docs/features/software-templates/writing-custom-actions.md b/docs/features/software-templates/writing-custom-actions.md index 92ff092948..96b2540527 100644 --- a/docs/features/software-templates/writing-custom-actions.md +++ b/docs/features/software-templates/writing-custom-actions.md @@ -32,6 +32,7 @@ import { z } from 'zod'; export const createNewFileAction = () => { return createTemplateAction({ id: 'acme:file:create', + description: 'Create an Acme file.', schema: { input: z.object({ contents: z.string().describe('The contents of the file'), @@ -59,9 +60,10 @@ for reference. The `createTemplateAction` takes an object which specifies the following: -- `id` - a unique ID for your custom action. We encourage you to namespace these +- `id` - A unique ID for your custom action. We encourage you to namespace these in some way so that they won't collide with future built-in actions that we may ship with the `scaffolder-backend` plugin. +- `description` - An optional field to describe the purpose of the action. This will populate in the `/create/actions` endpoint. - `schema.input` - A `zod` or JSON schema object for input values to your function - `schema.output` - A `zod` or JSON schema object for values which are output from the function using `ctx.output` @@ -76,6 +78,7 @@ import { writeFile } from 'fs'; export const createNewFileAction = () => { return createTemplateAction<{ contents: string; filename: string }>({ id: 'acme:file:create', + description: 'Create an Acme file.', schema: { input: { required: ['contents', 'filename'], @@ -114,7 +117,7 @@ We follow `provider:entity:verb` or as close to this as possible for our built i Also feel free to use your company name to namespace them if you prefer too, for example `acme:file:create` like above. -Prefer to use `camelCase` over `snake-case` for these actions if possible, which leads to better reading and writing of template entity definitions. +Prefer to use `camelCase` over `snake_case` or `kebab-case` for these actions if possible, which leads to better reading and writing of template entity definitions. > We're aware that there are some exceptions to this, but try to follow as close as possible. We'll be working on migrating these in the repository over time too. @@ -139,6 +142,8 @@ argument. It looks like the following: ## Registering Custom Actions +### Register Action With Previous Backend System, Backstage Version < 1.25.x + Once you have your Custom Action ready for usage with the scaffolder, you'll need to pass this into the `scaffolder-backend` `createRouter` function. You should have something similar to the below in @@ -189,7 +194,7 @@ export default async function createPlugin( } ``` -### Register Action With New Backend System +### Register Action With New Backend System, Backstage Version >= 1.25.0 To register your new custom action in the New Backend System you will need to create a backend module. Here is a very simplified example of how to do that: @@ -225,6 +230,29 @@ backend.add(import('@backstage/plugin-scaffolder-backend/alpha')); backend.add(scaffolderModuleCustomExtensions()); ``` +If your custom action requires core services such as `config` or `cache` they can be imported in the dependencies and passed to the custom action function. + +```ts title="packages/backend/src/index.ts" +import { + coreServices, + createBackendModule, +} from '@backstage/backend-plugin-api'; + +... + + env.registerInit({ + deps: { + scaffolder: scaffolderActionsExtensionPoint, + cache: coreServices.cache, + config: coreServices.rootConfig, + }, + async init({ scaffolder, cache, config }) { + scaffolder.addActions( + customActionNeedingCacheAndConfig({ cache: cache, config: config }), + ); + }) +``` + ## List of custom action packages Here is a list of Open Source custom actions that you can add to your Backstage diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index ad542ba4a3..1e289d2409 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -311,10 +311,37 @@ spec: ``` If you have a feature flag `experimental-feature` active then -your first step would be shown. The same goes for the nested properties in the +your first set of parameter fields would be shown. The same goes for the nested properties in the spec. Make sure to use the key `backstage:featureFlag` in your templates if you want to use this functionality. +Feature Flags cannot be used in `spec.steps[].if`(the conditional on whether to execute an step/action). But you can use feature flags to display parameters that allow for skipping steps. + +```yaml +spec: + type: website + owner: team-a + parameters: + - name: Enter some stuff + description: Enter some stuff + backstage:featureFlag: experimental-feature + properties: + skipStep: + type: boolean + title: Whether or not to skip a step. + default: false + restOfParameters: + ... + steps: + - id: skipMe + name: A step to skip if the feature flag is turned on and the user selects true + action: debug:log + if: ${{ parameters.skipStep }} + input: + message: | + ... +``` + ### The Repository Picker In order to make working with repository providers easier, we've built a custom From 6a563f9e53a62f352b12c61fb73f7df938a17706 Mon Sep 17 00:00:00 2001 From: Steven Billington Date: Wed, 24 Apr 2024 15:43:57 -0400 Subject: [PATCH 02/46] Added additional documentation to the software templating section including unit tests. Signed-off-by: Steven Billington --- .../software-templates/writing-templates.md | 2 +- .../writing-tests-for-actions.md | 77 ++++++++++++++++--- 2 files changed, 69 insertions(+), 10 deletions(-) diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index 1e289d2409..d8e6feb559 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -734,7 +734,7 @@ an entity reference, such as the `kind`, `namespace`, and `name`. ### pick -This `pick` filter allows you to select specific properties from an object. +This `pick` filter allows you to select specific properties (`kind`, `namespace`, `name`) from an object. **Usage Example** diff --git a/docs/features/software-templates/writing-tests-for-actions.md b/docs/features/software-templates/writing-tests-for-actions.md index 0c92811b6f..0bfd97e49f 100644 --- a/docs/features/software-templates/writing-tests-for-actions.md +++ b/docs/features/software-templates/writing-tests-for-actions.md @@ -4,15 +4,13 @@ title: Writing Tests For Actions description: How to write tests for actions --- -Once you created a new action, your own custom one, or you would like to contribute new actions, you have to cover it with -Unit tests to be sure that your actions do what they suppose to do. +# Unit Testing Custom Actions -Make sure that you cover the most of scenario's, which could happen with the action. -One of indispensable part of the test is to supply the context to a handler of action for the execution. -We encourage you to use a utility method for that, so your tests are immune to structural changes of context. -What is inevitably going to happen during the time. +Unit tests help prevent regressions in custom action functionality. The `createTemplateAction` function that is the core of a custom action can be difficult to mock. There are helper methods that can assist. -Example how to use it: +## Mocking the Context + +The `handler` property of the `createTemplateAction` input object expects a context. You can create a mock context using the code below: ```typescript import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; @@ -29,10 +27,11 @@ expect(mockContext.output).toHaveBeenCalledWith( ); ``` +### Mocking a Workspace within the Context object + One thing to be aware about: if you would like to call `createMockActionContext` inside `it`, you have to provide a `workspacePath`. By default, `createMockActionContext` uses -`import { createMockDirectory } from '@backstage/backend-test-utils';` to create it for you. -This implementation contains a hook inside which creates this limitation. So in this case you can do then: +`import { createMockDirectory } from '@backstage/backend-test-utils';` to create it for you. You can use the code below to customize the `workspacePath` without using the default workspace of the `createMockActionContext` function. ```typescript describe('github:autolinks:create', async () => { @@ -55,3 +54,63 @@ describe('github:autolinks:create', async () => { }); }); ``` + +## Mocking a Config Core Service + +If your custom Action requires the Config Core Service within execution of the `handler(ctx)` such as the custom action below, mocking the context object can be done by building a `mockContext` with the `ConfigReader` function within the `@backstage/config` package. + +```typescript +// custom-action.ts +import { Config } from '@backstage/config'; + +export const customActionRequiringConfigCoreService = (config: Config) => { + const fieldRequiringValueFromConfig = config.getString('app.service.url'); + return createTemplateAction({ + ... + async handler(ctx) { + // Some code requiring the config const + ctx.logger.info(fieldRequiringValueFromConfig); + } + }) +} +``` + +```typescript +// custom-action.test.ts +import { ConfigReader } from '@backstage/config'; +import { customActionRequiringConfigCoreService } from './custom-action.ts'; +... +const mockConfig = new ConfigReader({ + app: { + service: { + url: 'https://api.service.io/graphql', + apiKeyId: '123', + apiKeySecret: '123abc', + }, + }, +}); +... +const action = customActionRequiringConfigCoreService(mockConfig); +await action.handler({ + ...mockContext +}) +``` + +## Mocking a Cache Core Service + +Similar to the `Mocking a Config Core Service` section above, if your custom action expects a Cache Core Service Object as part of the function input, you can mock it out with the following: + +```typescript +import { CacheService } from '@backstage/backend-plugin-api'; + +const mockCacheServiceMethods = { + get: jest.fn(), + set: jest.fn(), + delete: jest.fn(), +}; + +const mockCacheService = mockCacheServiceMethods as unknown as CacheService; + +const action = customActionRequiringCacheCoreService(mockCacheService); +... +``` From 5f8ee599f5e9832e83ea6bcab791c1258ab683f6 Mon Sep 17 00:00:00 2001 From: Steven Billington Date: Thu, 25 Apr 2024 09:27:40 -0400 Subject: [PATCH 03/46] Minor fix on version numbering that I missed earlier in the documentation. Signed-off-by: Steven Billington --- docs/features/software-templates/writing-custom-actions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/features/software-templates/writing-custom-actions.md b/docs/features/software-templates/writing-custom-actions.md index 96b2540527..fa21c8f7a9 100644 --- a/docs/features/software-templates/writing-custom-actions.md +++ b/docs/features/software-templates/writing-custom-actions.md @@ -142,7 +142,7 @@ argument. It looks like the following: ## Registering Custom Actions -### Register Action With Previous Backend System, Backstage Version < 1.25.x +### Register Action With Previous Backend System, Backstage Version < 1.24.x Once you have your Custom Action ready for usage with the scaffolder, you'll need to pass this into the `scaffolder-backend` `createRouter` function. You @@ -194,7 +194,7 @@ export default async function createPlugin( } ``` -### Register Action With New Backend System, Backstage Version >= 1.25.0 +### Register Action With New Backend System, Backstage Version >= 1.24.0 To register your new custom action in the New Backend System you will need to create a backend module. Here is a very simplified example of how to do that: From 403357a37c1af49e34c3f813afce40ae981c782b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 12:57:13 +0000 Subject: [PATCH 04/46] chore(deps): update snyk/actions digest to d406fd2 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/sync_snyk-github-issues.yml | 2 +- .github/workflows/sync_snyk-monitor.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml index 2ea3fcd5a1..b369987f66 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -29,7 +29,7 @@ jobs: cache-prefix: ${{ runner.os }}-v18.x - name: Create Snyk report - uses: snyk/actions/node@8349f9043a8b7f0f3ee8885bf28f0b388d2446e8 # master + uses: snyk/actions/node@d406fd286b663eb8c6f8adcced4f7bcd199c0a3f # master continue-on-error: true # Snyk CLI exits with error when vulnerabilities are found with: args: > diff --git a/.github/workflows/sync_snyk-monitor.yml b/.github/workflows/sync_snyk-monitor.yml index e6b274c395..0919792a09 100644 --- a/.github/workflows/sync_snyk-monitor.yml +++ b/.github/workflows/sync_snyk-monitor.yml @@ -31,7 +31,7 @@ jobs: - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - name: Monitor and Synchronize Snyk Policies - uses: snyk/actions/node@8349f9043a8b7f0f3ee8885bf28f0b388d2446e8 # master + uses: snyk/actions/node@d406fd286b663eb8c6f8adcced4f7bcd199c0a3f # master with: command: monitor args: > @@ -46,7 +46,7 @@ jobs: # Above we run the `monitor` command, this runs the `test` command which is # the one that generates the SARIF report that we can upload to GitHub. - name: Create Snyk report - uses: snyk/actions/node@8349f9043a8b7f0f3ee8885bf28f0b388d2446e8 # master + uses: snyk/actions/node@d406fd286b663eb8c6f8adcced4f7bcd199c0a3f # master continue-on-error: true # To make sure that SARIF upload gets called with: args: > From 817e97606638bbf25bc504915f4090e3ae32a9ea Mon Sep 17 00:00:00 2001 From: Steven Billington Date: Fri, 31 May 2024 14:26:59 -0400 Subject: [PATCH 05/46] Changes made to the orger of registering a custom action as requested. Signed-off-by: Steven Billington --- .../writing-custom-actions.md | 108 +++++++++--------- 1 file changed, 53 insertions(+), 55 deletions(-) diff --git a/docs/features/software-templates/writing-custom-actions.md b/docs/features/software-templates/writing-custom-actions.md index fa21c8f7a9..c1386786c7 100644 --- a/docs/features/software-templates/writing-custom-actions.md +++ b/docs/features/software-templates/writing-custom-actions.md @@ -142,61 +142,7 @@ argument. It looks like the following: ## Registering Custom Actions -### Register Action With Previous Backend System, Backstage Version < 1.24.x - -Once you have your Custom Action ready for usage with the scaffolder, you'll -need to pass this into the `scaffolder-backend` `createRouter` function. You -should have something similar to the below in -`packages/backend/src/plugins/scaffolder.ts` - -```ts -return await createRouter({ - containerRunner, - catalogClient, - logger: env.logger, - config: env.config, - database: env.database, - reader: env.reader, -}); -``` - -There's another property you can pass here, which is an array of `actions` which -will set the available actions that the scaffolder has access to. - -```ts -import { createBuiltinActions } from '@backstage/plugin-scaffolder-backend'; -import { ScmIntegrations } from '@backstage/integration'; -import { createNewFileAction } from './scaffolder/actions/custom'; - -export default async function createPlugin( - env: PluginEnvironment, -): Promise { - const catalogClient = new CatalogClient({ discoveryApi: env.discovery }); - const integrations = ScmIntegrations.fromConfig(env.config); - - const builtInActions = createBuiltinActions({ - integrations, - catalogClient, - config: env.config, - reader: env.reader, - }); - - const actions = [...builtInActions, createNewFileAction()]; - - return createRouter({ - actions, - catalogClient: catalogClient, - logger: env.logger, - config: env.config, - database: env.database, - reader: env.reader, - }); -} -``` - -### Register Action With New Backend System, Backstage Version >= 1.24.0 - -To register your new custom action in the New Backend System you will need to create a backend module. Here is a very simplified example of how to do that: +To register your new custom action in the Backend System you will need to create a backend module. Here is a very simplified example of how to do that: ```ts title="packages/backend/src/index.ts" /* highlight-add-start */ @@ -253,6 +199,58 @@ import { }) ``` +### Register Custom Actions with the Legacy Backend System + +Once you have your Custom Action ready for usage with the scaffolder, you'll +need to pass this into the `scaffolder-backend` `createRouter` function. You +should have something similar to the below in +`packages/backend/src/plugins/scaffolder.ts` + +```ts +return await createRouter({ + containerRunner, + catalogClient, + logger: env.logger, + config: env.config, + database: env.database, + reader: env.reader, +}); +``` + +There's another property you can pass here, which is an array of `actions` which +will set the available actions that the scaffolder has access to. + +```ts +import { createBuiltinActions } from '@backstage/plugin-scaffolder-backend'; +import { ScmIntegrations } from '@backstage/integration'; +import { createNewFileAction } from './scaffolder/actions/custom'; + +export default async function createPlugin( + env: PluginEnvironment, +): Promise { + const catalogClient = new CatalogClient({ discoveryApi: env.discovery }); + const integrations = ScmIntegrations.fromConfig(env.config); + + const builtInActions = createBuiltinActions({ + integrations, + catalogClient, + config: env.config, + reader: env.reader, + }); + + const actions = [...builtInActions, createNewFileAction()]; + + return createRouter({ + actions, + catalogClient: catalogClient, + logger: env.logger, + config: env.config, + database: env.database, + reader: env.reader, + }); +} +``` + ## List of custom action packages Here is a list of Open Source custom actions that you can add to your Backstage From e46744f7f53ccf0b7e679328c114ce11594b3c6c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 5 Jun 2024 17:03:19 +0200 Subject: [PATCH 06/46] beps/0009: switch libraries alternative to main proposal Signed-off-by: Patrik Oldsberg --- beps/0009-plugin-metadata/README.md | 34 ++++++++++++++--------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/beps/0009-plugin-metadata/README.md b/beps/0009-plugin-metadata/README.md index a23a2d7ce4..b6ecd966d9 100644 --- a/beps/0009-plugin-metadata/README.md +++ b/beps/0009-plugin-metadata/README.md @@ -95,7 +95,7 @@ Packages that are part of the same plugin should always be managed within the sa Each plugin package must define a `backstage.pluginId` field, which is the same identifier as is used in the implementation of the plugin. This field is inferred from the package name by the `backstage-cli repo fix` command if it is not present. It should only be defined for plugin package, for example `@backstage/errors` should not define a plugin ID. The `backstage.pluginId` field is required when publishing a package with a plugin or module role, or a library role with "plugin" in its name. -The package relationships are defined in the `backstage.pluginPackages` field. The value of the field is an object where each key is the role of the package as defined by the `backstage.role` field, and the value is the package name. For example: +The package relationships are defined in the `backstage.pluginPackages` field. The value of the fields in an object with three optional keys, `frontend`, `backend`, and `libraries`. The `frontend` and `backend` fields must be the name of the frontend and backend plugin packages if present, while the `libraries` is an array of all library packages that are related to this plugin. For example: ```json { @@ -104,17 +104,19 @@ The package relationships are defined in the `backstage.pluginPackages` field. T "role": "frontend-plugin", "pluginId": "catalog", "pluginPackages": { - "frontend-plugin": "@backstage/plugin-catalog", - "backend-plugin": "@backstage/plugin-catalog-backend", - "web-library": "@backstage/plugin-catalog-react", - "node-library": "@backstage/plugin-catalog-node", - "common-library": "@backstage/plugin-catalog-common" + "frontend": "@backstage/plugin-catalog", + "backend": "@backstage/plugin-catalog-backend", + "libraries": [ + "@backstage/plugin-catalog-react", + "@backstage/plugin-catalog-node", + "@backstage/plugin-catalog-common" + ] } } } ``` -The `backstage.pluginPackages` field is generated and updated by the `backstage-cli repo fix` command based on the packages that are present in the workspace and their `backstage.pluginId` and `backstage.role` fields. There can only be a single package of each role with a given plugin ID. The `backstage.pluginPackages` field is required when publishing a package with a `backstage.pluginId` field that is not using a module role. +The `backstage.pluginPackages` field is generated and updated by the `backstage-cli repo fix` command based on the packages that are present in the workspace and their `backstage.pluginId` and `backstage.role` fields. The `backstage.pluginPackages` field is required when publishing a package with a `backstage.pluginId` field that is not using a module role. Module packages define their target plugin both via the `backstage.pluginId` field, as well as via `backstage.pluginPackage`. For example: @@ -161,9 +163,9 @@ None ## Alternatives -### Simplified Library Relationships +### Role-based Relationships -Rather than listing libraries for each role, we could simply have an array of libraries that are available for the plugin: +Rather than the proposed listing of related packages, we list packages by role instead. For example: ```json { @@ -174,21 +176,17 @@ Rather than listing libraries for each role, we could simply have an array of li "pluginPackages": { "frontend-plugin": "@backstage/plugin-catalog", "backend-plugin": "@backstage/plugin-catalog-backend", - "libraries": [ - "@backstage/plugin-catalog-react", - "@backstage/plugin-catalog-node", - "@backstage/plugin-catalog-common" - ] + "web-library": "@backstage/plugin-catalog-react", + "node-library": "@backstage/plugin-catalog-node", + "common-library": "@backstage/plugin-catalog-common" } } } ``` -A benefit of this approach is that it keeps the metadata simpler and reduces the need for conflict resolution logic since we can use the union of all listed library packages. +A benefit of this approach is that we know the role of each package upfront, although we'd likely want to validate the role of each package either way. -It also allows for the use-case of having multiple libraries of the same role, in case that would provide a benefit. Examples of this are the `@backstage/catalog-client` and `@backstage/catalog-model` packages. - -A downside of this approach could be that it may encourage a larger number of library packages, which is not necessarily what we want. Another downside is that the role of each package is not immediately available. +Another benefit is that there's a more strict requirement for only having a single package per role for each plugin, although this can also be considered a downside and limiting flexibility. ### Separate Metadata File From 83c4251d0e62d9d9e10e8304dabefe0419af0138 Mon Sep 17 00:00:00 2001 From: debsmita1 Date: Thu, 23 May 2024 17:41:37 +0530 Subject: [PATCH 07/46] adds icons to status component Signed-off-by: debsmita1 --- .changeset/spotty-ravens-perform.md | 5 + .../src/components/Status/Status.test.tsx | 28 ++- .../src/components/Status/Status.tsx | 168 ++++++++++++------ .../components/Status/icons/AbortedIcon.tsx | 36 ++++ .../components/Status/icons/PendingIcon.tsx | 36 ++++ .../components/Status/icons/RunningIcon.tsx | 36 ++++ 6 files changed, 253 insertions(+), 56 deletions(-) create mode 100644 .changeset/spotty-ravens-perform.md create mode 100644 packages/core-components/src/components/Status/icons/AbortedIcon.tsx create mode 100644 packages/core-components/src/components/Status/icons/PendingIcon.tsx create mode 100644 packages/core-components/src/components/Status/icons/RunningIcon.tsx diff --git a/.changeset/spotty-ravens-perform.md b/.changeset/spotty-ravens-perform.md new file mode 100644 index 0000000000..507561c11c --- /dev/null +++ b/.changeset/spotty-ravens-perform.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Adds icons to status component diff --git a/packages/core-components/src/components/Status/Status.test.tsx b/packages/core-components/src/components/Status/Status.test.tsx index c1e1d42af2..34f1a587bd 100644 --- a/packages/core-components/src/components/Status/Status.test.tsx +++ b/packages/core-components/src/components/Status/Status.test.tsx @@ -28,42 +28,58 @@ import { describe('', () => { it('renders without exploding', async () => { - const { getByLabelText } = await renderInTestApp(); + const { getByLabelText, getByTestId } = await renderInTestApp(); expect(getByLabelText('Status ok')).toBeInTheDocument(); + expect(getByTestId('status-ok')).toBeInTheDocument(); }); }); describe('', () => { it('renders without exploding', async () => { - const { getByLabelText } = await renderInTestApp(); + const { getByLabelText, getByTestId } = await renderInTestApp( + , + ); expect(getByLabelText('Status warning')).toBeInTheDocument(); + expect(getByTestId('status-warning')).toBeInTheDocument(); }); }); describe('', () => { it('renders without exploding', async () => { - const { getByLabelText } = await renderInTestApp(); + const { getByLabelText, getByTestId } = await renderInTestApp( + , + ); expect(getByLabelText('Status error')).toBeInTheDocument(); + expect(getByTestId('status-error')).toBeInTheDocument(); }); }); describe('', () => { it('renders without exploding', async () => { - const { getByLabelText } = await renderInTestApp(); + const { getByLabelText, getByTestId } = await renderInTestApp( + , + ); expect(getByLabelText('Status pending')).toBeInTheDocument(); + expect(getByTestId('status-pending')).toBeInTheDocument(); }); }); describe('', () => { it('renders without exploding', async () => { - const { getByLabelText } = await renderInTestApp(); + const { getByLabelText, getByTestId } = await renderInTestApp( + , + ); expect(getByLabelText('Status running')).toBeInTheDocument(); + expect(getByTestId('status-running')).toBeInTheDocument(); }); }); describe('', () => { it('renders without exploding', async () => { - const { getByLabelText } = await renderInTestApp(); + const { getByLabelText, getByTestId } = await renderInTestApp( + , + ); expect(getByLabelText('Status aborted')).toBeInTheDocument(); + expect(getByTestId('status-aborted')).toBeInTheDocument(); }); }); diff --git a/packages/core-components/src/components/Status/Status.tsx b/packages/core-components/src/components/Status/Status.tsx index 615eed6aec..63e3d3d3a6 100644 --- a/packages/core-components/src/components/Status/Status.tsx +++ b/packages/core-components/src/components/Status/Status.tsx @@ -16,8 +16,14 @@ import { makeStyles } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; +import CheckCircleOutline from '@material-ui/icons/CheckCircleOutline'; +import WarningOutline from '@material-ui/icons/ReportProblemOutlined'; +import ErrorOutline from '@material-ui/icons/ErrorOutline'; import classNames from 'classnames'; import React, { PropsWithChildren } from 'react'; +import { PendingIcon } from './icons/PendingIcon'; +import { RunningIcon } from './icons/RunningIcon'; +import { AbortedIcon } from './icons/AbortedIcon'; export type StatusClassKey = | 'status' @@ -32,123 +38,185 @@ const useStyles = makeStyles( theme => ({ status: { fontWeight: theme.typography.fontWeightMedium, - '&::before': { - width: '0.7em', - height: '0.7em', - display: 'inline-block', - marginRight: theme.spacing(1), - borderRadius: '50%', - content: '""', - }, + alignItems: 'baseline', + display: 'flex', + }, + statusIcon: { + flexShrink: 0, + position: 'relative', + top: '0.125em', + marginRight: theme.spacing(1), + }, + statusIconSize: { + width: '0.8em', + height: '0.8em', + }, + statusIconSizeForImg: { + width: '1.2em', + height: '1.2em', }, ok: { - '&::before': { - backgroundColor: theme.palette.status.ok, - }, + fill: theme.palette.status.ok || '#3E8635', }, warning: { - '&::before': { - backgroundColor: theme.palette.status.warning, - }, + fill: theme.palette.status.warning || '#F0AB00', }, error: { - '&::before': { - backgroundColor: theme.palette.status.error, - }, + fill: theme.palette.status.error || '#C9190B', }, pending: { - '&::before': { - backgroundColor: theme.palette.status.pending, - }, + fill: theme.palette.status.aborted || '#6A6E73', }, running: { - '&::before': { - backgroundColor: theme.palette.status.running, - }, + fill: theme.palette.status.aborted || '#6A6E73', }, aborted: { - '&::before': { - backgroundColor: theme.palette.status.aborted, - }, + fill: theme.palette.status.aborted || '#6A6E73', }, }), { name: 'BackstageStatus' }, ); export function StatusOK(props: PropsWithChildren<{}>) { - const classes = useStyles(props); + const { children, ...otherProps } = props; + const classes = useStyles(otherProps); return ( ); } export function StatusWarning(props: PropsWithChildren<{}>) { - const classes = useStyles(props); + const { children, ...otherProps } = props; + const classes = useStyles(otherProps); return ( ); } export function StatusError(props: PropsWithChildren<{}>) { - const classes = useStyles(props); + const { children, ...otherProps } = props; + const classes = useStyles(otherProps); return ( ); } export function StatusPending(props: PropsWithChildren<{}>) { - const classes = useStyles(props); + const { children, ...otherProps } = props; + const classes = useStyles(otherProps); return ( ); } export function StatusRunning(props: PropsWithChildren<{}>) { - const classes = useStyles(props); + const { children, ...otherProps } = props; + const classes = useStyles(otherProps); return ( ); } export function StatusAborted(props: PropsWithChildren<{}>) { - const classes = useStyles(props); + const { children, ...otherProps } = props; + const classes = useStyles(otherProps); return ( ); } diff --git a/packages/core-components/src/components/Status/icons/AbortedIcon.tsx b/packages/core-components/src/components/Status/icons/AbortedIcon.tsx new file mode 100644 index 0000000000..397f613e4a --- /dev/null +++ b/packages/core-components/src/components/Status/icons/AbortedIcon.tsx @@ -0,0 +1,36 @@ +/* + * 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 React from 'react'; + +export const AbortedIcon = ({ + className, + dataTestId, +}: { + className: string; + dataTestId: string; +}): React.ReactElement => { + return ( + + + + ); +}; diff --git a/packages/core-components/src/components/Status/icons/PendingIcon.tsx b/packages/core-components/src/components/Status/icons/PendingIcon.tsx new file mode 100644 index 0000000000..b98249947b --- /dev/null +++ b/packages/core-components/src/components/Status/icons/PendingIcon.tsx @@ -0,0 +1,36 @@ +/* + * 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 React from 'react'; + +export const PendingIcon = ({ + className, + dataTestId, +}: { + className: string; + dataTestId: string; +}): React.ReactElement => { + return ( + + + + ); +}; diff --git a/packages/core-components/src/components/Status/icons/RunningIcon.tsx b/packages/core-components/src/components/Status/icons/RunningIcon.tsx new file mode 100644 index 0000000000..8477d01bdc --- /dev/null +++ b/packages/core-components/src/components/Status/icons/RunningIcon.tsx @@ -0,0 +1,36 @@ +/* + * 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 React from 'react'; + +export const RunningIcon = ({ + className, + dataTestId, +}: { + className: string; + dataTestId: string; +}): React.ReactElement => { + return ( + + + + ); +}; From be1014d2294f8a7922741e9d79946bf039e01b51 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Fri, 7 Jun 2024 19:47:06 -0500 Subject: [PATCH 08/46] Removed deprecated `GitHub` cased code Signed-off-by: Andre Wanlin --- .changeset/nasty-roses-flash.md | 12 ++++ packages/integration/src/github/deprecated.ts | 71 ------------------- 2 files changed, 12 insertions(+), 71 deletions(-) create mode 100644 .changeset/nasty-roses-flash.md delete mode 100644 packages/integration/src/github/deprecated.ts diff --git a/.changeset/nasty-roses-flash.md b/.changeset/nasty-roses-flash.md new file mode 100644 index 0000000000..50ac7f2e50 --- /dev/null +++ b/.changeset/nasty-roses-flash.md @@ -0,0 +1,12 @@ +--- +'@backstage/integration': patch +--- + +**BREAKING** Removed deprecated code from when casing was changed from `GitHub` to `Github` nearly two years ago. The following items have been removed: + +- `getGitHubFileFetchUrl` (use `getGithubFileFetchUrl` instead) +- `GitHubIntegrationConfig` (use `GithubIntegrationConfig` instead) +- `GitHubIntegration` (use `GithubIntegration` instead) +- `readGitHubIntegrationConfig` (use `readGithubIntegrationConfig` instead) +- `readGitHubIntegrationConfigs` (use `readGithubIntegrationConfigs` instead) +- `replaceGitHubUrlType` (use `replaceGithubUrlType` instead) diff --git a/packages/integration/src/github/deprecated.ts b/packages/integration/src/github/deprecated.ts deleted file mode 100644 index 127040c1a7..0000000000 --- a/packages/integration/src/github/deprecated.ts +++ /dev/null @@ -1,71 +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 { - GithubIntegrationConfig, - readGithubIntegrationConfig, - readGithubIntegrationConfigs, -} from './config'; -import { getGithubFileFetchUrl } from './core'; -import { GithubIntegration, replaceGithubUrlType } from './GithubIntegration'; -import { ScmIntegrationsFactory } from '../types'; - -/** - * @public - * @deprecated Use {@link getGithubFileFetchUrl} instead. - */ -export const getGitHubFileFetchUrl = getGithubFileFetchUrl; - -/** - * @public - * @deprecated Use {@link GithubIntegrationConfig} instead. - */ -export type GitHubIntegrationConfig = GithubIntegrationConfig; - -/** - * @public - * @deprecated Use {@link GithubIntegration} instead. - */ -export class GitHubIntegration extends GithubIntegration { - static factory: ScmIntegrationsFactory = - GithubIntegration.factory; - - constructor(integrationConfig: GitHubIntegrationConfig) { - super(integrationConfig as GithubIntegrationConfig); - } - - get config(): GitHubIntegrationConfig { - return super.config as GitHubIntegrationConfig; - } -} - -/** - * @public - * @deprecated Use {@link readGithubIntegrationConfig} instead. - */ -export const readGitHubIntegrationConfig = readGithubIntegrationConfig; - -/** - * @public - * @deprecated Use {@link readGithubIntegrationConfigs} instead. - */ -export const readGitHubIntegrationConfigs = readGithubIntegrationConfigs; - -/** - * @public - * @deprecated Use {@link replaceGithubUrlType} instead. - */ -export const replaceGitHubUrlType = replaceGithubUrlType; From 3e0124dff2065fc5df8c5864b91fcb43e760f3d4 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Sat, 8 Jun 2024 11:50:47 -0500 Subject: [PATCH 09/46] Removed export Signed-off-by: Andre Wanlin --- packages/integration/src/github/index.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/integration/src/github/index.ts b/packages/integration/src/github/index.ts index 816b0d2ff9..ea6f18f2e0 100644 --- a/packages/integration/src/github/index.ts +++ b/packages/integration/src/github/index.ts @@ -31,5 +31,3 @@ export type { GithubCredentialType, } from './types'; export { GithubIntegration, replaceGithubUrlType } from './GithubIntegration'; - -export * from './deprecated'; From 01e646a032b65265ebea63dfba7a47eb7e5d867e Mon Sep 17 00:00:00 2001 From: Johan Hammar Date: Sun, 9 Jun 2024 18:27:20 +0200 Subject: [PATCH 10/46] fix: fix broken node-postgres url Signed-off-by: Johan Hammar --- docs/deployment/flightcontrol.md | 2 +- .../create-app/templates/default-app/app-config.production.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/deployment/flightcontrol.md b/docs/deployment/flightcontrol.md index 6078d931fb..5d59371b47 100644 --- a/docs/deployment/flightcontrol.md +++ b/docs/deployment/flightcontrol.md @@ -123,7 +123,7 @@ backend: # all interfaces, the most permissive setting. The right value depends on your specific deployment. listen: ':7007' - # config options: https://node-postgres.com/api/client + # config options: https://node-postgres.com/apis/client database: client: pg pluginDivisionMode: 'schema' diff --git a/packages/create-app/templates/default-app/app-config.production.yaml b/packages/create-app/templates/default-app/app-config.production.yaml index 05b02acd4f..5532d9067e 100644 --- a/packages/create-app/templates/default-app/app-config.production.yaml +++ b/packages/create-app/templates/default-app/app-config.production.yaml @@ -13,7 +13,7 @@ backend: # all interfaces, the most permissive setting. The right value depends on your specific deployment. listen: ':7007' - # config options: https://node-postgres.com/api/client + # config options: https://node-postgres.com/apis/client database: client: pg connection: From 254209fa7ea64ebf95d45311d75384e4734bdc53 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Sun, 9 Jun 2024 15:21:24 -0500 Subject: [PATCH 11/46] Updated API Report Signed-off-by: Andre Wanlin --- packages/integration/api-report.md | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/packages/integration/api-report.md b/packages/integration/api-report.md index 4945847751..ef2247c2de 100644 --- a/packages/integration/api-report.md +++ b/packages/integration/api-report.md @@ -479,9 +479,6 @@ export function getGiteaRequestOptions(config: GiteaIntegrationConfig): { headers?: Record; }; -// @public @deprecated (undocumented) -export const getGitHubFileFetchUrl: typeof getGithubFileFetchUrl; - // @public export function getGithubFileFetchUrl( url: string, @@ -604,15 +601,6 @@ export interface GithubCredentialsProvider { // @public export type GithubCredentialType = 'app' | 'token'; -// @public @deprecated (undocumented) -export class GitHubIntegration extends GithubIntegration { - constructor(integrationConfig: GitHubIntegrationConfig); - // (undocumented) - get config(): GitHubIntegrationConfig; - // (undocumented) - static factory: ScmIntegrationsFactory; -} - // @public export class GithubIntegration implements ScmIntegration { constructor(integrationConfig: GithubIntegrationConfig); @@ -636,9 +624,6 @@ export class GithubIntegration implements ScmIntegration { get type(): string; } -// @public @deprecated (undocumented) -export type GitHubIntegrationConfig = GithubIntegrationConfig; - // @public export type GithubIntegrationConfig = { host: string; @@ -877,17 +862,11 @@ export function readGerritIntegrationConfigs( // @public export function readGiteaConfig(config: Config): GiteaIntegrationConfig; -// @public @deprecated (undocumented) -export const readGitHubIntegrationConfig: typeof readGithubIntegrationConfig; - // @public export function readGithubIntegrationConfig( config: Config, ): GithubIntegrationConfig; -// @public @deprecated (undocumented) -export const readGitHubIntegrationConfigs: typeof readGithubIntegrationConfigs; - // @public export function readGithubIntegrationConfigs( configs: Config[], @@ -911,9 +890,6 @@ export function readGoogleGcsIntegrationConfig( // @public export function readHarnessConfig(config: Config): HarnessIntegrationConfig; -// @public @deprecated (undocumented) -export const replaceGitHubUrlType: typeof replaceGithubUrlType; - // @public export function replaceGithubUrlType( url: string, From 0d12b9e85b704186ae7fb616cec4686c93023a08 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Mon, 10 Jun 2024 11:17:40 -0500 Subject: [PATCH 12/46] Update .changeset/nasty-roses-flash.md Co-authored-by: Vincenzo Scamporlino Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .changeset/nasty-roses-flash.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/nasty-roses-flash.md b/.changeset/nasty-roses-flash.md index 50ac7f2e50..4c09a7e47f 100644 --- a/.changeset/nasty-roses-flash.md +++ b/.changeset/nasty-roses-flash.md @@ -1,5 +1,5 @@ --- -'@backstage/integration': patch +'@backstage/integration': minor --- **BREAKING** Removed deprecated code from when casing was changed from `GitHub` to `Github` nearly two years ago. The following items have been removed: From 3ddc81532004fdabee2d5774a16c792fff86cc6b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 10 Jun 2024 19:56:09 +0200 Subject: [PATCH 13/46] beps/0009: further simplification of plugin package listing Signed-off-by: Patrik Oldsberg --- beps/0009-plugin-metadata/README.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/beps/0009-plugin-metadata/README.md b/beps/0009-plugin-metadata/README.md index b6ecd966d9..c019211123 100644 --- a/beps/0009-plugin-metadata/README.md +++ b/beps/0009-plugin-metadata/README.md @@ -95,7 +95,7 @@ Packages that are part of the same plugin should always be managed within the sa Each plugin package must define a `backstage.pluginId` field, which is the same identifier as is used in the implementation of the plugin. This field is inferred from the package name by the `backstage-cli repo fix` command if it is not present. It should only be defined for plugin package, for example `@backstage/errors` should not define a plugin ID. The `backstage.pluginId` field is required when publishing a package with a plugin or module role, or a library role with "plugin" in its name. -The package relationships are defined in the `backstage.pluginPackages` field. The value of the fields in an object with three optional keys, `frontend`, `backend`, and `libraries`. The `frontend` and `backend` fields must be the name of the frontend and backend plugin packages if present, while the `libraries` is an array of all library packages that are related to this plugin. For example: +The package relationships are defined in the `backstage.pluginPackages` field. The value of the field is an array with the names of all packages that belong to this plugin. For example: ```json { @@ -103,15 +103,13 @@ The package relationships are defined in the `backstage.pluginPackages` field. T "backstage": { "role": "frontend-plugin", "pluginId": "catalog", - "pluginPackages": { - "frontend": "@backstage/plugin-catalog", - "backend": "@backstage/plugin-catalog-backend", - "libraries": [ - "@backstage/plugin-catalog-react", - "@backstage/plugin-catalog-node", - "@backstage/plugin-catalog-common" - ] - } + "pluginPackages": [ + "@backstage/plugin-catalog", + "@backstage/plugin-catalog-backend", + "@backstage/plugin-catalog-react", + "@backstage/plugin-catalog-node", + "@backstage/plugin-catalog-common" + ] } } ``` From 34daaea7209d2af4fd44fc63df15fafe54297c34 Mon Sep 17 00:00:00 2001 From: Johan Hammar Date: Mon, 10 Jun 2024 21:40:10 +0200 Subject: [PATCH 14/46] Add changeset Signed-off-by: Johan Hammar --- .changeset/rare-frogs-beam.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/rare-frogs-beam.md diff --git a/.changeset/rare-frogs-beam.md b/.changeset/rare-frogs-beam.md new file mode 100644 index 0000000000..981c0c00ce --- /dev/null +++ b/.changeset/rare-frogs-beam.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Fixed a broken link to the node-postgres documentation From 792612b46dfb036d9c183fa1349f5f43bbabf32c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Sep=C3=BAlveda?= Date: Mon, 10 Jun 2024 17:13:49 -0400 Subject: [PATCH 15/46] Update gitlab.examples.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit documentation fix. The correct name is `protect`. `protected` is use for variables. Signed-off-by: César Sepúlveda --- .../src/actions/gitlab.examples.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.examples.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.examples.ts index 9746bfabe2..f7a957c32e 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.examples.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.examples.ts @@ -121,12 +121,12 @@ export const examples: TemplateExample[] = [ { name: 'dev', create: true, - protected: true, + protect: true, ref: 'master', }, { name: 'master', - protected: true, + protect: true, }, ], }, From dcb75ee4c0c8b1b36d809510a4c93e5ccc2b1b91 Mon Sep 17 00:00:00 2001 From: "Stijn Brouwers (EISMEA)" Date: Sat, 18 May 2024 09:00:33 +0200 Subject: [PATCH 16/46] bugfix(code-commit-integration): Fix host for codecommit integrations Signed-off-by: Stijn Brouwers (EISMEA) --- docs/integrations/aws-codecommit/locations.md | 8 +++---- .../AwsCodeCommitIntegration.test.ts | 15 ++++++------ .../src/awsCodeCommit/config.test.ts | 15 ++++++------ .../integration/src/awsCodeCommit/config.ts | 24 +++++++++---------- 4 files changed, 29 insertions(+), 33 deletions(-) diff --git a/docs/integrations/aws-codecommit/locations.md b/docs/integrations/aws-codecommit/locations.md index 05a13e5b21..c91c995289 100644 --- a/docs/integrations/aws-codecommit/locations.md +++ b/docs/integrations/aws-codecommit/locations.md @@ -20,7 +20,8 @@ To use this integration, add configuration to your `app-config.yaml`: ```yaml integrations: awsCodeCommit: - - accessKeyId: ${AWS_ACCESS_KEY_ID} + - region: eu-west-1 + accessKeyId: ${AWS_ACCESS_KEY_ID} secretAccessKey: ${AWS_SECRET_ACCESS_KEY} ``` @@ -34,10 +35,7 @@ instruct the AWS CodeCommit reader to assume a role before accessing CodeCommit: ```yaml integrations: awsCodeCommit: - - accessKeyId: ${AWS_ACCESS_KEY_ID} - secretAccessKey: ${AWS_SECRET_ACCESS_KEY} + - region: eu-west-1 roleArn: 'arn:aws:iam::xxxxxxxxxxxx:role/example-role' externalId: 'some-id' # optional ``` - -When no entries are added, the AWS CodeCommit reader will add a default entry that uses the [standard credentials provider chain](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html). diff --git a/packages/integration/src/awsCodeCommit/AwsCodeCommitIntegration.test.ts b/packages/integration/src/awsCodeCommit/AwsCodeCommitIntegration.test.ts index 14b3c6c73b..76ccd59af6 100644 --- a/packages/integration/src/awsCodeCommit/AwsCodeCommitIntegration.test.ts +++ b/packages/integration/src/awsCodeCommit/AwsCodeCommitIntegration.test.ts @@ -30,30 +30,29 @@ describe('AwsCodeCommitIntegration', () => { secretAccessKey: ' secret key ', roleArn: `role arn`, externalId: `external id`, + region: `region`, }, ], }, }), }); expect(integrations.list().length).toBe(1); // including default - expect(integrations.list()[0].config.host).toBe(AMAZON_AWS_CODECOMMIT_HOST); + expect(integrations.list()[0].config.host).toBe( + `region.${AMAZON_AWS_CODECOMMIT_HOST}`, + ); expect(integrations.list()[0].config.accessKeyId).toBe('access key'); expect(integrations.list()[0].config.secretAccessKey).toBe('secret key'); expect(integrations.list()[0].config.roleArn).toBe(`role arn`); expect(integrations.list()[0].config.externalId).toBe(`external id`); + expect(integrations.list()[0].config.region).toBe(`region`); }); - it('has a working factory with default values when no data provided', () => { + it('does not have a working factory with default values when no data provided', () => { const integrations = AwsCodeCommitIntegration.factory({ config: new ConfigReader({ integrations: {}, }), }); - expect(integrations.list().length).toBe(1); // including default - expect(integrations.list()[0].config.host).toBe(AMAZON_AWS_CODECOMMIT_HOST); - expect(integrations.list()[0].config.accessKeyId).toBeUndefined(); - expect(integrations.list()[0].config.secretAccessKey).toBeUndefined(); - expect(integrations.list()[0].config.roleArn).toBeUndefined(); - expect(integrations.list()[0].config.externalId).toBeUndefined(); + expect(integrations.list().length).toBe(0); // including default }); it('returns the basics', () => { diff --git a/packages/integration/src/awsCodeCommit/config.test.ts b/packages/integration/src/awsCodeCommit/config.test.ts index 217485b45e..637189f1f8 100644 --- a/packages/integration/src/awsCodeCommit/config.test.ts +++ b/packages/integration/src/awsCodeCommit/config.test.ts @@ -31,7 +31,8 @@ describe('readAwsCodeCommitIntegrationConfig', () => { it('reads all values (default)', () => { const output = readAwsCodeCommitIntegrationConfig(buildConfig({})); expect(output).toEqual({ - host: AMAZON_AWS_CODECOMMIT_HOST, + host: `us-east-1.${AMAZON_AWS_CODECOMMIT_HOST}`, + region: `us-east-1`, }); }); @@ -42,14 +43,16 @@ describe('readAwsCodeCommitIntegrationConfig', () => { secretAccessKey: 'fake-secret-key', externalId: 'fake-external-id', roleArn: 'fake-role-arn', + region: 'fake-region', }), ); expect(output).toEqual({ - host: AMAZON_AWS_CODECOMMIT_HOST, + host: `fake-region.${AMAZON_AWS_CODECOMMIT_HOST}`, accessKeyId: 'fake-key', secretAccessKey: 'fake-secret-key', externalId: 'fake-external-id', roleArn: 'fake-role-arn', + region: 'fake-region', }); }); }); @@ -70,6 +73,7 @@ describe('readAwsCodeCommitIntegrationConfigs', () => { secretAccessKey: 'secret', externalId: 'external-id', roleArn: 'role-arn', + region: 'region', }, ]), ); @@ -79,15 +83,12 @@ describe('readAwsCodeCommitIntegrationConfigs', () => { secretAccessKey: 'secret', externalId: 'external-id', roleArn: 'role-arn', + region: 'region', }); }); it('adds a default entry when missing', () => { const output = readAwsCodeCommitIntegrationConfigs(buildConfig([])); - expect(output).toEqual([ - { - host: AMAZON_AWS_CODECOMMIT_HOST, - }, - ]); + expect(output).toEqual([]); }); }); diff --git a/packages/integration/src/awsCodeCommit/config.ts b/packages/integration/src/awsCodeCommit/config.ts index 0ebd62519f..9b8acccb6f 100644 --- a/packages/integration/src/awsCodeCommit/config.ts +++ b/packages/integration/src/awsCodeCommit/config.ts @@ -48,6 +48,11 @@ export type AwsCodeCommitIntegrationConfig = { * (Optional) External ID to use when assuming role */ externalId?: string; + + /** + * region to use for AWS (default: us-east-1) + */ + region: string; }; /** @@ -64,7 +69,10 @@ export function readAwsCodeCommitIntegrationConfig( const secretAccessKey = config.getOptionalString('secretAccessKey')?.trim(); const roleArn = config.getOptionalString('roleArn'); const externalId = config.getOptionalString('externalId'); - const host = AMAZON_AWS_CODECOMMIT_HOST; + const region = config.getOptionalString('region') || 'us-east-1'; + const host = + config.getOptionalString('host') || + `${region}.${AMAZON_AWS_CODECOMMIT_HOST}`; return { host, @@ -72,6 +80,7 @@ export function readAwsCodeCommitIntegrationConfig( secretAccessKey, roleArn, externalId, + region, }; } @@ -85,16 +94,5 @@ export function readAwsCodeCommitIntegrationConfig( export function readAwsCodeCommitIntegrationConfigs( configs: Config[], ): AwsCodeCommitIntegrationConfig[] { - // First read all the explicit integrations - const result = configs.map(readAwsCodeCommitIntegrationConfig); - - // If no explicit console.aws.amazon.com integration was added, put one in the list as - // a convenience - if (!result.some(c => c.host === AMAZON_AWS_CODECOMMIT_HOST)) { - result.push({ - host: AMAZON_AWS_CODECOMMIT_HOST, - }); - } - - return result; + return configs.map(readAwsCodeCommitIntegrationConfig); } From 786a8d0443a1d3b4ac65ab97dfbaefc2df263594 Mon Sep 17 00:00:00 2001 From: "Stijn Brouwers (EISMEA)" Date: Sat, 18 May 2024 09:24:29 +0200 Subject: [PATCH 17/46] feat(codecommit-integration): Make region mandatory Signed-off-by: Stijn Brouwers (EISMEA) --- docs/integrations/aws-codecommit/locations.md | 4 ++++ packages/integration/src/awsCodeCommit/config.test.ts | 4 +++- packages/integration/src/awsCodeCommit/config.ts | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/integrations/aws-codecommit/locations.md b/docs/integrations/aws-codecommit/locations.md index c91c995289..42b45f7905 100644 --- a/docs/integrations/aws-codecommit/locations.md +++ b/docs/integrations/aws-codecommit/locations.md @@ -39,3 +39,7 @@ integrations: roleArn: 'arn:aws:iam::xxxxxxxxxxxx:role/example-role' externalId: 'some-id' # optional ``` + +Each entry is a structure with the following required elements: + +- `region`: The AWS region to connect to, to communicate with the CodeCommit services. If no host is provided, this value will be used to determine the host url. diff --git a/packages/integration/src/awsCodeCommit/config.test.ts b/packages/integration/src/awsCodeCommit/config.test.ts index 637189f1f8..5bac85545c 100644 --- a/packages/integration/src/awsCodeCommit/config.test.ts +++ b/packages/integration/src/awsCodeCommit/config.test.ts @@ -29,7 +29,9 @@ describe('readAwsCodeCommitIntegrationConfig', () => { } it('reads all values (default)', () => { - const output = readAwsCodeCommitIntegrationConfig(buildConfig({})); + const output = readAwsCodeCommitIntegrationConfig( + buildConfig({ region: 'us-east-1' }), + ); expect(output).toEqual({ host: `us-east-1.${AMAZON_AWS_CODECOMMIT_HOST}`, region: `us-east-1`, diff --git a/packages/integration/src/awsCodeCommit/config.ts b/packages/integration/src/awsCodeCommit/config.ts index 9b8acccb6f..83c449ad16 100644 --- a/packages/integration/src/awsCodeCommit/config.ts +++ b/packages/integration/src/awsCodeCommit/config.ts @@ -69,7 +69,7 @@ export function readAwsCodeCommitIntegrationConfig( const secretAccessKey = config.getOptionalString('secretAccessKey')?.trim(); const roleArn = config.getOptionalString('roleArn'); const externalId = config.getOptionalString('externalId'); - const region = config.getOptionalString('region') || 'us-east-1'; + const region = config.getString('region'); const host = config.getOptionalString('host') || `${region}.${AMAZON_AWS_CODECOMMIT_HOST}`; From 2b8ea39a92ebf2ed95213fd5bd19655ebf516ded Mon Sep 17 00:00:00 2001 From: "Stijn Brouwers (EISMEA)" Date: Tue, 21 May 2024 10:47:47 +0200 Subject: [PATCH 18/46] bugfix(codecommit-integration): Fix unit tests and generate api-reports Signed-off-by: Stijn Brouwers (EISMEA) --- .../reading/AwsCodeCommitUrlReader.test.ts | 81 +++++++++++++++++-- .../src/api/ScmIntegrationsApi.test.ts | 2 +- packages/integration/api-report.md | 1 + 3 files changed, 77 insertions(+), 7 deletions(-) diff --git a/packages/backend-common/src/reading/AwsCodeCommitUrlReader.test.ts b/packages/backend-common/src/reading/AwsCodeCommitUrlReader.test.ts index 6263d073fc..a17f0c6c61 100644 --- a/packages/backend-common/src/reading/AwsCodeCommitUrlReader.test.ts +++ b/packages/backend-common/src/reading/AwsCodeCommitUrlReader.test.ts @@ -212,7 +212,7 @@ describe('AwsCodeCommitUrlReader', () => { integrations: {}, }); - expect(entries).toHaveLength(1); + expect(entries).toHaveLength(0); }); it('creates a reader with credentials correctly configured', () => { @@ -221,6 +221,7 @@ describe('AwsCodeCommitUrlReader', () => { host: AMAZON_AWS_CODECOMMIT_HOST, accessKeyId: 'fakekey', secretAccessKey: 'fakekey', + region: 'fakeregion', }); const entries = createReader({ @@ -236,6 +237,7 @@ describe('AwsCodeCommitUrlReader', () => { const awsCodeCommitIntegrations = []; awsCodeCommitIntegrations.push({ host: AMAZON_AWS_CODECOMMIT_HOST, + region: 'fakeregion', }); const entries = createReader({ @@ -247,10 +249,32 @@ describe('AwsCodeCommitUrlReader', () => { expect(entries).toHaveLength(1); }); + it('creates a reader without a region', () => { + const awsCodeCommitIntegrations: any[] = []; + awsCodeCommitIntegrations.push({ + accessKeyId: 'fakekey', + secretAccessKey: 'fakekey', + }); + + expect(() => { + createReader({ + integrations: { + awsCodeCommit: awsCodeCommitIntegrations, + }, + }); + }).toThrow( + "Missing required config value at 'integrations.awsCodeCommit[0].region' in 'mock-config'", + ); + }); + describe('predicates', () => { const readers = createReader({ integrations: { - awsCodeCommit: [{}], + awsCodeCommit: [ + { + region: 'fakeregion', + }, + ], }, }); const predicate = readers[0].predicate; @@ -259,7 +283,7 @@ describe('AwsCodeCommitUrlReader', () => { expect( predicate( new URL( - 'https://eu-west-1.console.aws.amazon.com/codesuite/codecommit/repositories/my-repo', + 'https://fakeregion.console.aws.amazon.com/codesuite/codecommit/repositories/my-repo', ), ), ).toBe(true); @@ -269,12 +293,54 @@ describe('AwsCodeCommitUrlReader', () => { expect( predicate( new URL( - 'https://eu-west-1.console.aws.amazon.com/codesuite/codecommit/repositories/my-repo/browse/--/catalog-info.yaml?region=eu-west-1', + 'https://fakeregion.console.aws.amazon.com/codesuite/codecommit/repositories/my-repo/browse/--/catalog-info.yaml?region=eu-west-1', ), ), ).toBe(true); }); + it('returns true for a url with the full path and the correct host when the host overrules the region', () => { + const predicateWithHost = createReader({ + integrations: { + awsCodeCommit: [ + { + host: 'fakehost', + region: 'fakeregion', + }, + ], + }, + })[0].predicate; + + expect( + predicateWithHost( + new URL( + 'https://fakehost/codesuite/codecommit/repositories/my-repo/browse/--/catalog-info.yaml?region=eu-west-1', + ), + ), + ).toBe(true); + }); + + it('returns false for a url with the full path and the wrong host when the host overrules the region', () => { + const predicateWithHost = createReader({ + integrations: { + awsCodeCommit: [ + { + host: 'fakehost', + region: 'fakeregion', + }, + ], + }, + })[0].predicate; + + expect( + predicateWithHost( + new URL( + 'https://fakeregion.console.aws.amazon.com/codesuite/codecommit/repositories/my-repo/browse/--/catalog-info.yaml?region=eu-west-1', + ), + ), + ).toBe(false); + }); + it('returns false for an incorrect host', () => { expect(predicate(new URL('https://amazon.com'))).toBe(false); }); @@ -304,6 +370,7 @@ describe('AwsCodeCommitUrlReader', () => { host: 'amazonaws.com', accessKeyId: 'fake-access-key', secretAccessKey: 'fake-secret-key', + region: 'fakeregion', }, ], }, @@ -348,6 +415,7 @@ describe('AwsCodeCommitUrlReader', () => { host: AMAZON_AWS_CODECOMMIT_HOST, accessKeyId: 'fake-access-key', secretAccessKey: 'fake-secret-key', + region: 'fakeregion', }, ], }, @@ -403,6 +471,7 @@ describe('AwsCodeCommitUrlReader', () => { host: AMAZON_AWS_CODECOMMIT_HOST, accessKeyId: 'fake-access-key', secretAccessKey: 'fake-secret-key', + region: 'fakeregion', }, ], }, @@ -509,9 +578,9 @@ describe('AwsCodeCommitUrlReader', () => { }); const config = new ConfigReader({ - host: AMAZON_AWS_CODECOMMIT_HOST, accessKeyId: 'fake-access-key', secretAccessKey: 'fake-secret-key', + region: 'fakeregion', }); const credsManager = DefaultAwsCredentialsManager.fromConfig(config); @@ -527,7 +596,7 @@ describe('AwsCodeCommitUrlReader', () => { it('returns contents of a file in a repository', async () => { const response = await awsCodeCommitUrlReader.readTree( - 'https://eu-west-1.console.aws.amazon.com/codesuite/codecommit/repositories/my-test-techdocs', + 'https://fakeregion.console.aws.amazon.com/codesuite/codecommit/repositories/my-test-techdocs', ); const files = await response.files(); diff --git a/packages/integration-react/src/api/ScmIntegrationsApi.test.ts b/packages/integration-react/src/api/ScmIntegrationsApi.test.ts index 0a1f1b1b8f..fb53bbdb12 100644 --- a/packages/integration-react/src/api/ScmIntegrationsApi.test.ts +++ b/packages/integration-react/src/api/ScmIntegrationsApi.test.ts @@ -26,6 +26,6 @@ describe('scmIntegrationsApiRef', () => { it('should be instantiated', () => { const i = ScmIntegrationsApi.fromConfig(new ConfigReader({})); - expect(i.list().length).toBe(7); // The default ones + expect(i.list().length).toBe(6); // The default ones }); }); diff --git a/packages/integration/api-report.md b/packages/integration/api-report.md index 4945847751..e5a655a667 100644 --- a/packages/integration/api-report.md +++ b/packages/integration/api-report.md @@ -35,6 +35,7 @@ export type AwsCodeCommitIntegrationConfig = { secretAccessKey?: string; roleArn?: string; externalId?: string; + region: string; }; // @public From 23ee9abacc8992f2db36a66b5e399a55d2edc9e2 Mon Sep 17 00:00:00 2001 From: "Stijn Brouwers (EISMEA)" Date: Tue, 21 May 2024 11:02:24 +0200 Subject: [PATCH 19/46] bugfix(codecommit-integration): Add changeset Signed-off-by: Stijn Brouwers (EISMEA) --- .changeset/spicy-ears-raise.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/spicy-ears-raise.md diff --git a/.changeset/spicy-ears-raise.md b/.changeset/spicy-ears-raise.md new file mode 100644 index 0000000000..a53ed9c721 --- /dev/null +++ b/.changeset/spicy-ears-raise.md @@ -0,0 +1,7 @@ +--- +'@backstage/integration-react': patch +'@backstage/backend-common': patch +'@backstage/integration': patch +--- + +Fix AWS CodeCommit integration by allowing to change the host From 697c44f4db21a4ca1738636e51b60256dd5e13a7 Mon Sep 17 00:00:00 2001 From: "Stijn Brouwers (EISMEA)" Date: Thu, 30 May 2024 08:02:54 +0200 Subject: [PATCH 20/46] feat(codecommit-integration): Add some documentation to locations.md Signed-off-by: Stijn Brouwers (EISMEA) --- docs/integrations/aws-codecommit/locations.md | 46 ++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/docs/integrations/aws-codecommit/locations.md b/docs/integrations/aws-codecommit/locations.md index 42b45f7905..fc9d2cfb1c 100644 --- a/docs/integrations/aws-codecommit/locations.md +++ b/docs/integrations/aws-codecommit/locations.md @@ -17,6 +17,32 @@ plugin. To use this integration, add configuration to your `app-config.yaml`: +```yaml +integrations: + awsCodeCommit: + - region: eu-west-1 +``` + +This most basic example can only be used if you are running Backstage on an instance that has an IAM identity with the following policies: + +``` +{ + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "codecommit:GetFile", + "codecommit:GetFolder" + ], + "Resource": "*", + "Effect": "Allow" + } + ] +} +``` + +If you are running Backstage outside AWS and want to use Access key authentication, you can use the following configuration: + ```yaml integrations: awsCodeCommit: @@ -40,6 +66,22 @@ integrations: externalId: 'some-id' # optional ``` -Each entry is a structure with the following required elements: +Each entry is a structure with the following **required** elements: -- `region`: The AWS region to connect to, to communicate with the CodeCommit services. If no host is provided, this value will be used to determine the host url. +- `region`: The AWS region to connect to, to communicate with the CodeCommit services + +The configuration can also provide a `host` property like the other integrations. If it is not provided, it will be determined from the provided region. +i.e. When you provide `eu-west-1` as the region, Backstage will use the host `eu-west-1.console.aws.amazon.com` to check whether a provided url matches the integration. + +## Register an entity on AWS CodeCommit + +To register an entity that is stored in an AWS CodeCommit repository, you need to fetch the URL from the AWS Console: + +- Navigate to the Code Commit service in the AWS Console ([https://console.aws.amazon.com/codecommit/home](https://console.aws.amazon.com/codecommit/home)) +- _Optional: Make sure you select the correct region if you don't use the default one (us-east-1)_ +- Select the repository where the entity file is stored +- Inside the repository navigate to the backstage entity file (`catalog-info.yaml`) and open the file +- Now you can copy-paste the URL from your browser inside Backstage + +The format would be something like: +`https://{region}.console.aws.amazon.com/codesuite/codecommit/repositories/{reponame}/browse/refs/heads/{branch}/--{/path-to-entity-file}/catalog-info.yaml` From ad91b87b0acaf328a1aaa199245c06494381069d Mon Sep 17 00:00:00 2001 From: "Stijn Brouwers (EISMEA)" Date: Thu, 30 May 2024 08:04:21 +0200 Subject: [PATCH 21/46] docs(codecommit-integration): Fix url format in locations.md Signed-off-by: Stijn Brouwers (EISMEA) --- docs/integrations/aws-codecommit/locations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/aws-codecommit/locations.md b/docs/integrations/aws-codecommit/locations.md index fc9d2cfb1c..35187b1b89 100644 --- a/docs/integrations/aws-codecommit/locations.md +++ b/docs/integrations/aws-codecommit/locations.md @@ -84,4 +84,4 @@ To register an entity that is stored in an AWS CodeCommit repository, you need t - Now you can copy-paste the URL from your browser inside Backstage The format would be something like: -`https://{region}.console.aws.amazon.com/codesuite/codecommit/repositories/{reponame}/browse/refs/heads/{branch}/--{/path-to-entity-file}/catalog-info.yaml` +`https://{region}.console.aws.amazon.com/codesuite/codecommit/repositories/{reponame}/browse/refs/heads/{branch}/--/catalog-info.yaml` From 4a12560aabcfb459324398c115f9692b0c6267f4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 8 Jun 2024 11:13:25 +0200 Subject: [PATCH 22/46] cli: add backstage.pluginId to repo fix Signed-off-by: Patrik Oldsberg --- .../cli-node/src/monorepo/PackageGraph.ts | 1 + packages/cli/src/commands/repo/fix.ts | 68 +++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/packages/cli-node/src/monorepo/PackageGraph.ts b/packages/cli-node/src/monorepo/PackageGraph.ts index 68ba614c94..84012f0b91 100644 --- a/packages/cli-node/src/monorepo/PackageGraph.ts +++ b/packages/cli-node/src/monorepo/PackageGraph.ts @@ -46,6 +46,7 @@ export interface BackstagePackageJson { backstage?: { role?: PackageRole; moved?: string; + pluginId?: string; }; exports?: JsonValue; diff --git a/packages/cli/src/commands/repo/fix.ts b/packages/cli/src/commands/repo/fix.ts index 049f5a8416..ae1084127c 100644 --- a/packages/cli/src/commands/repo/fix.ts +++ b/packages/cli/src/commands/repo/fix.ts @@ -18,6 +18,7 @@ import { BackstagePackage, BackstagePackageJson, PackageGraph, + PackageRole, PackageRoles, } from '@backstage/cli-node'; import { OptionValues } from 'commander'; @@ -239,6 +240,72 @@ export function createRepositoryFieldFixer() { }; } +function guessPluginId(role: PackageRole, pkgName: string): string | undefined { + switch (role) { + case 'frontend': + case 'frontend-plugin': + return pkgName.match(/plugin-(.*)/)?.[1]; + case 'frontend-plugin-module': + return pkgName.match(/plugin-(.*)-module-/)?.[1]; + case 'backend-plugin': + return pkgName.match(/plugin-(.*)-backend$/)?.[1]; + case 'backend-plugin-module': + return pkgName.match(/plugin-(.*)-backend-module-/)?.[1]; + case 'common-library': + return pkgName.match(/plugin-(.*)-(?:common)$/)?.[1]; + case 'web-library': + return pkgName.match(/plugin-(.*)-(?:react|test-utils)/)?.[1]; + case 'node-library': + return pkgName.match(/plugin-(.*)-(?:node|backend)-?/)?.[1]; + default: + throw new Error(`Invalid backstage.role in ${pkgName}, got '${role}'`); + } +} + +export function fixPluginId(pkg: FixablePackage) { + const role = pkg.packageJson.backstage?.role; + if (!role) { + return; + } + + if (role === 'backend' || role === 'frontend' || role === 'cli') { + return; + } + + const currentId = pkg.packageJson.backstage?.pluginId; + if (currentId !== undefined) { + if (typeof currentId !== 'string') { + throw new Error( + `Invalid backstage.pluginId in ${pkg.packageJson.name}, must be a string`, + ); + } + return; + } + + const guessedPluginId = guessPluginId(role, pkg.packageJson.name); + if ( + !guessedPluginId && + (role === 'frontend-plugin' || + role === 'frontend-plugin-module' || + role === 'backend-plugin' || + role === 'backend-plugin-module') + ) { + const path = relativePath( + paths.targetRoot, + resolvePath(pkg.dir, 'package.json'), + ); + throw new Error( + `Failed to guess plugin ID for ${pkg.packageJson.name}, please set backstage.pluginId manually in ${path}`, + ); + } + + pkg.packageJson.backstage = { + ...pkg.packageJson.backstage, + pluginId: guessedPluginId, + }; + pkg.changed = true; +} + export async function command(opts: OptionValues): Promise { const packages = await readFixablePackages(); const fixRepositoryField = createRepositoryFieldFixer(); @@ -247,6 +314,7 @@ export async function command(opts: OptionValues): Promise { fixPackageExports(pkg); fixSideEffects(pkg); fixRepositoryField(pkg); + fixPluginId(pkg); } if (opts.check) { From c3cb8068b3f4a76d2141b69bf6e06de31db77524 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 8 Jun 2024 11:22:59 +0200 Subject: [PATCH 23/46] app-next-example-plugin: set pluginId Signed-off-by: Patrik Oldsberg --- packages/app-next-example-plugin/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/app-next-example-plugin/package.json b/packages/app-next-example-plugin/package.json index bca9420d69..be0d5fc8ee 100644 --- a/packages/app-next-example-plugin/package.json +++ b/packages/app-next-example-plugin/package.json @@ -3,7 +3,8 @@ "version": "0.0.12-next.1", "description": "Backstage internal example plugin", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "example" }, "publishConfig": { "access": "public", From 28128767428856b72248e4f744d8535357e83503 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 8 Jun 2024 11:57:45 +0200 Subject: [PATCH 24/46] cli: add plugin packages metadata fix Signed-off-by: Patrik Oldsberg --- .../cli-node/src/monorepo/PackageGraph.ts | 6 + packages/cli/src/commands/repo/fix.ts | 123 ++++++++++++++++++ 2 files changed, 129 insertions(+) diff --git a/packages/cli-node/src/monorepo/PackageGraph.ts b/packages/cli-node/src/monorepo/PackageGraph.ts index 84012f0b91..016704b9c9 100644 --- a/packages/cli-node/src/monorepo/PackageGraph.ts +++ b/packages/cli-node/src/monorepo/PackageGraph.ts @@ -47,6 +47,12 @@ export interface BackstagePackageJson { role?: PackageRole; moved?: string; pluginId?: string; + pluginPackage?: string; + pluginPackages?: { + frontend?: string; + backend?: string; + libraries?: string[]; + }; }; exports?: JsonValue; diff --git a/packages/cli/src/commands/repo/fix.ts b/packages/cli/src/commands/repo/fix.ts index ae1084127c..6572ed219e 100644 --- a/packages/cli/src/commands/repo/fix.ts +++ b/packages/cli/src/commands/repo/fix.ts @@ -306,6 +306,128 @@ export function fixPluginId(pkg: FixablePackage) { pkg.changed = true; } +export function fixPluginPackages( + pkg: FixablePackage, + repoPackages: FixablePackage[], +) { + const pkgBackstage = pkg.packageJson.backstage; + const role = pkgBackstage?.role; + if (!role) { + return; + } + + if (role === 'backend' || role === 'frontend' || role === 'cli') { + return; + } + + const pluginId = pkgBackstage.pluginId; + if (!pluginId) { + // Might be a plugin-less library, skip + if ( + role === 'common-library' || + role === 'web-library' || + role === 'node-library' + ) { + return; + } + throw new Error(`Missing backstage.pluginId in ${pkg.packageJson.name}`); + } + + if (role === 'backend-plugin-module' || role === 'frontend-plugin-module') { + const targetRole = role.replace('-module', ''); + + const pluginPkg = repoPackages.find( + p => + p.packageJson.backstage?.pluginId === pluginId && + p.packageJson.backstage?.role === targetRole, + ); + if (!pluginPkg) { + // If we can't find a matching package in the repo but one is declared, skip + if (pkgBackstage.pluginPackage) { + return; + } + const path = relativePath( + paths.targetRoot, + resolvePath(pkg.dir, 'package.json'), + ); + throw new Error( + `Failed to find plugin package for ${pkg.packageJson.name}, please set backstage.pluginPackage manually in ${path}`, + ); + } + + if (pkgBackstage.pluginPackage !== pluginPkg.packageJson.name) { + pkgBackstage.pluginPackage = pluginPkg.packageJson.name; + pkg.changed = true; + } + } else { + let frontend: string | undefined = undefined; + let backend: string | undefined = undefined; + let libraries: string[] | undefined = []; + + for (const repoPkg of repoPackages) { + if (repoPkg.packageJson.backstage?.pluginId !== pluginId) { + continue; + } + const repoPkgRole = repoPkg.packageJson.backstage?.role; + const repoPkgName = repoPkg.packageJson.name; + if (repoPkgRole === 'frontend-plugin') { + if (frontend) { + throw new Error( + `Duplicate frontend plugin for '${pluginId}', ${frontend} and ${repoPkgName}`, + ); + } + frontend = repoPkgName; + } else if (repoPkgRole === 'backend-plugin') { + if (backend) { + throw new Error( + `Duplicate backend plugin for '${pluginId}', ${backend} and ${repoPkgName}`, + ); + } + backend = repoPkgName; + } else if ( + repoPkgRole === 'common-library' || + repoPkgRole === 'web-library' || + repoPkgRole === 'node-library' + ) { + libraries.push(repoPkgName); + } + } + + if (libraries.length === 0) { + // If there are no libraries, avoid an empty array in package.json + libraries = undefined; + } else { + // Sort libraries to ensure consistent order + libraries.sort(); + } + + if (!pkgBackstage.pluginPackages) { + pkgBackstage.pluginPackages = { + frontend, + backend, + libraries, + }; + pkg.changed = true; + } else { + if (pkgBackstage.pluginPackages.frontend !== frontend) { + pkgBackstage.pluginPackages.frontend = frontend; + pkg.changed = true; + } + if (pkgBackstage.pluginPackages.backend !== backend) { + pkgBackstage.pluginPackages.backend = backend; + pkg.changed = true; + } + if ( + pkgBackstage.pluginPackages.libraries?.join(',') !== + libraries?.join(',') + ) { + pkgBackstage.pluginPackages.libraries = libraries; + pkg.changed = true; + } + } + } +} + export async function command(opts: OptionValues): Promise { const packages = await readFixablePackages(); const fixRepositoryField = createRepositoryFieldFixer(); @@ -315,6 +437,7 @@ export async function command(opts: OptionValues): Promise { fixSideEffects(pkg); fixRepositoryField(pkg); fixPluginId(pkg); + fixPluginPackages(pkg, packages); } if (opts.check) { From 09049a612b0127a8489118056e225833f7894450 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 8 Jun 2024 12:09:01 +0200 Subject: [PATCH 25/46] cli: run package fixers separately Signed-off-by: Patrik Oldsberg --- packages/cli/src/commands/repo/fix.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/packages/cli/src/commands/repo/fix.ts b/packages/cli/src/commands/repo/fix.ts index 6572ed219e..c96484e2ed 100644 --- a/packages/cli/src/commands/repo/fix.ts +++ b/packages/cli/src/commands/repo/fix.ts @@ -432,12 +432,18 @@ export async function command(opts: OptionValues): Promise { const packages = await readFixablePackages(); const fixRepositoryField = createRepositoryFieldFixer(); - for (const pkg of packages) { - fixPackageExports(pkg); - fixSideEffects(pkg); - fixRepositoryField(pkg); - fixPluginId(pkg); - fixPluginPackages(pkg, packages); + const fixers = [ + fixPackageExports, + fixSideEffects, + fixRepositoryField, + fixPluginId, + fixPluginPackages, + ]; + + for (const fixer of fixers) { + for (const pkg of packages) { + fixer(pkg, packages); + } } if (opts.check) { From cb61f04da8877eddc293fd6e348c133d3cfedeb6 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 8 Jun 2024 12:17:53 +0200 Subject: [PATCH 26/46] cli-node: document new package fields Signed-off-by: Patrik Oldsberg --- packages/cli-node/src/monorepo/PackageGraph.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/cli-node/src/monorepo/PackageGraph.ts b/packages/cli-node/src/monorepo/PackageGraph.ts index 016704b9c9..f6b563202e 100644 --- a/packages/cli-node/src/monorepo/PackageGraph.ts +++ b/packages/cli-node/src/monorepo/PackageGraph.ts @@ -46,8 +46,20 @@ export interface BackstagePackageJson { backstage?: { role?: PackageRole; moved?: string; + + /** + * The ID of the plugin if this is a plugin package. Must always be set for plugin and module packages, and may be set for library packages. + */ pluginId?: string; + + /** + * The parent plugin package of a module. Must always and only be set for module packages. + */ pluginPackage?: string; + + /** + * All packages that are part of the plugin. Must always and only be set for plugin packages and plugin library packages. + */ pluginPackages?: { frontend?: string; backend?: string; From f85a7f2a5a60faed5e2cb82282ccccea85861472 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 8 Jun 2024 12:21:19 +0200 Subject: [PATCH 27/46] cli: add --publish option for repo fix Signed-off-by: Patrik Oldsberg --- package.json | 2 +- packages/cli/src/commands/index.ts | 4 ++++ packages/cli/src/commands/repo/fix.ts | 15 ++++++++------- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 2951eb8540..c81cb98d34 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "dev": "yarn workspaces foreach -A --include example-backend --include example-app --parallel -v -i run start", "dev:next": "yarn workspaces foreach -A --include example-backend --include example-app-next --parallel -v -i run start", "docker-build": "yarn tsc && yarn workspace example-backend build && yarn workspace example-backend build-image", - "fix": "backstage-cli repo fix", + "fix": "backstage-cli repo fix --publish", "postinstall": "husky || true", "lint": "backstage-cli repo lint --since origin/master", "lint:all": "backstage-cli repo lint", diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index 3554ddfbef..25a3a4e26c 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -70,6 +70,10 @@ export function registerRepoCommand(program: Command) { command .command('fix') .description('Automatically fix packages in the project') + .option( + '--publish', + 'Enable additional fixes that only apply when publishing packages', + ) .option( '--check', 'Fail if any packages would have been changed by the command', diff --git a/packages/cli/src/commands/repo/fix.ts b/packages/cli/src/commands/repo/fix.ts index c96484e2ed..88070ceb8f 100644 --- a/packages/cli/src/commands/repo/fix.ts +++ b/packages/cli/src/commands/repo/fix.ts @@ -428,17 +428,18 @@ export function fixPluginPackages( } } +type PackageFixer = (pkg: FixablePackage, packages: FixablePackage[]) => void; + export async function command(opts: OptionValues): Promise { const packages = await readFixablePackages(); const fixRepositoryField = createRepositoryFieldFixer(); - const fixers = [ - fixPackageExports, - fixSideEffects, - fixRepositoryField, - fixPluginId, - fixPluginPackages, - ]; + const fixers: PackageFixer[] = [fixPackageExports, fixSideEffects]; + + // Fixers that only apply to repos that publish packages + if (opts.publish) { + fixers.push(fixRepositoryField, fixPluginId, fixPluginPackages); + } for (const fixer of fixers) { for (const pkg of packages) { From b0de760792453ee703624369672f884fe688d21c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 8 Jun 2024 12:36:29 +0200 Subject: [PATCH 28/46] cli: add package publishing preflight check Signed-off-by: Patrik Oldsberg --- packages/cli/src/commands/pack.ts | 7 +++ packages/cli/src/commands/repo/fix.ts | 9 +++- packages/cli/src/lib/publishing.ts | 71 +++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 packages/cli/src/lib/publishing.ts diff --git a/packages/cli/src/commands/pack.ts b/packages/cli/src/commands/pack.ts index 9c101e97fe..8fbbdb3d74 100644 --- a/packages/cli/src/commands/pack.ts +++ b/packages/cli/src/commands/pack.ts @@ -19,8 +19,15 @@ import { revertProductionPack, } from '../lib/packager/productionPack'; import { paths } from '../lib/paths'; +import fs from 'fs-extra'; +import { publishPreflightCheck } from '../lib/publishing'; export const pre = async () => { + publishPreflightCheck({ + dir: paths.targetDir, + packageJson: await fs.readJson(paths.resolveTarget('package.json')), + }); + await productionPack({ packageDir: paths.targetDir }); }; diff --git a/packages/cli/src/commands/repo/fix.ts b/packages/cli/src/commands/repo/fix.ts index 88070ceb8f..c170c5c3fd 100644 --- a/packages/cli/src/commands/repo/fix.ts +++ b/packages/cli/src/commands/repo/fix.ts @@ -25,6 +25,7 @@ import { OptionValues } from 'commander'; import fs from 'fs-extra'; import { resolve as resolvePath, posix, relative as relativePath } from 'path'; import { paths } from '../../lib/paths'; +import { publishPreflightCheck } from '../../lib/publishing'; /** * A mutable object representing a package.json file with potential fixes. @@ -438,7 +439,13 @@ export async function command(opts: OptionValues): Promise { // Fixers that only apply to repos that publish packages if (opts.publish) { - fixers.push(fixRepositoryField, fixPluginId, fixPluginPackages); + fixers.push( + fixRepositoryField, + fixPluginId, + fixPluginPackages, + // Run the publish preflight check too, to make sure we don't uncover errors during publishing + publishPreflightCheck, + ); } for (const fixer of fixers) { diff --git a/packages/cli/src/lib/publishing.ts b/packages/cli/src/lib/publishing.ts new file mode 100644 index 0000000000..20e4241985 --- /dev/null +++ b/packages/cli/src/lib/publishing.ts @@ -0,0 +1,71 @@ +/* + * 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 { BackstagePackage } from '@backstage/cli-node'; + +/** + * A basic check that throws if a packages doesn't contain required backstage metadata for publishing + */ +export function publishPreflightCheck(pkg: BackstagePackage): void { + const { name, backstage } = pkg.packageJson; + if (!backstage || !name) { + return; + } + + const { role } = backstage; + + if ( + role === 'backend-plugin' || + role === 'backend-plugin-module' || + role === 'frontend-plugin' || + role === 'frontend-plugin-module' + ) { + if (!backstage.pluginId) { + throw new Error( + `Plugin package ${name} is missing a backstage.pluginId, please run 'backstage-cli repo fix --publish'`, + ); + } + } + + if (role === 'backend-plugin' || role === 'frontend-plugin') { + if (!backstage.pluginPackages) { + throw new Error( + `Plugin package ${name} is missing a backstage.pluginPackages, please run 'backstage-cli repo fix --publish'`, + ); + } + } + + if ( + backstage.pluginId && + (role === 'common-library' || + role === 'node-library' || + role === 'web-library') + ) { + if (!backstage.pluginPackages) { + throw new Error( + `Plugin library package ${name} is missing a backstage.pluginPackages, please run 'backstage-cli repo fix --publish'`, + ); + } + } + + if (role === 'backend-plugin-module' || role === 'frontend-plugin-module') { + if (!backstage.pluginPackage) { + throw new Error( + `Plugin module package ${name} is missing a backstage.pluginPackage, please run 'backstage-cli repo fix --publish'`, + ); + } + } +} From 037d57735e529ae07b28ffdd349b223a234b6260 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 8 Jun 2024 13:26:12 +0200 Subject: [PATCH 29/46] cli: clearer error messaging for publish fix + look up core feature plugin package names Signed-off-by: Patrik Oldsberg --- packages/cli/src/commands/repo/fix.ts | 56 ++++++++++++++++++++------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/packages/cli/src/commands/repo/fix.ts b/packages/cli/src/commands/repo/fix.ts index c170c5c3fd..547ba1ca8a 100644 --- a/packages/cli/src/commands/repo/fix.ts +++ b/packages/cli/src/commands/repo/fix.ts @@ -259,7 +259,9 @@ function guessPluginId(role: PackageRole, pkgName: string): string | undefined { case 'node-library': return pkgName.match(/plugin-(.*)-(?:node|backend)-?/)?.[1]; default: - throw new Error(`Invalid backstage.role in ${pkgName}, got '${role}'`); + throw new Error( + `Invalid 'backstage.role' field in "${pkgName}", got '${role}'`, + ); } } @@ -277,7 +279,7 @@ export function fixPluginId(pkg: FixablePackage) { if (currentId !== undefined) { if (typeof currentId !== 'string') { throw new Error( - `Invalid backstage.pluginId in ${pkg.packageJson.name}, must be a string`, + `Invalid 'backstage.pluginId' field in "${pkg.packageJson.name}", must be a string`, ); } return; @@ -296,7 +298,7 @@ export function fixPluginId(pkg: FixablePackage) { resolvePath(pkg.dir, 'package.json'), ); throw new Error( - `Failed to guess plugin ID for ${pkg.packageJson.name}, please set backstage.pluginId manually in ${path}`, + `Failed to guess plugin ID for "${pkg.packageJson.name}", please set the 'backstage.pluginId' field manually in "${path}"`, ); } @@ -307,6 +309,22 @@ export function fixPluginId(pkg: FixablePackage) { pkg.changed = true; } +const backendPluginPackageNameByPluginId = new Map( + [ + 'app', + 'auth', + 'catalog', + 'events', + 'kubernetes', + 'notifications', + 'permission', + 'scaffolder', + 'search', + 'signals', + 'techdocs', + ].map(pluginId => [pluginId, `@backstage/plugin-${pluginId}-backend`]), +); + export function fixPluginPackages( pkg: FixablePackage, repoPackages: FixablePackage[], @@ -331,18 +349,23 @@ export function fixPluginPackages( ) { return; } - throw new Error(`Missing backstage.pluginId in ${pkg.packageJson.name}`); + throw new Error( + `Missing 'backstage.pluginId' field in "${pkg.packageJson.name}"`, + ); } if (role === 'backend-plugin-module' || role === 'frontend-plugin-module') { const targetRole = role.replace('-module', ''); - const pluginPkg = repoPackages.find( - p => - p.packageJson.backstage?.pluginId === pluginId && - p.packageJson.backstage?.role === targetRole, - ); - if (!pluginPkg) { + // Try to find a plugin package in the same repo, but otherwise fall back to looking up the package name by ID of @backstage/* plugins + const pluginPkgName = + repoPackages.find( + p => + p.packageJson.backstage?.pluginId === pluginId && + p.packageJson.backstage?.role === targetRole, + )?.packageJson.name ?? backendPluginPackageNameByPluginId.get(pluginId); + + if (!pluginPkgName) { // If we can't find a matching package in the repo but one is declared, skip if (pkgBackstage.pluginPackage) { return; @@ -351,13 +374,16 @@ export function fixPluginPackages( paths.targetRoot, resolvePath(pkg.dir, 'package.json'), ); + const suggestedRole = + role === 'frontend-plugin-module' ? 'web-library' : 'node-library'; throw new Error( - `Failed to find plugin package for ${pkg.packageJson.name}, please set backstage.pluginPackage manually in ${path}`, + `Failed to find plugin package for "${pkg.packageJson.name}", please declare the name of the plugin package that this package is a module for in the 'backstage.pluginPackage' field in "${path}". ` + + `It is also possible that this package is not a module, and should use the '${suggestedRole}' role instead.`, ); } - if (pkgBackstage.pluginPackage !== pluginPkg.packageJson.name) { - pkgBackstage.pluginPackage = pluginPkg.packageJson.name; + if (pkgBackstage.pluginPackage !== pluginPkgName) { + pkgBackstage.pluginPackage = pluginPkgName; pkg.changed = true; } } else { @@ -374,14 +400,14 @@ export function fixPluginPackages( if (repoPkgRole === 'frontend-plugin') { if (frontend) { throw new Error( - `Duplicate frontend plugin for '${pluginId}', ${frontend} and ${repoPkgName}`, + `Duplicate frontend plugin for '${pluginId}', "${frontend}" and "${repoPkgName}"`, ); } frontend = repoPkgName; } else if (repoPkgRole === 'backend-plugin') { if (backend) { throw new Error( - `Duplicate backend plugin for '${pluginId}', ${backend} and ${repoPkgName}`, + `Duplicate backend plugin for '${pluginId}', "${backend}" and "${repoPkgName}"`, ); } backend = repoPkgName; From c7535dea31f7b7e6a1faae4074cd5d61aef53dd7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 11 Jun 2024 01:15:20 +0200 Subject: [PATCH 30/46] cli: update fix for simplified pluginPackages list Signed-off-by: Patrik Oldsberg --- .../cli-node/src/monorepo/PackageGraph.ts | 6 +- packages/cli/src/commands/repo/fix.ts | 80 +++++-------------- 2 files changed, 21 insertions(+), 65 deletions(-) diff --git a/packages/cli-node/src/monorepo/PackageGraph.ts b/packages/cli-node/src/monorepo/PackageGraph.ts index f6b563202e..afa5eed888 100644 --- a/packages/cli-node/src/monorepo/PackageGraph.ts +++ b/packages/cli-node/src/monorepo/PackageGraph.ts @@ -60,11 +60,7 @@ export interface BackstagePackageJson { /** * All packages that are part of the plugin. Must always and only be set for plugin packages and plugin library packages. */ - pluginPackages?: { - frontend?: string; - backend?: string; - libraries?: string[]; - }; + pluginPackages?: string[]; }; exports?: JsonValue; diff --git a/packages/cli/src/commands/repo/fix.ts b/packages/cli/src/commands/repo/fix.ts index 547ba1ca8a..285dd75e3b 100644 --- a/packages/cli/src/commands/repo/fix.ts +++ b/packages/cli/src/commands/repo/fix.ts @@ -325,6 +325,14 @@ const backendPluginPackageNameByPluginId = new Map( ].map(pluginId => [pluginId, `@backstage/plugin-${pluginId}-backend`]), ); +const pluginPackageRoles: Array = [ + 'frontend-plugin', + 'backend-plugin', + 'common-library', + 'web-library', + 'node-library', +]; + export function fixPluginPackages( pkg: FixablePackage, repoPackages: FixablePackage[], @@ -387,70 +395,22 @@ export function fixPluginPackages( pkg.changed = true; } } else { - let frontend: string | undefined = undefined; - let backend: string | undefined = undefined; - let libraries: string[] | undefined = []; + let pluginPackages: string[] | undefined = repoPackages + .filter( + p => + p.packageJson.backstage?.pluginId === pluginId && + pluginPackageRoles.includes(p.packageJson.backstage?.role), + ) + .map(p => p.packageJson.name) + .sort(); - for (const repoPkg of repoPackages) { - if (repoPkg.packageJson.backstage?.pluginId !== pluginId) { - continue; - } - const repoPkgRole = repoPkg.packageJson.backstage?.role; - const repoPkgName = repoPkg.packageJson.name; - if (repoPkgRole === 'frontend-plugin') { - if (frontend) { - throw new Error( - `Duplicate frontend plugin for '${pluginId}', "${frontend}" and "${repoPkgName}"`, - ); - } - frontend = repoPkgName; - } else if (repoPkgRole === 'backend-plugin') { - if (backend) { - throw new Error( - `Duplicate backend plugin for '${pluginId}', "${backend}" and "${repoPkgName}"`, - ); - } - backend = repoPkgName; - } else if ( - repoPkgRole === 'common-library' || - repoPkgRole === 'web-library' || - repoPkgRole === 'node-library' - ) { - libraries.push(repoPkgName); - } + if (pluginPackages.length === 0) { + pluginPackages = undefined; } - if (libraries.length === 0) { - // If there are no libraries, avoid an empty array in package.json - libraries = undefined; - } else { - // Sort libraries to ensure consistent order - libraries.sort(); - } - - if (!pkgBackstage.pluginPackages) { - pkgBackstage.pluginPackages = { - frontend, - backend, - libraries, - }; + if (pkgBackstage.pluginPackages?.join(',') !== pluginPackages?.join(',')) { + pkgBackstage.pluginPackages = pluginPackages; pkg.changed = true; - } else { - if (pkgBackstage.pluginPackages.frontend !== frontend) { - pkgBackstage.pluginPackages.frontend = frontend; - pkg.changed = true; - } - if (pkgBackstage.pluginPackages.backend !== backend) { - pkgBackstage.pluginPackages.backend = backend; - pkg.changed = true; - } - if ( - pkgBackstage.pluginPackages.libraries?.join(',') !== - libraries?.join(',') - ) { - pkgBackstage.pluginPackages.libraries = libraries; - pkg.changed = true; - } } } } From d44a20a5cd52f473f623af297f403e0c24ccb6cd Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 11 Jun 2024 01:32:43 +0200 Subject: [PATCH 31/46] add plugin metadata to all plugin packages Signed-off-by: Patrik Oldsberg --- .changeset/new-masks-occur.md | 136 ++++++++++++++++++ packages/app-next-example-plugin/package.json | 5 +- .../package.json | 4 +- plugins/api-docs/package.json | 6 +- plugins/app-backend/package.json | 55 +++---- plugins/app-node/package.json | 41 +++--- plugins/app-visualizer/package.json | 6 +- .../package.json | 34 ++--- .../package.json | 36 ++--- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 34 ++--- .../package.json | 4 +- .../package.json | 34 ++--- .../package.json | 34 ++--- .../package.json | 4 +- .../package.json | 34 ++--- .../package.json | 34 ++--- .../package.json | 32 +++-- .../package.json | 34 ++--- .../package.json | 34 ++--- .../package.json | 4 +- .../package.json | 32 +++-- .../package.json | 4 +- plugins/auth-backend/package.json | 8 +- plugins/auth-node/package.json | 8 +- plugins/auth-react/package.json | 8 +- plugins/bitbucket-cloud-common/package.json | 6 +- .../catalog-backend-module-aws/package.json | 4 +- .../catalog-backend-module-azure/package.json | 4 +- .../package.json | 4 +- .../package.json | 46 +++--- .../package.json | 44 +++--- .../catalog-backend-module-gcp/package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../catalog-backend-module-ldap/package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- plugins/catalog-backend/package.json | 10 +- plugins/catalog-common/package.json | 10 +- plugins/catalog-graph/package.json | 6 +- plugins/catalog-import/package.json | 6 +- plugins/catalog-node/package.json | 10 +- plugins/catalog-react/package.json | 62 ++++---- .../package.json | 7 +- .../catalog-unprocessed-entities/package.json | 7 +- plugins/catalog/package.json | 10 +- plugins/config-schema/package.json | 6 +- plugins/devtools-backend/package.json | 34 +++-- plugins/devtools-common/package.json | 8 +- plugins/devtools/package.json | 58 ++++---- .../package.json | 4 +- .../events-backend-module-azure/package.json | 4 +- .../package.json | 4 +- .../events-backend-module-gerrit/package.json | 4 +- .../events-backend-module-github/package.json | 4 +- .../events-backend-module-gitlab/package.json | 4 +- .../events-backend-test-utils/package.json | 8 +- plugins/events-backend/package.json | 8 +- plugins/events-node/package.json | 8 +- .../example-todo-list-backend/package.json | 8 +- plugins/example-todo-list-common/package.json | 8 +- plugins/example-todo-list/package.json | 8 +- plugins/home-react/package.json | 7 +- plugins/home/package.json | 7 +- plugins/kubernetes-backend/package.json | 56 ++++---- plugins/kubernetes-cluster/package.json | 6 +- plugins/kubernetes-common/package.json | 10 +- plugins/kubernetes-node/package.json | 10 +- plugins/kubernetes-react/package.json | 46 +++--- plugins/kubernetes/package.json | 52 ++++--- .../package.json | 4 +- plugins/notifications-backend/package.json | 9 +- plugins/notifications-common/package.json | 9 +- plugins/notifications-node/package.json | 9 +- plugins/notifications/package.json | 9 +- plugins/org-react/package.json | 7 +- plugins/org/package.json | 7 +- .../package.json | 4 +- plugins/permission-backend/package.json | 9 +- plugins/permission-common/package.json | 9 +- plugins/permission-node/package.json | 53 ++++--- plugins/permission-react/package.json | 9 +- plugins/proxy-backend/package.json | 6 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- plugins/scaffolder-backend/package.json | 11 +- plugins/scaffolder-common/package.json | 11 +- .../scaffolder-node-test-utils/package.json | 11 +- plugins/scaffolder-node/package.json | 11 +- plugins/scaffolder-react/package.json | 11 +- plugins/scaffolder/package.json | 11 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- plugins/search-backend-module-pg/package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- plugins/search-backend-node/package.json | 6 +- plugins/search-backend/package.json | 9 +- plugins/search-common/package.json | 9 +- plugins/search-react/package.json | 9 +- plugins/search/package.json | 9 +- plugins/signals-backend/package.json | 35 +++-- plugins/signals-node/package.json | 45 +++--- plugins/signals-react/package.json | 9 +- plugins/signals/package.json | 9 +- .../techdocs-addons-test-utils/package.json | 6 +- plugins/techdocs-backend/package.json | 9 +- .../package.json | 4 +- plugins/techdocs-node/package.json | 9 +- plugins/techdocs-react/package.json | 9 +- plugins/techdocs/package.json | 9 +- plugins/user-settings-backend/package.json | 8 +- plugins/user-settings-common/package.json | 8 +- plugins/user-settings/package.json | 8 +- 137 files changed, 1276 insertions(+), 561 deletions(-) create mode 100644 .changeset/new-masks-occur.md diff --git a/.changeset/new-masks-occur.md b/.changeset/new-masks-occur.md new file mode 100644 index 0000000000..b5777b7abe --- /dev/null +++ b/.changeset/new-masks-occur.md @@ -0,0 +1,136 @@ +--- +'@backstage/plugin-scaffolder-backend-module-confluence-to-markdown': patch +'@backstage/plugin-auth-backend-module-cloudflare-access-provider': patch +'@backstage/plugin-catalog-backend-module-scaffolder-entity-model': patch +'@backstage/plugin-search-backend-module-stack-overflow-collator': patch +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +'@backstage/plugin-auth-backend-module-azure-easyauth-provider': patch +'@backstage/plugin-permission-backend-module-allow-all-policy': patch +'@backstage/plugin-scaffolder-backend-module-bitbucket-server': patch +'@backstage/plugin-auth-backend-module-oauth2-proxy-provider': patch +'@backstage/plugin-auth-backend-module-vmware-cloud-provider': patch +'@backstage/plugin-scaffolder-backend-module-bitbucket-cloud': patch +'@backstage/plugin-catalog-backend-module-backstage-openapi': patch +'@backstage/plugin-catalog-backend-module-bitbucket-server': patch +'@backstage/plugin-scaffolder-backend-module-notifications': patch +'@backstage/plugin-auth-backend-module-atlassian-provider': patch +'@backstage/plugin-auth-backend-module-bitbucket-provider': patch +'@backstage/plugin-auth-backend-module-microsoft-provider': patch +'@backstage/plugin-catalog-backend-module-bitbucket-cloud': patch +'@backstage/plugin-scaffolder-backend-module-cookiecutter': patch +'@backstage/plugin-auth-backend-module-onelogin-provider': patch +'@backstage/plugin-auth-backend-module-pinniped-provider': patch +'@backstage/plugin-events-backend-module-bitbucket-cloud': patch +'@backstage/plugin-auth-backend-module-aws-alb-provider': patch +'@backstage/plugin-auth-backend-module-gcp-iap-provider': patch +'@backstage/plugin-auth-backend-module-github-provider': patch +'@backstage/plugin-auth-backend-module-gitlab-provider': patch +'@backstage/plugin-auth-backend-module-google-provider': patch +'@backstage/plugin-auth-backend-module-oauth2-provider': patch +'@backstage/plugin-catalog-unprocessed-entities-common': patch +'@backstage/plugin-scaffolder-backend-module-bitbucket': 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-auth-backend-module-okta-provider': patch +'@backstage/plugin-catalog-backend-module-github-org': patch +'@backstage/plugin-catalog-backend-module-gitlab-org': patch +'@backstage/plugin-scaffolder-backend-module-gerrit': patch +'@backstage/plugin-scaffolder-backend-module-github': patch +'@backstage/plugin-scaffolder-backend-module-gitlab': patch +'@backstage/plugin-scaffolder-backend-module-sentry': patch +'@backstage/plugin-scaffolder-backend-module-yeoman': patch +'@backstage/plugin-catalog-backend-module-puppetdb': patch +'@backstage/plugin-scaffolder-backend-module-azure': patch +'@backstage/plugin-scaffolder-backend-module-gitea': patch +'@backstage/plugin-scaffolder-backend-module-rails': patch +'@backstage/plugin-api-docs-module-protoc-gen-doc': patch +'@backstage/plugin-catalog-backend-module-msgraph': patch +'@backstage/plugin-catalog-backend-module-openapi': patch +'@backstage/plugin-search-backend-module-techdocs': patch +'@backstage/plugin-techdocs-module-addons-contrib': patch +'@backstage/plugin-catalog-backend-module-gerrit': patch +'@backstage/plugin-catalog-backend-module-github': patch +'@backstage/plugin-catalog-backend-module-gitlab': 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-catalog-backend-module-azure': patch +'@backstage/plugin-catalog-unprocessed-entities': patch +'@backstage/plugin-events-backend-module-gerrit': patch +'@backstage/plugin-events-backend-module-github': patch +'@backstage/plugin-events-backend-module-gitlab': patch +'@backstage/plugin-catalog-backend-module-ldap': patch +'@backstage/plugin-events-backend-module-azure': patch +'@backstage/plugin-catalog-backend-module-aws': patch +'@backstage/plugin-catalog-backend-module-gcp': patch +'@backstage/plugin-scaffolder-node-test-utils': patch +'@backstage/plugin-techdocs-addons-test-utils': patch +'@backstage/plugin-events-backend-test-utils': patch +'@backstage/plugin-search-backend-module-pg': patch +'@backstage/plugin-bitbucket-cloud-common': patch +'@backstage/plugin-notifications-backend': patch +'@backstage/plugin-user-settings-backend': patch +'@backstage/plugin-notifications-common': patch +'@backstage/plugin-user-settings-common': patch +'@backstage/plugin-search-backend-node': patch +'@backstage/plugin-kubernetes-backend': patch +'@backstage/plugin-kubernetes-cluster': patch +'@backstage/plugin-notifications-node': patch +'@backstage/plugin-permission-backend': patch +'@backstage/plugin-scaffolder-backend': patch +'@backstage/plugin-kubernetes-common': patch +'@backstage/plugin-permission-common': patch +'@backstage/plugin-scaffolder-common': patch +'@backstage/plugin-devtools-backend': patch +'@backstage/plugin-kubernetes-react': patch +'@backstage/plugin-permission-react': patch +'@backstage/plugin-scaffolder-react': patch +'@backstage/plugin-techdocs-backend': patch +'@backstage/plugin-catalog-backend': patch +'@backstage/plugin-devtools-common': patch +'@backstage/plugin-kubernetes-node': patch +'@backstage/plugin-permission-node': patch +'@backstage/plugin-scaffolder-node': patch +'@backstage/plugin-signals-backend': patch +'@backstage/plugin-app-visualizer': patch +'@backstage/plugin-catalog-common': patch +'@backstage/plugin-catalog-import': patch +'@backstage/plugin-events-backend': patch +'@backstage/plugin-search-backend': patch +'@backstage/plugin-techdocs-react': patch +'@backstage/plugin-catalog-graph': patch +'@backstage/plugin-catalog-react': patch +'@backstage/plugin-config-schema': patch +'@backstage/plugin-notifications': patch +'@backstage/plugin-proxy-backend': patch +'@backstage/plugin-search-common': patch +'@backstage/plugin-signals-react': patch +'@backstage/plugin-techdocs-node': patch +'@backstage/plugin-user-settings': patch +'@backstage/plugin-auth-backend': patch +'@backstage/plugin-catalog-node': patch +'@backstage/plugin-search-react': patch +'@backstage/plugin-signals-node': patch +'@backstage/plugin-app-backend': patch +'@backstage/plugin-events-node': patch +'@backstage/plugin-auth-react': patch +'@backstage/plugin-home-react': patch +'@backstage/plugin-kubernetes': patch +'@backstage/plugin-scaffolder': patch +'@backstage/plugin-auth-node': patch +'@backstage/plugin-org-react': patch +'@backstage/plugin-api-docs': patch +'@backstage/plugin-app-node': patch +'@backstage/plugin-devtools': patch +'@backstage/plugin-techdocs': patch +'@backstage/plugin-catalog': patch +'@backstage/plugin-signals': patch +'@backstage/plugin-search': patch +'@backstage/plugin-home': patch +'@backstage/plugin-org': patch +--- + +Added additional plugin metadata to `package.json`. diff --git a/packages/app-next-example-plugin/package.json b/packages/app-next-example-plugin/package.json index be0d5fc8ee..f42c07952c 100644 --- a/packages/app-next-example-plugin/package.json +++ b/packages/app-next-example-plugin/package.json @@ -4,7 +4,10 @@ "description": "Backstage internal example plugin", "backstage": { "role": "frontend-plugin", - "pluginId": "example" + "pluginId": "example", + "pluginPackages": [ + "app-next-example-plugin" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/api-docs-module-protoc-gen-doc/package.json b/plugins/api-docs-module-protoc-gen-doc/package.json index e90fa57137..053db849ca 100644 --- a/plugins/api-docs-module-protoc-gen-doc/package.json +++ b/plugins/api-docs-module-protoc-gen-doc/package.json @@ -3,7 +3,9 @@ "version": "0.1.6", "description": "Additional functionalities for the api-docs plugin that renders the output of the protoc-gen-doc", "backstage": { - "role": "frontend-plugin-module" + "role": "frontend-plugin-module", + "pluginId": "api-docs", + "pluginPackage": "@backstage/plugin-api-docs" }, "publishConfig": { "access": "public", diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 04965a8796..29a16e6ece 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -3,7 +3,11 @@ "version": "0.11.6-next.1", "description": "A Backstage plugin that helps represent API entities in the frontend", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "api-docs", + "pluginPackages": [ + "@backstage/plugin-api-docs" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index 8c61abfe30..c255c8ea40 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -1,18 +1,35 @@ { "name": "@backstage/plugin-app-backend", - "description": "A Backstage backend plugin that serves the Backstage frontend app", "version": "0.3.68-next.2", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "A Backstage backend plugin that serves the Backstage frontend app", + "backstage": { + "role": "backend-plugin", + "pluginId": "app", + "pluginPackages": [ + "@backstage/plugin-app-backend", + "@backstage/plugin-app-node" + ] + }, "publishConfig": { "access": "public" }, + "keywords": [ + "backstage" + ], + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/app-backend" + }, + "license": "Apache-2.0", "exports": { ".": "./src/index.ts", "./alpha": "./src/alpha.ts", "./package.json": "./package.json" }, + "main": "src/index.ts", + "types": "src/index.ts", "typesVersions": { "*": { "alpha": [ @@ -23,26 +40,20 @@ ] } }, - "backstage": { - "role": "backend-plugin" - }, - "homepage": "https://backstage.io", - "repository": { - "type": "git", - "url": "https://github.com/backstage/backstage", - "directory": "plugins/app-backend" - }, - "keywords": [ - "backstage" + "files": [ + "dist", + "config.d.ts", + "migrations/**/*.{js,d.ts}", + "static" ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", + "clean": "backstage-cli package clean", "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", "postpack": "backstage-cli package postpack", - "clean": "backstage-cli package clean" + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-common": "workspace:^", @@ -74,11 +85,5 @@ "node-fetch": "^2.6.7", "supertest": "^6.1.3" }, - "configSchema": "config.d.ts", - "files": [ - "dist", - "config.d.ts", - "migrations/**/*.{js,d.ts}", - "static" - ] + "configSchema": "config.d.ts" } diff --git a/plugins/app-node/package.json b/plugins/app-node/package.json index e6ece010e1..b258e3714e 100644 --- a/plugins/app-node/package.json +++ b/plugins/app-node/package.json @@ -1,10 +1,15 @@ { "name": "@backstage/plugin-app-node", - "description": "Node.js library for the app plugin", "version": "0.1.19-next.1", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "Node.js library for the app plugin", + "backstage": { + "role": "node-library", + "pluginId": "app", + "pluginPackages": [ + "@backstage/plugin-app-backend", + "@backstage/plugin-app-node" + ] + }, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", @@ -15,28 +20,28 @@ "url": "https://github.com/backstage/backstage", "directory": "plugins/app-node" }, - "backstage": { - "role": "node-library" - }, - "scripts": { - "build": "backstage-cli package build", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", - "clean": "backstage-cli package clean", - "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack" - }, - "devDependencies": { - "@backstage/cli": "workspace:^" - }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", "files": [ "dist" ], + "scripts": { + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "test": "backstage-cli package test" + }, "dependencies": { "@backstage/backend-plugin-api": "workspace:^", "@backstage/config-loader": "workspace:^", "@types/express": "^4.17.6", "express": "^4.17.1", "fs-extra": "^11.2.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" } } diff --git a/plugins/app-visualizer/package.json b/plugins/app-visualizer/package.json index eea4f630de..1d30d2b2b3 100644 --- a/plugins/app-visualizer/package.json +++ b/plugins/app-visualizer/package.json @@ -3,7 +3,11 @@ "version": "0.1.7-next.1", "description": "Visualizes the Backstage app structure", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "app-visualizer", + "pluginPackages": [ + "@backstage/plugin-app-visualizer" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/auth-backend-module-atlassian-provider/package.json b/plugins/auth-backend-module-atlassian-provider/package.json index 956d010f1d..6ee6423e49 100644 --- a/plugins/auth-backend-module-atlassian-provider/package.json +++ b/plugins/auth-backend-module-atlassian-provider/package.json @@ -1,10 +1,12 @@ { "name": "@backstage/plugin-auth-backend-module-atlassian-provider", - "description": "The atlassian-provider backend module for the auth plugin.", "version": "0.1.11-next.1", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "The atlassian-provider backend module for the auth plugin.", + "backstage": { + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" + }, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", @@ -15,17 +17,21 @@ "url": "https://github.com/backstage/backstage", "directory": "plugins/auth-backend-module-atlassian-provider" }, - "backstage": { - "role": "backend-plugin-module" - }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist", + "config.d.ts" + ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack" + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-plugin-api": "workspace:^", @@ -41,9 +47,5 @@ "@backstage/plugin-auth-backend": "workspace:^", "supertest": "^6.3.3" }, - "configSchema": "config.d.ts", - "files": [ - "dist", - "config.d.ts" - ] + "configSchema": "config.d.ts" } diff --git a/plugins/auth-backend-module-aws-alb-provider/package.json b/plugins/auth-backend-module-aws-alb-provider/package.json index 870216ecca..e47dd7d6d9 100644 --- a/plugins/auth-backend-module-aws-alb-provider/package.json +++ b/plugins/auth-backend-module-aws-alb-provider/package.json @@ -1,35 +1,40 @@ { "name": "@backstage/plugin-auth-backend-module-aws-alb-provider", - "description": "The aws-alb provider module for the Backstage auth backend.", "version": "0.1.11-next.2", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "The aws-alb provider module for the Backstage auth backend.", + "backstage": { + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" + }, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, - "backstage": { - "role": "backend-plugin-module" - }, + "keywords": [ + "backstage" + ], "homepage": "https://backstage.io", "repository": { "type": "git", "url": "https://github.com/backstage/backstage", "directory": "plugins/auth-backend-module-aws-alb-provider" }, - "keywords": [ - "backstage" + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack" + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-common": "workspace:^", @@ -47,8 +52,5 @@ "@backstage/config": "workspace:^", "express": "^4.18.2", "msw": "^2.0.8" - }, - "files": [ - "dist" - ] + } } diff --git a/plugins/auth-backend-module-azure-easyauth-provider/package.json b/plugins/auth-backend-module-azure-easyauth-provider/package.json index 298de835f9..cc15bc27d6 100644 --- a/plugins/auth-backend-module-azure-easyauth-provider/package.json +++ b/plugins/auth-backend-module-azure-easyauth-provider/package.json @@ -3,7 +3,9 @@ "version": "0.1.2-next.1", "description": "The azure-easyauth-provider backend module for the auth plugin.", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" }, "publishConfig": { "access": "public", diff --git a/plugins/auth-backend-module-bitbucket-provider/package.json b/plugins/auth-backend-module-bitbucket-provider/package.json index cdccd8df5a..6327422311 100644 --- a/plugins/auth-backend-module-bitbucket-provider/package.json +++ b/plugins/auth-backend-module-bitbucket-provider/package.json @@ -3,7 +3,9 @@ "version": "0.1.2-next.1", "description": "The bitbucket-provider backend module for the auth plugin.", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" }, "publishConfig": { "access": "public", diff --git a/plugins/auth-backend-module-cloudflare-access-provider/package.json b/plugins/auth-backend-module-cloudflare-access-provider/package.json index 8bbe01228e..01350b5616 100644 --- a/plugins/auth-backend-module-cloudflare-access-provider/package.json +++ b/plugins/auth-backend-module-cloudflare-access-provider/package.json @@ -3,7 +3,9 @@ "version": "0.1.2-next.2", "description": "The cloudflare-access-provider backend module for the auth plugin.", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" }, "publishConfig": { "access": "public", diff --git a/plugins/auth-backend-module-gcp-iap-provider/package.json b/plugins/auth-backend-module-gcp-iap-provider/package.json index 5ac57fe932..1c2d6b006d 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/package.json +++ b/plugins/auth-backend-module-gcp-iap-provider/package.json @@ -1,35 +1,41 @@ { "name": "@backstage/plugin-auth-backend-module-gcp-iap-provider", - "description": "A GCP IAP auth provider module for the Backstage auth backend", "version": "0.2.14-next.1", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "A GCP IAP auth provider module for the Backstage auth backend", + "backstage": { + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" + }, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, - "backstage": { - "role": "backend-plugin-module" - }, + "keywords": [ + "backstage" + ], "homepage": "https://backstage.io", "repository": { "type": "git", "url": "https://github.com/backstage/backstage", "directory": "plugins/auth-backend-module-gcp-iap-provider" }, - "keywords": [ - "backstage" + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist", + "config.d.ts" ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", + "clean": "backstage-cli package clean", "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", "postpack": "backstage-cli package postpack", - "clean": "backstage-cli package clean" + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-plugin-api": "workspace:^", @@ -43,9 +49,5 @@ "@backstage/cli": "workspace:^", "express": "^4.18.2" }, - "files": [ - "dist", - "config.d.ts" - ], "configSchema": "config.d.ts" } diff --git a/plugins/auth-backend-module-github-provider/package.json b/plugins/auth-backend-module-github-provider/package.json index f85d10dfa4..631ace3ef9 100644 --- a/plugins/auth-backend-module-github-provider/package.json +++ b/plugins/auth-backend-module-github-provider/package.json @@ -3,7 +3,9 @@ "version": "0.1.16-next.1", "description": "The github-provider backend module for the auth plugin.", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" }, "publishConfig": { "access": "public", diff --git a/plugins/auth-backend-module-gitlab-provider/package.json b/plugins/auth-backend-module-gitlab-provider/package.json index ff91c8395a..b1a2a0a59c 100644 --- a/plugins/auth-backend-module-gitlab-provider/package.json +++ b/plugins/auth-backend-module-gitlab-provider/package.json @@ -1,10 +1,12 @@ { "name": "@backstage/plugin-auth-backend-module-gitlab-provider", - "description": "The gitlab-provider backend module for the auth plugin.", "version": "0.1.16-next.1", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "The gitlab-provider backend module for the auth plugin.", + "backstage": { + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" + }, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", @@ -15,17 +17,21 @@ "url": "https://github.com/backstage/backstage", "directory": "plugins/auth-backend-module-gitlab-provider" }, - "backstage": { - "role": "backend-plugin-module" - }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist", + "config.d.ts" + ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack" + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-plugin-api": "workspace:^", @@ -41,9 +47,5 @@ "@backstage/plugin-auth-backend": "workspace:^", "supertest": "^6.3.3" }, - "configSchema": "config.d.ts", - "files": [ - "dist", - "config.d.ts" - ] + "configSchema": "config.d.ts" } diff --git a/plugins/auth-backend-module-google-provider/package.json b/plugins/auth-backend-module-google-provider/package.json index aae3b11256..b66bdba4e8 100644 --- a/plugins/auth-backend-module-google-provider/package.json +++ b/plugins/auth-backend-module-google-provider/package.json @@ -1,35 +1,41 @@ { "name": "@backstage/plugin-auth-backend-module-google-provider", - "description": "A Google auth provider module for the Backstage auth backend", "version": "0.1.16-next.1", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "A Google auth provider module for the Backstage auth backend", + "backstage": { + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" + }, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, - "backstage": { - "role": "backend-plugin-module" - }, + "keywords": [ + "backstage" + ], "homepage": "https://backstage.io", "repository": { "type": "git", "url": "https://github.com/backstage/backstage", "directory": "plugins/auth-backend-module-google-provider" }, - "keywords": [ - "backstage" + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist", + "config.d.ts" ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", + "clean": "backstage-cli package clean", "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", "postpack": "backstage-cli package postpack", - "clean": "backstage-cli package clean" + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-plugin-api": "workspace:^", @@ -44,9 +50,5 @@ "@types/passport-google-oauth20": "^2.0.3", "supertest": "^6.1.3" }, - "files": [ - "dist", - "config.d.ts" - ], "configSchema": "config.d.ts" } diff --git a/plugins/auth-backend-module-guest-provider/package.json b/plugins/auth-backend-module-guest-provider/package.json index f18e91ef58..6fa4e8f5a3 100644 --- a/plugins/auth-backend-module-guest-provider/package.json +++ b/plugins/auth-backend-module-guest-provider/package.json @@ -3,7 +3,9 @@ "version": "0.1.5-next.2", "description": "The guest-provider backend module for the auth plugin.", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" }, "publishConfig": { "access": "public", diff --git a/plugins/auth-backend-module-microsoft-provider/package.json b/plugins/auth-backend-module-microsoft-provider/package.json index af1b0c7f01..5c386706f1 100644 --- a/plugins/auth-backend-module-microsoft-provider/package.json +++ b/plugins/auth-backend-module-microsoft-provider/package.json @@ -1,10 +1,12 @@ { "name": "@backstage/plugin-auth-backend-module-microsoft-provider", - "description": "The microsoft-provider backend module for the auth plugin.", "version": "0.1.14-next.1", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "The microsoft-provider backend module for the auth plugin.", + "backstage": { + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" + }, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", @@ -15,17 +17,21 @@ "url": "https://github.com/backstage/backstage", "directory": "plugins/auth-backend-module-microsoft-provider" }, - "backstage": { - "role": "backend-plugin-module" - }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist", + "config.d.ts" + ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack" + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-plugin-api": "workspace:^", @@ -47,9 +53,5 @@ "msw": "^1.0.0", "supertest": "^6.3.3" }, - "configSchema": "config.d.ts", - "files": [ - "dist", - "config.d.ts" - ] + "configSchema": "config.d.ts" } diff --git a/plugins/auth-backend-module-oauth2-provider/package.json b/plugins/auth-backend-module-oauth2-provider/package.json index 67347e8cdd..aea5451b7b 100644 --- a/plugins/auth-backend-module-oauth2-provider/package.json +++ b/plugins/auth-backend-module-oauth2-provider/package.json @@ -1,10 +1,12 @@ { "name": "@backstage/plugin-auth-backend-module-oauth2-provider", - "description": "The oauth2-provider backend module for the auth plugin.", "version": "0.1.16-next.1", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "The oauth2-provider backend module for the auth plugin.", + "backstage": { + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" + }, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", @@ -15,17 +17,21 @@ "url": "https://github.com/backstage/backstage", "directory": "plugins/auth-backend-module-oauth2-provider" }, - "backstage": { - "role": "backend-plugin-module" - }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist", + "config.d.ts" + ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack" + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-plugin-api": "workspace:^", @@ -40,9 +46,5 @@ "@backstage/plugin-auth-backend": "workspace:^", "supertest": "^6.3.3" }, - "configSchema": "config.d.ts", - "files": [ - "dist", - "config.d.ts" - ] + "configSchema": "config.d.ts" } diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/package.json b/plugins/auth-backend-module-oauth2-proxy-provider/package.json index 3d02d39645..a8a981e13f 100644 --- a/plugins/auth-backend-module-oauth2-proxy-provider/package.json +++ b/plugins/auth-backend-module-oauth2-proxy-provider/package.json @@ -1,10 +1,12 @@ { "name": "@backstage/plugin-auth-backend-module-oauth2-proxy-provider", - "description": "The oauth2-proxy-provider backend module for the auth plugin.", "version": "0.1.12-next.1", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "The oauth2-proxy-provider backend module for the auth plugin.", + "backstage": { + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" + }, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", @@ -15,17 +17,20 @@ "url": "https://github.com/backstage/backstage", "directory": "plugins/auth-backend-module-oauth2-proxy-provider" }, - "backstage": { - "role": "backend-plugin-module" - }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack" + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-plugin-api": "workspace:^", @@ -36,8 +41,5 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^" - }, - "files": [ - "dist" - ] + } } diff --git a/plugins/auth-backend-module-oidc-provider/package.json b/plugins/auth-backend-module-oidc-provider/package.json index aa75b31ff2..f0a6d006c9 100644 --- a/plugins/auth-backend-module-oidc-provider/package.json +++ b/plugins/auth-backend-module-oidc-provider/package.json @@ -1,10 +1,12 @@ { "name": "@backstage/plugin-auth-backend-module-oidc-provider", - "description": "The oidc-provider backend module for the auth plugin.", "version": "0.1.10-next.2", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "The oidc-provider backend module for the auth plugin.", + "backstage": { + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" + }, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", @@ -15,17 +17,21 @@ "url": "https://github.com/backstage/backstage", "directory": "plugins/auth-backend-module-oidc-provider" }, - "backstage": { - "role": "backend-plugin-module" - }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist", + "config.d.ts" + ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack" + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-common": "workspace:^", @@ -48,9 +54,5 @@ "msw": "^1.3.1", "supertest": "^6.3.3" }, - "configSchema": "config.d.ts", - "files": [ - "dist", - "config.d.ts" - ] + "configSchema": "config.d.ts" } diff --git a/plugins/auth-backend-module-okta-provider/package.json b/plugins/auth-backend-module-okta-provider/package.json index 6a6e30cedc..869142062e 100644 --- a/plugins/auth-backend-module-okta-provider/package.json +++ b/plugins/auth-backend-module-okta-provider/package.json @@ -1,10 +1,12 @@ { "name": "@backstage/plugin-auth-backend-module-okta-provider", - "description": "The okta-provider backend module for the auth plugin.", "version": "0.0.12-next.1", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "The okta-provider backend module for the auth plugin.", + "backstage": { + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" + }, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", @@ -15,17 +17,21 @@ "url": "https://github.com/backstage/backstage", "directory": "plugins/auth-backend-module-okta-provider" }, - "backstage": { - "role": "backend-plugin-module" - }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist", + "config.d.ts" + ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack" + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-plugin-api": "workspace:^", @@ -41,9 +47,5 @@ "@backstage/plugin-auth-backend": "workspace:^", "supertest": "^6.3.3" }, - "configSchema": "config.d.ts", - "files": [ - "dist", - "config.d.ts" - ] + "configSchema": "config.d.ts" } diff --git a/plugins/auth-backend-module-onelogin-provider/package.json b/plugins/auth-backend-module-onelogin-provider/package.json index 7012742eb2..45a3ff45b7 100644 --- a/plugins/auth-backend-module-onelogin-provider/package.json +++ b/plugins/auth-backend-module-onelogin-provider/package.json @@ -3,7 +3,9 @@ "version": "0.0.0", "description": "The onelogin-provider backend module for the auth plugin.", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" }, "publishConfig": { "access": "public", diff --git a/plugins/auth-backend-module-pinniped-provider/package.json b/plugins/auth-backend-module-pinniped-provider/package.json index 3c97abd24c..fed98690b2 100644 --- a/plugins/auth-backend-module-pinniped-provider/package.json +++ b/plugins/auth-backend-module-pinniped-provider/package.json @@ -1,10 +1,12 @@ { "name": "@backstage/plugin-auth-backend-module-pinniped-provider", - "description": "The pinniped-provider backend module for the auth plugin.", "version": "0.1.13-next.1", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "The pinniped-provider backend module for the auth plugin.", + "backstage": { + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" + }, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", @@ -15,17 +17,20 @@ "url": "https://github.com/backstage/backstage", "directory": "plugins/auth-backend-module-pinniped-provider" }, - "backstage": { - "role": "backend-plugin-module" - }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack" + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-plugin-api": "workspace:^", @@ -46,8 +51,5 @@ "msw": "^1.3.0", "passport": "^0.7.0", "supertest": "^6.3.3" - }, - "files": [ - "dist" - ] + } } diff --git a/plugins/auth-backend-module-vmware-cloud-provider/package.json b/plugins/auth-backend-module-vmware-cloud-provider/package.json index 0173cf1d5e..9afe3fdf97 100644 --- a/plugins/auth-backend-module-vmware-cloud-provider/package.json +++ b/plugins/auth-backend-module-vmware-cloud-provider/package.json @@ -3,7 +3,9 @@ "version": "0.1.11-next.1", "description": "The vmware-cloud-provider backend module for the auth plugin.", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" }, "publishConfig": { "access": "public", diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index c756e7b190..16a820ea6c 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -3,7 +3,13 @@ "version": "0.22.6-next.2", "description": "A Backstage backend plugin that handles authentication", "backstage": { - "role": "backend-plugin" + "role": "backend-plugin", + "pluginId": "auth", + "pluginPackages": [ + "@backstage/plugin-auth-backend", + "@backstage/plugin-auth-node", + "@backstage/plugin-auth-react" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index 0af23792e2..f38cb7915e 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -2,7 +2,13 @@ "name": "@backstage/plugin-auth-node", "version": "0.4.14-next.2", "backstage": { - "role": "node-library" + "role": "node-library", + "pluginId": "auth", + "pluginPackages": [ + "@backstage/plugin-auth-backend", + "@backstage/plugin-auth-node", + "@backstage/plugin-auth-react" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/auth-react/package.json b/plugins/auth-react/package.json index 478c4e3fb0..ea0d247e69 100644 --- a/plugins/auth-react/package.json +++ b/plugins/auth-react/package.json @@ -3,7 +3,13 @@ "version": "0.1.3-next.1", "description": "Web library for the auth plugin", "backstage": { - "role": "web-library" + "role": "web-library", + "pluginId": "auth", + "pluginPackages": [ + "@backstage/plugin-auth-backend", + "@backstage/plugin-auth-node", + "@backstage/plugin-auth-react" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/bitbucket-cloud-common/package.json b/plugins/bitbucket-cloud-common/package.json index 929d4bf3cd..0e92907cc1 100644 --- a/plugins/bitbucket-cloud-common/package.json +++ b/plugins/bitbucket-cloud-common/package.json @@ -3,7 +3,11 @@ "version": "0.2.20-next.0", "description": "Common functionalities for bitbucket-cloud plugins", "backstage": { - "role": "common-library" + "role": "common-library", + "pluginId": "bitbucket-cloud", + "pluginPackages": [ + "@backstage/plugin-bitbucket-cloud-common" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 1877120e84..4562d0a798 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -3,7 +3,9 @@ "version": "0.3.14-next.2", "description": "A Backstage catalog backend module that helps integrate towards AWS", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index 1f1d67ae67..7536c85789 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -3,7 +3,9 @@ "version": "0.1.39-next.2", "description": "A Backstage catalog backend module that helps integrate towards Azure", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/catalog-backend-module-backstage-openapi/package.json b/plugins/catalog-backend-module-backstage-openapi/package.json index 8bf2800f6f..accbc5986c 100644 --- a/plugins/catalog-backend-module-backstage-openapi/package.json +++ b/plugins/catalog-backend-module-backstage-openapi/package.json @@ -2,7 +2,9 @@ "name": "@backstage/plugin-catalog-backend-module-backstage-openapi", "version": "0.2.2-next.1", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" }, "publishConfig": { "access": "public", diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 8c86ecbf19..7ae9003eab 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -1,18 +1,32 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-cloud", - "description": "A Backstage catalog backend module that helps integrate towards Bitbucket Cloud", "version": "0.2.6-next.2", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "A Backstage catalog backend module that helps integrate towards Bitbucket Cloud", + "backstage": { + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" + }, "publishConfig": { "access": "public" }, + "keywords": [ + "backstage" + ], + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/catalog-backend-module-bitbucket-cloud" + }, + "license": "Apache-2.0", "exports": { ".": "./src/index.ts", "./alpha": "./src/alpha.ts", "./package.json": "./package.json" }, + "main": "src/index.ts", + "types": "src/index.ts", "typesVersions": { "*": { "alpha": [ @@ -23,26 +37,18 @@ ] } }, - "backstage": { - "role": "backend-plugin-module" - }, - "homepage": "https://backstage.io", - "repository": { - "type": "git", - "url": "https://github.com/backstage/backstage", - "directory": "plugins/catalog-backend-module-bitbucket-cloud" - }, - "keywords": [ - "backstage" + "files": [ + "config.d.ts", + "dist" ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", + "clean": "backstage-cli package clean", "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", "postpack": "backstage-cli package postpack", - "clean": "backstage-cli package clean" + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-common": "workspace:^", @@ -66,9 +72,5 @@ "luxon": "^3.0.0", "msw": "^1.0.0" }, - "files": [ - "config.d.ts", - "dist" - ], "configSchema": "config.d.ts" } diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index 8abe89b04b..7c360d1701 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -1,17 +1,31 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-server", "version": "0.1.33-next.2", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "backstage": { + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" + }, "publishConfig": { "access": "public" }, + "keywords": [ + "backstage" + ], + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/catalog-backend-module-bitbucket-server" + }, + "license": "Apache-2.0", "exports": { ".": "./src/index.ts", "./alpha": "./src/alpha.ts", "./package.json": "./package.json" }, + "main": "src/index.ts", + "types": "src/index.ts", "typesVersions": { "*": { "alpha": [ @@ -22,26 +36,18 @@ ] } }, - "backstage": { - "role": "backend-plugin-module" - }, - "homepage": "https://backstage.io", - "repository": { - "type": "git", - "url": "https://github.com/backstage/backstage", - "directory": "plugins/catalog-backend-module-bitbucket-server" - }, - "keywords": [ - "backstage" + "files": [ + "config.d.ts", + "dist" ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", + "clean": "backstage-cli package clean", "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", "postpack": "backstage-cli package postpack", - "clean": "backstage-cli package clean" + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-common": "workspace:^", @@ -62,9 +68,5 @@ "luxon": "^3.0.0", "msw": "^1.0.0" }, - "files": [ - "config.d.ts", - "dist" - ], "configSchema": "config.d.ts" } diff --git a/plugins/catalog-backend-module-gcp/package.json b/plugins/catalog-backend-module-gcp/package.json index dd69e87ac2..0806cd80bd 100644 --- a/plugins/catalog-backend-module-gcp/package.json +++ b/plugins/catalog-backend-module-gcp/package.json @@ -3,7 +3,9 @@ "version": "0.1.20-next.2", "description": "A Backstage catalog backend module that helps integrate towards GCP", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index 017781ca1d..a372da0b4c 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -2,7 +2,9 @@ "name": "@backstage/plugin-catalog-backend-module-gerrit", "version": "0.1.36-next.2", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/catalog-backend-module-github-org/package.json b/plugins/catalog-backend-module-github-org/package.json index 6cedc22d4b..09cb2defb2 100644 --- a/plugins/catalog-backend-module-github-org/package.json +++ b/plugins/catalog-backend-module-github-org/package.json @@ -3,7 +3,9 @@ "version": "0.1.14-next.2", "description": "The github-org backend module for the catalog plugin.", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" }, "publishConfig": { "access": "public", diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index ca437f9bf7..daa6aa8c9b 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -3,7 +3,9 @@ "version": "0.6.2-next.2", "description": "A Backstage catalog backend module that helps integrate towards GitHub", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/catalog-backend-module-gitlab-org/package.json b/plugins/catalog-backend-module-gitlab-org/package.json index 0f12ca4b97..d3a2310feb 100644 --- a/plugins/catalog-backend-module-gitlab-org/package.json +++ b/plugins/catalog-backend-module-gitlab-org/package.json @@ -3,7 +3,9 @@ "version": "0.0.2-next.2", "description": "The gitlab-org backend module for the catalog plugin.", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" }, "publishConfig": { "access": "public", diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index e1d1d63e5f..3b9454c732 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -3,7 +3,9 @@ "version": "0.3.18-next.2", "description": "A Backstage catalog backend module that helps integrate towards GitLab", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index 8544c300b5..2baed748b3 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -3,7 +3,9 @@ "version": "0.4.24-next.2", "description": "An entity provider for streaming large asset sources into the catalog", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index ed2d4e6e65..8b729ca620 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -3,7 +3,9 @@ "version": "0.6.0-next.2", "description": "A Backstage catalog backend module that helps integrate towards LDAP", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" }, "publishConfig": { "access": "public", diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index 6d1a913b31..5b1fd2d29b 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -3,7 +3,9 @@ "version": "0.5.27-next.2", "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index 716f6312b3..98008900f8 100644 --- a/plugins/catalog-backend-module-openapi/package.json +++ b/plugins/catalog-backend-module-openapi/package.json @@ -3,7 +3,9 @@ "version": "0.1.37-next.2", "description": "A Backstage catalog backend module that helps with OpenAPI specifications", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" }, "publishConfig": { "access": "public", diff --git a/plugins/catalog-backend-module-puppetdb/package.json b/plugins/catalog-backend-module-puppetdb/package.json index 701c217c39..f1e0cbf935 100644 --- a/plugins/catalog-backend-module-puppetdb/package.json +++ b/plugins/catalog-backend-module-puppetdb/package.json @@ -3,7 +3,9 @@ "version": "0.1.25-next.2", "description": "A Backstage catalog backend module that helps integrate towards PuppetDB", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/catalog-backend-module-scaffolder-entity-model/package.json b/plugins/catalog-backend-module-scaffolder-entity-model/package.json index a435d8926c..a4c7532e2a 100644 --- a/plugins/catalog-backend-module-scaffolder-entity-model/package.json +++ b/plugins/catalog-backend-module-scaffolder-entity-model/package.json @@ -3,7 +3,9 @@ "version": "0.1.17-next.2", "description": "Adds support for the scaffolder specific entity model (e.g. the Template kind) to the catalog backend plugin.", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/catalog-backend-module-unprocessed/package.json b/plugins/catalog-backend-module-unprocessed/package.json index b09df8eb4c..13939adc24 100644 --- a/plugins/catalog-backend-module-unprocessed/package.json +++ b/plugins/catalog-backend-module-unprocessed/package.json @@ -3,7 +3,9 @@ "version": "0.4.6-next.2", "description": "Backstage Catalog module to view unprocessed entities", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" }, "publishConfig": { "access": "public", diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index a0447cd7d1..988c040037 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -3,7 +3,15 @@ "version": "1.23.0-next.2", "description": "The Backstage backend plugin that provides the Backstage catalog", "backstage": { - "role": "backend-plugin" + "role": "backend-plugin", + "pluginId": "catalog", + "pluginPackages": [ + "@backstage/plugin-catalog", + "@backstage/plugin-catalog-backend", + "@backstage/plugin-catalog-common", + "@backstage/plugin-catalog-node", + "@backstage/plugin-catalog-react" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/catalog-common/package.json b/plugins/catalog-common/package.json index 936fc3c935..bb56c0c804 100644 --- a/plugins/catalog-common/package.json +++ b/plugins/catalog-common/package.json @@ -3,7 +3,15 @@ "version": "1.0.23", "description": "Common functionalities for the catalog plugin", "backstage": { - "role": "common-library" + "role": "common-library", + "pluginId": "catalog", + "pluginPackages": [ + "@backstage/plugin-catalog", + "@backstage/plugin-catalog-backend", + "@backstage/plugin-catalog-common", + "@backstage/plugin-catalog-node", + "@backstage/plugin-catalog-react" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 108e48399a..14a0e8ce20 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -2,7 +2,11 @@ "name": "@backstage/plugin-catalog-graph", "version": "0.4.6-next.1", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "catalog-graph", + "pluginPackages": [ + "@backstage/plugin-catalog-graph" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index b914747961..fe1ad1c667 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -3,7 +3,11 @@ "version": "0.12.0-next.2", "description": "A Backstage plugin the helps you import entities into your catalog", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "catalog-import", + "pluginPackages": [ + "@backstage/plugin-catalog-import" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index 780e67a55e..27bc1b709f 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -3,7 +3,15 @@ "version": "1.12.1-next.1", "description": "The plugin-catalog-node module for @backstage/plugin-catalog-backend", "backstage": { - "role": "node-library" + "role": "node-library", + "pluginId": "catalog", + "pluginPackages": [ + "@backstage/plugin-catalog", + "@backstage/plugin-catalog-backend", + "@backstage/plugin-catalog-common", + "@backstage/plugin-catalog-node", + "@backstage/plugin-catalog-react" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 8a63a73a10..2bca89fa88 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -1,18 +1,39 @@ { "name": "@backstage/plugin-catalog-react", - "description": "A frontend library that helps other Backstage plugins interact with the catalog", "version": "1.12.1-next.1", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "A frontend library that helps other Backstage plugins interact with the catalog", + "backstage": { + "role": "web-library", + "pluginId": "catalog", + "pluginPackages": [ + "@backstage/plugin-catalog", + "@backstage/plugin-catalog-backend", + "@backstage/plugin-catalog-common", + "@backstage/plugin-catalog-node", + "@backstage/plugin-catalog-react" + ] + }, "publishConfig": { "access": "public" }, + "keywords": [ + "backstage" + ], + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/catalog-react" + }, + "license": "Apache-2.0", + "sideEffects": false, "exports": { ".": "./src/index.ts", "./alpha": "./src/alpha.tsx", "./package.json": "./package.json" }, + "main": "src/index.ts", + "types": "src/index.ts", "typesVersions": { "*": { "alpha": [ @@ -23,27 +44,17 @@ ] } }, - "backstage": { - "role": "web-library" - }, - "homepage": "https://backstage.io", - "repository": { - "type": "git", - "url": "https://github.com/backstage/backstage", - "directory": "plugins/catalog-react" - }, - "keywords": [ - "backstage" + "files": [ + "dist" ], - "sideEffects": false, "scripts": { "build": "backstage-cli package build", + "clean": "backstage-cli package clean", "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", "postpack": "backstage-cli package postpack", - "clean": "backstage-cli package clean", - "start": "backstage-cli package start" + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/catalog-client": "workspace:^", @@ -71,11 +82,6 @@ "yaml": "^2.0.0", "zen-observable": "^0.10.0" }, - "peerDependencies": { - "react": "^16.13.1 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", - "react-router-dom": "6.0.0-beta.0 || ^6.3.0" - }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/core-app-api": "workspace:^", @@ -89,7 +95,9 @@ "@types/zen-observable": "^0.8.0", "react-test-renderer": "^16.13.1" }, - "files": [ - "dist" - ] + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-router-dom": "6.0.0-beta.0 || ^6.3.0" + } } diff --git a/plugins/catalog-unprocessed-entities-common/package.json b/plugins/catalog-unprocessed-entities-common/package.json index 75e85a44e0..21e85e426f 100644 --- a/plugins/catalog-unprocessed-entities-common/package.json +++ b/plugins/catalog-unprocessed-entities-common/package.json @@ -3,7 +3,12 @@ "version": "0.0.1", "description": "Common functionalities for the catalog-unprocessed-entities plugin", "backstage": { - "role": "common-library" + "role": "common-library", + "pluginId": "catalog-unprocessed-entities", + "pluginPackages": [ + "@backstage/plugin-catalog-unprocessed-entities", + "@backstage/plugin-catalog-unprocessed-entities-common" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/catalog-unprocessed-entities/package.json b/plugins/catalog-unprocessed-entities/package.json index 819fdb1a1c..c8e91c7061 100644 --- a/plugins/catalog-unprocessed-entities/package.json +++ b/plugins/catalog-unprocessed-entities/package.json @@ -2,7 +2,12 @@ "name": "@backstage/plugin-catalog-unprocessed-entities", "version": "0.2.5-next.1", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "catalog-unprocessed-entities", + "pluginPackages": [ + "@backstage/plugin-catalog-unprocessed-entities", + "@backstage/plugin-catalog-unprocessed-entities-common" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index e100dab473..92ba874b24 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -3,7 +3,15 @@ "version": "1.21.0-next.2", "description": "The Backstage plugin for browsing the Backstage catalog", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "catalog", + "pluginPackages": [ + "@backstage/plugin-catalog", + "@backstage/plugin-catalog-backend", + "@backstage/plugin-catalog-common", + "@backstage/plugin-catalog-node", + "@backstage/plugin-catalog-react" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index d40e47a45e..f838b355f7 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -3,7 +3,11 @@ "version": "0.1.56-next.1", "description": "A Backstage plugin that lets you browse the configuration schema of your app", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "config-schema", + "pluginPackages": [ + "@backstage/plugin-config-schema" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/devtools-backend/package.json b/plugins/devtools-backend/package.json index 7e9727f534..adbc645b93 100644 --- a/plugins/devtools-backend/package.json +++ b/plugins/devtools-backend/package.json @@ -1,31 +1,41 @@ { "name": "@backstage/plugin-devtools-backend", "version": "0.3.5-next.2", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "backstage": { + "role": "backend-plugin", + "pluginId": "devtools", + "pluginPackages": [ + "@backstage/plugin-devtools", + "@backstage/plugin-devtools-backend", + "@backstage/plugin-devtools-common" + ] + }, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, - "backstage": { - "role": "backend-plugin" - }, "homepage": "https://backstage.io", "repository": { "type": "git", "url": "https://github.com/backstage/backstage", "directory": "plugins/devtools-backend" }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist", + "config.d.ts" + ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack" + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-common": "workspace:^", @@ -60,9 +70,5 @@ "@types/yarnpkg__lockfile": "^1.1.4", "supertest": "^6.2.4" }, - "files": [ - "dist", - "config.d.ts" - ], "configSchema": "config.d.ts" } diff --git a/plugins/devtools-common/package.json b/plugins/devtools-common/package.json index 1cce2487f6..fb664adabc 100644 --- a/plugins/devtools-common/package.json +++ b/plugins/devtools-common/package.json @@ -3,7 +3,13 @@ "version": "0.1.9", "description": "Common functionalities for the devtools plugin", "backstage": { - "role": "common-library" + "role": "common-library", + "pluginId": "devtools", + "pluginPackages": [ + "@backstage/plugin-devtools", + "@backstage/plugin-devtools-backend", + "@backstage/plugin-devtools-common" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/devtools/package.json b/plugins/devtools/package.json index 760a70bc62..71795111a4 100644 --- a/plugins/devtools/package.json +++ b/plugins/devtools/package.json @@ -1,17 +1,33 @@ { "name": "@backstage/plugin-devtools", "version": "0.1.15-next.1", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "backstage": { + "role": "frontend-plugin", + "pluginId": "devtools", + "pluginPackages": [ + "@backstage/plugin-devtools", + "@backstage/plugin-devtools-backend", + "@backstage/plugin-devtools-common" + ] + }, "publishConfig": { "access": "public" }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/devtools" + }, + "license": "Apache-2.0", + "sideEffects": false, "exports": { ".": "./src/index.ts", "./alpha": "./src/alpha.ts", "./package.json": "./package.json" }, + "main": "src/index.ts", + "types": "src/index.ts", "typesVersions": { "*": { "alpha": [ @@ -22,24 +38,17 @@ ] } }, - "backstage": { - "role": "frontend-plugin" - }, - "homepage": "https://backstage.io", - "repository": { - "type": "git", - "url": "https://github.com/backstage/backstage", - "directory": "plugins/devtools" - }, - "sideEffects": false, + "files": [ + "dist" + ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack" + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/core-compat-api": "workspace:^", @@ -55,18 +64,15 @@ "react-json-view": "^1.21.3", "react-use": "^17.2.4" }, - "peerDependencies": { - "@types/react": "^16.13.1 || ^17.0.0 || ^18.0.0", - "react": "^16.13.1 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", - "react-router-dom": "6.0.0-beta.0 || ^6.3.0" - }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/dev-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0" }, - "files": [ - "dist" - ] + "peerDependencies": { + "@types/react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-router-dom": "6.0.0-beta.0 || ^6.3.0" + } } diff --git a/plugins/events-backend-module-aws-sqs/package.json b/plugins/events-backend-module-aws-sqs/package.json index 3b8cdbf064..6d48c7aec9 100644 --- a/plugins/events-backend-module-aws-sqs/package.json +++ b/plugins/events-backend-module-aws-sqs/package.json @@ -2,7 +2,9 @@ "name": "@backstage/plugin-events-backend-module-aws-sqs", "version": "0.3.5-next.2", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "events", + "pluginPackage": "@backstage/plugin-events-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/events-backend-module-azure/package.json b/plugins/events-backend-module-azure/package.json index 2dccb516a1..950e2f2675 100644 --- a/plugins/events-backend-module-azure/package.json +++ b/plugins/events-backend-module-azure/package.json @@ -2,7 +2,9 @@ "name": "@backstage/plugin-events-backend-module-azure", "version": "0.2.5-next.1", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "events", + "pluginPackage": "@backstage/plugin-events-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/events-backend-module-bitbucket-cloud/package.json b/plugins/events-backend-module-bitbucket-cloud/package.json index 93e46be069..85570c8c43 100644 --- a/plugins/events-backend-module-bitbucket-cloud/package.json +++ b/plugins/events-backend-module-bitbucket-cloud/package.json @@ -2,7 +2,9 @@ "name": "@backstage/plugin-events-backend-module-bitbucket-cloud", "version": "0.2.5-next.1", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "events", + "pluginPackage": "@backstage/plugin-events-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/events-backend-module-gerrit/package.json b/plugins/events-backend-module-gerrit/package.json index f0296e341b..0867b52bf9 100644 --- a/plugins/events-backend-module-gerrit/package.json +++ b/plugins/events-backend-module-gerrit/package.json @@ -2,7 +2,9 @@ "name": "@backstage/plugin-events-backend-module-gerrit", "version": "0.2.5-next.1", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "events", + "pluginPackage": "@backstage/plugin-events-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/events-backend-module-github/package.json b/plugins/events-backend-module-github/package.json index 152a507203..a661ecde9f 100644 --- a/plugins/events-backend-module-github/package.json +++ b/plugins/events-backend-module-github/package.json @@ -2,7 +2,9 @@ "name": "@backstage/plugin-events-backend-module-github", "version": "0.2.5-next.1", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "events", + "pluginPackage": "@backstage/plugin-events-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/events-backend-module-gitlab/package.json b/plugins/events-backend-module-gitlab/package.json index a429a5eb15..1f03224f25 100644 --- a/plugins/events-backend-module-gitlab/package.json +++ b/plugins/events-backend-module-gitlab/package.json @@ -2,7 +2,9 @@ "name": "@backstage/plugin-events-backend-module-gitlab", "version": "0.2.5-next.1", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "events", + "pluginPackage": "@backstage/plugin-events-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/events-backend-test-utils/package.json b/plugins/events-backend-test-utils/package.json index 951b7cc162..0208778cd4 100644 --- a/plugins/events-backend-test-utils/package.json +++ b/plugins/events-backend-test-utils/package.json @@ -3,7 +3,13 @@ "version": "0.1.29-next.1", "description": "The plugin-events-backend-test-utils for @backstage/plugin-events-node", "backstage": { - "role": "node-library" + "role": "node-library", + "pluginId": "events", + "pluginPackages": [ + "@backstage/plugin-events-backend", + "@backstage/plugin-events-backend-test-utils", + "@backstage/plugin-events-node" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/events-backend/package.json b/plugins/events-backend/package.json index 7d4de4bca9..689e6098fb 100644 --- a/plugins/events-backend/package.json +++ b/plugins/events-backend/package.json @@ -2,7 +2,13 @@ "name": "@backstage/plugin-events-backend", "version": "0.3.6-next.2", "backstage": { - "role": "backend-plugin" + "role": "backend-plugin", + "pluginId": "events", + "pluginPackages": [ + "@backstage/plugin-events-backend", + "@backstage/plugin-events-backend-test-utils", + "@backstage/plugin-events-node" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/events-node/package.json b/plugins/events-node/package.json index a2fecb64e3..d52f6b6bf6 100644 --- a/plugins/events-node/package.json +++ b/plugins/events-node/package.json @@ -3,7 +3,13 @@ "version": "0.3.5-next.1", "description": "The plugin-events-node module for @backstage/plugin-events-backend", "backstage": { - "role": "node-library" + "role": "node-library", + "pluginId": "events", + "pluginPackages": [ + "@backstage/plugin-events-backend", + "@backstage/plugin-events-backend-test-utils", + "@backstage/plugin-events-node" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index e643eddc30..df80afa8d4 100644 --- a/plugins/example-todo-list-backend/package.json +++ b/plugins/example-todo-list-backend/package.json @@ -2,7 +2,13 @@ "name": "@internal/plugin-todo-list-backend", "version": "1.0.28-next.2", "backstage": { - "role": "backend-plugin" + "role": "backend-plugin", + "pluginId": "todo-list", + "pluginPackages": [ + "@internal/plugin-todo-list", + "@internal/plugin-todo-list-backend", + "@internal/plugin-todo-list-common" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/example-todo-list-common/package.json b/plugins/example-todo-list-common/package.json index 746908d0bb..8843bb86ec 100644 --- a/plugins/example-todo-list-common/package.json +++ b/plugins/example-todo-list-common/package.json @@ -2,7 +2,13 @@ "name": "@internal/plugin-todo-list-common", "version": "1.0.18", "backstage": { - "role": "common-library" + "role": "common-library", + "pluginId": "todo-list", + "pluginPackages": [ + "@internal/plugin-todo-list", + "@internal/plugin-todo-list-backend", + "@internal/plugin-todo-list-common" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index 06062e590d..916939f40f 100644 --- a/plugins/example-todo-list/package.json +++ b/plugins/example-todo-list/package.json @@ -2,7 +2,13 @@ "name": "@internal/plugin-todo-list", "version": "1.0.28-next.1", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "todo-list", + "pluginPackages": [ + "@internal/plugin-todo-list", + "@internal/plugin-todo-list-backend", + "@internal/plugin-todo-list-common" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/home-react/package.json b/plugins/home-react/package.json index 37c6c185d3..2a081579a8 100644 --- a/plugins/home-react/package.json +++ b/plugins/home-react/package.json @@ -3,7 +3,12 @@ "version": "0.1.14-next.1", "description": "A Backstage plugin that contains react components helps you build a home page", "backstage": { - "role": "web-library" + "role": "web-library", + "pluginId": "home", + "pluginPackages": [ + "@backstage/plugin-home", + "@backstage/plugin-home-react" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/home/package.json b/plugins/home/package.json index 52d27dbf58..f28e3db13d 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -3,7 +3,12 @@ "version": "0.7.5-next.1", "description": "A Backstage plugin that helps you build a home page", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "home", + "pluginPackages": [ + "@backstage/plugin-home", + "@backstage/plugin-home-react" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 2e097c1142..24d95cc020 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -1,18 +1,39 @@ { "name": "@backstage/plugin-kubernetes-backend", - "description": "A Backstage backend plugin that integrates towards Kubernetes", "version": "0.18.0-next.2", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "A Backstage backend plugin that integrates towards Kubernetes", + "backstage": { + "role": "backend-plugin", + "pluginId": "kubernetes", + "pluginPackages": [ + "@backstage/plugin-kubernetes", + "@backstage/plugin-kubernetes-backend", + "@backstage/plugin-kubernetes-common", + "@backstage/plugin-kubernetes-node", + "@backstage/plugin-kubernetes-react" + ] + }, "publishConfig": { "access": "public" }, + "keywords": [ + "backstage", + "kubernetes" + ], + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/kubernetes-backend" + }, + "license": "Apache-2.0", "exports": { ".": "./src/index.ts", "./alpha": "./src/alpha.ts", "./package.json": "./package.json" }, + "main": "src/index.ts", + "types": "src/index.ts", "typesVersions": { "*": { "alpha": [ @@ -23,28 +44,18 @@ ] } }, - "backstage": { - "role": "backend-plugin" - }, - "homepage": "https://backstage.io", - "repository": { - "type": "git", - "url": "https://github.com/backstage/backstage", - "directory": "plugins/kubernetes-backend" - }, - "keywords": [ - "backstage", - "kubernetes" + "files": [ + "dist", + "config.d.ts" ], - "configSchema": "config.d.ts", "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", + "clean": "backstage-cli package clean", "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", "postpack": "backstage-cli package postpack", - "clean": "backstage-cli package clean" + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@aws-crypto/sha256-js": "^5.0.0", @@ -97,8 +108,5 @@ "supertest": "^6.1.3", "ws": "^8.13.0" }, - "files": [ - "dist", - "config.d.ts" - ] + "configSchema": "config.d.ts" } diff --git a/plugins/kubernetes-cluster/package.json b/plugins/kubernetes-cluster/package.json index d032371e46..4cd646eae1 100644 --- a/plugins/kubernetes-cluster/package.json +++ b/plugins/kubernetes-cluster/package.json @@ -3,7 +3,11 @@ "version": "0.0.12-next.2", "description": "A Backstage plugin that shows details of Kubernetes clusters", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "kubernetes-cluster", + "pluginPackages": [ + "@backstage/plugin-kubernetes-cluster" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index 64807dd61f..420805462a 100644 --- a/plugins/kubernetes-common/package.json +++ b/plugins/kubernetes-common/package.json @@ -3,7 +3,15 @@ "version": "0.8.0-next.0", "description": "Common functionalities for kubernetes, to be shared between kubernetes and kubernetes-backend plugin", "backstage": { - "role": "common-library" + "role": "common-library", + "pluginId": "kubernetes", + "pluginPackages": [ + "@backstage/plugin-kubernetes", + "@backstage/plugin-kubernetes-backend", + "@backstage/plugin-kubernetes-common", + "@backstage/plugin-kubernetes-node", + "@backstage/plugin-kubernetes-react" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/kubernetes-node/package.json b/plugins/kubernetes-node/package.json index d20cc18d92..933d43184b 100644 --- a/plugins/kubernetes-node/package.json +++ b/plugins/kubernetes-node/package.json @@ -3,7 +3,15 @@ "version": "0.1.13-next.2", "description": "Node.js library for the kubernetes plugin", "backstage": { - "role": "node-library" + "role": "node-library", + "pluginId": "kubernetes", + "pluginPackages": [ + "@backstage/plugin-kubernetes", + "@backstage/plugin-kubernetes-backend", + "@backstage/plugin-kubernetes-common", + "@backstage/plugin-kubernetes-node", + "@backstage/plugin-kubernetes-react" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/kubernetes-react/package.json b/plugins/kubernetes-react/package.json index 6dca53fc50..00b96fed78 100644 --- a/plugins/kubernetes-react/package.json +++ b/plugins/kubernetes-react/package.json @@ -1,10 +1,18 @@ { "name": "@backstage/plugin-kubernetes-react", - "description": "Web library for the kubernetes-react plugin", "version": "0.4.0-next.2", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "Web library for the kubernetes-react plugin", + "backstage": { + "role": "web-library", + "pluginId": "kubernetes", + "pluginPackages": [ + "@backstage/plugin-kubernetes", + "@backstage/plugin-kubernetes-backend", + "@backstage/plugin-kubernetes-common", + "@backstage/plugin-kubernetes-node", + "@backstage/plugin-kubernetes-react" + ] + }, "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -15,19 +23,22 @@ "url": "https://github.com/backstage/backstage", "directory": "plugins/kubernetes-react" }, - "backstage": { - "role": "web-library" - }, + "license": "Apache-2.0", "sideEffects": false, - "configSchema": "config.d.ts", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist", + "config.d.ts" + ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack" + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/catalog-model": "workspace:^", @@ -53,9 +64,6 @@ "xterm-addon-attach": "^0.9.0", "xterm-addon-fit": "^0.8.0" }, - "peerDependencies": { - "react": "^16.13.1 || ^17.0.0 || ^18.0.0" - }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/core-app-api": "workspace:^", @@ -65,8 +73,8 @@ "jest-websocket-mock": "^2.5.0", "msw": "^1.3.1" }, - "files": [ - "dist", - "config.d.ts" - ] + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0 || ^18.0.0" + }, + "configSchema": "config.d.ts" } diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index cd8c1c0bf8..7262129adb 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -1,37 +1,48 @@ { "name": "@backstage/plugin-kubernetes", - "description": "A Backstage plugin that integrates towards Kubernetes", "version": "0.11.11-next.2", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "A Backstage plugin that integrates towards Kubernetes", + "backstage": { + "role": "frontend-plugin", + "pluginId": "kubernetes", + "pluginPackages": [ + "@backstage/plugin-kubernetes", + "@backstage/plugin-kubernetes-backend", + "@backstage/plugin-kubernetes-common", + "@backstage/plugin-kubernetes-node", + "@backstage/plugin-kubernetes-react" + ] + }, "publishConfig": { "access": "public", "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, - "backstage": { - "role": "frontend-plugin" - }, + "keywords": [ + "backstage", + "kubernetes" + ], "homepage": "https://backstage.io", "repository": { "type": "git", "url": "https://github.com/backstage/backstage", "directory": "plugins/kubernetes" }, - "keywords": [ - "backstage", - "kubernetes" - ], + "license": "Apache-2.0", "sideEffects": false, + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], "scripts": { "build": "backstage-cli package build", - "start": "backstage-cli package start", + "clean": "backstage-cli package clean", "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", "postpack": "backstage-cli package postpack", - "clean": "backstage-cli package clean" + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/catalog-model": "workspace:^", @@ -54,11 +65,6 @@ "xterm-addon-attach": "^0.9.0", "xterm-addon-fit": "^0.8.0" }, - "peerDependencies": { - "react": "^16.13.1 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", - "react-router-dom": "6.0.0-beta.0 || ^6.3.0" - }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/dev-utils": "workspace:^", @@ -67,7 +73,9 @@ "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^15.0.0" }, - "files": [ - "dist" - ] + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-router-dom": "6.0.0-beta.0 || ^6.3.0" + } } diff --git a/plugins/notifications-backend-module-email/package.json b/plugins/notifications-backend-module-email/package.json index ac3ec8e1c2..4e6ac85fcf 100644 --- a/plugins/notifications-backend-module-email/package.json +++ b/plugins/notifications-backend-module-email/package.json @@ -3,7 +3,9 @@ "version": "0.1.0-next.2", "description": "The email backend module for the notifications plugin.", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "notifications", + "pluginPackage": "@backstage/plugin-notifications-backend" }, "publishConfig": { "access": "public", diff --git a/plugins/notifications-backend/package.json b/plugins/notifications-backend/package.json index accc8e2d9f..403b86d5b0 100644 --- a/plugins/notifications-backend/package.json +++ b/plugins/notifications-backend/package.json @@ -2,7 +2,14 @@ "name": "@backstage/plugin-notifications-backend", "version": "0.3.0-next.2", "backstage": { - "role": "backend-plugin" + "role": "backend-plugin", + "pluginId": "notifications", + "pluginPackages": [ + "@backstage/plugin-notifications", + "@backstage/plugin-notifications-backend", + "@backstage/plugin-notifications-common", + "@backstage/plugin-notifications-node" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/notifications-common/package.json b/plugins/notifications-common/package.json index 2745230a4a..d3ca76342c 100644 --- a/plugins/notifications-common/package.json +++ b/plugins/notifications-common/package.json @@ -3,7 +3,14 @@ "version": "0.0.3", "description": "Common functionalities for the notifications plugin", "backstage": { - "role": "common-library" + "role": "common-library", + "pluginId": "notifications", + "pluginPackages": [ + "@backstage/plugin-notifications", + "@backstage/plugin-notifications-backend", + "@backstage/plugin-notifications-common", + "@backstage/plugin-notifications-node" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/notifications-node/package.json b/plugins/notifications-node/package.json index 0fc75d3a72..ea1ed94e81 100644 --- a/plugins/notifications-node/package.json +++ b/plugins/notifications-node/package.json @@ -3,7 +3,14 @@ "version": "0.2.0-next.2", "description": "Node.js library for the notifications plugin", "backstage": { - "role": "node-library" + "role": "node-library", + "pluginId": "notifications", + "pluginPackages": [ + "@backstage/plugin-notifications", + "@backstage/plugin-notifications-backend", + "@backstage/plugin-notifications-common", + "@backstage/plugin-notifications-node" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/notifications/package.json b/plugins/notifications/package.json index a5bd2a7d9b..0cfd15648c 100644 --- a/plugins/notifications/package.json +++ b/plugins/notifications/package.json @@ -2,7 +2,14 @@ "name": "@backstage/plugin-notifications", "version": "0.2.2-next.2", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "notifications", + "pluginPackages": [ + "@backstage/plugin-notifications", + "@backstage/plugin-notifications-backend", + "@backstage/plugin-notifications-common", + "@backstage/plugin-notifications-node" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index 6a78114b2a..a89fcd9eb1 100644 --- a/plugins/org-react/package.json +++ b/plugins/org-react/package.json @@ -2,7 +2,12 @@ "name": "@backstage/plugin-org-react", "version": "0.1.25-next.1", "backstage": { - "role": "web-library" + "role": "web-library", + "pluginId": "org", + "pluginPackages": [ + "@backstage/plugin-org", + "@backstage/plugin-org-react" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/org/package.json b/plugins/org/package.json index fcf8b58725..17435095f8 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -3,7 +3,12 @@ "version": "0.6.26-next.1", "description": "A Backstage plugin that helps you create entity pages for your organization", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "org", + "pluginPackages": [ + "@backstage/plugin-org", + "@backstage/plugin-org-react" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/permission-backend-module-policy-allow-all/package.json b/plugins/permission-backend-module-policy-allow-all/package.json index 41d972cc1b..e48bc83bc2 100644 --- a/plugins/permission-backend-module-policy-allow-all/package.json +++ b/plugins/permission-backend-module-policy-allow-all/package.json @@ -3,7 +3,9 @@ "version": "0.1.16-next.1", "description": "Allow all policy backend module for the permission plugin.", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "permission", + "pluginPackage": "@backstage/plugin-permission-backend" }, "publishConfig": { "access": "public", diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index 3e4fa61c3d..469d988ac6 100644 --- a/plugins/permission-backend/package.json +++ b/plugins/permission-backend/package.json @@ -2,7 +2,14 @@ "name": "@backstage/plugin-permission-backend", "version": "0.5.43-next.2", "backstage": { - "role": "backend-plugin" + "role": "backend-plugin", + "pluginId": "permission", + "pluginPackages": [ + "@backstage/plugin-permission-backend", + "@backstage/plugin-permission-common", + "@backstage/plugin-permission-node", + "@backstage/plugin-permission-react" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/permission-common/package.json b/plugins/permission-common/package.json index d0f8f7ffc4..1080bf00fb 100644 --- a/plugins/permission-common/package.json +++ b/plugins/permission-common/package.json @@ -3,7 +3,14 @@ "version": "0.7.13", "description": "Isomorphic types and client for Backstage permissions and authorization", "backstage": { - "role": "common-library" + "role": "common-library", + "pluginId": "permission", + "pluginPackages": [ + "@backstage/plugin-permission-backend", + "@backstage/plugin-permission-common", + "@backstage/plugin-permission-node", + "@backstage/plugin-permission-react" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index 7d172fadf7..7d64063d91 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -1,18 +1,38 @@ { "name": "@backstage/plugin-permission-node", - "description": "Common permission and authorization utilities for backend plugins", "version": "0.7.30-next.2", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "Common permission and authorization utilities for backend plugins", + "backstage": { + "role": "node-library", + "pluginId": "permission", + "pluginPackages": [ + "@backstage/plugin-permission-backend", + "@backstage/plugin-permission-common", + "@backstage/plugin-permission-node", + "@backstage/plugin-permission-react" + ] + }, "publishConfig": { "access": "public" }, + "keywords": [ + "backstage", + "permissions" + ], + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/permission-node" + }, + "license": "Apache-2.0", "exports": { ".": "./src/index.ts", "./alpha": "./src/alpha.ts", "./package.json": "./package.json" }, + "main": "src/index.ts", + "types": "src/index.ts", "typesVersions": { "*": { "alpha": [ @@ -23,27 +43,17 @@ ] } }, - "backstage": { - "role": "node-library" - }, - "homepage": "https://backstage.io", - "repository": { - "type": "git", - "url": "https://github.com/backstage/backstage", - "directory": "plugins/permission-node" - }, - "keywords": [ - "backstage", - "permissions" + "files": [ + "dist" ], "scripts": { "build": "backstage-cli package build", + "clean": "backstage-cli package clean", "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", "postpack": "backstage-cli package postpack", - "clean": "backstage-cli package clean", - "start": "backstage-cli package start" + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-common": "workspace:^", @@ -64,8 +74,5 @@ "@types/supertest": "^2.0.8", "msw": "^1.0.0", "supertest": "^6.1.3" - }, - "files": [ - "dist" - ] + } } diff --git a/plugins/permission-react/package.json b/plugins/permission-react/package.json index 25d3a8554c..9105a401a8 100644 --- a/plugins/permission-react/package.json +++ b/plugins/permission-react/package.json @@ -2,7 +2,14 @@ "name": "@backstage/plugin-permission-react", "version": "0.4.23-next.0", "backstage": { - "role": "web-library" + "role": "web-library", + "pluginId": "permission", + "pluginPackages": [ + "@backstage/plugin-permission-backend", + "@backstage/plugin-permission-common", + "@backstage/plugin-permission-node", + "@backstage/plugin-permission-react" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 37127b9ad8..f229ec8c6a 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -3,7 +3,11 @@ "version": "0.5.0-next.2", "description": "A Backstage backend plugin that helps you set up proxy endpoints in the backend", "backstage": { - "role": "backend-plugin" + "role": "backend-plugin", + "pluginId": "proxy", + "pluginPackages": [ + "@backstage/plugin-proxy-backend" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/scaffolder-backend-module-azure/package.json b/plugins/scaffolder-backend-module-azure/package.json index 05e4add652..23af17730e 100644 --- a/plugins/scaffolder-backend-module-azure/package.json +++ b/plugins/scaffolder-backend-module-azure/package.json @@ -3,7 +3,9 @@ "version": "0.1.11-next.1", "description": "The azure module for @backstage/plugin-scaffolder-backend", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "scaffolder", + "pluginPackage": "@backstage/plugin-scaffolder-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/package.json b/plugins/scaffolder-backend-module-bitbucket-cloud/package.json index c8beed9126..bd69da6fe4 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/package.json +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/package.json @@ -3,7 +3,9 @@ "version": "0.1.9-next.1", "description": "The Bitbucket Cloud module for @backstage/plugin-scaffolder-backend", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "scaffolder", + "pluginPackage": "@backstage/plugin-scaffolder-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/scaffolder-backend-module-bitbucket-server/package.json b/plugins/scaffolder-backend-module-bitbucket-server/package.json index 88d8ab70ce..779767cd0b 100644 --- a/plugins/scaffolder-backend-module-bitbucket-server/package.json +++ b/plugins/scaffolder-backend-module-bitbucket-server/package.json @@ -3,7 +3,9 @@ "version": "0.1.9-next.1", "description": "The Bitbucket Server module for @backstage/plugin-scaffolder-backend", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "scaffolder", + "pluginPackage": "@backstage/plugin-scaffolder-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/scaffolder-backend-module-bitbucket/package.json b/plugins/scaffolder-backend-module-bitbucket/package.json index e10d909548..fa4f09c729 100644 --- a/plugins/scaffolder-backend-module-bitbucket/package.json +++ b/plugins/scaffolder-backend-module-bitbucket/package.json @@ -3,7 +3,9 @@ "version": "0.2.9-next.1", "description": "The bitbucket module for @backstage/plugin-scaffolder-backend", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "scaffolder", + "pluginPackage": "@backstage/plugin-scaffolder-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/package.json b/plugins/scaffolder-backend-module-confluence-to-markdown/package.json index 2d8ecb7f3d..a0dcf8ac42 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/package.json +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/package.json @@ -3,7 +3,9 @@ "version": "0.2.20-next.2", "description": "The confluence-to-markdown module for @backstage/plugin-scaffolder-backend", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "scaffolder", + "pluginPackage": "@backstage/plugin-scaffolder-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index 3ce10cc57b..14dd97be21 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/package.json +++ b/plugins/scaffolder-backend-module-cookiecutter/package.json @@ -3,7 +3,9 @@ "version": "0.2.43-next.2", "description": "A module for the scaffolder backend that lets you template projects using cookiecutter", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "scaffolder", + "pluginPackage": "@backstage/plugin-scaffolder-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/scaffolder-backend-module-gerrit/package.json b/plugins/scaffolder-backend-module-gerrit/package.json index 519c507e2c..064f7c6a34 100644 --- a/plugins/scaffolder-backend-module-gerrit/package.json +++ b/plugins/scaffolder-backend-module-gerrit/package.json @@ -3,7 +3,9 @@ "version": "0.1.11-next.1", "description": "The gerrit module for @backstage/plugin-scaffolder-backend", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "scaffolder", + "pluginPackage": "@backstage/plugin-scaffolder-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/scaffolder-backend-module-gitea/package.json b/plugins/scaffolder-backend-module-gitea/package.json index 34cf67e766..759c8c928a 100644 --- a/plugins/scaffolder-backend-module-gitea/package.json +++ b/plugins/scaffolder-backend-module-gitea/package.json @@ -3,7 +3,9 @@ "version": "0.1.9-next.2", "description": "The gitea module for @backstage/plugin-scaffolder-backend", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "scaffolder", + "pluginPackage": "@backstage/plugin-scaffolder-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/scaffolder-backend-module-github/package.json b/plugins/scaffolder-backend-module-github/package.json index 6f8b952eac..1887df205a 100644 --- a/plugins/scaffolder-backend-module-github/package.json +++ b/plugins/scaffolder-backend-module-github/package.json @@ -3,7 +3,9 @@ "version": "0.3.0-next.2", "description": "The github module for @backstage/plugin-scaffolder-backend", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "scaffolder", + "pluginPackage": "@backstage/plugin-scaffolder-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/scaffolder-backend-module-gitlab/package.json b/plugins/scaffolder-backend-module-gitlab/package.json index c0533513f4..3464882af3 100644 --- a/plugins/scaffolder-backend-module-gitlab/package.json +++ b/plugins/scaffolder-backend-module-gitlab/package.json @@ -2,7 +2,9 @@ "name": "@backstage/plugin-scaffolder-backend-module-gitlab", "version": "0.4.1-next.2", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "scaffolder", + "pluginPackage": "@backstage/plugin-scaffolder-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/scaffolder-backend-module-notifications/package.json b/plugins/scaffolder-backend-module-notifications/package.json index 490c9291be..0dba6267a0 100644 --- a/plugins/scaffolder-backend-module-notifications/package.json +++ b/plugins/scaffolder-backend-module-notifications/package.json @@ -3,7 +3,9 @@ "version": "0.0.2-next.2", "description": "The notifications backend module for the scaffolder plugin.", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "scaffolder", + "pluginPackage": "@backstage/plugin-scaffolder-backend" }, "publishConfig": { "access": "public", diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index ffd335ead0..7851c8f5d8 100644 --- a/plugins/scaffolder-backend-module-rails/package.json +++ b/plugins/scaffolder-backend-module-rails/package.json @@ -3,7 +3,9 @@ "version": "0.4.36-next.2", "description": "A module for the scaffolder backend that lets you template projects using Rails", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "scaffolder", + "pluginPackage": "@backstage/plugin-scaffolder-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/scaffolder-backend-module-sentry/package.json b/plugins/scaffolder-backend-module-sentry/package.json index 919cc1a8aa..026d3f6efa 100644 --- a/plugins/scaffolder-backend-module-sentry/package.json +++ b/plugins/scaffolder-backend-module-sentry/package.json @@ -2,7 +2,9 @@ "name": "@backstage/plugin-scaffolder-backend-module-sentry", "version": "0.1.27-next.2", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "scaffolder", + "pluginPackage": "@backstage/plugin-scaffolder-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index b03e49e0c5..d2006948c9 100644 --- a/plugins/scaffolder-backend-module-yeoman/package.json +++ b/plugins/scaffolder-backend-module-yeoman/package.json @@ -2,7 +2,9 @@ "name": "@backstage/plugin-scaffolder-backend-module-yeoman", "version": "0.3.2-next.1", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "scaffolder", + "pluginPackage": "@backstage/plugin-scaffolder-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 76ae1cfcc8..73f7631ed8 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -3,7 +3,16 @@ "version": "1.22.8-next.2", "description": "The Backstage backend plugin that helps you create new things", "backstage": { - "role": "backend-plugin" + "role": "backend-plugin", + "pluginId": "scaffolder", + "pluginPackages": [ + "@backstage/plugin-scaffolder", + "@backstage/plugin-scaffolder-backend", + "@backstage/plugin-scaffolder-common", + "@backstage/plugin-scaffolder-node", + "@backstage/plugin-scaffolder-node-test-utils", + "@backstage/plugin-scaffolder-react" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/scaffolder-common/package.json b/plugins/scaffolder-common/package.json index 04f3375520..54501d64e5 100644 --- a/plugins/scaffolder-common/package.json +++ b/plugins/scaffolder-common/package.json @@ -3,7 +3,16 @@ "version": "1.5.3-next.0", "description": "Common functionalities for the scaffolder, to be shared between scaffolder and scaffolder-backend plugin", "backstage": { - "role": "common-library" + "role": "common-library", + "pluginId": "scaffolder", + "pluginPackages": [ + "@backstage/plugin-scaffolder", + "@backstage/plugin-scaffolder-backend", + "@backstage/plugin-scaffolder-common", + "@backstage/plugin-scaffolder-node", + "@backstage/plugin-scaffolder-node-test-utils", + "@backstage/plugin-scaffolder-react" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/scaffolder-node-test-utils/package.json b/plugins/scaffolder-node-test-utils/package.json index 1c5d6445bd..2f46101b3c 100644 --- a/plugins/scaffolder-node-test-utils/package.json +++ b/plugins/scaffolder-node-test-utils/package.json @@ -2,7 +2,16 @@ "name": "@backstage/plugin-scaffolder-node-test-utils", "version": "0.1.5-next.2", "backstage": { - "role": "node-library" + "role": "node-library", + "pluginId": "scaffolder", + "pluginPackages": [ + "@backstage/plugin-scaffolder", + "@backstage/plugin-scaffolder-backend", + "@backstage/plugin-scaffolder-common", + "@backstage/plugin-scaffolder-node", + "@backstage/plugin-scaffolder-node-test-utils", + "@backstage/plugin-scaffolder-react" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/scaffolder-node/package.json b/plugins/scaffolder-node/package.json index 30e67477e0..aca3ff3f5a 100644 --- a/plugins/scaffolder-node/package.json +++ b/plugins/scaffolder-node/package.json @@ -3,7 +3,16 @@ "version": "0.4.5-next.2", "description": "The plugin-scaffolder-node module for @backstage/plugin-scaffolder-backend", "backstage": { - "role": "node-library" + "role": "node-library", + "pluginId": "scaffolder", + "pluginPackages": [ + "@backstage/plugin-scaffolder", + "@backstage/plugin-scaffolder-backend", + "@backstage/plugin-scaffolder-common", + "@backstage/plugin-scaffolder-node", + "@backstage/plugin-scaffolder-node-test-utils", + "@backstage/plugin-scaffolder-react" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index 084eb34d20..3138c992cd 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -3,7 +3,16 @@ "version": "1.8.7-next.2", "description": "A frontend library that helps other Backstage plugins interact with the Scaffolder", "backstage": { - "role": "web-library" + "role": "web-library", + "pluginId": "scaffolder", + "pluginPackages": [ + "@backstage/plugin-scaffolder", + "@backstage/plugin-scaffolder-backend", + "@backstage/plugin-scaffolder-common", + "@backstage/plugin-scaffolder-node", + "@backstage/plugin-scaffolder-node-test-utils", + "@backstage/plugin-scaffolder-react" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 87fb77defd..cb6842c1c0 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -3,7 +3,16 @@ "version": "1.21.0-next.2", "description": "The Backstage plugin that helps you create new things", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "scaffolder", + "pluginPackages": [ + "@backstage/plugin-scaffolder", + "@backstage/plugin-scaffolder-backend", + "@backstage/plugin-scaffolder-common", + "@backstage/plugin-scaffolder-node", + "@backstage/plugin-scaffolder-node-test-utils", + "@backstage/plugin-scaffolder-react" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/search-backend-module-catalog/package.json b/plugins/search-backend-module-catalog/package.json index dea1865fca..ddeb0cb823 100644 --- a/plugins/search-backend-module-catalog/package.json +++ b/plugins/search-backend-module-catalog/package.json @@ -3,7 +3,9 @@ "version": "0.1.25-next.2", "description": "A module for the search backend that exports catalog modules", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "search", + "pluginPackage": "@backstage/plugin-search-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index 3994977fd2..a8c245c4d3 100644 --- a/plugins/search-backend-module-elasticsearch/package.json +++ b/plugins/search-backend-module-elasticsearch/package.json @@ -3,7 +3,9 @@ "version": "1.4.2-next.2", "description": "A module for the search backend that implements search using ElasticSearch", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "search", + "pluginPackage": "@backstage/plugin-search-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/search-backend-module-explore/package.json b/plugins/search-backend-module-explore/package.json index a195eb08d9..2d177c73bf 100644 --- a/plugins/search-backend-module-explore/package.json +++ b/plugins/search-backend-module-explore/package.json @@ -3,7 +3,9 @@ "version": "0.1.25-next.2", "description": "A module for the search backend that exports explore modules", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "search", + "pluginPackage": "@backstage/plugin-search-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index f81eef8fc7..83f6d72875 100644 --- a/plugins/search-backend-module-pg/package.json +++ b/plugins/search-backend-module-pg/package.json @@ -3,7 +3,9 @@ "version": "0.5.28-next.2", "description": "A module for the search backend that implements search using PostgreSQL", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "search", + "pluginPackage": "@backstage/plugin-search-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/search-backend-module-stack-overflow-collator/package.json b/plugins/search-backend-module-stack-overflow-collator/package.json index 443cfe1155..c35347f8da 100644 --- a/plugins/search-backend-module-stack-overflow-collator/package.json +++ b/plugins/search-backend-module-stack-overflow-collator/package.json @@ -3,7 +3,9 @@ "version": "0.1.12-next.2", "description": "A module for the search backend that exports stack overflow modules", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "search", + "pluginPackage": "@backstage/plugin-search-backend" }, "publishConfig": { "access": "public", diff --git a/plugins/search-backend-module-techdocs/package.json b/plugins/search-backend-module-techdocs/package.json index 8690558f8a..d487866f3d 100644 --- a/plugins/search-backend-module-techdocs/package.json +++ b/plugins/search-backend-module-techdocs/package.json @@ -3,7 +3,9 @@ "version": "0.1.24-next.2", "description": "A module for the search backend that exports techdocs modules", "backstage": { - "role": "backend-plugin-module" + "role": "backend-plugin-module", + "pluginId": "search", + "pluginPackage": "@backstage/plugin-search-backend" }, "publishConfig": { "access": "public" diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index 36a6a5de13..20d5e70048 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -3,7 +3,11 @@ "version": "1.2.24-next.2", "description": "A library for Backstage backend plugins that want to interact with the search backend plugin", "backstage": { - "role": "node-library" + "role": "node-library", + "pluginId": "search-backend", + "pluginPackages": [ + "@backstage/plugin-search-backend-node" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index 4a550de16f..97287b8f87 100644 --- a/plugins/search-backend/package.json +++ b/plugins/search-backend/package.json @@ -3,7 +3,14 @@ "version": "1.5.10-next.2", "description": "The Backstage backend plugin that provides your backstage app with search", "backstage": { - "role": "backend-plugin" + "role": "backend-plugin", + "pluginId": "search", + "pluginPackages": [ + "@backstage/plugin-search", + "@backstage/plugin-search-backend", + "@backstage/plugin-search-common", + "@backstage/plugin-search-react" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/search-common/package.json b/plugins/search-common/package.json index 9a3c7bce03..346a248bf6 100644 --- a/plugins/search-common/package.json +++ b/plugins/search-common/package.json @@ -3,7 +3,14 @@ "version": "1.2.11", "description": "Common functionalities for Search, to be shared between various search-enabled plugins", "backstage": { - "role": "common-library" + "role": "common-library", + "pluginId": "search", + "pluginPackages": [ + "@backstage/plugin-search", + "@backstage/plugin-search-backend", + "@backstage/plugin-search-common", + "@backstage/plugin-search-react" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index b3fe4f0dc0..2cd8d0af3d 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -2,7 +2,14 @@ "name": "@backstage/plugin-search-react", "version": "1.7.12-next.1", "backstage": { - "role": "web-library" + "role": "web-library", + "pluginId": "search", + "pluginPackages": [ + "@backstage/plugin-search", + "@backstage/plugin-search-backend", + "@backstage/plugin-search-common", + "@backstage/plugin-search-react" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/search/package.json b/plugins/search/package.json index 46167d484c..bfc4f0f103 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -3,7 +3,14 @@ "version": "1.4.12-next.2", "description": "The Backstage plugin that provides your backstage app with search", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "search", + "pluginPackages": [ + "@backstage/plugin-search", + "@backstage/plugin-search-backend", + "@backstage/plugin-search-common", + "@backstage/plugin-search-react" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/signals-backend/package.json b/plugins/signals-backend/package.json index 9b9429cd8e..f4e4f03a8d 100644 --- a/plugins/signals-backend/package.json +++ b/plugins/signals-backend/package.json @@ -1,9 +1,16 @@ { "name": "@backstage/plugin-signals-backend", "version": "0.1.5-next.2", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "backstage": { + "role": "backend-plugin", + "pluginId": "signals", + "pluginPackages": [ + "@backstage/plugin-signals", + "@backstage/plugin-signals-backend", + "@backstage/plugin-signals-node", + "@backstage/plugin-signals-react" + ] + }, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", @@ -14,17 +21,20 @@ "url": "https://github.com/backstage/backstage", "directory": "plugins/signals-backend" }, - "backstage": { - "role": "backend-plugin" - }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack" + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-common": "workspace:^", @@ -55,8 +65,5 @@ "@types/ws": "^8.5.10", "msw": "^1.0.0", "supertest": "^6.2.4" - }, - "files": [ - "dist" - ] + } } diff --git a/plugins/signals-node/package.json b/plugins/signals-node/package.json index 7541d19ff8..e7eb39c9e1 100644 --- a/plugins/signals-node/package.json +++ b/plugins/signals-node/package.json @@ -1,10 +1,17 @@ { "name": "@backstage/plugin-signals-node", - "description": "Node.js library for the signals plugin", "version": "0.1.5-next.2", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", + "description": "Node.js library for the signals plugin", + "backstage": { + "role": "node-library", + "pluginId": "signals", + "pluginPackages": [ + "@backstage/plugin-signals", + "@backstage/plugin-signals-backend", + "@backstage/plugin-signals-node", + "@backstage/plugin-signals-react" + ] + }, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", @@ -15,24 +22,20 @@ "url": "https://github.com/backstage/backstage", "directory": "plugins/signals-node" }, - "backstage": { - "role": "node-library" - }, - "scripts": { - "build": "backstage-cli package build", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", - "clean": "backstage-cli package clean", - "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack" - }, - "devDependencies": { - "@backstage/cli": "workspace:^", - "@types/express": "^4.17.21" - }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", "files": [ "dist" ], + "scripts": { + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "test": "backstage-cli package test" + }, "dependencies": { "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", @@ -43,5 +46,9 @@ "express": "^4.17.1", "uuid": "^9.0.0", "ws": "^8.14.2" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@types/express": "^4.17.21" } } diff --git a/plugins/signals-react/package.json b/plugins/signals-react/package.json index 2812ef6aa8..37353a7d80 100644 --- a/plugins/signals-react/package.json +++ b/plugins/signals-react/package.json @@ -3,7 +3,14 @@ "version": "0.0.4-next.0", "description": "Web library for the signals plugin", "backstage": { - "role": "web-library" + "role": "web-library", + "pluginId": "signals", + "pluginPackages": [ + "@backstage/plugin-signals", + "@backstage/plugin-signals-backend", + "@backstage/plugin-signals-node", + "@backstage/plugin-signals-react" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/signals/package.json b/plugins/signals/package.json index d313593271..c211003927 100644 --- a/plugins/signals/package.json +++ b/plugins/signals/package.json @@ -2,7 +2,14 @@ "name": "@backstage/plugin-signals", "version": "0.0.7-next.1", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "signals", + "pluginPackages": [ + "@backstage/plugin-signals", + "@backstage/plugin-signals-backend", + "@backstage/plugin-signals-node", + "@backstage/plugin-signals-react" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index 8fe3c2a942..b3fa6128fb 100644 --- a/plugins/techdocs-addons-test-utils/package.json +++ b/plugins/techdocs-addons-test-utils/package.json @@ -2,7 +2,11 @@ "name": "@backstage/plugin-techdocs-addons-test-utils", "version": "1.0.33-next.1", "backstage": { - "role": "web-library" + "role": "web-library", + "pluginId": "techdocs-addons", + "pluginPackages": [ + "@backstage/plugin-techdocs-addons-test-utils" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index c6773b1f64..d202c35719 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -3,7 +3,14 @@ "version": "1.10.6-next.2", "description": "The Backstage backend plugin that renders technical documentation for your components", "backstage": { - "role": "backend-plugin" + "role": "backend-plugin", + "pluginId": "techdocs", + "pluginPackages": [ + "@backstage/plugin-techdocs", + "@backstage/plugin-techdocs-backend", + "@backstage/plugin-techdocs-node", + "@backstage/plugin-techdocs-react" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 8b0e76168a..7836dc3e05 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -3,7 +3,9 @@ "version": "1.1.11-next.1", "description": "Plugin module for contributed TechDocs Addons", "backstage": { - "role": "frontend-plugin-module" + "role": "frontend-plugin-module", + "pluginId": "techdocs", + "pluginPackage": "@backstage/plugin-techdocs" }, "publishConfig": { "access": "public", diff --git a/plugins/techdocs-node/package.json b/plugins/techdocs-node/package.json index 21bbc89f4d..fdedeb679d 100644 --- a/plugins/techdocs-node/package.json +++ b/plugins/techdocs-node/package.json @@ -3,7 +3,14 @@ "version": "1.12.5-next.2", "description": "Common node.js functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", "backstage": { - "role": "node-library" + "role": "node-library", + "pluginId": "techdocs", + "pluginPackages": [ + "@backstage/plugin-techdocs", + "@backstage/plugin-techdocs-backend", + "@backstage/plugin-techdocs-node", + "@backstage/plugin-techdocs-react" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index 8b10c5e3c9..601eeea739 100644 --- a/plugins/techdocs-react/package.json +++ b/plugins/techdocs-react/package.json @@ -3,7 +3,14 @@ "version": "1.2.5-next.1", "description": "Shared frontend utilities for TechDocs and Addons", "backstage": { - "role": "web-library" + "role": "web-library", + "pluginId": "techdocs", + "pluginPackages": [ + "@backstage/plugin-techdocs", + "@backstage/plugin-techdocs-backend", + "@backstage/plugin-techdocs-node", + "@backstage/plugin-techdocs-react" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index e4d6c0eaef..84c9df25a6 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -3,7 +3,14 @@ "version": "1.10.6-next.1", "description": "The Backstage plugin that renders technical documentation for your components", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "techdocs", + "pluginPackages": [ + "@backstage/plugin-techdocs", + "@backstage/plugin-techdocs-backend", + "@backstage/plugin-techdocs-node", + "@backstage/plugin-techdocs-react" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index 332c7eada1..ce15f2b6c3 100644 --- a/plugins/user-settings-backend/package.json +++ b/plugins/user-settings-backend/package.json @@ -3,7 +3,13 @@ "version": "0.2.18-next.2", "description": "The Backstage backend plugin to manage user settings", "backstage": { - "role": "backend-plugin" + "role": "backend-plugin", + "pluginId": "user-settings", + "pluginPackages": [ + "@backstage/plugin-user-settings", + "@backstage/plugin-user-settings-backend", + "@backstage/plugin-user-settings-common" + ] }, "publishConfig": { "access": "public" diff --git a/plugins/user-settings-common/package.json b/plugins/user-settings-common/package.json index 1575712a05..d36029092b 100644 --- a/plugins/user-settings-common/package.json +++ b/plugins/user-settings-common/package.json @@ -3,7 +3,13 @@ "version": "0.0.0", "description": "Common functionalities for the user-settings plugin", "backstage": { - "role": "common-library" + "role": "common-library", + "pluginId": "user-settings", + "pluginPackages": [ + "@backstage/plugin-user-settings", + "@backstage/plugin-user-settings-backend", + "@backstage/plugin-user-settings-common" + ] }, "publishConfig": { "access": "public", diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index ed9affbfe7..7546b8ca64 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -3,7 +3,13 @@ "version": "0.8.7-next.1", "description": "A Backstage plugin that provides a settings page", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "user-settings", + "pluginPackages": [ + "@backstage/plugin-user-settings", + "@backstage/plugin-user-settings-backend", + "@backstage/plugin-user-settings-common" + ] }, "publishConfig": { "access": "public" From c328131b10c80d9e99dbd73f5fd56582b32d57e7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 11 Jun 2024 10:24:10 +0200 Subject: [PATCH 32/46] changesets: added changesets for cli plugin metadata updates Signed-off-by: Patrik Oldsberg --- .changeset/blue-hairs-marry.md | 5 +++++ .changeset/tasty-horses-breathe.md | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 .changeset/blue-hairs-marry.md create mode 100644 .changeset/tasty-horses-breathe.md diff --git a/.changeset/blue-hairs-marry.md b/.changeset/blue-hairs-marry.md new file mode 100644 index 0000000000..2ca1a3d47e --- /dev/null +++ b/.changeset/blue-hairs-marry.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli-node': patch +--- + +Added new plugin metadata fields to `BackstagePackageJson` type. diff --git a/.changeset/tasty-horses-breathe.md b/.changeset/tasty-horses-breathe.md new file mode 100644 index 0000000000..afd20e6c4a --- /dev/null +++ b/.changeset/tasty-horses-breathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Added a new `--publish` flag to the `repo fix` command. This command will validate and if possible generate the metadata required for publishing packages with the Backstage CLI. In addition, a check has been added that the `backstage.pluginId` and `backstage.pluginPackage(s)` fields are present when packing a package for publishing. From 429c31f2d762e80aed340e2f4681165b5974f226 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 11 Jun 2024 11:18:42 +0200 Subject: [PATCH 33/46] cli: fix for repo fix always considering non-plugin packages changed Signed-off-by: Patrik Oldsberg --- packages/cli/src/commands/repo/fix.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/commands/repo/fix.ts b/packages/cli/src/commands/repo/fix.ts index 285dd75e3b..e7d243ea2c 100644 --- a/packages/cli/src/commands/repo/fix.ts +++ b/packages/cli/src/commands/repo/fix.ts @@ -302,11 +302,13 @@ export function fixPluginId(pkg: FixablePackage) { ); } - pkg.packageJson.backstage = { - ...pkg.packageJson.backstage, - pluginId: guessedPluginId, - }; - pkg.changed = true; + if (guessedPluginId) { + pkg.packageJson.backstage = { + ...pkg.packageJson.backstage, + pluginId: guessedPluginId, + }; + pkg.changed = true; + } } const backendPluginPackageNameByPluginId = new Map( From e615ac22f556a7a2c868ab5e4cea19a699db9502 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 11 Jun 2024 11:28:13 +0200 Subject: [PATCH 34/46] beps/0009: move to implementable Signed-off-by: Patrik Oldsberg --- beps/0009-plugin-metadata/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/beps/0009-plugin-metadata/README.md b/beps/0009-plugin-metadata/README.md index c019211123..79d7dc2172 100644 --- a/beps/0009-plugin-metadata/README.md +++ b/beps/0009-plugin-metadata/README.md @@ -1,6 +1,6 @@ --- title: Plugin Metadata -status: provisional +status: implementable authors: - '@Rugvip' owners: @@ -155,6 +155,8 @@ The following resources have been used to inform this proposal: The new metadata fields and any generation and validation of fields will initially be rolled out as part of the `repo fix` command in the Backstage CLI. In addition we will also add validation to the `yarn prepack` command in such a way that it does not interfere with backend package bundling, but does apply when packing packages for publishing. These changes will all be rolled out in a single release of the Backstage CLI, meaning that anyone publishing Backstage packages using the Backstage CLI will be required to provide the new metadata. +We will roll out these changes early on but be prepared to change the metadata structure if needed. Initially there will be very few consumers of this information, and it will be up to these consumers to handle the potentially varying versions of this metadata. We will aim to reach a stable state for the metadata as soon as possible, but we believe we need real world usage and feedback to get there. + ## Dependencies None From 798ec37c1cdaed5c87ea75abc5181f4eb5f1e101 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 12 May 2024 22:22:33 +0200 Subject: [PATCH 35/46] auth-node: initial scope manager refactor Signed-off-by: Patrik Oldsberg --- .changeset/clever-kids-return.md | 13 ++ plugins/auth-node/api-report.md | 20 +++ .../auth-node/src/oauth/CookieScopeManager.ts | 156 ++++++++++++++++++ .../auth-node/src/oauth/OAuthCookieManager.ts | 13 +- .../src/oauth/createOAuthProviderFactory.ts | 2 + .../src/oauth/createOAuthRouteHandlers.ts | 91 +++++----- plugins/auth-node/src/oauth/index.ts | 1 + plugins/auth-node/src/oauth/types.ts | 18 ++ 8 files changed, 267 insertions(+), 47 deletions(-) create mode 100644 .changeset/clever-kids-return.md create mode 100644 plugins/auth-node/src/oauth/CookieScopeManager.ts diff --git a/.changeset/clever-kids-return.md b/.changeset/clever-kids-return.md new file mode 100644 index 0000000000..a6cab79f2b --- /dev/null +++ b/.changeset/clever-kids-return.md @@ -0,0 +1,13 @@ +--- +'@backstage/plugin-auth-node': patch +--- + +Updated scope management for OAuth providers, where the `createOAuthAuthenticator` now accepts a new collection of `scopes` options: + +- `scopes.persist` - Whether scopes should be persisted, replaces the `shouldPersistScopes` option. +- `scopes.required` - A list of required scopes that will always be requested. +- `scopes.transform` - A function that can be used to transform the scopes before they are requested. + +The `createOAuthProviderFactory` has also received a new `additionalScopes` option, and will also read `additionalScopes` from the auth provider configuration. Both of these can be used to add additional scopes that should always be requested. + +A significant change under the hood that this new scope management brings is that providers that persist scopes will now always merge the already granted scopes with the requested ones. The previous behavior was that the full authorization flow would not include existing scopes, while the refresh flow would only include the existing scopes. diff --git a/plugins/auth-node/api-report.md b/plugins/auth-node/api-report.md index 6a43d3b127..dc1d86308a 100644 --- a/plugins/auth-node/api-report.md +++ b/plugins/auth-node/api-report.md @@ -173,6 +173,7 @@ export function createOAuthAuthenticator( // @public (undocumented) export function createOAuthProviderFactory(options: { authenticator: OAuthAuthenticator; + additionalScopes?: string[]; stateTransform?: OAuthStateTransform; profileTransform?: ProfileTransform>; signInResolver?: SignInResolver>; @@ -291,6 +292,8 @@ export interface OAuthAuthenticator { ctx: TContext, ): Promise>; // (undocumented) + scopes?: OAuthAuthenticatorScopeOptions; + // @deprecated (undocumented) shouldPersistScopes?: boolean; // (undocumented) start( @@ -336,6 +339,21 @@ export interface OAuthAuthenticatorResult { session: OAuthSession; } +// @public (undocumented) +export interface OAuthAuthenticatorScopeOptions { + // (undocumented) + persist?: boolean; + // (undocumented) + required?: string[]; + // (undocumented) + transform?: (options: { + requested: Iterable; + granted: Iterable; + required: Iterable; + additional: Iterable; + }) => Iterable; +} + // @public (undocumented) export interface OAuthAuthenticatorStartInput { // (undocumented) @@ -366,6 +384,8 @@ export class OAuthEnvironmentHandler implements AuthProviderRouteHandlers { // @public (undocumented) export interface OAuthRouteHandlersOptions { + // (undocumented) + additionalScopes?: string[]; // (undocumented) appUrl: string; // (undocumented) diff --git a/plugins/auth-node/src/oauth/CookieScopeManager.ts b/plugins/auth-node/src/oauth/CookieScopeManager.ts new file mode 100644 index 0000000000..f75bf71db1 --- /dev/null +++ b/plugins/auth-node/src/oauth/CookieScopeManager.ts @@ -0,0 +1,156 @@ +/* + * 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 express from 'express'; +import { + OAuthAuthenticator, + OAuthAuthenticatorResult, + OAuthAuthenticatorScopeOptions, +} from './types'; +import { OAuthCookieManager } from './OAuthCookieManager'; +import { OAuthState } from './state'; +import { AuthenticationError } from '@backstage/errors'; + +function reqRes(req: express.Request): express.Response { + const res = req.res; + if (!res) { + throw new Error('No response object found in request'); + } + return res; +} + +const defaultTransform: Required['transform'] = + ({ required, additional, requested, granted }) => { + return new Set([...required, ...requested, ...additional, ...granted]); + }; + +function splitScope(scope?: string): Iterable { + if (!scope) { + return []; + } + + return new Set(scope.split(/[\s|,]/).filter(Boolean)); +} + +export class CookieScopeManager { + static create(options: { + additionalScopes: string[]; + authenticator: OAuthAuthenticator; + cookieManager: OAuthCookieManager; + }) { + const { authenticator } = options; + + const shouldPersistScopes = + authenticator.scopes?.persist ?? + authenticator.shouldPersistScopes ?? + false; + + const transform = authenticator?.scopes?.transform ?? defaultTransform; + const additional = options.additionalScopes; + const required = authenticator?.scopes?.required ?? []; + + return new CookieScopeManager( + (requested, granted) => + Array.from( + transform({ required, additional, requested, granted }), + ).join(' '), + shouldPersistScopes ? options.cookieManager : undefined, + ); + } + + private constructor( + private readonly scopeTransform: ( + requested: Iterable, + granted: Iterable, + ) => string, + private readonly cookieManager?: OAuthCookieManager, + ) {} + + async start( + req: express.Request, + ): Promise<{ scopeState?: Partial; scope: string }> { + const requestScope = splitScope(req.query.scope?.toString()); + + const scope = this.scopeTransform(requestScope, []); + + if (this.cookieManager) { + // If scopes are persisted then we pass them through the state so that we + // can set the cookie on successful auth + return { + scope, + scopeState: { scope }, + }; + } + return { scope }; + } + + async handleCallback( + req: express.Request, + ctx: { + result: OAuthAuthenticatorResult; + state: OAuthState; + origin?: string; + }, + ): Promise { + // If we are not persisting scopes we can forward the scope from the result + if (!this.cookieManager) { + return ctx.result.session.scope; + } + + const scope = ctx.state.scope; + if (!scope) { + throw new AuthenticationError('No scope found in OAuth state'); + } + + // Store the scope that we have been granted for this session. This is useful if + // the provider does not return granted scopes on refresh or if they are normalized. + this.cookieManager.setGrantedScopes(reqRes(req), scope, ctx.origin); + + return scope; + } + + async clear(req: express.Request): Promise { + if (this.cookieManager) { + this.cookieManager.removeGrantedScopes(reqRes(req), req.get('origin')); + } + } + + async refresh(req: express.Request): Promise<{ + scope: string; + commit(result: OAuthAuthenticatorResult): Promise; + }> { + const requestScope = splitScope(req.query.scope?.toString()); + const grantedScope = splitScope(this.cookieManager?.getGrantedScopes(req)); + + const scope = this.scopeTransform(requestScope, grantedScope); + + return { + scope, + commit: async result => { + if (this.cookieManager) { + this.cookieManager.setGrantedScopes( + reqRes(req), + scope, + req.get('origin'), + ); + return scope; + } + + return result.session.scope; + }, + }; + } +} diff --git a/plugins/auth-node/src/oauth/OAuthCookieManager.ts b/plugins/auth-node/src/oauth/OAuthCookieManager.ts index 5fe2304610..1d06242a2e 100644 --- a/plugins/auth-node/src/oauth/OAuthCookieManager.ts +++ b/plugins/auth-node/src/oauth/OAuthCookieManager.ts @@ -106,6 +106,13 @@ export class OAuthCookieManager { }); } + removeGrantedScopes(res: Response, origin?: string) { + res.cookie(this.grantedScopeCookie, '', { + maxAge: 0, + ...this.getConfig(origin), + }); + } + setGrantedScopes(res: Response, scope: string, origin?: string) { res.cookie(this.grantedScopeCookie, scope, { maxAge: THOUSAND_DAYS_MS, @@ -113,15 +120,15 @@ export class OAuthCookieManager { }); } - getNonce(req: Request) { + getNonce(req: Request): string | undefined { return req.cookies[this.nonceCookie]; } - getRefreshToken(req: Request) { + getRefreshToken(req: Request): string | undefined { return req.cookies[this.refreshTokenCookie]; } - getGrantedScopes(req: Request) { + getGrantedScopes(req: Request): string | undefined { return req.cookies[this.grantedScopeCookie]; } } diff --git a/plugins/auth-node/src/oauth/createOAuthProviderFactory.ts b/plugins/auth-node/src/oauth/createOAuthProviderFactory.ts index 87fde6a1a2..a3387b7038 100644 --- a/plugins/auth-node/src/oauth/createOAuthProviderFactory.ts +++ b/plugins/auth-node/src/oauth/createOAuthProviderFactory.ts @@ -29,6 +29,7 @@ import { SignInResolverFactory } from '../sign-in/createSignInResolverFactory'; /** @public */ export function createOAuthProviderFactory(options: { authenticator: OAuthAuthenticator; + additionalScopes?: string[]; stateTransform?: OAuthStateTransform; profileTransform?: ProfileTransform>; signInResolver?: SignInResolver>; @@ -57,6 +58,7 @@ export function createOAuthProviderFactory(options: { cookieConfigurer: ctx.cookieConfigurer, providerId: ctx.providerId, resolverContext: ctx.resolverContext, + additionalScopes: options.additionalScopes, stateTransform: options.stateTransform, profileTransform: options.profileTransform, signInResolver, diff --git a/plugins/auth-node/src/oauth/createOAuthRouteHandlers.ts b/plugins/auth-node/src/oauth/createOAuthRouteHandlers.ts index a0735e3ba0..c13b58f2fc 100644 --- a/plugins/auth-node/src/oauth/createOAuthRouteHandlers.ts +++ b/plugins/auth-node/src/oauth/createOAuthRouteHandlers.ts @@ -27,7 +27,6 @@ import { encodeOAuthState, decodeOAuthState, OAuthStateTransform, - OAuthState, } from './state'; import { sendWebMessageResponse } from '../flow'; import { prepareBackstageIdentityResponse } from '../identity'; @@ -42,6 +41,7 @@ import { } from '../types'; import { OAuthAuthenticator, OAuthAuthenticatorResult } from './types'; import { Config } from '@backstage/config'; +import { CookieScopeManager } from './CookieScopeManager'; /** @public */ export interface OAuthRouteHandlersOptions { @@ -52,6 +52,7 @@ export interface OAuthRouteHandlersOptions { providerId: string; config: Config; resolverContext: AuthResolverContext; + additionalScopes?: string[]; stateTransform?: OAuthStateTransform; profileTransform?: ProfileTransform>; cookieConfigurer?: CookieConfigurer; @@ -111,14 +112,21 @@ export function createOAuthRouteHandlers( cookieConfigurer, }); + const scopeManager = CookieScopeManager.create({ + authenticator, + cookieManager, + additionalScopes: [ + ...(options.additionalScopes ?? []), + ...(config.getOptionalStringArray('additionalScopes') ?? []), + ], + }); + return { async start( this: never, req: express.Request, res: express.Response, ): Promise { - // retrieve scopes from request - const scope = req.query.scope?.toString() ?? ''; const env = req.query.env?.toString(); const origin = req.query.origin?.toString(); const redirectUrl = req.query.redirectUrl?.toString(); @@ -132,19 +140,17 @@ export function createOAuthRouteHandlers( // set a nonce cookie before redirecting to oauth provider cookieManager.setNonce(res, nonce, origin); - const state: OAuthState = { nonce, env, origin, redirectUrl, flow }; - - // If scopes are persisted then we pass them through the state so that we - // can set the cookie on successful auth - if (authenticator.shouldPersistScopes && scope) { - state.scope = scope; - } + const { scope, scopeState } = await scopeManager.start(req); + const state = { nonce, env, origin, redirectUrl, flow, ...scopeState }; const { state: transformedState } = await stateTransform(state, { req }); - const encodedState = encodeOAuthState(transformedState); const { url, status } = await options.authenticator.start( - { req, scope, state: encodedState }, + { + req, + scope, + state: encodeOAuthState(transformedState), + }, authenticatorCtx, ); @@ -159,19 +165,19 @@ export function createOAuthRouteHandlers( req: express.Request, res: express.Response, ): Promise { - let appOrigin = defaultAppOrigin; + let origin = defaultAppOrigin; try { const state = decodeOAuthState(req.query.state?.toString() ?? ''); if (state.origin) { try { - appOrigin = new URL(state.origin).origin; + origin = new URL(state.origin).origin; } catch { throw new NotAllowedError('App origin is invalid, failed to parse'); } - if (!isOriginAllowed(appOrigin)) { - throw new NotAllowedError(`Origin '${appOrigin}' is not allowed`); + if (!isOriginAllowed(origin)) { + throw new NotAllowedError(`Origin '${origin}' is not allowed`); } } @@ -191,38 +197,35 @@ export function createOAuthRouteHandlers( ); const { profile } = await profileTransform(result, resolverContext); + const signInResult = + signInResolver && + (await signInResolver({ profile, result }, resolverContext)); + + const grantedScopes = await scopeManager.handleCallback(req, { + result, + state, + origin, + }); + const response: ClientOAuthResponse = { profile, providerInfo: { idToken: result.session.idToken, accessToken: result.session.accessToken, - scope: result.session.scope, + scope: grantedScopes, expiresInSeconds: result.session.expiresInSeconds, }, + ...(signInResult && { + backstageIdentity: prepareBackstageIdentityResponse(signInResult), + }), }; - if (signInResolver) { - const identity = await signInResolver( - { profile, result }, - resolverContext, - ); - response.backstageIdentity = - prepareBackstageIdentityResponse(identity); - } - - // Store the scope that we have been granted for this session. This is useful if - // the provider does not return granted scopes on refresh or if they are normalized. - if (authenticator.shouldPersistScopes && state.scope) { - cookieManager.setGrantedScopes(res, state.scope, appOrigin); - response.providerInfo.scope = state.scope; - } - if (result.session.refreshToken) { // set new refresh token cookieManager.setRefreshToken( res, result.session.refreshToken, - appOrigin, + origin, ); } @@ -239,7 +242,7 @@ export function createOAuthRouteHandlers( } // post message back to popup if successful - sendWebMessageResponse(res, appOrigin, { + sendWebMessageResponse(res, origin, { type: 'authorization_response', response, }); @@ -248,7 +251,7 @@ export function createOAuthRouteHandlers( ? error : new Error('Encountered invalid error'); // Being a bit safe and not forwarding the bad value // post error message back to popup if failure - sendWebMessageResponse(res, appOrigin, { + sendWebMessageResponse(res, origin, { type: 'authorization_response', error: { name, message }, }); @@ -273,6 +276,9 @@ export function createOAuthRouteHandlers( // remove refresh token cookie if it is set cookieManager.removeRefreshToken(res, req.get('origin')); + // remove persisted scopes + await scopeManager.clear(req); + res.status(200).end(); }, @@ -294,16 +300,15 @@ export function createOAuthRouteHandlers( throw new InputError('Missing session cookie'); } - let scope = req.query.scope?.toString() ?? ''; - if (authenticator.shouldPersistScopes) { - scope = cookieManager.getGrantedScopes(req); - } + const scopeRefresh = await scopeManager.refresh(req); const result = await authenticator.refresh( - { req, scope, refreshToken }, + { req, scope: scopeRefresh.scope, refreshToken }, authenticatorCtx, ); + const grantedScope = await scopeRefresh.commit(result); + const { profile } = await profileTransform(result, resolverContext); const newRefreshToken = result.session.refreshToken; @@ -320,9 +325,7 @@ export function createOAuthRouteHandlers( providerInfo: { idToken: result.session.idToken, accessToken: result.session.accessToken, - scope: authenticator.shouldPersistScopes - ? scope - : result.session.scope, + scope: grantedScope, expiresInSeconds: result.session.expiresInSeconds, }, }; diff --git a/plugins/auth-node/src/oauth/index.ts b/plugins/auth-node/src/oauth/index.ts index 25213dd2f0..9cff6c5358 100644 --- a/plugins/auth-node/src/oauth/index.ts +++ b/plugins/auth-node/src/oauth/index.ts @@ -39,6 +39,7 @@ export { type OAuthAuthenticatorLogoutInput, type OAuthAuthenticatorRefreshInput, type OAuthAuthenticatorResult, + type OAuthAuthenticatorScopeOptions, type OAuthAuthenticatorStartInput, type OAuthSession, } from './types'; diff --git a/plugins/auth-node/src/oauth/types.ts b/plugins/auth-node/src/oauth/types.ts index 4bd7bd3f3f..c4ae2ee1cf 100644 --- a/plugins/auth-node/src/oauth/types.ts +++ b/plugins/auth-node/src/oauth/types.ts @@ -29,6 +29,22 @@ export interface OAuthSession { refreshTokenExpiresInSeconds?: number; } +/** @public */ +export interface OAuthAuthenticatorScopeOptions { + persist?: boolean; + required?: string[]; + transform?: (options: { + /** Scopes requested by the client */ + requested: Iterable; + /** Scopes which have already been granted */ + granted: Iterable; + /** Scopes that are required for the authenticator to function */ + required: Iterable; + /** Additional scopes added through configuration */ + additional: Iterable; + }) => Iterable; +} + /** @public */ export interface OAuthAuthenticatorStartInput { scope: string; @@ -64,7 +80,9 @@ export interface OAuthAuthenticatorResult { /** @public */ export interface OAuthAuthenticator { defaultProfileTransform: ProfileTransform>; + /** @deprecated use `scopes.persist` instead */ shouldPersistScopes?: boolean; + scopes?: OAuthAuthenticatorScopeOptions; initialize(ctx: { callbackUrl: string; config: Config }): TContext; start( input: OAuthAuthenticatorStartInput, From bb7d150937cf775158ad9a78c97b717678b242d8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 13 May 2024 11:33:24 +0200 Subject: [PATCH 36/46] auth-node: added CookieScopeManager tests + fixes Signed-off-by: Patrik Oldsberg --- .../src/oauth/CookieScopeManager.test.ts | 236 ++++++++++++++++++ .../auth-node/src/oauth/CookieScopeManager.ts | 19 +- 2 files changed, 246 insertions(+), 9 deletions(-) create mode 100644 plugins/auth-node/src/oauth/CookieScopeManager.test.ts diff --git a/plugins/auth-node/src/oauth/CookieScopeManager.test.ts b/plugins/auth-node/src/oauth/CookieScopeManager.test.ts new file mode 100644 index 0000000000..82eeb902d8 --- /dev/null +++ b/plugins/auth-node/src/oauth/CookieScopeManager.test.ts @@ -0,0 +1,236 @@ +/* + * 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 express from 'express'; +import { + OAuthAuthenticator, + OAuthAuthenticatorResult, + OAuthAuthenticatorScopeOptions, +} from './types'; +import { OAuthCookieManager } from './OAuthCookieManager'; +import { OAuthState } from './state'; +import { CookieScopeManager } from './CookieScopeManager'; + +function makeReq(scope?: string): express.Request { + return { + query: { scope }, + res: {}, + get: _name => 'https://example.com', + } as express.Request; +} + +describe('CookieScopeManager', () => { + it('should work with minimal config', async () => { + const manager = CookieScopeManager.create({ + authenticator: {} as OAuthAuthenticator, + cookieManager: {} as OAuthCookieManager, + }); + + await expect(manager.start(makeReq())).resolves.toEqual({ + scope: '', + }); + await expect(manager.start(makeReq('x'))).resolves.toEqual({ + scope: 'x', + }); + await expect(manager.start(makeReq('x,y'))).resolves.toEqual({ + scope: 'x y', + }); + + await expect( + manager.handleCallback(makeReq(), { + result: { session: { scope: 'x,y' } } as OAuthAuthenticatorResult, + state: {} as OAuthState, + }), + ).resolves.toEqual('x y'); + + await expect(manager.clear(makeReq())).resolves.toBe(undefined); + + const refresh = await manager.refresh(makeReq('x,y')); + expect(refresh.scope).toBe('x y'); + + await expect( + refresh.commit({ + session: { scope: 'y,z' }, + } as OAuthAuthenticatorResult), + ).resolves.toEqual('y z'); + }); + + it('should include additional scopes', async () => { + const manager = CookieScopeManager.create({ + additionalScopes: ['a', 'b'], + authenticator: {} as OAuthAuthenticator, + cookieManager: {} as OAuthCookieManager, + }); + + await expect(manager.start(makeReq())).resolves.toEqual({ + scope: 'a b', + }); + await expect(manager.start(makeReq('x'))).resolves.toEqual({ + scope: 'x a b', + }); + await expect(manager.start(makeReq('x,y'))).resolves.toEqual({ + scope: 'x y a b', + }); + + const refresh = await manager.refresh(makeReq('x|y')); + expect(refresh.scope).toBe('x y a b'); + + await expect( + refresh.commit({ + session: { scope: 'y,z a' }, + } as OAuthAuthenticatorResult), + ).resolves.toEqual('y z a'); + }); + + it('should persist scopes', async () => { + const setGrantedScopes = jest.fn(); + const removeGrantedScopes = jest.fn(); + const manager = CookieScopeManager.create({ + authenticator: { + scopes: { + persist: true, + } as OAuthAuthenticatorScopeOptions, + } as OAuthAuthenticator, + cookieManager: { + getGrantedScopes: () => 'g', + setGrantedScopes, + removeGrantedScopes, + } as unknown as OAuthCookieManager, + }); + + await expect(manager.start(makeReq())).resolves.toEqual({ + scope: 'g', + scopeState: { + scope: 'g', + }, + }); + await expect(manager.start(makeReq('x'))).resolves.toEqual({ + scope: 'x g', + scopeState: { + scope: 'x g', + }, + }); + + expect(setGrantedScopes).not.toHaveBeenCalled(); + await expect( + manager.handleCallback(makeReq(), { + // The state is prioritized even if scope is present in the result + result: { session: { scope: 'x,y' } } as OAuthAuthenticatorResult, + state: { scope: 'x g' } as OAuthState, + origin: 'https://other.example.com', + }), + ).resolves.toEqual('x g'); + expect(setGrantedScopes).toHaveBeenCalledWith( + expect.anything(), + 'x g', + 'https://other.example.com', + ); + setGrantedScopes.mockClear(); + + expect(removeGrantedScopes).not.toHaveBeenCalled(); + await expect(manager.clear(makeReq())).resolves.toBe(undefined); + expect(removeGrantedScopes).toHaveBeenCalledWith( + expect.anything(), + 'https://example.com', + ); + + const refresh = await manager.refresh(makeReq('x,y')); + expect(refresh.scope).toBe('x y g'); + + expect(setGrantedScopes).not.toHaveBeenCalled(); + await expect( + refresh.commit({ + session: { scope: 'y,z a' }, + } as OAuthAuthenticatorResult), + ).resolves.toEqual('x y g'); + expect(setGrantedScopes).toHaveBeenCalledWith( + expect.anything(), + 'x y g', + 'https://example.com', + ); + }); + + it('should use custom scope transform', async () => { + const manager = CookieScopeManager.create({ + additionalScopes: ['b'], + authenticator: { + scopes: { + persist: true, + required: ['a'], + transform: ({ required, additional, requested, granted }) => + new Set([ + ...[...requested].map(s => `requested-${s}`), + ...[...granted].map(s => `granted-${s}`), + ...[...required].map(s => `required-${s}`), + ...[...additional].map(s => `additional-${s}`), + ]), + } as OAuthAuthenticatorScopeOptions, + } as OAuthAuthenticator, + cookieManager: { + getGrantedScopes: _req => 'g', + setGrantedScopes: (_req, _scope, _origin) => {}, + } as OAuthCookieManager, + }); + + await expect(manager.start(makeReq())).resolves.toEqual({ + scope: 'granted-g required-a additional-b', + scopeState: { + scope: 'granted-g required-a additional-b', + }, + }); + await expect(manager.start(makeReq('x'))).resolves.toEqual({ + scope: 'requested-x granted-g required-a additional-b', + scopeState: { + scope: 'requested-x granted-g required-a additional-b', + }, + }); + + const refresh = await manager.refresh(makeReq('x,y')); + expect(refresh.scope).toBe( + 'requested-x requested-y granted-g required-a additional-b', + ); + + await expect( + refresh.commit({ + session: { scope: 'y,z a' }, + } as OAuthAuthenticatorResult), + ).resolves.toEqual( + 'requested-x requested-y granted-g required-a additional-b', + ); + }); + + it('should fail on invalid input', async () => { + const manager = CookieScopeManager.create({ + authenticator: { + scopes: { + persist: true, + } as OAuthAuthenticatorScopeOptions, + } as OAuthAuthenticator, + cookieManager: {} as OAuthCookieManager, + }); + + await expect( + manager.handleCallback(makeReq(), { + result: { session: { scope: 'x,y' } } as OAuthAuthenticatorResult, + state: {} as OAuthState, + }), + ).rejects.toThrow('No scope found in OAuth state'); + + await expect(manager.clear({} as express.Request)).rejects.toThrow( + 'No response object found in request', + ); + }); +}); diff --git a/plugins/auth-node/src/oauth/CookieScopeManager.ts b/plugins/auth-node/src/oauth/CookieScopeManager.ts index f75bf71db1..45f6e6238a 100644 --- a/plugins/auth-node/src/oauth/CookieScopeManager.ts +++ b/plugins/auth-node/src/oauth/CookieScopeManager.ts @@ -33,8 +33,8 @@ function reqRes(req: express.Request): express.Response { } const defaultTransform: Required['transform'] = - ({ required, additional, requested, granted }) => { - return new Set([...required, ...requested, ...additional, ...granted]); + ({ requested, granted, required, additional }) => { + return [...requested, ...granted, ...required, ...additional]; }; function splitScope(scope?: string): Iterable { @@ -42,12 +42,12 @@ function splitScope(scope?: string): Iterable { return []; } - return new Set(scope.split(/[\s|,]/).filter(Boolean)); + return scope.split(/[\s|,]/).filter(Boolean); } export class CookieScopeManager { static create(options: { - additionalScopes: string[]; + additionalScopes?: string[]; authenticator: OAuthAuthenticator; cookieManager: OAuthCookieManager; }) { @@ -59,13 +59,13 @@ export class CookieScopeManager { false; const transform = authenticator?.scopes?.transform ?? defaultTransform; - const additional = options.additionalScopes; + const additional = options.additionalScopes ?? []; const required = authenticator?.scopes?.required ?? []; return new CookieScopeManager( (requested, granted) => Array.from( - transform({ required, additional, requested, granted }), + new Set(transform({ required, additional, requested, granted })), ).join(' '), shouldPersistScopes ? options.cookieManager : undefined, ); @@ -83,8 +83,9 @@ export class CookieScopeManager { req: express.Request, ): Promise<{ scopeState?: Partial; scope: string }> { const requestScope = splitScope(req.query.scope?.toString()); + const grantedScope = splitScope(this.cookieManager?.getGrantedScopes(req)); - const scope = this.scopeTransform(requestScope, []); + const scope = this.scopeTransform(requestScope, grantedScope); if (this.cookieManager) { // If scopes are persisted then we pass them through the state so that we @@ -107,7 +108,7 @@ export class CookieScopeManager { ): Promise { // If we are not persisting scopes we can forward the scope from the result if (!this.cookieManager) { - return ctx.result.session.scope; + return Array.from(splitScope(ctx.result.session.scope)).join(' '); } const scope = ctx.state.scope; @@ -149,7 +150,7 @@ export class CookieScopeManager { return scope; } - return result.session.scope; + return Array.from(splitScope(result.session.scope)).join(' '); }, }; } From dd99788e6bd85034e3aa8252723e6b5513ca8abe Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 13 May 2024 13:20:39 +0200 Subject: [PATCH 37/46] auth-node: allow additonalScopes to be a string too Signed-off-by: Patrik Oldsberg --- .../src/oauth/CookieScopeManager.test.ts | 34 +++++++++++++++++-- .../auth-node/src/oauth/CookieScopeManager.ts | 11 ++++-- .../src/oauth/createOAuthRouteHandlers.ts | 6 ++-- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/plugins/auth-node/src/oauth/CookieScopeManager.test.ts b/plugins/auth-node/src/oauth/CookieScopeManager.test.ts index 82eeb902d8..6cdee1168f 100644 --- a/plugins/auth-node/src/oauth/CookieScopeManager.test.ts +++ b/plugins/auth-node/src/oauth/CookieScopeManager.test.ts @@ -23,6 +23,7 @@ import { import { OAuthCookieManager } from './OAuthCookieManager'; import { OAuthState } from './state'; import { CookieScopeManager } from './CookieScopeManager'; +import { ConfigReader } from '@backstage/config'; function makeReq(scope?: string): express.Request { return { @@ -32,6 +33,11 @@ function makeReq(scope?: string): express.Request { } as express.Request; } +const baseOpts = { + authenticator: {} as OAuthAuthenticator, + cookieManager: {} as OAuthCookieManager, +}; + describe('CookieScopeManager', () => { it('should work with minimal config', async () => { const manager = CookieScopeManager.create({ @@ -71,8 +77,7 @@ describe('CookieScopeManager', () => { it('should include additional scopes', async () => { const manager = CookieScopeManager.create({ additionalScopes: ['a', 'b'], - authenticator: {} as OAuthAuthenticator, - cookieManager: {} as OAuthCookieManager, + ...baseOpts, }); await expect(manager.start(makeReq())).resolves.toEqual({ @@ -95,6 +100,31 @@ describe('CookieScopeManager', () => { ).resolves.toEqual('y z a'); }); + it('should include additional scopes from config', async () => { + await expect( + CookieScopeManager.create({ + additionalScopes: ['a'], + ...baseOpts, + }).start(makeReq()), + ).resolves.toEqual({ scope: 'a' }); + + await expect( + CookieScopeManager.create({ + config: new ConfigReader({ additionalScopes: 'a,b' }), + additionalScopes: ['c'], + ...baseOpts, + }).start(makeReq()), + ).resolves.toEqual({ scope: 'a b c' }); + + await expect( + CookieScopeManager.create({ + config: new ConfigReader({ additionalScopes: ['a', 'b'] }), + additionalScopes: ['c'], + ...baseOpts, + }).start(makeReq()), + ).resolves.toEqual({ scope: 'a b c' }); + }); + it('should persist scopes', async () => { const setGrantedScopes = jest.fn(); const removeGrantedScopes = jest.fn(); diff --git a/plugins/auth-node/src/oauth/CookieScopeManager.ts b/plugins/auth-node/src/oauth/CookieScopeManager.ts index 45f6e6238a..f012536755 100644 --- a/plugins/auth-node/src/oauth/CookieScopeManager.ts +++ b/plugins/auth-node/src/oauth/CookieScopeManager.ts @@ -23,6 +23,7 @@ import { import { OAuthCookieManager } from './OAuthCookieManager'; import { OAuthState } from './state'; import { AuthenticationError } from '@backstage/errors'; +import { Config } from '@backstage/config'; function reqRes(req: express.Request): express.Response { const res = req.res; @@ -47,19 +48,25 @@ function splitScope(scope?: string): Iterable { export class CookieScopeManager { static create(options: { + config?: Config; additionalScopes?: string[]; authenticator: OAuthAuthenticator; cookieManager: OAuthCookieManager; }) { - const { authenticator } = options; + const { authenticator, config } = options; const shouldPersistScopes = authenticator.scopes?.persist ?? authenticator.shouldPersistScopes ?? false; + const configScopes = + typeof config?.getOptional('additionalScopes') === 'string' + ? splitScope(config.getString('additionalScopes')) + : config?.getOptionalStringArray('additionalScopes') ?? []; + const transform = authenticator?.scopes?.transform ?? defaultTransform; - const additional = options.additionalScopes ?? []; + const additional = [...configScopes, ...(options.additionalScopes ?? [])]; const required = authenticator?.scopes?.required ?? []; return new CookieScopeManager( diff --git a/plugins/auth-node/src/oauth/createOAuthRouteHandlers.ts b/plugins/auth-node/src/oauth/createOAuthRouteHandlers.ts index c13b58f2fc..82bfa2f02c 100644 --- a/plugins/auth-node/src/oauth/createOAuthRouteHandlers.ts +++ b/plugins/auth-node/src/oauth/createOAuthRouteHandlers.ts @@ -113,12 +113,10 @@ export function createOAuthRouteHandlers( }); const scopeManager = CookieScopeManager.create({ + config, authenticator, cookieManager, - additionalScopes: [ - ...(options.additionalScopes ?? []), - ...(config.getOptionalStringArray('additionalScopes') ?? []), - ], + additionalScopes: options.additionalScopes, }); return { From bdabd9952e2fe46fc7dd7dcc8af1fd06f38c86e0 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 13 May 2024 14:04:05 +0200 Subject: [PATCH 38/46] auth-*: test fixes for new CookieScopeManager Signed-off-by: Patrik Oldsberg --- .../auth-backend-module-github-provider/src/module.test.ts | 1 + .../auth-backend-module-microsoft-provider/src/module.test.ts | 2 +- plugins/auth-backend-module-oidc-provider/src/module.test.ts | 1 + plugins/auth-backend-module-okta-provider/src/module.test.ts | 4 +--- plugins/auth-node/src/oauth/CookieScopeManager.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/auth-backend-module-github-provider/src/module.test.ts b/plugins/auth-backend-module-github-provider/src/module.test.ts index 437e002bc3..b592f07d4b 100644 --- a/plugins/auth-backend-module-github-provider/src/module.test.ts +++ b/plugins/auth-backend-module-github-provider/src/module.test.ts @@ -72,6 +72,7 @@ describe('authModuleGithubProvider', () => { expect(decodeOAuthState(startUrl.searchParams.get('state')!)).toEqual({ env: 'development', nonce: decodeURIComponent(nonceCookie.value), + scope: '', }); }); }); diff --git a/plugins/auth-backend-module-microsoft-provider/src/module.test.ts b/plugins/auth-backend-module-microsoft-provider/src/module.test.ts index 2ef92c0b44..b50956b9eb 100644 --- a/plugins/auth-backend-module-microsoft-provider/src/module.test.ts +++ b/plugins/auth-backend-module-microsoft-provider/src/module.test.ts @@ -67,7 +67,7 @@ describe('authModuleMicrosoftProvider', () => { expect(startUrl.pathname).toBe('/my-tenant-id/oauth2/v2.0/authorize'); expect(Object.fromEntries(startUrl.searchParams)).toEqual({ response_type: 'code', - scope: 'user.read User.Read.All', + scope: 'User.Read.All', client_id: 'my-client-id', redirect_uri: `http://localhost:${server.port()}/api/auth/microsoft/handler/frame`, state: expect.any(String), diff --git a/plugins/auth-backend-module-oidc-provider/src/module.test.ts b/plugins/auth-backend-module-oidc-provider/src/module.test.ts index 0edb43f9f3..8ceec1df15 100644 --- a/plugins/auth-backend-module-oidc-provider/src/module.test.ts +++ b/plugins/auth-backend-module-oidc-provider/src/module.test.ts @@ -212,6 +212,7 @@ describe('authModuleOidcProvider', () => { expect(decodeOAuthState(startUrl.searchParams.get('state')!)).toEqual({ env: 'development', nonce: decodeURIComponent(nonceCookie.value), + scope: '', }); }); diff --git a/plugins/auth-backend-module-okta-provider/src/module.test.ts b/plugins/auth-backend-module-okta-provider/src/module.test.ts index e469067b3f..ee410e4d2e 100644 --- a/plugins/auth-backend-module-okta-provider/src/module.test.ts +++ b/plugins/auth-backend-module-okta-provider/src/module.test.ts @@ -21,9 +21,7 @@ import { decodeOAuthState } from '@backstage/plugin-auth-node'; describe('authModuleOktaProvider', () => { it('should start', async () => { - const defaultScopes = 'openid profile email'; const additionalScopes = 'groups phone'; - const combinedScopes = `${defaultScopes} ${additionalScopes}`; const { server } = await startTestBackend({ features: [ import('@backstage/plugin-auth-backend'), @@ -68,7 +66,7 @@ describe('authModuleOktaProvider', () => { expect(startUrl.pathname).toBe('/oauth2/v1/authorize'); expect(Object.fromEntries(startUrl.searchParams)).toEqual({ response_type: 'code', - scope: combinedScopes, + scope: additionalScopes, client_id: 'my-client-id', redirect_uri: `http://localhost:${server.port()}/api/auth/okta/handler/frame`, state: expect.any(String), diff --git a/plugins/auth-node/src/oauth/CookieScopeManager.ts b/plugins/auth-node/src/oauth/CookieScopeManager.ts index f012536755..3cbf977e09 100644 --- a/plugins/auth-node/src/oauth/CookieScopeManager.ts +++ b/plugins/auth-node/src/oauth/CookieScopeManager.ts @@ -119,7 +119,7 @@ export class CookieScopeManager { } const scope = ctx.state.scope; - if (!scope) { + if (scope === undefined) { throw new AuthenticationError('No scope found in OAuth state'); } From 8efc6cf0d4ad29abc8ced6eab2a86e2d71479f70 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 11 Jun 2024 11:55:52 +0200 Subject: [PATCH 39/46] auth-backend-module-*: update OAuth providers to use new scope handling Signed-off-by: Patrik Oldsberg --- .changeset/long-llamas-push-atlassian.md | 5 ++ .changeset/long-llamas-push-bitbucket.md | 5 ++ .changeset/long-llamas-push-github.md | 5 ++ .changeset/long-llamas-push-gitlab.md | 5 ++ .changeset/long-llamas-push-google.md | 5 ++ .changeset/long-llamas-push-microsoft.md | 5 ++ .changeset/long-llamas-push-oauth2.md | 5 ++ .changeset/long-llamas-push-oidc.md | 5 ++ .changeset/long-llamas-push-okta.md | 5 ++ .changeset/long-llamas-push-pinniped.md | 5 ++ .changeset/long-llamas-push-vmware-cloud.md | 5 ++ .../config.d.ts | 2 +- .../src/authenticator.ts | 14 +-- .../src/module.test.ts | 87 +++++++------------ .../config.d.ts | 1 + .../src/authenticator.ts | 3 + .../src/module.test.ts | 1 + .../config.d.ts | 1 + .../src/authenticator.ts | 5 +- .../src/module.test.ts | 3 +- .../config.d.ts | 1 + .../src/authenticator.ts | 3 + .../config.d.ts | 1 + .../src/authenticator.ts | 7 ++ .../src/module.test.ts | 2 + .../config.d.ts | 2 +- .../config.d.ts | 2 + .../src/authenticator.ts | 8 +- .../api-report.md | 1 - .../config.d.ts | 2 +- .../src/authenticator.test.ts | 13 --- .../src/authenticator.ts | 19 ++-- .../src/module.test.ts | 2 +- .../config.d.ts | 2 +- .../src/authenticator.ts | 17 +--- .../src/module.test.ts | 5 +- .../src/authenticator.test.ts | 14 +-- .../src/authenticator.ts | 18 +++- .../config.d.ts | 1 + .../src/authenticator.test.ts | 4 +- .../src/authenticator.ts | 11 ++- 41 files changed, 183 insertions(+), 124 deletions(-) create mode 100644 .changeset/long-llamas-push-atlassian.md create mode 100644 .changeset/long-llamas-push-bitbucket.md create mode 100644 .changeset/long-llamas-push-github.md create mode 100644 .changeset/long-llamas-push-gitlab.md create mode 100644 .changeset/long-llamas-push-google.md create mode 100644 .changeset/long-llamas-push-microsoft.md create mode 100644 .changeset/long-llamas-push-oauth2.md create mode 100644 .changeset/long-llamas-push-oidc.md create mode 100644 .changeset/long-llamas-push-okta.md create mode 100644 .changeset/long-llamas-push-pinniped.md create mode 100644 .changeset/long-llamas-push-vmware-cloud.md diff --git a/.changeset/long-llamas-push-atlassian.md b/.changeset/long-llamas-push-atlassian.md new file mode 100644 index 0000000000..3e0ae5ad14 --- /dev/null +++ b/.changeset/long-llamas-push-atlassian.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-atlassian-provider': minor +--- + +**BREAKING**: The `scope` and `scopes` config options have been removed and replaced by the standard `additionalScopes` config. In addition, the `offline_access`, `read:jira-work`, and `read:jira-user` scopes have been set to required and will always be present. diff --git a/.changeset/long-llamas-push-bitbucket.md b/.changeset/long-llamas-push-bitbucket.md new file mode 100644 index 0000000000..36a68219eb --- /dev/null +++ b/.changeset/long-llamas-push-bitbucket.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-bitbucket-provider': patch +--- + +Added support for the new shared `additionalScopes` configuration. In addition, the `account` scope has been set to required and will always be present. diff --git a/.changeset/long-llamas-push-github.md b/.changeset/long-llamas-push-github.md new file mode 100644 index 0000000000..c68fb8e925 --- /dev/null +++ b/.changeset/long-llamas-push-github.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-github-provider': patch +--- + +Added support for the new shared `additionalScopes` configuration. In addition, the `read:user` scope has been set to required and will always be present. diff --git a/.changeset/long-llamas-push-gitlab.md b/.changeset/long-llamas-push-gitlab.md new file mode 100644 index 0000000000..fe5d293723 --- /dev/null +++ b/.changeset/long-llamas-push-gitlab.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-gitlab-provider': patch +--- + +Added support for the new shared `additionalScopes` configuration. In addition, the `read_user` scope has been set to required and will always be present. diff --git a/.changeset/long-llamas-push-google.md b/.changeset/long-llamas-push-google.md new file mode 100644 index 0000000000..c9de73eb36 --- /dev/null +++ b/.changeset/long-llamas-push-google.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-google-provider': patch +--- + +Added support for the new shared `additionalScopes` configuration. In addition, the `openid`, `userinfo.email`, and `userinfo.profile` scopes have been set to required and will always be present. diff --git a/.changeset/long-llamas-push-microsoft.md b/.changeset/long-llamas-push-microsoft.md new file mode 100644 index 0000000000..f6509db0f7 --- /dev/null +++ b/.changeset/long-llamas-push-microsoft.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-microsoft-provider': patch +--- + +Added support for the new shared `additionalScopes` configuration. diff --git a/.changeset/long-llamas-push-oauth2.md b/.changeset/long-llamas-push-oauth2.md new file mode 100644 index 0000000000..2a233dbb42 --- /dev/null +++ b/.changeset/long-llamas-push-oauth2.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-oauth2-provider': minor +--- + +**BREAKING**: The `scope` config option have been removed and replaced by the standard `additionalScopes` config. diff --git a/.changeset/long-llamas-push-oidc.md b/.changeset/long-llamas-push-oidc.md new file mode 100644 index 0000000000..248d762864 --- /dev/null +++ b/.changeset/long-llamas-push-oidc.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-oidc-provider': minor +--- + +**BREAKING**: The `scope` config option have been removed and replaced by the standard `additionalScopes` config. In addition, `openid`, `profile`, and `email` scopes have been set to required and will always be present. diff --git a/.changeset/long-llamas-push-okta.md b/.changeset/long-llamas-push-okta.md new file mode 100644 index 0000000000..d330746d2e --- /dev/null +++ b/.changeset/long-llamas-push-okta.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-okta-provider': patch +--- + +Added support for the new shared `additionalScopes` configuration, which means it can now also be specified as an array. In addition, the `openid`, `email`, `profile`, and `offline_access` scopes have been set to required and will always be present. diff --git a/.changeset/long-llamas-push-pinniped.md b/.changeset/long-llamas-push-pinniped.md new file mode 100644 index 0000000000..a9c6a54cee --- /dev/null +++ b/.changeset/long-llamas-push-pinniped.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-pinniped-provider': patch +--- + +**BREAKING**: The `scope` config option have been removed and replaced by the standard `additionalScopes` config. In addition, the `openid`, `pinniped:request-audience`, `username`, and `offline_access` scopes have been set to required and will always be present. diff --git a/.changeset/long-llamas-push-vmware-cloud.md b/.changeset/long-llamas-push-vmware-cloud.md new file mode 100644 index 0000000000..9edfb01f68 --- /dev/null +++ b/.changeset/long-llamas-push-vmware-cloud.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-vmware-cloud-provider': minor +--- + +**BREAKING**: The `scope` config option have been removed and replaced by the standard `additionalScopes` config. In addition, `openid`, and `offline_access` scopes have been set to required and will always be present. diff --git a/plugins/auth-backend-module-atlassian-provider/config.d.ts b/plugins/auth-backend-module-atlassian-provider/config.d.ts index 57def03aab..d2c8a249c1 100644 --- a/plugins/auth-backend-module-atlassian-provider/config.d.ts +++ b/plugins/auth-backend-module-atlassian-provider/config.d.ts @@ -27,7 +27,7 @@ export interface Config { clientSecret: string; audience?: string; callbackUrl?: string; - scope?: string; + additionalScopes?: string | string[]; }; }; }; diff --git a/plugins/auth-backend-module-atlassian-provider/src/authenticator.ts b/plugins/auth-backend-module-atlassian-provider/src/authenticator.ts index b31de13134..0ced9cf831 100644 --- a/plugins/auth-backend-module-atlassian-provider/src/authenticator.ts +++ b/plugins/auth-backend-module-atlassian-provider/src/authenticator.ts @@ -26,15 +26,20 @@ import { Strategy as AtlassianStrategy } from 'passport-atlassian-oauth2'; export const atlassianAuthenticator = createOAuthAuthenticator({ defaultProfileTransform: PassportOAuthAuthenticatorHelper.defaultProfileTransform, + scopes: { + required: ['offline_access', 'read:jira-work', 'read:jira-user'], + }, initialize({ callbackUrl, config }) { const clientId = config.getString('clientId'); const clientSecret = config.getString('clientSecret'); - const scope = - config.getOptionalString('scope') ?? - config.getOptionalString('scopes') ?? - 'offline_access read:jira-work read:jira-user'; const baseUrl = 'https://auth.atlassian.com'; + if (config.has('scope') || config.has('scopes')) { + throw new Error( + 'The atlassian provider no longer supports the "scope" or "scopes" configuration options. Please use the "additionalScopes" option instead.', + ); + } + return PassportOAuthAuthenticatorHelper.from( new AtlassianStrategy( { @@ -45,7 +50,6 @@ export const atlassianAuthenticator = createOAuthAuthenticator({ authorizationURL: `${baseUrl}/authorize`, tokenURL: `${baseUrl}/oauth/token`, profileURL: `${baseUrl}/api/v4/user`, - scope, }, ( accessToken: string, diff --git a/plugins/auth-backend-module-atlassian-provider/src/module.test.ts b/plugins/auth-backend-module-atlassian-provider/src/module.test.ts index 08b84ad165..7b92218d56 100644 --- a/plugins/auth-backend-module-atlassian-provider/src/module.test.ts +++ b/plugins/auth-backend-module-atlassian-provider/src/module.test.ts @@ -75,7 +75,8 @@ describe('authModuleAtlassianProvider', () => { nonce: decodeURIComponent(nonceCookie.value), }); }); - it('should start with and use custom scopes from scope config field', async () => { + + it('should start with and use custom scopes from additionalScopes config field', async () => { const { server } = await startTestBackend({ features: [ import('@backstage/plugin-auth-backend'), @@ -91,7 +92,10 @@ describe('authModuleAtlassianProvider', () => { development: { clientId: 'my-client-id', clientSecret: 'my-client-secret', - scope: 'offline_access read:filter:jira read:jira-work', + additionalScopes: [ + 'read:filter:jira', + 'read:jira-work', // already required + ], }, }, }, @@ -123,7 +127,7 @@ describe('authModuleAtlassianProvider', () => { client_id: 'my-client-id', redirect_uri: `http://localhost:${server.port()}/api/auth/atlassian/handler/frame`, state: expect.any(String), - scope: 'offline_access read:filter:jira read:jira-work', + scope: 'offline_access read:jira-work read:jira-user read:filter:jira', }); expect(decodeOAuthState(startUrl.searchParams.get('state')!)).toEqual({ @@ -131,60 +135,35 @@ describe('authModuleAtlassianProvider', () => { nonce: decodeURIComponent(nonceCookie.value), }); }); - it('should start with and use custom scopes from scopes config field for backward compatibility', async () => { - const { server } = await startTestBackend({ - features: [ - import('@backstage/plugin-auth-backend'), - authModuleAtlassianProvider, - mockServices.rootConfig.factory({ - data: { - app: { - baseUrl: 'http://localhost:3000', - }, - auth: { - providers: { - atlassian: { - development: { - clientId: 'my-client-id', - clientSecret: 'my-client-secret', - scopes: 'offline_access read:filter:jira read:jira-work', + + it('should fail to start with scope or scopes config', async () => { + await expect( + startTestBackend({ + features: [ + import('@backstage/plugin-auth-backend'), + authModuleAtlassianProvider, + mockServices.rootConfig.factory({ + data: { + app: { + baseUrl: 'http://localhost:3000', + }, + auth: { + providers: { + atlassian: { + development: { + clientId: 'my-client-id', + clientSecret: 'my-client-secret', + scope: 'foo', + }, }, }, }, }, - }, - }), - ], - }); - - const agent = request.agent(server); - - const res = await agent.get('/api/auth/atlassian/start?env=development'); - - expect(res.status).toEqual(302); - - const nonceCookie = agent.jar.getCookie('atlassian-nonce', { - domain: 'localhost', - path: '/api/auth/atlassian/handler', - script: false, - secure: false, - }); - expect(nonceCookie).toBeDefined(); - - const startUrl = new URL(res.get('location')); - expect(startUrl.origin).toBe('https://auth.atlassian.com'); - expect(startUrl.pathname).toBe('/authorize'); - expect(Object.fromEntries(startUrl.searchParams)).toEqual({ - response_type: 'code', - client_id: 'my-client-id', - redirect_uri: `http://localhost:${server.port()}/api/auth/atlassian/handler/frame`, - state: expect.any(String), - scope: 'offline_access read:filter:jira read:jira-work', - }); - - expect(decodeOAuthState(startUrl.searchParams.get('state')!)).toEqual({ - env: 'development', - nonce: decodeURIComponent(nonceCookie.value), - }); + }), + ], + }), + ).rejects.toThrow( + /atlassian provider no longer supports the "scope" or "scopes" configuration options/, + ); }); }); diff --git a/plugins/auth-backend-module-bitbucket-provider/config.d.ts b/plugins/auth-backend-module-bitbucket-provider/config.d.ts index 81e835a5e6..17cac1c194 100644 --- a/plugins/auth-backend-module-bitbucket-provider/config.d.ts +++ b/plugins/auth-backend-module-bitbucket-provider/config.d.ts @@ -25,6 +25,7 @@ export interface Config { * @visibility secret */ clientSecret: string; + additionalScopes?: string | string[]; }; }; }; diff --git a/plugins/auth-backend-module-bitbucket-provider/src/authenticator.ts b/plugins/auth-backend-module-bitbucket-provider/src/authenticator.ts index bc962ec773..a2d8275964 100644 --- a/plugins/auth-backend-module-bitbucket-provider/src/authenticator.ts +++ b/plugins/auth-backend-module-bitbucket-provider/src/authenticator.ts @@ -26,6 +26,9 @@ import { export const bitbucketAuthenticator = createOAuthAuthenticator({ defaultProfileTransform: PassportOAuthAuthenticatorHelper.defaultProfileTransform, + scopes: { + required: ['account'], + }, initialize({ callbackUrl, config }) { const clientID = config.getString('clientId'); const clientSecret = config.getString('clientSecret'); diff --git a/plugins/auth-backend-module-bitbucket-provider/src/module.test.ts b/plugins/auth-backend-module-bitbucket-provider/src/module.test.ts index e761369a9c..f1426d1b0d 100644 --- a/plugins/auth-backend-module-bitbucket-provider/src/module.test.ts +++ b/plugins/auth-backend-module-bitbucket-provider/src/module.test.ts @@ -67,6 +67,7 @@ describe('authModuleBitbucketProvider', () => { client_id: 'my-client-id', redirect_uri: `http://localhost:${server.port()}/api/auth/bitbucket/handler/frame`, state: expect.any(String), + scope: 'account', }); expect(decodeOAuthState(startUrl.searchParams.get('state')!)).toEqual({ diff --git a/plugins/auth-backend-module-github-provider/config.d.ts b/plugins/auth-backend-module-github-provider/config.d.ts index e79711310d..f60d4c239d 100644 --- a/plugins/auth-backend-module-github-provider/config.d.ts +++ b/plugins/auth-backend-module-github-provider/config.d.ts @@ -27,6 +27,7 @@ export interface Config { clientSecret: string; callbackUrl?: string; enterpriseInstanceUrl?: string; + additionalScopes?: string | string[]; }; }; }; diff --git a/plugins/auth-backend-module-github-provider/src/authenticator.ts b/plugins/auth-backend-module-github-provider/src/authenticator.ts index 4a9710d114..7c94a04c30 100644 --- a/plugins/auth-backend-module-github-provider/src/authenticator.ts +++ b/plugins/auth-backend-module-github-provider/src/authenticator.ts @@ -28,7 +28,10 @@ const ACCESS_TOKEN_PREFIX = 'access-token.'; export const githubAuthenticator = createOAuthAuthenticator({ defaultProfileTransform: PassportOAuthAuthenticatorHelper.defaultProfileTransform, - shouldPersistScopes: true, + scopes: { + persist: true, + required: ['read:user'], + }, initialize({ callbackUrl, config }) { const clientId = config.getString('clientId'); const clientSecret = config.getString('clientSecret'); diff --git a/plugins/auth-backend-module-github-provider/src/module.test.ts b/plugins/auth-backend-module-github-provider/src/module.test.ts index b592f07d4b..53308938c0 100644 --- a/plugins/auth-backend-module-github-provider/src/module.test.ts +++ b/plugins/auth-backend-module-github-provider/src/module.test.ts @@ -67,12 +67,13 @@ describe('authModuleGithubProvider', () => { client_id: 'my-client-id', redirect_uri: `http://localhost:${server.port()}/api/auth/github/handler/frame`, state: expect.any(String), + scope: 'read:user', }); expect(decodeOAuthState(startUrl.searchParams.get('state')!)).toEqual({ env: 'development', nonce: decodeURIComponent(nonceCookie.value), - scope: '', + scope: 'read:user', }); }); }); diff --git a/plugins/auth-backend-module-gitlab-provider/config.d.ts b/plugins/auth-backend-module-gitlab-provider/config.d.ts index d7f04d872a..18f7cb5005 100644 --- a/plugins/auth-backend-module-gitlab-provider/config.d.ts +++ b/plugins/auth-backend-module-gitlab-provider/config.d.ts @@ -27,6 +27,7 @@ export interface Config { clientSecret: string; audience?: string; callbackUrl?: string; + additionalScopes?: string | string[]; }; }; }; diff --git a/plugins/auth-backend-module-gitlab-provider/src/authenticator.ts b/plugins/auth-backend-module-gitlab-provider/src/authenticator.ts index 9cd5857b0d..8e93921b63 100644 --- a/plugins/auth-backend-module-gitlab-provider/src/authenticator.ts +++ b/plugins/auth-backend-module-gitlab-provider/src/authenticator.ts @@ -26,6 +26,9 @@ import { export const gitlabAuthenticator = createOAuthAuthenticator({ defaultProfileTransform: PassportOAuthAuthenticatorHelper.defaultProfileTransform, + scopes: { + required: ['read_user'], + }, initialize({ callbackUrl, config }) { const clientId = config.getString('clientId'); const clientSecret = config.getString('clientSecret'); diff --git a/plugins/auth-backend-module-google-provider/config.d.ts b/plugins/auth-backend-module-google-provider/config.d.ts index 6a1716c5bf..08a0e08f2b 100644 --- a/plugins/auth-backend-module-google-provider/config.d.ts +++ b/plugins/auth-backend-module-google-provider/config.d.ts @@ -26,6 +26,7 @@ export interface Config { */ clientSecret: string; callbackUrl?: string; + additionalScopes?: string | string[]; }; }; }; diff --git a/plugins/auth-backend-module-google-provider/src/authenticator.ts b/plugins/auth-backend-module-google-provider/src/authenticator.ts index a428519fee..9f1e298ae8 100644 --- a/plugins/auth-backend-module-google-provider/src/authenticator.ts +++ b/plugins/auth-backend-module-google-provider/src/authenticator.ts @@ -27,6 +27,13 @@ import { Strategy as GoogleStrategy } from 'passport-google-oauth20'; export const googleAuthenticator = createOAuthAuthenticator({ defaultProfileTransform: PassportOAuthAuthenticatorHelper.defaultProfileTransform, + scopes: { + required: [ + 'openid', + `https://www.googleapis.com/auth/userinfo.email`, + `https://www.googleapis.com/auth/userinfo.profile`, + ], + }, initialize({ callbackUrl, config }) { const clientId = config.getString('clientId'); const clientSecret = config.getString('clientSecret'); diff --git a/plugins/auth-backend-module-google-provider/src/module.test.ts b/plugins/auth-backend-module-google-provider/src/module.test.ts index 59066acd4c..8ece0c1942 100644 --- a/plugins/auth-backend-module-google-provider/src/module.test.ts +++ b/plugins/auth-backend-module-google-provider/src/module.test.ts @@ -69,6 +69,8 @@ describe('authModuleGoogleProvider', () => { client_id: 'my-client-id', redirect_uri: `http://localhost:${server.port()}/api/auth/google/handler/frame`, state: expect.any(String), + scope: + 'openid https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile', }); expect(decodeOAuthState(startUrl.searchParams.get('state')!)).toEqual({ diff --git a/plugins/auth-backend-module-microsoft-provider/config.d.ts b/plugins/auth-backend-module-microsoft-provider/config.d.ts index df63e9ccf4..a7ec027083 100644 --- a/plugins/auth-backend-module-microsoft-provider/config.d.ts +++ b/plugins/auth-backend-module-microsoft-provider/config.d.ts @@ -28,7 +28,7 @@ export interface Config { clientSecret: string; domainHint?: string; callbackUrl?: string; - additionalScopes?: string[]; + additionalScopes?: string | string[]; }; }; }; diff --git a/plugins/auth-backend-module-oauth2-provider/config.d.ts b/plugins/auth-backend-module-oauth2-provider/config.d.ts index afbfcf8f67..9b1ee18f1b 100644 --- a/plugins/auth-backend-module-oauth2-provider/config.d.ts +++ b/plugins/auth-backend-module-oauth2-provider/config.d.ts @@ -27,7 +27,9 @@ export interface Config { clientSecret: string; authorizationUrl: string; tokenUrl: string; + /** @deprecated use `additionalScopes` instead */ scope?: string; + additionalScopes?: string | string[]; disableRefresh?: boolean; includeBasicAuth?: boolean; }; diff --git a/plugins/auth-backend-module-oauth2-provider/src/authenticator.ts b/plugins/auth-backend-module-oauth2-provider/src/authenticator.ts index d6f84cf1c0..698d9e51cb 100644 --- a/plugins/auth-backend-module-oauth2-provider/src/authenticator.ts +++ b/plugins/auth-backend-module-oauth2-provider/src/authenticator.ts @@ -31,9 +31,14 @@ export const oauth2Authenticator = createOAuthAuthenticator({ const clientSecret = config.getString('clientSecret'); const authorizationUrl = config.getString('authorizationUrl'); const tokenUrl = config.getString('tokenUrl'); - const scope = config.getOptionalString('scope'); const includeBasicAuth = config.getOptionalBoolean('includeBasicAuth'); + if (config.has('scope')) { + throw new Error( + 'The oauth2 provider no longer supports the "scope" configuration option. Please use the "additionalScopes" option instead.', + ); + } + return PassportOAuthAuthenticatorHelper.from( new Oauth2Strategy( { @@ -43,7 +48,6 @@ export const oauth2Authenticator = createOAuthAuthenticator({ authorizationURL: authorizationUrl, tokenURL: tokenUrl, passReqToCallback: false, - scope: scope, customHeaders: includeBasicAuth ? { Authorization: `Basic ${encodeClientCredentials( diff --git a/plugins/auth-backend-module-oidc-provider/api-report.md b/plugins/auth-backend-module-oidc-provider/api-report.md index d96d9952a0..eb9b4fb21e 100644 --- a/plugins/auth-backend-module-oidc-provider/api-report.md +++ b/plugins/auth-backend-module-oidc-provider/api-report.md @@ -19,7 +19,6 @@ export default authModuleOidcProvider; // @public (undocumented) export const oidcAuthenticator: OAuthAuthenticator< { - initializedScope: string | undefined; initializedPrompt: string | undefined; promise: Promise<{ helper: PassportOAuthAuthenticatorHelper; diff --git a/plugins/auth-backend-module-oidc-provider/config.d.ts b/plugins/auth-backend-module-oidc-provider/config.d.ts index 16131c0761..398e63c466 100644 --- a/plugins/auth-backend-module-oidc-provider/config.d.ts +++ b/plugins/auth-backend-module-oidc-provider/config.d.ts @@ -29,7 +29,7 @@ export interface Config { callbackUrl?: string; tokenEndpointAuthMethod?: string; tokenSignedResponseAlg?: string; - scope?: string; + additionalScopes?: string | string[]; prompt?: string; }; }; diff --git a/plugins/auth-backend-module-oidc-provider/src/authenticator.test.ts b/plugins/auth-backend-module-oidc-provider/src/authenticator.test.ts index 67bfd27b19..4203a70153 100644 --- a/plugins/auth-backend-module-oidc-provider/src/authenticator.test.ts +++ b/plugins/auth-backend-module-oidc-provider/src/authenticator.test.ts @@ -254,19 +254,6 @@ describe('oidcAuthenticator', () => { expect(fakeSession['oidc:oidc.test'].code_verifier).toBeDefined(); }); - it('requests default scopes if none are provided in config', async () => { - const startResponse = await oidcAuthenticator.start( - startRequest, - implementation, - ); - const { searchParams } = new URL(startResponse.url); - const scopes = searchParams.get('scope')?.split(' ') ?? []; - - expect(scopes).toEqual( - expect.arrayContaining(['openid', 'profile', 'email']), - ); - }); - it('encodes OAuth state in query param', async () => { const startResponse = await oidcAuthenticator.start( startRequest, diff --git a/plugins/auth-backend-module-oidc-provider/src/authenticator.ts b/plugins/auth-backend-module-oidc-provider/src/authenticator.ts index 2b6a9b34f1..efcf1b61dd 100644 --- a/plugins/auth-backend-module-oidc-provider/src/authenticator.ts +++ b/plugins/auth-backend-module-oidc-provider/src/authenticator.ts @@ -53,7 +53,6 @@ export type OidcAuthResult = { /** @public */ export const oidcAuthenticator = createOAuthAuthenticator({ - shouldPersistScopes: true, defaultProfileTransform: async ( input: OAuthAuthenticatorResult, ) => ({ @@ -63,6 +62,10 @@ export const oidcAuthenticator = createOAuthAuthenticator({ displayName: input.fullProfile.userinfo.name, }, }), + scopes: { + persist: true, + required: ['openid', 'profile', 'email'], + }, initialize({ callbackUrl, config }) { const clientId = config.getString('clientId'); const clientSecret = config.getString('clientSecret'); @@ -74,9 +77,14 @@ export const oidcAuthenticator = createOAuthAuthenticator({ const tokenSignedResponseAlg = config.getOptionalString( 'tokenSignedResponseAlg', ); - const initializedScope = config.getOptionalString('scope'); const initializedPrompt = config.getOptionalString('prompt'); + if (config.has('scope')) { + throw new Error( + 'The oidc provider no longer supports the "scope" configuration option. Please use the "additionalScopes" option instead.', + ); + } + Issuer[custom.http_options] = httpOptionsProvider; const promise = Issuer.discover(metadataUrl).then(issuer => { issuer[custom.http_options] = httpOptionsProvider; @@ -91,7 +99,6 @@ export const oidcAuthenticator = createOAuthAuthenticator({ token_endpoint_auth_method: tokenEndpointAuthMethod || 'client_secret_basic', id_token_signed_response_alg: tokenSignedResponseAlg || 'RS256', - scope: initializedScope || '', }); client[custom.http_options] = httpOptionsProvider; @@ -123,14 +130,14 @@ export const oidcAuthenticator = createOAuthAuthenticator({ return { helper, client, strategy }; }); - return { initializedScope, initializedPrompt, promise }; + return { initializedPrompt, promise }; }, async start(input, ctx) { - const { initializedScope, initializedPrompt, promise } = ctx; + const { initializedPrompt, promise } = ctx; const { helper, strategy } = await promise; const options: Record = { - scope: input.scope || initializedScope || 'openid profile email', + scope: input.scope, state: input.state, nonce: crypto.randomBytes(16).toString('base64'), }; diff --git a/plugins/auth-backend-module-oidc-provider/src/module.test.ts b/plugins/auth-backend-module-oidc-provider/src/module.test.ts index 8ceec1df15..1359634950 100644 --- a/plugins/auth-backend-module-oidc-provider/src/module.test.ts +++ b/plugins/auth-backend-module-oidc-provider/src/module.test.ts @@ -212,7 +212,7 @@ describe('authModuleOidcProvider', () => { expect(decodeOAuthState(startUrl.searchParams.get('state')!)).toEqual({ env: 'development', nonce: decodeURIComponent(nonceCookie.value), - scope: '', + scope: 'openid profile email', }); }); diff --git a/plugins/auth-backend-module-okta-provider/config.d.ts b/plugins/auth-backend-module-okta-provider/config.d.ts index 42688528ee..aaf6ec1f91 100644 --- a/plugins/auth-backend-module-okta-provider/config.d.ts +++ b/plugins/auth-backend-module-okta-provider/config.d.ts @@ -29,7 +29,7 @@ export interface Config { authServerId?: string; idp?: string; callbackUrl?: string; - additionalScopes?: string; + additionalScopes?: string | string[]; }; }; }; diff --git a/plugins/auth-backend-module-okta-provider/src/authenticator.ts b/plugins/auth-backend-module-okta-provider/src/authenticator.ts index 42201232f1..1454d580cb 100644 --- a/plugins/auth-backend-module-okta-provider/src/authenticator.ts +++ b/plugins/auth-backend-module-okta-provider/src/authenticator.ts @@ -26,25 +26,15 @@ import { export const oktaAuthenticator = createOAuthAuthenticator({ defaultProfileTransform: PassportOAuthAuthenticatorHelper.defaultProfileTransform, + scopes: { + required: ['openid', 'email', 'profile', 'offline_access'], + }, initialize({ callbackUrl, config }) { const clientId = config.getString('clientId'); const clientSecret = config.getString('clientSecret'); const audience = config.getOptionalString('audience') || 'https://okta.com'; const authServerId = config.getOptionalString('authServerId'); const idp = config.getOptionalString('idp'); - // default scopes are taken from - // https://developer.okta.com/docs/reference/api/oidc/#response-example-success-refresh-token - const defaultScopes = 'openid profile email'; - // additional scopes can be configured in the config as a space separated string - const additionalScopes = config.getOptionalString('additionalScopes') || ''; - // combine default and additional scopes and remove duplicates - const combineScopeStrings = (scopesA: string, scopesB: string) => { - const scopesAArray = scopesA.split(' '); - const scopesBArray = scopesB.split(' '); - const combinedScopes = new Set([...scopesAArray, ...scopesBArray]); - return Array.from(combinedScopes).join(' '); - }; - const scope = combineScopeStrings(defaultScopes, additionalScopes); return PassportOAuthAuthenticatorHelper.from( new OktaStrategy( @@ -57,7 +47,6 @@ export const oktaAuthenticator = createOAuthAuthenticator({ idp: idp, passReqToCallback: false, response_type: 'code', - scope, }, ( accessToken: string, diff --git a/plugins/auth-backend-module-okta-provider/src/module.test.ts b/plugins/auth-backend-module-okta-provider/src/module.test.ts index ee410e4d2e..16a58b8713 100644 --- a/plugins/auth-backend-module-okta-provider/src/module.test.ts +++ b/plugins/auth-backend-module-okta-provider/src/module.test.ts @@ -21,7 +21,6 @@ import { decodeOAuthState } from '@backstage/plugin-auth-node'; describe('authModuleOktaProvider', () => { it('should start', async () => { - const additionalScopes = 'groups phone'; const { server } = await startTestBackend({ features: [ import('@backstage/plugin-auth-backend'), @@ -37,7 +36,7 @@ describe('authModuleOktaProvider', () => { development: { clientId: 'my-client-id', clientSecret: 'my-client-secret', - additionalScopes, + additionalScopes: 'groups phone', }, }, }, @@ -66,7 +65,7 @@ describe('authModuleOktaProvider', () => { expect(startUrl.pathname).toBe('/oauth2/v1/authorize'); expect(Object.fromEntries(startUrl.searchParams)).toEqual({ response_type: 'code', - scope: additionalScopes, + scope: 'openid email profile offline_access groups phone', client_id: 'my-client-id', redirect_uri: `http://localhost:${server.port()}/api/auth/okta/handler/frame`, state: expect.any(String), diff --git a/plugins/auth-backend-module-pinniped-provider/src/authenticator.test.ts b/plugins/auth-backend-module-pinniped-provider/src/authenticator.test.ts index 2ecd54e80a..e2dedf2129 100644 --- a/plugins/auth-backend-module-pinniped-provider/src/authenticator.test.ts +++ b/plugins/auth-backend-module-pinniped-provider/src/authenticator.test.ts @@ -249,22 +249,14 @@ describe('pinnipedAuthenticator', () => { expect(fakeSession['oidc:pinniped.test'].code_verifier).toBeDefined(); }); - it('requests sufficient scopes for token exchange by default', async () => { + it('forwards scopes for token exchange', async () => { const startResponse = await pinnipedAuthenticator.start( - startRequest, + { ...startRequest, scope: 'openid username' }, authCtx, ); const { searchParams } = new URL(startResponse.url); - const scopes = searchParams.get('scope')?.split(' ') ?? []; - expect(scopes).toEqual( - expect.arrayContaining([ - 'openid', - 'pinniped:request-audience', - 'username', - 'offline_access', - ]), - ); + expect(searchParams.get('scope')).toBe('openid username'); }); it('encodes OAuth state in query param', async () => { diff --git a/plugins/auth-backend-module-pinniped-provider/src/authenticator.ts b/plugins/auth-backend-module-pinniped-provider/src/authenticator.ts index e07eaba759..abacb14ccc 100644 --- a/plugins/auth-backend-module-pinniped-provider/src/authenticator.ts +++ b/plugins/auth-backend-module-pinniped-provider/src/authenticator.ts @@ -127,7 +127,6 @@ export class PinnipedStrategyCache { client_secret: this.config.getString('clientSecret'), redirect_uris: [this.callbackUrl], response_types: ['code'], - scope: this.config.getOptionalString('scope') || '', id_token_signed_response_alg: 'ES256', }); const providerStrategy = new OidcStrategy( @@ -154,7 +153,20 @@ export class PinnipedStrategyCache { /** @public */ export const pinnipedAuthenticator = createOAuthAuthenticator({ defaultProfileTransform: async (_r, _c) => ({ profile: {} }), + scopes: { + required: [ + 'openid', + 'pinniped:request-audience', + 'username', + 'offline_access', + ], + }, initialize({ callbackUrl, config }) { + if (config.has('scope')) { + throw new Error( + 'The pinniped provider no longer supports the "scope" configuration option. Please use the "additionalScopes" option instead.', + ); + } return new PinnipedStrategyCache(callbackUrl, config); }, async start(input, ctx): Promise<{ url: string; status?: number }> { @@ -163,9 +175,7 @@ export const pinnipedAuthenticator = createOAuthAuthenticator({ const decodedState = decodeOAuthState(input.state); const state = { ...decodedState, audience: stringifiedAudience }; const options: Record = { - scope: - input.scope || - 'openid pinniped:request-audience username offline_access', + scope: input.scope, state: encodeOAuthState(state), }; diff --git a/plugins/auth-backend-module-vmware-cloud-provider/config.d.ts b/plugins/auth-backend-module-vmware-cloud-provider/config.d.ts index 10b3566899..6ea07f1936 100644 --- a/plugins/auth-backend-module-vmware-cloud-provider/config.d.ts +++ b/plugins/auth-backend-module-vmware-cloud-provider/config.d.ts @@ -24,6 +24,7 @@ export interface Config { organizationId: string; scope?: string; consoleEndpoint?: string; + additionalScopes?: string | string[]; }; }; }; diff --git a/plugins/auth-backend-module-vmware-cloud-provider/src/authenticator.test.ts b/plugins/auth-backend-module-vmware-cloud-provider/src/authenticator.test.ts index f38ceeb462..c69d4e9ab1 100644 --- a/plugins/auth-backend-module-vmware-cloud-provider/src/authenticator.test.ts +++ b/plugins/auth-backend-module-vmware-cloud-provider/src/authenticator.test.ts @@ -163,9 +163,9 @@ describe('vmwareCloudAuthenticator', () => { expect(searchParams.get('redirect_uri')).toBe('http://callbackUrl'); }); - it('requests scopes for ID and refresh token', async () => { + it('forwards scopes for ID and refresh token', async () => { const startResponse = await vmwareCloudAuthenticator.start( - startRequest, + { ...startRequest, scope: 'openid offline_access' }, authenticatorCtx, ); const { searchParams } = new URL(startResponse.url); diff --git a/plugins/auth-backend-module-vmware-cloud-provider/src/authenticator.ts b/plugins/auth-backend-module-vmware-cloud-provider/src/authenticator.ts index 4db4836f13..55b3b5daec 100644 --- a/plugins/auth-backend-module-vmware-cloud-provider/src/authenticator.ts +++ b/plugins/auth-backend-module-vmware-cloud-provider/src/authenticator.ts @@ -96,6 +96,9 @@ export const vmwareCloudAuthenticator = createOAuthAuthenticator< }, }; }, + scopes: { + required: ['openid', 'offline_access'], + }, initialize({ callbackUrl, config }) { const consoleEndpoint = config.getOptionalString('consoleEndpoint') ?? @@ -106,7 +109,12 @@ export const vmwareCloudAuthenticator = createOAuthAuthenticator< const clientSecret = ''; const authorizationUrl = `${consoleEndpoint}/csp/gateway/discovery`; const tokenUrl = `${consoleEndpoint}/csp/gateway/am/api/auth/token`; - const scope = config.getOptionalString('scope') ?? 'openid offline_access'; + + if (config.has('scope')) { + throw new Error( + 'The vmware-cloud provider no longer supports the "scope" configuration option. Please use the "additionalScopes" option instead.', + ); + } const providerStrategy = new OAuth2Strategy( { @@ -118,7 +126,6 @@ export const vmwareCloudAuthenticator = createOAuthAuthenticator< passReqToCallback: false, pkce: true, state: true, - scope: scope, customHeaders: { Authorization: `Basic ${encodeClientCredentials( clientId, From b2ee7f3a658d4f8e0f79b780ad1d13060b44a427 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 23 May 2024 16:40:18 +0200 Subject: [PATCH 40/46] moved over the urlreader to backend-defaults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/nervous-kings-change.md | 15 + .changeset/shaggy-zebras-mate.md | 6 + docs/plugins/url-reader.md | 7 +- package.json | 2 +- packages/backend-app-api/api-report.md | 7 +- packages/backend-common/api-report.md | 441 +++++------------- packages/backend-common/src/reading/index.ts | 236 ++++++++-- .../backend-defaults/api-report-urlReader.md | 434 ++++++++++++++++- packages/backend-defaults/package.json | 22 + .../src/entrypoints/urlReader/index.ts | 1 + .../lib}/AwsCodeCommitUrlReader.test.ts | 0 .../urlReader/lib}/AwsCodeCommitUrlReader.ts | 29 +- .../urlReader/lib}/AwsS3UrlReader.test.ts | 0 .../urlReader/lib}/AwsS3UrlReader.ts | 29 +- .../urlReader/lib}/AzureUrlReader.test.ts | 0 .../urlReader/lib}/AzureUrlReader.ts | 36 +- .../lib}/BitbucketCloudUrlReader.test.ts | 0 .../urlReader/lib}/BitbucketCloudUrlReader.ts | 36 +- .../lib}/BitbucketServerUrlReader.test.ts | 0 .../lib}/BitbucketServerUrlReader.ts | 36 +- .../urlReader/lib}/BitbucketUrlReader.test.ts | 0 .../urlReader/lib}/BitbucketUrlReader.ts | 36 +- .../urlReader/lib}/FetchUrlReader.test.ts | 0 .../urlReader/lib}/FetchUrlReader.ts | 26 +- .../urlReader/lib}/GerritUrlReader.test.ts | 0 .../urlReader/lib}/GerritUrlReader.ts | 35 +- .../urlReader/lib}/GiteaUrlReader.test.ts | 0 .../urlReader/lib}/GiteaUrlReader.ts | 32 +- .../urlReader/lib}/GithubUrlReader.test.ts | 0 .../urlReader/lib}/GithubUrlReader.ts | 44 +- .../urlReader/lib}/GitlabUrlReader.test.ts | 0 .../urlReader/lib}/GitlabUrlReader.ts | 36 +- .../urlReader/lib}/GoogleGcsUrlReader.test.ts | 6 +- .../urlReader/lib}/GoogleGcsUrlReader.ts | 32 +- .../urlReader/lib}/HarnessUrlReader.test.ts | 0 .../urlReader/lib}/HarnessUrlReader.ts | 33 +- .../lib}/ReadUrlResponseFactory.test.ts | 0 .../urlReader/lib}/ReadUrlResponseFactory.ts | 10 +- .../lib}/UrlReaderPredicateMux.test.ts | 0 .../urlReader/lib}/UrlReaderPredicateMux.ts | 37 +- .../entrypoints/urlReader/lib}/UrlReaders.ts | 6 +- .../awsCodeCommit-mock-object.yaml | 0 .../subFolder/awsCodeCommit-mock-object2.yaml | 0 .../__fixtures__/awsS3/awsS3-mock-object.yaml | 0 .../awsS3/awsS3-mock-object2.yaml | 0 .../awsS3/awsS3-mock-object3.yaml | 0 .../backstage-mock-etag123.tar.gz | Bin .../bitbucket-repo-with-commit-hash.tar.gz | Bin .../__fixtures__/bitbucket-server-repo.tar.gz | Bin .../gerrit/branch-info-response.txt | 0 .../gerrit/gerrit-master-docs.tar.gz | Bin .../__fixtures__/gerrit/gerrit-master.tar.gz | Bin .../lib}/__fixtures__/gitlab-archive.tar.gz | Bin .../lib}/__fixtures__/gitlab-archive.zip | Bin .../gitlab-subpath-archive.tar.gz | Bin .../urlReader/lib}/__fixtures__/mallory.zip | Bin .../lib}/__fixtures__/mock-corrupted.zip | Bin .../lib}/__fixtures__/mock-main.tar.gz | Bin .../urlReader/lib}/__fixtures__/mock-main.zip | Bin .../__fixtures__/mock-with-extra-root-dir.zip | Bin .../src/entrypoints/urlReader/lib}/git.ts | 0 .../src/entrypoints/urlReader/lib/index.ts | 38 ++ .../lib}/tree/ReadTreeResponseFactory.ts | 8 +- .../lib}/tree/ReadableArrayResponse.test.ts | 0 .../lib}/tree/ReadableArrayResponse.ts | 21 +- .../lib}/tree/TarArchiveResponse.test.ts | 0 .../urlReader/lib}/tree/TarArchiveResponse.ts | 18 +- .../lib}/tree/ZipArchiveResponse.test.ts | 0 .../urlReader/lib}/tree/ZipArchiveResponse.ts | 18 +- .../entrypoints/urlReader/lib}/tree/index.ts | 0 .../entrypoints/urlReader/lib}/tree/util.ts | 0 .../src/entrypoints/urlReader/lib}/types.ts | 21 +- .../src/entrypoints/urlReader/lib}/util.ts | 0 .../urlReader/urlReaderServiceFactory.ts | 2 +- packages/backend-plugin-api/api-report.md | 162 ++++--- .../services/definitions/UrlReaderService.ts | 87 +++- .../src/services/definitions/index.ts | 9 + yarn.lock | 22 + 78 files changed, 1338 insertions(+), 738 deletions(-) create mode 100644 .changeset/nervous-kings-change.md create mode 100644 .changeset/shaggy-zebras-mate.md rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/AwsCodeCommitUrlReader.test.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/AwsCodeCommitUrlReader.ts (95%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/AwsS3UrlReader.test.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/AwsS3UrlReader.ts (95%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/AzureUrlReader.test.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/AzureUrlReader.ts (91%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/BitbucketCloudUrlReader.test.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/BitbucketCloudUrlReader.ts (92%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/BitbucketServerUrlReader.test.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/BitbucketServerUrlReader.ts (92%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/BitbucketUrlReader.test.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/BitbucketUrlReader.ts (93%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/FetchUrlReader.test.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/FetchUrlReader.ts (92%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/GerritUrlReader.test.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/GerritUrlReader.ts (93%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/GiteaUrlReader.test.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/GiteaUrlReader.ts (90%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/GithubUrlReader.test.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/GithubUrlReader.ts (93%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/GitlabUrlReader.test.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/GitlabUrlReader.ts (95%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/GoogleGcsUrlReader.test.ts (95%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/GoogleGcsUrlReader.ts (84%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/HarnessUrlReader.test.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/HarnessUrlReader.ts (90%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/ReadUrlResponseFactory.test.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/ReadUrlResponseFactory.ts (91%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/UrlReaderPredicateMux.test.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/UrlReaderPredicateMux.ts (74%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/UrlReaders.ts (94%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/awsCodeCommit/awsCodeCommit-mock-object.yaml (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/awsCodeCommit/subFolder/awsCodeCommit-mock-object2.yaml (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/awsS3/awsS3-mock-object.yaml (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/awsS3/awsS3-mock-object2.yaml (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/awsS3/awsS3-mock-object3.yaml (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/backstage-mock-etag123.tar.gz (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/bitbucket-repo-with-commit-hash.tar.gz (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/bitbucket-server-repo.tar.gz (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/gerrit/branch-info-response.txt (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/gerrit/gerrit-master-docs.tar.gz (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/gerrit/gerrit-master.tar.gz (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/gitlab-archive.tar.gz (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/gitlab-archive.zip (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/gitlab-subpath-archive.tar.gz (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/mallory.zip (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/mock-corrupted.zip (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/mock-main.tar.gz (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/mock-main.zip (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/__fixtures__/mock-with-extra-root-dir.zip (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/git.ts (100%) create mode 100644 packages/backend-defaults/src/entrypoints/urlReader/lib/index.ts rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/tree/ReadTreeResponseFactory.ts (90%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/tree/ReadableArrayResponse.test.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/tree/ReadableArrayResponse.ts (84%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/tree/TarArchiveResponse.test.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/tree/TarArchiveResponse.ts (93%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/tree/ZipArchiveResponse.test.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/tree/ZipArchiveResponse.ts (93%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/tree/index.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/tree/util.ts (100%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/types.ts (88%) rename packages/{backend-common/src/reading => backend-defaults/src/entrypoints/urlReader/lib}/util.ts (100%) diff --git a/.changeset/nervous-kings-change.md b/.changeset/nervous-kings-change.md new file mode 100644 index 0000000000..99a3547574 --- /dev/null +++ b/.changeset/nervous-kings-change.md @@ -0,0 +1,15 @@ +--- +'@backstage/backend-plugin-api': patch +--- + +Deprecated all of the `UrlReader` related type names and replaced them with prefixed versions. Please update your imports. + +- `ReadTreeOptions` was renamed to `UrlReaderReadTreeOptions` +- `ReadTreeResponse` was renamed to `UrlReaderReadTreeResponse` +- `ReadTreeResponseDirOptions` was renamed to `UrlReaderReadTreeResponseDirOptions` +- `ReadTreeResponseFile` was renamed to `UrlReaderReadTreeResponseFile` +- `ReadUrlResponse` was renamed to `UrlReaderReadUrlResponse` +- `ReadUrlOptions` was renamed to `UrlReaderReadUrlOptions` +- `SearchOptions` was renamed to `UrlReaderSearchOptions` +- `SearchResponse` was renamed to `UrlReaderSearchResponse` +- `SearchResponseFile` was renamed to `UrlReaderSearchResponseFile` diff --git a/.changeset/shaggy-zebras-mate.md b/.changeset/shaggy-zebras-mate.md new file mode 100644 index 0000000000..c66a92d1e9 --- /dev/null +++ b/.changeset/shaggy-zebras-mate.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-defaults': patch +'@backstage/backend-common': patch +--- + +Moved over all URL reader functionality from `@backstage/backend-common` to `@backstage/backend-defaults/urlReader`. Please update your imports. diff --git a/docs/plugins/url-reader.md b/docs/plugins/url-reader.md index c8ff18952c..c551cdc086 100644 --- a/docs/plugins/url-reader.md +++ b/docs/plugins/url-reader.md @@ -19,7 +19,7 @@ files before generating a documentation site. Since, the requirement for reading files is so essential for Backstage plugins, the -[`@backstage/backend-common`](https://github.com/backstage/backstage/tree/master/packages/backend-common) +[`coreServices.urlReader`](../reference/backend-plugin-api.coreservices.urlreader/) package provides a dedicated API for reading from such URL based remote locations like GitHub, GitLab, Bitbucket, Google Cloud Storage, etc. This is commonly referred to as "URL Reader". It takes care of making authenticated @@ -49,9 +49,8 @@ function makeCreateEnv(config: Config) { } ``` -This instance contains all -[the default URL Reader providers](https://github.com/backstage/backstage/blob/master/packages/backend-common/src/reading/UrlReaders.ts) -in the backend-common package including GitHub, GitLab, Bitbucket, Azure, Google +This instance contains all the default URL Reader providers +in the backend-defaults package including GitHub, GitLab, Bitbucket, Azure, Google GCS. As the need arises, more URL Readers are being written to support different providers. diff --git a/package.json b/package.json index 2951eb8540..c81f4bf07d 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/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-common,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/api-report.md b/packages/backend-app-api/api-report.md index 11d9dd90d4..3d7357cb87 100644 --- a/packages/backend-app-api/api-report.md +++ b/packages/backend-app-api/api-report.md @@ -42,7 +42,7 @@ import { ServiceFactory } from '@backstage/backend-plugin-api'; import { ServiceFactoryOrFunction } from '@backstage/backend-plugin-api'; import { TokenManagerService } from '@backstage/backend-plugin-api'; import { transport } from 'winston'; -import { UrlReader } from '@backstage/backend-common'; +import { UrlReaderService } from '@backstage/backend-plugin-api'; import { UserInfoService } from '@backstage/backend-plugin-api'; // @public (undocumented) @@ -339,7 +339,10 @@ export const tokenManagerServiceFactory: () => ServiceFactory< >; // @public @deprecated (undocumented) -export const urlReaderServiceFactory: () => ServiceFactory; +export const urlReaderServiceFactory: () => ServiceFactory< + UrlReaderService, + 'plugin' +>; // @public (undocumented) export const userInfoServiceFactory: () => ServiceFactory< diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index 2947741fe3..977809071b 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -49,26 +49,32 @@ import { PluginMetadataService } from '@backstage/backend-plugin-api'; import { PushResult } from 'isomorphic-git'; import { Readable } from 'stream'; import { ReadCommitResult } from 'isomorphic-git'; -import { ReadTreeOptions } from '@backstage/backend-plugin-api'; -import { ReadTreeResponse } from '@backstage/backend-plugin-api'; -import { ReadTreeResponseDirOptions } from '@backstage/backend-plugin-api'; -import { ReadTreeResponseFile } from '@backstage/backend-plugin-api'; -import { ReadUrlOptions } from '@backstage/backend-plugin-api'; -import { ReadUrlResponse } from '@backstage/backend-plugin-api'; +import type { ReadTreeOptions as ReadTreeOptions_2 } from '@backstage/backend-plugin-api'; +import type { ReadTreeResponse as ReadTreeResponse_2 } from '@backstage/backend-plugin-api'; +import type { ReadTreeResponseDirOptions as ReadTreeResponseDirOptions_2 } from '@backstage/backend-plugin-api'; +import type { ReadTreeResponseFile as ReadTreeResponseFile_2 } from '@backstage/backend-plugin-api'; +import type { ReadUrlOptions as ReadUrlOptions_2 } from '@backstage/backend-plugin-api'; +import type { ReadUrlResponse as ReadUrlResponse_2 } from '@backstage/backend-plugin-api'; 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 { SearchOptions } from '@backstage/backend-plugin-api'; -import { SearchResponse } from '@backstage/backend-plugin-api'; -import { SearchResponseFile } from '@backstage/backend-plugin-api'; +import type { SearchOptions as SearchOptions_2 } from '@backstage/backend-plugin-api'; +import type { SearchResponse as SearchResponse_2 } from '@backstage/backend-plugin-api'; +import type { SearchResponseFile as SearchResponseFile_2 } from '@backstage/backend-plugin-api'; import { Server } from 'http'; import { ServiceRef } from '@backstage/backend-plugin-api'; import { TokenManagerService as TokenManager } from '@backstage/backend-plugin-api'; import { TransportStreamOptions } from 'winston-transport'; -import { UrlReaderService as UrlReader } from '@backstage/backend-plugin-api'; +import { UrlReaderReadTreeOptions } from '@backstage/backend-plugin-api'; +import { UrlReaderReadTreeResponse } from '@backstage/backend-plugin-api'; +import { UrlReaderReadUrlOptions } from '@backstage/backend-plugin-api'; +import { UrlReaderReadUrlResponse } from '@backstage/backend-plugin-api'; +import { UrlReaderSearchOptions } from '@backstage/backend-plugin-api'; +import { UrlReaderSearchResponse } from '@backstage/backend-plugin-api'; +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'; @@ -80,118 +86,30 @@ export type AuthCallbackOptions = { logger?: LoggerService; }; -// @public -export class AwsS3UrlReader implements UrlReader { - constructor( - credsManager: AwsCredentialsManager, - integration: AwsS3Integration, - deps: { - treeResponseFactory: ReadTreeResponseFactory; - }, - ); - // (undocumented) - static factory: ReaderFactory; - // (undocumented) - read(url: string): Promise; - // (undocumented) - readTree(url: string, options?: ReadTreeOptions): Promise; - // (undocumented) - readUrl(url: string, options?: ReadUrlOptions): Promise; - // (undocumented) - search(): Promise; - // (undocumented) - toString(): string; -} +// Warning: (ae-forgotten-export) The symbol "AwsS3UrlReader_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const AwsS3UrlReader: typeof AwsS3UrlReader_2; -// @public -export class AzureUrlReader implements UrlReader { - constructor( - integration: AzureIntegration, - deps: { - treeResponseFactory: ReadTreeResponseFactory; - credentialsProvider: AzureDevOpsCredentialsProvider; - }, - ); - // (undocumented) - static factory: ReaderFactory; - // (undocumented) - read(url: string): Promise; - // (undocumented) - readTree(url: string, options?: ReadTreeOptions): Promise; - // (undocumented) - readUrl(url: string, options?: ReadUrlOptions): Promise; - // (undocumented) - search(url: string, options?: SearchOptions): Promise; - // (undocumented) - toString(): string; -} +// Warning: (ae-forgotten-export) The symbol "AzureUrlReader_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const AzureUrlReader: typeof AzureUrlReader_2; -// @public -export class BitbucketCloudUrlReader implements UrlReader { - constructor( - integration: BitbucketCloudIntegration, - deps: { - treeResponseFactory: ReadTreeResponseFactory; - }, - ); - // (undocumented) - static factory: ReaderFactory; - // (undocumented) - read(url: string): Promise; - // (undocumented) - readTree(url: string, options?: ReadTreeOptions): Promise; - // (undocumented) - readUrl(url: string, options?: ReadUrlOptions): Promise; - // (undocumented) - search(url: string, options?: SearchOptions): Promise; - // (undocumented) - toString(): string; -} +// Warning: (ae-forgotten-export) The symbol "BitbucketCloudUrlReader_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const BitbucketCloudUrlReader: typeof BitbucketCloudUrlReader_2; -// @public -export class BitbucketServerUrlReader implements UrlReader { - constructor( - integration: BitbucketServerIntegration, - deps: { - treeResponseFactory: ReadTreeResponseFactory; - }, - ); - // (undocumented) - static factory: ReaderFactory; - // (undocumented) - read(url: string): Promise; - // (undocumented) - readTree(url: string, options?: ReadTreeOptions): Promise; - // (undocumented) - readUrl(url: string, options?: ReadUrlOptions): Promise; - // (undocumented) - search(url: string, options?: SearchOptions): Promise; - // (undocumented) - toString(): string; -} +// Warning: (ae-forgotten-export) The symbol "BitbucketServerUrlReader_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const BitbucketServerUrlReader: typeof BitbucketServerUrlReader_2; -// @public @deprecated -export class BitbucketUrlReader implements UrlReader { - constructor( - integration: BitbucketIntegration, - logger: LoggerService, - deps: { - treeResponseFactory: ReadTreeResponseFactory; - }, - ); - // (undocumented) - static factory: ReaderFactory; - // (undocumented) - read(url: string): Promise; - // (undocumented) - readTree(url: string, options?: ReadTreeOptions): Promise; - // (undocumented) - readUrl(url: string, options?: ReadUrlOptions): Promise; - // (undocumented) - search(url: string, options?: SearchOptions): Promise; - // (undocumented) - toString(): string; -} +// Warning: (ae-forgotten-export) The symbol "BitbucketUrlReader_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const BitbucketUrlReader: typeof BitbucketUrlReader_2; // @public @deprecated (undocumented) export type CacheClient = CacheService; @@ -330,50 +248,20 @@ export type ErrorHandlerOptions = { logClientErrors?: boolean; }; -// @public -export class FetchUrlReader implements UrlReader { - static factory: ReaderFactory; - // (undocumented) - read(url: string): Promise; - // (undocumented) - readTree(): Promise; - // (undocumented) - readUrl(url: string, options?: ReadUrlOptions): Promise; - // (undocumented) - search(): Promise; - // (undocumented) - toString(): string; -} +// Warning: (ae-forgotten-export) The symbol "FetchUrlReader_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const FetchUrlReader: typeof FetchUrlReader_2; -// @public -export type FromReadableArrayOptions = Array<{ - data: Readable; - path: string; - lastModifiedAt?: Date; -}>; +// Warning: (ae-forgotten-export) The symbol "FromReadableArrayOptions_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type FromReadableArrayOptions = FromReadableArrayOptions_2; -// @public -export class GerritUrlReader implements UrlReader { - constructor( - integration: GerritIntegration, - deps: { - treeResponseFactory: ReadTreeResponseFactory; - }, - workDir: string, - ); - // (undocumented) - static factory: ReaderFactory; - // (undocumented) - read(url: string): Promise; - // (undocumented) - readTree(url: string, options?: ReadTreeOptions): Promise; - // (undocumented) - readUrl(url: string, options?: ReadUrlOptions): Promise; - // (undocumented) - search(): Promise; - // (undocumented) - toString(): string; -} +// Warning: (ae-forgotten-export) The symbol "GerritUrlReader_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const GerritUrlReader: typeof GerritUrlReader_2; // @public @deprecated export function getRootLogger(): winston.Logger; @@ -457,94 +345,25 @@ export class Git { resolveRef(options: { dir: string; ref: string }): Promise; } -// @public -export class GiteaUrlReader implements UrlReader { - constructor( - integration: GiteaIntegration, - deps: { - treeResponseFactory: ReadTreeResponseFactory; - }, - ); - // (undocumented) - static factory: ReaderFactory; - // (undocumented) - read(url: string): Promise; - // (undocumented) - readTree(url: string, options?: ReadTreeOptions): Promise; - // (undocumented) - readUrl(url: string, options?: ReadUrlOptions): Promise; - // (undocumented) - search(): Promise; - // (undocumented) - toString(): string; -} +// Warning: (ae-forgotten-export) The symbol "GiteaUrlReader_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const GiteaUrlReader: typeof GiteaUrlReader_2; -// @public -export class GithubUrlReader implements UrlReader { - constructor( - integration: GithubIntegration, - deps: { - treeResponseFactory: ReadTreeResponseFactory; - credentialsProvider: GithubCredentialsProvider; - }, - ); - // (undocumented) - static factory: ReaderFactory; - // (undocumented) - read(url: string): Promise; - // (undocumented) - readTree(url: string, options?: ReadTreeOptions): Promise; - // (undocumented) - readUrl(url: string, options?: ReadUrlOptions): Promise; - // (undocumented) - search(url: string, options?: SearchOptions): Promise; - // (undocumented) - toString(): string; -} +// Warning: (ae-forgotten-export) The symbol "GithubUrlReader_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const GithubUrlReader: typeof GithubUrlReader_2; -// @public -export class GitlabUrlReader implements UrlReader { - constructor( - integration: GitLabIntegration, - deps: { - treeResponseFactory: ReadTreeResponseFactory; - }, - ); - // (undocumented) - static factory: ReaderFactory; - // (undocumented) - read(url: string): Promise; - // (undocumented) - readTree(url: string, options?: ReadTreeOptions): Promise; - // (undocumented) - readUrl(url: string, options?: ReadUrlOptions): Promise; - // (undocumented) - search(url: string, options?: SearchOptions): Promise; - // (undocumented) - toString(): string; -} +// Warning: (ae-forgotten-export) The symbol "GitlabUrlReader_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const GitlabUrlReader: typeof GitlabUrlReader_2; -// @public -export class HarnessUrlReader implements UrlReader { - constructor( - integration: HarnessIntegration, - deps: { - treeResponseFactory: ReadTreeResponseFactory; - }, - ); - // (undocumented) - static factory: ReaderFactory; - // (undocumented) - read(url: string): Promise; - // (undocumented) - readTree(url: string, options?: ReadTreeOptions): Promise; - // (undocumented) - readUrl(url: string, options?: ReadUrlOptions): Promise; - // (undocumented) - search(): Promise; - // (undocumented) - toString(): string; -} +// Warning: (ae-forgotten-export) The symbol "HarnessUrlReader_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const HarnessUrlReader: typeof HarnessUrlReader_2; // @public @deprecated export const HostDiscovery: typeof HostDiscovery_2; @@ -596,7 +415,7 @@ export const legacyPlugin: ( permissions: PermissionsService; scheduler: SchedulerService; tokenManager: TokenManager; - reader: UrlReader; + reader: UrlReaderService; identity: IdentityService; }, { @@ -677,73 +496,49 @@ export interface PullOptions { }; } -// @public -export type ReaderFactory = (options: { - config: Config; - logger: LoggerService; - treeResponseFactory: ReadTreeResponseFactory; -}) => UrlReaderPredicateTuple[]; +// Warning: (ae-forgotten-export) The symbol "ReaderFactory_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type ReaderFactory = ReaderFactory_2; -export { ReadTreeOptions }; +// @public @deprecated (undocumented) +export type ReadTreeOptions = ReadTreeOptions_2; -export { ReadTreeResponse }; +// @public @deprecated (undocumented) +export type ReadTreeResponse = ReadTreeResponse_2; -export { ReadTreeResponseDirOptions }; +// @public @deprecated (undocumented) +export type ReadTreeResponseDirOptions = ReadTreeResponseDirOptions_2; -// @public -export interface ReadTreeResponseFactory { - // (undocumented) - fromReadableArray( - options: FromReadableArrayOptions, - ): Promise; - // (undocumented) - fromTarArchive( - options: ReadTreeResponseFactoryOptions & { - stripFirstDirectory?: boolean; - }, - ): Promise; - // (undocumented) - fromZipArchive( - options: ReadTreeResponseFactoryOptions, - ): Promise; -} +// Warning: (ae-forgotten-export) The symbol "ReadTreeResponseFactory_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type ReadTreeResponseFactory = ReadTreeResponseFactory_2; -// @public -export type ReadTreeResponseFactoryOptions = { - stream: Readable; - subpath?: string; - etag: string; - filter?: ( - path: string, - info?: { - size: number; - }, - ) => boolean; -}; +// Warning: (ae-forgotten-export) The symbol "ReadTreeResponseFactoryOptions_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type ReadTreeResponseFactoryOptions = ReadTreeResponseFactoryOptions_2; -export { ReadTreeResponseFile }; +// @public @deprecated (undocumented) +export type ReadTreeResponseFile = ReadTreeResponseFile_2; -export { ReadUrlOptions }; +// @public @deprecated (undocumented) +export type ReadUrlOptions = ReadUrlOptions_2; -export { ReadUrlResponse }; +// @public @deprecated (undocumented) +export type ReadUrlResponse = ReadUrlResponse_2; -// @public -export class ReadUrlResponseFactory { - static fromNodeJSReadable( - oldStyleStream: NodeJS.ReadableStream, - options?: ReadUrlResponseFactoryFromStreamOptions, - ): Promise; - static fromReadable( - stream: Readable, - options?: ReadUrlResponseFactoryFromStreamOptions, - ): Promise; -} +// Warning: (ae-forgotten-export) The symbol "ReadUrlResponseFactory_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const ReadUrlResponseFactory: typeof ReadUrlResponseFactory_2; -// @public -export type ReadUrlResponseFactoryFromStreamOptions = { - etag?: string; - lastModifiedAt?: Date; -}; +// Warning: (ae-forgotten-export) The symbol "ReadUrlResponseFactoryFromStreamOptions_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type ReadUrlResponseFactoryFromStreamOptions = + ReadUrlResponseFactoryFromStreamOptions_2; // @public export function redactWinstonLogLine( @@ -778,11 +573,14 @@ export type RunContainerOptions = { pullOptions?: PullOptions; }; -export { SearchOptions }; +// @public @deprecated (undocumented) +export type SearchOptions = SearchOptions_2; -export { SearchResponse }; +// @public @deprecated (undocumented) +export type SearchResponse = SearchResponse_2; -export { SearchResponseFile }; +// @public @deprecated (undocumented) +export type SearchResponseFile = SearchResponseFile_2; // @public export class ServerTokenManager implements TokenManager { @@ -861,26 +659,23 @@ export interface StatusCheckHandlerOptions { export { TokenManager }; -export { UrlReader }; +// @public @deprecated (undocumented) +export type UrlReader = UrlReaderService; -// @public -export type UrlReaderPredicateTuple = { - predicate: (url: URL) => boolean; - reader: UrlReader; -}; +// Warning: (ae-forgotten-export) The symbol "UrlReaderPredicateTuple_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type UrlReaderPredicateTuple = UrlReaderPredicateTuple_2; -// @public -export class UrlReaders { - static create(options: UrlReadersOptions): UrlReader; - static default(options: UrlReadersOptions): UrlReader; -} +// Warning: (ae-forgotten-export) The symbol "UrlReaders_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export const UrlReaders: typeof UrlReaders_2; -// @public -export type UrlReadersOptions = { - config: Config; - logger: LoggerService; - factories?: ReaderFactory[]; -}; +// Warning: (ae-forgotten-export) The symbol "UrlReadersOptions_2" needs to be exported by the entry point index.d.ts +// +// @public @deprecated (undocumented) +export type UrlReadersOptions = UrlReadersOptions_2; // @public @deprecated export function useHotCleanup( diff --git a/packages/backend-common/src/reading/index.ts b/packages/backend-common/src/reading/index.ts index a99bb6dda1..0b037ed6c2 100644 --- a/packages/backend-common/src/reading/index.ts +++ b/packages/backend-common/src/reading/index.ts @@ -14,35 +14,207 @@ * limitations under the License. */ -export { AzureUrlReader } from './AzureUrlReader'; -export { BitbucketCloudUrlReader } from './BitbucketCloudUrlReader'; -export { BitbucketUrlReader } from './BitbucketUrlReader'; -export { BitbucketServerUrlReader } from './BitbucketServerUrlReader'; -export { GerritUrlReader } from './GerritUrlReader'; -export { GithubUrlReader } from './GithubUrlReader'; -export { GitlabUrlReader } from './GitlabUrlReader'; -export { GiteaUrlReader } from './GiteaUrlReader'; -export { HarnessUrlReader } from './HarnessUrlReader'; -export { AwsS3UrlReader } from './AwsS3UrlReader'; -export { FetchUrlReader } from './FetchUrlReader'; -export { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; -export type { - FromReadableArrayOptions, - ReaderFactory, - ReadTreeOptions, - ReadTreeResponse, - ReadTreeResponseFactory, - ReadTreeResponseFile, - ReadTreeResponseDirOptions, - ReadTreeResponseFactoryOptions, - ReadUrlOptions, - ReadUrlResponse, - ReadUrlResponseFactoryFromStreamOptions, - SearchOptions, - SearchResponse, - SearchResponseFile, - UrlReader, - UrlReaderPredicateTuple, -} from './types'; -export { UrlReaders } from './UrlReaders'; -export type { UrlReadersOptions } from './UrlReaders'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { AzureUrlReader as _AzureUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/AzureUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { BitbucketCloudUrlReader as _BitbucketCloudUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/BitbucketCloudUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { BitbucketUrlReader as _BitbucketUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { BitbucketServerUrlReader as _BitbucketServerUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/BitbucketServerUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { GerritUrlReader as _GerritUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/GerritUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { GithubUrlReader as _GithubUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { GitlabUrlReader as _GitlabUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { GiteaUrlReader as _GiteaUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/GiteaUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { HarnessUrlReader as _HarnessUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/HarnessUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { AwsS3UrlReader as _AwsS3UrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { FetchUrlReader as _FetchUrlReader } from '../../../backend-defaults/src/entrypoints/urlReader/lib/FetchUrlReader'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { UrlReaders as _UrlReaders } from '../../../backend-defaults/src/entrypoints/urlReader/lib/UrlReaders'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { ReadUrlResponseFactory as _ReadUrlResponseFactory } from '../../../backend-defaults/src/entrypoints/urlReader/lib/ReadUrlResponseFactory'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import type { UrlReadersOptions as _UrlReadersOptions } from '../../../backend-defaults/src/entrypoints/urlReader/lib/UrlReaders'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import type { FromReadableArrayOptions as _FromReadableArrayOptions } from '../../../backend-defaults/src/entrypoints/urlReader/lib/types'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import type { + ReaderFactory as _ReaderFactory, + ReadTreeResponseFactory as _ReadTreeResponseFactory, + ReadTreeResponseFactoryOptions as _ReadTreeResponseFactoryOptions, + ReadUrlResponseFactoryFromStreamOptions as _ReadUrlResponseFactoryFromStreamOptions, + UrlReaderPredicateTuple as _UrlReaderPredicateTuple, +} from '../../../backend-defaults/src/entrypoints/urlReader/lib/types'; + +import type { + ReadTreeOptions as _ReadTreeOptions, + ReadTreeResponse as _ReadTreeResponse, + ReadTreeResponseFile as _ReadTreeResponseFile, + ReadTreeResponseDirOptions as _ReadTreeResponseDirOptions, + ReadUrlOptions as _ReadUrlOptions, + ReadUrlResponse as _ReadUrlResponse, + SearchOptions as _SearchOptions, + SearchResponse as _SearchResponse, + SearchResponseFile as _SearchResponseFile, + UrlReaderService as _UrlReaderService, +} from '@backstage/backend-plugin-api'; + +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export const AzureUrlReader = _AzureUrlReader; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export const BitbucketCloudUrlReader = _BitbucketCloudUrlReader; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export const BitbucketUrlReader = _BitbucketUrlReader; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export const BitbucketServerUrlReader = _BitbucketServerUrlReader; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export const GerritUrlReader = _GerritUrlReader; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export const GithubUrlReader = _GithubUrlReader; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export const GitlabUrlReader = _GitlabUrlReader; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export const GiteaUrlReader = _GiteaUrlReader; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export const HarnessUrlReader = _HarnessUrlReader; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export const AwsS3UrlReader = _AwsS3UrlReader; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export const FetchUrlReader = _FetchUrlReader; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export const UrlReaders = _UrlReaders; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export const ReadUrlResponseFactory = _ReadUrlResponseFactory; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export type UrlReadersOptions = _UrlReadersOptions; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export type FromReadableArrayOptions = _FromReadableArrayOptions; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export type ReaderFactory = _ReaderFactory; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export type ReadTreeResponseFactory = _ReadTreeResponseFactory; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export type ReadTreeResponseFactoryOptions = _ReadTreeResponseFactoryOptions; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export type ReadUrlResponseFactoryFromStreamOptions = + _ReadUrlResponseFactoryFromStreamOptions; +/** + * @public + * @deprecated Import from `@backstage/backend-defaults/urlReader` instead + */ +export type UrlReaderPredicateTuple = _UrlReaderPredicateTuple; + +/** + * @public + * @deprecated Use `ÙrlReaderReadTreeOptions` from `@backstage/backend-plugin-api` instead + */ +export type ReadTreeOptions = _ReadTreeOptions; +/** + * @public + * @deprecated Use `ÙrlReaderReadTreeResponse` from `@backstage/backend-plugin-api` instead + */ +export type ReadTreeResponse = _ReadTreeResponse; +/** + * @public + * @deprecated Use `ÙrlReaderReadTreeResponseFile` from `@backstage/backend-plugin-api` instead + */ +export type ReadTreeResponseFile = _ReadTreeResponseFile; +/** + * @public + * @deprecated Use `ÙrlReaderReadTreeResponseDirOptions` from `@backstage/backend-plugin-api` instead + */ +export type ReadTreeResponseDirOptions = _ReadTreeResponseDirOptions; +/** + * @public + * @deprecated Use `ÙrlReaderReadUrlOptions` from `@backstage/backend-plugin-api` instead + */ +export type ReadUrlOptions = _ReadUrlOptions; +/** + * @public + * @deprecated Use `ÙrlReaderReadUrlResponse` from `@backstage/backend-plugin-api` instead + */ +export type ReadUrlResponse = _ReadUrlResponse; +/** + * @public + * @deprecated Use `ÙrlReaderSearchOptions` from `@backstage/backend-plugin-api` instead + */ +export type SearchOptions = _SearchOptions; +/** + * @public + * @deprecated Use `ÙrlReaderSearchResponse` from `@backstage/backend-plugin-api` instead + */ +export type SearchResponse = _SearchResponse; +/** + * @public + * @deprecated Use `ÙrlReaderSearchResponseFile` from `@backstage/backend-plugin-api` instead + */ +export type SearchResponseFile = _SearchResponseFile; +/** + * @public + * @deprecated Use `ÙrlReaderService` from `@backstage/backend-plugin-api` instead + */ +export type UrlReader = _UrlReaderService; diff --git a/packages/backend-defaults/api-report-urlReader.md b/packages/backend-defaults/api-report-urlReader.md index 8c7147bd7c..d9300d731a 100644 --- a/packages/backend-defaults/api-report-urlReader.md +++ b/packages/backend-defaults/api-report-urlReader.md @@ -3,11 +3,441 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +/// + +import { AwsCredentialsManager } from '@backstage/integration-aws-node'; +import { AwsS3Integration } from '@backstage/integration'; +import { AzureDevOpsCredentialsProvider } from '@backstage/integration'; +import { AzureIntegration } from '@backstage/integration'; +import { BitbucketCloudIntegration } from '@backstage/integration'; +import { BitbucketIntegration } from '@backstage/integration'; +import { BitbucketServerIntegration } from '@backstage/integration'; +import { Config } from '@backstage/config'; +import { GerritIntegration } from '@backstage/integration'; +import { GiteaIntegration } from '@backstage/integration'; +import { GithubCredentialsProvider } from '@backstage/integration'; +import { GithubIntegration } from '@backstage/integration'; +import { GitLabIntegration } from '@backstage/integration'; +import { HarnessIntegration } from '@backstage/integration'; +import { LoggerService } from '@backstage/backend-plugin-api'; +import { Readable } from 'stream'; import { ServiceFactory } from '@backstage/backend-plugin-api'; -import { UrlReader } from '@backstage/backend-common'; +import { UrlReaderReadTreeOptions } from '@backstage/backend-plugin-api'; +import { UrlReaderReadTreeResponse } from '@backstage/backend-plugin-api'; +import { UrlReaderReadUrlOptions } from '@backstage/backend-plugin-api'; +import { UrlReaderReadUrlResponse } from '@backstage/backend-plugin-api'; +import { UrlReaderSearchOptions } from '@backstage/backend-plugin-api'; +import { UrlReaderSearchResponse } from '@backstage/backend-plugin-api'; +import { UrlReaderService } from '@backstage/backend-plugin-api'; + +// @public +export class AwsS3UrlReader implements UrlReaderService { + constructor( + credsManager: AwsCredentialsManager, + integration: AwsS3Integration, + deps: { + treeResponseFactory: ReadTreeResponseFactory; + }, + ); + // (undocumented) + static factory: ReaderFactory; + // (undocumented) + read(url: string): Promise; + // (undocumented) + readTree( + url: string, + options?: UrlReaderReadTreeOptions, + ): Promise; + // (undocumented) + readUrl( + url: string, + options?: UrlReaderReadUrlOptions, + ): Promise; + // (undocumented) + search(): Promise; + // (undocumented) + toString(): string; +} + +// @public +export class AzureUrlReader implements UrlReaderService { + constructor( + integration: AzureIntegration, + deps: { + treeResponseFactory: ReadTreeResponseFactory; + credentialsProvider: AzureDevOpsCredentialsProvider; + }, + ); + // (undocumented) + static factory: ReaderFactory; + // (undocumented) + read(url: string): Promise; + // (undocumented) + readTree( + url: string, + options?: UrlReaderReadTreeOptions, + ): Promise; + // (undocumented) + readUrl( + url: string, + options?: UrlReaderReadUrlOptions, + ): Promise; + // (undocumented) + search( + url: string, + options?: UrlReaderSearchOptions, + ): Promise; + // (undocumented) + toString(): string; +} + +// @public +export class BitbucketCloudUrlReader implements UrlReaderService { + constructor( + integration: BitbucketCloudIntegration, + deps: { + treeResponseFactory: ReadTreeResponseFactory; + }, + ); + // (undocumented) + static factory: ReaderFactory; + // (undocumented) + read(url: string): Promise; + // (undocumented) + readTree( + url: string, + options?: UrlReaderReadTreeOptions, + ): Promise; + // (undocumented) + readUrl( + url: string, + options?: UrlReaderReadUrlOptions, + ): Promise; + // (undocumented) + search( + url: string, + options?: UrlReaderSearchOptions, + ): Promise; + // (undocumented) + toString(): string; +} + +// @public +export class BitbucketServerUrlReader implements UrlReaderService { + constructor( + integration: BitbucketServerIntegration, + deps: { + treeResponseFactory: ReadTreeResponseFactory; + }, + ); + // (undocumented) + static factory: ReaderFactory; + // (undocumented) + read(url: string): Promise; + // (undocumented) + readTree( + url: string, + options?: UrlReaderReadTreeOptions, + ): Promise; + // (undocumented) + readUrl( + url: string, + options?: UrlReaderReadUrlOptions, + ): Promise; + // (undocumented) + search( + url: string, + options?: UrlReaderSearchOptions, + ): Promise; + // (undocumented) + toString(): string; +} + +// @public @deprecated +export class BitbucketUrlReader implements UrlReaderService { + constructor( + integration: BitbucketIntegration, + logger: LoggerService, + deps: { + treeResponseFactory: ReadTreeResponseFactory; + }, + ); + // (undocumented) + static factory: ReaderFactory; + // (undocumented) + read(url: string): Promise; + // (undocumented) + readTree( + url: string, + options?: UrlReaderReadTreeOptions, + ): Promise; + // (undocumented) + readUrl( + url: string, + options?: UrlReaderReadUrlOptions, + ): Promise; + // (undocumented) + search( + url: string, + options?: UrlReaderSearchOptions, + ): Promise; + // (undocumented) + toString(): string; +} + +// @public +export class FetchUrlReader implements UrlReaderService { + static factory: ReaderFactory; + // (undocumented) + read(url: string): Promise; + // (undocumented) + readTree(): Promise; + // (undocumented) + readUrl( + url: string, + options?: UrlReaderReadUrlOptions, + ): Promise; + // (undocumented) + search(): Promise; + // (undocumented) + toString(): string; +} + +// @public +export type FromReadableArrayOptions = Array<{ + data: Readable; + path: string; + lastModifiedAt?: Date; +}>; + +// @public +export class GerritUrlReader implements UrlReaderService { + constructor( + integration: GerritIntegration, + deps: { + treeResponseFactory: ReadTreeResponseFactory; + }, + workDir: string, + ); + // (undocumented) + static factory: ReaderFactory; + // (undocumented) + read(url: string): Promise; + // (undocumented) + readTree( + url: string, + options?: UrlReaderReadTreeOptions, + ): Promise; + // (undocumented) + readUrl( + url: string, + options?: UrlReaderReadUrlOptions, + ): Promise; + // (undocumented) + search(): Promise; + // (undocumented) + toString(): string; +} + +// @public +export class GiteaUrlReader implements UrlReaderService { + constructor( + integration: GiteaIntegration, + deps: { + treeResponseFactory: ReadTreeResponseFactory; + }, + ); + // (undocumented) + static factory: ReaderFactory; + // (undocumented) + read(url: string): Promise; + // (undocumented) + readTree( + url: string, + options?: UrlReaderReadTreeOptions, + ): Promise; + // (undocumented) + readUrl( + url: string, + options?: UrlReaderReadUrlOptions, + ): Promise; + // (undocumented) + search(): Promise; + // (undocumented) + toString(): string; +} + +// @public +export class GithubUrlReader implements UrlReaderService { + constructor( + integration: GithubIntegration, + deps: { + treeResponseFactory: ReadTreeResponseFactory; + credentialsProvider: GithubCredentialsProvider; + }, + ); + // (undocumented) + static factory: ReaderFactory; + // (undocumented) + read(url: string): Promise; + // (undocumented) + readTree( + url: string, + options?: UrlReaderReadTreeOptions, + ): Promise; + // (undocumented) + readUrl( + url: string, + options?: UrlReaderReadUrlOptions, + ): Promise; + // (undocumented) + search( + url: string, + options?: UrlReaderSearchOptions, + ): Promise; + // (undocumented) + toString(): string; +} + +// @public +export class GitlabUrlReader implements UrlReaderService { + constructor( + integration: GitLabIntegration, + deps: { + treeResponseFactory: ReadTreeResponseFactory; + }, + ); + // (undocumented) + static factory: ReaderFactory; + // (undocumented) + read(url: string): Promise; + // (undocumented) + readTree( + url: string, + options?: UrlReaderReadTreeOptions, + ): Promise; + // (undocumented) + readUrl( + url: string, + options?: UrlReaderReadUrlOptions, + ): Promise; + // (undocumented) + search( + url: string, + options?: UrlReaderSearchOptions, + ): Promise; + // (undocumented) + toString(): string; +} + +// @public +export class HarnessUrlReader implements UrlReaderService { + constructor( + integration: HarnessIntegration, + deps: { + treeResponseFactory: ReadTreeResponseFactory; + }, + ); + // (undocumented) + static factory: ReaderFactory; + // (undocumented) + read(url: string): Promise; + // (undocumented) + readTree( + url: string, + options?: UrlReaderReadTreeOptions, + ): Promise; + // (undocumented) + readUrl( + url: string, + options?: UrlReaderReadUrlOptions, + ): Promise; + // (undocumented) + search(): Promise; + // (undocumented) + toString(): string; +} + +// @public +export type ReaderFactory = (options: { + config: Config; + logger: LoggerService; + treeResponseFactory: ReadTreeResponseFactory; +}) => UrlReaderPredicateTuple[]; + +// @public +export interface ReadTreeResponseFactory { + // (undocumented) + fromReadableArray( + options: FromReadableArrayOptions, + ): Promise; + // (undocumented) + fromTarArchive( + options: ReadTreeResponseFactoryOptions & { + stripFirstDirectory?: boolean; + }, + ): Promise; + // (undocumented) + fromZipArchive( + options: ReadTreeResponseFactoryOptions, + ): Promise; +} + +// @public +export type ReadTreeResponseFactoryOptions = { + stream: Readable; + subpath?: string; + etag: string; + filter?: ( + path: string, + info?: { + size: number; + }, + ) => boolean; +}; + +// @public +export class ReadUrlResponseFactory { + static fromNodeJSReadable( + oldStyleStream: NodeJS.ReadableStream, + options?: ReadUrlResponseFactoryFromStreamOptions, + ): Promise; + static fromReadable( + stream: Readable, + options?: ReadUrlResponseFactoryFromStreamOptions, + ): Promise; +} + +// @public +export type ReadUrlResponseFactoryFromStreamOptions = { + etag?: string; + lastModifiedAt?: Date; +}; + +// @public +export type UrlReaderPredicateTuple = { + predicate: (url: URL) => boolean; + reader: UrlReaderService; +}; + +// @public +export class UrlReaders { + static create(options: UrlReadersOptions): UrlReaderService; + static default(options: UrlReadersOptions): UrlReaderService; +} // @public (undocumented) -export const urlReaderServiceFactory: () => ServiceFactory; +export const urlReaderServiceFactory: () => ServiceFactory< + UrlReaderService, + 'plugin' +>; + +// @public +export type UrlReadersOptions = { + config: Config; + logger: LoggerService; + factories?: ReaderFactory[]; +}; // (No @packageDocumentation comment for this package) ``` diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index 505c8924ba..19d0781e7e 100644 --- a/packages/backend-defaults/package.json +++ b/packages/backend-defaults/package.json @@ -82,6 +82,11 @@ "test": "backstage-cli package test" }, "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-app-api": "workspace:^", "@backstage/backend-common": "workspace:^", "@backstage/backend-dev-utils": "workspace:^", @@ -89,31 +94,48 @@ "@backstage/config": "workspace:^", "@backstage/config-loader": "workspace:^", "@backstage/errors": "workspace:^", + "@backstage/integration": "workspace:^", + "@backstage/integration-aws-node": "workspace:^", "@backstage/plugin-events-node": "workspace:^", "@backstage/plugin-permission-node": "workspace:^", "@backstage/types": "workspace:^", + "@google-cloud/storage": "^7.0.0", "@keyv/memcache": "^1.3.5", "@keyv/redis": "^2.5.3", + "@octokit/rest": "^19.0.3", "@opentelemetry/api": "^1.3.0", + "archiver": "^6.0.0", + "base64-stream": "^1.0.0", "better-sqlite3": "^9.0.0", + "concat-stream": "^2.0.0", "cron": "^3.0.0", "fs-extra": "^11.2.0", + "git-url-parse": "^14.0.0", + "isomorphic-git": "^1.23.0", "keyv": "^4.5.2", "knex": "^3.0.0", "lodash": "^4.17.21", "luxon": "^3.0.0", + "minimatch": "^9.0.0", "mysql2": "^3.0.0", + "node-fetch": "^2.6.7", "p-limit": "^3.1.0", "pg": "^8.11.3", "pg-connection-string": "^2.3.0", + "raw-body": "^2.4.1", + "tar": "^6.1.12", "uuid": "^9.0.0", + "yauzl": "^3.0.0", "yn": "^4.0.0", "zod": "^3.22.4" }, "devDependencies": { + "@aws-sdk/util-stream-node": "^3.350.0", "@backstage/backend-plugin-api": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "aws-sdk-client-mock": "^4.0.0", + "msw": "^1.0.0", "wait-for-expect": "^3.0.2" }, "configSchema": "config.d.ts" diff --git a/packages/backend-defaults/src/entrypoints/urlReader/index.ts b/packages/backend-defaults/src/entrypoints/urlReader/index.ts index 6a4b9f65be..cf927ea031 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/index.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/index.ts @@ -14,4 +14,5 @@ * limitations under the License. */ +export * from './lib'; export { urlReaderServiceFactory } from './urlReaderServiceFactory'; diff --git a/packages/backend-common/src/reading/AwsCodeCommitUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.test.ts similarity index 100% rename from packages/backend-common/src/reading/AwsCodeCommitUrlReader.test.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.test.ts diff --git a/packages/backend-common/src/reading/AwsCodeCommitUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.ts similarity index 95% rename from packages/backend-common/src/reading/AwsCodeCommitUrlReader.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.ts index fda8e4c3a0..f204d1390d 100644 --- a/packages/backend-common/src/reading/AwsCodeCommitUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.ts @@ -14,16 +14,15 @@ * limitations under the License. */ +import { ReaderFactory, ReadTreeResponseFactory } from './types'; import { - ReaderFactory, - ReadTreeOptions, - ReadTreeResponse, - ReadTreeResponseFactory, - ReadUrlOptions, - ReadUrlResponse, - SearchResponse, - UrlReader, -} from './types'; + UrlReaderService, + UrlReaderReadTreeOptions, + UrlReaderReadTreeResponse, + UrlReaderReadUrlOptions, + UrlReaderReadUrlResponse, + UrlReaderSearchResponse, +} from '@backstage/backend-plugin-api'; import { AwsCredentialsManager, DefaultAwsCredentialsManager, @@ -118,7 +117,7 @@ export function parseUrl( * * @public */ -export class AwsCodeCommitUrlReader implements UrlReader { +export class AwsCodeCommitUrlReader implements UrlReaderService { static factory: ReaderFactory = ({ config, treeResponseFactory }) => { const integrations = ScmIntegrations.fromConfig(config); const credsManager = DefaultAwsCredentialsManager.fromConfig(config); @@ -222,8 +221,8 @@ export class AwsCodeCommitUrlReader implements UrlReader { async readUrl( url: string, - options?: ReadUrlOptions, - ): Promise { + options?: UrlReaderReadUrlOptions, + ): Promise { // etag and lastModifiedAfter are not supported by the CodeCommit API try { const { path, repositoryName, region, commitSpecifier } = parseUrl( @@ -326,8 +325,8 @@ export class AwsCodeCommitUrlReader implements UrlReader { async readTree( url: string, - options?: ReadTreeOptions, - ): Promise { + options?: UrlReaderReadTreeOptions, + ): Promise { // url: https://eu-west-1.console.aws.amazon.com/codesuite/codecommit/repositories/test-stijn-delete-techdocs/browse?region=eu-west-1 try { const { path, repositoryName, region, commitSpecifier } = parseUrl(url); @@ -380,7 +379,7 @@ export class AwsCodeCommitUrlReader implements UrlReader { } } - async search(): Promise { + async search(): Promise { throw new Error('AwsCodeCommitReader does not implement search'); } diff --git a/packages/backend-common/src/reading/AwsS3UrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader.test.ts similarity index 100% rename from packages/backend-common/src/reading/AwsS3UrlReader.test.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader.test.ts diff --git a/packages/backend-common/src/reading/AwsS3UrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader.ts similarity index 95% rename from packages/backend-common/src/reading/AwsS3UrlReader.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader.ts index 3ba4eebb48..b98b285f99 100644 --- a/packages/backend-common/src/reading/AwsS3UrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader.ts @@ -15,15 +15,14 @@ */ import { - ReaderFactory, - ReadTreeOptions, - ReadTreeResponse, - ReadTreeResponseFactory, - ReadUrlOptions, - ReadUrlResponse, - SearchResponse, - UrlReader, -} from './types'; + UrlReaderService, + UrlReaderReadTreeOptions, + UrlReaderReadTreeResponse, + UrlReaderReadUrlOptions, + UrlReaderReadUrlResponse, + UrlReaderSearchResponse, +} from '@backstage/backend-plugin-api'; +import { ReaderFactory, ReadTreeResponseFactory } from './types'; import { AwsCredentialsManager, DefaultAwsCredentialsManager, @@ -132,7 +131,7 @@ export function parseUrl( * * @public */ -export class AwsS3UrlReader implements UrlReader { +export class AwsS3UrlReader implements UrlReaderService { static factory: ReaderFactory = ({ config, treeResponseFactory }) => { const integrations = ScmIntegrations.fromConfig(config); const credsManager = DefaultAwsCredentialsManager.fromConfig(config); @@ -253,8 +252,8 @@ export class AwsS3UrlReader implements UrlReader { async readUrl( url: string, - options?: ReadUrlOptions, - ): Promise { + options?: UrlReaderReadUrlOptions, + ): Promise { const { etag, lastModifiedAfter } = options ?? {}; try { @@ -300,8 +299,8 @@ export class AwsS3UrlReader implements UrlReader { async readTree( url: string, - options?: ReadTreeOptions, - ): Promise { + options?: UrlReaderReadTreeOptions, + ): Promise { try { const { path, bucket, region } = parseUrl(url, this.integration.config); const s3Client = await this.buildS3Client( @@ -357,7 +356,7 @@ export class AwsS3UrlReader implements UrlReader { } } - async search(): Promise { + async search(): Promise { throw new Error('AwsS3Reader does not implement search'); } diff --git a/packages/backend-common/src/reading/AzureUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/AzureUrlReader.test.ts similarity index 100% rename from packages/backend-common/src/reading/AzureUrlReader.test.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/AzureUrlReader.test.ts diff --git a/packages/backend-common/src/reading/AzureUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/AzureUrlReader.ts similarity index 91% rename from packages/backend-common/src/reading/AzureUrlReader.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/AzureUrlReader.ts index 783736b639..b6945f11ea 100644 --- a/packages/backend-common/src/reading/AzureUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/AzureUrlReader.ts @@ -14,6 +14,15 @@ * limitations under the License. */ +import { + UrlReaderService, + UrlReaderReadTreeOptions, + UrlReaderReadTreeResponse, + UrlReaderReadUrlOptions, + UrlReaderReadUrlResponse, + UrlReaderSearchOptions, + UrlReaderSearchResponse, +} from '@backstage/backend-plugin-api'; import { getAzureCommitsUrl, getAzureDownloadUrl, @@ -27,17 +36,7 @@ import fetch, { Response } from 'node-fetch'; import { Minimatch } from 'minimatch'; import { Readable } from 'stream'; import { NotFoundError, NotModifiedError } from '@backstage/errors'; -import { - ReadTreeResponseFactory, - ReaderFactory, - ReadTreeOptions, - ReadTreeResponse, - SearchOptions, - SearchResponse, - UrlReader, - ReadUrlOptions, - ReadUrlResponse, -} from './types'; +import { ReadTreeResponseFactory, ReaderFactory } from './types'; import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; /** @@ -45,7 +44,7 @@ import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; * * @public */ -export class AzureUrlReader implements UrlReader { +export class AzureUrlReader implements UrlReaderService { static factory: ReaderFactory = ({ config, treeResponseFactory }) => { const integrations = ScmIntegrations.fromConfig(config); const credentialProvider = @@ -75,8 +74,8 @@ export class AzureUrlReader implements UrlReader { async readUrl( url: string, - options?: ReadUrlOptions, - ): Promise { + options?: UrlReaderReadUrlOptions, + ): Promise { // TODO: etag is not implemented yet. const { signal } = options ?? {}; @@ -114,8 +113,8 @@ export class AzureUrlReader implements UrlReader { async readTree( url: string, - options?: ReadTreeOptions, - ): Promise { + options?: UrlReaderReadTreeOptions, + ): Promise { const { etag, filter, signal } = options ?? {}; // TODO: Support filepath based reading tree feature like other providers @@ -180,7 +179,10 @@ export class AzureUrlReader implements UrlReader { }); } - async search(url: string, options?: SearchOptions): Promise { + async search( + url: string, + options?: UrlReaderSearchOptions, + ): Promise { const treeUrl = new URL(url); const path = treeUrl.searchParams.get('path'); diff --git a/packages/backend-common/src/reading/BitbucketCloudUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketCloudUrlReader.test.ts similarity index 100% rename from packages/backend-common/src/reading/BitbucketCloudUrlReader.test.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketCloudUrlReader.test.ts diff --git a/packages/backend-common/src/reading/BitbucketCloudUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketCloudUrlReader.ts similarity index 92% rename from packages/backend-common/src/reading/BitbucketCloudUrlReader.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketCloudUrlReader.ts index 93587cd6ae..5235215758 100644 --- a/packages/backend-common/src/reading/BitbucketCloudUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketCloudUrlReader.ts @@ -14,6 +14,15 @@ * limitations under the License. */ +import { + UrlReaderService, + UrlReaderReadTreeOptions, + UrlReaderReadTreeResponse, + UrlReaderReadUrlOptions, + UrlReaderReadUrlResponse, + UrlReaderSearchOptions, + UrlReaderSearchResponse, +} from '@backstage/backend-plugin-api'; import { NotFoundError, NotModifiedError } from '@backstage/errors'; import { BitbucketCloudIntegration, @@ -28,17 +37,7 @@ import parseGitUrl from 'git-url-parse'; import { trimEnd } from 'lodash'; import { Minimatch } from 'minimatch'; import { Readable } from 'stream'; -import { - ReaderFactory, - ReadTreeOptions, - ReadTreeResponse, - ReadTreeResponseFactory, - ReadUrlOptions, - ReadUrlResponse, - SearchOptions, - SearchResponse, - UrlReader, -} from './types'; +import { ReaderFactory, ReadTreeResponseFactory } from './types'; import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; import { parseLastModified } from './util'; @@ -47,7 +46,7 @@ import { parseLastModified } from './util'; * * @public */ -export class BitbucketCloudUrlReader implements UrlReader { +export class BitbucketCloudUrlReader implements UrlReaderService { static factory: ReaderFactory = ({ config, treeResponseFactory }) => { const integrations = ScmIntegrations.fromConfig(config); return integrations.bitbucketCloud.list().map(integration => { @@ -79,8 +78,8 @@ export class BitbucketCloudUrlReader implements UrlReader { async readUrl( url: string, - options?: ReadUrlOptions, - ): Promise { + options?: UrlReaderReadUrlOptions, + ): Promise { const { etag, lastModifiedAfter, signal } = options ?? {}; const bitbucketUrl = getBitbucketCloudFileFetchUrl( url, @@ -134,8 +133,8 @@ export class BitbucketCloudUrlReader implements UrlReader { async readTree( url: string, - options?: ReadTreeOptions, - ): Promise { + options?: UrlReaderReadTreeOptions, + ): Promise { const { filepath } = parseGitUrl(url); const lastCommitShortHash = await this.getLastCommitShortHash(url); @@ -167,7 +166,10 @@ export class BitbucketCloudUrlReader implements UrlReader { }); } - async search(url: string, options?: SearchOptions): Promise { + async search( + url: string, + options?: UrlReaderSearchOptions, + ): Promise { const { filepath } = parseGitUrl(url); const matcher = new Minimatch(filepath); diff --git a/packages/backend-common/src/reading/BitbucketServerUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketServerUrlReader.test.ts similarity index 100% rename from packages/backend-common/src/reading/BitbucketServerUrlReader.test.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketServerUrlReader.test.ts diff --git a/packages/backend-common/src/reading/BitbucketServerUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketServerUrlReader.ts similarity index 92% rename from packages/backend-common/src/reading/BitbucketServerUrlReader.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketServerUrlReader.ts index 8e2f1708c4..d539b006ed 100644 --- a/packages/backend-common/src/reading/BitbucketServerUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketServerUrlReader.ts @@ -14,6 +14,15 @@ * limitations under the License. */ +import { + UrlReaderService, + UrlReaderReadTreeOptions, + UrlReaderReadTreeResponse, + UrlReaderReadUrlOptions, + UrlReaderReadUrlResponse, + UrlReaderSearchOptions, + UrlReaderSearchResponse, +} from '@backstage/backend-plugin-api'; import { NotFoundError, NotModifiedError } from '@backstage/errors'; import { BitbucketServerIntegration, @@ -27,17 +36,7 @@ import parseGitUrl from 'git-url-parse'; import { trimEnd } from 'lodash'; import { Minimatch } from 'minimatch'; import { Readable } from 'stream'; -import { - ReaderFactory, - ReadTreeOptions, - ReadTreeResponse, - ReadTreeResponseFactory, - ReadUrlOptions, - ReadUrlResponse, - SearchOptions, - SearchResponse, - UrlReader, -} from './types'; +import { ReaderFactory, ReadTreeResponseFactory } from './types'; import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; import { parseLastModified } from './util'; @@ -46,7 +45,7 @@ import { parseLastModified } from './util'; * * @public */ -export class BitbucketServerUrlReader implements UrlReader { +export class BitbucketServerUrlReader implements UrlReaderService { static factory: ReaderFactory = ({ config, treeResponseFactory }) => { const integrations = ScmIntegrations.fromConfig(config); return integrations.bitbucketServer.list().map(integration => { @@ -70,8 +69,8 @@ export class BitbucketServerUrlReader implements UrlReader { async readUrl( url: string, - options?: ReadUrlOptions, - ): Promise { + options?: UrlReaderReadUrlOptions, + ): Promise { const { etag, lastModifiedAfter, signal } = options ?? {}; const bitbucketUrl = getBitbucketServerFileFetchUrl( url, @@ -125,8 +124,8 @@ export class BitbucketServerUrlReader implements UrlReader { async readTree( url: string, - options?: ReadTreeOptions, - ): Promise { + options?: UrlReaderReadTreeOptions, + ): Promise { const { filepath } = parseGitUrl(url); const lastCommitShortHash = await this.getLastCommitShortHash(url); @@ -158,7 +157,10 @@ export class BitbucketServerUrlReader implements UrlReader { }); } - async search(url: string, options?: SearchOptions): Promise { + async search( + url: string, + options?: UrlReaderSearchOptions, + ): Promise { const { filepath } = parseGitUrl(url); const matcher = new Minimatch(filepath); diff --git a/packages/backend-common/src/reading/BitbucketUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.test.ts similarity index 100% rename from packages/backend-common/src/reading/BitbucketUrlReader.test.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.test.ts diff --git a/packages/backend-common/src/reading/BitbucketUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts similarity index 93% rename from packages/backend-common/src/reading/BitbucketUrlReader.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts index 090fe9098d..7f831800d3 100644 --- a/packages/backend-common/src/reading/BitbucketUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts @@ -14,6 +14,15 @@ * limitations under the License. */ +import { + UrlReaderService, + UrlReaderReadTreeOptions, + UrlReaderReadTreeResponse, + UrlReaderReadUrlOptions, + UrlReaderReadUrlResponse, + UrlReaderSearchOptions, + UrlReaderSearchResponse, +} from '@backstage/backend-plugin-api'; import { NotFoundError, NotModifiedError } from '@backstage/errors'; import { BitbucketIntegration, @@ -29,17 +38,7 @@ import { trimEnd } from 'lodash'; import { Minimatch } from 'minimatch'; import { Readable } from 'stream'; import { LoggerService } from '@backstage/backend-plugin-api'; -import { - ReaderFactory, - ReadTreeOptions, - ReadTreeResponse, - ReadTreeResponseFactory, - ReadUrlOptions, - ReadUrlResponse, - SearchOptions, - SearchResponse, - UrlReader, -} from './types'; +import { ReaderFactory, ReadTreeResponseFactory } from './types'; import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; import { parseLastModified } from './util'; @@ -50,7 +49,7 @@ import { parseLastModified } from './util'; * @public * @deprecated in favor of BitbucketCloudUrlReader and BitbucketServerUrlReader */ -export class BitbucketUrlReader implements UrlReader { +export class BitbucketUrlReader implements UrlReaderService { static factory: ReaderFactory = ({ config, logger, treeResponseFactory }) => { const integrations = ScmIntegrations.fromConfig(config); return integrations.bitbucket @@ -95,8 +94,8 @@ export class BitbucketUrlReader implements UrlReader { async readUrl( url: string, - options?: ReadUrlOptions, - ): Promise { + options?: UrlReaderReadUrlOptions, + ): Promise { const { etag, lastModifiedAfter, signal } = options ?? {}; const bitbucketUrl = getBitbucketFileFetchUrl(url, this.integration.config); const requestOptions = getBitbucketRequestOptions(this.integration.config); @@ -145,8 +144,8 @@ export class BitbucketUrlReader implements UrlReader { async readTree( url: string, - options?: ReadTreeOptions, - ): Promise { + options?: UrlReaderReadTreeOptions, + ): Promise { const { filepath } = parseGitUrl(url); const lastCommitShortHash = await this.getLastCommitShortHash(url); @@ -178,7 +177,10 @@ export class BitbucketUrlReader implements UrlReader { }); } - async search(url: string, options?: SearchOptions): Promise { + async search( + url: string, + options?: UrlReaderSearchOptions, + ): Promise { const { filepath } = parseGitUrl(url); const matcher = new Minimatch(filepath); diff --git a/packages/backend-common/src/reading/FetchUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/FetchUrlReader.test.ts similarity index 100% rename from packages/backend-common/src/reading/FetchUrlReader.test.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/FetchUrlReader.test.ts diff --git a/packages/backend-common/src/reading/FetchUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/FetchUrlReader.ts similarity index 92% rename from packages/backend-common/src/reading/FetchUrlReader.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/FetchUrlReader.ts index 475a98ffdc..d62eaedc1a 100644 --- a/packages/backend-common/src/reading/FetchUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/FetchUrlReader.ts @@ -14,16 +14,16 @@ * limitations under the License. */ +import { + UrlReaderService, + UrlReaderReadTreeResponse, + UrlReaderReadUrlOptions, + UrlReaderReadUrlResponse, + UrlReaderSearchResponse, +} from '@backstage/backend-plugin-api'; import { NotFoundError, NotModifiedError } from '@backstage/errors'; import fetch, { Response } from 'node-fetch'; -import { - ReaderFactory, - ReadTreeResponse, - ReadUrlOptions, - ReadUrlResponse, - SearchResponse, - UrlReader, -} from './types'; +import { ReaderFactory } from './types'; import path from 'path'; import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; import { parseLastModified } from './util'; @@ -68,7 +68,7 @@ const parsePortPredicate = (port: string | undefined) => { * * @public */ -export class FetchUrlReader implements UrlReader { +export class FetchUrlReader implements UrlReaderService { /** * The factory creates a single reader that will be used for reading any URL that's listed * in configuration at `backend.reading.allow`. The allow list contains a list of objects describing @@ -121,8 +121,8 @@ export class FetchUrlReader implements UrlReader { async readUrl( url: string, - options?: ReadUrlOptions, - ): Promise { + options?: UrlReaderReadUrlOptions, + ): Promise { let response: Response; try { response = await fetch(url, { @@ -165,11 +165,11 @@ export class FetchUrlReader implements UrlReader { throw new Error(message); } - async readTree(): Promise { + async readTree(): Promise { throw new Error('FetchUrlReader does not implement readTree'); } - async search(): Promise { + async search(): Promise { throw new Error('FetchUrlReader does not implement search'); } diff --git a/packages/backend-common/src/reading/GerritUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GerritUrlReader.test.ts similarity index 100% rename from packages/backend-common/src/reading/GerritUrlReader.test.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/GerritUrlReader.test.ts diff --git a/packages/backend-common/src/reading/GerritUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GerritUrlReader.ts similarity index 93% rename from packages/backend-common/src/reading/GerritUrlReader.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/GerritUrlReader.ts index 52a541382b..2274182e02 100644 --- a/packages/backend-common/src/reading/GerritUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GerritUrlReader.ts @@ -14,6 +14,14 @@ * limitations under the License. */ +import { + UrlReaderService, + UrlReaderReadTreeOptions, + UrlReaderReadTreeResponse, + UrlReaderReadUrlOptions, + UrlReaderReadUrlResponse, + UrlReaderSearchResponse, +} from '@backstage/backend-plugin-api'; import { Base64Decode } from 'base64-stream'; import concatStream from 'concat-stream'; import fs from 'fs-extra'; @@ -35,16 +43,7 @@ import { parseGerritJsonResponse, } from '@backstage/integration'; import { NotFoundError, NotModifiedError } from '@backstage/errors'; -import { - ReadTreeOptions, - ReadTreeResponse, - ReadTreeResponseFactory, - ReadUrlOptions, - ReadUrlResponse, - ReaderFactory, - SearchResponse, - UrlReader, -} from './types'; +import { ReadTreeResponseFactory, ReaderFactory } from './types'; import { Git } from './git'; const pipeline = promisify(pipelineCb); @@ -78,7 +77,7 @@ const createTemporaryDirectory = async (workDir: string): Promise => * * @public */ -export class GerritUrlReader implements UrlReader { +export class GerritUrlReader implements UrlReaderService { static factory: ReaderFactory = ({ config, treeResponseFactory }) => { const integrations = ScmIntegrations.fromConfig(config); if (!integrations.gerrit) { @@ -121,8 +120,8 @@ export class GerritUrlReader implements UrlReader { async readUrl( url: string, - options?: ReadUrlOptions, - ): Promise { + options?: UrlReaderReadUrlOptions, + ): Promise { const apiUrl = getGerritFileContentsApiUrl(this.integration.config, url); let response: Response; try { @@ -166,8 +165,8 @@ export class GerritUrlReader implements UrlReader { async readTree( url: string, - options?: ReadTreeOptions, - ): Promise { + options?: UrlReaderReadTreeOptions, + ): Promise { const apiUrl = getGerritBranchApiUrl(this.integration.config, url); let response: Response; try { @@ -203,7 +202,7 @@ export class GerritUrlReader implements UrlReader { return this.readTreeFromGitClone(url, branchInfo.revision, options); } - async search(): Promise { + async search(): Promise { throw new Error('GerritReader does not implement search'); } @@ -215,7 +214,7 @@ export class GerritUrlReader implements UrlReader { private async readTreeFromGitClone( url: string, revision: string, - options?: ReadTreeOptions, + options?: UrlReaderReadTreeOptions, ) { const { filePath } = parseGerritGitilesUrl(this.integration.config, url); @@ -258,7 +257,7 @@ export class GerritUrlReader implements UrlReader { private async readTreeFromGitiles( url: string, revision: string, - options?: ReadTreeOptions, + options?: UrlReaderReadTreeOptions, ) { const { branch, filePath, project } = parseGerritGitilesUrl( this.integration.config, diff --git a/packages/backend-common/src/reading/GiteaUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GiteaUrlReader.test.ts similarity index 100% rename from packages/backend-common/src/reading/GiteaUrlReader.test.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/GiteaUrlReader.test.ts diff --git a/packages/backend-common/src/reading/GiteaUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GiteaUrlReader.ts similarity index 90% rename from packages/backend-common/src/reading/GiteaUrlReader.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/GiteaUrlReader.ts index c8fab45157..da1b30ab6b 100644 --- a/packages/backend-common/src/reading/GiteaUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GiteaUrlReader.ts @@ -13,6 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +import { + UrlReaderService, + UrlReaderReadTreeOptions, + UrlReaderReadTreeResponse, + UrlReaderReadUrlOptions, + UrlReaderReadUrlResponse, + UrlReaderSearchResponse, +} from '@backstage/backend-plugin-api'; import { getGiteaFileContentsUrl, getGiteaArchiveUrl, @@ -22,16 +31,7 @@ import { GiteaIntegration, ScmIntegrations, } from '@backstage/integration'; -import { - ReaderFactory, - ReadTreeOptions, - ReadTreeResponse, - ReadTreeResponseFactory, - ReadUrlOptions, - ReadUrlResponse, - SearchResponse, - UrlReader, -} from './types'; +import { ReaderFactory, ReadTreeResponseFactory } from './types'; import fetch, { Response } from 'node-fetch'; import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; import { @@ -47,7 +47,7 @@ import { parseLastModified } from './util'; * * @public */ -export class GiteaUrlReader implements UrlReader { +export class GiteaUrlReader implements UrlReaderService { static factory: ReaderFactory = ({ config, treeResponseFactory }) => { return ScmIntegrations.fromConfig(config) .gitea.list() @@ -74,8 +74,8 @@ export class GiteaUrlReader implements UrlReader { async readUrl( url: string, - options?: ReadUrlOptions, - ): Promise { + options?: UrlReaderReadUrlOptions, + ): Promise { let response: Response; const blobUrl = getGiteaFileContentsUrl(this.integration.config, url); @@ -126,8 +126,8 @@ export class GiteaUrlReader implements UrlReader { async readTree( url: string, - options?: ReadTreeOptions, - ): Promise { + options?: UrlReaderReadTreeOptions, + ): Promise { const lastCommitHash = await this.getLastCommitHash(url); if (options?.etag && options.etag === lastCommitHash) { throw new NotModifiedError(); @@ -156,7 +156,7 @@ export class GiteaUrlReader implements UrlReader { }); } - search(): Promise { + search(): Promise { throw new Error('GiteaUrlReader search not implemented.'); } diff --git a/packages/backend-common/src/reading/GithubUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader.test.ts similarity index 100% rename from packages/backend-common/src/reading/GithubUrlReader.test.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader.test.ts diff --git a/packages/backend-common/src/reading/GithubUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader.ts similarity index 93% rename from packages/backend-common/src/reading/GithubUrlReader.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader.ts index b49945013d..60e9b210cd 100644 --- a/packages/backend-common/src/reading/GithubUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GithubUrlReader.ts @@ -14,6 +14,16 @@ * limitations under the License. */ +import { + UrlReaderService, + UrlReaderReadTreeOptions, + UrlReaderReadTreeResponse, + UrlReaderReadUrlOptions, + UrlReaderReadUrlResponse, + UrlReaderSearchOptions, + UrlReaderSearchResponse, + UrlReaderSearchResponseFile, +} from '@backstage/backend-plugin-api'; import { getGithubFileFetchUrl, DefaultGithubCredentialsProvider, @@ -28,18 +38,7 @@ import parseGitUrl from 'git-url-parse'; import { Minimatch } from 'minimatch'; import { Readable } from 'stream'; import { NotFoundError, NotModifiedError } from '@backstage/errors'; -import { - ReadTreeResponseFactory, - ReaderFactory, - ReadTreeOptions, - ReadTreeResponse, - SearchOptions, - SearchResponse, - SearchResponseFile, - UrlReader, - ReadUrlOptions, - ReadUrlResponse, -} from './types'; +import { ReadTreeResponseFactory, ReaderFactory } from './types'; import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; import { parseLastModified } from './util'; @@ -58,7 +57,7 @@ export type GhBlobResponse = * * @public */ -export class GithubUrlReader implements UrlReader { +export class GithubUrlReader implements UrlReaderService { static factory: ReaderFactory = ({ config, treeResponseFactory }) => { const integrations = ScmIntegrations.fromConfig(config); const credentialsProvider = @@ -113,8 +112,8 @@ export class GithubUrlReader implements UrlReader { async readUrl( url: string, - options?: ReadUrlOptions, - ): Promise { + options?: UrlReaderReadUrlOptions, + ): Promise { const credentials = await this.getCredentials(url, options); const ghUrl = getGithubFileFetchUrl( @@ -149,8 +148,8 @@ export class GithubUrlReader implements UrlReader { async readTree( url: string, - options?: ReadTreeOptions, - ): Promise { + options?: UrlReaderReadTreeOptions, + ): Promise { const repoDetails = await this.getRepoDetails(url); const commitSha = repoDetails.commitSha; @@ -176,7 +175,10 @@ export class GithubUrlReader implements UrlReader { ); } - async search(url: string, options?: SearchOptions): Promise { + async search( + url: string, + options?: UrlReaderSearchOptions, + ): Promise { const repoDetails = await this.getRepoDetails(url); const commitSha = repoDetails.commitSha; @@ -209,8 +211,8 @@ export class GithubUrlReader implements UrlReader { sha: string, subpath: string, init: RequestInit, - options?: ReadTreeOptions, - ): Promise { + options?: UrlReaderReadTreeOptions, + ): Promise { // archive_url looks like "https://api.github.com/repos/owner/repo/{archive_format}{/ref}" const archive = await this.fetchResponse( archiveUrl @@ -236,7 +238,7 @@ export class GithubUrlReader implements UrlReader { sha: string, query: string, init: RequestInit, - ): Promise { + ): Promise { function pathToUrl(path: string): string { // TODO(freben): Use the integration package facility for this instead // pathname starts as /backstage/backstage/blob/master/ diff --git a/packages/backend-common/src/reading/GitlabUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.test.ts similarity index 100% rename from packages/backend-common/src/reading/GitlabUrlReader.test.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.test.ts diff --git a/packages/backend-common/src/reading/GitlabUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.ts similarity index 95% rename from packages/backend-common/src/reading/GitlabUrlReader.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.ts index 178e65b40a..b45a61a40e 100644 --- a/packages/backend-common/src/reading/GitlabUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.ts @@ -14,6 +14,15 @@ * limitations under the License. */ +import { + UrlReaderService, + UrlReaderReadTreeOptions, + UrlReaderReadTreeResponse, + UrlReaderReadUrlOptions, + UrlReaderReadUrlResponse, + UrlReaderSearchOptions, + UrlReaderSearchResponse, +} from '@backstage/backend-plugin-api'; import { getGitLabFileFetchUrl, getGitLabIntegrationRelativePath, @@ -26,17 +35,7 @@ import parseGitUrl from 'git-url-parse'; import { Minimatch } from 'minimatch'; import { Readable } from 'stream'; import { NotFoundError, NotModifiedError } from '@backstage/errors'; -import { - ReadTreeResponseFactory, - ReaderFactory, - ReadTreeOptions, - ReadTreeResponse, - SearchOptions, - SearchResponse, - UrlReader, - ReadUrlResponse, - ReadUrlOptions, -} from './types'; +import { ReadTreeResponseFactory, ReaderFactory } from './types'; import { trimEnd, trimStart } from 'lodash'; import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; import { parseLastModified } from './util'; @@ -46,7 +45,7 @@ import { parseLastModified } from './util'; * * @public */ -export class GitlabUrlReader implements UrlReader { +export class GitlabUrlReader implements UrlReaderService { static factory: ReaderFactory = ({ config, treeResponseFactory }) => { const integrations = ScmIntegrations.fromConfig(config); return integrations.gitlab.list().map(integration => { @@ -70,8 +69,8 @@ export class GitlabUrlReader implements UrlReader { async readUrl( url: string, - options?: ReadUrlOptions, - ): Promise { + options?: UrlReaderReadUrlOptions, + ): Promise { const { etag, lastModifiedAfter, signal } = options ?? {}; const builtUrl = await this.getGitlabFetchUrl(url); @@ -119,8 +118,8 @@ export class GitlabUrlReader implements UrlReader { async readTree( url: string, - options?: ReadTreeOptions, - ): Promise { + options?: UrlReaderReadTreeOptions, + ): Promise { const { etag, signal } = options ?? {}; const { ref, full_name, filepath } = parseGitUrl(url); @@ -236,7 +235,10 @@ export class GitlabUrlReader implements UrlReader { }); } - async search(url: string, options?: SearchOptions): Promise { + async search( + url: string, + options?: UrlReaderSearchOptions, + ): Promise { const { filepath } = parseGitUrl(url); const staticPart = this.getStaticPart(filepath); const matcher = new Minimatch(filepath); diff --git a/packages/backend-common/src/reading/GoogleGcsUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.test.ts similarity index 95% rename from packages/backend-common/src/reading/GoogleGcsUrlReader.test.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.test.ts index bc31818d23..318b134aa4 100644 --- a/packages/backend-common/src/reading/GoogleGcsUrlReader.test.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.test.ts @@ -19,7 +19,7 @@ import { JsonObject } from '@backstage/types'; import { DefaultReadTreeResponseFactory } from './tree'; import { GoogleGcsUrlReader } from './GoogleGcsUrlReader'; import { UrlReaderPredicateTuple } from './types'; -import packageinfo from '../../package.json'; +import packageinfo from '@backstage/backend-defaults/package.json'; import { mockServices } from '@backstage/backend-test-utils'; const bucketGetFilesMock = jest.fn(); @@ -80,7 +80,7 @@ describe('GcsUrlReader', () => { }); it('check if userAgent has been called with this key value', async () => { const getStorage: any = { - userAgent: `backstage/backend-common.GoogleGcsUrlReader/${packageinfo.version}`, + userAgent: `backstage/backend-defaults.GoogleGcsUrlReader/${packageinfo.version}`, }; jest.mock('@google-cloud/storage', () => { return { @@ -89,7 +89,7 @@ describe('GcsUrlReader', () => { }); const getUserAgent = getStorage.userAgent.toString(); expect(getUserAgent).toBe( - `backstage/backend-common.GoogleGcsUrlReader/${packageinfo.version}`, + `backstage/backend-defaults.GoogleGcsUrlReader/${packageinfo.version}`, ); }); diff --git a/packages/backend-common/src/reading/GoogleGcsUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.ts similarity index 84% rename from packages/backend-common/src/reading/GoogleGcsUrlReader.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.ts index 9cf6bbcd61..124461ff80 100644 --- a/packages/backend-common/src/reading/GoogleGcsUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.ts @@ -14,15 +14,15 @@ * limitations under the License. */ -import { Storage } from '@google-cloud/storage'; import { - ReaderFactory, - ReadTreeResponse, - ReadUrlOptions, - ReadUrlResponse, - SearchResponse, - UrlReader, -} from './types'; + UrlReaderService, + UrlReaderReadTreeResponse, + UrlReaderReadUrlOptions, + UrlReaderReadUrlResponse, + UrlReaderSearchResponse, +} from '@backstage/backend-plugin-api'; +import { Storage } from '@google-cloud/storage'; +import { ReaderFactory } from './types'; import getRawBody from 'raw-body'; import { GoogleGcsIntegrationConfig, @@ -30,7 +30,7 @@ import { } from '@backstage/integration'; import { Readable } from 'stream'; import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; -import packageinfo from '../../package.json'; +import packageinfo from '@backstage/backend-defaults/package.json'; const GOOGLE_GCS_HOST = 'storage.cloud.google.com'; @@ -56,7 +56,7 @@ const parseURL = ( * * @public */ -export class GoogleGcsUrlReader implements UrlReader { +export class GoogleGcsUrlReader implements UrlReaderService { static factory: ReaderFactory = ({ config, logger }) => { if (!config.has('integrations.googleGcs')) { return []; @@ -70,7 +70,7 @@ export class GoogleGcsUrlReader implements UrlReader { 'googleGcs credentials not found in config. Using default credentials provider.', ); storage = new Storage({ - userAgent: `backstage/backend-common.GoogleGcsUrlReader/${packageinfo.version}`, + userAgent: `backstage/backend-defaults.GoogleGcsUrlReader/${packageinfo.version}`, }); } else { storage = new Storage({ @@ -78,7 +78,7 @@ export class GoogleGcsUrlReader implements UrlReader { client_email: gcsConfig.clientEmail || undefined, private_key: gcsConfig.privateKey || undefined, }, - userAgent: `backstage/backend-common.GoogleGcsUrlReader/${packageinfo.version}`, + userAgent: `backstage/backend-defaults.GoogleGcsUrlReader/${packageinfo.version}`, }); } const reader = new GoogleGcsUrlReader(gcsConfig, storage); @@ -106,18 +106,18 @@ export class GoogleGcsUrlReader implements UrlReader { async readUrl( url: string, - _options?: ReadUrlOptions, - ): Promise { + _options?: UrlReaderReadUrlOptions, + ): Promise { // TODO etag is not implemented yet. const stream = this.readStreamFromUrl(url); return ReadUrlResponseFactory.fromReadable(stream); } - async readTree(): Promise { + async readTree(): Promise { throw new Error('GcsUrlReader does not implement readTree'); } - async search(url: string): Promise { + async search(url: string): Promise { const { bucket, key: pattern } = parseURL(url); if (!pattern.endsWith('*') || pattern.indexOf('*') !== pattern.length - 1) { diff --git a/packages/backend-common/src/reading/HarnessUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/HarnessUrlReader.test.ts similarity index 100% rename from packages/backend-common/src/reading/HarnessUrlReader.test.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/HarnessUrlReader.test.ts diff --git a/packages/backend-common/src/reading/HarnessUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/HarnessUrlReader.ts similarity index 90% rename from packages/backend-common/src/reading/HarnessUrlReader.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/HarnessUrlReader.ts index 76ad882d80..23b5284b43 100644 --- a/packages/backend-common/src/reading/HarnessUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/HarnessUrlReader.ts @@ -13,6 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +import { + UrlReaderService, + UrlReaderReadTreeResponse, + UrlReaderReadUrlOptions, + UrlReaderReadUrlResponse, + UrlReaderSearchResponse, + UrlReaderReadTreeOptions, +} from '@backstage/backend-plugin-api'; import { getHarnessRequestOptions, getHarnessFileContentsUrl, @@ -22,16 +31,7 @@ import { getHarnessArchiveUrl, parseHarnessUrl, } from '@backstage/integration'; -import { - ReaderFactory, - ReadTreeOptions, - ReadTreeResponse, - SearchResponse, - ReadTreeResponseFactory, - ReadUrlOptions, - ReadUrlResponse, - UrlReader, -} from './types'; +import { ReadTreeResponseFactory, ReaderFactory } from './types'; import fetch, { Response } from 'node-fetch'; import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; import { @@ -47,7 +47,7 @@ import { Readable } from 'stream'; * * @public */ -export class HarnessUrlReader implements UrlReader { +export class HarnessUrlReader implements UrlReaderService { static factory: ReaderFactory = ({ config, treeResponseFactory }) => { return ScmIntegrations.fromConfig(config) .harness.list() @@ -75,8 +75,8 @@ export class HarnessUrlReader implements UrlReader { async readUrl( url: string, - options?: ReadUrlOptions, - ): Promise { + options?: UrlReaderReadUrlOptions, + ): Promise { let response: Response; const blobUrl = getHarnessFileContentsUrl(this.integration.config, url); @@ -123,8 +123,8 @@ export class HarnessUrlReader implements UrlReader { async readTree( url: string, - options?: ReadTreeOptions, - ): Promise { + options?: UrlReaderReadTreeOptions, + ): Promise { const lastCommitHash = await this.getLastCommitHash(url); if (options?.etag && options.etag === lastCommitHash) { @@ -153,7 +153,8 @@ export class HarnessUrlReader implements UrlReader { filter: options?.filter, }); } - search(): Promise { + + search(): Promise { throw new Error('HarnessUrlReader search not implemented.'); } diff --git a/packages/backend-common/src/reading/ReadUrlResponseFactory.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/ReadUrlResponseFactory.test.ts similarity index 100% rename from packages/backend-common/src/reading/ReadUrlResponseFactory.test.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/ReadUrlResponseFactory.test.ts diff --git a/packages/backend-common/src/reading/ReadUrlResponseFactory.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/ReadUrlResponseFactory.ts similarity index 91% rename from packages/backend-common/src/reading/ReadUrlResponseFactory.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/ReadUrlResponseFactory.ts index 5eb4b2f5bc..805008c34e 100644 --- a/packages/backend-common/src/reading/ReadUrlResponseFactory.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/ReadUrlResponseFactory.ts @@ -15,12 +15,10 @@ */ import { ConflictError } from '@backstage/errors'; +import { UrlReaderReadUrlResponse } from '@backstage/backend-plugin-api'; import getRawBody from 'raw-body'; import { Readable } from 'stream'; -import { - ReadUrlResponse, - ReadUrlResponseFactoryFromStreamOptions, -} from './types'; +import { ReadUrlResponseFactoryFromStreamOptions } from './types'; /** * Utility class for UrlReader implementations to create valid ReadUrlResponse @@ -35,7 +33,7 @@ export class ReadUrlResponseFactory { static async fromReadable( stream: Readable, options?: ReadUrlResponseFactoryFromStreamOptions, - ): Promise { + ): Promise { // Reference to eventual buffer enables callers to call buffer() multiple // times without consequence. let buffer: Promise; @@ -71,7 +69,7 @@ export class ReadUrlResponseFactory { static async fromNodeJSReadable( oldStyleStream: NodeJS.ReadableStream, options?: ReadUrlResponseFactoryFromStreamOptions, - ): Promise { + ): Promise { const readable = Readable.from(oldStyleStream); return ReadUrlResponseFactory.fromReadable(readable, options); } diff --git a/packages/backend-common/src/reading/UrlReaderPredicateMux.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/UrlReaderPredicateMux.test.ts similarity index 100% rename from packages/backend-common/src/reading/UrlReaderPredicateMux.test.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/UrlReaderPredicateMux.test.ts diff --git a/packages/backend-common/src/reading/UrlReaderPredicateMux.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/UrlReaderPredicateMux.ts similarity index 74% rename from packages/backend-common/src/reading/UrlReaderPredicateMux.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/UrlReaderPredicateMux.ts index a7c2e5f983..b6db60af0a 100644 --- a/packages/backend-common/src/reading/UrlReaderPredicateMux.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/UrlReaderPredicateMux.ts @@ -14,17 +14,17 @@ * limitations under the License. */ -import { NotAllowedError } from '@backstage/errors'; import { - ReadTreeOptions, - ReadTreeResponse, - ReadUrlOptions, - ReadUrlResponse, - SearchOptions, - SearchResponse, - UrlReader, - UrlReaderPredicateTuple, -} from './types'; + UrlReaderReadTreeOptions, + UrlReaderReadTreeResponse, + UrlReaderReadUrlOptions, + UrlReaderReadUrlResponse, + UrlReaderSearchOptions, + UrlReaderSearchResponse, + UrlReaderService, +} from '@backstage/backend-plugin-api'; +import { NotAllowedError } from '@backstage/errors'; +import { UrlReaderPredicateTuple } from './types'; function notAllowedMessage(url: string) { return ( @@ -35,10 +35,10 @@ function notAllowedMessage(url: string) { } /** - * A UrlReader implementation that selects from a set of UrlReaders + * A UrlReaderService implementation that selects from a set of readers * based on a predicate tied to each reader. */ -export class UrlReaderPredicateMux implements UrlReader { +export class UrlReaderPredicateMux implements UrlReaderService { private readonly readers: UrlReaderPredicateTuple[] = []; register(tuple: UrlReaderPredicateTuple): void { @@ -47,8 +47,8 @@ export class UrlReaderPredicateMux implements UrlReader { async readUrl( url: string, - options?: ReadUrlOptions, - ): Promise { + options?: UrlReaderReadUrlOptions, + ): Promise { const parsed = new URL(url); for (const { predicate, reader } of this.readers) { @@ -62,8 +62,8 @@ export class UrlReaderPredicateMux implements UrlReader { async readTree( url: string, - options?: ReadTreeOptions, - ): Promise { + options?: UrlReaderReadTreeOptions, + ): Promise { const parsed = new URL(url); for (const { predicate, reader } of this.readers) { @@ -75,7 +75,10 @@ export class UrlReaderPredicateMux implements UrlReader { throw new NotAllowedError(notAllowedMessage(url)); } - async search(url: string, options?: SearchOptions): Promise { + async search( + url: string, + options?: UrlReaderSearchOptions, + ): Promise { const parsed = new URL(url); for (const { predicate, reader } of this.readers) { diff --git a/packages/backend-common/src/reading/UrlReaders.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/UrlReaders.ts similarity index 94% rename from packages/backend-common/src/reading/UrlReaders.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/UrlReaders.ts index 7aaaf120b4..cb496dd702 100644 --- a/packages/backend-common/src/reading/UrlReaders.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/UrlReaders.ts @@ -14,9 +14,9 @@ * limitations under the License. */ -import { LoggerService } from '@backstage/backend-plugin-api'; +import { LoggerService, UrlReaderService } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; -import { ReaderFactory, UrlReader } from './types'; +import { ReaderFactory } from './types'; import { UrlReaderPredicateMux } from './UrlReaderPredicateMux'; import { AzureUrlReader } from './AzureUrlReader'; import { BitbucketCloudUrlReader } from './BitbucketCloudUrlReader'; @@ -56,7 +56,7 @@ export class UrlReaders { /** * Creates a custom {@link @backstage/backend-plugin-api#UrlReaderService} wrapper for your own set of factories. */ - static create(options: UrlReadersOptions): UrlReader { + static create(options: UrlReadersOptions): UrlReaderService { const { logger, config, factories } = options; const mux = new UrlReaderPredicateMux(); const treeResponseFactory = DefaultReadTreeResponseFactory.create({ diff --git a/packages/backend-common/src/reading/__fixtures__/awsCodeCommit/awsCodeCommit-mock-object.yaml b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/awsCodeCommit/awsCodeCommit-mock-object.yaml similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/awsCodeCommit/awsCodeCommit-mock-object.yaml rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/awsCodeCommit/awsCodeCommit-mock-object.yaml diff --git a/packages/backend-common/src/reading/__fixtures__/awsCodeCommit/subFolder/awsCodeCommit-mock-object2.yaml b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/awsCodeCommit/subFolder/awsCodeCommit-mock-object2.yaml similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/awsCodeCommit/subFolder/awsCodeCommit-mock-object2.yaml rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/awsCodeCommit/subFolder/awsCodeCommit-mock-object2.yaml diff --git a/packages/backend-common/src/reading/__fixtures__/awsS3/awsS3-mock-object.yaml b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/awsS3/awsS3-mock-object.yaml similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/awsS3/awsS3-mock-object.yaml rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/awsS3/awsS3-mock-object.yaml diff --git a/packages/backend-common/src/reading/__fixtures__/awsS3/awsS3-mock-object2.yaml b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/awsS3/awsS3-mock-object2.yaml similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/awsS3/awsS3-mock-object2.yaml rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/awsS3/awsS3-mock-object2.yaml diff --git a/packages/backend-common/src/reading/__fixtures__/awsS3/awsS3-mock-object3.yaml b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/awsS3/awsS3-mock-object3.yaml similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/awsS3/awsS3-mock-object3.yaml rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/awsS3/awsS3-mock-object3.yaml diff --git a/packages/backend-common/src/reading/__fixtures__/backstage-mock-etag123.tar.gz b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/backstage-mock-etag123.tar.gz similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/backstage-mock-etag123.tar.gz rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/backstage-mock-etag123.tar.gz diff --git a/packages/backend-common/src/reading/__fixtures__/bitbucket-repo-with-commit-hash.tar.gz b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/bitbucket-repo-with-commit-hash.tar.gz similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/bitbucket-repo-with-commit-hash.tar.gz rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/bitbucket-repo-with-commit-hash.tar.gz diff --git a/packages/backend-common/src/reading/__fixtures__/bitbucket-server-repo.tar.gz b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/bitbucket-server-repo.tar.gz similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/bitbucket-server-repo.tar.gz rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/bitbucket-server-repo.tar.gz diff --git a/packages/backend-common/src/reading/__fixtures__/gerrit/branch-info-response.txt b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/gerrit/branch-info-response.txt similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/gerrit/branch-info-response.txt rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/gerrit/branch-info-response.txt diff --git a/packages/backend-common/src/reading/__fixtures__/gerrit/gerrit-master-docs.tar.gz b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/gerrit/gerrit-master-docs.tar.gz similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/gerrit/gerrit-master-docs.tar.gz rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/gerrit/gerrit-master-docs.tar.gz diff --git a/packages/backend-common/src/reading/__fixtures__/gerrit/gerrit-master.tar.gz b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/gerrit/gerrit-master.tar.gz similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/gerrit/gerrit-master.tar.gz rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/gerrit/gerrit-master.tar.gz diff --git a/packages/backend-common/src/reading/__fixtures__/gitlab-archive.tar.gz b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/gitlab-archive.tar.gz similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/gitlab-archive.tar.gz rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/gitlab-archive.tar.gz diff --git a/packages/backend-common/src/reading/__fixtures__/gitlab-archive.zip b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/gitlab-archive.zip similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/gitlab-archive.zip rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/gitlab-archive.zip diff --git a/packages/backend-common/src/reading/__fixtures__/gitlab-subpath-archive.tar.gz b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/gitlab-subpath-archive.tar.gz similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/gitlab-subpath-archive.tar.gz rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/gitlab-subpath-archive.tar.gz diff --git a/packages/backend-common/src/reading/__fixtures__/mallory.zip b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/mallory.zip similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/mallory.zip rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/mallory.zip diff --git a/packages/backend-common/src/reading/__fixtures__/mock-corrupted.zip b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/mock-corrupted.zip similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/mock-corrupted.zip rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/mock-corrupted.zip diff --git a/packages/backend-common/src/reading/__fixtures__/mock-main.tar.gz b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/mock-main.tar.gz similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/mock-main.tar.gz rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/mock-main.tar.gz diff --git a/packages/backend-common/src/reading/__fixtures__/mock-main.zip b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/mock-main.zip similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/mock-main.zip rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/mock-main.zip diff --git a/packages/backend-common/src/reading/__fixtures__/mock-with-extra-root-dir.zip b/packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/mock-with-extra-root-dir.zip similarity index 100% rename from packages/backend-common/src/reading/__fixtures__/mock-with-extra-root-dir.zip rename to packages/backend-defaults/src/entrypoints/urlReader/lib/__fixtures__/mock-with-extra-root-dir.zip diff --git a/packages/backend-common/src/reading/git.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/git.ts similarity index 100% rename from packages/backend-common/src/reading/git.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/git.ts diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/index.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/index.ts new file mode 100644 index 0000000000..678c6ef64b --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/index.ts @@ -0,0 +1,38 @@ +/* + * 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 { AzureUrlReader } from './AzureUrlReader'; +export { BitbucketCloudUrlReader } from './BitbucketCloudUrlReader'; +export { BitbucketUrlReader } from './BitbucketUrlReader'; +export { BitbucketServerUrlReader } from './BitbucketServerUrlReader'; +export { GerritUrlReader } from './GerritUrlReader'; +export { GithubUrlReader } from './GithubUrlReader'; +export { GitlabUrlReader } from './GitlabUrlReader'; +export { GiteaUrlReader } from './GiteaUrlReader'; +export { HarnessUrlReader } from './HarnessUrlReader'; +export { AwsS3UrlReader } from './AwsS3UrlReader'; +export { FetchUrlReader } from './FetchUrlReader'; +export { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; +export type { + FromReadableArrayOptions, + ReaderFactory, + ReadTreeResponseFactory, + ReadTreeResponseFactoryOptions, + ReadUrlResponseFactoryFromStreamOptions, + UrlReaderPredicateTuple, +} from './types'; +export { UrlReaders } from './UrlReaders'; +export type { UrlReadersOptions } from './UrlReaders'; diff --git a/packages/backend-common/src/reading/tree/ReadTreeResponseFactory.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.ts similarity index 90% rename from packages/backend-common/src/reading/tree/ReadTreeResponseFactory.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.ts index 90c58c0efa..e61ce3242e 100644 --- a/packages/backend-common/src/reading/tree/ReadTreeResponseFactory.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.ts @@ -17,7 +17,6 @@ import os from 'os'; import { Config } from '@backstage/config'; import { - ReadTreeResponse, ReadTreeResponseFactoryOptions, ReadTreeResponseFactory, FromReadableArrayOptions, @@ -25,6 +24,7 @@ import { import { TarArchiveResponse } from './TarArchiveResponse'; import { ZipArchiveResponse } from './ZipArchiveResponse'; import { ReadableArrayResponse } from './ReadableArrayResponse'; +import { UrlReaderReadTreeResponse } from '@backstage/backend-plugin-api'; export class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory { static create(options: { config: Config }): DefaultReadTreeResponseFactory { @@ -40,7 +40,7 @@ export class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory { options: ReadTreeResponseFactoryOptions & { stripFirstDirectory?: boolean; }, - ): Promise { + ): Promise { return new TarArchiveResponse( options.stream, options.subpath ?? '', @@ -53,7 +53,7 @@ export class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory { async fromZipArchive( options: ReadTreeResponseFactoryOptions, - ): Promise { + ): Promise { return new ZipArchiveResponse( options.stream, options.subpath ?? '', @@ -65,7 +65,7 @@ export class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory { async fromReadableArray( options: FromReadableArrayOptions, - ): Promise { + ): Promise { return new ReadableArrayResponse(options, this.workDir, ''); } } diff --git a/packages/backend-common/src/reading/tree/ReadableArrayResponse.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ReadableArrayResponse.test.ts similarity index 100% rename from packages/backend-common/src/reading/tree/ReadableArrayResponse.test.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ReadableArrayResponse.test.ts diff --git a/packages/backend-common/src/reading/tree/ReadableArrayResponse.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ReadableArrayResponse.ts similarity index 84% rename from packages/backend-common/src/reading/tree/ReadableArrayResponse.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ReadableArrayResponse.ts index 3c8bfd1fbc..4e1b24f47f 100644 --- a/packages/backend-common/src/reading/tree/ReadableArrayResponse.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ReadableArrayResponse.ts @@ -14,27 +14,26 @@ * limitations under the License. */ +import { + UrlReaderReadTreeResponse, + UrlReaderReadTreeResponseDirOptions, + UrlReaderReadTreeResponseFile, +} from '@backstage/backend-plugin-api'; import concatStream from 'concat-stream'; import platformPath, { dirname } from 'path'; - import getRawBody from 'raw-body'; import fs from 'fs-extra'; import { promisify } from 'util'; import tar from 'tar'; import { pipeline as pipelineCb, Readable } from 'stream'; -import { - ReadTreeResponse, - ReadTreeResponseFile, - ReadTreeResponseDirOptions, - FromReadableArrayOptions, -} from '../types'; +import { FromReadableArrayOptions } from '../types'; const pipeline = promisify(pipelineCb); /** * Wraps a array of Readable objects into a tree response reader. */ -export class ReadableArrayResponse implements ReadTreeResponse { +export class ReadableArrayResponse implements UrlReaderReadTreeResponse { private read = false; constructor( @@ -53,10 +52,10 @@ export class ReadableArrayResponse implements ReadTreeResponse { this.read = true; } - async files(): Promise { + async files(): Promise { this.onlyOnce(); - const files = Array(); + const files = Array(); for (let i = 0; i < this.stream.length; i++) { if (!this.stream[i].path.endsWith('/')) { @@ -87,7 +86,7 @@ export class ReadableArrayResponse implements ReadTreeResponse { } } - async dir(options?: ReadTreeResponseDirOptions): Promise { + async dir(options?: UrlReaderReadTreeResponseDirOptions): Promise { this.onlyOnce(); const dir = diff --git a/packages/backend-common/src/reading/tree/TarArchiveResponse.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/TarArchiveResponse.test.ts similarity index 100% rename from packages/backend-common/src/reading/tree/TarArchiveResponse.test.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/tree/TarArchiveResponse.test.ts diff --git a/packages/backend-common/src/reading/tree/TarArchiveResponse.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/TarArchiveResponse.ts similarity index 93% rename from packages/backend-common/src/reading/tree/TarArchiveResponse.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/tree/TarArchiveResponse.ts index 294ec22609..59b750eb1e 100644 --- a/packages/backend-common/src/reading/tree/TarArchiveResponse.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/TarArchiveResponse.ts @@ -14,17 +14,17 @@ * limitations under the License. */ +import { + UrlReaderReadTreeResponse, + UrlReaderReadTreeResponseDirOptions, + UrlReaderReadTreeResponseFile, +} from '@backstage/backend-plugin-api'; import concatStream from 'concat-stream'; import fs from 'fs-extra'; import platformPath from 'path'; import { pipeline as pipelineCb, Readable } from 'stream'; import tar, { Parse, ParseStream, ReadEntry } from 'tar'; import { promisify } from 'util'; -import { - ReadTreeResponse, - ReadTreeResponseDirOptions, - ReadTreeResponseFile, -} from '../types'; import { stripFirstDirectoryFromPath } from './util'; // Tar types for `Parse` is not a proper constructor, but it should be @@ -35,7 +35,7 @@ const pipeline = promisify(pipelineCb); /** * Wraps a tar archive stream into a tree response reader. */ -export class TarArchiveResponse implements ReadTreeResponse { +export class TarArchiveResponse implements UrlReaderReadTreeResponse { private read = false; constructor( @@ -68,10 +68,10 @@ export class TarArchiveResponse implements ReadTreeResponse { this.read = true; } - async files(): Promise { + async files(): Promise { this.onlyOnce(); - const files = Array(); + const files = Array(); const parser = new TarParseStream(); parser.on('entry', (entry: ReadEntry & Readable) => { @@ -142,7 +142,7 @@ export class TarArchiveResponse implements ReadTreeResponse { } } - async dir(options?: ReadTreeResponseDirOptions): Promise { + async dir(options?: UrlReaderReadTreeResponseDirOptions): Promise { this.onlyOnce(); const dir = diff --git a/packages/backend-common/src/reading/tree/ZipArchiveResponse.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ZipArchiveResponse.test.ts similarity index 100% rename from packages/backend-common/src/reading/tree/ZipArchiveResponse.test.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ZipArchiveResponse.test.ts diff --git a/packages/backend-common/src/reading/tree/ZipArchiveResponse.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ZipArchiveResponse.ts similarity index 93% rename from packages/backend-common/src/reading/tree/ZipArchiveResponse.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ZipArchiveResponse.ts index 412819c5b9..3d3b615ee7 100644 --- a/packages/backend-common/src/reading/tree/ZipArchiveResponse.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ZipArchiveResponse.ts @@ -14,23 +14,23 @@ * limitations under the License. */ +import { + UrlReaderReadTreeResponse, + UrlReaderReadTreeResponseDirOptions, + UrlReaderReadTreeResponseFile, +} from '@backstage/backend-plugin-api'; import archiver from 'archiver'; import yauzl, { Entry } from 'yauzl'; import fs from 'fs-extra'; import platformPath from 'path'; import { Readable } from 'stream'; -import { - ReadTreeResponse, - ReadTreeResponseDirOptions, - ReadTreeResponseFile, -} from '../types'; import { streamToBuffer } from './util'; import { resolveSafeChildPath } from '@backstage/backend-plugin-api'; /** * Wraps a zip archive stream into a tree response reader. */ -export class ZipArchiveResponse implements ReadTreeResponse { +export class ZipArchiveResponse implements UrlReaderReadTreeResponse { private read = false; constructor( @@ -141,9 +141,9 @@ export class ZipArchiveResponse implements ReadTreeResponse { }); } - async files(): Promise { + async files(): Promise { this.onlyOnce(); - const files = Array(); + const files = Array(); const temporary = await this.streamToTemporaryFile(this.stream); await this.forEveryZipEntry(temporary.fileName, async (entry, content) => { @@ -184,7 +184,7 @@ export class ZipArchiveResponse implements ReadTreeResponse { return archive; } - async dir(options?: ReadTreeResponseDirOptions): Promise { + async dir(options?: UrlReaderReadTreeResponseDirOptions): Promise { this.onlyOnce(); const dir = options?.targetDir ?? diff --git a/packages/backend-common/src/reading/tree/index.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/index.ts similarity index 100% rename from packages/backend-common/src/reading/tree/index.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/tree/index.ts diff --git a/packages/backend-common/src/reading/tree/util.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/tree/util.ts similarity index 100% rename from packages/backend-common/src/reading/tree/util.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/tree/util.ts diff --git a/packages/backend-common/src/reading/types.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/types.ts similarity index 88% rename from packages/backend-common/src/reading/types.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/types.ts index 90a3c6287e..254fe1dcec 100644 --- a/packages/backend-common/src/reading/types.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/types.ts @@ -18,23 +18,10 @@ import { Readable } from 'stream'; import { Config } from '@backstage/config'; import { UrlReaderService, - ReadTreeResponse, + UrlReaderReadTreeResponse, LoggerService, } from '@backstage/backend-plugin-api'; -export type { - UrlReaderService as UrlReader, - ReadTreeOptions, - ReadTreeResponse, - ReadTreeResponseDirOptions, - ReadTreeResponseFile, - ReadUrlResponse, - ReadUrlOptions, - SearchOptions, - SearchResponse, - SearchResponseFile, -} from '@backstage/backend-plugin-api'; - /** * A predicate that decides whether a specific {@link @backstage/backend-plugin-api#UrlReaderService} can handle a * given URL. @@ -123,11 +110,11 @@ export interface ReadTreeResponseFactory { */ stripFirstDirectory?: boolean; }, - ): Promise; + ): Promise; fromZipArchive( options: ReadTreeResponseFactoryOptions, - ): Promise; + ): Promise; fromReadableArray( options: FromReadableArrayOptions, - ): Promise; + ): Promise; } diff --git a/packages/backend-common/src/reading/util.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/util.ts similarity index 100% rename from packages/backend-common/src/reading/util.ts rename to packages/backend-defaults/src/entrypoints/urlReader/lib/util.ts diff --git a/packages/backend-defaults/src/entrypoints/urlReader/urlReaderServiceFactory.ts b/packages/backend-defaults/src/entrypoints/urlReader/urlReaderServiceFactory.ts index 7f404a24b1..dae8d692cb 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/urlReaderServiceFactory.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/urlReaderServiceFactory.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { UrlReaders } from '@backstage/backend-common'; +import { UrlReaders } from './lib/UrlReaders'; import { coreServices, createServiceFactory, diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index 70ab3d8eed..5ba4e758ca 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -466,54 +466,23 @@ export function readSchedulerServiceTaskScheduleDefinitionFromConfig( config: Config, ): SchedulerServiceTaskScheduleDefinition; -// @public -export type ReadTreeOptions = { - filter?( - path: string, - info?: { - size: number; - }, - ): boolean; - etag?: string; - signal?: AbortSignal; - token?: string; -}; +// @public @deprecated (undocumented) +export type ReadTreeOptions = UrlReaderReadTreeOptions; -// @public -export type ReadTreeResponse = { - files(): Promise; - archive(): Promise; - dir(options?: ReadTreeResponseDirOptions): Promise; - etag: string; -}; +// @public @deprecated (undocumented) +export type ReadTreeResponse = UrlReaderReadTreeResponse; -// @public -export type ReadTreeResponseDirOptions = { - targetDir?: string; -}; +// @public @deprecated (undocumented) +export type ReadTreeResponseDirOptions = UrlReaderReadTreeResponseDirOptions; -// @public -export type ReadTreeResponseFile = { - path: string; - content(): Promise; - lastModifiedAt?: Date; -}; +// @public @deprecated (undocumented) +export type ReadTreeResponseFile = UrlReaderReadTreeResponseFile; -// @public -export type ReadUrlOptions = { - etag?: string; - lastModifiedAfter?: Date; - signal?: AbortSignal; - token?: string; -}; +// @public @deprecated (undocumented) +export type ReadUrlOptions = UrlReaderReadUrlOptions; -// @public -export type ReadUrlResponse = { - buffer(): Promise; - stream?(): Readable; - etag?: string; - lastModifiedAt?: Date; -}; +// @public @deprecated (undocumented) +export type ReadUrlResponse = UrlReaderReadUrlResponse; // @public export function resolvePackagePath(name: string, ...paths: string[]): string; @@ -617,25 +586,14 @@ export interface SchedulerServiceTaskScheduleDefinitionConfig { timeout: string | HumanDuration; } -// @public -export type SearchOptions = { - etag?: string; - signal?: AbortSignal; - token?: string; -}; +// @public @deprecated (undocumented) +export type SearchOptions = UrlReaderSearchOptions; -// @public -export type SearchResponse = { - files: SearchResponseFile[]; - etag: string; -}; +// @public @deprecated (undocumented) +export type SearchResponse = UrlReaderSearchResponse; -// @public -export type SearchResponseFile = { - url: string; - content(): Promise; - lastModifiedAt?: Date; -}; +// @public @deprecated (undocumented) +export type SearchResponseFile = UrlReaderSearchResponseFile; // @public (undocumented) export interface ServiceFactory< @@ -680,11 +638,89 @@ export interface TokenManagerService { }>; } +// @public +export type UrlReaderReadTreeOptions = { + filter?( + path: string, + info?: { + size: number; + }, + ): boolean; + etag?: string; + signal?: AbortSignal; + token?: string; +}; + +// @public +export type UrlReaderReadTreeResponse = { + files(): Promise; + archive(): Promise; + dir(options?: UrlReaderReadTreeResponseDirOptions): Promise; + etag: string; +}; + +// @public +export type UrlReaderReadTreeResponseDirOptions = { + targetDir?: string; +}; + +// @public +export type UrlReaderReadTreeResponseFile = { + path: string; + content(): Promise; + lastModifiedAt?: Date; +}; + +// @public +export type UrlReaderReadUrlOptions = { + etag?: string; + lastModifiedAfter?: Date; + signal?: AbortSignal; + token?: string; +}; + +// @public +export type UrlReaderReadUrlResponse = { + buffer(): Promise; + stream?(): Readable; + etag?: string; + lastModifiedAt?: Date; +}; + +// @public +export type UrlReaderSearchOptions = { + etag?: string; + signal?: AbortSignal; + token?: string; +}; + +// @public +export type UrlReaderSearchResponse = { + files: UrlReaderSearchResponseFile[]; + etag: string; +}; + +// @public +export type UrlReaderSearchResponseFile = { + url: string; + content(): Promise; + lastModifiedAt?: Date; +}; + // @public export interface UrlReaderService { - readTree(url: string, options?: ReadTreeOptions): Promise; - readUrl(url: string, options?: ReadUrlOptions): Promise; - search(url: string, options?: SearchOptions): Promise; + readTree( + url: string, + options?: UrlReaderReadTreeOptions, + ): Promise; + readUrl( + url: string, + options?: UrlReaderReadUrlOptions, + ): Promise; + search( + url: string, + options?: UrlReaderSearchOptions, + ): Promise; } // @public diff --git a/packages/backend-plugin-api/src/services/definitions/UrlReaderService.ts b/packages/backend-plugin-api/src/services/definitions/UrlReaderService.ts index 8cb40ff202..085b0b6844 100644 --- a/packages/backend-plugin-api/src/services/definitions/UrlReaderService.ts +++ b/packages/backend-plugin-api/src/services/definitions/UrlReaderService.ts @@ -27,17 +27,26 @@ export interface UrlReaderService { /** * Reads a single file and return its content. */ - readUrl(url: string, options?: ReadUrlOptions): Promise; + readUrl( + url: string, + options?: UrlReaderReadUrlOptions, + ): Promise; /** * Reads a full or partial file tree. */ - readTree(url: string, options?: ReadTreeOptions): Promise; + readTree( + url: string, + options?: UrlReaderReadTreeOptions, + ): Promise; /** * Searches for a file in a tree using a glob pattern. */ - search(url: string, options?: SearchOptions): Promise; + search( + url: string, + options?: UrlReaderSearchOptions, + ): Promise; } /** @@ -45,7 +54,7 @@ export interface UrlReaderService { * * @public */ -export type ReadUrlOptions = { +export type UrlReaderReadUrlOptions = { /** * An ETag which can be provided to check whether a * {@link UrlReaderService.readUrl} response has changed from a previous execution. @@ -113,7 +122,7 @@ export type ReadUrlOptions = { * * @public */ -export type ReadUrlResponse = { +export type UrlReaderReadUrlResponse = { /** * Returns the data that was read from the remote URL. */ @@ -148,7 +157,7 @@ export type ReadUrlResponse = { * * @public */ -export type ReadTreeOptions = { +export type UrlReaderReadTreeOptions = { /** * A filter that can be used to select which files should be included. * @@ -208,11 +217,11 @@ export type ReadTreeOptions = { }; /** - * Options that control {@link ReadTreeResponse.dir} execution. + * Options that control {@link UrlReaderReadTreeResponse.dir} execution. * * @public */ -export type ReadTreeResponseDirOptions = { +export type UrlReaderReadTreeResponseDirOptions = { /** * The directory to write files to. * @@ -228,12 +237,12 @@ export type ReadTreeResponseDirOptions = { * * @public */ -export type ReadTreeResponse = { +export type UrlReaderReadTreeResponse = { /** * Returns an array of all the files inside the tree, and corresponding * functions to read their content. */ - files(): Promise; + files(): Promise; /** * Returns the tree contents as a binary archive, using a stream. @@ -246,7 +255,7 @@ export type ReadTreeResponse = { * * **NOTE**: It is the responsibility of the caller to remove the directory after use. */ - dir(options?: ReadTreeResponseDirOptions): Promise; + dir(options?: UrlReaderReadTreeResponseDirOptions): Promise; /** * Etag returned by content provider. @@ -263,7 +272,7 @@ export type ReadTreeResponse = { * * @public */ -export type ReadTreeResponseFile = { +export type UrlReaderReadTreeResponseFile = { /** * The filepath of the data. */ @@ -285,7 +294,7 @@ export type ReadTreeResponseFile = { * * @public */ -export type SearchOptions = { +export type UrlReaderSearchOptions = { /** * An etag can be provided to check whether the search response has changed from a previous execution. * @@ -326,11 +335,11 @@ export type SearchOptions = { * * @public */ -export type SearchResponse = { +export type UrlReaderSearchResponse = { /** * The files that matched the search query. */ - files: SearchResponseFile[]; + files: UrlReaderSearchResponseFile[]; /** * A unique identifier of the current remote tree, usually the commit SHA or etag from the target. @@ -343,7 +352,7 @@ export type SearchResponse = { * * @public */ -export type SearchResponseFile = { +export type UrlReaderSearchResponseFile = { /** * The full URL to the file. */ @@ -359,3 +368,49 @@ export type SearchResponseFile = { */ lastModifiedAt?: Date; }; + +/** + * @public + * @deprecated Use `UrlReaderReadTreeOptions` instead + */ +export type ReadTreeOptions = UrlReaderReadTreeOptions; +/** + * @public + * @deprecated Use `UrlReaderReadTreeResponse` instead + */ +export type ReadTreeResponse = UrlReaderReadTreeResponse; +/** + * @public + * @deprecated Use `UrlReaderReadTreeResponseDirOptions` instead + */ +export type ReadTreeResponseDirOptions = UrlReaderReadTreeResponseDirOptions; +/** + * @public + * @deprecated Use `UrlReaderReadTreeResponseFile` instead + */ +export type ReadTreeResponseFile = UrlReaderReadTreeResponseFile; +/** + * @public + * @deprecated Use `UrlReaderReadUrlResponse` instead + */ +export type ReadUrlResponse = UrlReaderReadUrlResponse; +/** + * @public + * @deprecated Use `UrlReaderReadUrlOptions` instead + */ +export type ReadUrlOptions = UrlReaderReadUrlOptions; +/** + * @public + * @deprecated Use `UrlReaderSearchOptions` instead + */ +export type SearchOptions = UrlReaderSearchOptions; +/** + * @public + * @deprecated Use `UrlReaderSearchResponse` instead + */ +export type SearchResponse = UrlReaderSearchResponse; +/** + * @public + * @deprecated Use `UrlReaderSearchResponseFile` instead + */ +export type SearchResponseFile = UrlReaderSearchResponseFile; diff --git a/packages/backend-plugin-api/src/services/definitions/index.ts b/packages/backend-plugin-api/src/services/definitions/index.ts index f22213a285..13175b96ae 100644 --- a/packages/backend-plugin-api/src/services/definitions/index.ts +++ b/packages/backend-plugin-api/src/services/definitions/index.ts @@ -74,6 +74,15 @@ export type { SearchOptions, SearchResponse, SearchResponseFile, + UrlReaderReadTreeOptions, + UrlReaderReadTreeResponse, + UrlReaderReadTreeResponseDirOptions, + UrlReaderReadTreeResponseFile, + UrlReaderReadUrlResponse, + UrlReaderReadUrlOptions, + UrlReaderSearchOptions, + UrlReaderSearchResponse, + UrlReaderSearchResponseFile, UrlReaderService, } from './UrlReaderService'; export type { BackstageUserInfo, UserInfoService } from './UserInfoService'; diff --git a/yarn.lock b/yarn.lock index ee4185b5b4..5c0993f074 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3588,6 +3588,12 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/backend-defaults@workspace:packages/backend-defaults" 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-app-api": "workspace:^" "@backstage/backend-common": "workspace:^" "@backstage/backend-dev-utils": "workspace:^" @@ -3597,25 +3603,41 @@ __metadata: "@backstage/config": "workspace:^" "@backstage/config-loader": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/integration": "workspace:^" + "@backstage/integration-aws-node": "workspace:^" "@backstage/plugin-events-node": "workspace:^" "@backstage/plugin-permission-node": "workspace:^" "@backstage/types": "workspace:^" + "@google-cloud/storage": ^7.0.0 "@keyv/memcache": ^1.3.5 "@keyv/redis": ^2.5.3 + "@octokit/rest": ^19.0.3 "@opentelemetry/api": ^1.3.0 + archiver: ^6.0.0 + aws-sdk-client-mock: ^4.0.0 + base64-stream: ^1.0.0 better-sqlite3: ^9.0.0 + concat-stream: ^2.0.0 cron: ^3.0.0 fs-extra: ^11.2.0 + git-url-parse: ^14.0.0 + isomorphic-git: ^1.23.0 keyv: ^4.5.2 knex: ^3.0.0 lodash: ^4.17.21 luxon: ^3.0.0 + minimatch: ^9.0.0 + msw: ^1.0.0 mysql2: ^3.0.0 + node-fetch: ^2.6.7 p-limit: ^3.1.0 pg: ^8.11.3 pg-connection-string: ^2.3.0 + raw-body: ^2.4.1 + tar: ^6.1.12 uuid: ^9.0.0 wait-for-expect: ^3.0.2 + yauzl: ^3.0.0 yn: ^4.0.0 zod: ^3.22.4 languageName: unknown From cd1e5bf33dd242cb5ee1b7ba7a400e27c03f5c30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 23 May 2024 21:23:48 +0200 Subject: [PATCH 41/46] temporarily fix the tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- docs/plugins/url-reader.md | 2 +- .../urlReader/lib/GoogleGcsUrlReader.test.ts | 30 ++++++++----------- .../urlReader/lib/GoogleGcsUrlReader.ts | 16 +++++----- 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/docs/plugins/url-reader.md b/docs/plugins/url-reader.md index c551cdc086..9fab0482bb 100644 --- a/docs/plugins/url-reader.md +++ b/docs/plugins/url-reader.md @@ -19,7 +19,7 @@ files before generating a documentation site. Since, the requirement for reading files is so essential for Backstage plugins, the -[`coreServices.urlReader`](../reference/backend-plugin-api.coreservices.urlreader/) +[`coreServices.urlReader`](../reference/backend-plugin-api.coreservices.urlreader.md) package provides a dedicated API for reading from such URL based remote locations like GitHub, GitLab, Bitbucket, Google Cloud Storage, etc. This is commonly referred to as "URL Reader". It takes care of making authenticated diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.test.ts index 318b134aa4..9a5cf741db 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.test.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.test.ts @@ -14,31 +14,27 @@ * limitations under the License. */ +import * as GoogleCloud from '@google-cloud/storage'; import { ConfigReader } from '@backstage/config'; import { JsonObject } from '@backstage/types'; import { DefaultReadTreeResponseFactory } from './tree'; import { GoogleGcsUrlReader } from './GoogleGcsUrlReader'; import { UrlReaderPredicateTuple } from './types'; -import packageinfo from '@backstage/backend-defaults/package.json'; +import packageinfo from '../../../../package.json'; import { mockServices } from '@backstage/backend-test-utils'; const bucketGetFilesMock = jest.fn(); -jest.mock('@google-cloud/storage', () => { - class Bucket { - getFiles(query: any) { - return bucketGetFilesMock(query); - } +class Bucket { + getFiles(query: any) { + return bucketGetFilesMock(query); } - class Storage { - bucket() { - return new Bucket(); - } +} +class Storage { + bucket() { + return new Bucket(); } - return { - __esModule: true, - Storage, - }; -}); +} +jest.spyOn(GoogleCloud, 'Storage').mockReturnValue(new Storage() as any); describe('GcsUrlReader', () => { const createReader = (config: JsonObject): UrlReaderPredicateTuple[] => { @@ -80,7 +76,7 @@ describe('GcsUrlReader', () => { }); it('check if userAgent has been called with this key value', async () => { const getStorage: any = { - userAgent: `backstage/backend-defaults.GoogleGcsUrlReader/${packageinfo.version}`, + userAgent: `backstage/backend-common.GoogleGcsUrlReader/${packageinfo.version}`, }; jest.mock('@google-cloud/storage', () => { return { @@ -89,7 +85,7 @@ describe('GcsUrlReader', () => { }); const getUserAgent = getStorage.userAgent.toString(); expect(getUserAgent).toBe( - `backstage/backend-defaults.GoogleGcsUrlReader/${packageinfo.version}`, + `backstage/backend-common.GoogleGcsUrlReader/${packageinfo.version}`, ); }); diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.ts index 124461ff80..0e8fef7683 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import * as GoogleCloud from '@google-cloud/storage'; import { UrlReaderService, UrlReaderReadTreeResponse, @@ -21,7 +22,6 @@ import { UrlReaderReadUrlResponse, UrlReaderSearchResponse, } from '@backstage/backend-plugin-api'; -import { Storage } from '@google-cloud/storage'; import { ReaderFactory } from './types'; import getRawBody from 'raw-body'; import { @@ -30,7 +30,7 @@ import { } from '@backstage/integration'; import { Readable } from 'stream'; import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; -import packageinfo from '@backstage/backend-defaults/package.json'; +import packageinfo from '../../../../package.json'; const GOOGLE_GCS_HOST = 'storage.cloud.google.com'; @@ -64,21 +64,21 @@ export class GoogleGcsUrlReader implements UrlReaderService { const gcsConfig = readGoogleGcsIntegrationConfig( config.getConfig('integrations.googleGcs'), ); - let storage: Storage; + let storage: GoogleCloud.Storage; if (!gcsConfig.clientEmail || !gcsConfig.privateKey) { logger.info( 'googleGcs credentials not found in config. Using default credentials provider.', ); - storage = new Storage({ - userAgent: `backstage/backend-defaults.GoogleGcsUrlReader/${packageinfo.version}`, + storage = new GoogleCloud.Storage({ + userAgent: `backstage/backend-common.GoogleGcsUrlReader/${packageinfo.version}`, }); } else { - storage = new Storage({ + storage = new GoogleCloud.Storage({ credentials: { client_email: gcsConfig.clientEmail || undefined, private_key: gcsConfig.privateKey || undefined, }, - userAgent: `backstage/backend-defaults.GoogleGcsUrlReader/${packageinfo.version}`, + userAgent: `backstage/backend-common.GoogleGcsUrlReader/${packageinfo.version}`, }); } const reader = new GoogleGcsUrlReader(gcsConfig, storage); @@ -88,7 +88,7 @@ export class GoogleGcsUrlReader implements UrlReaderService { constructor( private readonly integration: GoogleGcsIntegrationConfig, - private readonly storage: Storage, + private readonly storage: GoogleCloud.Storage, ) {} private readStreamFromUrl(url: string): Readable { From 3c7dbc00917939936425ee66e383fc0b04063aa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 11 Jun 2024 08:53:24 +0200 Subject: [PATCH 42/46] review comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .../src/entrypoints/urlReader/lib/GoogleGcsUrlReader.test.ts | 4 ++-- .../src/entrypoints/urlReader/lib/GoogleGcsUrlReader.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.test.ts index 9a5cf741db..537b8c375e 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.test.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.test.ts @@ -76,7 +76,7 @@ describe('GcsUrlReader', () => { }); it('check if userAgent has been called with this key value', async () => { const getStorage: any = { - userAgent: `backstage/backend-common.GoogleGcsUrlReader/${packageinfo.version}`, + userAgent: `backstage/backend-defaults.GoogleGcsUrlReader/${packageinfo.version}`, }; jest.mock('@google-cloud/storage', () => { return { @@ -85,7 +85,7 @@ describe('GcsUrlReader', () => { }); const getUserAgent = getStorage.userAgent.toString(); expect(getUserAgent).toBe( - `backstage/backend-common.GoogleGcsUrlReader/${packageinfo.version}`, + `backstage/backend-defaults.GoogleGcsUrlReader/${packageinfo.version}`, ); }); diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.ts index 0e8fef7683..843eee9c21 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GoogleGcsUrlReader.ts @@ -70,7 +70,7 @@ export class GoogleGcsUrlReader implements UrlReaderService { 'googleGcs credentials not found in config. Using default credentials provider.', ); storage = new GoogleCloud.Storage({ - userAgent: `backstage/backend-common.GoogleGcsUrlReader/${packageinfo.version}`, + userAgent: `backstage/backend-defaults.GoogleGcsUrlReader/${packageinfo.version}`, }); } else { storage = new GoogleCloud.Storage({ @@ -78,7 +78,7 @@ export class GoogleGcsUrlReader implements UrlReaderService { client_email: gcsConfig.clientEmail || undefined, private_key: gcsConfig.privateKey || undefined, }, - userAgent: `backstage/backend-common.GoogleGcsUrlReader/${packageinfo.version}`, + userAgent: `backstage/backend-defaults.GoogleGcsUrlReader/${packageinfo.version}`, }); } const reader = new GoogleGcsUrlReader(gcsConfig, storage); From 11d4ee4030659145a64064a244ec64cb5b17aa11 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 11 Jun 2024 13:08:03 +0200 Subject: [PATCH 43/46] cli: update reports Signed-off-by: Patrik Oldsberg --- packages/cli-node/api-report.md | 3 +++ packages/cli/cli-report.md | 1 + 2 files changed, 4 insertions(+) diff --git a/packages/cli-node/api-report.md b/packages/cli-node/api-report.md index 5b9b8485b8..a16b4c91a4 100644 --- a/packages/cli-node/api-report.md +++ b/packages/cli-node/api-report.md @@ -18,6 +18,9 @@ export interface BackstagePackageJson { backstage?: { role?: PackageRole; moved?: string; + pluginId?: string; + pluginPackage?: string; + pluginPackages?: string[]; }; // (undocumented) bundled?: boolean; diff --git a/packages/cli/cli-report.md b/packages/cli/cli-report.md index 7b6df4366c..01b0f7ddec 100644 --- a/packages/cli/cli-report.md +++ b/packages/cli/cli-report.md @@ -442,6 +442,7 @@ Options: Usage: backstage-cli repo fix [options] Options: + --publish --check -h, --help ``` From 9bdc3e89ab4f5bc20815dfd3793d4897900d1622 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 11 Jun 2024 09:36:58 +0200 Subject: [PATCH 44/46] refactor: set extenstion point "t" to null Signed-off-by: Camila Belo --- .changeset/calm-files-sort.md | 5 +++++ packages/backend-plugin-api/src/wiring/factories.test.ts | 2 +- packages/backend-plugin-api/src/wiring/factories.ts | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 .changeset/calm-files-sort.md diff --git a/.changeset/calm-files-sort.md b/.changeset/calm-files-sort.md new file mode 100644 index 0000000000..a487c00eb4 --- /dev/null +++ b/.changeset/calm-files-sort.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': patch +--- + +In tests, return `null` rather than throwing an error when trying to get the `ExtensionPoint.T` property, so that tests asserting the property are not easily broken. diff --git a/packages/backend-plugin-api/src/wiring/factories.test.ts b/packages/backend-plugin-api/src/wiring/factories.test.ts index 1fd05a1605..9f11c9b40b 100644 --- a/packages/backend-plugin-api/src/wiring/factories.test.ts +++ b/packages/backend-plugin-api/src/wiring/factories.test.ts @@ -26,7 +26,7 @@ describe('createExtensionPoint', () => { const extensionPoint = createExtensionPoint({ id: 'x' }); expect(extensionPoint).toBeDefined(); expect(extensionPoint.id).toBe('x'); - expect(() => extensionPoint.T).toThrow(); + expect(() => extensionPoint.T).not.toThrow(); expect(String(extensionPoint)).toBe('extensionPoint{x}'); }); }); diff --git a/packages/backend-plugin-api/src/wiring/factories.ts b/packages/backend-plugin-api/src/wiring/factories.ts index d0199e775a..5442bab897 100644 --- a/packages/backend-plugin-api/src/wiring/factories.ts +++ b/packages/backend-plugin-api/src/wiring/factories.ts @@ -51,6 +51,10 @@ export function createExtensionPoint( return { id: options.id, get T(): T { + if (process.env.NODE_ENV === 'test') { + // Avoid throwing errors so tests asserting extensions' properties cannot be easily broken + return null as T; + } throw new Error(`tried to read ExtensionPoint.T of ${this}`); }, toString() { From 006b3e8effa2ef123fd07ad0e04d895b3d2e04c4 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 11 Jun 2024 13:50:39 +0200 Subject: [PATCH 45/46] refactor(test-utils): rename MockDirectoryOptions to CreateMockDirectoryOptions Signed-off-by: Camila Belo --- .changeset/honest-badgers-ring.md | 5 ++++ packages/backend-test-utils/api-report.md | 15 +++++++----- packages/backend-test-utils/src/deprecated.ts | 23 +++++++++++++++++++ .../src/filesystem/MockDirectory.ts | 4 ++-- .../src/filesystem/index.ts | 2 +- packages/backend-test-utils/src/index.ts | 1 + 6 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 .changeset/honest-badgers-ring.md create mode 100644 packages/backend-test-utils/src/deprecated.ts diff --git a/.changeset/honest-badgers-ring.md b/.changeset/honest-badgers-ring.md new file mode 100644 index 0000000000..c1e763e6cb --- /dev/null +++ b/.changeset/honest-badgers-ring.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-test-utils': patch +--- + +The type `MockDirectoryOptions` was renamed to `CreateMockDirectoryOptions` so that it's clear these options are exclusive to the mock directory factory. diff --git a/packages/backend-test-utils/api-report.md b/packages/backend-test-utils/api-report.md index f3d790ebfe..cc30dc8f56 100644 --- a/packages/backend-test-utils/api-report.md +++ b/packages/backend-test-utils/api-report.md @@ -45,9 +45,15 @@ import { UserInfoService } from '@backstage/backend-plugin-api'; // @public export function createMockDirectory( - options?: MockDirectoryOptions, + options?: CreateMockDirectoryOptions, ): MockDirectory; +// @public +export interface CreateMockDirectoryOptions { + content?: MockDirectoryContent; + mockOsTmpDir?: boolean; +} + // @public (undocumented) export function isDockerDisabledForTests(): boolean; @@ -136,11 +142,8 @@ export interface MockDirectoryContentOptions { shouldReadAsText?: boolean | ((path: string, buffer: Buffer) => boolean); } -// @public -export interface MockDirectoryOptions { - content?: MockDirectoryContent; - mockOsTmpDir?: boolean; -} +// @public @deprecated (undocumented) +export type MockDirectoryOptions = CreateMockDirectoryOptions; // @public (undocumented) export namespace mockServices { diff --git a/packages/backend-test-utils/src/deprecated.ts b/packages/backend-test-utils/src/deprecated.ts new file mode 100644 index 0000000000..fad7523367 --- /dev/null +++ b/packages/backend-test-utils/src/deprecated.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CreateMockDirectoryOptions } from './filesystem'; + +/** + * @public + * @deprecated Use `CreateMockDirectoryOptions` from `@backstage/backend-test-utils` instead. + */ +export type MockDirectoryOptions = CreateMockDirectoryOptions; diff --git a/packages/backend-test-utils/src/filesystem/MockDirectory.ts b/packages/backend-test-utils/src/filesystem/MockDirectory.ts index 1c10c77fc6..39518f5d9c 100644 --- a/packages/backend-test-utils/src/filesystem/MockDirectory.ts +++ b/packages/backend-test-utils/src/filesystem/MockDirectory.ts @@ -347,7 +347,7 @@ class MockDirectoryImpl { * * @public */ -export interface MockDirectoryOptions { +export interface CreateMockDirectoryOptions { /** * In addition to creating a temporary directory, also mock `os.tmpdir()` to return the * mock directory path until the end of the test suite. @@ -386,7 +386,7 @@ export interface MockDirectoryOptions { * ``` */ export function createMockDirectory( - options?: MockDirectoryOptions, + options?: CreateMockDirectoryOptions, ): MockDirectory { const tmpDir = process.env.RUNNER_TEMP || os.tmpdir(); // GitHub Actions const root = fs.mkdtempSync(joinPath(tmpDir, 'backstage-tmp-test-dir-')); diff --git a/packages/backend-test-utils/src/filesystem/index.ts b/packages/backend-test-utils/src/filesystem/index.ts index e18b0b55b8..4a045c153d 100644 --- a/packages/backend-test-utils/src/filesystem/index.ts +++ b/packages/backend-test-utils/src/filesystem/index.ts @@ -16,8 +16,8 @@ export { createMockDirectory, + type CreateMockDirectoryOptions, type MockDirectory, - type MockDirectoryOptions, type MockDirectoryContent, type MockDirectoryContentOptions, type MockDirectoryContentCallback, diff --git a/packages/backend-test-utils/src/index.ts b/packages/backend-test-utils/src/index.ts index 72abd908c5..a9feacbacd 100644 --- a/packages/backend-test-utils/src/index.ts +++ b/packages/backend-test-utils/src/index.ts @@ -20,6 +20,7 @@ * @packageDocumentation */ +export * from './deprecated'; export * from './cache'; export * from './database'; export * from './msw'; From 227b57d5b499e8db9ca01d497f1934d7c5eb4424 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 11 Jun 2024 14:42:14 +0200 Subject: [PATCH 46/46] cli: more informative error message for missing plugin ID for modules during fix Signed-off-by: Patrik Oldsberg --- packages/cli/src/commands/repo/fix.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/commands/repo/fix.ts b/packages/cli/src/commands/repo/fix.ts index e7d243ea2c..370e5c0cb1 100644 --- a/packages/cli/src/commands/repo/fix.ts +++ b/packages/cli/src/commands/repo/fix.ts @@ -297,9 +297,17 @@ export function fixPluginId(pkg: FixablePackage) { paths.targetRoot, resolvePath(pkg.dir, 'package.json'), ); - throw new Error( - `Failed to guess plugin ID for "${pkg.packageJson.name}", please set the 'backstage.pluginId' field manually in "${path}"`, - ); + const msg = `Failed to guess plugin ID for "${pkg.packageJson.name}", please set the 'backstage.pluginId' field manually in "${path}"`; + if (role.endsWith('module')) { + const suggestedRole = role.startsWith('frontend') + ? 'web-library' + : 'node-library'; + throw new Error( + `${msg}. It is also possible that this package is not a module, and should use the '${suggestedRole}' role instead.`, + ); + } else { + throw new Error(msg); + } } if (guessedPluginId) {