From 72747b4b55d88db7e6012b9fe3cf530a5df87527 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Sat, 21 Feb 2026 10:02:13 -0600 Subject: [PATCH 01/26] Catalog - Deprecated two moved processors Signed-off-by: Andre Wanlin --- .changeset/rare-falcons-pump.md | 8 ++++++++ plugins/catalog-backend/report.api.md | 4 ++-- .../src/processors/AnnotateScmSlugEntityProcessor.ts | 5 ++++- .../catalog-backend/src/processors/CodeOwnersProcessor.ts | 5 ++++- 4 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 .changeset/rare-falcons-pump.md diff --git a/.changeset/rare-falcons-pump.md b/.changeset/rare-falcons-pump.md new file mode 100644 index 0000000000..78b0f48f8c --- /dev/null +++ b/.changeset/rare-falcons-pump.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Deprecated two processors as they have been moved to the Community Plugins repo with their own backend modules: + +- `AnnotateScmSlugEntityProcessor`: Use `@backstage-community/plugin-catalog-backend-module-annotate-scm-slug` instead +- `CodeOwnersProcessor`: Use `@backstage-community/plugin-catalog-backend-module-codeowners` instead diff --git a/plugins/catalog-backend/report.api.md b/plugins/catalog-backend/report.api.md index 9fc3041d6f..610548aec6 100644 --- a/plugins/catalog-backend/report.api.md +++ b/plugins/catalog-backend/report.api.md @@ -31,7 +31,7 @@ export class AnnotateLocationEntityProcessor implements CatalogProcessor { ): Promise; } -// @public (undocumented) +// @public @deprecated (undocumented) export class AnnotateScmSlugEntityProcessor implements CatalogProcessor { constructor(opts: { scmIntegrationRegistry: ScmIntegrationRegistry; @@ -76,7 +76,7 @@ export const CATALOG_ERRORS_TOPIC = 'experimental.catalog.errors'; const catalogPlugin: BackendFeature; export default catalogPlugin; -// @public (undocumented) +// @public @deprecated (undocumented) export class CodeOwnersProcessor implements CatalogProcessor { constructor(options: { integrations: ScmIntegrationRegistry; diff --git a/plugins/catalog-backend/src/processors/AnnotateScmSlugEntityProcessor.ts b/plugins/catalog-backend/src/processors/AnnotateScmSlugEntityProcessor.ts index a000f2f422..2cf9fcb24d 100644 --- a/plugins/catalog-backend/src/processors/AnnotateScmSlugEntityProcessor.ts +++ b/plugins/catalog-backend/src/processors/AnnotateScmSlugEntityProcessor.ts @@ -29,7 +29,10 @@ const GITHUB_ACTIONS_ANNOTATION = 'github.com/project-slug'; const GITLAB_ACTIONS_ANNOTATION = 'gitlab.com/project-slug'; const AZURE_ACTIONS_ANNOTATION = 'dev.azure.com/project-repo'; -/** @public */ +/** + * @public + * @deprecated Use `@backstage-community/plugin-catalog-backend-module-annotate-scm-slug` instead, this will be removed in a future release + */ export class AnnotateScmSlugEntityProcessor implements CatalogProcessor { private readonly opts: { scmIntegrationRegistry: ScmIntegrationRegistry; diff --git a/plugins/catalog-backend/src/processors/CodeOwnersProcessor.ts b/plugins/catalog-backend/src/processors/CodeOwnersProcessor.ts index f6dc27101c..24dc2b9b54 100644 --- a/plugins/catalog-backend/src/processors/CodeOwnersProcessor.ts +++ b/plugins/catalog-backend/src/processors/CodeOwnersProcessor.ts @@ -28,7 +28,10 @@ import { LoggerService, UrlReaderService } from '@backstage/backend-plugin-api'; const ALLOWED_KINDS = ['API', 'Component', 'Domain', 'Resource', 'System']; const ALLOWED_LOCATION_TYPES = ['url']; -/** @public */ +/** + * @public + * @deprecated Use `@backstage-community/plugin-catalog-backend-module-codeowners` instead, this will be removed in a future release + */ export class CodeOwnersProcessor implements CatalogProcessor { private readonly integrations: ScmIntegrationRegistry; private readonly logger: LoggerService; From cb7c6b1bc0d6dafe49144dc829394e470c1c4b9f Mon Sep 17 00:00:00 2001 From: Bond Yan Date: Thu, 26 Feb 2026 17:27:23 -0500 Subject: [PATCH 02/26] allowed keys implementation Signed-off-by: Bond Yan --- .changeset/crazy-ravens-reply.md | 6 ++ plugins/techdocs-backend/config.d.ts | 12 +++ .../src/stages/generate/helpers.test.ts | 77 +++++++++++++++++++ .../src/stages/generate/mkdocsPatchers.ts | 17 +++- .../src/stages/generate/techdocs.ts | 9 ++- .../src/stages/generate/types.ts | 1 + 6 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 .changeset/crazy-ravens-reply.md diff --git a/.changeset/crazy-ravens-reply.md b/.changeset/crazy-ravens-reply.md new file mode 100644 index 0000000000..48bc36c464 --- /dev/null +++ b/.changeset/crazy-ravens-reply.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-techdocs-backend': patch +'@backstage/plugin-techdocs-node': patch +--- + +Added `techdocs.generator.mkdocs.dangerouslyAllowAdditionalKeys` configuration option to explicit bypass MkDocs configuration key restrictions. This enables support for additional MkDocs configuration keys beyond the default safe allowlist, such as the `hooks` key which some MkDocs plugins require. diff --git a/plugins/techdocs-backend/config.d.ts b/plugins/techdocs-backend/config.d.ts index 5d3baa940a..87369f2ccd 100644 --- a/plugins/techdocs-backend/config.d.ts +++ b/plugins/techdocs-backend/config.d.ts @@ -64,6 +64,18 @@ export interface Config { * List of mkdocs plugins which should be added as default to all mkdocs.yml files. */ defaultPlugins?: string[]; + + /** + * List of additional MkDocs configuration keys to allow beyond + * the default safe allowlist. This can introduce security vulnerabilities. + * + * WARNING: Some MkDocs configuration keys can execute arbitrary code. For example, the + * 'hooks' key allows running arbitrary Python code during documentation generation. + * Only use this in trusted environments where all mkdocs.yml files are audited. + * + * @see https://www.mkdocs.org/user-guide/configuration/#hooks + */ + dangerouslyAllowAdditionalKeys?: string[]; }; }; diff --git a/plugins/techdocs-node/src/stages/generate/helpers.test.ts b/plugins/techdocs-node/src/stages/generate/helpers.test.ts index fd428fd23a..eb3c32a464 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.test.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.test.ts @@ -910,6 +910,83 @@ another_unknown: true expect(warn).toHaveBeenCalledWith(expect.stringContaining('hooks')); }); + + it('should allow additional keys when configured via dangerouslyAllowAdditionalKeys', async () => { + const mkdocsWithHooksAndCustom = `site_name: Test +hooks: + - hook.py +custom_dir: custom +some_unknown_key: value +`; + mockDir.setContent({ + 'mkdocs_allowed.yml': mkdocsWithHooksAndCustom, + }); + + // Allow 'hooks' and 'custom_dir' but not 'some_unknown_key' + await sanitizeMkdocsYml( + mockDir.resolve('mkdocs_allowed.yml'), + mockLogger, + ['hooks', 'custom_dir'], + ); + + const updatedMkdocsYml = await fs.readFile( + mockDir.resolve('mkdocs_allowed.yml'), + ); + const parsedYml = yaml.load(updatedMkdocsYml.toString()) as Record< + string, + unknown + >; + + // 'hooks' and 'custom_dir' should be preserved + expect(parsedYml.hooks).toEqual(['hook.py']); + expect(parsedYml.custom_dir).toBe('custom'); + // 'some_unknown_key' should still be removed + expect(parsedYml.some_unknown_key).toBeUndefined(); + expect(parsedYml.site_name).toBe('Test'); + + // Should warn about the dangerous configuration AND the removed key + expect(warn).toHaveBeenCalledWith( + expect.stringContaining( + 'DANGEROUS: Allowing additional MkDocs configuration keys beyond the default safe allowlist: hooks, custom_dir', + ), + ); + expect(warn).toHaveBeenCalledWith( + expect.stringContaining( + 'Removed the following unsupported configuration keys from mkdocs.yml: some_unknown_key', + ), + ); + }); + + it('should warn about dangerous keys even when no keys are removed', async () => { + mockDir.setContent({ + 'mkdocs_with_hooks.yml': mkdocsYmlWithHooks, + }); + + await sanitizeMkdocsYml( + mockDir.resolve('mkdocs_with_hooks.yml'), + mockLogger, + ['hooks'], + ); + + const updatedMkdocsYml = await fs.readFile( + mockDir.resolve('mkdocs_with_hooks.yml'), + ); + const parsedYml = yaml.load(updatedMkdocsYml.toString()) as { + hooks?: string[]; + site_name: string; + }; + + // Hooks should be preserved + expect(parsedYml.hooks).toBeDefined(); + expect(parsedYml.site_name).toBe('Test site name'); + + // Should warn about dangerous configuration + expect(warn).toHaveBeenCalledWith( + expect.stringContaining( + 'DANGEROUS: Allowing additional MkDocs configuration keys beyond the default safe allowlist: hooks', + ), + ); + }); }); describe('validateDocsDirectory', () => { diff --git a/plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts b/plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts index cd506d3b28..d676237b01 100644 --- a/plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts +++ b/plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts @@ -198,15 +198,28 @@ export const patchMkdocsYmlWithPlugins = async ( * * @param mkdocsYmlPath - Absolute path to mkdocs.yml or equivalent of a docs site * @param logger - A logger instance + * @param additionalAllowedKeys - Optional array of additional keys to allow beyond the default allowlist */ export const sanitizeMkdocsYml = async ( mkdocsYmlPath: string, logger: LoggerService, + additionalAllowedKeys?: string[], ) => { await patchMkdocsFile(mkdocsYmlPath, logger, mkdocsYml => { + // Combine default allowed keys with additional keys + const allowedKeys = new Set(ALLOWED_MKDOCS_KEYS); + if (additionalAllowedKeys && additionalAllowedKeys.length > 0) { + logger.warn( + `DANGEROUS: Allowing additional MkDocs configuration keys beyond the default safe allowlist: ${additionalAllowedKeys.join( + ', ', + )}. This may introduce security vulnerabilities. Only use in trusted environments.`, + ); + additionalAllowedKeys.forEach(key => allowedKeys.add(key)); + } + // Identify keys that will be removed for logging const removedKeys = Object.keys(mkdocsYml).filter( - key => !ALLOWED_MKDOCS_KEYS.has(key), + key => !allowedKeys.has(key), ); if (removedKeys.length > 0) { @@ -220,7 +233,7 @@ export const sanitizeMkdocsYml = async ( // Build a new object with only allowed keys const sanitized: Record = {}; - for (const key of ALLOWED_MKDOCS_KEYS) { + for (const key of allowedKeys) { if (key in mkdocsYml) { sanitized[key] = (mkdocsYml as Record)[key]; } diff --git a/plugins/techdocs-node/src/stages/generate/techdocs.ts b/plugins/techdocs-node/src/stages/generate/techdocs.ts index ed357c5c81..8a764eb391 100644 --- a/plugins/techdocs-node/src/stages/generate/techdocs.ts +++ b/plugins/techdocs-node/src/stages/generate/techdocs.ts @@ -115,7 +115,11 @@ export class TechdocsGenerator implements GeneratorBase { const docsDir = await validateMkdocsYaml(inputDir, content); // Remove unsupported configuration keys - await sanitizeMkdocsYml(mkdocsYmlPath, childLogger); + await sanitizeMkdocsYml( + mkdocsYmlPath, + childLogger, + this.options.dangerouslyAllowAdditionalKeys, + ); // Validate that no symlinks in the docs directory point outside the input directory // This prevents path traversal attacks where malicious symlinks could leak host files @@ -257,5 +261,8 @@ export function readGeneratorConfig( defaultPlugins: config.getOptionalStringArray( 'techdocs.generator.mkdocs.defaultPlugins', ), + dangerouslyAllowAdditionalKeys: config.getOptionalStringArray( + 'techdocs.generator.mkdocs.dangerouslyAllowAdditionalKeys', + ), }; } diff --git a/plugins/techdocs-node/src/stages/generate/types.ts b/plugins/techdocs-node/src/stages/generate/types.ts index 418260b819..b716e9510b 100644 --- a/plugins/techdocs-node/src/stages/generate/types.ts +++ b/plugins/techdocs-node/src/stages/generate/types.ts @@ -45,6 +45,7 @@ export type GeneratorConfig = { omitTechdocsCoreMkdocsPlugin?: boolean; legacyCopyReadmeMdToIndexMd?: boolean; defaultPlugins?: string[]; + dangerouslyAllowAdditionalKeys?: string[]; }; /** From 2e20bf20d76c1fc31e1933c6a8feb1c5780d4ddb Mon Sep 17 00:00:00 2001 From: Bond Yan Date: Fri, 27 Feb 2026 11:15:27 -0500 Subject: [PATCH 03/26] changeset typo Signed-off-by: Bond Yan --- .changeset/crazy-ravens-reply.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/crazy-ravens-reply.md b/.changeset/crazy-ravens-reply.md index 48bc36c464..d52b62880e 100644 --- a/.changeset/crazy-ravens-reply.md +++ b/.changeset/crazy-ravens-reply.md @@ -3,4 +3,4 @@ '@backstage/plugin-techdocs-node': patch --- -Added `techdocs.generator.mkdocs.dangerouslyAllowAdditionalKeys` configuration option to explicit bypass MkDocs configuration key restrictions. This enables support for additional MkDocs configuration keys beyond the default safe allowlist, such as the `hooks` key which some MkDocs plugins require. +Added `techdocs.generator.mkdocs.dangerouslyAllowAdditionalKeys` configuration option to explicitly bypass MkDocs configuration key restrictions. This enables support for additional MkDocs configuration keys beyond the default safe allow list, such as the `hooks` key which some MkDocs plugins require. From 527cf88a90f6fe2e0c0f5289a6f8fd75d6d24e55 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Fri, 6 Feb 2026 14:07:52 -0600 Subject: [PATCH 04/26] Integration - Removed long deprecated code Signed-off-by: Andre Wanlin Fixed lock file Signed-off-by: Andre Wanlin Improve changesets Signed-off-by: Andre Wanlin Removed link Signed-off-by: Andre Wanlin Update .changeset/sharp-ravens-shop.md Co-authored-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com> Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Update .changeset/six-trees-carry.md Co-authored-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com> Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Update .changeset/tiny-zoos-smash.md Co-authored-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com> Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Corrected gerrit changes based on feedback Signed-off-by: Andre Wanlin Updated API report Signed-off-by: Andre Wanlin Fixed some tests Signed-off-by: Andre Wanlin Fixed test Signed-off-by: Andre Wanlin Fixed another test Signed-off-by: Andre Wanlin Removed parseGerritGitilesUrl Signed-off-by: Andre Wanlin Table clean up Signed-off-by: Andre Wanlin Remove from changeset Signed-off-by: Andre Wanlin Changes based on feedback Signed-off-by: Andre Wanlin --- .changeset/sharp-ravens-shop.md | 10 + .changeset/six-trees-carry.md | 5 + .changeset/tiny-zoos-smash.md | 5 + .../building-backends/08-migrating.md | 102 -- .../backend-defaults/report-urlReader.api.md | 33 - .../urlReader/lib/BitbucketUrlReader.test.ts | 656 -------- .../urlReader/lib/BitbucketUrlReader.ts | 313 ---- .../entrypoints/urlReader/lib/UrlReaders.ts | 2 - .../src/entrypoints/urlReader/lib/index.ts | 1 - packages/integration-react/dev/DevPage.tsx | 6 +- packages/integration-react/dev/index.tsx | 2 +- .../src/api/ScmIntegrationsApi.test.ts | 2 +- packages/integration/config.d.ts | 58 - packages/integration/report.api.md | 108 -- .../integration/src/ScmIntegrations.test.ts | 11 - packages/integration/src/ScmIntegrations.ts | 25 +- packages/integration/src/azure/config.test.ts | 44 - packages/integration/src/azure/config.ts | 18 - .../integration/src/azure/deprecated.test.ts | 128 -- packages/integration/src/azure/deprecated.ts | 61 - packages/integration/src/azure/index.ts | 2 - .../bitbucket/BitbucketIntegration.test.ts | 114 -- .../src/bitbucket/BitbucketIntegration.ts | 99 -- .../integration/src/bitbucket/config.test.ts | 175 --- packages/integration/src/bitbucket/config.ts | 136 -- .../integration/src/bitbucket/core.test.ts | 304 ---- packages/integration/src/bitbucket/core.ts | 183 --- packages/integration/src/bitbucket/index.ts | 28 - packages/integration/src/gerrit/core.test.ts | 141 +- packages/integration/src/gerrit/core.ts | 98 +- packages/integration/src/gerrit/index.ts | 2 - packages/integration/src/github/core.test.ts | 24 +- packages/integration/src/github/core.ts | 24 - packages/integration/src/github/index.ts | 2 +- packages/integration/src/index.ts | 1 - packages/integration/src/registry.ts | 5 - .../.eslintrc.js | 1 - .../CHANGELOG.md | 1341 ----------------- .../README.md | 8 - .../catalog-info.yaml | 10 - .../knip-report.md | 8 - .../package.json | 62 - .../report.api.md | 110 -- .../src/actions/bitbucket.examples.test.ts | 368 ----- .../src/actions/bitbucket.examples.ts | 203 --- .../src/actions/bitbucket.test.ts | 619 -------- .../src/actions/bitbucket.ts | 450 ------ .../src/deprecated.ts | 47 - .../src/index.ts | 24 - .../src/module.ts | 58 - .../scaffolder-common/src/ScaffolderClient.ts | 7 - .../scaffolder-node/src/actions/util.test.ts | 9 +- plugins/scaffolder-node/src/actions/util.ts | 9 +- .../fields/RepoUrlPicker/validation.test.ts | 4 +- .../fields/RepoUrlPicker/validation.ts | 13 +- yarn.lock | 24 +- 56 files changed, 60 insertions(+), 6243 deletions(-) create mode 100644 .changeset/sharp-ravens-shop.md create mode 100644 .changeset/six-trees-carry.md create mode 100644 .changeset/tiny-zoos-smash.md delete mode 100644 packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.test.ts delete mode 100644 packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts delete mode 100644 packages/integration/src/azure/deprecated.test.ts delete mode 100644 packages/integration/src/azure/deprecated.ts delete mode 100644 packages/integration/src/bitbucket/BitbucketIntegration.test.ts delete mode 100644 packages/integration/src/bitbucket/BitbucketIntegration.ts delete mode 100644 packages/integration/src/bitbucket/config.test.ts delete mode 100644 packages/integration/src/bitbucket/config.ts delete mode 100644 packages/integration/src/bitbucket/core.test.ts delete mode 100644 packages/integration/src/bitbucket/core.ts delete mode 100644 packages/integration/src/bitbucket/index.ts delete mode 100644 plugins/scaffolder-backend-module-bitbucket/.eslintrc.js delete mode 100644 plugins/scaffolder-backend-module-bitbucket/CHANGELOG.md delete mode 100644 plugins/scaffolder-backend-module-bitbucket/README.md delete mode 100644 plugins/scaffolder-backend-module-bitbucket/catalog-info.yaml delete mode 100644 plugins/scaffolder-backend-module-bitbucket/knip-report.md delete mode 100644 plugins/scaffolder-backend-module-bitbucket/package.json delete mode 100644 plugins/scaffolder-backend-module-bitbucket/report.api.md delete mode 100644 plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.examples.test.ts delete mode 100644 plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.examples.ts delete mode 100644 plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.test.ts delete mode 100644 plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.ts delete mode 100644 plugins/scaffolder-backend-module-bitbucket/src/deprecated.ts delete mode 100644 plugins/scaffolder-backend-module-bitbucket/src/index.ts delete mode 100644 plugins/scaffolder-backend-module-bitbucket/src/module.ts diff --git a/.changeset/sharp-ravens-shop.md b/.changeset/sharp-ravens-shop.md new file mode 100644 index 0000000000..eb7486c490 --- /dev/null +++ b/.changeset/sharp-ravens-shop.md @@ -0,0 +1,10 @@ +--- +'@backstage/integration': major +--- + +**BREAKING** Removed deprecated Azure DevOps, Bitbucket, Gerrit and GitHub code: + +- For Azure Devops, the long deprecated `token` string and `credential` object have been removed from the `config.d.ts`. Use the `credentials` array object instead. +- For Bitbucket, the long deprecated `bitbucket` object has been removed from the `config.d.ts`. Use the `bitbucketCloud` or `bitbucketServer` objects instead. +- For Gerrit, the `parseGerritGitilesUrl` function has been removed, use `parseGitilesUrlRef` instead. The `buildGerritGitilesArchiveUrl` function has also been removed, use `buildGerritGitilesArchiveUrlFromLocation` instead. +- For GitHub, the `getGitHubRequestOptions` function has been removed. diff --git a/.changeset/six-trees-carry.md b/.changeset/six-trees-carry.md new file mode 100644 index 0000000000..9e21487c23 --- /dev/null +++ b/.changeset/six-trees-carry.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-defaults': minor +--- + +**BREAKING** Removed deprecated `BitbucketUrlReader`. Use the `BitbucketCloudUrlReader` or the `BitbucketServerUrlReader` instead. diff --git a/.changeset/tiny-zoos-smash.md b/.changeset/tiny-zoos-smash.md new file mode 100644 index 0000000000..883ea4f29a --- /dev/null +++ b/.changeset/tiny-zoos-smash.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-common': major +--- + +**BREAKING** Removed deprecated `bitbucket` integration from being registered in the `ScaffolderClient`. Use the `bitbucketCloud` or `bitbucketServer` integrations instead. diff --git a/docs/backend-system/building-backends/08-migrating.md b/docs/backend-system/building-backends/08-migrating.md index 3aa06216b4..fdbac8e65f 100644 --- a/docs/backend-system/building-backends/08-migrating.md +++ b/docs/backend-system/building-backends/08-migrating.md @@ -1340,105 +1340,3 @@ const backend = createBackend(); backend.add(import('@backstage/plugin-kubernetes-backend')); /* highlight-add-end */ ``` - -### The Plugins in Backstage Repo - -The vast majority of the backend plugins that currently live in the Backstage Repo have been migrated and their respective `README`s have details on how they should be installed using the New Backend System. - -| Package | Role | Migrated | Uses Alpha Export | Link to `README` | -| ------------------------------------------------------------------ | --------------------- | -------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -| @backstage-community/plugin-adr-backend | backend-plugin | true | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/adr/plugins/adr-backend/README.md) | -| @backstage-community/plugin-airbrake-backend | backend-plugin | true | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/airbrake/plugins/airbrake-backend/README.md) | -| @backstage/plugin-app-backend | backend-plugin | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/app-backend/README.md) | -| @backstage/plugin-auth-backend | backend-plugin | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/auth-backend/README.md) | -| @backstage/plugin-auth-backend-module-atlassian-provider | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/auth-backend-module-atlassian-provider/README.md) | -| @backstage/plugin-auth-backend-module-aws-alb-provider | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/auth-backend-module-aws-alb-provider/README.md) | -| @backstage/plugin-auth-backend-module-gcp-iap-provider | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/auth-backend-module-gcp-iap-provider/README.md) | -| @backstage/plugin-auth-backend-module-github-provider | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/auth-backend-module-github-provider/README.md) | -| @backstage/plugin-auth-backend-module-gitlab-provider | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/auth-backend-module-gitlab-provider/README.md) | -| @backstage/plugin-auth-backend-module-google-provider | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/auth-backend-module-google-provider/README.md) | -| @backstage/plugin-auth-backend-module-guest-provider | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/auth-backend-module-guest-provider/README.md) | -| @backstage/plugin-auth-backend-module-microsoft-provider | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/auth-backend-module-microsoft-provider/README.md) | -| @backstage/plugin-auth-backend-module-oauth2-provider | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/auth-backend-module-oauth2-provider/README.md) | -| @backstage/plugin-auth-backend-module-oauth2-proxy-provider | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/auth-backend-module-oauth2-proxy-provider/README.md) | -| @backstage/plugin-auth-backend-module-oidc-provider | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/auth-backend-module-oidc-provider/README.md) | -| @backstage/plugin-auth-backend-module-okta-provider | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/auth-backend-module-okta-provider/README.md) | -| @backstage/plugin-auth-backend-module-pinniped-provider | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/auth-backend-module-pinniped-provider/README.md) | -| @backstage/plugin-auth-backend-module-vmware-cloud-provider | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/auth-backend-module-vmware-cloud-provider/README.md) | -| @backstage-community/plugin-azure-devops-backend | backend-plugin | true | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/azure-devops/plugins/azure-devops-backend/README.md) | -| @backstage-community/plugin-azure-sites-backend | backend-plugin | true | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/azure-sites/plugins/azure-sites-backend/README.md) | -| @backstage-community/plugin-badges-backend | backend-plugin | true | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/badges/plugins/badges-backend/README.md) | -| @backstage-community/plugin-bazaar-backend | backend-plugin | true | true | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/bazaar/plugins/bazaar-backend/README.md) | -| @backstage/plugin-catalog-backend | backend-plugin | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/README.md) | -| @backstage/plugin-catalog-backend-module-aws | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-aws/README.md) | -| @backstage/plugin-catalog-backend-module-azure | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-azure/README.md) | -| @backstage/plugin-catalog-backend-module-backstage-openapi | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-backstage-openapi/README.md) | -| @backstage/plugin-catalog-backend-module-bitbucket-cloud | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-bitbucket-cloud/README.md) | -| @backstage/plugin-catalog-backend-module-bitbucket-server | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-bitbucket-server/README.md) | -| @backstage/plugin-catalog-backend-module-gcp | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-gcp/README.md) | -| @backstage/plugin-catalog-backend-module-gerrit | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-gerrit/README.md) | -| @backstage/plugin-catalog-backend-module-github | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-github/README.md) | -| @backstage/plugin-catalog-backend-module-github-org | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-github-org/README.md) | -| @backstage/plugin-catalog-backend-module-gitlab | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-gitlab/README.md) | -| @backstage/plugin-catalog-backend-module-incremental-ingestion | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-incremental-ingestion/README.md) | -| @backstage/plugin-catalog-backend-module-ldap | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-ldap/README.md) | -| @backstage/plugin-catalog-backend-module-msgraph | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-msgraph/README.md) | -| @backstage/plugin-catalog-backend-module-openapi | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-openapi/README.md) | -| @backstage/plugin-catalog-backend-module-puppetdb | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-puppetdb/README.md) | -| @backstage/plugin-catalog-backend-module-scaffolder-entity-model | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-scaffolder-entity-model/README.md) | -| @backstage/plugin-catalog-backend-module-unprocessed | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-unprocessed/README.md) | -| @backstage-community/plugin-code-coverage-backend | backend-plugin | true | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/code-coverage/plugins/code-coverage-backend/README.md) | -| @backstage/plugin-devtools-backend | backend-plugin | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/devtools-backend/README.md) | -| @backstage-community/plugin-entity-feedback-backend | backend-plugin | true | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/entity-feedback/plugins/entity-feedback-backend/README.md) | -| @backstage/plugin-events-backend | backend-plugin | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/events-backend/README.md) | -| @backstage/plugin-events-backend-module-aws-sqs | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/events-backend-module-aws-sqs/README.md) | -| @backstage/plugin-events-backend-module-azure | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/events-backend-module-azure/README.md) | -| @backstage/plugin-events-backend-module-bitbucket-cloud | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/events-backend-module-bitbucket-cloud/README.md) | -| @backstage/plugin-events-backend-module-gerrit | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/events-backend-module-gerrit/README.md) | -| @backstage/plugin-events-backend-module-github | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/events-backend-module-github/README.md) | -| @backstage/plugin-events-backend-module-gitlab | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/events-backend-module-gitlab/README.md) | -| @internal/plugin-todo-list-backend | backend-plugin | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/example-todo-list-backend/README.md) | -| @backstage-community/plugin-explore-backend | backend-plugin | true | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/explore/plugins/explore-backend/README.md) | -| @backstage-community/plugin-jenkins-backend | backend-plugin | true | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/jenkins/plugins/jenkins-backend/README.md) | -| @backstage-community/plugin-kafka-backend | backend-plugin | true | true | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/kafka/plugins/kafka-backend/README.md) | -| @backstage/plugin-kubernetes-backend | backend-plugin | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/kubernetes-backend/README.md) | -| @backstage-community/plugin-lighthouse-backend | backend-plugin | true | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/lighthouse/plugins/lighthouse-backend/README.md) | -| @backstage-community/plugin-linguist-backend | backend-plugin | true | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/linguist/plugins/linguist-backend/README.md) | -| @backstage-community/plugin-nomad-backend | backend-plugin | true | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/nomad/plugins/nomad-backend/README.md) | -| @backstage/plugin-notifications-backend | backend-plugin | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/notifications-backend/README.md) | -| @backstage-community/plugin-periskop-backend | backend-plugin | true | true | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/periskop/plugins/periskop-backend/README.md) | -| @backstage/plugin-permission-backend | backend-plugin | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/permission-backend/README.md) | -| @backstage/plugin-permission-backend-module-allow-all-policy | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/permission-backend-module-policy-allow-all/README.md) | -| @backstage-community/plugin-playlist-backend | backend-plugin | true | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/playlist/plugins/playlist-backend/README.md) | -| @backstage/plugin-proxy-backend | backend-plugin | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/proxy-backend/README.md) | -| @backstage-community/plugin-rollbar-backend | backend-plugin | | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/rollbar/plugins/rollbar-backend/README.md) | -| @backstage/plugin-scaffolder-backend | backend-plugin | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/README.md) | -| @backstage/plugin-scaffolder-backend-module-azure | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-azure/README.md) | -| @backstage/plugin-scaffolder-backend-module-bitbucket | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-bitbucket/README.md) | -| @backstage/plugin-scaffolder-backend-module-bitbucket-cloud | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-bitbucket-cloud/README.md) | -| @backstage/plugin-scaffolder-backend-module-bitbucket-server | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-bitbucket-server/README.md) | -| @backstage/plugin-scaffolder-backend-module-confluence-to-markdown | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-confluence-to-markdown/README.md) | -| @backstage/plugin-scaffolder-backend-module-cookiecutter | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-cookiecutter/README.md) | -| @backstage/plugin-scaffolder-backend-module-gerrit | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-gerrit/README.md) | -| @backstage/plugin-scaffolder-backend-module-gitea | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-gitea/README.md) | -| @backstage/plugin-scaffolder-backend-module-github | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-github/README.md) | -| @backstage/plugin-scaffolder-backend-module-gitlab | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-gitlab/README.md) | -| @backstage/plugin-scaffolder-backend-module-rails | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-rails/README.md) | -| @backstage/plugin-scaffolder-backend-module-sentry | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-sentry/README.md) | -| @backstage/plugin-scaffolder-backend-module-yeoman | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-yeoman/README.md) | -| @backstage/plugin-search-backend | backend-plugin | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/search-backend/README.md) | -| @backstage/plugin-search-backend-module-catalog | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/search-backend-module-catalog/README.md) | -| @backstage/plugin-search-backend-module-elasticsearch | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/search-backend-module-elasticsearch/README.md) | -| @backstage/plugin-search-backend-module-explore | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/search-backend-module-explore/README.md) | -| @backstage/plugin-search-backend-module-pg | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/search-backend-module-pg/README.md) | -| @backstage/plugin-search-backend-module-stack-overflow-collator | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/search-backend-module-stack-overflow-collator/README.md) | -| @backstage/plugin-search-backend-module-techdocs | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/search-backend-module-techdocs/README.md) | -| @backstage/plugin-signals-backend | backend-plugin | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/signals-backend/README.md) | -| @backstage-community/plugin-sonarqube-backend | backend-plugin | true | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/sonarqube/plugins/sonarqube-backend/README.md) | -| @backstage-community/plugin-stack-overflow-backend | backend-plugin | | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/stack-overflow/plugins/stack-overflow-backend/README.md) | -| @backstage-community/plugin-tech-insights-backend | backend-plugin | true | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/tech-insights/plugins/tech-insights-backend/README.md) | -| @backstage-community/plugin-tech-insights-backend-module-jsonfc | backend-plugin-module | true | | [README](https://github.com/backstage/community-plugins/blob/main/workspaces/tech-insights/plugins/tech-insights-backend-module-jsonfc/README.md) | -| @backstage/plugin-techdocs-backend | backend-plugin | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/techdocs-backend/README.md) | -| @backstage-community/plugin-todo-backend | backend-plugin | true | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/todo/plugins/todo-backend/README.md) | -| @backstage/plugin-user-settings-backend | backend-plugin | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/user-settings-backend/README.md) | -| @backstage-community/plugin-vault-backend | backend-plugin | true | | [README](https://github.com/backstage/community-plugins/blob/master/workspaces/vault/plugins/vault-backend/README.md) | diff --git a/packages/backend-defaults/report-urlReader.api.md b/packages/backend-defaults/report-urlReader.api.md index 78a35911b8..c32a63231b 100644 --- a/packages/backend-defaults/report-urlReader.api.md +++ b/packages/backend-defaults/report-urlReader.api.md @@ -10,7 +10,6 @@ import { AzureCredentialsManager } 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'; @@ -190,38 +189,6 @@ export class BitbucketServerUrlReader implements UrlReaderService { 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?: UrlReaderServiceReadTreeOptions, - ): Promise; - // (undocumented) - readUrl( - url: string, - options?: UrlReaderServiceReadUrlOptions, - ): Promise; - // (undocumented) - search( - url: string, - options?: UrlReaderServiceSearchOptions, - ): Promise; - // (undocumented) - toString(): string; -} - // @public export class FetchUrlReader implements UrlReaderService { static factory: ReaderFactory; diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.test.ts deleted file mode 100644 index 1a72d2af73..0000000000 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.test.ts +++ /dev/null @@ -1,656 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { ConfigReader } from '@backstage/config'; -import { - BitbucketIntegration, - readBitbucketIntegrationConfig, -} from '@backstage/integration'; -import { - createMockDirectory, - mockServices, - registerMswTestHooks, -} from '@backstage/backend-test-utils'; -import fs from 'fs-extra'; -import { rest } from 'msw'; -import { setupServer } from 'msw/node'; -import path from 'node:path'; -import { NotModifiedError } from '@backstage/errors'; -import { BitbucketUrlReader } from './BitbucketUrlReader'; -import { DefaultReadTreeResponseFactory } from './tree'; -import getRawBody from 'raw-body'; -import { UrlReaderServiceReadUrlResponse } from '@backstage/backend-plugin-api'; - -const logger = mockServices.logger.mock(); - -describe('BitbucketUrlReader.factory', () => { - it('only apply integration configs not inherited from bitbucketCloud or bitbucketServer', () => { - const config = new ConfigReader({ - integrations: { - bitbucket: [], - bitbucketCloud: [ - { - username: 'username', - appPassword: 'password', - }, - ], - bitbucketServer: [ - { - host: 'bitbucket-server.local', - token: 'test-token', - }, - ], - }, - }); - const treeResponseFactory = DefaultReadTreeResponseFactory.create({ - config: config, - }); - - const tuples = BitbucketUrlReader.factory({ - config, - logger, - treeResponseFactory, - }); - - expect(tuples).toHaveLength(0); - }); -}); - -describe('BitbucketUrlReader', () => { - const mockDir = createMockDirectory({ mockOsTmpDir: true }); - - beforeEach(mockDir.clear); - - const treeResponseFactory = DefaultReadTreeResponseFactory.create({ - config: new ConfigReader({}), - }); - - const bitbucketProcessor = new BitbucketUrlReader( - new BitbucketIntegration( - readBitbucketIntegrationConfig( - new ConfigReader({ - host: 'bitbucket.org', - apiBaseUrl: 'https://api.bitbucket.org/2.0', - }), - ), - ), - logger, - { treeResponseFactory }, - ); - - const hostedBitbucketProcessor = new BitbucketUrlReader( - new BitbucketIntegration( - readBitbucketIntegrationConfig( - new ConfigReader({ - host: 'bitbucket.mycompany.net', - apiBaseUrl: 'https://api.bitbucket.mycompany.net/rest/api/1.0', - }), - ), - ), - logger, - { treeResponseFactory }, - ); - - const worker = setupServer(); - registerMswTestHooks(worker); - - describe('readUrl', () => { - it('should be able to readUrl via buffer without ETag', async () => { - worker.use( - rest.get( - 'https://api.bitbucket.org/2.0/repositories/backstage-verification/test-template/src/master/template.yaml', - (req, res, ctx) => { - expect(req.headers.get('If-None-Match')).toBeNull(); - return res( - ctx.status(200), - ctx.body('foo'), - ctx.set('ETag', 'etag-value'), - ); - }, - ), - ); - - const result = await bitbucketProcessor.readUrl( - 'https://bitbucket.org/backstage-verification/test-template/src/master/template.yaml', - ); - const buffer = await result.buffer(); - expect(buffer.toString()).toBe('foo'); - }); - - it('should be able to readUrl using provided token', async () => { - worker.use( - rest.get( - 'https://api.bitbucket.org/2.0/repositories/backstage-verification/test-template/src/master/template.yaml', - (req, res, ctx) => { - expect(req.headers.get('authorization')).toBe( - 'Bearer manual-token', - ); - return res(ctx.status(200), ctx.body('foo')); - }, - ), - ); - - const result = await bitbucketProcessor.readUrl( - 'https://bitbucket.org/backstage-verification/test-template/src/master/template.yaml', - { token: 'manual-token' }, - ); - const buffer = await result.buffer(); - expect(buffer.toString()).toBe('foo'); - }); - - it('should be able to readUrl via stream without ETag', async () => { - worker.use( - rest.get( - 'https://api.bitbucket.org/2.0/repositories/backstage-verification/test-template/src/master/template.yaml', - (req, res, ctx) => { - expect(req.headers.get('If-None-Match')).toBeNull(); - return res( - ctx.status(200), - ctx.body('foo'), - ctx.set('ETag', 'etag-value'), - ); - }, - ), - ); - - const result = await bitbucketProcessor.readUrl( - 'https://bitbucket.org/backstage-verification/test-template/src/master/template.yaml', - ); - const fromStream = await getRawBody(result.stream!()); - expect(fromStream.toString()).toBe('foo'); - }); - - it('should be able to readUrl with matching ETag', async () => { - worker.use( - rest.get( - 'https://api.bitbucket.org/2.0/repositories/backstage-verification/test-template/src/master/template.yaml', - (req, res, ctx) => { - expect(req.headers.get('If-None-Match')).toBe( - 'matching-etag-value', - ); - return res(ctx.status(304)); - }, - ), - ); - - await expect( - bitbucketProcessor.readUrl( - 'https://bitbucket.org/backstage-verification/test-template/src/master/template.yaml', - { etag: 'matching-etag-value' }, - ), - ).rejects.toThrow(NotModifiedError); - }); - - it('should be able to readUrl without matching ETag', async () => { - worker.use( - rest.get( - 'https://api.bitbucket.org/2.0/repositories/backstage-verification/test-template/src/master/template.yaml', - (req, res, ctx) => { - expect(req.headers.get('If-None-Match')).toBe( - 'previous-etag-value', - ); - return res( - ctx.status(200), - ctx.body('foo'), - ctx.set('ETag', 'new-etag-value'), - ); - }, - ), - ); - - const result = await bitbucketProcessor.readUrl( - 'https://bitbucket.org/backstage-verification/test-template/src/master/template.yaml', - { etag: 'previous-etag-value' }, - ); - const buffer = await result.buffer(); - expect(buffer.toString()).toBe('foo'); - expect(result.etag).toBe('new-etag-value'); - }); - - it('should be able to readUrl via buffer without If-Modified-Since', async () => { - worker.use( - rest.get( - 'https://api.bitbucket.org/2.0/repositories/backstage-verification/test-template/src/master/template.yaml', - (req, res, ctx) => { - expect(req.headers.get('If-None-Match')).toBeNull(); - return res( - ctx.status(200), - ctx.body('foo'), - ctx.set('ETag', 'etag-value'), - ctx.set( - 'Last-Modified', - new Date('2020-01-01T00:00:00Z').toUTCString(), - ), - ); - }, - ), - ); - - const result = await bitbucketProcessor.readUrl( - 'https://bitbucket.org/backstage-verification/test-template/src/master/template.yaml', - ); - const buffer = await result.buffer(); - expect(result.lastModifiedAt).toEqual(new Date('2020-01-01T00:00:00Z')); - expect(buffer.toString()).toBe('foo'); - }); - - it('should be throw not modified when If-Modified-Since returns a 304', async () => { - worker.use( - rest.get( - 'https://api.bitbucket.org/2.0/repositories/backstage-verification/test-template/src/master/template.yaml', - (req, res, ctx) => { - expect(req.headers.get('If-Modified-Since')).toBe( - new Date('1999 12 31 23:59:59 GMT').toUTCString(), - ); - return res(ctx.status(304)); - }, - ), - ); - - await expect( - bitbucketProcessor.readUrl( - 'https://bitbucket.org/backstage-verification/test-template/src/master/template.yaml', - { lastModifiedAfter: new Date('1999 12 31 23:59:59 GMT') }, - ), - ).rejects.toThrow(NotModifiedError); - }); - - it('should be able to readUrl when If-Modified-Since is before Last-Modified', async () => { - worker.use( - rest.get( - 'https://api.bitbucket.org/2.0/repositories/backstage-verification/test-template/src/master/template.yaml', - (req, res, ctx) => { - expect(req.headers.get('If-Modified-Since')).toBe( - new Date('1999 12 31 23:59:59 GMT').toUTCString(), - ); - return res( - ctx.status(200), - ctx.set( - 'Last-Modified', - new Date('2020-01-01T00:00:00Z').toUTCString(), - ), - ctx.body('foo'), - ); - }, - ), - ); - - const result = await bitbucketProcessor.readUrl( - 'https://bitbucket.org/backstage-verification/test-template/src/master/template.yaml', - { lastModifiedAfter: new Date('1999 12 31 23:59:59 GMT') }, - ); - const buffer = await result.buffer(); - expect(buffer.toString()).toBe('foo'); - expect(result.lastModifiedAt).toEqual(new Date('2020-01-01T00:00:00Z')); - }); - }); - - describe('read', () => { - it('rejects unknown targets', async () => { - await expect( - bitbucketProcessor.read('https://not.bitbucket.com/apa'), - ).rejects.toThrow( - 'Incorrect URL: https://not.bitbucket.com/apa, Error: Invalid Bitbucket URL or file path', - ); - }); - }); - - describe('readTree', () => { - const repoBuffer = fs.readFileSync( - path.resolve( - __dirname, - '__fixtures__/bitbucket-repo-with-commit-hash.tar.gz', - ), - ); - - const privateBitbucketRepoBuffer = fs.readFileSync( - path.resolve(__dirname, '__fixtures__/bitbucket-server-repo.tar.gz'), - ); - - beforeEach(() => { - worker.use( - rest.get( - 'https://api.bitbucket.org/2.0/repositories/backstage/mock', - (_, res, ctx) => - res( - ctx.status(200), - ctx.json({ - mainbranch: { - type: 'branch', - name: 'master', - }, - }), - ), - ), - rest.get( - 'https://bitbucket.org/backstage/mock/get/master.tar.gz', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/zip'), - ctx.set( - 'content-disposition', - 'attachment; filename=backstage-mock-12ab34cd56ef.tar.gz', - ), - ctx.body(new Uint8Array(repoBuffer)), - ), - ), - rest.get( - 'https://api.bitbucket.org/2.0/repositories/backstage/mock/commits/master', - (_, res, ctx) => - res( - ctx.status(200), - ctx.json({ - values: [{ hash: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st' }], - }), - ), - ), - rest.get( - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/archive', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/zip'), - ctx.set( - 'content-disposition', - 'attachment; filename=backstage-mock.tgz', - ), - ctx.body(new Uint8Array(privateBitbucketRepoBuffer)), - ), - ), - rest.get( - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/commits', - (_, res, ctx) => - res( - ctx.status(200), - ctx.json({ - values: [{ id: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st' }], - }), - ), - ), - ); - }); - - it('returns the wanted files from an archive', async () => { - const response = await bitbucketProcessor.readTree( - 'https://bitbucket.org/backstage/mock/src/master', - ); - - expect(response.etag).toBe('12ab34cd56ef'); - - const files = await response.files(); - - expect(files.length).toBe(2); - const mkDocsFile = await files[0].content(); - const indexMarkdownFile = await files[1].content(); - - expect(indexMarkdownFile.toString()).toBe('# Test\n'); - expect(mkDocsFile.toString()).toBe('site_name: Test\n'); - }); - - it('creates a directory with the wanted files', async () => { - const response = await bitbucketProcessor.readTree( - 'https://bitbucket.org/backstage/mock', - ); - - const dir = await response.dir({ targetDir: mockDir.path }); - - await expect( - fs.readFile(path.join(dir, 'mkdocs.yml'), 'utf8'), - ).resolves.toBe('site_name: Test\n'); - await expect( - fs.readFile(path.join(dir, 'docs', 'index.md'), 'utf8'), - ).resolves.toBe('# Test\n'); - }); - - it('uses private bitbucket host', async () => { - const response = await hostedBitbucketProcessor.readTree( - 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/docs?at=some-branch', - ); - - expect(response.etag).toBe('12ab34cd56ef'); - - const files = await response.files(); - - expect(files.length).toBe(1); - const indexMarkdownFile = await files[0].content(); - - expect(indexMarkdownFile.toString()).toBe('# Test\n'); - }); - - it('returns the wanted files from an archive with a subpath', async () => { - const response = await bitbucketProcessor.readTree( - 'https://bitbucket.org/backstage/mock/src/master/docs', - ); - - expect(response.etag).toBe('12ab34cd56ef'); - - const files = await response.files(); - - expect(files.length).toBe(1); - const indexMarkdownFile = await files[0].content(); - - expect(indexMarkdownFile.toString()).toBe('# Test\n'); - }); - - it('creates a directory with the wanted files with a subpath', async () => { - const response = await bitbucketProcessor.readTree( - 'https://bitbucket.org/backstage/mock/src/master/docs', - ); - - const dir = await response.dir({ targetDir: mockDir.path }); - - await expect( - fs.readFile(path.join(dir, 'index.md'), 'utf8'), - ).resolves.toBe('# Test\n'); - }); - - it('throws a NotModifiedError when given a etag in options', async () => { - const fnBitbucket = async () => { - await bitbucketProcessor.readTree( - 'https://bitbucket.org/backstage/mock', - { etag: '12ab34cd56ef' }, - ); - }; - - await expect(fnBitbucket).rejects.toThrow(NotModifiedError); - }); - - it('should not throw a NotModifiedError when given an outdated etag in options', async () => { - const response = await bitbucketProcessor.readTree( - 'https://bitbucket.org/backstage/mock', - { etag: 'outdatedetag123abc' }, - ); - - expect(response.etag).toBe('12ab34cd56ef'); - }); - }); - - describe('search hosted', () => { - const repoBuffer = fs.readFileSync( - path.resolve( - __dirname, - '__fixtures__/bitbucket-repo-with-commit-hash.tar.gz', - ), - ); - - beforeEach(() => { - worker.use( - rest.get( - 'https://api.bitbucket.org/2.0/repositories/backstage/mock', - (_, res, ctx) => - res( - ctx.status(200), - ctx.json({ - mainbranch: { - type: 'branch', - name: 'master', - }, - }), - ), - ), - rest.get( - 'https://bitbucket.org/backstage/mock/get/master.tar.gz', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/zip'), - ctx.set( - 'content-disposition', - 'attachment; filename=backstage-mock-12ab34cd56ef.tar.gz', - ), - ctx.body(new Uint8Array(repoBuffer)), - ), - ), - rest.get( - 'https://api.bitbucket.org/2.0/repositories/backstage/mock/commits/master', - (_, res, ctx) => - res( - ctx.status(200), - ctx.json({ - values: [{ hash: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st' }], - }), - ), - ), - ); - }); - - it('works for the naive case', async () => { - const result = await bitbucketProcessor.search( - 'https://bitbucket.org/backstage/mock/src/master/**/index.*', - ); - expect(result.etag).toBe('12ab34cd56ef'); - expect(result.files.length).toBe(1); - expect(result.files[0].url).toBe( - 'https://bitbucket.org/backstage/mock/src/master/docs/index.md', - ); - await expect(result.files[0].content()).resolves.toEqual( - Buffer.from('# Test\n'), - ); - }); - - it('works in nested folders', async () => { - const result = await bitbucketProcessor.search( - 'https://bitbucket.org/backstage/mock/src/master/docs/index.*', - ); - expect(result.etag).toBe('12ab34cd56ef'); - expect(result.files.length).toBe(1); - expect(result.files[0].url).toBe( - 'https://bitbucket.org/backstage/mock/src/master/docs/index.md', - ); - await expect(result.files[0].content()).resolves.toEqual( - Buffer.from('# Test\n'), - ); - }); - - it('throws NotModifiedError when same etag', async () => { - await expect( - bitbucketProcessor.search( - 'https://bitbucket.org/backstage/mock/src/master/**/index.*', - { etag: '12ab34cd56ef' }, - ), - ).rejects.toThrow(NotModifiedError); - }); - }); - - describe('search private', () => { - const privateBitbucketRepoBuffer = fs.readFileSync( - path.resolve(__dirname, '__fixtures__/bitbucket-server-repo.tar.gz'), - ); - - beforeEach(() => { - worker.use( - rest.get( - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/archive', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/zip'), - ctx.set( - 'content-disposition', - 'attachment; filename=backstage-mock.tgz', - ), - ctx.body(new Uint8Array(privateBitbucketRepoBuffer)), - ), - ), - rest.get( - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/commits', - (_, res, ctx) => - res( - ctx.status(200), - ctx.json({ - values: [{ id: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st' }], - }), - ), - ), - ); - }); - - it('works for the naive case', async () => { - const result = await hostedBitbucketProcessor.search( - 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/**/index.*?at=master', - ); - expect(result.etag).toBe('12ab34cd56ef'); - expect(result.files.length).toBe(1); - expect(result.files[0].url).toBe( - 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/docs/index.md?at=master', - ); - await expect(result.files[0].content()).resolves.toEqual( - Buffer.from('# Test\n'), - ); - }); - - it('works in nested folders', async () => { - const result = await hostedBitbucketProcessor.search( - 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/docs/index.*?at=master', - ); - expect(result.etag).toBe('12ab34cd56ef'); - expect(result.files.length).toBe(1); - expect(result.files[0].url).toBe( - 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/docs/index.md?at=master', - ); - await expect(result.files[0].content()).resolves.toEqual( - Buffer.from('# Test\n'), - ); - }); - - it('throws NotModifiedError when same etag', async () => { - await expect( - hostedBitbucketProcessor.search( - 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/**/index.*?at=master', - { etag: '12ab34cd56ef' }, - ), - ).rejects.toThrow(NotModifiedError); - }); - - it('should work for exact URLs', async () => { - hostedBitbucketProcessor.readUrl = jest.fn().mockResolvedValue({ - buffer: async () => Buffer.from('content'), - etag: 'etag', - } as UrlReaderServiceReadUrlResponse); - - const result = await hostedBitbucketProcessor.search( - 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/docs/index.md?at=master', - ); - expect(result.etag).toBe('etag'); - expect(result.files.length).toBe(1); - expect(result.files[0].url).toBe( - 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/docs/index.md?at=master', - ); - expect((await result.files[0].content()).toString()).toEqual('content'); - }); - }); -}); diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts deleted file mode 100644 index 8c8843d7e9..0000000000 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - UrlReaderService, - UrlReaderServiceReadTreeOptions, - UrlReaderServiceReadTreeResponse, - UrlReaderServiceReadUrlOptions, - UrlReaderServiceReadUrlResponse, - UrlReaderServiceSearchOptions, - UrlReaderServiceSearchResponse, -} from '@backstage/backend-plugin-api'; -import { - assertError, - NotFoundError, - NotModifiedError, -} from '@backstage/errors'; -import { - BitbucketIntegration, - getBitbucketDefaultBranch, - getBitbucketDownloadUrl, - getBitbucketFileFetchUrl, - getBitbucketRequestOptions, - ScmIntegrations, -} from '@backstage/integration'; -import parseGitUrl from 'git-url-parse'; -import { trimEnd } from 'lodash'; -import { Minimatch } from 'minimatch'; -import { LoggerService } from '@backstage/backend-plugin-api'; -import { ReaderFactory, ReadTreeResponseFactory } from './types'; -import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; - -/** - * Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for files from Bitbucket v1 and v2 APIs, such - * as the one exposed by Bitbucket Cloud itself. - * - * @public - * @deprecated in favor of BitbucketCloudUrlReader and BitbucketServerUrlReader - */ -export class BitbucketUrlReader implements UrlReaderService { - static factory: ReaderFactory = ({ config, logger, treeResponseFactory }) => { - const integrations = ScmIntegrations.fromConfig(config); - return integrations.bitbucket - .list() - .filter( - item => - !integrations.bitbucketCloud.byHost(item.config.host) && - !integrations.bitbucketServer.byHost(item.config.host), - ) - .map(integration => { - const reader = new BitbucketUrlReader(integration, logger, { - treeResponseFactory, - }); - const predicate = (url: URL) => url.host === integration.config.host; - return { reader, predicate }; - }); - }; - - private readonly integration: BitbucketIntegration; - private readonly deps: { treeResponseFactory: ReadTreeResponseFactory }; - - constructor( - integration: BitbucketIntegration, - logger: LoggerService, - deps: { treeResponseFactory: ReadTreeResponseFactory }, - ) { - this.integration = integration; - this.deps = deps; - const { host, token, username, appPassword } = integration.config; - const replacement = - host === 'bitbucket.org' ? 'bitbucketCloud' : 'bitbucketServer'; - logger.warn( - `[Deprecated] Please migrate from "integrations.bitbucket" to "integrations.${replacement}".`, - ); - - if (!token && username && !appPassword) { - throw new Error( - `Bitbucket integration for '${host}' has configured a username but is missing a required appPassword.`, - ); - } - } - - async read(url: string): Promise { - const response = await this.readUrl(url); - return response.buffer(); - } - - private getCredentials = async (options?: { - token?: string; - }): Promise<{ headers: Record }> => { - if (options?.token) { - return { - headers: { - Authorization: `Bearer ${options.token}`, - }, - }; - } - - return await getBitbucketRequestOptions(this.integration.config); - }; - - async readUrl( - url: string, - options?: UrlReaderServiceReadUrlOptions, - ): Promise { - const { etag, lastModifiedAfter, signal } = options ?? {}; - const bitbucketUrl = getBitbucketFileFetchUrl(url, this.integration.config); - const requestOptions = await this.getCredentials(options); - - let response: Response; - try { - response = await fetch(bitbucketUrl.toString(), { - headers: { - ...requestOptions.headers, - ...(etag && { 'If-None-Match': etag }), - ...(lastModifiedAfter && { - 'If-Modified-Since': lastModifiedAfter.toUTCString(), - }), - }, - // TODO(freben): The signal cast is there because pre-3.x versions of - // node-fetch have a very slightly deviating AbortSignal type signature. - // The difference does not affect us in practice however. The cast can be - // removed after we support ESM for CLI dependencies and migrate to - // version 3 of node-fetch. - // https://github.com/backstage/backstage/issues/8242 - ...(signal && { signal: signal as any }), - }); - } catch (e) { - throw new Error(`Unable to read ${url}, ${e}`); - } - - if (response.status === 304) { - throw new NotModifiedError(); - } - - if (response.ok) { - return ReadUrlResponseFactory.fromResponse(response); - } - - const message = `${url} could not be read as ${bitbucketUrl}, ${response.status} ${response.statusText}`; - if (response.status === 404) { - throw new NotFoundError(message); - } - throw new Error(message); - } - - async readTree( - url: string, - options?: UrlReaderServiceReadTreeOptions, - ): Promise { - const { filepath } = parseGitUrl(url); - - const lastCommitShortHash = await this.getLastCommitShortHash(url); - if (options?.etag && options.etag === lastCommitShortHash) { - throw new NotModifiedError(); - } - - const downloadUrl = await getBitbucketDownloadUrl( - url, - this.integration.config, - ); - const archiveBitbucketResponse = await fetch( - downloadUrl, - getBitbucketRequestOptions(this.integration.config), - ); - if (!archiveBitbucketResponse.ok) { - const message = `Failed to read tree from ${url}, ${archiveBitbucketResponse.status} ${archiveBitbucketResponse.statusText}`; - if (archiveBitbucketResponse.status === 404) { - throw new NotFoundError(message); - } - throw new Error(message); - } - - return await this.deps.treeResponseFactory.fromTarArchive({ - response: archiveBitbucketResponse, - subpath: filepath, - etag: lastCommitShortHash, - filter: options?.filter, - }); - } - - async search( - url: string, - options?: UrlReaderServiceSearchOptions, - ): Promise { - const { filepath } = parseGitUrl(url); - - // If it's a direct URL we use readUrl instead - if (!filepath?.match(/[*?]/)) { - try { - const data = await this.readUrl(url, options); - - return { - files: [ - { - url: url, - content: data.buffer, - lastModifiedAt: data.lastModifiedAt, - }, - ], - etag: data.etag ?? '', - }; - } catch (error) { - assertError(error); - if (error.name === 'NotFoundError') { - return { - files: [], - etag: '', - }; - } - throw error; - } - } - - const matcher = new Minimatch(filepath); - - // TODO(freben): For now, read the entire repo and filter through that. In - // a future improvement, we could be smart and try to deduce that non-glob - // prefixes (like for filepaths such as some-prefix/**/a.yaml) can be used - // to get just that part of the repo. - const treeUrl = trimEnd(url.replace(filepath, ''), '/'); - - const tree = await this.readTree(treeUrl, { - etag: options?.etag, - filter: path => matcher.match(path), - }); - const files = await tree.files(); - - return { - etag: tree.etag, - files: files.map(file => ({ - url: this.integration.resolveUrl({ - url: `/${file.path}`, - base: url, - }), - content: file.content, - lastModifiedAt: file.lastModifiedAt, - })), - }; - } - - toString() { - const { host, token, username, appPassword } = this.integration.config; - let authed = Boolean(token); - if (!authed) { - authed = Boolean(username && appPassword); - } - return `bitbucket{host=${host},authed=${authed}}`; - } - - private async getLastCommitShortHash(url: string): Promise { - const { resource, name: repoName, owner: project, ref } = parseGitUrl(url); - - let branch = ref; - if (!branch) { - branch = await getBitbucketDefaultBranch(url, this.integration.config); - } - - const isHosted = resource === 'bitbucket.org'; - // Bitbucket Server https://docs.atlassian.com/bitbucket-server/rest/7.9.0/bitbucket-rest.html#idp222 - const commitsApiUrl = isHosted - ? `${this.integration.config.apiBaseUrl}/repositories/${project}/${repoName}/commits/${branch}` - : `${this.integration.config.apiBaseUrl}/projects/${project}/repos/${repoName}/commits`; - - const commitsResponse = await fetch( - commitsApiUrl, - getBitbucketRequestOptions(this.integration.config), - ); - if (!commitsResponse.ok) { - const message = `Failed to retrieve commits from ${commitsApiUrl}, ${commitsResponse.status} ${commitsResponse.statusText}`; - if (commitsResponse.status === 404) { - throw new NotFoundError(message); - } - throw new Error(message); - } - - const commits = await commitsResponse.json(); - if (isHosted) { - if ( - commits && - commits.values && - commits.values.length > 0 && - commits.values[0].hash - ) { - return commits.values[0].hash.substring(0, 12); - } - } else { - if ( - commits && - commits.values && - commits.values.length > 0 && - commits.values[0].id - ) { - return commits.values[0].id.substring(0, 12); - } - } - - throw new Error(`Failed to read response from ${commitsApiUrl}`); - } -} diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/UrlReaders.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/UrlReaders.ts index 229bdd4903..f04a668b0a 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/UrlReaders.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/UrlReaders.ts @@ -24,7 +24,6 @@ import { UrlReaderPredicateMux } from './UrlReaderPredicateMux'; import { AzureUrlReader } from './AzureUrlReader'; import { BitbucketCloudUrlReader } from './BitbucketCloudUrlReader'; import { BitbucketServerUrlReader } from './BitbucketServerUrlReader'; -import { BitbucketUrlReader } from './BitbucketUrlReader'; import { GerritUrlReader } from './GerritUrlReader'; import { GithubUrlReader } from './GithubUrlReader'; import { GitlabUrlReader } from './GitlabUrlReader'; @@ -92,7 +91,6 @@ export class UrlReaders { AzureUrlReader.factory, BitbucketCloudUrlReader.factory, BitbucketServerUrlReader.factory, - BitbucketUrlReader.factory, GerritUrlReader.factory, GithubUrlReader.factory, GiteaUrlReader.factory, diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/index.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/index.ts index fc33efbc3a..3f5d7a7ea5 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/index.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/index.ts @@ -16,7 +16,6 @@ export { AzureUrlReader } from './AzureUrlReader'; export { BitbucketCloudUrlReader } from './BitbucketCloudUrlReader'; -export { BitbucketUrlReader } from './BitbucketUrlReader'; export { BitbucketServerUrlReader } from './BitbucketServerUrlReader'; export { GerritUrlReader } from './GerritUrlReader'; export { GithubUrlReader } from './GithubUrlReader'; diff --git a/packages/integration-react/dev/DevPage.tsx b/packages/integration-react/dev/DevPage.tsx index d03baca1d7..1c94ef984a 100644 --- a/packages/integration-react/dev/DevPage.tsx +++ b/packages/integration-react/dev/DevPage.tsx @@ -16,7 +16,7 @@ import { ScmIntegration, ScmIntegrationsGroup } from '@backstage/integration'; import Typography from '@material-ui/core/Typography'; -import { scmIntegrationsApiRef } from '../src/ScmIntegrationsApi'; +import { scmIntegrationsApiRef } from '../src/api/ScmIntegrationsApi'; import { Content } from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; @@ -48,10 +48,6 @@ export const DevPage = () => { Azure - - Bitbucket - - Bitbucket Cloud diff --git a/packages/integration-react/dev/index.tsx b/packages/integration-react/dev/index.tsx index 65486d1f06..fbff7ef0c6 100644 --- a/packages/integration-react/dev/index.tsx +++ b/packages/integration-react/dev/index.tsx @@ -15,7 +15,7 @@ */ import { createDevApp } from '@backstage/dev-utils'; import { ScmIntegrations } from '@backstage/integration'; -import { scmIntegrationsApiRef } from '../src/ScmIntegrationsApi'; +import { scmIntegrationsApiRef } from '../src/api/ScmIntegrationsApi'; import { DevPage } from './DevPage'; import { configApiRef, createApiFactory } from '@backstage/core-plugin-api'; diff --git a/packages/integration-react/src/api/ScmIntegrationsApi.test.ts b/packages/integration-react/src/api/ScmIntegrationsApi.test.ts index 55acd29eec..0a1f1b1b8f 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(8); // The default ones + expect(i.list().length).toBe(7); // The default ones }); }); diff --git a/packages/integration/config.d.ts b/packages/integration/config.d.ts index add237a6b9..df7a3aa4af 100644 --- a/packages/integration/config.d.ts +++ b/packages/integration/config.d.ts @@ -27,27 +27,6 @@ export interface Config { * @visibility frontend */ host: string; - /** - * Token used to authenticate requests. - * @visibility secret - * @deprecated Use `credentials` instead. - */ - token?: string; - - /** - * The credential to use for requests. - * - * If no credential is specified anonymous access is used. - * - * @deepVisibility secret - * @deprecated Use `credentials` instead. - */ - credential?: { - clientId?: string; - clientSecret?: string; - tenantId?: string; - personalAccessToken?: string; - }; /** * The credentials to use for requests. If multiple credentials are specified the first one that matches the organization is used. @@ -131,43 +110,6 @@ export interface Config { }; }>; - /** - * Integration configuration for Bitbucket - * @deprecated replaced by bitbucketCloud and bitbucketServer - */ - bitbucket?: Array<{ - /** - * The hostname of the given Bitbucket instance - * @visibility frontend - */ - host: string; - /** - * Token used to authenticate requests. - * @visibility secret - */ - token?: string; - /** - * The base url for the Bitbucket API, for example https://api.bitbucket.org/2.0 - * @visibility frontend - */ - apiBaseUrl?: string; - /** - * The username to use for authenticated requests. - * @visibility secret - */ - username?: string; - /** - * Bitbucket app password used to authenticate requests. - * @visibility secret - */ - appPassword?: string; - /** - * PGP signing key for signing commits. - * @visibility secret - */ - commitSigningKey?: string; - }>; - /** Integration configuration for Bitbucket Cloud */ bitbucketCloud?: Array<{ /** diff --git a/packages/integration/report.api.md b/packages/integration/report.api.md index 83c75db4d1..df1c7e9112 100644 --- a/packages/integration/report.api.md +++ b/packages/integration/report.api.md @@ -201,8 +201,6 @@ export class AzureIntegration implements ScmIntegration { // @public export type AzureIntegrationConfig = { host: string; - token?: string; - credential?: AzureDevOpsCredential; credentials?: AzureDevOpsCredential[]; commitSigningKey?: string; }; @@ -255,37 +253,6 @@ export type BitbucketCloudIntegrationConfig = { commitSigningKey?: string; }; -// @public @deprecated -export class BitbucketIntegration implements ScmIntegration { - constructor(integrationConfig: BitbucketIntegrationConfig); - // (undocumented) - get config(): BitbucketIntegrationConfig; - // (undocumented) - static factory: ScmIntegrationsFactory; - // (undocumented) - resolveEditUrl(url: string): string; - // (undocumented) - resolveUrl(options: { - url: string; - base: string; - lineNumber?: number; - }): string; - // (undocumented) - get title(): string; - // (undocumented) - get type(): string; -} - -// @public @deprecated -export type BitbucketIntegrationConfig = { - host: string; - apiBaseUrl: string; - token?: string; - username?: string; - appPassword?: string; - commitSigningKey?: string; -}; - // @public export class BitbucketServerIntegration implements ScmIntegration { constructor(integrationConfig: BitbucketServerIntegrationConfig); @@ -317,14 +284,6 @@ export type BitbucketServerIntegrationConfig = { commitSigningKey?: string; }; -// @public @deprecated -export function buildGerritGitilesArchiveUrl( - config: GerritIntegrationConfig, - project: string, - branch: string, - filePath: string, -): string; - // @public export function buildGerritGitilesArchiveUrlFromLocation( config: GerritIntegrationConfig, @@ -426,14 +385,6 @@ export function getAzureDownloadUrl(url: string): string; // @public export function getAzureFileFetchUrl(url: string): string; -// @public @deprecated -export function getAzureRequestOptions( - config: AzureIntegrationConfig, - additionalHeaders?: Record, -): Promise<{ - headers: Record; -}>; - // @public export function getBitbucketCloudDefaultBranch( url: string, @@ -465,31 +416,6 @@ export function getBitbucketCloudRequestOptions( headers: Record; }>; -// @public @deprecated -export function getBitbucketDefaultBranch( - url: string, - config: BitbucketIntegrationConfig, -): Promise; - -// @public @deprecated -export function getBitbucketDownloadUrl( - url: string, - config: BitbucketIntegrationConfig, -): Promise; - -// @public @deprecated -export function getBitbucketFileFetchUrl( - url: string, - config: BitbucketIntegrationConfig, -): string; - -// @public @deprecated -export function getBitbucketRequestOptions( - config: BitbucketIntegrationConfig, -): { - headers: Record; -}; - // @public export function getBitbucketServerDefaultBranch( url: string, @@ -579,14 +505,6 @@ export function getGithubFileFetchUrl( credentials: GithubCredentials, ): string; -// @public @deprecated -export function getGitHubRequestOptions( - config: GithubIntegrationConfig, - credentials: GithubCredentials, -): { - headers: Record; -}; - // @public export function getGitilesAuthenticationUrl( config: GerritIntegrationConfig, @@ -854,8 +772,6 @@ export interface IntegrationsByType { azure: ScmIntegrationsGroup; // (undocumented) azureBlobStorage: ScmIntegrationsGroup; - // @deprecated (undocumented) - bitbucket: ScmIntegrationsGroup; // (undocumented) bitbucketCloud: ScmIntegrationsGroup; // (undocumented) @@ -874,16 +790,6 @@ export interface IntegrationsByType { harness: ScmIntegrationsGroup; } -// @public @deprecated -export function parseGerritGitilesUrl( - config: GerritIntegrationConfig, - url: string, -): { - branch: string; - filePath: string; - project: string; -}; - // @public export function parseGerritJsonResponse(response: Response): Promise; @@ -989,16 +895,6 @@ export function readBitbucketCloudIntegrationConfigs( configs: Config[], ): BitbucketCloudIntegrationConfig[]; -// @public @deprecated -export function readBitbucketIntegrationConfig( - config: Config, -): BitbucketIntegrationConfig; - -// @public @deprecated -export function readBitbucketIntegrationConfigs( - configs: Config[], -): BitbucketIntegrationConfig[]; - // @public export function readBitbucketServerIntegrationConfig( config: Config, @@ -1085,8 +981,6 @@ export interface ScmIntegrationRegistry azure: ScmIntegrationsGroup; // (undocumented) azureBlobStorage: ScmIntegrationsGroup; - // @deprecated (undocumented) - bitbucket: ScmIntegrationsGroup; // (undocumented) bitbucketCloud: ScmIntegrationsGroup; // (undocumented) @@ -1120,8 +1014,6 @@ export class ScmIntegrations implements ScmIntegrationRegistry { get azure(): ScmIntegrationsGroup; // (undocumented) get azureBlobStorage(): ScmIntegrationsGroup; - // @deprecated (undocumented) - get bitbucket(): ScmIntegrationsGroup; // (undocumented) get bitbucketCloud(): ScmIntegrationsGroup; // (undocumented) diff --git a/packages/integration/src/ScmIntegrations.test.ts b/packages/integration/src/ScmIntegrations.test.ts index 7f75ab44fc..254d774a80 100644 --- a/packages/integration/src/ScmIntegrations.test.ts +++ b/packages/integration/src/ScmIntegrations.test.ts @@ -21,8 +21,6 @@ import { BitbucketCloudIntegration, BitbucketCloudIntegrationConfig, } from './bitbucketCloud'; -import { BitbucketIntegrationConfig } from './bitbucket'; -import { BitbucketIntegration } from './bitbucket/BitbucketIntegration'; import { BitbucketServerIntegration, BitbucketServerIntegrationConfig, @@ -62,10 +60,6 @@ describe('ScmIntegrations', () => { host: 'azureblobstorage.local', } as AzureBlobStorageIntegrationConfig); - const bitbucket = new BitbucketIntegration({ - host: 'bitbucket.local', - } as BitbucketIntegrationConfig); - const bitbucketCloud = new BitbucketCloudIntegration({ host: 'bitbucket.org', } as BitbucketCloudIntegrationConfig); @@ -103,7 +97,6 @@ describe('ScmIntegrations', () => { awsCodeCommit: basicIntegrations([awsCodeCommit], item => item.config.host), azure: basicIntegrations([azure], item => item.config.host), azureBlobStorage: basicIntegrations([azureBlob], item => item.config.host), - bitbucket: basicIntegrations([bitbucket], item => item.config.host), bitbucketCloud: basicIntegrations([bitbucketCloud], item => item.title), bitbucketServer: basicIntegrations( [bitbucketServer], @@ -126,7 +119,6 @@ describe('ScmIntegrations', () => { expect(i.azureBlobStorage.byUrl('https://azureblobstorage.local')).toBe( azureBlob, ); - expect(i.bitbucket.byUrl('https://bitbucket.local')).toBe(bitbucket); expect(i.bitbucketCloud.byUrl('https://bitbucket.org')).toBe( bitbucketCloud, ); @@ -147,7 +139,6 @@ describe('ScmIntegrations', () => { awsCodeCommit, azure, azureBlob, - bitbucket, bitbucketCloud, bitbucketServer, gerrit, @@ -166,7 +157,6 @@ describe('ScmIntegrations', () => { expect(i.azureBlobStorage.byUrl('https://azureblobstorage.local')).toBe( azureBlob, ); - expect(i.byUrl('https://bitbucket.local')).toBe(bitbucket); expect(i.byUrl('https://bitbucket.org')).toBe(bitbucketCloud); expect(i.byUrl('https://bitbucket-server.local')).toBe(bitbucketServer); expect(i.byUrl('https://gerrit.local')).toBe(gerrit); @@ -179,7 +169,6 @@ describe('ScmIntegrations', () => { expect(i.byHost('awscodecommit.local')).toBe(awsCodeCommit); expect(i.byHost('azure.local')).toBe(azure); expect(i.byHost('azureblobstorage.local')).toBe(azureBlob); - expect(i.byHost('bitbucket.local')).toBe(bitbucket); expect(i.byHost('bitbucket.org')).toBe(bitbucketCloud); expect(i.byHost('bitbucket-server.local')).toBe(bitbucketServer); expect(i.byHost('gerrit.local')).toBe(gerrit); diff --git a/packages/integration/src/ScmIntegrations.ts b/packages/integration/src/ScmIntegrations.ts index 573975da0e..26a278fdbf 100644 --- a/packages/integration/src/ScmIntegrations.ts +++ b/packages/integration/src/ScmIntegrations.ts @@ -19,7 +19,6 @@ import { AwsS3Integration } from './awsS3/AwsS3Integration'; import { AwsCodeCommitIntegration } from './awsCodeCommit/AwsCodeCommitIntegration'; import { AzureIntegration } from './azure/AzureIntegration'; import { BitbucketCloudIntegration } from './bitbucketCloud/BitbucketCloudIntegration'; -import { BitbucketIntegration } from './bitbucket/BitbucketIntegration'; import { BitbucketServerIntegration } from './bitbucketServer/BitbucketServerIntegration'; import { GerritIntegration } from './gerrit/GerritIntegration'; import { GithubIntegration } from './github/GithubIntegration'; @@ -42,10 +41,6 @@ export interface IntegrationsByType { awsCodeCommit: ScmIntegrationsGroup; azureBlobStorage: ScmIntegrationsGroup; azure: ScmIntegrationsGroup; - /** - * @deprecated in favor of `bitbucketCloud` and `bitbucketServer` - */ - bitbucket: ScmIntegrationsGroup; bitbucketCloud: ScmIntegrationsGroup; bitbucketServer: ScmIntegrationsGroup; gerrit: ScmIntegrationsGroup; @@ -70,7 +65,6 @@ export class ScmIntegrations implements ScmIntegrationRegistry { awsCodeCommit: AwsCodeCommitIntegration.factory({ config }), azureBlobStorage: AzureBlobStorageIntergation.factory({ config }), azure: AzureIntegration.factory({ config }), - bitbucket: BitbucketIntegration.factory({ config }), bitbucketCloud: BitbucketCloudIntegration.factory({ config }), bitbucketServer: BitbucketServerIntegration.factory({ config }), gerrit: GerritIntegration.factory({ config }), @@ -102,13 +96,6 @@ export class ScmIntegrations implements ScmIntegrationRegistry { return this.byType.azure; } - /** - * @deprecated in favor of `bitbucketCloud()` and `bitbucketServer()` - */ - get bitbucket(): ScmIntegrationsGroup { - return this.byType.bitbucket; - } - get bitbucketCloud(): ScmIntegrationsGroup { return this.byType.bitbucketCloud; } @@ -148,20 +135,10 @@ export class ScmIntegrations implements ScmIntegrationRegistry { } byUrl(url: string | URL): ScmIntegration | undefined { - let candidates = Object.values(this.byType) + const candidates = Object.values(this.byType) .map(i => i.byUrl(url)) .filter(Boolean); - // Do not return deprecated integrations if there are other options - if (candidates.length > 1) { - const filteredCandidates = candidates.filter( - x => !(x instanceof BitbucketIntegration), - ); - if (filteredCandidates.length !== 0) { - candidates = filteredCandidates; - } - } - return candidates[0]; } diff --git a/packages/integration/src/azure/config.test.ts b/packages/integration/src/azure/config.test.ts index c1ddf1590f..cd2d916837 100644 --- a/packages/integration/src/azure/config.test.ts +++ b/packages/integration/src/azure/config.test.ts @@ -276,50 +276,6 @@ describe('readAzureIntegrationConfig', () => { expect(output).toEqual({ host: 'dev.azure.com' }); }); - it('maps deprecated token to credentials', () => { - const output = readAzureIntegrationConfig( - buildConfig({ - host: 'dev.azure.com', - token: 't', - }), - ); - - expect(output).toEqual({ - host: 'dev.azure.com', - credentials: [ - { - kind: 'PersonalAccessToken', - personalAccessToken: 't', - }, - ], - }); - }); - - it('maps deprecated credential to credentials', () => { - const output = readAzureIntegrationConfig( - buildConfig({ - host: 'dev.azure.com', - credential: { - clientId: 'id', - clientSecret: 'secret', - tenantId: 'tenantId', - }, - }), - ); - - expect(output).toEqual({ - host: 'dev.azure.com', - credentials: [ - { - kind: 'ClientSecret', - clientId: 'id', - clientSecret: 'secret', - tenantId: 'tenantId', - }, - ], - }); - }); - it('rejects config when host is not valid', () => { expect(() => readAzureIntegrationConfig(buildConfig({ ...valid, host: 7 })), diff --git a/packages/integration/src/azure/config.ts b/packages/integration/src/azure/config.ts index 09b97755ec..0213475cc8 100644 --- a/packages/integration/src/azure/config.ts +++ b/packages/integration/src/azure/config.ts @@ -32,24 +32,6 @@ export type AzureIntegrationConfig = { */ host: string; - /** - * The authorization token to use for requests. - * - * If no token is specified, anonymous access is used. - * - * @deprecated Use `credentials` instead. - */ - token?: string; - - /** - * The credential to use for requests. - * - * If no credential is specified anonymous access is used. - * - * @deprecated Use `credentials` instead. - */ - credential?: AzureDevOpsCredential; - /** * The credentials to use for requests. If multiple credentials are specified the first one that matches the organization is used. * If not organization matches the first credential without an organization is used. diff --git a/packages/integration/src/azure/deprecated.test.ts b/packages/integration/src/azure/deprecated.test.ts deleted file mode 100644 index 4411ef5f2f..0000000000 --- a/packages/integration/src/azure/deprecated.test.ts +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2023 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { getAzureRequestOptions } from './deprecated'; -import { DateTime } from 'luxon'; -import { - AccessToken, - ClientSecretCredential, - ManagedIdentityCredential, -} from '@azure/identity'; - -jest.mock('@azure/identity'); - -const MockedClientSecretCredential = ClientSecretCredential as jest.MockedClass< - typeof ClientSecretCredential ->; - -const MockedManagedIdentityCredential = - ManagedIdentityCredential as jest.MockedClass< - typeof ManagedIdentityCredential - >; - -describe('azure core', () => { - beforeEach(() => { - jest.resetAllMocks(); - - MockedClientSecretCredential.prototype.getToken.mockImplementation(() => - Promise.resolve({ - expiresOnTimestamp: DateTime.local().plus({ days: 1 }).toSeconds(), - token: 'fake-client-secret-token', - } as AccessToken), - ); - MockedManagedIdentityCredential.prototype.getToken.mockImplementation(() => - Promise.resolve({ - expiresOnTimestamp: DateTime.local().plus({ days: 1 }).toSeconds(), - token: 'fake-managed-identity-token', - } as AccessToken), - ); - }); - - describe('getAzureRequestOptions', () => { - it('should not add authorization header when not using token or credential', async () => { - expect(await getAzureRequestOptions({ host: '' })).toEqual( - expect.objectContaining({ - headers: expect.not.objectContaining({ - Authorization: expect.anything(), - }), - }), - ); - }); - - it('should add authorization header when using a personal access token', async () => { - const pat = '0123456789'; - const encoded = Buffer.from(`:${pat}`).toString('base64'); - expect( - await getAzureRequestOptions({ - host: '', - credentials: [ - { - kind: 'PersonalAccessToken', - personalAccessToken: pat, - }, - ], - }), - ).toEqual( - expect.objectContaining({ - headers: expect.objectContaining({ - Authorization: `Basic ${encoded}`, - }), - }), - ); - }); - - it('should add authorization header when using a client secret', async () => { - expect( - await getAzureRequestOptions({ - host: '', - credentials: [ - { - kind: 'ClientSecret', - clientId: 'fake-id', - clientSecret: 'fake-secret', - tenantId: 'fake-tenant', - }, - ], - }), - ).toEqual( - expect.objectContaining({ - headers: expect.objectContaining({ - Authorization: 'Bearer fake-client-secret-token', - }), - }), - ); - }); - - it('should add authorization header when using a managed identity', async () => { - expect( - await getAzureRequestOptions({ - host: '', - credentials: [ - { - kind: 'ManagedIdentity', - clientId: 'fake-id', - }, - ], - }), - ).toEqual( - expect.objectContaining({ - headers: expect.objectContaining({ - Authorization: 'Bearer fake-managed-identity-token', - }), - }), - ); - }); - }); -}); diff --git a/packages/integration/src/azure/deprecated.ts b/packages/integration/src/azure/deprecated.ts deleted file mode 100644 index fd19f3dc14..0000000000 --- a/packages/integration/src/azure/deprecated.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2023 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { AzureIntegrationConfig } from './config'; -import { CachedAzureDevOpsCredentialsProvider } from './CachedAzureDevOpsCredentialsProvider'; - -/** - * Gets the request options necessary to make requests to a given provider. - * - * @param config - The relevant provider config - * @param additionalHeaders - Additional headers for the request - * @public - * @deprecated Use {@link AzureDevOpsCredentialsProvider} instead. - */ -export async function getAzureRequestOptions( - config: AzureIntegrationConfig, - additionalHeaders?: Record, -): Promise<{ headers: Record }> { - const headers: Record = additionalHeaders - ? { ...additionalHeaders } - : {}; - - /* - * Since we do not have a way to determine which organization the request is for, - * we will use the first credential that does not have an organization specified. - */ - const credentialConfig = config.credentials?.filter( - credential => - credential.organizations === undefined || - credential.organizations.length === 0, - )[0]; - - if (credentialConfig) { - const credentialsProvider = - CachedAzureDevOpsCredentialsProvider.fromAzureDevOpsCredential( - credentialConfig, - ); - const credentials = await credentialsProvider.getCredentials(); - - return { - headers: { - ...credentials?.headers, - ...headers, - }, - }; - } - - return { headers }; -} diff --git a/packages/integration/src/azure/index.ts b/packages/integration/src/azure/index.ts index a447c8ffd8..b04ead862f 100644 --- a/packages/integration/src/azure/index.ts +++ b/packages/integration/src/azure/index.ts @@ -38,5 +38,3 @@ export { export * from './types'; export { DefaultAzureDevOpsCredentialsProvider } from './DefaultAzureDevOpsCredentialsProvider'; - -export * from './deprecated'; diff --git a/packages/integration/src/bitbucket/BitbucketIntegration.test.ts b/packages/integration/src/bitbucket/BitbucketIntegration.test.ts deleted file mode 100644 index 575e1c9b6f..0000000000 --- a/packages/integration/src/bitbucket/BitbucketIntegration.test.ts +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { ConfigReader } from '@backstage/config'; -import { BitbucketIntegration } from './BitbucketIntegration'; - -describe('BitbucketIntegration', () => { - describe('factory', () => { - it('works', () => { - const integrations = BitbucketIntegration.factory({ - config: new ConfigReader({ - integrations: { - bitbucket: [ - { - host: 'h.com', - apiBaseUrl: 'a', - token: 't', - username: 'u', - appPassword: 'p', - }, - ], - }, - }), - }); - expect(integrations.list().length).toBe(2); // including default - expect(integrations.list()[0].config.host).toBe('h.com'); - expect(integrations.list()[1].config.host).toBe('bitbucket.org'); - }); - - it('falls back to bitbucketCloud+bitbucketServer', () => { - const integrations = BitbucketIntegration.factory({ - config: new ConfigReader({ - integrations: { - bitbucketCloud: [ - { - username: 'u', - appPassword: 'p', - }, - ], - bitbucketServer: [ - { - host: 'h.com', - apiBaseUrl: 'a', - token: 't', - }, - ], - }, - }), - }); - expect(integrations.list().length).toBe(2); // including default - expect(integrations.list()[0].config.host).toBe('bitbucket.org'); - expect(integrations.list()[1].config.host).toBe('h.com'); - }); - }); - - it('returns the basics', () => { - const integration = new BitbucketIntegration({ host: 'h.com' } as any); - expect(integration.type).toBe('bitbucket'); - expect(integration.title).toBe('h.com'); - }); - - it('resolves url line number correctly for Bitbucket Cloud', () => { - const integration = new BitbucketIntegration({ - host: 'bitbucket.org', - } as any); - - expect( - integration.resolveUrl({ - url: './a.yaml', - base: 'https://bitbucket.org/my-owner/my-project/src/master/README.md', - lineNumber: 14, - }), - ).toBe( - 'https://bitbucket.org/my-owner/my-project/src/master/a.yaml#lines-14', - ); - }); - - it('resolves url line number correctly for Bitbucket Server', () => { - const integration = new BitbucketIntegration({ host: 'h.com' } as any); - - expect( - integration.resolveUrl({ - url: './a.yaml', - base: 'https://bitbucket.org/my-owner/my-project/src/master/README.md', - lineNumber: 14, - }), - ).toBe('https://bitbucket.org/my-owner/my-project/src/master/a.yaml#14'); - }); - - it('resolve edit URL', () => { - const integration = new BitbucketIntegration({ host: 'h.com' } as any); - - expect( - integration.resolveEditUrl( - 'https://bitbucket.org/my-owner/my-project/src/master/README.md', - ), - ).toBe( - 'https://bitbucket.org/my-owner/my-project/src/master/README.md?mode=edit&spa=0&at=master', - ); - }); -}); diff --git a/packages/integration/src/bitbucket/BitbucketIntegration.ts b/packages/integration/src/bitbucket/BitbucketIntegration.ts deleted file mode 100644 index d92532b54a..0000000000 --- a/packages/integration/src/bitbucket/BitbucketIntegration.ts +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import parseGitUrl from 'git-url-parse'; -import { basicIntegrations, defaultScmResolveUrl } from '../helpers'; -import { ScmIntegration, ScmIntegrationsFactory } from '../types'; -import { - BitbucketIntegrationConfig, - readBitbucketIntegrationConfigs, -} from './config'; - -/** - * A Bitbucket based integration. - * - * @public - * @deprecated replaced by the integrations bitbucketCloud and bitbucketServer. - */ -export class BitbucketIntegration implements ScmIntegration { - static factory: ScmIntegrationsFactory = ({ - config, - }) => { - const configs = readBitbucketIntegrationConfigs( - config.getOptionalConfigArray('integrations.bitbucket') ?? [ - // if integrations.bitbucket was not used assume the use was migrated to the new configs - // and backport for the deprecated integration to be usable for other parts of the system - // until these got migrated - ...(config.getOptionalConfigArray('integrations.bitbucketCloud') ?? []), - ...(config.getOptionalConfigArray('integrations.bitbucketServer') ?? - []), - ], - ); - return basicIntegrations( - configs.map(c => new BitbucketIntegration(c)), - i => i.config.host, - ); - }; - - constructor(private readonly integrationConfig: BitbucketIntegrationConfig) {} - - get type(): string { - return 'bitbucket'; - } - - get title(): string { - return this.integrationConfig.host; - } - - get config(): BitbucketIntegrationConfig { - return this.integrationConfig; - } - - resolveUrl(options: { - url: string; - base: string; - lineNumber?: number; - }): string { - const resolved = defaultScmResolveUrl(options); - if (!options.lineNumber) { - return resolved; - } - - const url = new URL(resolved); - - if (this.integrationConfig.host === 'bitbucket.org') { - // Bitbucket Cloud uses the syntax #lines-{start}[:{end}][,...] - url.hash = `lines-${options.lineNumber}`; - } else { - // Bitbucket Server uses the syntax #{start}[-{end}][,...] - url.hash = `${options.lineNumber}`; - } - - return url.toString(); - } - - resolveEditUrl(url: string): string { - const urlData = parseGitUrl(url); - const editUrl = new URL(url); - - editUrl.searchParams.set('mode', 'edit'); - // TODO: Not sure what spa=0 does, at least bitbucket.org doesn't support it - // but this is taken over from the initial implementation. - editUrl.searchParams.set('spa', '0'); - editUrl.searchParams.set('at', urlData.ref); - return editUrl.toString(); - } -} diff --git a/packages/integration/src/bitbucket/config.test.ts b/packages/integration/src/bitbucket/config.test.ts deleted file mode 100644 index 8dd20cade7..0000000000 --- a/packages/integration/src/bitbucket/config.test.ts +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Config, ConfigReader } from '@backstage/config'; -import { loadConfigSchema } from '@backstage/config-loader'; -import { - BitbucketIntegrationConfig, - readBitbucketIntegrationConfig, - readBitbucketIntegrationConfigs, -} from './config'; - -describe('readBitbucketIntegrationConfig', () => { - function buildConfig(data: Partial): Config { - return new ConfigReader(data); - } - - async function buildFrontendConfig( - data: Partial, - ): Promise { - const fullSchema = await loadConfigSchema({ - dependencies: ['@backstage/integration'], - }); - const serializedSchema = fullSchema.serialize() as { - schemas: { value: { properties?: { integrations?: object } } }[]; - }; - const schema = await loadConfigSchema({ - serialized: { - ...serializedSchema, // only include schemas that apply to integrations - schemas: serializedSchema.schemas.filter( - s => s.value?.properties?.integrations, - ), - }, - }); - const processed = schema.process( - [{ data: { integrations: { bitbucket: [data] } }, context: 'app' }], - { visibility: ['frontend'] }, - ); - return new ConfigReader( - (processed[0].data as any).integrations.bitbucket[0], - ); - } - - it('reads all values', () => { - const output = readBitbucketIntegrationConfig( - buildConfig({ - host: 'a.com', - apiBaseUrl: 'https://a.com/api', - token: 't\n\n\n', - username: 'u', - appPassword: '\n\n\np', - }), - ); - expect(output).toEqual({ - host: 'a.com', - apiBaseUrl: 'https://a.com/api', - token: 't', - username: 'u', - appPassword: 'p', - }); - }); - - it('inserts the defaults if missing', () => { - const output = readBitbucketIntegrationConfig(buildConfig({})); - expect(output).toEqual( - expect.objectContaining({ - host: 'bitbucket.org', - apiBaseUrl: 'https://api.bitbucket.org/2.0', - }), - ); - }); - - it('rejects funky configs', () => { - const valid: any = { - host: 'a.com', - apiBaseUrl: 'https://a.com/api', - token: 't', - username: 'u', - appPassword: 'p', - }; - expect(() => - readBitbucketIntegrationConfig(buildConfig({ ...valid, host: 7 })), - ).toThrow(/host/); - expect(() => - readBitbucketIntegrationConfig(buildConfig({ ...valid, apiBaseUrl: 7 })), - ).toThrow(/apiBaseUrl/); - expect(() => - readBitbucketIntegrationConfig(buildConfig({ ...valid, token: 7 })), - ).toThrow(/token/); - expect(() => - readBitbucketIntegrationConfig(buildConfig({ ...valid, username: 7 })), - ).toThrow(/username/); - expect(() => - readBitbucketIntegrationConfig(buildConfig({ ...valid, appPassword: 7 })), - ).toThrow(/appPassword/); - }); - - it('works on the frontend', async () => { - expect( - readBitbucketIntegrationConfig( - await buildFrontendConfig({ - host: 'a.com', - apiBaseUrl: 'https://a.com/api', - token: 't', - username: 'u', - appPassword: 'p', - }), - ), - ).toEqual({ - host: 'a.com', - apiBaseUrl: 'https://a.com/api', - }); - }); -}); - -describe('readBitbucketIntegrationConfigs', () => { - function buildConfig(data: Partial[]): Config[] { - return data.map(item => new ConfigReader(item)); - } - - it('reads all values', () => { - const output = readBitbucketIntegrationConfigs( - buildConfig([ - { - host: 'a.com', - apiBaseUrl: 'https://a.com/api', - token: 't', - username: 'u', - appPassword: 'p', - }, - ]), - ); - expect(output).toContainEqual({ - host: 'a.com', - apiBaseUrl: 'https://a.com/api', - token: 't', - username: 'u', - appPassword: 'p', - }); - }); - - it('adds a default Bitbucket Cloud entry when missing', () => { - const output = readBitbucketIntegrationConfigs(buildConfig([])); - expect(output).toEqual([ - { - host: 'bitbucket.org', - apiBaseUrl: 'https://api.bitbucket.org/2.0', - }, - ]); - }); - - it('injects the correct Bitbucket Cloud API base URL when missing', () => { - const output = readBitbucketIntegrationConfigs( - buildConfig([{ host: 'bitbucket.org' }]), - ); - expect(output).toEqual([ - { - host: 'bitbucket.org', - apiBaseUrl: 'https://api.bitbucket.org/2.0', - }, - ]); - }); -}); diff --git a/packages/integration/src/bitbucket/config.ts b/packages/integration/src/bitbucket/config.ts deleted file mode 100644 index 6939034e7d..0000000000 --- a/packages/integration/src/bitbucket/config.ts +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Config } from '@backstage/config'; -import { trimEnd } from 'lodash'; -import { isValidHost } from '../helpers'; - -const BITBUCKET_HOST = 'bitbucket.org'; -const BITBUCKET_API_BASE_URL = 'https://api.bitbucket.org/2.0'; - -/** - * The configuration parameters for a single Bitbucket API provider. - * - * @public - * @deprecated bitbucket integration replaced by integrations bitbucketCloud and bitbucketServer. - */ -export type BitbucketIntegrationConfig = { - /** - * The host of the target that this matches on, e.g. "bitbucket.org" - */ - host: string; - - /** - * The base URL of the API of this provider, e.g. "https://api.bitbucket.org/2.0", - * with no trailing slash. - * - * Values omitted at the optional property at the app-config will be deduced - * from the "host" value. - */ - apiBaseUrl: string; - - /** - * The authorization token to use for requests to a Bitbucket Server provider. - * - * See https://confluence.atlassian.com/bitbucketserver/personal-access-tokens-939515499.html - * - * If no token is specified, anonymous access is used. - */ - token?: string; - - /** - * The username to use for requests to Bitbucket Cloud (bitbucket.org). - */ - username?: string; - - /** - * Authentication with Bitbucket Cloud (bitbucket.org) is done using app passwords. - * - * See https://support.atlassian.com/bitbucket-cloud/docs/app-passwords/ - */ - appPassword?: string; - - /** - * Signing key for commits - */ - commitSigningKey?: string; -}; - -/** - * Reads a single Bitbucket integration config. - * - * @param config - The config object of a single integration - * @public - * @deprecated bitbucket integration replaced by integrations bitbucketCloud and bitbucketServer. - */ -export function readBitbucketIntegrationConfig( - config: Config, -): BitbucketIntegrationConfig { - const host = config.getOptionalString('host') ?? BITBUCKET_HOST; - let apiBaseUrl = config.getOptionalString('apiBaseUrl'); - const token = config.getOptionalString('token')?.trim(); - const username = config.getOptionalString('username'); - const appPassword = config.getOptionalString('appPassword')?.trim(); - - if (!isValidHost(host)) { - throw new Error( - `Invalid Bitbucket integration config, '${host}' is not a valid host`, - ); - } - - if (apiBaseUrl) { - apiBaseUrl = trimEnd(apiBaseUrl, '/'); - } else if (host === BITBUCKET_HOST) { - apiBaseUrl = BITBUCKET_API_BASE_URL; - } else { - apiBaseUrl = `https://${host}/rest/api/1.0`; - } - - return { - host, - apiBaseUrl, - token, - username, - appPassword, - commitSigningKey: config.getOptionalString('commitSigningKey'), - }; -} - -/** - * Reads a set of Bitbucket integration configs, and inserts some defaults for - * public Bitbucket if not specified. - * - * @param configs - All of the integration config objects - * @public - * @deprecated bitbucket integration replaced by integrations bitbucketCloud and bitbucketServer. - */ -export function readBitbucketIntegrationConfigs( - configs: Config[], -): BitbucketIntegrationConfig[] { - // First read all the explicit integrations - const result = configs.map(readBitbucketIntegrationConfig); - - // If no explicit bitbucket.org integration was added, put one in the list as - // a convenience - if (!result.some(c => c.host === BITBUCKET_HOST)) { - result.push({ - host: BITBUCKET_HOST, - apiBaseUrl: BITBUCKET_API_BASE_URL, - }); - } - - return result; -} diff --git a/packages/integration/src/bitbucket/core.test.ts b/packages/integration/src/bitbucket/core.test.ts deleted file mode 100644 index f1b4e04f15..0000000000 --- a/packages/integration/src/bitbucket/core.test.ts +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { rest } from 'msw'; -import { setupServer } from 'msw/node'; -import { registerMswTestHooks } from '../helpers'; -import { BitbucketIntegrationConfig } from './config'; -import { - getBitbucketDefaultBranch, - getBitbucketDownloadUrl, - getBitbucketFileFetchUrl, - getBitbucketRequestOptions, -} from './core'; - -describe('bitbucket core', () => { - const worker = setupServer(); - registerMswTestHooks(worker); - - describe('getBitbucketRequestOptions', () => { - it('inserts a token when needed', () => { - const withToken: BitbucketIntegrationConfig = { - host: '', - apiBaseUrl: '', - token: 'A', - }; - const withoutToken: BitbucketIntegrationConfig = { - host: '', - apiBaseUrl: '', - }; - expect( - (getBitbucketRequestOptions(withToken).headers as any).Authorization, - ).toEqual('Bearer A'); - expect( - (getBitbucketRequestOptions(withoutToken).headers as any).Authorization, - ).toBeUndefined(); - }); - - it('insert basic auth when needed', () => { - const withUsernameAndPassword: BitbucketIntegrationConfig = { - host: '', - apiBaseUrl: '', - username: 'some-user', - appPassword: 'my-secret', - }; - const withoutUsernameAndPassword: BitbucketIntegrationConfig = { - host: '', - apiBaseUrl: '', - }; - expect( - (getBitbucketRequestOptions(withUsernameAndPassword).headers as any) - .Authorization, - ).toEqual('Basic c29tZS11c2VyOm15LXNlY3JldA=='); - expect( - (getBitbucketRequestOptions(withoutUsernameAndPassword).headers as any) - .Authorization, - ).toBeUndefined(); - }); - }); - - describe('getBitbucketFileFetchUrl', () => { - it('rejects targets that do not look like URLs', () => { - const config: BitbucketIntegrationConfig = { host: '', apiBaseUrl: '' }; - expect(() => getBitbucketFileFetchUrl('a/b', config)).toThrow( - /Incorrect URL: a\/b/, - ); - }); - - it('happy path for Bitbucket Cloud', () => { - const config: BitbucketIntegrationConfig = { - host: 'bitbucket.org', - apiBaseUrl: 'https://api.bitbucket.org/2.0', - }; - expect( - getBitbucketFileFetchUrl( - 'https://bitbucket.org/org-name/repo-name/src/master/templates/my-template.yaml', - config, - ), - ).toEqual( - 'https://api.bitbucket.org/2.0/repositories/org-name/repo-name/src/master/templates/my-template.yaml', - ); - }); - - it('happy path for Bitbucket Server', () => { - const config: BitbucketIntegrationConfig = { - host: 'bitbucket.mycompany.net', - apiBaseUrl: 'https://bitbucket.mycompany.net/rest/api/1.0', - }; - expect( - getBitbucketFileFetchUrl( - 'https://bitbucket.mycompany.net/projects/a/repos/b/browse/path/to/c.yaml', - config, - ), - ).toEqual( - 'https://bitbucket.mycompany.net/rest/api/1.0/projects/a/repos/b/raw/path/to/c.yaml?at=', - ); - }); - }); - - describe('getBitbucketDownloadUrl', () => { - it('add path param if a path is specified for Bitbucket Server', async () => { - const defaultBranchResponse = { - displayId: 'main', - }; - worker.use( - rest.get( - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/default-branch', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json(defaultBranchResponse), - ), - ), - ); - - const config: BitbucketIntegrationConfig = { - host: 'bitbucket.mycompany.net', - apiBaseUrl: 'https://api.bitbucket.mycompany.net/rest/api/1.0', - }; - const result = await getBitbucketDownloadUrl( - 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/docs', - config, - ); - expect(result).toEqual( - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/archive?format=tgz&at=main&prefix=backstage-mock&path=docs', - ); - }); - - it('does not double encode the filepath', async () => { - const config: BitbucketIntegrationConfig = { - host: 'bitbucket.mycompany.net', - apiBaseUrl: 'https://api.bitbucket.mycompany.net/rest/api/1.0', - }; - const result = await getBitbucketDownloadUrl( - 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/%2Fdocs?at=some-branch', - config, - ); - expect(result).toEqual( - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/archive?format=tgz&at=some-branch&prefix=backstage-mock&path=%2Fdocs', - ); - }); - - it('do not add path param if no path is specified for Bitbucket Server', async () => { - const defaultBranchResponse = { - displayId: 'main', - }; - worker.use( - rest.get( - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/default-branch', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json(defaultBranchResponse), - ), - ), - ); - const config: BitbucketIntegrationConfig = { - host: 'bitbucket.mycompany.net', - apiBaseUrl: 'https://api.bitbucket.mycompany.net/rest/api/1.0', - }; - const result = await getBitbucketDownloadUrl( - 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse', - config, - ); - - expect(result).toEqual( - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/archive?format=tgz&at=main&prefix=backstage-mock', - ); - }); - - it('get by branch for Bitbucket Server', async () => { - const config: BitbucketIntegrationConfig = { - host: 'bitbucket.mycompany.net', - apiBaseUrl: 'https://api.bitbucket.mycompany.net/rest/api/1.0', - }; - const result = await getBitbucketDownloadUrl( - 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/docs?at=some-branch', - config, - ); - expect(result).toEqual( - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/archive?format=tgz&at=some-branch&prefix=backstage-mock&path=docs', - ); - }); - - it('do not add path param for Bitbucket Cloud', async () => { - const config: BitbucketIntegrationConfig = { - host: 'bitbucket.org', - apiBaseUrl: 'https://api.bitbucket.org/2.0', - }; - const result = await getBitbucketDownloadUrl( - 'https://bitbucket.org/backstage/mock/src/master', - config, - ); - expect(result).toEqual( - 'https://bitbucket.org/backstage/mock/get/master.tar.gz', - ); - }); - }); - - describe('getBitbucketDefaultBranch', () => { - it('return default branch for Bitbucket Cloud', async () => { - const repoInfoResponse = { - mainbranch: { - name: 'main', - }, - }; - worker.use( - rest.get( - 'https://api.bitbucket.org/2.0/repositories/backstage/mock', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json(repoInfoResponse), - ), - ), - ); - const config: BitbucketIntegrationConfig = { - host: 'bitbucket.org', - apiBaseUrl: 'https://api.bitbucket.org/2.0', - }; - const defaultBranch = await getBitbucketDefaultBranch( - 'https://bitbucket.org/backstage/mock/src/main', - config, - ); - expect(defaultBranch).toEqual('main'); - }); - - it('return default branch for Bitbucket Server', async () => { - const defaultBranchResponse = { - displayId: 'main', - }; - worker.use( - rest.get( - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/default-branch', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json(defaultBranchResponse), - ), - ), - ); - const config: BitbucketIntegrationConfig = { - host: 'bitbucket.mycompany.net', - apiBaseUrl: 'https://api.bitbucket.mycompany.net/rest/api/1.0', - }; - const defaultBranch = await getBitbucketDefaultBranch( - 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/README.md', - config, - ); - expect(defaultBranch).toEqual('main'); - }); - - it('return default branch for Bitbucket Server for bitbucket version 5.11', async () => { - const defaultBranchResponse = { - displayId: 'main', - }; - worker.use( - rest.get( - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/default-branch', - (_, res, ctx) => - res( - ctx.status(404), - ctx.set('Content-Type', 'application/json'), - ctx.json(defaultBranchResponse), - ), - ), - rest.get( - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/branches/default', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json(defaultBranchResponse), - ), - ), - ); - const config: BitbucketIntegrationConfig = { - host: 'bitbucket.mycompany.net', - apiBaseUrl: 'https://api.bitbucket.mycompany.net/rest/api/1.0', - }; - const defaultBranch = await getBitbucketDefaultBranch( - 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse/README.md', - config, - ); - expect(defaultBranch).toEqual('main'); - }); - }); -}); diff --git a/packages/integration/src/bitbucket/core.ts b/packages/integration/src/bitbucket/core.ts deleted file mode 100644 index 5c5533155d..0000000000 --- a/packages/integration/src/bitbucket/core.ts +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import fetch from 'cross-fetch'; -import parseGitUrl from 'git-url-parse'; -import { BitbucketIntegrationConfig } from './config'; - -/** - * Given a URL pointing to a path on a provider, returns the default branch. - * - * @param url - A URL pointing to a path - * @param config - The relevant provider config - * @public - * @deprecated no longer in use, bitbucket integration replaced by integrations bitbucketCloud and bitbucketServer. - */ -export async function getBitbucketDefaultBranch( - url: string, - config: BitbucketIntegrationConfig, -): Promise { - const { name: repoName, owner: project, resource } = parseGitUrl(url); - - const isHosted = resource === 'bitbucket.org'; - // Bitbucket Server https://docs.atlassian.com/bitbucket-server/rest/7.9.0/bitbucket-rest.html#idp184 - let branchUrl = isHosted - ? `${config.apiBaseUrl}/repositories/${project}/${repoName}` - : `${config.apiBaseUrl}/projects/${project}/repos/${repoName}/default-branch`; - - let response = await fetch(branchUrl, getBitbucketRequestOptions(config)); - - if (response.status === 404 && !isHosted) { - // First try the new format, and then if it gets specifically a 404 it should try the old format - // (to support old Atlassian Bitbucket v5.11.1 format ) - branchUrl = `${config.apiBaseUrl}/projects/${project}/repos/${repoName}/branches/default`; - response = await fetch(branchUrl, getBitbucketRequestOptions(config)); - } - - if (!response.ok) { - const message = `Failed to retrieve default branch from ${branchUrl}, ${response.status} ${response.statusText}`; - throw new Error(message); - } - - let defaultBranch; - if (isHosted) { - const repoInfo = await response.json(); - defaultBranch = repoInfo.mainbranch.name; - } else { - const { displayId } = await response.json(); - defaultBranch = displayId; - } - if (!defaultBranch) { - throw new Error( - `Failed to read default branch from ${branchUrl}. ` + - `Response ${response.status} ${response.json()}`, - ); - } - return defaultBranch; -} - -/** - * Given a URL pointing to a path on a provider, returns a URL that is suitable - * for downloading the subtree. - * - * @param url - A URL pointing to a path - * @param config - The relevant provider config - * @public - * @deprecated no longer in use, bitbucket integration replaced by integrations bitbucketCloud and bitbucketServer. - */ -export async function getBitbucketDownloadUrl( - url: string, - config: BitbucketIntegrationConfig, -): Promise { - const { - name: repoName, - owner: project, - ref, - protocol, - resource, - filepath, - } = parseGitUrl(url); - - const isHosted = resource === 'bitbucket.org'; - - let branch = ref; - if (!branch) { - branch = await getBitbucketDefaultBranch(url, config); - } - // path will limit the downloaded content - // /docs will only download the docs folder and everything below it - // /docs/index.md will download the docs folder and everything below it - const path = filepath - ? `&path=${encodeURIComponent(decodeURIComponent(filepath))}` - : ''; - const archiveUrl = isHosted - ? `${protocol}://${resource}/${project}/${repoName}/get/${branch}.tar.gz` - : `${config.apiBaseUrl}/projects/${project}/repos/${repoName}/archive?format=tgz&at=${branch}&prefix=${project}-${repoName}${path}`; - - return archiveUrl; -} - -/** - * Given a URL pointing to a file on a provider, returns a URL that is suitable - * for fetching the contents of the data. - * - * @remarks - * - * Converts - * from: https://bitbucket.org/orgname/reponame/src/master/file.yaml - * to: https://api.bitbucket.org/2.0/repositories/orgname/reponame/src/master/file.yaml - * - * @param url - A URL pointing to a file - * @param config - The relevant provider config - * @public - * @deprecated no longer in use, bitbucket integration replaced by integrations bitbucketCloud and bitbucketServer. - */ -export function getBitbucketFileFetchUrl( - url: string, - config: BitbucketIntegrationConfig, -): string { - try { - const { owner, name, ref, filepathtype, filepath } = parseGitUrl(url); - if ( - !owner || - !name || - (filepathtype !== 'browse' && - filepathtype !== 'raw' && - filepathtype !== 'src') - ) { - throw new Error('Invalid Bitbucket URL or file path'); - } - - const pathWithoutSlash = filepath.replace(/^\//, ''); - - if (config.host === 'bitbucket.org') { - if (!ref) { - throw new Error('Invalid Bitbucket URL or file path'); - } - return `${config.apiBaseUrl}/repositories/${owner}/${name}/src/${ref}/${pathWithoutSlash}`; - } - return `${config.apiBaseUrl}/projects/${owner}/repos/${name}/raw/${pathWithoutSlash}?at=${ref}`; - } catch (e) { - throw new Error(`Incorrect URL: ${url}, ${e}`); - } -} - -/** - * Gets the request options necessary to make requests to a given provider. - * - * @param config - The relevant provider config - * @public - * @deprecated no longer in use, bitbucket integration replaced by integrations bitbucketCloud and bitbucketServer. - */ -export function getBitbucketRequestOptions( - config: BitbucketIntegrationConfig, -): { headers: Record } { - const headers: Record = {}; - - if (config.token) { - headers.Authorization = `Bearer ${config.token}`; - } else if (config.username && config.appPassword) { - const buffer = Buffer.from( - `${config.username}:${config.appPassword}`, - 'utf8', - ); - headers.Authorization = `Basic ${buffer.toString('base64')}`; - } - - return { - headers, - }; -} diff --git a/packages/integration/src/bitbucket/index.ts b/packages/integration/src/bitbucket/index.ts deleted file mode 100644 index 356e760fd8..0000000000 --- a/packages/integration/src/bitbucket/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { BitbucketIntegration } from './BitbucketIntegration'; -export { - readBitbucketIntegrationConfig, - readBitbucketIntegrationConfigs, -} from './config'; -export type { BitbucketIntegrationConfig } from './config'; -export { - getBitbucketDefaultBranch, - getBitbucketDownloadUrl, - getBitbucketFileFetchUrl, - getBitbucketRequestOptions, -} from './core'; diff --git a/packages/integration/src/gerrit/core.test.ts b/packages/integration/src/gerrit/core.test.ts index 5899196f65..60bd898008 100644 --- a/packages/integration/src/gerrit/core.test.ts +++ b/packages/integration/src/gerrit/core.test.ts @@ -20,7 +20,6 @@ import fetch from 'cross-fetch'; import { registerMswTestHooks } from '../helpers'; import { GerritIntegrationConfig } from './config'; import { - buildGerritGitilesArchiveUrl, buildGerritGitilesArchiveUrlFromLocation, buildGerritGitilesUrl, getGerritBranchApiUrl, @@ -28,7 +27,6 @@ import { getGerritRequestOptions, parseGerritJsonResponse, parseGitilesUrlRef, - parseGerritGitilesUrl, getGerritFileContentsApiUrl, } from './core'; @@ -36,86 +34,6 @@ describe('gerrit core', () => { const worker = setupServer(); registerMswTestHooks(worker); - describe('buildGerritGitilesArchiveUrl', () => { - const config: GerritIntegrationConfig = { - host: 'gerrit.com', - baseUrl: 'https://gerrit.com', - gitilesBaseUrl: 'https://gerrit.com/gitiles', - }; - const configWithPath: GerritIntegrationConfig = { - host: 'gerrit.com', - baseUrl: 'https://gerrit.com/gerrit', - gitilesBaseUrl: 'https://gerrit.com/gerrit/plugins/gitiles', - }; - const configWithDedicatedGitiles: GerritIntegrationConfig = { - host: 'gerrit.com', - baseUrl: 'https://gerrit.com/gerrit', - gitilesBaseUrl: 'https://dedicated-gitiles-server.com/gerrit/gitiles', - }; - it('can create an archive url for a branch', () => { - expect(buildGerritGitilesArchiveUrl(config, 'repo', 'dev', '')).toEqual( - 'https://gerrit.com/gitiles/repo/+archive/refs/heads/dev.tar.gz', - ); - - expect(buildGerritGitilesArchiveUrl(config, 'repo', 'dev', '/')).toEqual( - 'https://gerrit.com/gitiles/repo/+archive/refs/heads/dev.tar.gz', - ); - }); - it('can create an archive url for a specific directory', () => { - expect( - buildGerritGitilesArchiveUrl(config, 'repo', 'dev', 'docs'), - ).toEqual( - 'https://gerrit.com/gitiles/repo/+archive/refs/heads/dev/docs.tar.gz', - ); - }); - it('can create an authenticated url when auth is enabled', () => { - const authConfig = { - ...config, - username: 'username', - password: 'password', - }; - expect( - buildGerritGitilesArchiveUrl(authConfig, 'repo', 'dev', 'docs'), - ).toEqual( - 'https://gerrit.com/a/gitiles/repo/+archive/refs/heads/dev/docs.tar.gz', - ); - }); - it('can create an authenticated url when auth is enabled and an url-path is used', () => { - const authConfig = { - ...configWithPath, - username: 'username', - password: 'password', - }; - expect( - buildGerritGitilesArchiveUrl(authConfig, 'repo', 'dev', 'docs'), - ).toEqual( - 'https://gerrit.com/gerrit/a/plugins/gitiles/repo/+archive/refs/heads/dev/docs.tar.gz', - ); - }); - it('Cannot build an authenticated url when a dedicated Gitiles server is used', () => { - const authConfig = { - ...configWithDedicatedGitiles, - username: 'username', - password: 'password', - }; - expect(() => - buildGerritGitilesArchiveUrl(authConfig, 'repo', 'dev', 'docs'), - ).toThrow( - 'Since the baseUrl (Gerrit) is not part of the gitilesBaseUrl, an authentication URL could not be constructed.', - ); - }); - it('Build a non-authenticated url when a dedicated Gitiles server is used', () => { - const authConfig = { - ...configWithDedicatedGitiles, - }; - expect( - buildGerritGitilesArchiveUrl(authConfig, 'repo', 'dev', 'docs'), - ).toEqual( - 'https://dedicated-gitiles-server.com/gerrit/gitiles/repo/+archive/refs/heads/dev/docs.tar.gz', - ); - }); - }); - describe('buildGerritGitilesArchiveUrlFromLocation', () => { const config: GerritIntegrationConfig = { host: 'gerrit.com', @@ -238,6 +156,7 @@ describe('gerrit core', () => { ).toBeUndefined(); }); }); + describe('parseGitilesUrlRef', () => { const config: GerritIntegrationConfig = { host: 'gerrit.com', @@ -360,64 +279,6 @@ describe('gerrit core', () => { }); }); }); - describe('parseGerritGitilesUrl', () => { - it('can parse a valid gitiles urls.', () => { - const config: GerritIntegrationConfig = { - host: 'gerrit.com', - gitilesBaseUrl: 'https://gerrit.com/gitiles', - }; - const { branch, filePath, project } = parseGerritGitilesUrl( - config, - 'https://gerrit.com/gitiles/web/project/+/refs/heads/master/README.md', - ); - expect(project).toEqual('web/project'); - expect(branch).toEqual('master'); - expect(filePath).toEqual('README.md'); - - const { filePath: rootPath } = parseGerritGitilesUrl( - config, - 'https://gerrit.com/gitiles/web/project/+/refs/heads/master', - ); - expect(rootPath).toEqual('/'); - }); - it('can parse a valid authenticated gitiles url.', () => { - const config: GerritIntegrationConfig = { - host: 'gerrit.com', - gitilesBaseUrl: 'https://gerrit.com/gitiles', - }; - const { branch, filePath, project } = parseGerritGitilesUrl( - config, - 'https://gerrit.com/a/gitiles/web/project/+/refs/heads/master/README.md', - ); - expect(project).toEqual('web/project'); - expect(branch).toEqual('master'); - expect(filePath).toEqual('README.md'); - - const { filePath: rootPath } = parseGerritGitilesUrl( - config, - 'https://gerrit.com/gitiles/web/project/+/refs/heads/master', - ); - expect(rootPath).toEqual('/'); - }); - it('throws on incorrect gitiles urls.', () => { - const config: GerritIntegrationConfig = { - host: 'gerrit.com', - gitilesBaseUrl: 'https://gerrit.com', - }; - expect(() => - parseGerritGitilesUrl( - config, - 'https://gerrit.com/+/refs/heads/master/README.md', - ), - ).toThrow(/project/); - expect(() => - parseGerritGitilesUrl( - config, - 'https://gerrit.com/web/project/+/refs/changes/1/11/master/README.md', - ), - ).toThrow(/branch/); - }); - }); describe('getGerritBranchApiUrl', () => { it('can create an url for anonymous access.', () => { diff --git a/packages/integration/src/gerrit/core.ts b/packages/integration/src/gerrit/core.ts index ae6a5baa10..e8db1305ed 100644 --- a/packages/integration/src/gerrit/core.ts +++ b/packages/integration/src/gerrit/core.ts @@ -18,70 +18,6 @@ import { GerritIntegrationConfig } from './config'; const GERRIT_BODY_PREFIX = ")]}'"; -/** - * Parse a Gitiles URL and return branch, file path and project. - * - * @remarks - * - * Gerrit only handles code reviews so it does not have a native way to browse - * or showing the content of gits. Image if Github only had the "pull requests" - * tab. - * - * Any source code browsing is instead handled by optional services outside - * Gerrit. The url format chosen for the Gerrit url reader is the one used by - * the Gitiles project. Gerrit will work perfectly with Backstage without - * having Gitiles installed but there are some places in the Backstage GUI - * with links to the url used by the url reader. These will not work unless - * the urls point to an actual Gitiles installation. - * - * Gitiles url: - * https://g.com/optional_path/\{project\}/+/refs/heads/\{branch\}/\{filePath\} - * https://g.com/a/optional_path/\{project\}/+/refs/heads/\{branch\}/\{filePath\} - * - * - * @param url - An URL pointing to a file stored in git. - * @public - * @deprecated `parseGerritGitilesUrl` is deprecated. Use - * {@link parseGitilesUrlRef} instead. - */ -export function parseGerritGitilesUrl( - config: GerritIntegrationConfig, - url: string, -): { branch: string; filePath: string; project: string } { - const baseUrlParse = new URL(config.gitilesBaseUrl!); - const urlParse = new URL(url); - - // Remove the gerrit authentication prefix '/a/' from the url - // In case of the gitilesBaseUrl is https://review.gerrit.com/plugins/gitiles - // and the url provided is https://review.gerrit.com/a/plugins/gitiles/... - // remove the prefix only if the pathname start with '/a/' - const urlPath = urlParse.pathname - .substring(urlParse.pathname.startsWith('/a/') ? 2 : 0) - .replace(baseUrlParse.pathname, ''); - - const parts = urlPath.split('/').filter(p => !!p); - - const projectEndIndex = parts.indexOf('+'); - - if (projectEndIndex <= 0) { - throw new Error(`Unable to parse project from url: ${url}`); - } - const project = trimStart(parts.slice(0, projectEndIndex).join('/'), '/'); - - const branchIndex = parts.indexOf('heads'); - if (branchIndex <= 0) { - throw new Error(`Unable to parse branch from url: ${url}`); - } - const branch = parts[branchIndex + 1]; - const filePath = parts.slice(branchIndex + 2).join('/'); - - return { - branch, - filePath: filePath === '' ? '/' : filePath, - project, - }; -} - /** * Parses Gitiles urls and returns the following: * @@ -231,30 +167,6 @@ export function buildGerritEditUrl( )}`; } -/** - * Build a Gerrit Gitiles archive url that targets a specific branch and path - * - * @param config - A Gerrit provider config. - * @param project - The name of the git project - * @param branch - The branch we will target. - * @param filePath - The absolute file path. - * @public - * @deprecated `buildGerritGitilesArchiveUrl` is deprecated. Use - * {@link buildGerritGitilesArchiveUrlFromLocation} instead. - */ -export function buildGerritGitilesArchiveUrl( - config: GerritIntegrationConfig, - project: string, - branch: string, - filePath: string, -): string { - const archiveName = - filePath === '/' || filePath === '' ? '.tar.gz' : `/${filePath}.tar.gz`; - return `${getGitilesAuthenticationUrl( - config, - )}/${project}/+archive/refs/heads/${branch}${archiveName}`; -} - /** * Build a Gerrit Gitiles archive url from a Gitiles url. * @@ -350,11 +262,15 @@ export function getGerritBranchApiUrl( config: GerritIntegrationConfig, url: string, ) { - const { branch, project } = parseGerritGitilesUrl(config, url); + const { ref, refType, project } = parseGitilesUrlRef(config, url); + + if (refType !== 'branch') { + throw new Error(`Unsupported gitiles ref type: ${refType}`); + } return `${config.baseUrl}${getAuthenticationPrefix( config, - )}projects/${encodeURIComponent(project)}/branches/${branch}`; + )}projects/${encodeURIComponent(project)}/branches/${ref}`; } /** @@ -367,7 +283,7 @@ export function getGerritCloneRepoUrl( config: GerritIntegrationConfig, url: string, ) { - const { project } = parseGerritGitilesUrl(config, url); + const { project } = parseGitilesUrlRef(config, url); return `${config.cloneUrl}${getAuthenticationPrefix(config)}${project}`; } diff --git a/packages/integration/src/gerrit/index.ts b/packages/integration/src/gerrit/index.ts index 534315cfba..5af75e36ab 100644 --- a/packages/integration/src/gerrit/index.ts +++ b/packages/integration/src/gerrit/index.ts @@ -19,7 +19,6 @@ export { readGerritIntegrationConfigs, } from './config'; export { - buildGerritGitilesArchiveUrl, buildGerritGitilesArchiveUrlFromLocation, getGitilesAuthenticationUrl, getGerritBranchApiUrl, @@ -28,7 +27,6 @@ export { getGerritProjectsApiUrl, getGerritRequestOptions, parseGerritJsonResponse, - parseGerritGitilesUrl, parseGitilesUrlRef, } from './core'; diff --git a/packages/integration/src/github/core.test.ts b/packages/integration/src/github/core.test.ts index 982a096b43..8e9507b239 100644 --- a/packages/integration/src/github/core.test.ts +++ b/packages/integration/src/github/core.test.ts @@ -15,7 +15,7 @@ */ import { GithubIntegrationConfig } from './config'; -import { getGithubFileFetchUrl, getGitHubRequestOptions } from './core'; +import { getGithubFileFetchUrl } from './core'; import { GithubCredentials } from './types'; describe('github core', () => { @@ -35,28 +35,6 @@ describe('github core', () => { type: 'token', }; - describe('getGitHubRequestOptions', () => { - it('inserts a token when needed', () => { - const withToken: GithubIntegrationConfig = { - host: '', - rawBaseUrl: '', - token: 'A', - }; - const withoutToken: GithubIntegrationConfig = { - host: '', - rawBaseUrl: '', - }; - expect( - (getGitHubRequestOptions(withToken, appCredentials).headers as any) - .Authorization, - ).toEqual('token A'); - expect( - (getGitHubRequestOptions(withoutToken, noCredentials).headers as any) - .Authorization, - ).toBeUndefined(); - }); - }); - describe('getGithubFileFetchUrl', () => { it('rejects targets that do not look like URLs', () => { const config: GithubIntegrationConfig = { host: '', apiBaseUrl: '' }; diff --git a/packages/integration/src/github/core.ts b/packages/integration/src/github/core.ts index a755f3383c..d1f583b2fb 100644 --- a/packages/integration/src/github/core.ts +++ b/packages/integration/src/github/core.ts @@ -63,30 +63,6 @@ export function getGithubFileFetchUrl( } } -/** - * Gets the request options necessary to make requests to a given provider. - * - * @deprecated This function is no longer used internally - * @param config - The relevant provider config - * @public - */ -export function getGitHubRequestOptions( - config: GithubIntegrationConfig, - credentials: GithubCredentials, -): { headers: Record } { - const headers: Record = {}; - - if (chooseEndpoint(config, credentials) === 'api') { - headers.Accept = 'application/vnd.github.v3.raw'; - } - - if (credentials.token) { - headers.Authorization = `token ${credentials.token}`; - } - - return { headers }; -} - export function chooseEndpoint( config: GithubIntegrationConfig, credentials: GithubCredentials, diff --git a/packages/integration/src/github/index.ts b/packages/integration/src/github/index.ts index ea6f18f2e0..450ac38a63 100644 --- a/packages/integration/src/github/index.ts +++ b/packages/integration/src/github/index.ts @@ -19,7 +19,7 @@ export { readGithubIntegrationConfigs, } from './config'; export type { GithubAppConfig, GithubIntegrationConfig } from './config'; -export { getGithubFileFetchUrl, getGitHubRequestOptions } from './core'; +export { getGithubFileFetchUrl } from './core'; export { DefaultGithubCredentialsProvider } from './DefaultGithubCredentialsProvider'; export { GithubAppCredentialsMux, diff --git a/packages/integration/src/index.ts b/packages/integration/src/index.ts index a625f5d83c..1c0919fcbd 100644 --- a/packages/integration/src/index.ts +++ b/packages/integration/src/index.ts @@ -24,7 +24,6 @@ export * from './awsS3'; export * from './awsCodeCommit'; export * from './azureBlobStorage'; export * from './azure'; -export * from './bitbucket'; export * from './bitbucketCloud'; export * from './bitbucketServer'; export * from './gerrit'; diff --git a/packages/integration/src/registry.ts b/packages/integration/src/registry.ts index 2e8111903b..6aca5b197b 100644 --- a/packages/integration/src/registry.ts +++ b/packages/integration/src/registry.ts @@ -19,7 +19,6 @@ import { AwsS3Integration } from './awsS3/AwsS3Integration'; import { AwsCodeCommitIntegration } from './awsCodeCommit'; import { AzureIntegration } from './azure/AzureIntegration'; import { BitbucketCloudIntegration } from './bitbucketCloud/BitbucketCloudIntegration'; -import { BitbucketIntegration } from './bitbucket/BitbucketIntegration'; import { BitbucketServerIntegration } from './bitbucketServer/BitbucketServerIntegration'; import { GerritIntegration } from './gerrit/GerritIntegration'; import { GithubIntegration } from './github/GithubIntegration'; @@ -39,10 +38,6 @@ export interface ScmIntegrationRegistry awsCodeCommit: ScmIntegrationsGroup; azureBlobStorage: ScmIntegrationsGroup; azure: ScmIntegrationsGroup; - /** - * @deprecated in favor of `bitbucketCloud` and `bitbucketServer` - */ - bitbucket: ScmIntegrationsGroup; bitbucketCloud: ScmIntegrationsGroup; bitbucketServer: ScmIntegrationsGroup; gerrit: ScmIntegrationsGroup; diff --git a/plugins/scaffolder-backend-module-bitbucket/.eslintrc.js b/plugins/scaffolder-backend-module-bitbucket/.eslintrc.js deleted file mode 100644 index e2a53a6ad2..0000000000 --- a/plugins/scaffolder-backend-module-bitbucket/.eslintrc.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/scaffolder-backend-module-bitbucket/CHANGELOG.md b/plugins/scaffolder-backend-module-bitbucket/CHANGELOG.md deleted file mode 100644 index 286dcbece7..0000000000 --- a/plugins/scaffolder-backend-module-bitbucket/CHANGELOG.md +++ /dev/null @@ -1,1341 +0,0 @@ -# @backstage/plugin-scaffolder-backend-module-bitbucket - -## 0.3.20-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/integration@1.21.0-next.0 - - @backstage/backend-plugin-api@1.7.1-next.0 - - @backstage/config@1.3.6 - - @backstage/errors@1.2.7 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.3.4-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.19-next.0 - - @backstage/plugin-scaffolder-node@0.12.6-next.0 - -## 0.3.19 - -### Patch Changes - -- 7455dae: Use node prefix on native imports -- Updated dependencies - - @backstage/integration@1.20.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.3.3 - - @backstage/backend-plugin-api@1.7.0 - - @backstage/plugin-scaffolder-node@0.12.5 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.18 - -## 0.3.19-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/integration@1.20.0-next.1 - - @backstage/backend-plugin-api@1.7.0-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.3.3-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.18-next.1 - - @backstage/plugin-scaffolder-node@0.12.5-next.1 - -## 0.3.19-next.0 - -### Patch Changes - -- 7455dae: Use node prefix on native imports -- Updated dependencies - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.3.2-next.0 - - @backstage/backend-plugin-api@1.7.0-next.0 - - @backstage/plugin-scaffolder-node@0.12.4-next.0 - - @backstage/integration@1.19.3-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.18-next.0 - - @backstage/config@1.3.6 - - @backstage/errors@1.2.7 - -## 0.3.18 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@1.6.1 - - @backstage/plugin-scaffolder-node@0.12.3 - - @backstage/integration@1.19.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.3.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.17 - -## 0.3.18-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/integration@1.19.2-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.3.1-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.17-next.0 - - @backstage/plugin-scaffolder-node@0.12.3-next.0 - -## 0.3.17 - -### Patch Changes - -- Updated dependencies - - @backstage/integration@1.19.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.3.0 - - @backstage/backend-plugin-api@1.6.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.16 - - @backstage/plugin-scaffolder-node@0.12.2 - -## 0.3.17-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/integration@1.18.3-next.1 - - @backstage/backend-plugin-api@1.6.0-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.16-next.1 - - @backstage/config@1.3.6 - - @backstage/errors@1.2.7 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.16-next.1 - - @backstage/plugin-scaffolder-node@0.12.2-next.1 - -## 0.3.17-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@1.5.1-next.0 - - @backstage/integration@1.18.3-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.16-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.16-next.0 - - @backstage/plugin-scaffolder-node@0.12.2-next.0 - - @backstage/config@1.3.6 - - @backstage/errors@1.2.7 - -## 0.3.16 - -### Patch Changes - -- fa255f5: Support for Bitbucket Cloud's API token was added as `appPassword` is deprecated (no new creation from September 9, 2025) and will be removed on June 9, 2026. - - API token usage example: - - ```yaml - integrations: - bitbucketCloud: - - username: user@domain.com - token: my-token - ``` - -- Updated dependencies - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.15 - - @backstage/integration@1.18.2 - - @backstage/backend-plugin-api@1.5.0 - - @backstage/config@1.3.6 - - @backstage/plugin-scaffolder-node@0.12.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.15 - -## 0.3.16-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@1.5.0-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.15-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.15-next.1 - - @backstage/plugin-scaffolder-node@0.12.1-next.1 - -## 0.3.16-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/config@1.3.6-next.0 - - @backstage/integration@1.18.2-next.0 - - @backstage/plugin-scaffolder-node@0.12.1-next.0 - - @backstage/backend-plugin-api@1.4.5-next.0 - - @backstage/errors@1.2.7 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.15-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.15-next.0 - -## 0.3.15 - -### Patch Changes - -- c8aa210: Updating import for the `scaffolderActionsExtensionPoint` to be the main export -- Updated dependencies - - @backstage/integration@1.18.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.14 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.14 - - @backstage/plugin-scaffolder-node@0.12.0 - - @backstage/config@1.3.5 - - @backstage/backend-plugin-api@1.4.4 - -## 0.3.15-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/config@1.3.4-next.0 - - @backstage/integration@1.18.1-next.1 - - @backstage/backend-plugin-api@1.4.4-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.14-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.14-next.1 - - @backstage/plugin-scaffolder-node@0.12.0-next.1 - -## 0.3.15-next.0 - -### Patch Changes - -- c8aa210: Updating import for the `scaffolderActionsExtensionPoint` to be the main export -- Updated dependencies - - @backstage/integration@1.18.1-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.14-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.14-next.0 - - @backstage/plugin-scaffolder-node@0.12.0-next.0 - - @backstage/backend-plugin-api@1.4.3 - - @backstage/config@1.3.3 - - @backstage/errors@1.2.7 - -## 0.3.14 - -### Patch Changes - -- Updated dependencies - - @backstage/integration@1.18.0 - - @backstage/backend-plugin-api@1.4.3 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.13 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.13 - - @backstage/plugin-scaffolder-node@0.11.1 - -## 0.3.14-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/integration@1.18.0-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.13-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.13-next.0 - - @backstage/plugin-scaffolder-node@0.11.1-next.0 - - @backstage/backend-plugin-api@1.4.3-next.0 - -## 0.3.13 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.11.0 - - @backstage/backend-plugin-api@1.4.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.12 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.12 - -## 0.3.13-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.11.0-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.12-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.12-next.0 - - @backstage/backend-plugin-api@1.4.2-next.0 - - @backstage/config@1.3.3 - - @backstage/errors@1.2.7 - - @backstage/integration@1.17.1 - -## 0.3.12 - -### Patch Changes - -- Updated dependencies - - @backstage/config@1.3.3 - - @backstage/plugin-scaffolder-node@0.10.0 - - @backstage/integration@1.17.1 - - @backstage/backend-plugin-api@1.4.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.11 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.11 - -## 0.3.12-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.10.0-next.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.11-next.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.11-next.2 - -## 0.3.12-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/config@1.3.3-next.0 - - @backstage/integration@1.17.1-next.1 - - @backstage/backend-plugin-api@1.4.1-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.11-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.11-next.1 - - @backstage/plugin-scaffolder-node@0.9.1-next.1 - -## 0.3.12-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.9.1-next.0 - - @backstage/integration@1.17.1-next.0 - - @backstage/backend-plugin-api@1.4.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.11-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.11-next.0 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - -## 0.3.11 - -### Patch Changes - -- 7f710d2: Migrating `bitbucket` actions to use the new `zod` format -- Updated dependencies - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.10 - - @backstage/plugin-scaffolder-node@0.9.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.10 - - @backstage/backend-plugin-api@1.4.0 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - - @backstage/integration@1.17.0 - -## 0.3.11-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.9.0-next.2 - - @backstage/backend-plugin-api@1.4.0-next.1 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - - @backstage/integration@1.17.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.10-next.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.10-next.2 - -## 0.3.11-next.1 - -### Patch Changes - -- 7f710d2: Migrating `bitbucket` actions to use the new `zod` format -- Updated dependencies - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.10-next.1 - - @backstage/plugin-scaffolder-node@0.8.3-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.10-next.1 - - @backstage/backend-plugin-api@1.4.0-next.1 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - - @backstage/integration@1.17.0 - -## 0.3.11-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.10-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.10-next.0 - - @backstage/plugin-scaffolder-node@0.8.3-next.0 - - @backstage/backend-plugin-api@1.4.0-next.0 - -## 0.3.10 - -### Patch Changes - -- 72d019d: Removed various typos -- Updated dependencies - - @backstage/integration@1.17.0 - - @backstage/backend-plugin-api@1.3.1 - - @backstage/plugin-scaffolder-node@0.8.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.9 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.9 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - -## 0.3.10-next.3 - -### Patch Changes - -- Updated dependencies - - @backstage/integration@1.17.0-next.3 - - @backstage/plugin-scaffolder-node@0.8.2-next.3 - - @backstage/backend-plugin-api@1.3.1-next.2 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.9-next.3 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.9-next.3 - -## 0.3.10-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/integration@1.17.0-next.2 - - @backstage/config@1.3.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.9-next.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.9-next.2 - - @backstage/plugin-scaffolder-node@0.8.2-next.2 - - @backstage/backend-plugin-api@1.3.1-next.1 - - @backstage/errors@1.2.7 - -## 0.3.10-next.1 - -### Patch Changes - -- 72d019d: Removed various typos -- Updated dependencies - - @backstage/backend-plugin-api@1.3.1-next.1 - - @backstage/integration@1.16.4-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.9-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.9-next.1 - - @backstage/plugin-scaffolder-node@0.8.2-next.1 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - -## 0.3.10-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/integration@1.16.4-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.9-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.9-next.0 - - @backstage/plugin-scaffolder-node@0.8.2-next.0 - - @backstage/backend-plugin-api@1.3.1-next.0 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - -## 0.3.9 - -### Patch Changes - -- adfceee: Made "publish:bitbucket" action idempotent -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.8.1 - - @backstage/backend-plugin-api@1.3.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.8 - - @backstage/integration@1.16.3 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.8 - -## 0.3.9-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/integration@1.16.3-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.8-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.8-next.1 - - @backstage/plugin-scaffolder-node@0.8.1-next.1 - - @backstage/backend-plugin-api@1.2.1 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - -## 0.3.9-next.0 - -### Patch Changes - -- adfceee: Made "publish:bitbucket" action idempotent -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.8.1-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.8-next.0 - - @backstage/backend-plugin-api@1.2.1 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - - @backstage/integration@1.16.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.8-next.0 - -## 0.3.8 - -### Patch Changes - -- 4f8b5b6: Allow signing git commits using configured private PGP key in scaffolder -- Updated dependencies - - @backstage/integration@1.16.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.7 - - @backstage/plugin-scaffolder-node@0.8.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.7 - - @backstage/backend-plugin-api@1.2.1 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - -## 0.3.8-next.2 - -### Patch Changes - -- 4f8b5b6: Allow signing git commits using configured private PGP key in scaffolder -- Updated dependencies - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.7-next.2 - - @backstage/plugin-scaffolder-node@0.8.0-next.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.7-next.2 - - @backstage/integration@1.16.2-next.0 - - @backstage/backend-plugin-api@1.2.1-next.1 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - -## 0.3.8-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.7.1-next.1 - - @backstage/backend-plugin-api@1.2.1-next.1 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - - @backstage/integration@1.16.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.7-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.7-next.1 - -## 0.3.8-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@1.2.1-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.7-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.7-next.0 - - @backstage/plugin-scaffolder-node@0.7.1-next.0 - -## 0.3.7 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@1.2.0 - - @backstage/plugin-scaffolder-node@0.7.0 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - - @backstage/integration@1.16.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.6 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.6 - -## 0.3.7-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.7.0-next.2 - - @backstage/backend-plugin-api@1.2.0-next.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.6-next.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.6-next.2 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - - @backstage/integration@1.16.1 - -## 0.3.7-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@1.2.0-next.1 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - - @backstage/integration@1.16.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.6-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.6-next.1 - - @backstage/plugin-scaffolder-node@0.7.0-next.1 - -## 0.3.7-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@1.2.0-next.0 - - @backstage/plugin-scaffolder-node@0.7.0-next.0 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - - @backstage/integration@1.16.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.6-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.6-next.0 - -## 0.3.6 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.6.3 - - @backstage/integration@1.16.1 - - @backstage/backend-plugin-api@1.1.1 - - @backstage/config@1.3.2 - - @backstage/errors@1.2.7 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.5 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.5 - -## 0.3.6-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@1.1.1-next.1 - - @backstage/config@1.3.2-next.0 - - @backstage/errors@1.2.7-next.0 - - @backstage/plugin-scaffolder-node@0.6.3-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.5-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.5-next.1 - - @backstage/integration@1.16.1-next.0 - -## 0.3.6-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.6.3-next.0 - - @backstage/backend-plugin-api@1.1.1-next.0 - - @backstage/config@1.3.1 - - @backstage/errors@1.2.6 - - @backstage/integration@1.16.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.5-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.5-next.0 - -## 0.3.5 - -### Patch Changes - -- 5f04976: Fixed a bug that caused missing code in published packages. -- 5c9cc05: Use native fetch instead of node-fetch -- Updated dependencies - - @backstage/integration@1.16.0 - - @backstage/backend-plugin-api@1.1.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.4 - - @backstage/plugin-scaffolder-node@0.6.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.4 - - @backstage/errors@1.2.6 - - @backstage/config@1.3.1 - -## 0.3.5-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@1.1.0-next.2 - - @backstage/errors@1.2.6-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.4-next.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.4-next.2 - - @backstage/plugin-scaffolder-node@0.6.2-next.2 - - @backstage/config@1.3.1-next.0 - - @backstage/integration@1.16.0-next.1 - -## 0.3.5-next.1 - -### Patch Changes - -- 5c9cc05: Use native fetch instead of node-fetch -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.6.2-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.4-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.4-next.1 - - @backstage/backend-plugin-api@1.1.0-next.1 - - @backstage/config@1.3.0 - - @backstage/errors@1.2.5 - - @backstage/integration@1.16.0-next.0 - -## 0.3.4-next.0 - -### Patch Changes - -- 5f04976: Fixed a bug that caused missing code in published packages. -- Updated dependencies - - @backstage/integration@1.16.0-next.0 - - @backstage/backend-plugin-api@1.0.3-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.3-next.0 - - @backstage/plugin-scaffolder-node@0.6.1-next.0 - - @backstage/config@1.3.0 - - @backstage/errors@1.2.5 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.3-next.0 - -## 0.3.2 - -### Patch Changes - -- Updated dependencies - - @backstage/config@1.3.0 - - @backstage/backend-plugin-api@1.0.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.2 - - @backstage/plugin-scaffolder-node@0.6.0 - - @backstage/errors@1.2.5 - - @backstage/integration@1.15.2 - -## 0.3.2-next.3 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@1.0.2-next.2 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.15.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.2-next.3 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.2-next.3 - - @backstage/plugin-scaffolder-node@0.5.1-next.3 - -## 0.3.2-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@1.0.2-next.2 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.15.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.2-next.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.2-next.2 - - @backstage/plugin-scaffolder-node@0.5.1-next.2 - -## 0.3.2-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.2-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.2-next.1 - - @backstage/backend-plugin-api@1.0.2-next.1 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.15.1 - - @backstage/plugin-scaffolder-node@0.5.1-next.1 - -## 0.3.2-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@1.0.2-next.0 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.15.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.2-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.2-next.0 - - @backstage/plugin-scaffolder-node@0.5.1-next.0 - -## 0.3.1 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.5.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.1 - - @backstage/integration@1.15.1 - - @backstage/backend-plugin-api@1.0.1 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.1 - -## 0.3.1-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.1-next.2 - - @backstage/integration@1.15.1-next.1 - - @backstage/plugin-scaffolder-node@0.5.0-next.2 - - @backstage/backend-plugin-api@1.0.1-next.1 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.1-next.2 - -## 0.3.1-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/integration@1.15.1-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.1-next.1 - - @backstage/backend-plugin-api@1.0.1-next.0 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.1-next.1 - - @backstage/plugin-scaffolder-node@0.5.0-next.1 - -## 0.3.1-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.5.0-next.0 - - @backstage/backend-plugin-api@1.0.1-next.0 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.15.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.1-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.1-next.0 - -## 0.3.0 - -### Minor Changes - -- d425fc4: **BREAKING**: The return values from `createBackendPlugin`, `createBackendModule`, and `createServiceFactory` are now simply `BackendFeature` and `ServiceFactory`, instead of the previously deprecated form of a function that returns them. For this reason, `createServiceFactory` also no longer accepts the callback form where you provide direct options to the service. This also affects all `coreServices.*` service refs. - - This may in particular affect tests; if you were effectively doing `createBackendModule({...})()` (note the parentheses), you can now remove those extra parentheses at the end. You may encounter cases of this in your `packages/backend/src/index.ts` too, where you add plugins, modules, and services. If you were using `createServiceFactory` with a function as its argument for the purpose of passing in options, this pattern has been deprecated for a while and is no longer supported. You may want to explore the new multiton patterns to achieve your goals, or moving settings to app-config. - - As part of this change, the `IdentityFactoryOptions` type was removed, and can no longer be used to tweak that service. The identity service was also deprecated some time ago, and you will want to [migrate to the new auth system](https://backstage.io/docs/tutorials/auth-service-migration) if you still rely on it. - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@1.0.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.0 - - @backstage/integration@1.15.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.0 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/plugin-scaffolder-node@0.4.11 - -## 0.3.0-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.0-next.2 - - @backstage/backend-plugin-api@1.0.0-next.2 - - @backstage/integration@1.15.0-next.0 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.0-next.2 - - @backstage/plugin-scaffolder-node@0.4.11-next.2 - -## 0.3.0-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@0.9.0-next.1 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.14.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.0-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.0-next.1 - - @backstage/plugin-scaffolder-node@0.4.11-next.1 - -## 0.3.0-next.0 - -### Minor Changes - -- d425fc4: **BREAKING**: The return values from `createBackendPlugin`, `createBackendModule`, and `createServiceFactory` are now simply `BackendFeature` and `ServiceFactory`, instead of the previously deprecated form of a function that returns them. For this reason, `createServiceFactory` also no longer accepts the callback form where you provide direct options to the service. This also affects all `coreServices.*` service refs. - - This may in particular affect tests; if you were effectively doing `createBackendModule({...})()` (note the parentheses), you can now remove those extra parentheses at the end. You may encounter cases of this in your `packages/backend/src/index.ts` too, where you add plugins, modules, and services. If you were using `createServiceFactory` with a function as its argument for the purpose of passing in options, this pattern has been deprecated for a while and is no longer supported. You may want to explore the new multiton patterns to achieve your goals, or moving settings to app-config. - - As part of this change, the `IdentityFactoryOptions` type was removed, and can no longer be used to tweak that service. The identity service was also deprecated some time ago, and you will want to [migrate to the new auth system](https://backstage.io/docs/tutorials/auth-service-migration) if you still rely on it. - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@0.9.0-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.0-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.0-next.0 - - @backstage/plugin-scaffolder-node@0.4.11-next.0 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.14.0 - -## 0.2.13 - -### Patch Changes - -- 93095ee: Make sure node-fetch is version 2.7.0 or greater -- Updated dependencies - - @backstage/backend-plugin-api@0.8.0 - - @backstage/plugin-scaffolder-node@0.4.9 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.13 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.13 - - @backstage/integration@1.14.0 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - -## 0.2.13-next.3 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.13-next.3 - - @backstage/backend-plugin-api@0.8.0-next.3 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.14.0-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.13-next.3 - - @backstage/plugin-scaffolder-node@0.4.9-next.3 - -## 0.2.13-next.2 - -### Patch Changes - -- 93095ee: Make sure node-fetch is version 2.7.0 or greater -- Updated dependencies - - @backstage/backend-plugin-api@0.8.0-next.2 - - @backstage/plugin-scaffolder-node@0.4.9-next.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.13-next.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.13-next.2 - - @backstage/integration@1.14.0-next.0 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - -## 0.2.13-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.13-next.1 - - @backstage/backend-plugin-api@0.7.1-next.1 - - @backstage/integration@1.14.0-next.0 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.13-next.1 - - @backstage/plugin-scaffolder-node@0.4.9-next.1 - -## 0.2.13-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/integration@1.14.0-next.0 - - @backstage/backend-plugin-api@0.7.1-next.0 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.13-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.13-next.0 - - @backstage/plugin-scaffolder-node@0.4.9-next.0 - -## 0.2.12 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@0.7.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.12 - - @backstage/integration@1.13.0 - - @backstage/plugin-scaffolder-node@0.4.8 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.12 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - -## 0.2.12-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@0.6.22-next.1 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.13.0-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.12-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.12-next.1 - - @backstage/plugin-scaffolder-node@0.4.8-next.1 - -## 0.2.11-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@0.6.21-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.11-next.0 - - @backstage/integration@1.13.0-next.0 - - @backstage/plugin-scaffolder-node@0.4.7-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.11-next.0 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - -## 0.2.9 - -### Patch Changes - -- 78a0b08: Internal refactor to handle `BackendFeature` contract change. -- d44a20a: Added additional plugin metadata to `package.json`. -- Updated dependencies - - @backstage/backend-plugin-api@0.6.19 - - @backstage/integration@1.12.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.9 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.9 - - @backstage/plugin-scaffolder-node@0.4.5 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - -## 0.2.9-next.2 - -### Patch Changes - -- d44a20a: Added additional plugin metadata to `package.json`. -- Updated dependencies - - @backstage/backend-plugin-api@0.6.19-next.3 - - @backstage/integration@1.12.0-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.9-next.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.9-next.2 - - @backstage/plugin-scaffolder-node@0.4.5-next.3 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - -## 0.2.9-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@0.6.19-next.2 - - @backstage/integration@1.12.0-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.9-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.9-next.1 - - @backstage/plugin-scaffolder-node@0.4.5-next.2 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - -## 0.2.9-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@0.6.19-next.0 - - @backstage/plugin-scaffolder-node@0.4.5-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.9-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.9-next.0 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.11.0 - -## 0.2.8 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@0.6.18 - - @backstage/plugin-scaffolder-node@0.4.4 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.8 - - @backstage/integration@1.11.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.8 - -## 0.2.8-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.4.4-next.2 - - @backstage/integration@1.11.0-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.8-next.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.8-next.2 - -## 0.2.8-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.4.4-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.8-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.8-next.1 - - @backstage/backend-plugin-api@0.6.18-next.1 - -## 0.2.8-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.8-next.0 - - @backstage/backend-plugin-api@0.6.18-next.0 - - @backstage/plugin-scaffolder-node@0.4.4-next.0 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.10.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.8-next.0 - -## 0.2.7 - -### Patch Changes - -- 33f958a: Improve examples to ensure consistency across all publish actions -- Updated dependencies - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.7 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.7 - - @backstage/backend-plugin-api@0.6.17 - - @backstage/integration@1.10.0 - - @backstage/plugin-scaffolder-node@0.4.3 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - -## 0.2.7-next.1 - -### Patch Changes - -- 33f958a: Improve examples to ensure consistency across all publish actions -- Updated dependencies - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.7-next.1 - - @backstage/backend-plugin-api@0.6.17-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.7-next.1 - - @backstage/plugin-scaffolder-node@0.4.3-next.1 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.10.0-next.0 - -## 0.2.7-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.7-next.0 - - @backstage/integration@1.10.0-next.0 - - @backstage/backend-plugin-api@0.6.17-next.0 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.7-next.0 - - @backstage/plugin-scaffolder-node@0.4.3-next.0 - -## 0.2.6 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@0.6.16 - - @backstage/plugin-scaffolder-node@0.4.2 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.9.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.6 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.6 - -## 0.2.5 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.4.1 - - @backstage/backend-plugin-api@0.6.15 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/integration@1.9.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.5 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.5 - -## 0.2.4 - -### Patch Changes - -- 2bd1410: Removed unused dependencies -- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. - - It will help to maintain tests in a long run during structural changes of action context. - -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.4.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.4 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.4 - - @backstage/integration@1.9.1 - - @backstage/config@1.2.0 - - @backstage/errors@1.2.4 - - @backstage/backend-plugin-api@0.6.14 - -## 0.2.4-next.2 - -### Patch Changes - -- 2bd1410: Removed unused dependencies -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.4.0-next.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.4-next.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.4-next.2 - - @backstage/integration@1.9.1-next.2 - - @backstage/backend-plugin-api@0.6.14-next.2 - - @backstage/config@1.2.0-next.1 - - @backstage/errors@1.2.4-next.0 - -## 0.2.4-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/config@1.2.0-next.1 - - @backstage/plugin-scaffolder-node@0.4.0-next.1 - - @backstage/backend-common@0.21.4-next.1 - - @backstage/backend-plugin-api@0.6.14-next.1 - - @backstage/integration@1.9.1-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.4-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.4-next.1 - - @backstage/errors@1.2.4-next.0 - -## 0.2.3-next.0 - -### Patch Changes - -- f44589d: Introduced `createMockActionContext` to unify the way of creating scaffolder mock context. - - It will help to maintain tests in a long run during structural changes of action context. - -- Updated dependencies - - @backstage/backend-common@0.21.3-next.0 - - @backstage/errors@1.2.4-next.0 - - @backstage/plugin-scaffolder-node@0.3.3-next.0 - - @backstage/backend-plugin-api@0.6.13-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.3-next.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.3-next.0 - - @backstage/config@1.1.2-next.0 - - @backstage/integration@1.9.1-next.0 - -## 0.2.0 - -### Minor Changes - -- 5eb6882: Split `@backstage/plugin-scaffolder-backend-module-bitbucket` into - `@backstage/plugin-scaffolder-backend-module-bitbucket-cloud` and - `@backstage/plugin-scaffolder-backend-module-bitbucket-server`. - - `@backstage/plugin-scaffolder-backend-module-bitbucket` was **deprecated** in favor of these two replacements. - - Please use any of the two replacements depending on your needs. - - ```diff - - backend.add(import('@backstage/plugin-scaffolder-backend-module-bitbucket')); - + backend.add(import('@backstage/plugin-scaffolder-backend-module-bitbucket-cloud')); - + backend.add(import('@backstage/plugin-scaffolder-backend-module-bitbucket-server')); - ``` - -### Patch Changes - -- e9a5228: Exporting a default module for the new Backend System -- 8472188: Added or fixed the `repository` field in `package.json`. -- 6bb6f3e: Updated dependency `fs-extra` to `^11.2.0`. - Updated dependency `@types/fs-extra` to `^11.0.0`. -- fc98bb6: Enhanced the pull request action to allow for adding new content to the PR as described in this issue #21762 -- Updated dependencies - - @backstage/backend-common@0.21.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.0 - - @backstage/backend-plugin-api@0.6.10 - - @backstage/integration@1.9.0 - - @backstage/plugin-scaffolder-node@0.3.0 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.0 - - @backstage/config@1.1.1 - - @backstage/errors@1.2.3 - -## 0.2.0-next.3 - -### Patch Changes - -- 8472188: Added or fixed the `repository` field in `package.json`. -- Updated dependencies - - @backstage/backend-common@0.21.0-next.3 - - @backstage/integration@1.9.0-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.0-next.1 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.0-next.1 - - @backstage/plugin-scaffolder-node@0.3.0-next.3 - - @backstage/backend-plugin-api@0.6.10-next.3 - - @backstage/config@1.1.1 - - @backstage/errors@1.2.3 - -## 0.2.0-next.2 - -### Minor Changes - -- 5eb6882: Split `@backstage/plugin-scaffolder-backend-module-bitbucket` into - `@backstage/plugin-scaffolder-backend-module-bitbucket-cloud` and - `@backstage/plugin-scaffolder-backend-module-bitbucket-server`. - - `@backstage/plugin-scaffolder-backend-module-bitbucket` was **deprecated** in favor of these two replacements. - - Please use any of the two replacements depending on your needs. - - ```diff - - backend.add(import('@backstage/plugin-scaffolder-backend-module-bitbucket')); - + backend.add(import('@backstage/plugin-scaffolder-backend-module-bitbucket-cloud')); - + backend.add(import('@backstage/plugin-scaffolder-backend-module-bitbucket-server')); - ``` - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.0-next.0 - - @backstage/backend-common@0.21.0-next.2 - - @backstage/backend-plugin-api@0.6.10-next.2 - - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.0-next.0 - - @backstage/plugin-scaffolder-node@0.3.0-next.2 - - @backstage/config@1.1.1 - - @backstage/errors@1.2.3 - - @backstage/integration@1.9.0-next.0 - -## 0.1.2-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-plugin-api@0.6.10-next.1 - - @backstage/backend-common@0.21.0-next.1 - - @backstage/integration@1.9.0-next.0 - - @backstage/plugin-scaffolder-node@0.3.0-next.1 - - @backstage/config@1.1.1 - - @backstage/errors@1.2.3 - -## 0.1.2-next.0 - -### Patch Changes - -- e9a5228: Exporting a default module for the new Backend System -- fc98bb6: Enhanced the pull request action to allow for adding new content to the PR as described in this issue #21762 -- Updated dependencies - - @backstage/backend-common@0.21.0-next.0 - - @backstage/plugin-scaffolder-node@0.3.0-next.0 - - @backstage/backend-plugin-api@0.6.10-next.0 - - @backstage/config@1.1.1 - - @backstage/errors@1.2.3 - - @backstage/integration@1.8.0 - -## 0.1.1 - -### Patch Changes - -- a694f71: The Scaffolder builtin actions now contains an action for running pipelines from Bitbucket Cloud Rest API -- Updated dependencies - - @backstage/backend-common@0.20.1 - - @backstage/plugin-scaffolder-node@0.2.10 - - @backstage/config@1.1.1 - - @backstage/errors@1.2.3 - - @backstage/integration@1.8.0 - -## 0.1.1-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.20.1-next.2 - - @backstage/plugin-scaffolder-node@0.2.10-next.2 - -## 0.1.1-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.20.1-next.1 - - @backstage/integration@1.8.0 - - @backstage/config@1.1.1 - - @backstage/plugin-scaffolder-node@0.2.10-next.1 - - @backstage/errors@1.2.3 - -## 0.1.1-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.20.1-next.0 - - @backstage/config@1.1.1 - - @backstage/errors@1.2.3 - - @backstage/integration@1.8.0 - - @backstage/plugin-scaffolder-node@0.2.10-next.0 - -## 0.1.0 - -### Minor Changes - -- 219d7f0: Create new scaffolder module for external integrations - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.20.0 - - @backstage/plugin-scaffolder-node@0.2.9 - - @backstage/integration@1.8.0 - - @backstage/config@1.1.1 - - @backstage/errors@1.2.3 - -## 0.1.0-next.0 - -### Minor Changes - -- 219d7f0: Create new scaffolder module for external integrations - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-scaffolder-node@0.2.9-next.3 - - @backstage/backend-common@0.20.0-next.3 - - @backstage/config@1.1.1 - - @backstage/errors@1.2.3 - - @backstage/integration@1.8.0-next.1 diff --git a/plugins/scaffolder-backend-module-bitbucket/README.md b/plugins/scaffolder-backend-module-bitbucket/README.md deleted file mode 100644 index dde4207c0a..0000000000 --- a/plugins/scaffolder-backend-module-bitbucket/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# @backstage/plugin-scaffolder-backend-module-bitbucket - -**Deprecated!** - -Please use one of the following modules instead: - -- [@backstage/plugin-scaffolder-backend-module-bitbucket-cloud](https://www.npmjs.com/package/@backstage/plugin-scaffolder-backend-module-bitbucket-cloud) -- [@backstage/plugin-scaffolder-backend-module-bitbucket-server](https://www.npmjs.com/package/@backstage/plugin-scaffolder-backend-module-bitbucket-server). diff --git a/plugins/scaffolder-backend-module-bitbucket/catalog-info.yaml b/plugins/scaffolder-backend-module-bitbucket/catalog-info.yaml deleted file mode 100644 index b0a94d1c13..0000000000 --- a/plugins/scaffolder-backend-module-bitbucket/catalog-info.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: backstage-plugin-scaffolder-backend-module-bitbucket - title: '@backstage/plugin-scaffolder-backend-module-bitbucket' - description: The bitbucket module for @backstage/plugin-scaffolder-backend -spec: - lifecycle: experimental - type: backstage-backend-plugin-module - owner: maintainers diff --git a/plugins/scaffolder-backend-module-bitbucket/knip-report.md b/plugins/scaffolder-backend-module-bitbucket/knip-report.md deleted file mode 100644 index c8b2aa1788..0000000000 --- a/plugins/scaffolder-backend-module-bitbucket/knip-report.md +++ /dev/null @@ -1,8 +0,0 @@ -# Knip report - -## Unused dependencies (1) - -| Name | Location | Severity | -| :------- | :----------- | :------- | -| fs-extra | plugins/scaffolder-backend-module-bitbucket/package.json | error | - diff --git a/plugins/scaffolder-backend-module-bitbucket/package.json b/plugins/scaffolder-backend-module-bitbucket/package.json deleted file mode 100644 index d048f9dcc9..0000000000 --- a/plugins/scaffolder-backend-module-bitbucket/package.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "name": "@backstage/plugin-scaffolder-backend-module-bitbucket", - "version": "0.3.20-next.0", - "description": "The bitbucket module for @backstage/plugin-scaffolder-backend", - "backstage": { - "role": "backend-plugin-module", - "pluginId": "scaffolder", - "pluginPackage": "@backstage/plugin-scaffolder-backend" - }, - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "https://github.com/backstage/backstage", - "directory": "plugins/scaffolder-backend-module-bitbucket" - }, - "license": "Apache-2.0", - "exports": { - ".": "./src/index.ts", - "./package.json": "./package.json" - }, - "main": "src/index.ts", - "types": "src/index.ts", - "typesVersions": { - "*": { - "package.json": [ - "package.json" - ] - } - }, - "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", - "start": "backstage-cli package start", - "test": "backstage-cli package test" - }, - "dependencies": { - "@backstage/backend-plugin-api": "workspace:^", - "@backstage/config": "workspace:^", - "@backstage/errors": "workspace:^", - "@backstage/integration": "workspace:^", - "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "workspace:^", - "@backstage/plugin-scaffolder-backend-module-bitbucket-server": "workspace:^", - "@backstage/plugin-scaffolder-node": "workspace:^", - "fs-extra": "^11.2.0", - "yaml": "^2.0.0" - }, - "devDependencies": { - "@backstage/backend-test-utils": "workspace:^", - "@backstage/cli": "workspace:^", - "@backstage/plugin-scaffolder-node-test-utils": "workspace:^", - "msw": "^1.0.0" - }, - "deprecated": true -} diff --git a/plugins/scaffolder-backend-module-bitbucket/report.api.md b/plugins/scaffolder-backend-module-bitbucket/report.api.md deleted file mode 100644 index 33c9bcc9bd..0000000000 --- a/plugins/scaffolder-backend-module-bitbucket/report.api.md +++ /dev/null @@ -1,110 +0,0 @@ -## API Report File for "@backstage/plugin-scaffolder-backend-module-bitbucket" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; -import * as bitbucketCloud from '@backstage/plugin-scaffolder-backend-module-bitbucket-cloud'; -import * as bitbucketServer from '@backstage/plugin-scaffolder-backend-module-bitbucket-server'; -import { Config } from '@backstage/config'; -import { ScmIntegrationRegistry } from '@backstage/integration'; -import { TemplateAction } from '@backstage/plugin-scaffolder-node'; - -// @public @deprecated -const bitbucketModule: BackendFeature; -export default bitbucketModule; - -// @public @deprecated (undocumented) -export const createBitbucketPipelinesRunAction: (options: { - integrations: ScmIntegrationRegistry; -}) => TemplateAction< - { - workspace: string; - repo_slug: string; - body?: - | { - target?: - | { - type?: string | undefined; - source?: string | undefined; - selector?: - | { - type: string; - pattern: string; - } - | undefined; - pull_request?: - | { - id: string; - } - | undefined; - commit?: - | { - type: string; - hash: string; - } - | undefined; - destination?: string | undefined; - ref_name?: string | undefined; - ref_type?: string | undefined; - destination_commit?: - | { - hash: string; - } - | undefined; - } - | undefined; - variables?: - | { - key: string; - value: string; - secured: boolean; - }[] - | undefined; - } - | undefined; - token?: string | undefined; - }, - { - buildNumber?: number | undefined; - repoUrl?: string | undefined; - pipelinesUrl?: string | undefined; - }, - 'v2' ->; - -// @public @deprecated -export function createPublishBitbucketAction(options: { - integrations: ScmIntegrationRegistry; - config: Config; -}): TemplateAction< - { - repoUrl: string; - description?: string | undefined; - repoVisibility?: 'private' | 'public' | undefined; - defaultBranch?: string | undefined; - sourcePath?: string | undefined; - enableLFS?: boolean | undefined; - token?: string | undefined; - gitCommitMessage?: string | undefined; - gitAuthorName?: string | undefined; - gitAuthorEmail?: string | undefined; - signCommit?: boolean | undefined; - }, - { - remoteUrl?: string | undefined; - repoContentsUrl?: string | undefined; - commitHash?: string | undefined; - }, - 'v2' ->; - -// @public @deprecated (undocumented) -export const createPublishBitbucketCloudAction: typeof bitbucketCloud.createPublishBitbucketCloudAction; - -// @public @deprecated (undocumented) -export const createPublishBitbucketServerAction: typeof bitbucketServer.createPublishBitbucketServerAction; - -// @public @deprecated (undocumented) -export const createPublishBitbucketServerPullRequestAction: typeof bitbucketServer.createPublishBitbucketServerPullRequestAction; -``` diff --git a/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.examples.test.ts b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.examples.test.ts deleted file mode 100644 index 8496405abf..0000000000 --- a/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.examples.test.ts +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright 2023 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -jest.mock('@backstage/plugin-scaffolder-node', () => { - return { - ...jest.requireActual('@backstage/plugin-scaffolder-node'), - initRepoAndPush: jest.fn().mockResolvedValue({ - commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', - }), - commitAndPushRepo: jest.fn().mockResolvedValue({ - commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', - }), - }; -}); - -import { createPublishBitbucketAction } from './bitbucket'; -import { rest } from 'msw'; -import { setupServer } from 'msw/node'; -import { registerMswTestHooks } from '@backstage/backend-test-utils'; -import { ScmIntegrations } from '@backstage/integration'; -import { ConfigReader } from '@backstage/config'; -import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; -import yaml from 'yaml'; -import { sep } from 'node:path'; -import { examples } from './bitbucket.examples'; -import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; - -describe('publish:bitbucket', () => { - const config = new ConfigReader({ - integrations: { - bitbucket: [ - { - host: 'bitbucket.org', - token: 'tokenlols', - }, - { - host: 'hosted.bitbucket.com', - token: 'thing', - apiBaseUrl: 'https://hosted.bitbucket.com/rest/api/1.0', - }, - { - host: 'notoken.bitbucket.com', - }, - ], - }, - }); - - const integrations = ScmIntegrations.fromConfig(config); - const action = createPublishBitbucketAction({ integrations, config }); - const mockContext = createMockActionContext({ - input: { - repoUrl: 'bitbucket.org?workspace=workspace&project=project&repo=repo', - repoVisibility: 'private' as const, - }, - }); - const server = setupServer(); - registerMswTestHooks(server); - - beforeEach(() => { - jest.resetAllMocks(); - }); - - it('should call initAndPush with the correct values', async () => { - server.use( - rest.post( - 'https://api.bitbucket.org/2.0/repositories/workspace/repo', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json({ - links: { - html: { - href: 'https://bitbucket.org/workspace/repo', - }, - clone: [ - { - name: 'https', - href: 'https://bitbucket.org/workspace/cloneurl', - }, - ], - }, - }), - ), - ), - ); - - await action.handler({ - ...mockContext, - input: yaml.parse(examples[0].example).steps[0].input, - }); - - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: mockContext.workspacePath, - remoteUrl: 'https://bitbucket.org/workspace/cloneurl', - defaultBranch: 'master', - auth: { username: 'x-token-auth', password: 'tokenlols' }, - logger: mockContext.logger, - commitMessage: 'initial commit', - gitAuthorInfo: { email: undefined, name: undefined }, - }); - }); - - it('should call initAndPush with the correct default branch', async () => { - server.use( - rest.post( - 'https://api.bitbucket.org/2.0/repositories/workspace/repo', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json({ - links: { - html: { - href: 'https://bitbucket.org/workspace/repo', - }, - clone: [ - { - name: 'https', - href: 'https://bitbucket.org/workspace/cloneurl', - }, - ], - }, - }), - ), - ), - ); - - await action.handler({ - ...mockContext, - input: yaml.parse(examples[3].example).steps[0].input, - }); - - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: mockContext.workspacePath, - remoteUrl: 'https://bitbucket.org/workspace/cloneurl', - defaultBranch: 'main', - auth: { username: 'x-token-auth', password: 'tokenlols' }, - logger: mockContext.logger, - commitMessage: 'initial commit', - gitAuthorInfo: { email: undefined, name: undefined }, - }); - }); - - it('should call initAndPush with the specified source path', async () => { - server.use( - rest.post( - 'https://api.bitbucket.org/2.0/repositories/workspace/repo', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json({ - links: { - html: { - href: 'https://bitbucket.org/workspace/repo', - }, - clone: [ - { - name: 'https', - href: 'https://bitbucket.org/workspace/cloneurl', - }, - ], - }, - }), - ), - ), - ); - - await action.handler({ - ...mockContext, - input: yaml.parse(examples[4].example).steps[0].input, - }); - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: `${mockContext.workspacePath}${sep}repoRoot`, - remoteUrl: 'https://bitbucket.org/workspace/cloneurl', - auth: { username: 'x-token-auth', password: 'tokenlols' }, - logger: mockContext.logger, - defaultBranch: 'master', - commitMessage: 'initial commit', - gitAuthorInfo: { email: undefined, name: undefined }, - }); - }); - - it('should call initAndPush with the authentication token', async () => { - server.use( - rest.post( - 'https://api.bitbucket.org/2.0/repositories/workspace/repo', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json({ - links: { - html: { - href: 'https://bitbucket.org/workspace/repo', - }, - clone: [ - { - name: 'https', - href: 'https://bitbucket.org/workspace/cloneurl', - }, - ], - }, - }), - ), - ), - ); - - await action.handler({ - ...mockContext, - input: yaml.parse(examples[6].example).steps[0].input, - }); - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: mockContext.workspacePath, - remoteUrl: 'https://bitbucket.org/workspace/cloneurl', - auth: { username: 'x-token-auth', password: 'your-auth-token' }, - logger: mockContext.logger, - defaultBranch: 'master', - commitMessage: 'initial commit', - gitAuthorInfo: { - email: undefined, - name: undefined, - }, - }); - }); - - it('should call initAndPush with the custom commit message', async () => { - server.use( - rest.post( - 'https://api.bitbucket.org/2.0/repositories/workspace/repo', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json({ - links: { - html: { - href: 'https://bitbucket.org/workspace/repo', - }, - clone: [ - { - name: 'https', - href: 'https://bitbucket.org/workspace/cloneurl', - }, - ], - }, - }), - ), - ), - ); - - await action.handler({ - ...mockContext, - input: yaml.parse(examples[7].example).steps[0].input, - }); - - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: mockContext.workspacePath, - remoteUrl: 'https://bitbucket.org/workspace/cloneurl', - auth: { username: 'x-token-auth', password: 'tokenlols' }, - logger: mockContext.logger, - defaultBranch: 'master', - commitMessage: 'Initial commit with custom message', - gitAuthorInfo: { email: undefined, name: undefined }, - }); - }); - - it('should call initAndPush with the custom author name and email for the commit.', async () => { - server.use( - rest.post( - 'https://api.bitbucket.org/2.0/repositories/workspace/repo', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json({ - links: { - html: { - href: 'https://bitbucket.org/workspace/repo', - }, - clone: [ - { - name: 'https', - href: 'https://bitbucket.org/workspace/cloneurl', - }, - ], - }, - }), - ), - ), - ); - - await action.handler({ - ...mockContext, - input: yaml.parse(examples[8].example).steps[0].input, - }); - - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: mockContext.workspacePath, - remoteUrl: 'https://bitbucket.org/workspace/cloneurl', - auth: { username: 'x-token-auth', password: 'tokenlols' }, - logger: mockContext.logger, - defaultBranch: 'master', - commitMessage: 'initial commit', - gitAuthorInfo: { email: 'your.email@example.com', name: 'Your Name' }, - }); - }); - - describe('LFS for hosted bitbucket', () => { - const repoCreationResponse = { - links: { - self: [ - { - href: 'https://bitbucket.mycompany.com/projects/project/repos/repo', - }, - ], - clone: [ - { - name: 'http', - href: 'https://bitbucket.mycompany.com/scm/project/repo', - }, - ], - }, - }; - - it('should call the correct APIs to enable LFS if requested and the host is hosted bitbucket', async () => { - expect.assertions(1); - server.use( - rest.post( - 'https://hosted.bitbucket.com/rest/api/1.0/projects/project/repos', - (_, res, ctx) => { - return res( - ctx.status(201), - ctx.set('Content-Type', 'application/json'), - ctx.json(repoCreationResponse), - ); - }, - ), - rest.put( - 'https://hosted.bitbucket.com/rest/git-lfs/admin/projects/project/repos/repo/enabled', - (req, res, ctx) => { - expect(req.headers.get('Authorization')).toBe('Bearer thing'); - return res(ctx.status(204)); - }, - ), - ); - - await action.handler({ - ...mockContext, - input: yaml.parse(examples[5].example).steps[0].input, - }); - }); - }); -}); diff --git a/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.examples.ts b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.examples.ts deleted file mode 100644 index 6248c991f8..0000000000 --- a/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.examples.ts +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2023 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { TemplateExample } from '@backstage/plugin-scaffolder-node'; -import yaml from 'yaml'; - -export const examples: TemplateExample[] = [ - { - description: - 'Initializes a git repository with the content in the workspace, and publishes it to Bitbucket with the default configuration.', - example: yaml.stringify({ - steps: [ - { - id: 'publish', - action: 'publish:bitbucket', - name: 'Publish to Bitbucket', - input: { - repoUrl: - 'bitbucket.org?repo=repo&workspace=workspace&project=project', - }, - }, - ], - }), - }, - { - description: 'Initializes a Bitbucket repository with a description.', - example: yaml.stringify({ - steps: [ - { - id: 'publish', - action: 'publish:bitbucket', - name: 'Publish to Bitbucket', - input: { - repoUrl: - 'bitbucket.org?repo=repo&workspace=workspace&project=project', - description: 'Initialize a git repository', - }, - }, - ], - }), - }, - { - description: - 'Initializes a Bitbucket repository with public repo visibility, if not set defaults to private', - example: yaml.stringify({ - steps: [ - { - id: 'publish', - action: 'publish:bitbucket', - name: 'Publish to Bitbucket', - input: { - repoUrl: - 'bitbucket.org?repo=repo&workspace=workspace&project=project', - repoVisibility: 'public', - }, - }, - ], - }), - }, - { - description: - 'Initializes a Bitbucket repository with a default branch, if not set defaults to master', - example: yaml.stringify({ - steps: [ - { - id: 'publish', - action: 'publish:bitbucket', - name: 'Publish to Bitbucket', - input: { - repoUrl: - 'bitbucket.org?repo=repo&workspace=workspace&project=project', - defaultBranch: 'main', - }, - }, - ], - }), - }, - { - description: - 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository', - example: yaml.stringify({ - steps: [ - { - id: 'publish', - action: 'publish:bitbucket', - name: 'Publish to Bitbucket', - input: { - repoUrl: - 'bitbucket.org?repo=repo&workspace=workspace&project=project', - sourcePath: './repoRoot', - }, - }, - ], - }), - }, - { - description: 'Initializes a Bitbucket repository with LFS enabled', - example: yaml.stringify({ - steps: [ - { - id: 'publish', - action: 'publish:bitbucket', - name: 'Publish to Bitbucket', - input: { - repoUrl: 'hosted.bitbucket.com?project=project&repo=repo', - enableLFS: true, - }, - }, - ], - }), - }, - { - description: - 'Initializes a Bitbucket repository with a custom authentication token', - example: yaml.stringify({ - steps: [ - { - id: 'publish', - action: 'publish:bitbucket', - name: 'Publish to Bitbucket', - input: { - repoUrl: - 'bitbucket.org?repo=repo&workspace=workspace&project=project', - token: 'your-auth-token', - }, - }, - ], - }), - }, - { - description: - 'Initializes a Bitbucket repository with an initial commit message, if not set defaults to `initial commit`', - example: yaml.stringify({ - steps: [ - { - id: 'publish', - action: 'publish:bitbucket', - name: 'Publish to Bitbucket', - input: { - repoUrl: - 'bitbucket.org?repo=repo&workspace=workspace&project=project', - gitCommitMessage: 'Initial commit with custom message', - }, - }, - ], - }), - }, - { - description: 'Initializes a Bitbucket repository with a custom author', - example: yaml.stringify({ - steps: [ - { - id: 'publish', - action: 'publish:bitbucket', - name: 'Publish to Bitbucket', - input: { - repoUrl: - 'bitbucket.org?repo=repo&workspace=workspace&project=project', - gitAuthorName: 'Your Name', - gitAuthorEmail: 'your.email@example.com', - }, - }, - ], - }), - }, - { - description: - 'Initializes a Bitbucket repository with all properties being set', - example: yaml.stringify({ - steps: [ - { - id: 'publish', - action: 'publish:bitbucket', - name: 'Publish to Bitbucket', - input: { - repoUrl: - 'bitbucket.org?repo=repo&workspace=workspace&project=project', - description: 'Initialize a git repository', - repoVisibility: 'public', - defaultBranch: 'main', - token: 'your-auth-token', - gitCommitMessage: 'Initial commit with custom message', - gitAuthorName: 'Your Name', - gitAuthorEmail: 'your.email@example.com', - }, - }, - ], - }), - }, -]; diff --git a/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.test.ts b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.test.ts deleted file mode 100644 index 654b0fffcb..0000000000 --- a/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.test.ts +++ /dev/null @@ -1,619 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -jest.mock('@backstage/plugin-scaffolder-node', () => { - return { - ...jest.requireActual('@backstage/plugin-scaffolder-node'), - initRepoAndPush: jest.fn().mockResolvedValue({ - commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', - }), - commitAndPushRepo: jest.fn().mockResolvedValue({ - commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', - }), - }; -}); -import { createPublishBitbucketAction } from './bitbucket'; -import { rest } from 'msw'; -import { setupServer } from 'msw/node'; -import { registerMswTestHooks } from '@backstage/backend-test-utils'; -import { ScmIntegrations } from '@backstage/integration'; -import { ConfigReader } from '@backstage/config'; -import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; -import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; - -describe('publish:bitbucket', () => { - const config = new ConfigReader({ - integrations: { - bitbucket: [ - { - host: 'bitbucket.org', - token: 'tokenlols', - }, - { - host: 'hosted.bitbucket.com', - token: 'thing', - apiBaseUrl: 'https://hosted.bitbucket.com/rest/api/1.0', - }, - { - host: 'notoken.bitbucket.com', - }, - ], - }, - }); - - const integrations = ScmIntegrations.fromConfig(config); - const action = createPublishBitbucketAction({ integrations, config }); - const mockContext = createMockActionContext({ - input: { - repoUrl: 'bitbucket.org?workspace=workspace&project=project&repo=repo', - repoVisibility: 'private' as const, - }, - }); - const server = setupServer(); - registerMswTestHooks(server); - - beforeEach(() => { - jest.resetAllMocks(); - }); - - it('should throw an error when the repoUrl is not well formed', async () => { - await expect( - action.handler({ - ...mockContext, - input: { repoUrl: 'bitbucket.org?project=project&repo=repo' }, - }), - ).rejects.toThrow(/missing workspace/); - - await expect( - action.handler({ - ...mockContext, - input: { repoUrl: 'bitbucket.org?workspace=workspace&repo=repo' }, - }), - ).rejects.toThrow(/missing project/); - - await expect( - action.handler({ - ...mockContext, - input: { repoUrl: 'bitbucket.org?workspace=workspace&project=project' }, - }), - ).rejects.toThrow(/missing repo/); - }); - - it('should throw if there is no integration config provided', async () => { - await expect( - action.handler({ - ...mockContext, - input: { - repoUrl: 'missing.com?workspace=workspace&project=project&repo=repo', - }, - }), - ).rejects.toThrow(/No matching integration configuration/); - }); - - it('should throw if there is no token in the integration config that is returned', async () => { - await expect( - action.handler({ - ...mockContext, - input: { - repoUrl: - 'notoken.bitbucket.com?workspace=workspace&project=project&repo=repo', - }, - }), - ).rejects.toThrow(/Authorization has not been provided for Bitbucket/); - }); - - it('should call the correct APIs when the host is bitbucket cloud', async () => { - expect.assertions(2); - server.use( - rest.post( - 'https://api.bitbucket.org/2.0/repositories/workspace/repo', - (req, res, ctx) => { - expect(req.headers.get('Authorization')).toBe('Bearer tokenlols'); - expect(req.body).toEqual({ - is_private: true, - scm: 'git', - project: { key: 'project' }, - }); - return res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json({ - links: { - html: { - href: 'https://bitbucket.org/workspace/repo', - }, - clone: [ - { - name: 'https', - href: 'https://bitbucket.org/workspace/repo', - }, - ], - }, - }), - ); - }, - ), - ); - - await action.handler({ - ...mockContext, - input: { - ...mockContext.input, - repoUrl: 'bitbucket.org?workspace=workspace&project=project&repo=repo', - }, - }); - }); - - it('should call the correct APIs when the host is hosted bitbucket', async () => { - expect.assertions(2); - server.use( - rest.post( - 'https://hosted.bitbucket.com/rest/api/1.0/projects/project/repos', - (req, res, ctx) => { - expect(req.headers.get('Authorization')).toBe('Bearer thing'); - expect(req.body).toEqual({ public: false, name: 'repo' }); - return res( - ctx.status(201), - ctx.set('Content-Type', 'application/json'), - ctx.json({ - links: { - self: [ - { - href: 'https://bitbucket.mycompany.com/projects/project/repos/repo', - }, - ], - clone: [ - { - name: 'http', - href: 'https://bitbucket.mycompany.com/scm/project/repo', - }, - ], - }, - }), - ); - }, - ), - ); - - await action.handler({ - ...mockContext, - input: { - ...mockContext.input, - repoUrl: 'hosted.bitbucket.com?project=project&repo=repo', - }, - }); - }); - - it('should work if the token is provided through ctx.input', async () => { - expect.assertions(2); - server.use( - rest.post( - 'https://notoken.bitbucket.com/rest/api/1.0/projects/project/repos', - (req, res, ctx) => { - expect(req.headers.get('Authorization')).toBe('Bearer lols'); - expect(req.body).toEqual({ public: false, name: 'repo' }); - return res( - ctx.status(201), - ctx.set('Content-Type', 'application/json'), - ctx.json({ - links: { - self: [ - { - href: 'https://bitbucket.mycompany.com/projects/project/repos/repo', - }, - ], - clone: [ - { - name: 'http', - href: 'https://bitbucket.mycompany.com/scm/project/repo', - }, - ], - }, - }), - ); - }, - ), - ); - await action.handler({ - ...mockContext, - input: { - repoUrl: 'notoken.bitbucket.com?project=project&repo=repo', - token: 'lols', - }, - }); - }); - - describe('LFS for hosted bitbucket', () => { - const repoCreationResponse = { - links: { - self: [ - { - href: 'https://bitbucket.mycompany.com/projects/project/repos/repo', - }, - ], - clone: [ - { - name: 'http', - href: 'https://bitbucket.mycompany.com/scm/project/repo', - }, - ], - }, - }; - - it('should call the correct APIs to enable LFS if requested and the host is hosted bitbucket', async () => { - expect.assertions(1); - server.use( - rest.post( - 'https://hosted.bitbucket.com/rest/api/1.0/projects/project/repos', - (_, res, ctx) => { - return res( - ctx.status(201), - ctx.set('Content-Type', 'application/json'), - ctx.json(repoCreationResponse), - ); - }, - ), - rest.put( - 'https://hosted.bitbucket.com/rest/git-lfs/admin/projects/project/repos/repo/enabled', - (req, res, ctx) => { - expect(req.headers.get('Authorization')).toBe('Bearer thing'); - return res(ctx.status(204)); - }, - ), - ); - - await action.handler({ - ...mockContext, - input: { - ...mockContext.input, - repoUrl: 'hosted.bitbucket.com?project=project&repo=repo', - enableLFS: true, - }, - }); - }); - - it('should report an error if enabling LFS fails', async () => { - server.use( - rest.post( - 'https://hosted.bitbucket.com/rest/api/1.0/projects/project/repos', - (_, res, ctx) => { - return res( - ctx.status(201), - ctx.set('Content-Type', 'application/json'), - ctx.json(repoCreationResponse), - ); - }, - ), - rest.put( - 'https://hosted.bitbucket.com/rest/git-lfs/admin/projects/project/repos/repo/enabled', - (_, res, ctx) => { - return res(ctx.status(500)); - }, - ), - ); - - await expect( - action.handler({ - ...mockContext, - input: { - ...mockContext.input, - repoUrl: 'hosted.bitbucket.com?project=project&repo=repo', - enableLFS: true, - }, - }), - ).rejects.toThrow(/Failed to enable LFS/); - }); - }); - - it('should call initAndPush with the correct values', async () => { - server.use( - rest.post( - 'https://api.bitbucket.org/2.0/repositories/workspace/repo', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json({ - links: { - html: { - href: 'https://bitbucket.org/workspace/repo', - }, - clone: [ - { - name: 'https', - href: 'https://bitbucket.org/workspace/cloneurl', - }, - ], - }, - }), - ), - ), - ); - - await action.handler(mockContext); - - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: mockContext.workspacePath, - remoteUrl: 'https://bitbucket.org/workspace/cloneurl', - defaultBranch: 'master', - auth: { username: 'x-token-auth', password: 'tokenlols' }, - logger: mockContext.logger, - commitMessage: 'initial commit', - gitAuthorInfo: {}, - }); - }); - - it('should call initAndPush with the correct default branch', async () => { - server.use( - rest.post( - 'https://api.bitbucket.org/2.0/repositories/workspace/repo', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json({ - links: { - html: { - href: 'https://bitbucket.org/workspace/repo', - }, - clone: [ - { - name: 'https', - href: 'https://bitbucket.org/workspace/cloneurl', - }, - ], - }, - }), - ), - ), - ); - - await action.handler({ - ...mockContext, - input: { - ...mockContext.input, - defaultBranch: 'main', - }, - }); - - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: mockContext.workspacePath, - remoteUrl: 'https://bitbucket.org/workspace/cloneurl', - defaultBranch: 'main', - auth: { username: 'x-token-auth', password: 'tokenlols' }, - logger: mockContext.logger, - commitMessage: 'initial commit', - gitAuthorInfo: {}, - }); - }); - - it('should call initAndPush with the configured defaultAuthor', async () => { - const customAuthorConfig = new ConfigReader({ - integrations: { - bitbucket: [ - { - host: 'bitbucket.org', - token: 'tokenlols', - }, - { - host: 'hosted.bitbucket.com', - token: 'thing', - apiBaseUrl: 'https://hosted.bitbucket.com/rest/api/1.0', - }, - { - host: 'notoken.bitbucket.com', - }, - ], - }, - scaffolder: { - defaultAuthor: { - name: 'Test', - email: 'example@example.com', - }, - }, - }); - - const customAuthorIntegrations = - ScmIntegrations.fromConfig(customAuthorConfig); - const customAuthorAction = createPublishBitbucketAction({ - integrations: customAuthorIntegrations, - config: customAuthorConfig, - }); - - server.use( - rest.post( - 'https://api.bitbucket.org/2.0/repositories/workspace/repo', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json({ - links: { - html: { - href: 'https://bitbucket.org/workspace/repo', - }, - clone: [ - { - name: 'https', - href: 'https://bitbucket.org/workspace/cloneurl', - }, - ], - }, - }), - ), - ), - ); - - await customAuthorAction.handler(mockContext); - - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: mockContext.workspacePath, - remoteUrl: 'https://bitbucket.org/workspace/cloneurl', - auth: { username: 'x-token-auth', password: 'tokenlols' }, - logger: mockContext.logger, - defaultBranch: 'master', - commitMessage: 'initial commit', - gitAuthorInfo: { name: 'Test', email: 'example@example.com' }, - }); - }); - - it('should call initAndPush with the configured defaultCommitMessage', async () => { - const customAuthorConfig = new ConfigReader({ - integrations: { - bitbucket: [ - { - host: 'bitbucket.org', - token: 'tokenlols', - }, - { - host: 'hosted.bitbucket.com', - token: 'thing', - apiBaseUrl: 'https://hosted.bitbucket.com/rest/api/1.0', - }, - { - host: 'notoken.bitbucket.com', - }, - ], - }, - scaffolder: { - defaultCommitMessage: 'Test commit message', - }, - }); - - const customAuthorIntegrations = - ScmIntegrations.fromConfig(customAuthorConfig); - const customAuthorAction = createPublishBitbucketAction({ - integrations: customAuthorIntegrations, - config: customAuthorConfig, - }); - - server.use( - rest.post( - 'https://api.bitbucket.org/2.0/repositories/workspace/repo', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json({ - links: { - html: { - href: 'https://bitbucket.org/workspace/repo', - }, - clone: [ - { - name: 'https', - href: 'https://bitbucket.org/workspace/cloneurl', - }, - ], - }, - }), - ), - ), - ); - - await customAuthorAction.handler(mockContext); - - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: mockContext.workspacePath, - remoteUrl: 'https://bitbucket.org/workspace/cloneurl', - auth: { username: 'x-token-auth', password: 'tokenlols' }, - logger: mockContext.logger, - defaultBranch: 'master', - commitMessage: 'initial commit', - gitAuthorInfo: { email: undefined, name: undefined }, - }); - }); - - it('should call outputs with the correct urls', async () => { - server.use( - rest.post( - 'https://api.bitbucket.org/2.0/repositories/workspace/repo', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json({ - links: { - html: { - href: 'https://bitbucket.org/workspace/repo', - }, - clone: [ - { - name: 'https', - href: 'https://bitbucket.org/workspace/cloneurl', - }, - ], - }, - }), - ), - ), - ); - - await action.handler(mockContext); - - expect(mockContext.output).toHaveBeenCalledWith( - 'remoteUrl', - 'https://bitbucket.org/workspace/cloneurl', - ); - expect(mockContext.output).toHaveBeenCalledWith( - 'repoContentsUrl', - 'https://bitbucket.org/workspace/repo/src/master', - ); - }); - - it('should call outputs with the correct urls with correct default branch', async () => { - server.use( - rest.post( - 'https://api.bitbucket.org/2.0/repositories/workspace/repo', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json({ - links: { - html: { - href: 'https://bitbucket.org/workspace/repo', - }, - clone: [ - { - name: 'https', - href: 'https://bitbucket.org/workspace/cloneurl', - }, - ], - }, - }), - ), - ), - ); - - await action.handler({ - ...mockContext, - input: { - ...mockContext.input, - defaultBranch: 'main', - }, - }); - - expect(mockContext.output).toHaveBeenCalledWith( - 'remoteUrl', - 'https://bitbucket.org/workspace/cloneurl', - ); - expect(mockContext.output).toHaveBeenCalledWith( - 'repoContentsUrl', - 'https://bitbucket.org/workspace/repo/src/main', - ); - }); -}); diff --git a/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.ts b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.ts deleted file mode 100644 index 113e642ee8..0000000000 --- a/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.ts +++ /dev/null @@ -1,450 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { InputError } from '@backstage/errors'; -import { - BitbucketIntegrationConfig, - ScmIntegrationRegistry, -} from '@backstage/integration'; -import { - createTemplateAction, - getRepoSourceDirectory, - initRepoAndPush, - parseRepoUrl, -} from '@backstage/plugin-scaffolder-node'; -import { Config } from '@backstage/config'; -import { examples } from './bitbucket.examples'; - -const createBitbucketCloudRepository = async (opts: { - workspace: string; - project: string; - repo: string; - description?: string; - repoVisibility: 'private' | 'public'; - mainBranch: string; - authorization: string; - apiBaseUrl: string; -}) => { - const { - workspace, - project, - repo, - description, - repoVisibility, - mainBranch, - authorization, - apiBaseUrl, - } = opts; - - const options: RequestInit = { - method: 'POST', - body: JSON.stringify({ - scm: 'git', - description: description, - is_private: repoVisibility === 'private', - project: { key: project }, - }), - headers: { - Authorization: authorization, - 'Content-Type': 'application/json', - }, - }; - - let response: Response; - try { - response = await fetch( - `${apiBaseUrl}/repositories/${workspace}/${repo}`, - options, - ); - } catch (e) { - throw new Error(`Unable to create repository, ${e}`); - } - - if (response.status !== 200) { - throw new Error( - `Unable to create repository, ${response.status} ${ - response.statusText - }, ${await response.text()}`, - ); - } - - const r = await response.json(); - let remoteUrl = ''; - for (const link of r.links.clone) { - if (link.name === 'https') { - remoteUrl = link.href; - } - } - - // "mainbranch.name" cannot be set neither at create nor update of the repo - // the first pushed branch will be set as "main branch" then - const repoContentsUrl = `${r.links.html.href}/src/${mainBranch}`; - return { remoteUrl, repoContentsUrl }; -}; - -const createBitbucketServerRepository = async (opts: { - project: string; - repo: string; - description?: string; - repoVisibility: 'private' | 'public'; - authorization: string; - apiBaseUrl: string; -}) => { - const { - project, - repo, - description, - authorization, - repoVisibility, - apiBaseUrl, - } = opts; - - let response: Response; - const options: RequestInit = { - method: 'POST', - body: JSON.stringify({ - name: repo, - description: description, - public: repoVisibility === 'public', - }), - headers: { - Authorization: authorization, - 'Content-Type': 'application/json', - }, - }; - - try { - response = await fetch(`${apiBaseUrl}/projects/${project}/repos`, options); - } catch (e) { - throw new Error(`Unable to create repository, ${e}`); - } - - if (response.status !== 201) { - throw new Error( - `Unable to create repository, ${response.status} ${ - response.statusText - }, ${await response.text()}`, - ); - } - - const r = await response.json(); - let remoteUrl = ''; - for (const link of r.links.clone) { - if (link.name === 'http') { - remoteUrl = link.href; - } - } - - const repoContentsUrl = `${r.links.self[0].href}`; - return { remoteUrl, repoContentsUrl }; -}; - -const getAuthorizationHeader = (config: BitbucketIntegrationConfig) => { - if (config.username && (config.token ?? config.appPassword)) { - const buffer = Buffer.from( - `${config.username}:${config.token ?? config.appPassword}`, - 'utf8', - ); - - return `Basic ${buffer.toString('base64')}`; - } - - if (config.token) { - return `Bearer ${config.token}`; - } - - throw new Error( - `Authorization has not been provided for Bitbucket. Please add either provide a username and token or username and appPassword to the Integrations config`, - ); -}; - -const performEnableLFS = async (opts: { - authorization: string; - host: string; - project: string; - repo: string; -}) => { - const { authorization, host, project, repo } = opts; - - const options: RequestInit = { - method: 'PUT', - headers: { - Authorization: authorization, - }, - }; - - const { ok, status, statusText } = await fetch( - `https://${host}/rest/git-lfs/admin/projects/${project}/repos/${repo}/enabled`, - options, - ); - - if (!ok) - throw new Error( - `Failed to enable LFS in the repository, ${status}: ${statusText}`, - ); -}; - -/** - * Creates a new action that initializes a git repository of the content in the workspace - * and publishes it to Bitbucket. - * @public - * @deprecated in favor of "createPublishBitbucketCloudAction" by \@backstage/plugin-scaffolder-backend-module-bitbucket-cloud and "createPublishBitbucketServerAction" by \@backstage/plugin-scaffolder-backend-module-bitbucket-server - */ -export function createPublishBitbucketAction(options: { - integrations: ScmIntegrationRegistry; - config: Config; -}) { - const { integrations, config } = options; - - return createTemplateAction({ - id: 'publish:bitbucket', - description: - 'Initializes a git repository of the content in the workspace, and publishes it to Bitbucket.', - examples, - schema: { - input: { - repoUrl: z => - z.string({ - description: 'Repository Location', - }), - description: z => - z - .string({ - description: 'Repository Description', - }) - .optional(), - repoVisibility: z => - z - .enum(['private', 'public'], { - description: 'Repository Visibility', - }) - .optional(), - defaultBranch: z => - z - .string({ - description: `Sets the default branch on the repository. The default value is 'master'`, - }) - .optional(), - sourcePath: z => - z - .string({ - description: - 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.', - }) - .optional(), - enableLFS: z => - z - .boolean({ - description: - 'Enable LFS for the repository. Only available for hosted Bitbucket.', - }) - .optional(), - token: z => - z - .string({ - description: 'The token to use for authorization to BitBucket', - }) - .optional(), - gitCommitMessage: z => - z - .string({ - description: `Sets the commit message on the repository. The default value is 'initial commit'`, - }) - .optional(), - gitAuthorName: z => - z - .string({ - description: `Sets the default author name for the commit. The default value is 'Scaffolder'`, - }) - .optional(), - gitAuthorEmail: z => - z - .string({ - description: `Sets the default author email for the commit.`, - }) - .optional(), - signCommit: z => - z - .boolean({ - description: 'Sign commit with configured PGP private key', - }) - .optional(), - }, - output: { - remoteUrl: z => - z - .string({ - description: 'A URL to the repository with the provider', - }) - .optional(), - repoContentsUrl: z => - z - .string({ - description: 'A URL to the root of the repository', - }) - .optional(), - commitHash: z => - z - .string({ - description: 'The git commit hash of the initial commit', - }) - .optional(), - }, - }, - async handler(ctx) { - ctx.logger.warn( - `[Deprecated] Please migrate the use of action "publish:bitbucket" to "publish:bitbucketCloud" or "publish:bitbucketServer".`, - ); - const { - repoUrl, - description, - defaultBranch = 'master', - repoVisibility = 'private', - enableLFS = false, - gitCommitMessage = 'initial commit', - gitAuthorName, - gitAuthorEmail, - signCommit, - } = ctx.input; - - const { workspace, project, repo, host } = parseRepoUrl( - repoUrl, - integrations, - ); - - // Workspace is only required for bitbucket cloud - if (host === 'bitbucket.org') { - if (!workspace) { - throw new InputError( - `Invalid URL provider was included in the repo URL to create ${ctx.input.repoUrl}, missing workspace`, - ); - } - } - - // Project is required for both bitbucket cloud and bitbucket server - if (!project) { - throw new InputError( - `Invalid URL provider was included in the repo URL to create ${ctx.input.repoUrl}, missing project`, - ); - } - - const integrationConfig = integrations.bitbucket.byHost(host); - - if (!integrationConfig) { - throw new InputError( - `No matching integration configuration for host ${host}, please check your integrations config`, - ); - } - - const authorization = getAuthorizationHeader( - ctx.input.token - ? { - host: integrationConfig.config.host, - apiBaseUrl: integrationConfig.config.apiBaseUrl, - token: ctx.input.token, - } - : integrationConfig.config, - ); - - const apiBaseUrl = integrationConfig.config.apiBaseUrl; - - const createMethod = - host === 'bitbucket.org' - ? createBitbucketCloudRepository - : createBitbucketServerRepository; - - const { remoteUrl, repoContentsUrl } = await ctx.checkpoint({ - key: `create.repo.${host}.${repo}`, - fn: async () => - createMethod({ - authorization, - workspace: workspace || '', - project, - repo, - repoVisibility, - mainBranch: defaultBranch, - description, - apiBaseUrl, - }), - }); - - const gitAuthorInfo = { - name: gitAuthorName - ? gitAuthorName - : config.getOptionalString('scaffolder.defaultAuthor.name'), - email: gitAuthorEmail - ? gitAuthorEmail - : config.getOptionalString('scaffolder.defaultAuthor.email'), - }; - const signingKey = - integrationConfig.config.commitSigningKey ?? - config.getOptionalString('scaffolder.defaultCommitSigningKey'); - if (signCommit && !signingKey) { - throw new Error( - 'Signing commits is enabled but no signing key is provided in the configuration', - ); - } - - let auth; - - if (ctx.input.token) { - auth = { - username: 'x-token-auth', - password: ctx.input.token, - }; - } else { - auth = { - username: integrationConfig.config.username - ? integrationConfig.config.username - : 'x-token-auth', - password: integrationConfig.config.appPassword - ? integrationConfig.config.appPassword - : integrationConfig.config.token ?? '', - }; - } - - const commitHash = await ctx.checkpoint({ - key: `init.repo.and.push${host}.${repo}`, - fn: async () => { - const commitResult = await initRepoAndPush({ - dir: getRepoSourceDirectory( - ctx.workspacePath, - ctx.input.sourcePath, - ), - remoteUrl, - auth, - defaultBranch, - logger: ctx.logger, - commitMessage: gitCommitMessage - ? gitCommitMessage - : config.getOptionalString('scaffolder.defaultCommitMessage'), - gitAuthorInfo, - signingKey: signCommit ? signingKey : undefined, - }); - return commitResult?.commitHash; - }, - }); - - if (enableLFS && host !== 'bitbucket.org') { - await performEnableLFS({ authorization, host, project, repo }); - } - - ctx.output('commitHash', commitHash); - ctx.output('remoteUrl', remoteUrl); - ctx.output('repoContentsUrl', repoContentsUrl); - }, - }); -} diff --git a/plugins/scaffolder-backend-module-bitbucket/src/deprecated.ts b/plugins/scaffolder-backend-module-bitbucket/src/deprecated.ts deleted file mode 100644 index a9daa771f0..0000000000 --- a/plugins/scaffolder-backend-module-bitbucket/src/deprecated.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import * as bitbucketCloud from '@backstage/plugin-scaffolder-backend-module-bitbucket-cloud'; -import * as bitbucketServer from '@backstage/plugin-scaffolder-backend-module-bitbucket-server'; - -export { createPublishBitbucketAction } from './actions/bitbucket'; - -/** - * @public - * @deprecated use import from `@backstage/plugin-scaffolder-backend-module-bitbucket-cloud` instead - */ -export const createPublishBitbucketCloudAction = - bitbucketCloud.createPublishBitbucketCloudAction; - -/** - * @public - * @deprecated use import from `@backstage/plugin-scaffolder-backend-module-bitbucket-cloud` instead - */ -export const createBitbucketPipelinesRunAction = - bitbucketCloud.createBitbucketPipelinesRunAction; - -/** - * @public - * @deprecated use import from `@backstage/plugin-scaffolder-backend-module-bitbucket-server` instead - */ -export const createPublishBitbucketServerAction = - bitbucketServer.createPublishBitbucketServerAction; - -/** - * @public - * @deprecated use import from `@backstage/plugin-scaffolder-backend-module-bitbucket-server` instead - */ -export const createPublishBitbucketServerPullRequestAction = - bitbucketServer.createPublishBitbucketServerPullRequestAction; diff --git a/plugins/scaffolder-backend-module-bitbucket/src/index.ts b/plugins/scaffolder-backend-module-bitbucket/src/index.ts deleted file mode 100644 index 7f68a3f395..0000000000 --- a/plugins/scaffolder-backend-module-bitbucket/src/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2023 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * A module for the scaffolder backend that lets you interact with bitbucket - * - * @packageDocumentation - */ - -export * from './deprecated'; -export { bitbucketModule as default } from './module'; diff --git a/plugins/scaffolder-backend-module-bitbucket/src/module.ts b/plugins/scaffolder-backend-module-bitbucket/src/module.ts deleted file mode 100644 index 884c8be004..0000000000 --- a/plugins/scaffolder-backend-module-bitbucket/src/module.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { - coreServices, - createBackendModule, -} from '@backstage/backend-plugin-api'; -import { scaffolderActionsExtensionPoint } from '@backstage/plugin-scaffolder-node'; -import { - createBitbucketPipelinesRunAction, - createPublishBitbucketCloudAction, - createPublishBitbucketServerAction, - createPublishBitbucketServerPullRequestAction, -} from './deprecated'; -import { ScmIntegrations } from '@backstage/integration'; - -/** - * The Bitbucket Module for the Scaffolder Backend - * @public - * @deprecated use module by \@backstage/plugin-scaffolder-backend-module-bitbucket-cloud or \@backstage/plugin-scaffolder-backend-module-bitbucket-server instead - */ -export const bitbucketModule = createBackendModule({ - moduleId: 'bitbucket', - pluginId: 'scaffolder', - register({ registerInit }) { - registerInit({ - deps: { - scaffolder: scaffolderActionsExtensionPoint, - config: coreServices.rootConfig, - }, - async init({ scaffolder, config }) { - const integrations = ScmIntegrations.fromConfig(config); - - scaffolder.addActions( - createPublishBitbucketCloudAction({ integrations, config }), - createPublishBitbucketServerAction({ integrations, config }), - createPublishBitbucketServerPullRequestAction({ - integrations, - config, - }), - createBitbucketPipelinesRunAction({ integrations }), - ); - }, - }); - }, -}); diff --git a/plugins/scaffolder-common/src/ScaffolderClient.ts b/plugins/scaffolder-common/src/ScaffolderClient.ts index d8aa5106c9..3aaa7ebefc 100644 --- a/plugins/scaffolder-common/src/ScaffolderClient.ts +++ b/plugins/scaffolder-common/src/ScaffolderClient.ts @@ -125,13 +125,6 @@ export class ScaffolderClient implements ScaffolderApi { ): Promise { const integrations = [ ...this.scmIntegrationsApi.azure.list(), - ...this.scmIntegrationsApi.bitbucket - .list() - .filter( - item => - !this.scmIntegrationsApi.bitbucketCloud.byHost(item.config.host) && - !this.scmIntegrationsApi.bitbucketServer.byHost(item.config.host), - ), ...this.scmIntegrationsApi.bitbucketCloud.list(), ...this.scmIntegrationsApi.bitbucketServer.list(), ...this.scmIntegrationsApi.gerrit.list(), diff --git a/plugins/scaffolder-node/src/actions/util.test.ts b/plugins/scaffolder-node/src/actions/util.test.ts index 792e306d00..8afbbf553a 100644 --- a/plugins/scaffolder-node/src/actions/util.test.ts +++ b/plugins/scaffolder-node/src/actions/util.test.ts @@ -54,11 +54,11 @@ describe('scaffolder action utils', () => { /No matching integration configuration for host/, ); }); - describe('bitbucket', () => { - beforeEach(() => byHost.mockReturnValue({ type: 'bitbucket' })); + describe('bitbucketCloud', () => { + beforeEach(() => byHost.mockReturnValue({ type: 'bitbucketCloud' })); describe('cloud', () => { const [host, workspace, project, repo] = [ - 'www.bitbucket.org', + 'bitbucket.org', 'foo', 'bar', 'baz', @@ -97,6 +97,9 @@ describe('scaffolder action utils', () => { repo, })); }); + }); + describe('bitbucketServer', () => { + beforeEach(() => byHost.mockReturnValue({ type: 'bitbucketServer' })); describe('other', () => { const [host, project, repo] = ['bitbucket.other', 'foo', 'bar']; it('requires project', () => diff --git a/plugins/scaffolder-node/src/actions/util.ts b/plugins/scaffolder-node/src/actions/util.ts index 0e90122cdd..e698306a45 100644 --- a/plugins/scaffolder-node/src/actions/util.ts +++ b/plugins/scaffolder-node/src/actions/util.ts @@ -84,10 +84,11 @@ export const parseRepoUrl = ( ]), ); switch (type) { - case 'bitbucket': { - if (host === 'www.bitbucket.org') { - checkRequiredParams(parsed, 'workspace'); - } + case 'bitbucketCloud': { + checkRequiredParams(parsed, 'workspace', 'project', 'repo'); + break; + } + case 'bitbucketServer': { checkRequiredParams(parsed, 'project', 'repo'); break; } diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts index 2b59775d3a..16552c1292 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts @@ -28,10 +28,12 @@ describe('RepoPicker Validation', () => { const config = new ConfigReader({ integrations: { - bitbucket: [ + bitbucketCloud: [ { host: 'bitbucket.org', }, + ], + bitbucketServer: [ { host: 'server.bitbucket.com', }, diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts index 682fc6bb2a..2f3c5deeb9 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts @@ -39,9 +39,16 @@ export const repoPickerValidation = ( 'Incomplete repository location provided, host not provided', ); } else { - if (integrationApi?.byHost(host)?.type === 'bitbucket') { + const integrationType = integrationApi?.byHost(host)?.type; + if ( + integrationType === 'bitbucketCloud' || + integrationType === 'bitbucketServer' + ) { // workspace is only applicable for bitbucket cloud - if (host === 'bitbucket.org' && !searchParams.get('workspace')) { + if ( + integrationType === 'bitbucketCloud' && + !searchParams.get('workspace') + ) { validation.addError( 'Incomplete repository location provided, workspace not provided', ); @@ -52,7 +59,7 @@ export const repoPickerValidation = ( 'Incomplete repository location provided, project not provided', ); } - } else if (integrationApi?.byHost(host)?.type === 'azure') { + } else if (integrationType === 'azure') { if (!searchParams.get('project')) { validation.addError( 'Incomplete repository location provided, project not provided', diff --git a/yarn.lock b/yarn.lock index 3f6c5e083f..3956198af0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6709,7 +6709,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-scaffolder-backend-module-bitbucket-cloud@workspace:^, @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@workspace:plugins/scaffolder-backend-module-bitbucket-cloud": +"@backstage/plugin-scaffolder-backend-module-bitbucket-cloud@workspace:plugins/scaffolder-backend-module-bitbucket-cloud": version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud@workspace:plugins/scaffolder-backend-module-bitbucket-cloud" dependencies: @@ -6730,7 +6730,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-scaffolder-backend-module-bitbucket-server@workspace:^, @backstage/plugin-scaffolder-backend-module-bitbucket-server@workspace:plugins/scaffolder-backend-module-bitbucket-server": +"@backstage/plugin-scaffolder-backend-module-bitbucket-server@workspace:plugins/scaffolder-backend-module-bitbucket-server": version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend-module-bitbucket-server@workspace:plugins/scaffolder-backend-module-bitbucket-server" dependencies: @@ -6748,26 +6748,6 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-scaffolder-backend-module-bitbucket@workspace:plugins/scaffolder-backend-module-bitbucket": - version: 0.0.0-use.local - resolution: "@backstage/plugin-scaffolder-backend-module-bitbucket@workspace:plugins/scaffolder-backend-module-bitbucket" - dependencies: - "@backstage/backend-plugin-api": "workspace:^" - "@backstage/backend-test-utils": "workspace:^" - "@backstage/cli": "workspace:^" - "@backstage/config": "workspace:^" - "@backstage/errors": "workspace:^" - "@backstage/integration": "workspace:^" - "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "workspace:^" - "@backstage/plugin-scaffolder-backend-module-bitbucket-server": "workspace:^" - "@backstage/plugin-scaffolder-node": "workspace:^" - "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" - fs-extra: "npm:^11.2.0" - msw: "npm:^1.0.0" - yaml: "npm:^2.0.0" - languageName: unknown - linkType: soft - "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown@workspace:plugins/scaffolder-backend-module-confluence-to-markdown": version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown@workspace:plugins/scaffolder-backend-module-confluence-to-markdown" From e27bd4e40fb58be4d0bee0b0948999b580c93917 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Fri, 13 Feb 2026 06:49:13 -0600 Subject: [PATCH 05/26] Added more changesets Signed-off-by: Andre Wanlin --- .changeset/cyan-falcons-serve.md | 5 +++++ .changeset/fine-poems-sit.md | 5 +++++ .changeset/silly-shrimps-start.md | 5 +++++ 3 files changed, 15 insertions(+) create mode 100644 .changeset/cyan-falcons-serve.md create mode 100644 .changeset/fine-poems-sit.md create mode 100644 .changeset/silly-shrimps-start.md diff --git a/.changeset/cyan-falcons-serve.md b/.changeset/cyan-falcons-serve.md new file mode 100644 index 0000000000..82a13b4fb3 --- /dev/null +++ b/.changeset/cyan-falcons-serve.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Removed check for deprecated `bitbucket` integration from `repoPickerValidation` function used by the `RepoUrlPicker`, it now validates the `bitbucketServer` and `bitbucketCloud` integrations instead. diff --git a/.changeset/fine-poems-sit.md b/.changeset/fine-poems-sit.md new file mode 100644 index 0000000000..a6a92c4027 --- /dev/null +++ b/.changeset/fine-poems-sit.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Removed `@backstage/plugin-scaffolder-backend-module-bitbucket` from `package.json` as the package itself has been deprecated and the code deleted. diff --git a/.changeset/silly-shrimps-start.md b/.changeset/silly-shrimps-start.md new file mode 100644 index 0000000000..b0777243b0 --- /dev/null +++ b/.changeset/silly-shrimps-start.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-node': patch +--- + +Removed deprecated `bitbucket` integration from being used in the `parseRepoUrl` function. It will use the `bitbucketCloud` or `bitbucketServer` integrations instead. From 5da7c6c5c256fb3198c256ff93f85b1ee0cc02c3 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Sat, 21 Feb 2026 07:05:16 -0600 Subject: [PATCH 06/26] Add check for removed config Signed-off-by: Andre Wanlin --- packages/integration/src/azure/config.ts | 74 ++++++++---------------- 1 file changed, 25 insertions(+), 49 deletions(-) diff --git a/packages/integration/src/azure/config.ts b/packages/integration/src/azure/config.ts index 0213475cc8..2f6a08a43c 100644 --- a/packages/integration/src/azure/config.ts +++ b/packages/integration/src/azure/config.ts @@ -218,9 +218,17 @@ function asAzureDevOpsCredential( export function readAzureIntegrationConfig( config: Config, ): AzureIntegrationConfig { + deprecatedConfigCheck(config); + const host = config.getOptionalString('host') ?? AZURE_HOST; - let credentialConfigs = config + if (!isValidHost(host)) { + throw new Error( + `Invalid Azure integration config, '${host}' is not a valid host`, + ); + } + + const credentialConfigs = config .getOptionalConfigArray('credentials') ?.map(credential => { const result: Partial = { @@ -239,54 +247,6 @@ export function readAzureIntegrationConfig( return result; }); - const token = config.getOptionalString('token')?.trim(); - - if ( - config.getOptional('credential') !== undefined && - config.getOptional('credentials') !== undefined - ) { - throw new Error( - `Invalid Azure integration config, 'credential' and 'credentials' cannot be used together. Use 'credentials' instead.`, - ); - } - - if ( - config.getOptional('token') !== undefined && - config.getOptional('credentials') !== undefined - ) { - throw new Error( - `Invalid Azure integration config, 'token' and 'credentials' cannot be used together. Use 'credentials' instead.`, - ); - } - - if (token !== undefined) { - const mapped = [{ personalAccessToken: token }]; - credentialConfigs = credentialConfigs?.concat(mapped) ?? mapped; - } - - if (config.getOptional('credential') !== undefined) { - const mapped = [ - { - organizations: config.getOptionalStringArray( - 'credential.organizations', - ), - token: config.getOptionalString('credential.token')?.trim(), - tenantId: config.getOptionalString('credential.tenantId'), - clientId: config.getOptionalString('credential.clientId'), - clientSecret: config - .getOptionalString('credential.clientSecret') - ?.trim(), - }, - ]; - credentialConfigs = credentialConfigs?.concat(mapped) ?? mapped; - } - - if (!isValidHost(host)) { - throw new Error( - `Invalid Azure integration config, '${host}' is not a valid host`, - ); - } - let credentials: AzureDevOpsCredential[] | undefined = undefined; if (credentialConfigs !== undefined) { const errors = credentialConfigs @@ -397,3 +357,19 @@ export function readAzureIntegrationConfigs( return result; } + +/** + * These config sections have been removed but to insure they + * don't leak sensitive tokens we have this check in place + * to throw an error if found + * + * @internal + * @deprecated To be removed at a later date + */ +export function deprecatedConfigCheck(config: Config) { + if (config.getOptional('credential') || config.getOptional('token')) { + throw new Error( + `Invalid Azure integration config, 'credential' and 'token' have been removed. Use 'credentials' instead.`, + ); + } +} From c6e0bc40bd94df70237ffa6d94c74434170b380a Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Sat, 21 Feb 2026 07:08:31 -0600 Subject: [PATCH 07/26] Changeset feedback Signed-off-by: Andre Wanlin --- .changeset/sharp-ravens-shop.md | 2 +- .changeset/silly-shrimps-start.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.changeset/sharp-ravens-shop.md b/.changeset/sharp-ravens-shop.md index eb7486c490..55a8b0fe41 100644 --- a/.changeset/sharp-ravens-shop.md +++ b/.changeset/sharp-ravens-shop.md @@ -4,7 +4,7 @@ **BREAKING** Removed deprecated Azure DevOps, Bitbucket, Gerrit and GitHub code: -- For Azure Devops, the long deprecated `token` string and `credential` object have been removed from the `config.d.ts`. Use the `credentials` array object instead. +- For Azure DevOps, the long deprecated `token` string and `credential` object have been removed from the `config.d.ts`. Use the `credentials` array object instead. - For Bitbucket, the long deprecated `bitbucket` object has been removed from the `config.d.ts`. Use the `bitbucketCloud` or `bitbucketServer` objects instead. - For Gerrit, the `parseGerritGitilesUrl` function has been removed, use `parseGitilesUrlRef` instead. The `buildGerritGitilesArchiveUrl` function has also been removed, use `buildGerritGitilesArchiveUrlFromLocation` instead. - For GitHub, the `getGitHubRequestOptions` function has been removed. diff --git a/.changeset/silly-shrimps-start.md b/.changeset/silly-shrimps-start.md index b0777243b0..a6baac94b7 100644 --- a/.changeset/silly-shrimps-start.md +++ b/.changeset/silly-shrimps-start.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-scaffolder-node': patch +'@backstage/plugin-scaffolder-node': minor --- -Removed deprecated `bitbucket` integration from being used in the `parseRepoUrl` function. It will use the `bitbucketCloud` or `bitbucketServer` integrations instead. +**BREAKING** Removed deprecated `bitbucket` integration from being used in the `parseRepoUrl` function. It will use the `bitbucketCloud` or `bitbucketServer` integrations instead. From d8116c463d2e46ad49c900f6ce764cd6796f6f78 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Sat, 21 Feb 2026 07:25:52 -0600 Subject: [PATCH 08/26] Latest feedback Signed-off-by: Andre Wanlin --- packages/integration/src/azure/config.ts | 4 +- packages/integration/src/gerrit/core.test.ts | 39 ++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/packages/integration/src/azure/config.ts b/packages/integration/src/azure/config.ts index 2f6a08a43c..3d6244d69a 100644 --- a/packages/integration/src/azure/config.ts +++ b/packages/integration/src/azure/config.ts @@ -359,14 +359,14 @@ export function readAzureIntegrationConfigs( } /** - * These config sections have been removed but to insure they + * These config sections have been removed but to ensure they * don't leak sensitive tokens we have this check in place * to throw an error if found * * @internal * @deprecated To be removed at a later date */ -export function deprecatedConfigCheck(config: Config) { +function deprecatedConfigCheck(config: Config) { if (config.getOptional('credential') || config.getOptional('token')) { throw new Error( `Invalid Azure integration config, 'credential' and 'token' have been removed. Use 'credentials' instead.`, diff --git a/packages/integration/src/gerrit/core.test.ts b/packages/integration/src/gerrit/core.test.ts index 60bd898008..b22b5f2caf 100644 --- a/packages/integration/src/gerrit/core.test.ts +++ b/packages/integration/src/gerrit/core.test.ts @@ -311,6 +311,45 @@ describe('gerrit core', () => { 'https://gerrit.com/a/projects/web%2Fproject/branches/master', ); }); + it('throws when ref type is not a branch (tag).', () => { + const config: GerritIntegrationConfig = { + host: 'gerrit.com', + baseUrl: 'https://gerrit.com', + gitilesBaseUrl: 'https://gerrit.com', + }; + expect(() => + getGerritBranchApiUrl( + config, + 'https://gerrit.com/web/project/+/refs/tags/v1.0.0/README.md', + ), + ).toThrow('Unsupported gitiles ref type: tag'); + }); + it('throws when ref type is not a branch (sha).', () => { + const config: GerritIntegrationConfig = { + host: 'gerrit.com', + baseUrl: 'https://gerrit.com', + gitilesBaseUrl: 'https://gerrit.com', + }; + expect(() => + getGerritBranchApiUrl( + config, + 'https://gerrit.com/web/project/+/157f862803d45b9d269f0e390f88aece1ded51e8/README.md', + ), + ).toThrow('Unsupported gitiles ref type: sha'); + }); + it('throws when ref type is not a branch (head).', () => { + const config: GerritIntegrationConfig = { + host: 'gerrit.com', + baseUrl: 'https://gerrit.com', + gitilesBaseUrl: 'https://gerrit.com', + }; + expect(() => + getGerritBranchApiUrl( + config, + 'https://gerrit.com/web/project/+/HEAD/README.md', + ), + ).toThrow('Unsupported gitiles ref type: head'); + }); }); describe('getGerritCloneRepoUrl', () => { From 120d4253263f52fb41043fb07691be930571655c Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Sat, 21 Feb 2026 08:57:53 -0600 Subject: [PATCH 09/26] Fixed failing tests Signed-off-by: Andre Wanlin --- .../src/azure/AzureIntegration.test.ts | 2 +- .../AzureDevOpsDiscoveryProcessor.test.ts | 24 +++++++++++++++---- .../fetch/cookiecutter.examples.test.ts | 17 ++++--------- .../src/actions/fetch/cookiecutter.test.ts | 17 ++++--------- .../fetch/rails/index.examples.test.ts | 17 ++++--------- .../src/actions/fetch/rails/index.test.ts | 17 ++++--------- 6 files changed, 41 insertions(+), 53 deletions(-) diff --git a/packages/integration/src/azure/AzureIntegration.test.ts b/packages/integration/src/azure/AzureIntegration.test.ts index c30283f432..e6a903814a 100644 --- a/packages/integration/src/azure/AzureIntegration.test.ts +++ b/packages/integration/src/azure/AzureIntegration.test.ts @@ -25,7 +25,7 @@ describe('AzureIntegration', () => { azure: [ { host: 'h.com', - token: 'token', + credentials: [{ personalAccessToken: 'token' }], }, ], }, diff --git a/plugins/catalog-backend-module-azure/src/processors/AzureDevOpsDiscoveryProcessor.test.ts b/plugins/catalog-backend-module-azure/src/processors/AzureDevOpsDiscoveryProcessor.test.ts index e692be66e3..1281306c0e 100644 --- a/plugins/catalog-backend-module-azure/src/processors/AzureDevOpsDiscoveryProcessor.test.ts +++ b/plugins/catalog-backend-module-azure/src/processors/AzureDevOpsDiscoveryProcessor.test.ts @@ -103,7 +103,12 @@ describe('AzureDevOpsDiscoveryProcessor', () => { const processor = AzureDevOpsDiscoveryProcessor.fromConfig( new ConfigReader({ integrations: { - azure: [{ host: 'dev.azure.com', token: 'blob' }], + azure: [ + { + host: 'dev.azure.com', + credentials: [{ personalAccessToken: 'token' }], + }, + ], }, }), { logger: mockServices.logger.mock() }, @@ -123,8 +128,14 @@ describe('AzureDevOpsDiscoveryProcessor', () => { new ConfigReader({ integrations: { github: [ - { host: 'dev.azure.com', token: 'blob' }, - { host: 'azure.myorg.com', token: 'blob' }, + { + host: 'dev.azure.com', + credentials: [{ personalAccessToken: 'token' }], + }, + { + host: 'azure.myorg.com', + credentials: [{ personalAccessToken: 'token' }], + }, ], }, }), @@ -145,7 +156,12 @@ describe('AzureDevOpsDiscoveryProcessor', () => { const processor = AzureDevOpsDiscoveryProcessor.fromConfig( new ConfigReader({ integrations: { - github: [{ host: 'dev.azure.com', token: 'blob' }], + github: [ + { + host: 'dev.azure.com', + credentials: [{ personalAccessToken: 'token' }], + }, + ], }, }), { logger: mockServices.logger.mock() }, diff --git a/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.examples.test.ts b/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.examples.test.ts index 98ea001bc1..3797651420 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.examples.test.ts +++ b/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.examples.test.ts @@ -14,10 +14,12 @@ * limitations under the License. */ -import { ConfigReader } from '@backstage/config'; import { JsonObject } from '@backstage/types'; import { ScmIntegrations } from '@backstage/integration'; -import { createMockDirectory } from '@backstage/backend-test-utils'; +import { + createMockDirectory, + mockServices, +} from '@backstage/backend-test-utils'; import { createFetchCookiecutterAction } from './cookiecutter'; import { join } from 'node:path'; import type { ActionContext } from '@backstage/plugin-scaffolder-node'; @@ -46,16 +48,7 @@ jest.mock( describe('fetch:cookiecutter', () => { const mockDir = createMockDirectory({ mockOsTmpDir: true }); - const integrations = ScmIntegrations.fromConfig( - new ConfigReader({ - integrations: { - azure: [ - { host: 'dev.azure.com', token: 'tokenlols' }, - { host: 'myazurehostnotoken.com' }, - ], - }, - }), - ); + const integrations = ScmIntegrations.fromConfig(mockServices.rootConfig()); const mockTmpDir = mockDir.path; diff --git a/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts b/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts index 2013206036..9b5dd31fc6 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts +++ b/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts @@ -14,10 +14,12 @@ * limitations under the License. */ -import { ConfigReader } from '@backstage/config'; import { JsonObject } from '@backstage/types'; import { ScmIntegrations } from '@backstage/integration'; -import { createMockDirectory } from '@backstage/backend-test-utils'; +import { + createMockDirectory, + mockServices, +} from '@backstage/backend-test-utils'; import { createFetchCookiecutterAction } from './cookiecutter'; import { join } from 'node:path'; import type { ActionContext } from '@backstage/plugin-scaffolder-node'; @@ -45,16 +47,7 @@ jest.mock( describe('fetch:cookiecutter', () => { const mockDir = createMockDirectory({ mockOsTmpDir: true }); - const integrations = ScmIntegrations.fromConfig( - new ConfigReader({ - integrations: { - azure: [ - { host: 'dev.azure.com', token: 'tokenlols' }, - { host: 'myazurehostnotoken.com' }, - ], - }, - }), - ); + const integrations = ScmIntegrations.fromConfig(mockServices.rootConfig()); const mockTmpDir = mockDir.path; diff --git a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.examples.test.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.examples.test.ts index 751751642a..5ad1eba2fb 100644 --- a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.examples.test.ts +++ b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.examples.test.ts @@ -27,12 +27,14 @@ jest.mock('./railsNewRunner', () => { }; }); -import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; import { resolve as resolvePath } from 'node:path'; import { createFetchRailsAction } from './index'; import { fetchContents } from '@backstage/plugin-scaffolder-node'; -import { createMockDirectory } from '@backstage/backend-test-utils'; +import { + createMockDirectory, + mockServices, +} from '@backstage/backend-test-utils'; import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { examples } from './index.examples'; import yaml from 'yaml'; @@ -41,16 +43,7 @@ import { ContainerRunner } from './ContainerRunner'; describe('fetch:rails', () => { const mockDir = createMockDirectory(); - const integrations = ScmIntegrations.fromConfig( - new ConfigReader({ - integrations: { - azure: [ - { host: 'dev.azure.com', token: 'tokenlols' }, - { host: 'myazurehostnotoken.com' }, - ], - }, - }), - ); + const integrations = ScmIntegrations.fromConfig(mockServices.rootConfig()); const mockContext = createMockActionContext({ input: { diff --git a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts index c9b4ad2646..a538066f59 100644 --- a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts +++ b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts @@ -27,12 +27,14 @@ jest.mock('./railsNewRunner', () => { }; }); -import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; import { resolve as resolvePath } from 'node:path'; import { createFetchRailsAction } from './index'; import { fetchContents } from '@backstage/plugin-scaffolder-node'; -import { createMockDirectory } from '@backstage/backend-test-utils'; +import { + createMockDirectory, + mockServices, +} from '@backstage/backend-test-utils'; import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; import { Writable } from 'node:stream'; import { UrlReaderService } from '@backstage/backend-plugin-api'; @@ -40,16 +42,7 @@ import { ContainerRunner } from './ContainerRunner'; describe('fetch:rails', () => { const mockDir = createMockDirectory(); - const integrations = ScmIntegrations.fromConfig( - new ConfigReader({ - integrations: { - azure: [ - { host: 'dev.azure.com', token: 'tokenlols' }, - { host: 'myazurehostnotoken.com' }, - ], - }, - }), - ); + const integrations = ScmIntegrations.fromConfig(mockServices.rootConfig()); const mockContext = createMockActionContext({ input: { From 56d01c7a7d254c6898446e1fa97616b16061e11f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 27 Feb 2026 20:22:28 +0100 Subject: [PATCH 10/26] test-utils: add `const` type parameter modifier to TestApiProvider and TestApiRegistry.from Signed-off-by: Patrik Oldsberg --- .changeset/fix-test-api-provider-const.md | 5 +++++ packages/test-utils/report.api.md | 4 ++-- packages/test-utils/src/testUtils/TestApiProvider.tsx | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 .changeset/fix-test-api-provider-const.md diff --git a/.changeset/fix-test-api-provider-const.md b/.changeset/fix-test-api-provider-const.md new file mode 100644 index 0000000000..b2bc0f49cd --- /dev/null +++ b/.changeset/fix-test-api-provider-const.md @@ -0,0 +1,5 @@ +--- +'@backstage/test-utils': patch +--- + +Added `const` type parameter modifier to `TestApiProvider` and `TestApiRegistry.from` for improved type inference of API pairs. diff --git a/packages/test-utils/report.api.md b/packages/test-utils/report.api.md index b3cf84b5ae..f830cde655 100644 --- a/packages/test-utils/report.api.md +++ b/packages/test-utils/report.api.md @@ -340,7 +340,7 @@ export function setupRequestMockHandlers(worker: { export type SyncLogCollector = () => void; // @public -export const TestApiProvider: ( +export const TestApiProvider: ( props: TestApiProviderProps, ) => JSX_2.Element; @@ -352,7 +352,7 @@ export type TestApiProviderProps = { // @public export class TestApiRegistry implements ApiHolder { - static from( + static from( ...apis: readonly [...TestApiProviderPropsApiPairs] ): TestApiRegistry; get(api: ApiRef): T | undefined; diff --git a/packages/test-utils/src/testUtils/TestApiProvider.tsx b/packages/test-utils/src/testUtils/TestApiProvider.tsx index 18a7174201..63e8a56f3b 100644 --- a/packages/test-utils/src/testUtils/TestApiProvider.tsx +++ b/packages/test-utils/src/testUtils/TestApiProvider.tsx @@ -63,7 +63,7 @@ export class TestApiRegistry implements ApiHolder { * @public * @param apis - A list of pairs mapping an ApiRef to its respective implementation. */ - static from( + static from( ...apis: readonly [...TestApiProviderPropsApiPairs] ) { return new TestApiRegistry( @@ -124,7 +124,7 @@ export class TestApiRegistry implements ApiHolder { * * @public */ -export const TestApiProvider = ( +export const TestApiProvider = ( props: TestApiProviderProps, ) => { return ( From ce7894007fedddd55f4f47db70b5f3254b9e34be Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 27 Feb 2026 20:24:25 +0100 Subject: [PATCH 11/26] patches: add pr-33057 to patch release Signed-off-by: Patrik Oldsberg --- .patches/pr-33057.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 .patches/pr-33057.txt diff --git a/.patches/pr-33057.txt b/.patches/pr-33057.txt new file mode 100644 index 0000000000..9f17de4205 --- /dev/null +++ b/.patches/pr-33057.txt @@ -0,0 +1 @@ +Added `const` type parameter modifier to `TestApiProvider` and `TestApiRegistry.from` in `@backstage/test-utils` for improved type inference of API pairs. \ No newline at end of file From a39b080302a8c6c4013620700b75a1da401610eb Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 27 Feb 2026 21:03:05 +0100 Subject: [PATCH 12/26] patches: remove pr-33057 from patch release Signed-off-by: Patrik Oldsberg --- .patches/pr-33057.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .patches/pr-33057.txt diff --git a/.patches/pr-33057.txt b/.patches/pr-33057.txt deleted file mode 100644 index 9f17de4205..0000000000 --- a/.patches/pr-33057.txt +++ /dev/null @@ -1 +0,0 @@ -Added `const` type parameter modifier to `TestApiProvider` and `TestApiRegistry.from` in `@backstage/test-utils` for improved type inference of API pairs. \ No newline at end of file From 479282f38e0fcd60385059a6e93bb7cf99910f10 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 27 Feb 2026 21:13:25 +0100 Subject: [PATCH 13/26] frontend-test-utils: fix TestApiPair type inference for tuple syntax Signed-off-by: Patrik Oldsberg --- .changeset/fix-test-api-pair-inference.md | 5 +++++ .changeset/fix-test-api-provider-const.md | 5 ----- .patches/pr-33057.txt | 1 + packages/frontend-test-utils/report.api.md | 2 +- packages/frontend-test-utils/src/apis/TestApiProvider.tsx | 2 +- packages/test-utils/report.api.md | 4 ++-- packages/test-utils/src/testUtils/TestApiProvider.tsx | 4 ++-- 7 files changed, 12 insertions(+), 11 deletions(-) create mode 100644 .changeset/fix-test-api-pair-inference.md delete mode 100644 .changeset/fix-test-api-provider-const.md create mode 100644 .patches/pr-33057.txt diff --git a/.changeset/fix-test-api-pair-inference.md b/.changeset/fix-test-api-pair-inference.md new file mode 100644 index 0000000000..d527a27600 --- /dev/null +++ b/.changeset/fix-test-api-pair-inference.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-test-utils': patch +--- + +Fixed type inference of `TestApiPair` when using tuple syntax by wrapping `MockWithApiFactory` in `NoInfer`. diff --git a/.changeset/fix-test-api-provider-const.md b/.changeset/fix-test-api-provider-const.md deleted file mode 100644 index b2bc0f49cd..0000000000 --- a/.changeset/fix-test-api-provider-const.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/test-utils': patch ---- - -Added `const` type parameter modifier to `TestApiProvider` and `TestApiRegistry.from` for improved type inference of API pairs. diff --git a/.patches/pr-33057.txt b/.patches/pr-33057.txt new file mode 100644 index 0000000000..3499e84a89 --- /dev/null +++ b/.patches/pr-33057.txt @@ -0,0 +1 @@ +Fixed a type inference issue with the `apis` option of testing utilities in `@backstage/frontend-test-utils`. \ No newline at end of file diff --git a/packages/frontend-test-utils/report.api.md b/packages/frontend-test-utils/report.api.md index 1cba02f393..a17c2ed483 100644 --- a/packages/frontend-test-utils/report.api.md +++ b/packages/frontend-test-utils/report.api.md @@ -443,7 +443,7 @@ export type RenderTestAppOptions = { // @public export type TestApiPair = | readonly [ApiRef, TApi extends infer TImpl ? Partial : never] - | MockWithApiFactory; + | MockWithApiFactory>; // @public export type TestApiPairs = { diff --git a/packages/frontend-test-utils/src/apis/TestApiProvider.tsx b/packages/frontend-test-utils/src/apis/TestApiProvider.tsx index 215e8c8a71..d0eca87a33 100644 --- a/packages/frontend-test-utils/src/apis/TestApiProvider.tsx +++ b/packages/frontend-test-utils/src/apis/TestApiProvider.tsx @@ -29,7 +29,7 @@ import { */ export type TestApiPair = | readonly [ApiRef, TApi extends infer TImpl ? Partial : never] - | MockWithApiFactory; + | MockWithApiFactory>; /** * Represents an array of mock API implementation. diff --git a/packages/test-utils/report.api.md b/packages/test-utils/report.api.md index f830cde655..b3cf84b5ae 100644 --- a/packages/test-utils/report.api.md +++ b/packages/test-utils/report.api.md @@ -340,7 +340,7 @@ export function setupRequestMockHandlers(worker: { export type SyncLogCollector = () => void; // @public -export const TestApiProvider: ( +export const TestApiProvider: ( props: TestApiProviderProps, ) => JSX_2.Element; @@ -352,7 +352,7 @@ export type TestApiProviderProps = { // @public export class TestApiRegistry implements ApiHolder { - static from( + static from( ...apis: readonly [...TestApiProviderPropsApiPairs] ): TestApiRegistry; get(api: ApiRef): T | undefined; diff --git a/packages/test-utils/src/testUtils/TestApiProvider.tsx b/packages/test-utils/src/testUtils/TestApiProvider.tsx index 63e8a56f3b..18a7174201 100644 --- a/packages/test-utils/src/testUtils/TestApiProvider.tsx +++ b/packages/test-utils/src/testUtils/TestApiProvider.tsx @@ -63,7 +63,7 @@ export class TestApiRegistry implements ApiHolder { * @public * @param apis - A list of pairs mapping an ApiRef to its respective implementation. */ - static from( + static from( ...apis: readonly [...TestApiProviderPropsApiPairs] ) { return new TestApiRegistry( @@ -124,7 +124,7 @@ export class TestApiRegistry implements ApiHolder { * * @public */ -export const TestApiProvider = ( +export const TestApiProvider = ( props: TestApiProviderProps, ) => { return ( From fba2809b20996c676d6d5ef98c619b0633741aed Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 27 Feb 2026 23:45:54 +0100 Subject: [PATCH 14/26] frontend-test-utils: add type tests for TestApiProvider Signed-off-by: Patrik Oldsberg --- .../src/apis/TestApiProvider.test.tsx | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 packages/frontend-test-utils/src/apis/TestApiProvider.test.tsx diff --git a/packages/frontend-test-utils/src/apis/TestApiProvider.test.tsx b/packages/frontend-test-utils/src/apis/TestApiProvider.test.tsx new file mode 100644 index 0000000000..1bb5673751 --- /dev/null +++ b/packages/frontend-test-utils/src/apis/TestApiProvider.test.tsx @@ -0,0 +1,95 @@ +/* + * 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 { createApiRef } from '@backstage/frontend-plugin-api'; +import { TestApiProvider } from './TestApiProvider'; +import { mockApis } from './mockApis'; +import { render, screen } from '@testing-library/react'; + +const xApiRef = createApiRef<{ a: string; b: number }>({ + id: 'x', +}); +const yApiRef = createApiRef({ + id: 'y', +}); + +describe('TestApiProvider', () => { + it('should provide tuple APIs and check types', () => { + render( + +
+ , + ); + }); + + it('should allow partial API implementations', () => { + render( + +
+ , + ); + }); + + it('should reject mismatched types in tuple syntax', () => { + render( + // @ts-expect-error - a should be a string, not a number + +
+ , + ); + }); + + it('should accept MockWithApiFactory entries', () => { + render( + +
+ , + ); + }); + + it('should accept a mix of tuples and MockWithApiFactory entries', () => { + render( + +
+ , + ); + }); + + it('should allow empty APIs', () => { + render( + +
+ , + ); + }); + + it('should provide APIs at runtime', async () => { + const alertApi = mockApis.alert(); + + render( + + rendered + , + ); + + expect(await screen.findByText('rendered')).toBeInTheDocument(); + }); +}); From 1ccad86e356bd0b4ada8b5cddd2b2a24a3200912 Mon Sep 17 00:00:00 2001 From: Ben Lambert Date: Sat, 28 Feb 2026 10:08:46 +0100 Subject: [PATCH 15/26] feat(auth-backend): add who-am-i action to actions registry (#33046) Signed-off-by: benjdlambert --- .changeset/add-who-am-i-action.md | 5 + .../src/actions/createWhoAmIAction.test.ts | 101 ++++++++++++++++++ .../src/actions/createWhoAmIAction.ts | 92 ++++++++++++++++ plugins/auth-backend/src/actions/index.ts | 28 +++++ plugins/auth-backend/src/authPlugin.ts | 8 ++ 5 files changed, 234 insertions(+) create mode 100644 .changeset/add-who-am-i-action.md create mode 100644 plugins/auth-backend/src/actions/createWhoAmIAction.test.ts create mode 100644 plugins/auth-backend/src/actions/createWhoAmIAction.ts create mode 100644 plugins/auth-backend/src/actions/index.ts diff --git a/.changeset/add-who-am-i-action.md b/.changeset/add-who-am-i-action.md new file mode 100644 index 0000000000..5c1008a7e1 --- /dev/null +++ b/.changeset/add-who-am-i-action.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +Added `who-am-i` action to the auth backend actions registry. Returns the catalog entity and user info for the currently authenticated user. diff --git a/plugins/auth-backend/src/actions/createWhoAmIAction.test.ts b/plugins/auth-backend/src/actions/createWhoAmIAction.test.ts new file mode 100644 index 0000000000..6de064e3e9 --- /dev/null +++ b/plugins/auth-backend/src/actions/createWhoAmIAction.test.ts @@ -0,0 +1,101 @@ +/* + * Copyright 2025 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 { mockCredentials, mockServices } from '@backstage/backend-test-utils'; +import { actionsRegistryServiceMock } from '@backstage/backend-test-utils/alpha'; +import { catalogServiceMock } from '@backstage/plugin-catalog-node/testUtils'; +import { createWhoAmIAction } from './createWhoAmIAction'; + +const mockUserEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + name: 'mock', + namespace: 'default', + }, + spec: { + profile: { + displayName: 'Mock User', + email: 'mock@example.com', + }, + }, +}; + +describe('createWhoAmIAction', () => { + it('should return the user entity and user info for authenticated user credentials', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + + createWhoAmIAction({ + auth: mockServices.auth(), + catalog: catalogServiceMock({ entities: [mockUserEntity] }), + userInfo: mockServices.userInfo(), + actionsRegistry: mockActionsRegistry, + }); + + const result = await mockActionsRegistry.invoke({ + id: 'test:who-am-i', + input: {}, + credentials: mockCredentials.user(), + }); + + expect(result.output).toEqual({ + entity: mockUserEntity, + userInfo: { + userEntityRef: 'user:default/mock', + ownershipEntityRefs: ['user:default/mock'], + }, + }); + }); + + it('should throw when called with service credentials', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + + createWhoAmIAction({ + auth: mockServices.auth(), + catalog: catalogServiceMock({ entities: [mockUserEntity] }), + userInfo: mockServices.userInfo(), + actionsRegistry: mockActionsRegistry, + }); + + await expect( + mockActionsRegistry.invoke({ + id: 'test:who-am-i', + input: {}, + credentials: mockCredentials.service(), + }), + ).rejects.toThrow('This action requires user credentials'); + }); + + it('should throw when the user entity is not found in the catalog', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + + createWhoAmIAction({ + auth: mockServices.auth(), + catalog: catalogServiceMock(), + userInfo: mockServices.userInfo(), + actionsRegistry: mockActionsRegistry, + }); + + await expect( + mockActionsRegistry.invoke({ + id: 'test:who-am-i', + input: {}, + credentials: mockCredentials.user(), + }), + ).rejects.toThrow( + 'User entity not found in the catalog for "user:default/mock"', + ); + }); +}); diff --git a/plugins/auth-backend/src/actions/createWhoAmIAction.ts b/plugins/auth-backend/src/actions/createWhoAmIAction.ts new file mode 100644 index 0000000000..2a9817bf57 --- /dev/null +++ b/plugins/auth-backend/src/actions/createWhoAmIAction.ts @@ -0,0 +1,92 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { AuthService, UserInfoService } from '@backstage/backend-plugin-api'; +import { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha'; +import { NotAllowedError, NotFoundError } from '@backstage/errors'; +import { CatalogService } from '@backstage/plugin-catalog-node'; + +export const createWhoAmIAction = ({ + auth, + catalog, + userInfo, + actionsRegistry, +}: { + auth: AuthService; + catalog: CatalogService; + userInfo: UserInfoService; + actionsRegistry: ActionsRegistryService; +}) => { + actionsRegistry.register({ + name: 'who-am-i', + title: 'Who Am I', + attributes: { + destructive: false, + readOnly: true, + idempotent: true, + }, + description: + 'Returns the catalog entity and user info for the currently authenticated user. This action requires user credentials and cannot be used with service or unauthenticated credentials.', + schema: { + input: z => z.object({}), + output: z => + z.object({ + entity: z + .object({}) + .passthrough() + .describe('The full catalog entity for the authenticated user'), + userInfo: z + .object({ + userEntityRef: z + .string() + .describe( + 'The entity ref of the user, e.g. user:default/jane.doe', + ), + ownershipEntityRefs: z + .array(z.string()) + .describe('Entity refs that the user claims ownership through'), + }) + .describe( + 'User identity information extracted from the authentication token', + ), + }), + }, + action: async ({ credentials }) => { + if (!auth.isPrincipal(credentials, 'user')) { + throw new NotAllowedError('This action requires user credentials'); + } + + const { userEntityRef } = credentials.principal; + + const [entity, info] = await Promise.all([ + catalog.getEntityByRef(userEntityRef, { credentials }), + userInfo.getUserInfo(credentials), + ]); + + if (!entity) { + throw new NotFoundError( + `User entity not found in the catalog for "${userEntityRef}"`, + ); + } + + return { + output: { + entity, + userInfo: info, + }, + }; + }, + }); +}; diff --git a/plugins/auth-backend/src/actions/index.ts b/plugins/auth-backend/src/actions/index.ts new file mode 100644 index 0000000000..28c611cca0 --- /dev/null +++ b/plugins/auth-backend/src/actions/index.ts @@ -0,0 +1,28 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { AuthService, UserInfoService } from '@backstage/backend-plugin-api'; +import { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha'; +import { CatalogService } from '@backstage/plugin-catalog-node'; +import { createWhoAmIAction } from './createWhoAmIAction'; + +export const createAuthActions = (options: { + auth: AuthService; + actionsRegistry: ActionsRegistryService; + catalog: CatalogService; + userInfo: UserInfoService; +}) => { + createWhoAmIAction(options); +}; diff --git a/plugins/auth-backend/src/authPlugin.ts b/plugins/auth-backend/src/authPlugin.ts index df42ddce9e..3e721d18a7 100644 --- a/plugins/auth-backend/src/authPlugin.ts +++ b/plugins/auth-backend/src/authPlugin.ts @@ -24,7 +24,9 @@ import { AuthProviderFactory, authProvidersExtensionPoint, } from '@backstage/plugin-auth-node'; +import { actionsRegistryServiceRef } from '@backstage/backend-plugin-api/alpha'; import { catalogServiceRef } from '@backstage/plugin-catalog-node'; +import { createAuthActions } from './actions'; import { createRouter } from './service/router'; import { OfflineAccessService } from './service/OfflineAccessService'; @@ -70,6 +72,8 @@ export const authPlugin = createBackendPlugin({ httpAuth: coreServices.httpAuth, lifecycle: coreServices.lifecycle, catalog: catalogServiceRef, + actionsRegistry: actionsRegistryServiceRef, + userInfo: coreServices.userInfo, }, async init({ httpRouter, @@ -81,6 +85,8 @@ export const authPlugin = createBackendPlugin({ httpAuth, lifecycle, catalog, + actionsRegistry, + userInfo, }) { const refreshTokensEnabled = config.getOptionalBoolean( 'auth.experimentalRefreshToken.enabled', @@ -112,6 +118,8 @@ export const authPlugin = createBackendPlugin({ allow: 'unauthenticated', }); httpRouter.use(router); + + createAuthActions({ auth, catalog, userInfo, actionsRegistry }); }, }); }, From 233c33f2debd03e99c1d7225dc0276d932e8583f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 28 Feb 2026 14:44:33 +0100 Subject: [PATCH 16/26] Rename top-level contentOrder to defaultContentOrder in entity page config Signed-off-by: Patrik Oldsberg --- .../entity-page-group-aliases-and-ordering-catalog.md | 2 +- docs/features/software-catalog/catalog-customization.md | 6 +++--- packages/app/app-config.yaml | 2 +- plugins/catalog/report-alpha.api.md | 8 ++++---- plugins/catalog/src/alpha/pages.test.tsx | 4 ++-- plugins/catalog/src/alpha/pages.tsx | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.changeset/entity-page-group-aliases-and-ordering-catalog.md b/.changeset/entity-page-group-aliases-and-ordering-catalog.md index c2a17ae773..5db7c0fc4b 100644 --- a/.changeset/entity-page-group-aliases-and-ordering-catalog.md +++ b/.changeset/entity-page-group-aliases-and-ordering-catalog.md @@ -2,4 +2,4 @@ '@backstage/plugin-catalog': minor --- -Added support for group alias IDs and configurable content ordering on the entity page. Groups can now declare `aliases` so that content targeting an aliased group is included in the group. A new `contentOrder` option (default `title`) controls how content items within each group are sorted, with support for both a page-level default and per-group overrides. +Added support for group alias IDs and configurable content ordering on the entity page. Groups can now declare `aliases` so that content targeting an aliased group is included in the group. A new `defaultContentOrder` option (default `title`) controls how content items within each group are sorted, with support for both a page-level default and per-group overrides. diff --git a/docs/features/software-catalog/catalog-customization.md b/docs/features/software-catalog/catalog-customization.md index 5ddcb7d5a4..2e984d2942 100644 --- a/docs/features/software-catalog/catalog-customization.md +++ b/docs/features/software-catalog/catalog-customization.md @@ -730,12 +730,12 @@ Notes: ### Content ordering within groups -By default, content items within each group are sorted alphabetically by title. You can change this with the `contentOrder` option, which supports two modes: +By default, content items within each group are sorted alphabetically by title. You can change this with the `defaultContentOrder` option, which supports two modes: - **`title`** (default) — sort alphabetically by the content extension's title (case-insensitive). - **`natural`** — preserve the natural extension discovery/registration order. -A page-level `contentOrder` sets the default for all groups, and individual groups can override it: +A page-level `defaultContentOrder` sets the default for all groups, and individual groups can override it with a per-group `contentOrder`: ```yaml app: @@ -743,7 +743,7 @@ app: - page:catalog/entity: config: # Default content order for all groups - contentOrder: title + defaultContentOrder: title groups: - documentation: diff --git a/packages/app/app-config.yaml b/packages/app/app-config.yaml index 0e49365c08..37893722f7 100644 --- a/packages/app/app-config.yaml +++ b/packages/app/app-config.yaml @@ -49,7 +49,7 @@ app: config: showNavItemIcons: true # default content order for all groups, can be 'title' or 'natural' - # contentOrder: title + # defaultContentOrder: title groups: # placing a tab at the beginning - overview: diff --git a/plugins/catalog/report-alpha.api.md b/plugins/catalog/report-alpha.api.md index 3aae7d8920..82b6837cc7 100644 --- a/plugins/catalog/report-alpha.api.md +++ b/plugins/catalog/report-alpha.api.md @@ -1097,12 +1097,12 @@ const _default: OverridableFrontendPlugin< { title: string; icon?: string | undefined; - contentOrder?: 'title' | 'natural' | undefined; aliases?: string[] | undefined; + contentOrder?: 'title' | 'natural' | undefined; } >[] | undefined; - contentOrder: 'title' | 'natural'; + defaultContentOrder: 'title' | 'natural'; showNavItemIcons: boolean; path: string | undefined; title: string | undefined; @@ -1114,13 +1114,13 @@ const _default: OverridableFrontendPlugin< { title: string; icon?: string | undefined; - contentOrder?: 'title' | 'natural' | undefined; aliases?: string[] | undefined; + contentOrder?: 'title' | 'natural' | undefined; } >[] | undefined; + defaultContentOrder?: 'title' | 'natural' | undefined; showNavItemIcons?: boolean | undefined; - contentOrder?: 'title' | 'natural' | undefined; title?: string | undefined; path?: string | undefined; }; diff --git a/plugins/catalog/src/alpha/pages.test.tsx b/plugins/catalog/src/alpha/pages.test.tsx index 39f96f8d5e..a19c9017c0 100644 --- a/plugins/catalog/src/alpha/pages.test.tsx +++ b/plugins/catalog/src/alpha/pages.test.tsx @@ -523,7 +523,7 @@ describe('Entity page', () => { Object.assign({ namespace: 'catalog' }, catalogEntityPage), { config: { - contentOrder: 'natural', + defaultContentOrder: 'natural', }, }, ) @@ -564,7 +564,7 @@ describe('Entity page', () => { Object.assign({ namespace: 'catalog' }, catalogEntityPage), { config: { - contentOrder: 'title', + defaultContentOrder: 'title', groups: [ { documentation: { diff --git a/plugins/catalog/src/alpha/pages.tsx b/plugins/catalog/src/alpha/pages.tsx index 4d37a18c98..ab71cf39dc 100644 --- a/plugins/catalog/src/alpha/pages.tsx +++ b/plugins/catalog/src/alpha/pages.tsx @@ -115,7 +115,7 @@ export const catalogEntityPage = PageBlueprint.makeWithOverrides({ ), ) .optional(), - contentOrder: z => + defaultContentOrder: z => z.enum(['title', 'natural']).optional().default('title'), showNavItemIcons: z => z.boolean().optional().default(false), }, @@ -178,7 +178,7 @@ export const catalogEntityPage = PageBlueprint.makeWithOverrides({ header={header} contextMenuItems={filteredMenuItems} groupDefinitions={groupDefinitions} - defaultContentOrder={config.contentOrder} + defaultContentOrder={config.defaultContentOrder} showNavItemIcons={config.showNavItemIcons} > {inputs.contents.map(output => ( From 0fbcf23714c9b1506500a0f13a03423b5a9c93dd Mon Sep 17 00:00:00 2001 From: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com> Date: Sat, 28 Feb 2026 09:04:02 -0500 Subject: [PATCH 17/26] feat: add support for OpenAPI 3.1 (#32300) * breaking: add support for OpenAPI 3.1 Signed-off-by: aramissennyeydd * add changeset Signed-off-by: aramissennyeydd * update nullable prop Signed-off-by: aramissennyeydd * remove more allowReserved usages Signed-off-by: aramissennyeydd * make changes less breaking Signed-off-by: aramissennyeydd * Apply suggestion from @aramissennyeydd Signed-off-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com> --------- Signed-off-by: aramissennyeydd Signed-off-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com> --- .changeset/deep-moments-deny.md | 5 ++ .changeset/legal-ants-show.md | 10 +++ docs/openapi/01-getting-started.md | 9 ++- .../src/schema/openapi.yaml | 2 +- .../openapi/generated/apis/Api.server.ts | 2 +- .../schema/openapi/generated/apis/index.ts | 2 +- .../src/schema/openapi/generated/index.ts | 2 +- .../generated/models/ErrorError.model.ts | 2 +- .../generated/models/ErrorRequest.model.ts | 2 +- .../generated/models/ErrorResponse.model.ts | 2 +- .../generated/models/ModelError.model.ts | 3 +- .../openapi/generated/models/Remote.model.ts | 2 +- .../generated/models/RemoteInfo.model.ts | 2 +- .../schema/openapi/generated/models/index.ts | 2 +- .../src/schema/openapi/generated/router.ts | 4 +- .../src/schema/openapi/index.ts | 2 +- packages/backend-openapi-utils/README.md | 2 + packages/backend-openapi-utils/src/stub.ts | 3 + .../openapi/generated/apis/Api.client.ts | 16 ++-- .../AnalyzeLocationExistingEntity.model.ts | 3 +- .../AnalyzeLocationGenerateEntity.model.ts | 3 +- .../models/AnalyzeLocationRequest.model.ts | 1 - .../models/AnalyzeLocationResponse.model.ts | 1 - .../models/CreateLocation201Response.model.ts | 1 - .../models/EntitiesBatchResponse.model.ts | 1 - .../models/EntitiesQueryResponse.model.ts | 1 - .../openapi/generated/models/Entity.model.ts | 3 +- .../models/EntityAncestryResponse.model.ts | 1 - .../EntityAncestryResponseItemsInner.model.ts | 1 - .../models/EntityFacetsResponse.model.ts | 1 - .../generated/models/EntityMeta.model.ts | 2 - .../GetLocations200ResponseInner.model.ts | 1 - .../models/LocationsQueryResponse.model.ts | 1 - .../generated/models/ModelError.model.ts | 2 - .../generated/models/NullableEntity.model.ts | 3 +- .../QueryEntitiesByPredicateRequest.model.ts | 1 - .../models/RecursivePartialEntity.model.ts | 1 - .../RecursivePartialEntityMeta.model.ts | 1 - .../RecursivePartialEntityMetaAllOf.model.ts | 68 ---------------- .../models/ValidateEntity400Response.model.ts | 1 - ...idateEntity400ResponseErrorsInner.model.ts | 1 - .../schema/openapi/generated/models/index.ts | 1 - .../openapi/generated/apis/Api.client.ts | 3 +- .../schema/openapi/generated/apis/index.ts | 2 +- .../src/schema/openapi/generated/index.ts | 2 +- .../generated/models/ErrorError.model.ts | 2 +- .../generated/models/ErrorRequest.model.ts | 2 +- .../generated/models/ErrorResponse.model.ts | 2 +- .../generated/models/ModelError.model.ts | 3 +- .../openapi/generated/models/Remote.model.ts | 2 +- .../generated/models/RemoteInfo.model.ts | 2 +- .../schema/openapi/generated/models/index.ts | 2 +- .../src/schema/openapi/generated/pluginId.ts | 2 +- .../src/schema/openapi/index.ts | 2 +- packages/repo-tools/openapitools.json | 2 +- .../package/schema/openapi/generate/client.ts | 9 ++- .../package/schema/openapi/generate/server.ts | 9 ++- .../src/commands/repo/schema/openapi/lint.ts | 6 +- .../repo-tools/src/lib/openapi/helpers.ts | 29 +++++++ .../catalog-backend/src/schema/openapi.yaml | 67 +++++++--------- .../openapi/generated/apis/Api.server.ts | 1 - .../AnalyzeLocationExistingEntity.model.ts | 3 +- .../AnalyzeLocationGenerateEntity.model.ts | 3 +- .../models/AnalyzeLocationRequest.model.ts | 1 - .../models/AnalyzeLocationResponse.model.ts | 1 - .../models/CreateLocation201Response.model.ts | 1 - .../models/EntitiesBatchResponse.model.ts | 1 - .../models/EntitiesQueryResponse.model.ts | 1 - .../openapi/generated/models/Entity.model.ts | 3 +- .../models/EntityAncestryResponse.model.ts | 1 - .../EntityAncestryResponseItemsInner.model.ts | 1 - .../models/EntityFacetsResponse.model.ts | 1 - .../generated/models/EntityMeta.model.ts | 2 - .../GetLocations200ResponseInner.model.ts | 1 - .../models/LocationsQueryResponse.model.ts | 1 - .../generated/models/ModelError.model.ts | 2 - .../generated/models/NullableEntity.model.ts | 3 +- .../QueryEntitiesByPredicateRequest.model.ts | 1 - .../models/RecursivePartialEntity.model.ts | 1 - .../RecursivePartialEntityMeta.model.ts | 1 - .../RecursivePartialEntityMetaAllOf.model.ts | 68 ---------------- .../models/ValidateEntity400Response.model.ts | 1 - ...idateEntity400ResponseErrorsInner.model.ts | 1 - .../schema/openapi/generated/models/index.ts | 1 - .../src/schema/openapi/generated/router.ts | 79 ++++++++++--------- .../events-backend/src/schema/openapi.yaml | 3 +- .../openapi/generated/apis/Api.server.ts | 2 +- .../schema/openapi/generated/apis/index.ts | 2 +- .../src/schema/openapi/generated/index.ts | 2 +- .../generated/models/ErrorError.model.ts | 2 +- .../generated/models/ErrorRequest.model.ts | 2 +- .../generated/models/ErrorResponse.model.ts | 2 +- .../openapi/generated/models/Event.model.ts | 5 +- .../GetSubscriptionEvents200Response.model.ts | 2 +- .../generated/models/ModelError.model.ts | 2 +- .../models/PostEventRequest.model.ts | 2 +- .../models/PutSubscriptionRequest.model.ts | 2 +- .../schema/openapi/generated/models/index.ts | 2 +- .../src/schema/openapi/generated/router.ts | 5 +- .../src/schema/openapi/index.ts | 2 +- .../openapi/generated/apis/Api.client.ts | 3 +- .../schema/openapi/generated/apis/index.ts | 2 +- .../src/schema/openapi/generated/index.ts | 2 +- .../generated/models/ErrorError.model.ts | 2 +- .../generated/models/ErrorRequest.model.ts | 2 +- .../generated/models/ErrorResponse.model.ts | 2 +- .../openapi/generated/models/Event.model.ts | 5 +- .../GetSubscriptionEvents200Response.model.ts | 2 +- .../generated/models/ModelError.model.ts | 2 +- .../models/PostEventRequest.model.ts | 2 +- .../models/PutSubscriptionRequest.model.ts | 2 +- .../schema/openapi/generated/models/index.ts | 2 +- .../src/schema/openapi/generated/pluginId.ts | 2 +- .../events-node/src/schema/openapi/index.ts | 2 +- .../src/schema/openapi.yaml | 16 ++-- .../openapi/generated/apis/Api.server.ts | 2 +- .../schema/openapi/generated/apis/index.ts | 2 +- .../src/schema/openapi/generated/index.ts | 2 +- .../openapi/generated/models/Action.model.ts | 2 +- .../generated/models/ActionExample.model.ts | 2 +- .../generated/models/ActionSchema.model.ts | 2 +- .../models/Autocomplete200Response.model.ts | 2 +- ...tocomplete200ResponseResultsInner.model.ts | 2 +- .../models/Autocomplete400Response.model.ts | 2 +- .../models/AutocompleteRequest.model.ts | 2 +- .../models/CancelTask200Response.model.ts | 2 +- .../models/DryRun200Response.model.ts | 2 +- .../models/DryRun200ResponseAllOf.model.ts | 29 ------- ...sponseAllOfDirectoryContentsInner.model.ts | 2 +- .../DryRun200ResponseAllOfStepsInner.model.ts | 3 +- .../generated/models/DryRunRequest.model.ts | 2 +- ...yRunRequestDirectoryContentsInner.model.ts | 2 +- .../generated/models/DryRunResult.model.ts | 2 +- .../models/DryRunResultLogInner.model.ts | 2 +- .../models/DryRunResultLogInnerBody.model.ts | 2 +- .../DryRunResultLogInnerBodyAllOf.model.ts | 29 ------- .../generated/models/ErrorError.model.ts | 2 +- .../generated/models/ErrorRequest.model.ts | 2 +- .../generated/models/ErrorResponse.model.ts | 2 +- .../generated/models/JsonPrimitive.model.ts | 4 +- .../generated/models/JsonValue.model.ts | 2 +- .../models/ListTasksResponse.model.ts | 2 +- .../ListTemplatingExtensionsResponse.model.ts | 2 +- ...mplatingExtensionsResponseGlobals.model.ts | 2 +- .../generated/models/ModelError.model.ts | 3 +- .../generated/models/RetryRequest.model.ts | 2 +- .../models/Scaffold201Response.model.ts | 2 +- .../models/Scaffold400Response.model.ts | 2 +- .../models/ScaffolderScaffoldOptions.model.ts | 2 +- .../models/ScaffolderUsageExample.model.ts | 2 +- .../generated/models/SerializedFile.model.ts | 2 +- .../generated/models/SerializedTask.model.ts | 2 +- .../models/SerializedTaskEvent.model.ts | 2 +- .../generated/models/TaskEventType.model.ts | 2 +- .../generated/models/TaskSecrets.model.ts | 2 +- .../models/TaskSecretsAllOf.model.ts | 26 ------ .../generated/models/TaskStatus.model.ts | 2 +- .../generated/models/TemplateFilter.model.ts | 2 +- .../models/TemplateFilterSchema.model.ts | 2 +- .../models/TemplateGlobalFunction.model.ts | 2 +- .../TemplateGlobalFunctionSchema.model.ts | 2 +- .../models/TemplateGlobalValue.model.ts | 2 +- .../models/TemplateParameterSchema.model.ts | 3 +- ...TemplateParameterSchemaStepsInner.model.ts | 2 +- .../generated/models/ValidationError.model.ts | 3 +- .../models/ValidationErrorArgument.model.ts | 2 +- .../models/ValidationErrorPathInner.model.ts | 2 +- .../schema/openapi/generated/models/index.ts | 5 +- .../src/schema/openapi/generated/router.ts | 23 +++--- .../src/schema/openapi/index.ts | 2 +- .../openapi/generated/apis/Api.client.ts | 3 +- .../schema/openapi/generated/apis/index.ts | 2 +- .../src/schema/openapi/generated/index.ts | 2 +- .../openapi/generated/models/Action.model.ts | 2 +- .../generated/models/ActionExample.model.ts | 2 +- .../generated/models/ActionSchema.model.ts | 2 +- .../models/Autocomplete200Response.model.ts | 2 +- ...tocomplete200ResponseResultsInner.model.ts | 2 +- .../models/Autocomplete400Response.model.ts | 2 +- .../models/AutocompleteRequest.model.ts | 2 +- .../models/CancelTask200Response.model.ts | 2 +- .../models/DryRun200Response.model.ts | 2 +- .../models/DryRun200ResponseAllOf.model.ts | 29 ------- ...sponseAllOfDirectoryContentsInner.model.ts | 2 +- .../DryRun200ResponseAllOfStepsInner.model.ts | 3 +- .../generated/models/DryRunRequest.model.ts | 2 +- ...yRunRequestDirectoryContentsInner.model.ts | 2 +- .../generated/models/DryRunResult.model.ts | 2 +- .../models/DryRunResultLogInner.model.ts | 2 +- .../models/DryRunResultLogInnerBody.model.ts | 2 +- .../DryRunResultLogInnerBodyAllOf.model.ts | 29 ------- .../generated/models/ErrorError.model.ts | 2 +- .../generated/models/ErrorRequest.model.ts | 2 +- .../generated/models/ErrorResponse.model.ts | 2 +- .../generated/models/JsonPrimitive.model.ts | 4 +- .../generated/models/JsonValue.model.ts | 2 +- .../models/ListTasksResponse.model.ts | 2 +- .../ListTemplatingExtensionsResponse.model.ts | 2 +- ...mplatingExtensionsResponseGlobals.model.ts | 2 +- .../generated/models/ModelError.model.ts | 3 +- .../generated/models/RetryRequest.model.ts | 2 +- .../models/Scaffold201Response.model.ts | 2 +- .../models/Scaffold400Response.model.ts | 2 +- .../models/ScaffolderScaffoldOptions.model.ts | 2 +- .../models/ScaffolderUsageExample.model.ts | 2 +- .../generated/models/SerializedFile.model.ts | 2 +- .../generated/models/SerializedTask.model.ts | 2 +- .../models/SerializedTaskEvent.model.ts | 2 +- .../generated/models/TaskEventType.model.ts | 2 +- .../generated/models/TaskSecrets.model.ts | 2 +- .../models/TaskSecretsAllOf.model.ts | 26 ------ .../generated/models/TaskStatus.model.ts | 2 +- .../generated/models/TemplateFilter.model.ts | 2 +- .../models/TemplateFilterSchema.model.ts | 2 +- .../models/TemplateGlobalFunction.model.ts | 2 +- .../TemplateGlobalFunctionSchema.model.ts | 2 +- .../models/TemplateGlobalValue.model.ts | 2 +- .../models/TemplateParameterSchema.model.ts | 3 +- ...TemplateParameterSchemaStepsInner.model.ts | 2 +- .../generated/models/ValidationError.model.ts | 3 +- .../models/ValidationErrorArgument.model.ts | 2 +- .../models/ValidationErrorPathInner.model.ts | 2 +- .../schema/openapi/generated/models/index.ts | 5 +- .../src/schema/openapi/generated/pluginId.ts | 2 +- .../src/schema/openapi/index.ts | 2 +- .../search-backend/src/schema/openapi.yaml | 2 +- .../openapi/generated/apis/Api.server.ts | 2 +- .../schema/openapi/generated/apis/index.ts | 2 +- .../src/schema/openapi/generated/index.ts | 2 +- .../generated/models/ErrorError.model.ts | 2 +- .../generated/models/ErrorRequest.model.ts | 2 +- .../generated/models/ErrorResponse.model.ts | 2 +- .../generated/models/ModelError.model.ts | 2 +- .../models/Query200Response.model.ts | 2 +- .../Query200ResponseResultsInner.model.ts | 2 +- ...ry200ResponseResultsInnerDocument.model.ts | 2 +- .../schema/openapi/generated/models/index.ts | 2 +- .../src/schema/openapi/generated/router.ts | 4 +- .../src/schema/openapi/index.ts | 2 +- 239 files changed, 360 insertions(+), 673 deletions(-) create mode 100644 .changeset/deep-moments-deny.md create mode 100644 .changeset/legal-ants-show.md delete mode 100644 packages/catalog-client/src/schema/openapi/generated/models/RecursivePartialEntityMetaAllOf.model.ts delete mode 100644 plugins/catalog-backend/src/schema/openapi/generated/models/RecursivePartialEntityMetaAllOf.model.ts delete mode 100644 plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRun200ResponseAllOf.model.ts delete mode 100644 plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunResultLogInnerBodyAllOf.model.ts delete mode 100644 plugins/scaffolder-backend/src/schema/openapi/generated/models/TaskSecretsAllOf.model.ts delete mode 100644 plugins/scaffolder-common/src/schema/openapi/generated/models/DryRun200ResponseAllOf.model.ts delete mode 100644 plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunResultLogInnerBodyAllOf.model.ts delete mode 100644 plugins/scaffolder-common/src/schema/openapi/generated/models/TaskSecretsAllOf.model.ts diff --git a/.changeset/deep-moments-deny.md b/.changeset/deep-moments-deny.md new file mode 100644 index 0000000000..21de414350 --- /dev/null +++ b/.changeset/deep-moments-deny.md @@ -0,0 +1,5 @@ +--- +'@backstage/repo-tools': minor +--- + +Added support for OpenAPI 3.1 to all `schema openapi` commands. The commands now auto-detect the OpenAPI version from the spec file and use the appropriate generator, supporting both OpenAPI 3.0.x and 3.1.x specifications. diff --git a/.changeset/legal-ants-show.md b/.changeset/legal-ants-show.md new file mode 100644 index 0000000000..724f9eabee --- /dev/null +++ b/.changeset/legal-ants-show.md @@ -0,0 +1,10 @@ +--- +'@backstage/backend-dynamic-feature-service': minor +'@backstage/plugin-scaffolder-backend': minor +'@backstage/catalog-client': minor +'@backstage/plugin-catalog-backend': minor +'@backstage/plugin-events-backend': minor +'@backstage/plugin-search-backend': minor +--- + +Migrated OpenAPI schemas to 3.1. diff --git a/docs/openapi/01-getting-started.md b/docs/openapi/01-getting-started.md index 875a369dbf..c300ac1370 100644 --- a/docs/openapi/01-getting-started.md +++ b/docs/openapi/01-getting-started.md @@ -26,7 +26,14 @@ This tutorial assumes that you're already familiar with the following, 1. How to build a Backstage plugin. 2. `Express.js` and `Typescript` -3. OpenAPI 3.0 schemas +3. OpenAPI 3.1 schemas + +:::note OpenAPI Version Support +Backstage supports both OpenAPI 3.0 and 3.1 specifications. If you have existing OpenAPI 3.0 specs, we recommend that you migrate them to 3.1. The main changes are: + +- Replace `nullable: true` with `type: ['string', 'null']` or use `anyOf`/`oneOf` +- Remove `allowReserved` from path parameters (only valid on query/cookie parameters in 3.1) + ::: ### Setting up diff --git a/packages/backend-dynamic-feature-service/src/schema/openapi.yaml b/packages/backend-dynamic-feature-service/src/schema/openapi.yaml index 9b1871c366..987b59f4b5 100644 --- a/packages/backend-dynamic-feature-service/src/schema/openapi.yaml +++ b/packages/backend-dynamic-feature-service/src/schema/openapi.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.1.0 info: title: .backstage/dynamic-features version: '1' diff --git a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/apis/Api.server.ts b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/apis/Api.server.ts index 285345d44c..7d241760dc 100644 --- a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/apis/Api.server.ts +++ b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/apis/Api.server.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/apis/index.ts b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/apis/index.ts index 8d81cbaf39..9a0ffed740 100644 --- a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/apis/index.ts +++ b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/apis/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/index.ts b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/index.ts index dec4b8804e..58fc52487a 100644 --- a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/index.ts +++ b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/ErrorError.model.ts b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/ErrorError.model.ts index e0265e95d7..853f88cc14 100644 --- a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/ErrorError.model.ts +++ b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/ErrorError.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/ErrorRequest.model.ts b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/ErrorRequest.model.ts index 3eb5e15740..1591911bc9 100644 --- a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/ErrorRequest.model.ts +++ b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/ErrorRequest.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/ErrorResponse.model.ts b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/ErrorResponse.model.ts index edbcc32df7..1eff0557ed 100644 --- a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/ErrorResponse.model.ts +++ b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/ErrorResponse.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/ModelError.model.ts b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/ModelError.model.ts index 958fde7d0b..9d5c36325e 100644 --- a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/ModelError.model.ts +++ b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/ModelError.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -26,7 +26,6 @@ import { ErrorResponse } from '../models/ErrorResponse.model'; */ export interface ModelError { [key: string]: any; - error: ErrorError; request?: ErrorRequest; response: ErrorResponse; diff --git a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/Remote.model.ts b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/Remote.model.ts index 7440110ad8..ff5cae705f 100644 --- a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/Remote.model.ts +++ b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/Remote.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/RemoteInfo.model.ts b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/RemoteInfo.model.ts index 72edba90d4..6e8bdeff0a 100644 --- a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/RemoteInfo.model.ts +++ b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/RemoteInfo.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/index.ts b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/index.ts index 0c54a6585b..4cf296a0b9 100644 --- a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/index.ts +++ b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/models/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/router.ts b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/router.ts index cf48bcfc95..b228198c3c 100644 --- a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/router.ts +++ b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/router.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -21,7 +21,7 @@ import { createValidatedOpenApiRouterFromGeneratedEndpointMap } from '@backstage import { EndpointMap } from './apis'; export const spec = { - openapi: '3.0.3', + openapi: '3.1.0', info: { title: '.backstage/dynamic-features', version: '1', diff --git a/packages/backend-dynamic-feature-service/src/schema/openapi/index.ts b/packages/backend-dynamic-feature-service/src/schema/openapi/index.ts index 196aad553a..fb49a2b9c0 100644 --- a/packages/backend-dynamic-feature-service/src/schema/openapi/index.ts +++ b/packages/backend-dynamic-feature-service/src/schema/openapi/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/backend-openapi-utils/README.md b/packages/backend-openapi-utils/README.md index 33f2200f81..bb420f49fa 100644 --- a/packages/backend-openapi-utils/README.md +++ b/packages/backend-openapi-utils/README.md @@ -4,6 +4,8 @@ This package is meant to provide a typed Express router for an OpenAPI spec. Based on the [`oatx`](https://github.com/varanauskas/oatx) library and adapted to override Express values. +Only supports OpenAPI 3.1 specifications. + ## Getting Started ### Configuration diff --git a/packages/backend-openapi-utils/src/stub.ts b/packages/backend-openapi-utils/src/stub.ts index 717e2ae19b..b595f357bc 100644 --- a/packages/backend-openapi-utils/src/stub.ts +++ b/packages/backend-openapi-utils/src/stub.ts @@ -54,6 +54,7 @@ export function getOpenApiSpecRoute(baseUrl: string) { /** * Create a router with validation middleware. This is used by typing methods to create an * "OpenAPI router" with all of the expected validation + metadata. + * Only supports OpenAPI 3.1 specifications. * @param spec - Your OpenAPI spec imported as a JSON object. * @param validatorOptions - `openapi-express-validator` options to override the defaults. * @returns A new express router with validation middleware. @@ -115,6 +116,7 @@ function createRouterWithValidation( /** * Create a new OpenAPI router with some default middleware. + * Only supports OpenAPI 3.1 specifications. * @param spec - Your OpenAPI spec imported as a JSON object. * @param validatorOptions - `openapi-express-validator` options to override the defaults. * @returns A new express router with validation middleware. @@ -132,6 +134,7 @@ export function createValidatedOpenApiRouter( /** * Create a new OpenAPI router with some default middleware. + * Only supports OpenAPI 3.1 specifications. * @param spec - Your OpenAPI spec imported as a JSON object. * @param validatorOptions - `openapi-express-validator` options to override the defaults. * @returns A new express router with validation middleware. diff --git a/packages/catalog-client/src/schema/openapi/generated/apis/Api.client.ts b/packages/catalog-client/src/schema/openapi/generated/apis/Api.client.ts index 899e310e94..63d55aea55 100644 --- a/packages/catalog-client/src/schema/openapi/generated/apis/Api.client.ts +++ b/packages/catalog-client/src/schema/openapi/generated/apis/Api.client.ts @@ -260,9 +260,9 @@ export class DefaultApiClient { /** * Get all entities matching a given filter. - * @param fields - By default the full entities are returned, but you can pass in a `fields` query parameter which selects what parts of the entity data to retain. This makes the response smaller and faster to transfer, and may allow the catalog to perform more efficient queries. The query parameter value is a comma separated list of simplified JSON paths like above. Each path corresponds to the key of either a value, or of a subtree root that you want to keep in the output. The rest is pruned away. For example, specifying `?fields=metadata.name,metadata.annotations,spec` retains only the `name` and `annotations` fields of the `metadata` of each entity (it'll be an object with at most two keys), keeps the entire `spec` unchanged, and cuts out all other roots such as `relations`. Some more real world usable examples: - Return only enough data to form the full ref of each entity: `/entities/by-query?fields=kind,metadata.namespace,metadata.name` + * @param fields - By default the full entities are returned, but you can pass in a `fields` query parameter which selects what parts of the entity data to retain. This makes the response smaller and faster to transfer, and may allow the catalog to perform more efficient queries. The query parameter value is a comma separated list of simplified JSON paths like above. Each path corresponds to the key of either a value, or of a subtree root that you want to keep in the output. The rest is pruned away. For example, specifying `?fields=metadata.name,metadata.annotations,spec` retains only the `name` and `annotations` fields of the `metadata` of each entity (it\'ll be an object with at most two keys), keeps the entire `spec` unchanged, and cuts out all other roots such as `relations`. Some more real world usable examples: - Return only enough data to form the full ref of each entity: `/entities/by-query?fields=kind,metadata.namespace,metadata.name` * @param limit - Number of records to return in the response. - * @param filter - You can pass in one or more filter sets that get matched against each entity. Each filter set is a number of conditions that all have to match for the condition to be true (conditions effectively have an AND between them). At least one filter set has to be true for the entity to be part of the result set (filter sets effectively have an OR between them). Example: ```text /entities/by-query?filter=kind=user,metadata.namespace=default&filter=kind=group,spec.type Return entities that match Filter set 1: Condition 1: kind = user AND Condition 2: metadata.namespace = default OR Filter set 2: Condition 1: kind = group AND Condition 2: spec.type exists ``` Each condition is either on the form `<key>`, or on the form `<key>=<value>`. The first form asserts on the existence of a certain key (with any value), and the second asserts that the key exists and has a certain value. All checks are always case _insensitive_. In all cases, the key is a simplified JSON path in a given piece of entity data. Each part of the path is a key of an object, and the traversal also descends through arrays. There are two special forms: - Array items that are simple value types (such as strings) match on a key-value pair where the key is the item as a string, and the value is the string `true` - Relations can be matched on a `relations.<type>=<targetRef>` form Let's look at a simplified example to illustrate the concept: ```json { \"a\": { \"b\": [\"c\", { \"d\": 1 }], \"e\": 7 } } ``` This would match any one of the following conditions: - `a` - `a.b` - `a.b.c` - `a.b.c=true` - `a.b.d` - `a.b.d=1` - `a.e` - `a.e=7` Some more real world usable examples: - Return all orphaned entities: `/entities/by-query?filter=metadata.annotations.backstage.io/orphan=true` - Return all users and groups: `/entities/by-query?filter=kind=user&filter=kind=group` - Return all service components: `/entities/by-query?filter=kind=component,spec.type=service` - Return all entities with the `java` tag: `/entities/by-query?filter=metadata.tags.java` - Return all users who are members of the `ops` group (note that the full [reference](references.md) of the group is used): `/entities/by-query?filter=kind=user,relations.memberof=group:default/ops` + * @param filter - You can pass in one or more filter sets that get matched against each entity. Each filter set is a number of conditions that all have to match for the condition to be true (conditions effectively have an AND between them). At least one filter set has to be true for the entity to be part of the result set (filter sets effectively have an OR between them). Example: ```text /entities/by-query?filter=kind=user,metadata.namespace=default&filter=kind=group,spec.type Return entities that match Filter set 1: Condition 1: kind = user AND Condition 2: metadata.namespace = default OR Filter set 2: Condition 1: kind = group AND Condition 2: spec.type exists ``` Each condition is either on the form `<key>`, or on the form `<key>=<value>`. The first form asserts on the existence of a certain key (with any value), and the second asserts that the key exists and has a certain value. All checks are always case _insensitive_. In all cases, the key is a simplified JSON path in a given piece of entity data. Each part of the path is a key of an object, and the traversal also descends through arrays. There are two special forms: - Array items that are simple value types (such as strings) match on a key-value pair where the key is the item as a string, and the value is the string `true` - Relations can be matched on a `relations.<type>=<targetRef>` form Let\'s look at a simplified example to illustrate the concept: ```json { \"a\": { \"b\": [\"c\", { \"d\": 1 }], \"e\": 7 } } ``` This would match any one of the following conditions: - `a` - `a.b` - `a.b.c` - `a.b.c=true` - `a.b.d` - `a.b.d=1` - `a.e` - `a.e=7` Some more real world usable examples: - Return all orphaned entities: `/entities/by-query?filter=metadata.annotations.backstage.io/orphan=true` - Return all users and groups: `/entities/by-query?filter=kind=user&filter=kind=group` - Return all service components: `/entities/by-query?filter=kind=component,spec.type=service` - Return all entities with the `java` tag: `/entities/by-query?filter=metadata.tags.java` - Return all users who are members of the `ops` group (note that the full [reference](references.md) of the group is used): `/entities/by-query?filter=kind=user,relations.memberof=group:default/ops` * @param offset - Number of records to skip in the query page. * @param after - Pointer to the previous page of results. * @param order - @@ -291,12 +291,12 @@ export class DefaultApiClient { /** * Search for entities by a given query. - * @param fields - By default the full entities are returned, but you can pass in a `fields` query parameter which selects what parts of the entity data to retain. This makes the response smaller and faster to transfer, and may allow the catalog to perform more efficient queries. The query parameter value is a comma separated list of simplified JSON paths like above. Each path corresponds to the key of either a value, or of a subtree root that you want to keep in the output. The rest is pruned away. For example, specifying `?fields=metadata.name,metadata.annotations,spec` retains only the `name` and `annotations` fields of the `metadata` of each entity (it'll be an object with at most two keys), keeps the entire `spec` unchanged, and cuts out all other roots such as `relations`. Some more real world usable examples: - Return only enough data to form the full ref of each entity: `/entities/by-query?fields=kind,metadata.namespace,metadata.name` + * @param fields - By default the full entities are returned, but you can pass in a `fields` query parameter which selects what parts of the entity data to retain. This makes the response smaller and faster to transfer, and may allow the catalog to perform more efficient queries. The query parameter value is a comma separated list of simplified JSON paths like above. Each path corresponds to the key of either a value, or of a subtree root that you want to keep in the output. The rest is pruned away. For example, specifying `?fields=metadata.name,metadata.annotations,spec` retains only the `name` and `annotations` fields of the `metadata` of each entity (it\'ll be an object with at most two keys), keeps the entire `spec` unchanged, and cuts out all other roots such as `relations`. Some more real world usable examples: - Return only enough data to form the full ref of each entity: `/entities/by-query?fields=kind,metadata.namespace,metadata.name` * @param limit - Number of records to return in the response. * @param offset - Number of records to skip in the query page. * @param orderField - By default the entities are returned ordered by their internal uid. You can customize the `orderField` query parameters to affect that ordering. For example, to return entities by their name: `/entities/by-query?orderField=metadata.name,asc` Each parameter can be followed by `asc` for ascending lexicographical order or `desc` for descending (reverse) lexicographical order. - * @param cursor - You may pass the `cursor` query parameters to perform cursor based pagination through the set of entities. The value of `cursor` will be returned in the response, under the `pageInfo` property: ```json \"pageInfo\": { \"nextCursor\": \"a-cursor\", \"prevCursor\": \"another-cursor\" } ``` If `nextCursor` exists, it can be used to retrieve the next batch of entities. Following the same approach, if `prevCursor` exists, it can be used to retrieve the previous batch of entities. - [`filter`](#filtering), for selecting only a subset of all entities - [`fields`](#field-selection), for selecting only parts of the full data structure of each entity - `limit` for limiting the number of entities returned (20 is the default) - [`orderField`](#ordering), for deciding the order of the entities - `fullTextFilter` **NOTE**: [`filter`, `orderField`, `fullTextFilter`] and `cursor` are mutually exclusive. This means that, it isn't possible to change any of [`filter`, `orderField`, `fullTextFilter`] when passing `cursor` as query parameters, as changing any of these properties will affect pagination. If any of `filter`, `orderField`, `fullTextFilter` is specified together with `cursor`, only the latter is taken into consideration. - * @param filter - You can pass in one or more filter sets that get matched against each entity. Each filter set is a number of conditions that all have to match for the condition to be true (conditions effectively have an AND between them). At least one filter set has to be true for the entity to be part of the result set (filter sets effectively have an OR between them). Example: ```text /entities/by-query?filter=kind=user,metadata.namespace=default&filter=kind=group,spec.type Return entities that match Filter set 1: Condition 1: kind = user AND Condition 2: metadata.namespace = default OR Filter set 2: Condition 1: kind = group AND Condition 2: spec.type exists ``` Each condition is either on the form `<key>`, or on the form `<key>=<value>`. The first form asserts on the existence of a certain key (with any value), and the second asserts that the key exists and has a certain value. All checks are always case _insensitive_. In all cases, the key is a simplified JSON path in a given piece of entity data. Each part of the path is a key of an object, and the traversal also descends through arrays. There are two special forms: - Array items that are simple value types (such as strings) match on a key-value pair where the key is the item as a string, and the value is the string `true` - Relations can be matched on a `relations.<type>=<targetRef>` form Let's look at a simplified example to illustrate the concept: ```json { \"a\": { \"b\": [\"c\", { \"d\": 1 }], \"e\": 7 } } ``` This would match any one of the following conditions: - `a` - `a.b` - `a.b.c` - `a.b.c=true` - `a.b.d` - `a.b.d=1` - `a.e` - `a.e=7` Some more real world usable examples: - Return all orphaned entities: `/entities/by-query?filter=metadata.annotations.backstage.io/orphan=true` - Return all users and groups: `/entities/by-query?filter=kind=user&filter=kind=group` - Return all service components: `/entities/by-query?filter=kind=component,spec.type=service` - Return all entities with the `java` tag: `/entities/by-query?filter=metadata.tags.java` - Return all users who are members of the `ops` group (note that the full [reference](references.md) of the group is used): `/entities/by-query?filter=kind=user,relations.memberof=group:default/ops` + * @param cursor - You may pass the `cursor` query parameters to perform cursor based pagination through the set of entities. The value of `cursor` will be returned in the response, under the `pageInfo` property: ```json \"pageInfo\": { \"nextCursor\": \"a-cursor\", \"prevCursor\": \"another-cursor\" } ``` If `nextCursor` exists, it can be used to retrieve the next batch of entities. Following the same approach, if `prevCursor` exists, it can be used to retrieve the previous batch of entities. - [`filter`](#filtering), for selecting only a subset of all entities - [`fields`](#field-selection), for selecting only parts of the full data structure of each entity - `limit` for limiting the number of entities returned (20 is the default) - [`orderField`](#ordering), for deciding the order of the entities - `fullTextFilter` **NOTE**: [`filter`, `orderField`, `fullTextFilter`] and `cursor` are mutually exclusive. This means that, it isn\'t possible to change any of [`filter`, `orderField`, `fullTextFilter`] when passing `cursor` as query parameters, as changing any of these properties will affect pagination. If any of `filter`, `orderField`, `fullTextFilter` is specified together with `cursor`, only the latter is taken into consideration. + * @param filter - You can pass in one or more filter sets that get matched against each entity. Each filter set is a number of conditions that all have to match for the condition to be true (conditions effectively have an AND between them). At least one filter set has to be true for the entity to be part of the result set (filter sets effectively have an OR between them). Example: ```text /entities/by-query?filter=kind=user,metadata.namespace=default&filter=kind=group,spec.type Return entities that match Filter set 1: Condition 1: kind = user AND Condition 2: metadata.namespace = default OR Filter set 2: Condition 1: kind = group AND Condition 2: spec.type exists ``` Each condition is either on the form `<key>`, or on the form `<key>=<value>`. The first form asserts on the existence of a certain key (with any value), and the second asserts that the key exists and has a certain value. All checks are always case _insensitive_. In all cases, the key is a simplified JSON path in a given piece of entity data. Each part of the path is a key of an object, and the traversal also descends through arrays. There are two special forms: - Array items that are simple value types (such as strings) match on a key-value pair where the key is the item as a string, and the value is the string `true` - Relations can be matched on a `relations.<type>=<targetRef>` form Let\'s look at a simplified example to illustrate the concept: ```json { \"a\": { \"b\": [\"c\", { \"d\": 1 }], \"e\": 7 } } ``` This would match any one of the following conditions: - `a` - `a.b` - `a.b.c` - `a.b.c=true` - `a.b.d` - `a.b.d=1` - `a.e` - `a.e=7` Some more real world usable examples: - Return all orphaned entities: `/entities/by-query?filter=metadata.annotations.backstage.io/orphan=true` - Return all users and groups: `/entities/by-query?filter=kind=user&filter=kind=group` - Return all service components: `/entities/by-query?filter=kind=component,spec.type=service` - Return all entities with the `java` tag: `/entities/by-query?filter=metadata.tags.java` - Return all users who are members of the `ops` group (note that the full [reference](references.md) of the group is used): `/entities/by-query?filter=kind=user,relations.memberof=group:default/ops` * @param fullTextFilterTerm - Text search term. * @param fullTextFilterFields - A comma separated list of fields to sort returned results by. */ @@ -324,7 +324,7 @@ export class DefaultApiClient { /** * Get a batch set of entities given an array of entityRefs. - * @param filter - You can pass in one or more filter sets that get matched against each entity. Each filter set is a number of conditions that all have to match for the condition to be true (conditions effectively have an AND between them). At least one filter set has to be true for the entity to be part of the result set (filter sets effectively have an OR between them). Example: ```text /entities/by-query?filter=kind=user,metadata.namespace=default&filter=kind=group,spec.type Return entities that match Filter set 1: Condition 1: kind = user AND Condition 2: metadata.namespace = default OR Filter set 2: Condition 1: kind = group AND Condition 2: spec.type exists ``` Each condition is either on the form `<key>`, or on the form `<key>=<value>`. The first form asserts on the existence of a certain key (with any value), and the second asserts that the key exists and has a certain value. All checks are always case _insensitive_. In all cases, the key is a simplified JSON path in a given piece of entity data. Each part of the path is a key of an object, and the traversal also descends through arrays. There are two special forms: - Array items that are simple value types (such as strings) match on a key-value pair where the key is the item as a string, and the value is the string `true` - Relations can be matched on a `relations.<type>=<targetRef>` form Let's look at a simplified example to illustrate the concept: ```json { \"a\": { \"b\": [\"c\", { \"d\": 1 }], \"e\": 7 } } ``` This would match any one of the following conditions: - `a` - `a.b` - `a.b.c` - `a.b.c=true` - `a.b.d` - `a.b.d=1` - `a.e` - `a.e=7` Some more real world usable examples: - Return all orphaned entities: `/entities/by-query?filter=metadata.annotations.backstage.io/orphan=true` - Return all users and groups: `/entities/by-query?filter=kind=user&filter=kind=group` - Return all service components: `/entities/by-query?filter=kind=component,spec.type=service` - Return all entities with the `java` tag: `/entities/by-query?filter=metadata.tags.java` - Return all users who are members of the `ops` group (note that the full [reference](references.md) of the group is used): `/entities/by-query?filter=kind=user,relations.memberof=group:default/ops` + * @param filter - You can pass in one or more filter sets that get matched against each entity. Each filter set is a number of conditions that all have to match for the condition to be true (conditions effectively have an AND between them). At least one filter set has to be true for the entity to be part of the result set (filter sets effectively have an OR between them). Example: ```text /entities/by-query?filter=kind=user,metadata.namespace=default&filter=kind=group,spec.type Return entities that match Filter set 1: Condition 1: kind = user AND Condition 2: metadata.namespace = default OR Filter set 2: Condition 1: kind = group AND Condition 2: spec.type exists ``` Each condition is either on the form `<key>`, or on the form `<key>=<value>`. The first form asserts on the existence of a certain key (with any value), and the second asserts that the key exists and has a certain value. All checks are always case _insensitive_. In all cases, the key is a simplified JSON path in a given piece of entity data. Each part of the path is a key of an object, and the traversal also descends through arrays. There are two special forms: - Array items that are simple value types (such as strings) match on a key-value pair where the key is the item as a string, and the value is the string `true` - Relations can be matched on a `relations.<type>=<targetRef>` form Let\'s look at a simplified example to illustrate the concept: ```json { \"a\": { \"b\": [\"c\", { \"d\": 1 }], \"e\": 7 } } ``` This would match any one of the following conditions: - `a` - `a.b` - `a.b.c` - `a.b.c=true` - `a.b.d` - `a.b.d=1` - `a.e` - `a.e=7` Some more real world usable examples: - Return all orphaned entities: `/entities/by-query?filter=metadata.annotations.backstage.io/orphan=true` - Return all users and groups: `/entities/by-query?filter=kind=user&filter=kind=group` - Return all service components: `/entities/by-query?filter=kind=component,spec.type=service` - Return all entities with the `java` tag: `/entities/by-query?filter=metadata.tags.java` - Return all users who are members of the `ops` group (note that the full [reference](references.md) of the group is used): `/entities/by-query?filter=kind=user,relations.memberof=group:default/ops` * @param getEntitiesByRefsRequest - */ public async getEntitiesByRefs( @@ -351,7 +351,7 @@ export class DefaultApiClient { } /** - * Get an entity's ancestry by entity ref. + * Get an entity\'s ancestry by entity ref. * @param kind - * @param namespace - * @param name - @@ -439,7 +439,7 @@ export class DefaultApiClient { /** * Get all entity facets that match the given filters. * @param facet - - * @param filter - You can pass in one or more filter sets that get matched against each entity. Each filter set is a number of conditions that all have to match for the condition to be true (conditions effectively have an AND between them). At least one filter set has to be true for the entity to be part of the result set (filter sets effectively have an OR between them). Example: ```text /entities/by-query?filter=kind=user,metadata.namespace=default&filter=kind=group,spec.type Return entities that match Filter set 1: Condition 1: kind = user AND Condition 2: metadata.namespace = default OR Filter set 2: Condition 1: kind = group AND Condition 2: spec.type exists ``` Each condition is either on the form `<key>`, or on the form `<key>=<value>`. The first form asserts on the existence of a certain key (with any value), and the second asserts that the key exists and has a certain value. All checks are always case _insensitive_. In all cases, the key is a simplified JSON path in a given piece of entity data. Each part of the path is a key of an object, and the traversal also descends through arrays. There are two special forms: - Array items that are simple value types (such as strings) match on a key-value pair where the key is the item as a string, and the value is the string `true` - Relations can be matched on a `relations.<type>=<targetRef>` form Let's look at a simplified example to illustrate the concept: ```json { \"a\": { \"b\": [\"c\", { \"d\": 1 }], \"e\": 7 } } ``` This would match any one of the following conditions: - `a` - `a.b` - `a.b.c` - `a.b.c=true` - `a.b.d` - `a.b.d=1` - `a.e` - `a.e=7` Some more real world usable examples: - Return all orphaned entities: `/entities/by-query?filter=metadata.annotations.backstage.io/orphan=true` - Return all users and groups: `/entities/by-query?filter=kind=user&filter=kind=group` - Return all service components: `/entities/by-query?filter=kind=component,spec.type=service` - Return all entities with the `java` tag: `/entities/by-query?filter=metadata.tags.java` - Return all users who are members of the `ops` group (note that the full [reference](references.md) of the group is used): `/entities/by-query?filter=kind=user,relations.memberof=group:default/ops` + * @param filter - You can pass in one or more filter sets that get matched against each entity. Each filter set is a number of conditions that all have to match for the condition to be true (conditions effectively have an AND between them). At least one filter set has to be true for the entity to be part of the result set (filter sets effectively have an OR between them). Example: ```text /entities/by-query?filter=kind=user,metadata.namespace=default&filter=kind=group,spec.type Return entities that match Filter set 1: Condition 1: kind = user AND Condition 2: metadata.namespace = default OR Filter set 2: Condition 1: kind = group AND Condition 2: spec.type exists ``` Each condition is either on the form `<key>`, or on the form `<key>=<value>`. The first form asserts on the existence of a certain key (with any value), and the second asserts that the key exists and has a certain value. All checks are always case _insensitive_. In all cases, the key is a simplified JSON path in a given piece of entity data. Each part of the path is a key of an object, and the traversal also descends through arrays. There are two special forms: - Array items that are simple value types (such as strings) match on a key-value pair where the key is the item as a string, and the value is the string `true` - Relations can be matched on a `relations.<type>=<targetRef>` form Let\'s look at a simplified example to illustrate the concept: ```json { \"a\": { \"b\": [\"c\", { \"d\": 1 }], \"e\": 7 } } ``` This would match any one of the following conditions: - `a` - `a.b` - `a.b.c` - `a.b.c=true` - `a.b.d` - `a.b.d=1` - `a.e` - `a.e=7` Some more real world usable examples: - Return all orphaned entities: `/entities/by-query?filter=metadata.annotations.backstage.io/orphan=true` - Return all users and groups: `/entities/by-query?filter=kind=user&filter=kind=group` - Return all service components: `/entities/by-query?filter=kind=component,spec.type=service` - Return all entities with the `java` tag: `/entities/by-query?filter=metadata.tags.java` - Return all users who are members of the `ops` group (note that the full [reference](references.md) of the group is used): `/entities/by-query?filter=kind=user,relations.memberof=group:default/ops` */ public async getEntityFacets( // @ts-ignore diff --git a/packages/catalog-client/src/schema/openapi/generated/models/AnalyzeLocationExistingEntity.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/AnalyzeLocationExistingEntity.model.ts index ea3d097ec5..06998f5422 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/AnalyzeLocationExistingEntity.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/AnalyzeLocationExistingEntity.model.ts @@ -17,12 +17,11 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { Entity } from '../models/Entity.model'; import { LocationSpec } from '../models/LocationSpec.model'; /** - * If the folder pointed to already contained catalog info yaml files, they are read and emitted like this so that the frontend can inform the user that it located them and can make sure to register them as well if they weren't already + * If the folder pointed to already contained catalog info yaml files, they are read and emitted like this so that the frontend can inform the user that it located them and can make sure to register them as well if they weren\'t already * @public */ export interface AnalyzeLocationExistingEntity { diff --git a/packages/catalog-client/src/schema/openapi/generated/models/AnalyzeLocationGenerateEntity.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/AnalyzeLocationGenerateEntity.model.ts index 2999da3ddf..7b2ba72114 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/AnalyzeLocationGenerateEntity.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/AnalyzeLocationGenerateEntity.model.ts @@ -17,12 +17,11 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { AnalyzeLocationEntityField } from '../models/AnalyzeLocationEntityField.model'; import { RecursivePartialEntity } from '../models/RecursivePartialEntity.model'; /** - * This is some form of representation of what the analyzer could deduce. We should probably have a chat about how this can best be conveyed to the frontend. It'll probably contain a (possibly incomplete) entity, plus enough info for the frontend to know what form data to show to the user for overriding/completing the info. + * This is some form of representation of what the analyzer could deduce. We should probably have a chat about how this can best be conveyed to the frontend. It\'ll probably contain a (possibly incomplete) entity, plus enough info for the frontend to know what form data to show to the user for overriding/completing the info. * @public */ export interface AnalyzeLocationGenerateEntity { diff --git a/packages/catalog-client/src/schema/openapi/generated/models/AnalyzeLocationRequest.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/AnalyzeLocationRequest.model.ts index 5099a5c8aa..a0a5615f25 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/AnalyzeLocationRequest.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/AnalyzeLocationRequest.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { LocationInput } from '../models/LocationInput.model'; /** diff --git a/packages/catalog-client/src/schema/openapi/generated/models/AnalyzeLocationResponse.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/AnalyzeLocationResponse.model.ts index a5eac33f7c..d4d8a0fdd9 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/AnalyzeLocationResponse.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/AnalyzeLocationResponse.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { AnalyzeLocationExistingEntity } from '../models/AnalyzeLocationExistingEntity.model'; import { AnalyzeLocationGenerateEntity } from '../models/AnalyzeLocationGenerateEntity.model'; diff --git a/packages/catalog-client/src/schema/openapi/generated/models/CreateLocation201Response.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/CreateLocation201Response.model.ts index 610e565b3e..e224386de4 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/CreateLocation201Response.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/CreateLocation201Response.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { Entity } from '../models/Entity.model'; import { Location } from '../models/Location.model'; diff --git a/packages/catalog-client/src/schema/openapi/generated/models/EntitiesBatchResponse.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/EntitiesBatchResponse.model.ts index e8bf79a501..0434965888 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/EntitiesBatchResponse.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/EntitiesBatchResponse.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { NullableEntity } from '../models/NullableEntity.model'; /** diff --git a/packages/catalog-client/src/schema/openapi/generated/models/EntitiesQueryResponse.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/EntitiesQueryResponse.model.ts index d201466db6..5165faec58 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/EntitiesQueryResponse.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/EntitiesQueryResponse.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { EntitiesQueryResponsePageInfo } from '../models/EntitiesQueryResponsePageInfo.model'; import { Entity } from '../models/Entity.model'; diff --git a/packages/catalog-client/src/schema/openapi/generated/models/Entity.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/Entity.model.ts index 108a7b15b8..00cc91e89b 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/Entity.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/Entity.model.ts @@ -17,12 +17,11 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { EntityMeta } from '../models/EntityMeta.model'; import { EntityRelation } from '../models/EntityRelation.model'; /** - * The parts of the format that's common to all versions/kinds of entity. + * The parts of the format that\'s common to all versions/kinds of entity. * @public */ export interface Entity { diff --git a/packages/catalog-client/src/schema/openapi/generated/models/EntityAncestryResponse.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/EntityAncestryResponse.model.ts index f2c1116f35..9d1e4d9052 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/EntityAncestryResponse.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/EntityAncestryResponse.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { EntityAncestryResponseItemsInner } from '../models/EntityAncestryResponseItemsInner.model'; /** diff --git a/packages/catalog-client/src/schema/openapi/generated/models/EntityAncestryResponseItemsInner.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/EntityAncestryResponseItemsInner.model.ts index 9c816e5517..0936545ec7 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/EntityAncestryResponseItemsInner.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/EntityAncestryResponseItemsInner.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { Entity } from '../models/Entity.model'; /** diff --git a/packages/catalog-client/src/schema/openapi/generated/models/EntityFacetsResponse.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/EntityFacetsResponse.model.ts index 5cc67294e5..540650bcaf 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/EntityFacetsResponse.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/EntityFacetsResponse.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { EntityFacet } from '../models/EntityFacet.model'; /** diff --git a/packages/catalog-client/src/schema/openapi/generated/models/EntityMeta.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/EntityMeta.model.ts index c1e1471045..a35ee87b61 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/EntityMeta.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/EntityMeta.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { EntityLink } from '../models/EntityLink.model'; /** @@ -26,7 +25,6 @@ import { EntityLink } from '../models/EntityLink.model'; */ export interface EntityMeta { [key: string]: any; - /** * A list of external hyperlinks related to the entity. */ diff --git a/packages/catalog-client/src/schema/openapi/generated/models/GetLocations200ResponseInner.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/GetLocations200ResponseInner.model.ts index b77b78971f..846b58ba97 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/GetLocations200ResponseInner.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/GetLocations200ResponseInner.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { Location } from '../models/Location.model'; /** diff --git a/packages/catalog-client/src/schema/openapi/generated/models/LocationsQueryResponse.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/LocationsQueryResponse.model.ts index c231fccc57..05259caf32 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/LocationsQueryResponse.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/LocationsQueryResponse.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { Location } from '../models/Location.model'; import { LocationsQueryResponsePageInfo } from '../models/LocationsQueryResponsePageInfo.model'; diff --git a/packages/catalog-client/src/schema/openapi/generated/models/ModelError.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/ModelError.model.ts index 207f16f828..9d5c36325e 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/ModelError.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/ModelError.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { ErrorError } from '../models/ErrorError.model'; import { ErrorRequest } from '../models/ErrorRequest.model'; import { ErrorResponse } from '../models/ErrorResponse.model'; @@ -27,7 +26,6 @@ import { ErrorResponse } from '../models/ErrorResponse.model'; */ export interface ModelError { [key: string]: any; - error: ErrorError; request?: ErrorRequest; response: ErrorResponse; diff --git a/packages/catalog-client/src/schema/openapi/generated/models/NullableEntity.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/NullableEntity.model.ts index 5e59af3327..288b6febb6 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/NullableEntity.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/NullableEntity.model.ts @@ -17,12 +17,11 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { EntityMeta } from '../models/EntityMeta.model'; import { EntityRelation } from '../models/EntityRelation.model'; /** - * The parts of the format that's common to all versions/kinds of entity. + * The parts of the format that\'s common to all versions/kinds of entity. * @public */ export type NullableEntity = { diff --git a/packages/catalog-client/src/schema/openapi/generated/models/QueryEntitiesByPredicateRequest.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/QueryEntitiesByPredicateRequest.model.ts index 17a9c9962f..7196156f55 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/QueryEntitiesByPredicateRequest.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/QueryEntitiesByPredicateRequest.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { QueryEntitiesByPredicateRequestFullTextFilter } from '../models/QueryEntitiesByPredicateRequestFullTextFilter.model'; import { QueryEntitiesByPredicateRequestOrderByInner } from '../models/QueryEntitiesByPredicateRequestOrderByInner.model'; diff --git a/packages/catalog-client/src/schema/openapi/generated/models/RecursivePartialEntity.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/RecursivePartialEntity.model.ts index 3f09c69672..3a607dd878 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/RecursivePartialEntity.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/RecursivePartialEntity.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { RecursivePartialEntityMeta } from '../models/RecursivePartialEntityMeta.model'; import { RecursivePartialEntityRelation } from '../models/RecursivePartialEntityRelation.model'; diff --git a/packages/catalog-client/src/schema/openapi/generated/models/RecursivePartialEntityMeta.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/RecursivePartialEntityMeta.model.ts index 2db84dd085..7c2d3bed48 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/RecursivePartialEntityMeta.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/RecursivePartialEntityMeta.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { EntityLink } from '../models/EntityLink.model'; /** diff --git a/packages/catalog-client/src/schema/openapi/generated/models/RecursivePartialEntityMetaAllOf.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/RecursivePartialEntityMetaAllOf.model.ts deleted file mode 100644 index caca69a622..0000000000 --- a/packages/catalog-client/src/schema/openapi/generated/models/RecursivePartialEntityMetaAllOf.model.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2026 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. - */ - -// ****************************************************************** -// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * -// ****************************************************************** - -import { EntityLink } from '../models/EntityLink.model'; - -/** - * Metadata fields common to all versions/kinds of entity. - * @public - */ -export interface RecursivePartialEntityMetaAllOf { - /** - * A list of external hyperlinks related to the entity. - */ - links?: Array; - /** - * A list of single-valued strings, to for example classify catalog entities in various ways. - */ - tags?: Array; - /** - * Construct a type with a set of properties K of type T - */ - annotations?: { [key: string]: string }; - /** - * Construct a type with a set of properties K of type T - */ - labels?: { [key: string]: string }; - /** - * A short (typically relatively few words, on one line) description of the entity. - */ - description?: string; - /** - * A display name of the entity, to be presented in user interfaces instead of the `name` property above, when available. This field is sometimes useful when the `name` is cumbersome or ends up being perceived as overly technical. The title generally does not have as stringent format requirements on it, so it may contain special characters and be more explanatory. Do keep it very short though, and avoid situations where a title can be confused with the name of another entity, or where two entities share a title. Note that this is only for display purposes, and may be ignored by some parts of the code. Entity references still always make use of the `name` property, not the title. - */ - title?: string; - /** - * The namespace that the entity belongs to. - */ - namespace?: string; - /** - * The name of the entity. Must be unique within the catalog at any given point in time, for any given namespace + kind pair. This value is part of the technical identifier of the entity, and as such it will appear in URLs, database tables, entity references, and similar. It is subject to restrictions regarding what characters are allowed. If you want to use a different, more human readable string with fewer restrictions on it in user interfaces, see the `title` field below. - */ - name?: string; - /** - * An opaque string that changes for each update operation to any part of the entity, including metadata. This field can not be set by the user at creation time, and the server will reject an attempt to do so. The field will be populated in read operations. The field can (optionally) be specified when performing update or delete operations, and the server will then reject the operation if it does not match the current stored value. - */ - etag?: string; - /** - * A globally unique ID for the entity. This field can not be set by the user at creation time, and the server will reject an attempt to do so. The field will be populated in read operations. The field can (optionally) be specified when performing update or delete operations, but the server is free to reject requests that do so in such a way that it breaks semantics. - */ - uid?: string; -} diff --git a/packages/catalog-client/src/schema/openapi/generated/models/ValidateEntity400Response.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/ValidateEntity400Response.model.ts index aabf825a57..2a41f2df5c 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/ValidateEntity400Response.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/ValidateEntity400Response.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { ValidateEntity400ResponseErrorsInner } from '../models/ValidateEntity400ResponseErrorsInner.model'; /** diff --git a/packages/catalog-client/src/schema/openapi/generated/models/ValidateEntity400ResponseErrorsInner.model.ts b/packages/catalog-client/src/schema/openapi/generated/models/ValidateEntity400ResponseErrorsInner.model.ts index 4582bf2046..f8a7ae4386 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/ValidateEntity400ResponseErrorsInner.model.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/ValidateEntity400ResponseErrorsInner.model.ts @@ -23,7 +23,6 @@ */ export interface ValidateEntity400ResponseErrorsInner { [key: string]: any; - name: string; message: string; } diff --git a/packages/catalog-client/src/schema/openapi/generated/models/index.ts b/packages/catalog-client/src/schema/openapi/generated/models/index.ts index ebecb8dbb7..aaafc8e60e 100644 --- a/packages/catalog-client/src/schema/openapi/generated/models/index.ts +++ b/packages/catalog-client/src/schema/openapi/generated/models/index.ts @@ -51,7 +51,6 @@ export * from '../models/QueryEntitiesByPredicateRequestOrderByInner.model'; export * from '../models/QueryEntityFacetsByPredicateRequest.model'; export * from '../models/RecursivePartialEntity.model'; export * from '../models/RecursivePartialEntityMeta.model'; -export * from '../models/RecursivePartialEntityMetaAllOf.model'; export * from '../models/RecursivePartialEntityRelation.model'; export * from '../models/RefreshEntityRequest.model'; export * from '../models/ValidateEntity400Response.model'; diff --git a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/apis/Api.client.ts b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/apis/Api.client.ts index 8623dc3c33..9802afba0f 100644 --- a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/apis/Api.client.ts +++ b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/apis/Api.client.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -17,6 +17,7 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** + import { DiscoveryApi } from '../types/discovery'; import { FetchApi } from '../types/fetch'; import crossFetch from 'cross-fetch'; diff --git a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/apis/index.ts b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/apis/index.ts index fc7c83b736..c2e931caf8 100644 --- a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/apis/index.ts +++ b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/apis/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/index.ts b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/index.ts index dc3055033d..19501a5dcb 100644 --- a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/index.ts +++ b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/ErrorError.model.ts b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/ErrorError.model.ts index e0265e95d7..853f88cc14 100644 --- a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/ErrorError.model.ts +++ b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/ErrorError.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/ErrorRequest.model.ts b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/ErrorRequest.model.ts index 3eb5e15740..1591911bc9 100644 --- a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/ErrorRequest.model.ts +++ b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/ErrorRequest.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/ErrorResponse.model.ts b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/ErrorResponse.model.ts index edbcc32df7..1eff0557ed 100644 --- a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/ErrorResponse.model.ts +++ b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/ErrorResponse.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/ModelError.model.ts b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/ModelError.model.ts index 958fde7d0b..9d5c36325e 100644 --- a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/ModelError.model.ts +++ b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/ModelError.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -26,7 +26,6 @@ import { ErrorResponse } from '../models/ErrorResponse.model'; */ export interface ModelError { [key: string]: any; - error: ErrorError; request?: ErrorRequest; response: ErrorResponse; diff --git a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/Remote.model.ts b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/Remote.model.ts index 7440110ad8..ff5cae705f 100644 --- a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/Remote.model.ts +++ b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/Remote.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/RemoteInfo.model.ts b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/RemoteInfo.model.ts index 72edba90d4..6e8bdeff0a 100644 --- a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/RemoteInfo.model.ts +++ b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/RemoteInfo.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/index.ts b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/index.ts index 0c54a6585b..4cf296a0b9 100644 --- a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/index.ts +++ b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/models/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/pluginId.ts b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/pluginId.ts index eaea330f99..465ea2d806 100644 --- a/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/pluginId.ts +++ b/packages/frontend-dynamic-feature-loader/src/schema/openapi/generated/pluginId.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/frontend-dynamic-feature-loader/src/schema/openapi/index.ts b/packages/frontend-dynamic-feature-loader/src/schema/openapi/index.ts index 196aad553a..fb49a2b9c0 100644 --- a/packages/frontend-dynamic-feature-loader/src/schema/openapi/index.ts +++ b/packages/frontend-dynamic-feature-loader/src/schema/openapi/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/packages/repo-tools/openapitools.json b/packages/repo-tools/openapitools.json index 65c0d8ead7..c7593e7a28 100644 --- a/packages/repo-tools/openapitools.json +++ b/packages/repo-tools/openapitools.json @@ -2,6 +2,6 @@ "$schema": "../../node_modules/@openapitools/openapi-generator-cli/config.schema.json", "spaces": 2, "generator-cli": { - "version": "6.5.0" + "version": "7.18.0" } } diff --git a/packages/repo-tools/src/commands/package/schema/openapi/generate/client.ts b/packages/repo-tools/src/commands/package/schema/openapi/generate/client.ts index c5b2807fbd..42e9a9e682 100644 --- a/packages/repo-tools/src/commands/package/schema/openapi/generate/client.ts +++ b/packages/repo-tools/src/commands/package/schema/openapi/generate/client.ts @@ -26,6 +26,7 @@ import { import { deduplicateImports } from '../../../../../lib/openapi/dedupe-imports'; import { targetPaths } from '@backstage/cli-common'; import { + getOpenApiGeneratorKey, getPathToCurrentOpenApiSpec, toGeneratorAdditionalProperties, } from '../../../../../lib/openapi/helpers'; @@ -43,6 +44,7 @@ async function generate( const additionalProperties = toGeneratorAdditionalProperties({ initialValue: clientAdditionalProperties, }); + const generatorKey = await getOpenApiGeneratorKey(resolvedOpenapiPath); await fs.emptyDir(resolvedOutputDirectory); @@ -68,7 +70,7 @@ async function generate( 'templates/typescript-backstage-client.yaml', ), '--generator-key', - 'v3.0', + generatorKey, additionalProperties ? `--additional-properties=${additionalProperties}` : '', @@ -111,7 +113,12 @@ async function generate( } fs.removeSync(resolve(resolvedOutputDirectory, '.openapi-generator-ignore')); + fs.removeSync(resolve(resolvedOutputDirectory, '.gitattributes')); + fs.rmSync(resolve(resolvedOutputDirectory, 'docs'), { + recursive: true, + force: true, + }); fs.rmSync(resolve(resolvedOutputDirectory, '.openapi-generator'), { recursive: true, force: true, diff --git a/packages/repo-tools/src/commands/package/schema/openapi/generate/server.ts b/packages/repo-tools/src/commands/package/schema/openapi/generate/server.ts index e913fd3a8c..daaf619450 100644 --- a/packages/repo-tools/src/commands/package/schema/openapi/generate/server.ts +++ b/packages/repo-tools/src/commands/package/schema/openapi/generate/server.ts @@ -29,6 +29,7 @@ import { import { deduplicateImports } from '../../../../../lib/openapi/dedupe-imports'; import { targetPaths } from '@backstage/cli-common'; import { + getOpenApiGeneratorKey, getPathToCurrentOpenApiSpec, getRelativePathToFile, toGeneratorAdditionalProperties, @@ -103,6 +104,7 @@ async function generate( const additionalProperties = toGeneratorAdditionalProperties({ initialValue: serverAdditionalProperties, }); + const generatorKey = await getOpenApiGeneratorKey(resolvedOpenapiPath); await exec( 'node', @@ -121,7 +123,7 @@ async function generate( 'templates/typescript-backstage-server.yaml', ), '--generator-key', - 'v3.0', + generatorKey, additionalProperties ? `--additional-properties=${additionalProperties}` : '', @@ -160,7 +162,12 @@ async function generate( } fs.removeSync(resolve(resolvedOutputDirectory, '.openapi-generator-ignore')); + fs.removeSync(resolve(resolvedOutputDirectory, '.gitattributes')); + fs.rmSync(resolve(resolvedOutputDirectory, 'docs'), { + recursive: true, + force: true, + }); fs.rmSync(resolve(resolvedOutputDirectory, '.openapi-generator'), { recursive: true, force: true, diff --git a/packages/repo-tools/src/commands/repo/schema/openapi/lint.ts b/packages/repo-tools/src/commands/repo/schema/openapi/lint.ts index 34c8589d54..91f43c4cee 100644 --- a/packages/repo-tools/src/commands/repo/schema/openapi/lint.ts +++ b/packages/repo-tools/src/commands/repo/schema/openapi/lint.ts @@ -49,13 +49,15 @@ async function lint(directoryPath: string, config?: { strict: boolean }) { { extends: [oas, ruleset], rules: { - 'allow-reserved-in-params': { - given: '$.paths..parameters[*]', + 'allow-reserved-in-query-params': { + given: '$.paths..parameters[?(@.in == "query")]', then: { field: 'allowReserved', function: truthy, }, severity: 'error', + message: + 'Query parameters must specify allowReserved (true or false)', }, }, overrides: [ diff --git a/packages/repo-tools/src/lib/openapi/helpers.ts b/packages/repo-tools/src/lib/openapi/helpers.ts index d6b6927660..c4cd1564c6 100644 --- a/packages/repo-tools/src/lib/openapi/helpers.ts +++ b/packages/repo-tools/src/lib/openapi/helpers.ts @@ -70,3 +70,32 @@ export function toGeneratorAdditionalProperties({ .map(([key, value]) => `${key}=${value}`) .join(','); } + +export async function getOpenApiGeneratorKey( + specPath: string, +): Promise { + const yaml = (await loadAndValidateOpenApiYaml(specPath)) as any; + const version = yaml.openapi; + + if (!version) { + throw new Error(`Could not determine OpenAPI version from ${specPath}`); + } + + const semver = /^(\d+)\.(\d+)\.(\d+)(-.+)?$/.exec(version); + if (!semver) { + throw new Error(`Invalid OpenAPI version format ${version} in ${specPath}`); + } + const [, major, minor] = semver; + const supportedVersions = ['3.0', '3.1']; + + const majorMinor = `${major}.${minor}`; + if (!supportedVersions.includes(majorMinor)) { + throw new Error( + `Unsupported OpenAPI version ${version} in ${specPath}. Supported versions are: ${supportedVersions.join( + ', ', + )}`, + ); + } + + return `v${majorMinor}`; +} diff --git a/plugins/catalog-backend/src/schema/openapi.yaml b/plugins/catalog-backend/src/schema/openapi.yaml index 382dfedade..57d950b9f8 100644 --- a/plugins/catalog-backend/src/schema/openapi.yaml +++ b/plugins/catalog-backend/src/schema/openapi.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.1.0 info: title: catalog version: '1' @@ -35,28 +35,24 @@ components: name: kind in: path required: true - allowReserved: true schema: type: string namespace: name: namespace in: path required: true - allowReserved: true schema: type: string name: name: name in: path required: true - allowReserved: true schema: type: string uid: name: uid in: path required: true - allowReserved: true schema: type: string cursor: @@ -478,31 +474,32 @@ components: - apiVersion description: The parts of the format that's common to all versions/kinds of entity. NullableEntity: - type: object - properties: - relations: - type: array - items: - $ref: '#/components/schemas/EntityRelation' - description: The relations that this entity has with other entities. - spec: - $ref: '#/components/schemas/JsonObject' - metadata: - $ref: '#/components/schemas/EntityMeta' - kind: - type: string - description: The high level entity type being described. - apiVersion: - type: string - description: |- - The version of specification format for this particular entity that - this is written against. - required: - - metadata - - kind - - apiVersion - description: The parts of the format that's common to all versions/kinds of entity. - nullable: true + anyOf: + - type: object + properties: + relations: + type: array + items: + $ref: '#/components/schemas/EntityRelation' + description: The relations that this entity has with other entities. + spec: + $ref: '#/components/schemas/JsonObject' + metadata: + $ref: '#/components/schemas/EntityMeta' + kind: + type: string + description: The high level entity type being described. + apiVersion: + type: string + description: |- + The version of specification format for this particular entity that + this is written against. + required: + - metadata + - kind + - apiVersion + description: The parts of the format that's common to all versions/kinds of entity. + - type: 'null' EntityAncestryResponse: type: object properties: @@ -748,8 +745,9 @@ components: field empty; which would currently make it owned by X" where X is taken from the codeowners file. value: - type: string - nullable: true + oneOf: + - type: string + - type: 'null' state: type: string enum: @@ -1361,7 +1359,6 @@ paths: - in: path name: id required: true - allowReserved: true schema: type: string delete: @@ -1383,7 +1380,6 @@ paths: - in: path name: id required: true - allowReserved: true schema: type: string /locations/by-entity/{kind}/{namespace}/{name}: @@ -1408,19 +1404,16 @@ paths: - in: path name: kind required: true - allowReserved: true schema: type: string - in: path name: namespace required: true - allowReserved: true schema: type: string - in: path name: name required: true - allowReserved: true schema: type: string /analyze-location: diff --git a/plugins/catalog-backend/src/schema/openapi/generated/apis/Api.server.ts b/plugins/catalog-backend/src/schema/openapi/generated/apis/Api.server.ts index 3362f903d0..cbde6365ea 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/apis/Api.server.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/apis/Api.server.ts @@ -19,7 +19,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { EntitiesBatchResponse } from '../models/EntitiesBatchResponse.model'; import { EntitiesQueryResponse } from '../models/EntitiesQueryResponse.model'; import { Entity } from '../models/Entity.model'; diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/AnalyzeLocationExistingEntity.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/AnalyzeLocationExistingEntity.model.ts index ea3d097ec5..06998f5422 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/AnalyzeLocationExistingEntity.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/AnalyzeLocationExistingEntity.model.ts @@ -17,12 +17,11 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { Entity } from '../models/Entity.model'; import { LocationSpec } from '../models/LocationSpec.model'; /** - * If the folder pointed to already contained catalog info yaml files, they are read and emitted like this so that the frontend can inform the user that it located them and can make sure to register them as well if they weren't already + * If the folder pointed to already contained catalog info yaml files, they are read and emitted like this so that the frontend can inform the user that it located them and can make sure to register them as well if they weren\'t already * @public */ export interface AnalyzeLocationExistingEntity { diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/AnalyzeLocationGenerateEntity.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/AnalyzeLocationGenerateEntity.model.ts index 2999da3ddf..7b2ba72114 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/AnalyzeLocationGenerateEntity.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/AnalyzeLocationGenerateEntity.model.ts @@ -17,12 +17,11 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { AnalyzeLocationEntityField } from '../models/AnalyzeLocationEntityField.model'; import { RecursivePartialEntity } from '../models/RecursivePartialEntity.model'; /** - * This is some form of representation of what the analyzer could deduce. We should probably have a chat about how this can best be conveyed to the frontend. It'll probably contain a (possibly incomplete) entity, plus enough info for the frontend to know what form data to show to the user for overriding/completing the info. + * This is some form of representation of what the analyzer could deduce. We should probably have a chat about how this can best be conveyed to the frontend. It\'ll probably contain a (possibly incomplete) entity, plus enough info for the frontend to know what form data to show to the user for overriding/completing the info. * @public */ export interface AnalyzeLocationGenerateEntity { diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/AnalyzeLocationRequest.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/AnalyzeLocationRequest.model.ts index 5099a5c8aa..a0a5615f25 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/AnalyzeLocationRequest.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/AnalyzeLocationRequest.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { LocationInput } from '../models/LocationInput.model'; /** diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/AnalyzeLocationResponse.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/AnalyzeLocationResponse.model.ts index a5eac33f7c..d4d8a0fdd9 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/AnalyzeLocationResponse.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/AnalyzeLocationResponse.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { AnalyzeLocationExistingEntity } from '../models/AnalyzeLocationExistingEntity.model'; import { AnalyzeLocationGenerateEntity } from '../models/AnalyzeLocationGenerateEntity.model'; diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/CreateLocation201Response.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/CreateLocation201Response.model.ts index 610e565b3e..e224386de4 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/CreateLocation201Response.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/CreateLocation201Response.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { Entity } from '../models/Entity.model'; import { Location } from '../models/Location.model'; diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/EntitiesBatchResponse.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/EntitiesBatchResponse.model.ts index e8bf79a501..0434965888 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/EntitiesBatchResponse.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/EntitiesBatchResponse.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { NullableEntity } from '../models/NullableEntity.model'; /** diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/EntitiesQueryResponse.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/EntitiesQueryResponse.model.ts index d201466db6..5165faec58 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/EntitiesQueryResponse.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/EntitiesQueryResponse.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { EntitiesQueryResponsePageInfo } from '../models/EntitiesQueryResponsePageInfo.model'; import { Entity } from '../models/Entity.model'; diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/Entity.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/Entity.model.ts index 108a7b15b8..00cc91e89b 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/Entity.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/Entity.model.ts @@ -17,12 +17,11 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { EntityMeta } from '../models/EntityMeta.model'; import { EntityRelation } from '../models/EntityRelation.model'; /** - * The parts of the format that's common to all versions/kinds of entity. + * The parts of the format that\'s common to all versions/kinds of entity. * @public */ export interface Entity { diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/EntityAncestryResponse.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/EntityAncestryResponse.model.ts index f2c1116f35..9d1e4d9052 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/EntityAncestryResponse.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/EntityAncestryResponse.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { EntityAncestryResponseItemsInner } from '../models/EntityAncestryResponseItemsInner.model'; /** diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/EntityAncestryResponseItemsInner.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/EntityAncestryResponseItemsInner.model.ts index 9c816e5517..0936545ec7 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/EntityAncestryResponseItemsInner.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/EntityAncestryResponseItemsInner.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { Entity } from '../models/Entity.model'; /** diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/EntityFacetsResponse.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/EntityFacetsResponse.model.ts index 5cc67294e5..540650bcaf 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/EntityFacetsResponse.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/EntityFacetsResponse.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { EntityFacet } from '../models/EntityFacet.model'; /** diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/EntityMeta.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/EntityMeta.model.ts index c1e1471045..a35ee87b61 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/EntityMeta.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/EntityMeta.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { EntityLink } from '../models/EntityLink.model'; /** @@ -26,7 +25,6 @@ import { EntityLink } from '../models/EntityLink.model'; */ export interface EntityMeta { [key: string]: any; - /** * A list of external hyperlinks related to the entity. */ diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/GetLocations200ResponseInner.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/GetLocations200ResponseInner.model.ts index b77b78971f..846b58ba97 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/GetLocations200ResponseInner.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/GetLocations200ResponseInner.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { Location } from '../models/Location.model'; /** diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/LocationsQueryResponse.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/LocationsQueryResponse.model.ts index c231fccc57..05259caf32 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/LocationsQueryResponse.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/LocationsQueryResponse.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { Location } from '../models/Location.model'; import { LocationsQueryResponsePageInfo } from '../models/LocationsQueryResponsePageInfo.model'; diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/ModelError.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/ModelError.model.ts index 207f16f828..9d5c36325e 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/ModelError.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/ModelError.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { ErrorError } from '../models/ErrorError.model'; import { ErrorRequest } from '../models/ErrorRequest.model'; import { ErrorResponse } from '../models/ErrorResponse.model'; @@ -27,7 +26,6 @@ import { ErrorResponse } from '../models/ErrorResponse.model'; */ export interface ModelError { [key: string]: any; - error: ErrorError; request?: ErrorRequest; response: ErrorResponse; diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/NullableEntity.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/NullableEntity.model.ts index 5e59af3327..288b6febb6 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/NullableEntity.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/NullableEntity.model.ts @@ -17,12 +17,11 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { EntityMeta } from '../models/EntityMeta.model'; import { EntityRelation } from '../models/EntityRelation.model'; /** - * The parts of the format that's common to all versions/kinds of entity. + * The parts of the format that\'s common to all versions/kinds of entity. * @public */ export type NullableEntity = { diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/QueryEntitiesByPredicateRequest.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/QueryEntitiesByPredicateRequest.model.ts index 17a9c9962f..7196156f55 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/QueryEntitiesByPredicateRequest.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/QueryEntitiesByPredicateRequest.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { QueryEntitiesByPredicateRequestFullTextFilter } from '../models/QueryEntitiesByPredicateRequestFullTextFilter.model'; import { QueryEntitiesByPredicateRequestOrderByInner } from '../models/QueryEntitiesByPredicateRequestOrderByInner.model'; diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/RecursivePartialEntity.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/RecursivePartialEntity.model.ts index 3f09c69672..3a607dd878 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/RecursivePartialEntity.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/RecursivePartialEntity.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { RecursivePartialEntityMeta } from '../models/RecursivePartialEntityMeta.model'; import { RecursivePartialEntityRelation } from '../models/RecursivePartialEntityRelation.model'; diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/RecursivePartialEntityMeta.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/RecursivePartialEntityMeta.model.ts index 2db84dd085..7c2d3bed48 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/RecursivePartialEntityMeta.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/RecursivePartialEntityMeta.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { EntityLink } from '../models/EntityLink.model'; /** diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/RecursivePartialEntityMetaAllOf.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/RecursivePartialEntityMetaAllOf.model.ts deleted file mode 100644 index caca69a622..0000000000 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/RecursivePartialEntityMetaAllOf.model.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2026 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. - */ - -// ****************************************************************** -// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * -// ****************************************************************** - -import { EntityLink } from '../models/EntityLink.model'; - -/** - * Metadata fields common to all versions/kinds of entity. - * @public - */ -export interface RecursivePartialEntityMetaAllOf { - /** - * A list of external hyperlinks related to the entity. - */ - links?: Array; - /** - * A list of single-valued strings, to for example classify catalog entities in various ways. - */ - tags?: Array; - /** - * Construct a type with a set of properties K of type T - */ - annotations?: { [key: string]: string }; - /** - * Construct a type with a set of properties K of type T - */ - labels?: { [key: string]: string }; - /** - * A short (typically relatively few words, on one line) description of the entity. - */ - description?: string; - /** - * A display name of the entity, to be presented in user interfaces instead of the `name` property above, when available. This field is sometimes useful when the `name` is cumbersome or ends up being perceived as overly technical. The title generally does not have as stringent format requirements on it, so it may contain special characters and be more explanatory. Do keep it very short though, and avoid situations where a title can be confused with the name of another entity, or where two entities share a title. Note that this is only for display purposes, and may be ignored by some parts of the code. Entity references still always make use of the `name` property, not the title. - */ - title?: string; - /** - * The namespace that the entity belongs to. - */ - namespace?: string; - /** - * The name of the entity. Must be unique within the catalog at any given point in time, for any given namespace + kind pair. This value is part of the technical identifier of the entity, and as such it will appear in URLs, database tables, entity references, and similar. It is subject to restrictions regarding what characters are allowed. If you want to use a different, more human readable string with fewer restrictions on it in user interfaces, see the `title` field below. - */ - name?: string; - /** - * An opaque string that changes for each update operation to any part of the entity, including metadata. This field can not be set by the user at creation time, and the server will reject an attempt to do so. The field will be populated in read operations. The field can (optionally) be specified when performing update or delete operations, and the server will then reject the operation if it does not match the current stored value. - */ - etag?: string; - /** - * A globally unique ID for the entity. This field can not be set by the user at creation time, and the server will reject an attempt to do so. The field will be populated in read operations. The field can (optionally) be specified when performing update or delete operations, but the server is free to reject requests that do so in such a way that it breaks semantics. - */ - uid?: string; -} diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/ValidateEntity400Response.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/ValidateEntity400Response.model.ts index aabf825a57..2a41f2df5c 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/ValidateEntity400Response.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/ValidateEntity400Response.model.ts @@ -17,7 +17,6 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** - import { ValidateEntity400ResponseErrorsInner } from '../models/ValidateEntity400ResponseErrorsInner.model'; /** diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/ValidateEntity400ResponseErrorsInner.model.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/ValidateEntity400ResponseErrorsInner.model.ts index 4582bf2046..f8a7ae4386 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/ValidateEntity400ResponseErrorsInner.model.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/ValidateEntity400ResponseErrorsInner.model.ts @@ -23,7 +23,6 @@ */ export interface ValidateEntity400ResponseErrorsInner { [key: string]: any; - name: string; message: string; } diff --git a/plugins/catalog-backend/src/schema/openapi/generated/models/index.ts b/plugins/catalog-backend/src/schema/openapi/generated/models/index.ts index ebecb8dbb7..aaafc8e60e 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/models/index.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/models/index.ts @@ -51,7 +51,6 @@ export * from '../models/QueryEntitiesByPredicateRequestOrderByInner.model'; export * from '../models/QueryEntityFacetsByPredicateRequest.model'; export * from '../models/RecursivePartialEntity.model'; export * from '../models/RecursivePartialEntityMeta.model'; -export * from '../models/RecursivePartialEntityMetaAllOf.model'; export * from '../models/RecursivePartialEntityRelation.model'; export * from '../models/RefreshEntityRequest.model'; export * from '../models/ValidateEntity400Response.model'; diff --git a/plugins/catalog-backend/src/schema/openapi/generated/router.ts b/plugins/catalog-backend/src/schema/openapi/generated/router.ts index 74668310c5..56ee4cc036 100644 --- a/plugins/catalog-backend/src/schema/openapi/generated/router.ts +++ b/plugins/catalog-backend/src/schema/openapi/generated/router.ts @@ -21,7 +21,7 @@ import { createValidatedOpenApiRouterFromGeneratedEndpointMap } from '@backstage import { EndpointMap } from './apis'; export const spec = { - openapi: '3.0.3', + openapi: '3.1.0', info: { title: 'catalog', version: '1', @@ -46,7 +46,6 @@ export const spec = { name: 'kind', in: 'path', required: true, - allowReserved: true, schema: { type: 'string', }, @@ -55,7 +54,6 @@ export const spec = { name: 'namespace', in: 'path', required: true, - allowReserved: true, schema: { type: 'string', }, @@ -64,7 +62,6 @@ export const spec = { name: 'name', in: 'path', required: true, - allowReserved: true, schema: { type: 'string', }, @@ -73,7 +70,6 @@ export const spec = { name: 'uid', in: 'path', required: true, - allowReserved: true, schema: { type: 'string', }, @@ -404,36 +400,42 @@ export const spec = { "The parts of the format that's common to all versions/kinds of entity.", }, NullableEntity: { - type: 'object', - properties: { - relations: { - type: 'array', - items: { - $ref: '#/components/schemas/EntityRelation', + anyOf: [ + { + type: 'object', + properties: { + relations: { + type: 'array', + items: { + $ref: '#/components/schemas/EntityRelation', + }, + description: + 'The relations that this entity has with other entities.', + }, + spec: { + $ref: '#/components/schemas/JsonObject', + }, + metadata: { + $ref: '#/components/schemas/EntityMeta', + }, + kind: { + type: 'string', + description: 'The high level entity type being described.', + }, + apiVersion: { + type: 'string', + description: + 'The version of specification format for this particular entity that\nthis is written against.', + }, }, + required: ['metadata', 'kind', 'apiVersion'], description: - 'The relations that this entity has with other entities.', + "The parts of the format that's common to all versions/kinds of entity.", }, - spec: { - $ref: '#/components/schemas/JsonObject', + { + type: 'null', }, - metadata: { - $ref: '#/components/schemas/EntityMeta', - }, - kind: { - type: 'string', - description: 'The high level entity type being described.', - }, - apiVersion: { - type: 'string', - description: - 'The version of specification format for this particular entity that\nthis is written against.', - }, - }, - required: ['metadata', 'kind', 'apiVersion'], - description: - "The parts of the format that's common to all versions/kinds of entity.", - nullable: true, + ], }, EntityAncestryResponse: { type: 'object', @@ -703,8 +705,14 @@ export const spec = { 'A text to show to the user to inform about the choices made. Like, it could say\n"Found a CODEOWNERS file that covers this target, so we suggest leaving this\nfield empty; which would currently make it owned by X" where X is taken from the\ncodeowners file.', }, value: { - type: 'string', - nullable: true, + oneOf: [ + { + type: 'string', + }, + { + type: 'null', + }, + ], }, state: { type: 'string', @@ -1620,7 +1628,6 @@ export const spec = { in: 'path', name: 'id', required: true, - allowReserved: true, schema: { type: 'string', }, @@ -1653,7 +1660,6 @@ export const spec = { in: 'path', name: 'id', required: true, - allowReserved: true, schema: { type: 'string', }, @@ -1692,7 +1698,6 @@ export const spec = { in: 'path', name: 'kind', required: true, - allowReserved: true, schema: { type: 'string', }, @@ -1701,7 +1706,6 @@ export const spec = { in: 'path', name: 'namespace', required: true, - allowReserved: true, schema: { type: 'string', }, @@ -1710,7 +1714,6 @@ export const spec = { in: 'path', name: 'name', required: true, - allowReserved: true, schema: { type: 'string', }, diff --git a/plugins/events-backend/src/schema/openapi.yaml b/plugins/events-backend/src/schema/openapi.yaml index 97f7705f87..6ff064d660 100644 --- a/plugins/events-backend/src/schema/openapi.yaml +++ b/plugins/events-backend/src/schema/openapi.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.1.0 info: title: events version: '1' @@ -17,7 +17,6 @@ components: name: subscriptionId in: path required: true - allowReserved: true schema: type: string requestBodies: {} diff --git a/plugins/events-backend/src/schema/openapi/generated/apis/Api.server.ts b/plugins/events-backend/src/schema/openapi/generated/apis/Api.server.ts index 0b116fe012..62130143f9 100644 --- a/plugins/events-backend/src/schema/openapi/generated/apis/Api.server.ts +++ b/plugins/events-backend/src/schema/openapi/generated/apis/Api.server.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-backend/src/schema/openapi/generated/apis/index.ts b/plugins/events-backend/src/schema/openapi/generated/apis/index.ts index 8d81cbaf39..9a0ffed740 100644 --- a/plugins/events-backend/src/schema/openapi/generated/apis/index.ts +++ b/plugins/events-backend/src/schema/openapi/generated/apis/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-backend/src/schema/openapi/generated/index.ts b/plugins/events-backend/src/schema/openapi/generated/index.ts index dec4b8804e..58fc52487a 100644 --- a/plugins/events-backend/src/schema/openapi/generated/index.ts +++ b/plugins/events-backend/src/schema/openapi/generated/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-backend/src/schema/openapi/generated/models/ErrorError.model.ts b/plugins/events-backend/src/schema/openapi/generated/models/ErrorError.model.ts index 809cd3fa80..d72822b815 100644 --- a/plugins/events-backend/src/schema/openapi/generated/models/ErrorError.model.ts +++ b/plugins/events-backend/src/schema/openapi/generated/models/ErrorError.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-backend/src/schema/openapi/generated/models/ErrorRequest.model.ts b/plugins/events-backend/src/schema/openapi/generated/models/ErrorRequest.model.ts index 3eb5e15740..1591911bc9 100644 --- a/plugins/events-backend/src/schema/openapi/generated/models/ErrorRequest.model.ts +++ b/plugins/events-backend/src/schema/openapi/generated/models/ErrorRequest.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-backend/src/schema/openapi/generated/models/ErrorResponse.model.ts b/plugins/events-backend/src/schema/openapi/generated/models/ErrorResponse.model.ts index edbcc32df7..1eff0557ed 100644 --- a/plugins/events-backend/src/schema/openapi/generated/models/ErrorResponse.model.ts +++ b/plugins/events-backend/src/schema/openapi/generated/models/ErrorResponse.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-backend/src/schema/openapi/generated/models/Event.model.ts b/plugins/events-backend/src/schema/openapi/generated/models/Event.model.ts index 02e52a81d9..04cf4b5d3d 100644 --- a/plugins/events-backend/src/schema/openapi/generated/models/Event.model.ts +++ b/plugins/events-backend/src/schema/openapi/generated/models/Event.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -26,8 +26,5 @@ export interface Event { * The topic that the event is published on */ topic: string; - /** - * The event payload - */ payload: any | null; } diff --git a/plugins/events-backend/src/schema/openapi/generated/models/GetSubscriptionEvents200Response.model.ts b/plugins/events-backend/src/schema/openapi/generated/models/GetSubscriptionEvents200Response.model.ts index ff15eef3ce..cd0b45e19d 100644 --- a/plugins/events-backend/src/schema/openapi/generated/models/GetSubscriptionEvents200Response.model.ts +++ b/plugins/events-backend/src/schema/openapi/generated/models/GetSubscriptionEvents200Response.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-backend/src/schema/openapi/generated/models/ModelError.model.ts b/plugins/events-backend/src/schema/openapi/generated/models/ModelError.model.ts index 3914d73531..c4af31b48c 100644 --- a/plugins/events-backend/src/schema/openapi/generated/models/ModelError.model.ts +++ b/plugins/events-backend/src/schema/openapi/generated/models/ModelError.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-backend/src/schema/openapi/generated/models/PostEventRequest.model.ts b/plugins/events-backend/src/schema/openapi/generated/models/PostEventRequest.model.ts index 6bbb2974b5..c097e10d11 100644 --- a/plugins/events-backend/src/schema/openapi/generated/models/PostEventRequest.model.ts +++ b/plugins/events-backend/src/schema/openapi/generated/models/PostEventRequest.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-backend/src/schema/openapi/generated/models/PutSubscriptionRequest.model.ts b/plugins/events-backend/src/schema/openapi/generated/models/PutSubscriptionRequest.model.ts index 786f0a0644..dabc823807 100644 --- a/plugins/events-backend/src/schema/openapi/generated/models/PutSubscriptionRequest.model.ts +++ b/plugins/events-backend/src/schema/openapi/generated/models/PutSubscriptionRequest.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-backend/src/schema/openapi/generated/models/index.ts b/plugins/events-backend/src/schema/openapi/generated/models/index.ts index 6baa8ef449..b3cd7dc096 100644 --- a/plugins/events-backend/src/schema/openapi/generated/models/index.ts +++ b/plugins/events-backend/src/schema/openapi/generated/models/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-backend/src/schema/openapi/generated/router.ts b/plugins/events-backend/src/schema/openapi/generated/router.ts index f1b9de2099..ce89146f9b 100644 --- a/plugins/events-backend/src/schema/openapi/generated/router.ts +++ b/plugins/events-backend/src/schema/openapi/generated/router.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -21,7 +21,7 @@ import { createValidatedOpenApiRouterFromGeneratedEndpointMap } from '@backstage import { EndpointMap } from './apis'; export const spec = { - openapi: '3.0.3', + openapi: '3.1.0', info: { title: 'events', version: '1', @@ -45,7 +45,6 @@ export const spec = { name: 'subscriptionId', in: 'path', required: true, - allowReserved: true, schema: { type: 'string', }, diff --git a/plugins/events-backend/src/schema/openapi/index.ts b/plugins/events-backend/src/schema/openapi/index.ts index 196aad553a..fb49a2b9c0 100644 --- a/plugins/events-backend/src/schema/openapi/index.ts +++ b/plugins/events-backend/src/schema/openapi/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-node/src/schema/openapi/generated/apis/Api.client.ts b/plugins/events-node/src/schema/openapi/generated/apis/Api.client.ts index 71e3767af2..a03ea2e7fd 100644 --- a/plugins/events-node/src/schema/openapi/generated/apis/Api.client.ts +++ b/plugins/events-node/src/schema/openapi/generated/apis/Api.client.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -17,6 +17,7 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** + import { DiscoveryApi } from '../types/discovery'; import { FetchApi } from '../types/fetch'; import crossFetch from 'cross-fetch'; diff --git a/plugins/events-node/src/schema/openapi/generated/apis/index.ts b/plugins/events-node/src/schema/openapi/generated/apis/index.ts index fc7c83b736..c2e931caf8 100644 --- a/plugins/events-node/src/schema/openapi/generated/apis/index.ts +++ b/plugins/events-node/src/schema/openapi/generated/apis/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-node/src/schema/openapi/generated/index.ts b/plugins/events-node/src/schema/openapi/generated/index.ts index dc3055033d..19501a5dcb 100644 --- a/plugins/events-node/src/schema/openapi/generated/index.ts +++ b/plugins/events-node/src/schema/openapi/generated/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-node/src/schema/openapi/generated/models/ErrorError.model.ts b/plugins/events-node/src/schema/openapi/generated/models/ErrorError.model.ts index 809cd3fa80..d72822b815 100644 --- a/plugins/events-node/src/schema/openapi/generated/models/ErrorError.model.ts +++ b/plugins/events-node/src/schema/openapi/generated/models/ErrorError.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-node/src/schema/openapi/generated/models/ErrorRequest.model.ts b/plugins/events-node/src/schema/openapi/generated/models/ErrorRequest.model.ts index 3eb5e15740..1591911bc9 100644 --- a/plugins/events-node/src/schema/openapi/generated/models/ErrorRequest.model.ts +++ b/plugins/events-node/src/schema/openapi/generated/models/ErrorRequest.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-node/src/schema/openapi/generated/models/ErrorResponse.model.ts b/plugins/events-node/src/schema/openapi/generated/models/ErrorResponse.model.ts index edbcc32df7..1eff0557ed 100644 --- a/plugins/events-node/src/schema/openapi/generated/models/ErrorResponse.model.ts +++ b/plugins/events-node/src/schema/openapi/generated/models/ErrorResponse.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-node/src/schema/openapi/generated/models/Event.model.ts b/plugins/events-node/src/schema/openapi/generated/models/Event.model.ts index 02e52a81d9..04cf4b5d3d 100644 --- a/plugins/events-node/src/schema/openapi/generated/models/Event.model.ts +++ b/plugins/events-node/src/schema/openapi/generated/models/Event.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -26,8 +26,5 @@ export interface Event { * The topic that the event is published on */ topic: string; - /** - * The event payload - */ payload: any | null; } diff --git a/plugins/events-node/src/schema/openapi/generated/models/GetSubscriptionEvents200Response.model.ts b/plugins/events-node/src/schema/openapi/generated/models/GetSubscriptionEvents200Response.model.ts index ff15eef3ce..cd0b45e19d 100644 --- a/plugins/events-node/src/schema/openapi/generated/models/GetSubscriptionEvents200Response.model.ts +++ b/plugins/events-node/src/schema/openapi/generated/models/GetSubscriptionEvents200Response.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-node/src/schema/openapi/generated/models/ModelError.model.ts b/plugins/events-node/src/schema/openapi/generated/models/ModelError.model.ts index 3914d73531..c4af31b48c 100644 --- a/plugins/events-node/src/schema/openapi/generated/models/ModelError.model.ts +++ b/plugins/events-node/src/schema/openapi/generated/models/ModelError.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-node/src/schema/openapi/generated/models/PostEventRequest.model.ts b/plugins/events-node/src/schema/openapi/generated/models/PostEventRequest.model.ts index 6bbb2974b5..c097e10d11 100644 --- a/plugins/events-node/src/schema/openapi/generated/models/PostEventRequest.model.ts +++ b/plugins/events-node/src/schema/openapi/generated/models/PostEventRequest.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-node/src/schema/openapi/generated/models/PutSubscriptionRequest.model.ts b/plugins/events-node/src/schema/openapi/generated/models/PutSubscriptionRequest.model.ts index 786f0a0644..dabc823807 100644 --- a/plugins/events-node/src/schema/openapi/generated/models/PutSubscriptionRequest.model.ts +++ b/plugins/events-node/src/schema/openapi/generated/models/PutSubscriptionRequest.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-node/src/schema/openapi/generated/models/index.ts b/plugins/events-node/src/schema/openapi/generated/models/index.ts index 6baa8ef449..b3cd7dc096 100644 --- a/plugins/events-node/src/schema/openapi/generated/models/index.ts +++ b/plugins/events-node/src/schema/openapi/generated/models/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-node/src/schema/openapi/generated/pluginId.ts b/plugins/events-node/src/schema/openapi/generated/pluginId.ts index b5fc50cfc0..5351088e31 100644 --- a/plugins/events-node/src/schema/openapi/generated/pluginId.ts +++ b/plugins/events-node/src/schema/openapi/generated/pluginId.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/events-node/src/schema/openapi/index.ts b/plugins/events-node/src/schema/openapi/index.ts index 196aad553a..fb49a2b9c0 100644 --- a/plugins/events-node/src/schema/openapi/index.ts +++ b/plugins/events-node/src/schema/openapi/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi.yaml b/plugins/scaffolder-backend/src/schema/openapi.yaml index b26515a71b..72fa89532c 100644 --- a/plugins/scaffolder-backend/src/schema/openapi.yaml +++ b/plugins/scaffolder-backend/src/schema/openapi.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.1.0 info: title: scaffolder version: '1' @@ -35,7 +35,6 @@ components: name: kind in: path required: true - allowReserved: true schema: type: string limit: @@ -51,14 +50,12 @@ components: name: namespace in: path required: true - allowReserved: true schema: type: string name: name: name in: path required: true - allowReserved: true schema: type: string offset: @@ -94,7 +91,6 @@ components: name: taskId in: path required: true - allowReserved: true schema: type: string requestBodies: {} @@ -224,8 +220,7 @@ components: - type: boolean - type: number - type: string - - type: object - nullable: true + - type: 'null' description: A type representing all allowed JSON primitive values. JsonValue: oneOf: @@ -428,8 +423,9 @@ components: description: type: string value: - type: object - nullable: true + anyOf: + - type: object + - type: 'null' required: - value description: The response shape for a single global value in the `listTemplatingExtensions` call to the `scaffolder-backend` @@ -860,13 +856,11 @@ paths: - in: path name: provider required: true - allowReserved: true schema: type: string - in: path name: resource required: true - allowReserved: true schema: type: string diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/apis/Api.server.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/apis/Api.server.ts index c5bd9f0ac2..6263921887 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/apis/Api.server.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/apis/Api.server.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/apis/index.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/apis/index.ts index 8d81cbaf39..9a0ffed740 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/apis/index.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/apis/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/index.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/index.ts index dec4b8804e..58fc52487a 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/index.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/Action.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/Action.model.ts index f9c028f3e3..a29e2f704d 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/Action.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/Action.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ActionExample.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ActionExample.model.ts index 50550e2883..c7a5cf5075 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ActionExample.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ActionExample.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ActionSchema.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ActionSchema.model.ts index 35d2014181..e8cc85c647 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ActionSchema.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ActionSchema.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/Autocomplete200Response.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/Autocomplete200Response.model.ts index e3eec0aa20..eb59d6a061 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/Autocomplete200Response.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/Autocomplete200Response.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/Autocomplete200ResponseResultsInner.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/Autocomplete200ResponseResultsInner.model.ts index 00ccb41b0f..fe329488d5 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/Autocomplete200ResponseResultsInner.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/Autocomplete200ResponseResultsInner.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/Autocomplete400Response.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/Autocomplete400Response.model.ts index 1456babb96..3dae0fd0f1 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/Autocomplete400Response.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/Autocomplete400Response.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/AutocompleteRequest.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/AutocompleteRequest.model.ts index 769a929918..197582c944 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/AutocompleteRequest.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/AutocompleteRequest.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/CancelTask200Response.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/CancelTask200Response.model.ts index f29c509d41..b23fafc892 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/CancelTask200Response.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/CancelTask200Response.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRun200Response.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRun200Response.model.ts index 62e3689d5d..d0c1450785 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRun200Response.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRun200Response.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRun200ResponseAllOf.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRun200ResponseAllOf.model.ts deleted file mode 100644 index 5b6c2ff9c7..0000000000 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRun200ResponseAllOf.model.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2025 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. - */ - -// ****************************************************************** -// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * -// ****************************************************************** -import { DryRun200ResponseAllOfDirectoryContentsInner } from '../models/DryRun200ResponseAllOfDirectoryContentsInner.model'; -import { DryRun200ResponseAllOfStepsInner } from '../models/DryRun200ResponseAllOfStepsInner.model'; - -/** - * @public - */ -export interface DryRun200ResponseAllOf { - steps: Array; - directoryContents?: Array; -} diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRun200ResponseAllOfDirectoryContentsInner.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRun200ResponseAllOfDirectoryContentsInner.model.ts index 2646ca49f9..ced04f2ae6 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRun200ResponseAllOfDirectoryContentsInner.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRun200ResponseAllOfDirectoryContentsInner.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRun200ResponseAllOfStepsInner.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRun200ResponseAllOfStepsInner.model.ts index 2a462edefa..9818ca581e 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRun200ResponseAllOfStepsInner.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRun200ResponseAllOfStepsInner.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -23,7 +23,6 @@ */ export interface DryRun200ResponseAllOfStepsInner { [key: string]: any; - id: string; name: string; action: string; diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunRequest.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunRequest.model.ts index 212b36c26b..254605a6b4 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunRequest.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunRequest.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunRequestDirectoryContentsInner.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunRequestDirectoryContentsInner.model.ts index ddcae4fd9d..f01e2d18c8 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunRequestDirectoryContentsInner.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunRequestDirectoryContentsInner.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunResult.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunResult.model.ts index 6e2ad23ef4..cfdcf163bd 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunResult.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunResult.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunResultLogInner.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunResultLogInner.model.ts index 4c6b786d82..496650d8ba 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunResultLogInner.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunResultLogInner.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunResultLogInnerBody.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunResultLogInnerBody.model.ts index e3b19be045..a56e7b1107 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunResultLogInnerBody.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunResultLogInnerBody.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunResultLogInnerBodyAllOf.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunResultLogInnerBodyAllOf.model.ts deleted file mode 100644 index e67240ee54..0000000000 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/DryRunResultLogInnerBodyAllOf.model.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2025 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. - */ - -// ****************************************************************** -// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * -// ****************************************************************** -import { TaskStatus } from '../models/TaskStatus.model'; - -/** - * @public - */ -export interface DryRunResultLogInnerBodyAllOf { - message: string; - status?: TaskStatus; - stepId?: string; -} diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ErrorError.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ErrorError.model.ts index e0265e95d7..853f88cc14 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ErrorError.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ErrorError.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ErrorRequest.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ErrorRequest.model.ts index 3eb5e15740..1591911bc9 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ErrorRequest.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ErrorRequest.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ErrorResponse.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ErrorResponse.model.ts index edbcc32df7..1eff0557ed 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ErrorResponse.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ErrorResponse.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/JsonPrimitive.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/JsonPrimitive.model.ts index 6aa6394c14..0142269c5b 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/JsonPrimitive.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/JsonPrimitive.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -22,4 +22,4 @@ * A type representing all allowed JSON primitive values. * @public */ -export type JsonPrimitive = any | boolean | number | string; +export type JsonPrimitive = boolean | number | string; diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/JsonValue.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/JsonValue.model.ts index 9fe2ac9de3..a706c3c93e 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/JsonValue.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/JsonValue.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ListTasksResponse.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ListTasksResponse.model.ts index 9347c766a9..0f641660fe 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ListTasksResponse.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ListTasksResponse.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ListTemplatingExtensionsResponse.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ListTemplatingExtensionsResponse.model.ts index 74b7cd3780..6c65af534c 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ListTemplatingExtensionsResponse.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ListTemplatingExtensionsResponse.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ListTemplatingExtensionsResponseGlobals.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ListTemplatingExtensionsResponseGlobals.model.ts index 1f022a0675..b827a9f083 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ListTemplatingExtensionsResponseGlobals.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ListTemplatingExtensionsResponseGlobals.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ModelError.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ModelError.model.ts index 958fde7d0b..9d5c36325e 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ModelError.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ModelError.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -26,7 +26,6 @@ import { ErrorResponse } from '../models/ErrorResponse.model'; */ export interface ModelError { [key: string]: any; - error: ErrorError; request?: ErrorRequest; response: ErrorResponse; diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/RetryRequest.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/RetryRequest.model.ts index 858fa67566..b25d0a2ed5 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/RetryRequest.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/RetryRequest.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/Scaffold201Response.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/Scaffold201Response.model.ts index 1271642e81..b69aa7b00c 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/Scaffold201Response.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/Scaffold201Response.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/Scaffold400Response.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/Scaffold400Response.model.ts index e3cb7eaa45..d42caec5a4 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/Scaffold400Response.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/Scaffold400Response.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ScaffolderScaffoldOptions.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ScaffolderScaffoldOptions.model.ts index 93f4ae71c0..dbcc372253 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ScaffolderScaffoldOptions.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ScaffolderScaffoldOptions.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ScaffolderUsageExample.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ScaffolderUsageExample.model.ts index 3e0f4ef866..7e664963eb 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ScaffolderUsageExample.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ScaffolderUsageExample.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/SerializedFile.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/SerializedFile.model.ts index 65a3c714a7..74ee62f05a 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/SerializedFile.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/SerializedFile.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/SerializedTask.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/SerializedTask.model.ts index 67cbf14279..779efcab87 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/SerializedTask.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/SerializedTask.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/SerializedTaskEvent.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/SerializedTaskEvent.model.ts index 6e4ddaa296..da412a5839 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/SerializedTaskEvent.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/SerializedTaskEvent.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TaskEventType.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TaskEventType.model.ts index d32d77a448..daa28d1d62 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TaskEventType.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TaskEventType.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TaskSecrets.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TaskSecrets.model.ts index c78c39c1ec..0cbaa38a55 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TaskSecrets.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TaskSecrets.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TaskSecretsAllOf.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TaskSecretsAllOf.model.ts deleted file mode 100644 index 0b33852cc9..0000000000 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TaskSecretsAllOf.model.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2025 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. - */ - -// ****************************************************************** -// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * -// ****************************************************************** - -/** - * @public - */ -export interface TaskSecretsAllOf { - backstageToken?: string; -} diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TaskStatus.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TaskStatus.model.ts index 1f209a3656..75df8d3679 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TaskStatus.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TaskStatus.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateFilter.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateFilter.model.ts index 7c631978e6..3339c61a77 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateFilter.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateFilter.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateFilterSchema.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateFilterSchema.model.ts index 5a95a58ead..930a9760d9 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateFilterSchema.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateFilterSchema.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateGlobalFunction.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateGlobalFunction.model.ts index ee19ce723b..7567b3112d 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateGlobalFunction.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateGlobalFunction.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateGlobalFunctionSchema.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateGlobalFunctionSchema.model.ts index b3a39c3b24..731cf53496 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateGlobalFunctionSchema.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateGlobalFunctionSchema.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateGlobalValue.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateGlobalValue.model.ts index 95d177a05a..d85fe0c395 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateGlobalValue.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateGlobalValue.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateParameterSchema.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateParameterSchema.model.ts index 8638ee8114..dd71410c86 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateParameterSchema.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateParameterSchema.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -25,7 +25,6 @@ import { TemplateParameterSchemaStepsInner } from '../models/TemplateParameterSc */ export interface TemplateParameterSchema { [key: string]: any; - title: string; description?: string; steps: Array; diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateParameterSchemaStepsInner.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateParameterSchemaStepsInner.model.ts index 2f7892fd41..ef94e58643 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateParameterSchemaStepsInner.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/TemplateParameterSchemaStepsInner.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ValidationError.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ValidationError.model.ts index 7e762f616c..43c45c8351 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ValidationError.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ValidationError.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -25,7 +25,6 @@ import { ValidationErrorPathInner } from '../models/ValidationErrorPathInner.mod */ export interface ValidationError { [key: string]: any; - path: Array; property: string; message: string; diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ValidationErrorArgument.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ValidationErrorArgument.model.ts index 85c9576fd0..123b2a0d76 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ValidationErrorArgument.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ValidationErrorArgument.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ValidationErrorPathInner.model.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ValidationErrorPathInner.model.ts index 4535c735db..53d3b9d2e7 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/ValidationErrorPathInner.model.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/ValidationErrorPathInner.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/models/index.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/models/index.ts index 1bc447fa3d..3d5ceab140 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/models/index.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/models/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -23,7 +23,6 @@ export * from '../models/Autocomplete400Response.model'; export * from '../models/AutocompleteRequest.model'; export * from '../models/CancelTask200Response.model'; export * from '../models/DryRun200Response.model'; -export * from '../models/DryRun200ResponseAllOf.model'; export * from '../models/DryRun200ResponseAllOfDirectoryContentsInner.model'; export * from '../models/DryRun200ResponseAllOfStepsInner.model'; export * from '../models/DryRunRequest.model'; @@ -31,7 +30,6 @@ export * from '../models/DryRunRequestDirectoryContentsInner.model'; export * from '../models/DryRunResult.model'; export * from '../models/DryRunResultLogInner.model'; export * from '../models/DryRunResultLogInnerBody.model'; -export * from '../models/DryRunResultLogInnerBodyAllOf.model'; export * from '../models/ErrorError.model'; export * from '../models/ErrorRequest.model'; export * from '../models/ErrorResponse.model'; @@ -51,7 +49,6 @@ export * from '../models/SerializedTask.model'; export * from '../models/SerializedTaskEvent.model'; export * from '../models/TaskEventType.model'; export * from '../models/TaskSecrets.model'; -export * from '../models/TaskSecretsAllOf.model'; export * from '../models/TaskStatus.model'; export * from '../models/TemplateFilter.model'; export * from '../models/TemplateFilterSchema.model'; diff --git a/plugins/scaffolder-backend/src/schema/openapi/generated/router.ts b/plugins/scaffolder-backend/src/schema/openapi/generated/router.ts index 6401c84964..1cb3ba755f 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/generated/router.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/generated/router.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -21,7 +21,7 @@ import { createValidatedOpenApiRouterFromGeneratedEndpointMap } from '@backstage import { EndpointMap } from './apis'; export const spec = { - openapi: '3.0.3', + openapi: '3.1.0', info: { title: 'scaffolder', version: '1', @@ -69,7 +69,6 @@ export const spec = { name: 'kind', in: 'path', required: true, - allowReserved: true, schema: { type: 'string', }, @@ -89,7 +88,6 @@ export const spec = { name: 'namespace', in: 'path', required: true, - allowReserved: true, schema: { type: 'string', }, @@ -98,7 +96,6 @@ export const spec = { name: 'name', in: 'path', required: true, - allowReserved: true, schema: { type: 'string', }, @@ -144,7 +141,6 @@ export const spec = { name: 'taskId', in: 'path', required: true, - allowReserved: true, schema: { type: 'string', }, @@ -325,8 +321,7 @@ export const spec = { type: 'string', }, { - type: 'object', - nullable: true, + type: 'null', }, ], description: 'A type representing all allowed JSON primitive values.', @@ -605,8 +600,14 @@ export const spec = { type: 'string', }, value: { - type: 'object', - nullable: true, + anyOf: [ + { + type: 'object', + }, + { + type: 'null', + }, + ], }, }, required: ['value'], @@ -1272,7 +1273,6 @@ export const spec = { in: 'path', name: 'provider', required: true, - allowReserved: true, schema: { type: 'string', }, @@ -1281,7 +1281,6 @@ export const spec = { in: 'path', name: 'resource', required: true, - allowReserved: true, schema: { type: 'string', }, diff --git a/plugins/scaffolder-backend/src/schema/openapi/index.ts b/plugins/scaffolder-backend/src/schema/openapi/index.ts index 196aad553a..fb49a2b9c0 100644 --- a/plugins/scaffolder-backend/src/schema/openapi/index.ts +++ b/plugins/scaffolder-backend/src/schema/openapi/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/apis/Api.client.ts b/plugins/scaffolder-common/src/schema/openapi/generated/apis/Api.client.ts index ca5ae10b8f..e87c838d1a 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/apis/Api.client.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/apis/Api.client.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -17,6 +17,7 @@ // ****************************************************************** // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** + import { DiscoveryApi } from '../types/discovery'; import { FetchApi } from '../types/fetch'; import crossFetch from 'cross-fetch'; diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/apis/index.ts b/plugins/scaffolder-common/src/schema/openapi/generated/apis/index.ts index fc7c83b736..c2e931caf8 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/apis/index.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/apis/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/index.ts b/plugins/scaffolder-common/src/schema/openapi/generated/index.ts index dc3055033d..19501a5dcb 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/index.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/Action.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/Action.model.ts index f9c028f3e3..a29e2f704d 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/Action.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/Action.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/ActionExample.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/ActionExample.model.ts index 50550e2883..c7a5cf5075 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/ActionExample.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/ActionExample.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/ActionSchema.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/ActionSchema.model.ts index 35d2014181..e8cc85c647 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/ActionSchema.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/ActionSchema.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/Autocomplete200Response.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/Autocomplete200Response.model.ts index e3eec0aa20..eb59d6a061 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/Autocomplete200Response.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/Autocomplete200Response.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/Autocomplete200ResponseResultsInner.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/Autocomplete200ResponseResultsInner.model.ts index 00ccb41b0f..fe329488d5 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/Autocomplete200ResponseResultsInner.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/Autocomplete200ResponseResultsInner.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/Autocomplete400Response.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/Autocomplete400Response.model.ts index 1456babb96..3dae0fd0f1 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/Autocomplete400Response.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/Autocomplete400Response.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/AutocompleteRequest.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/AutocompleteRequest.model.ts index 769a929918..197582c944 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/AutocompleteRequest.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/AutocompleteRequest.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/CancelTask200Response.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/CancelTask200Response.model.ts index f29c509d41..b23fafc892 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/CancelTask200Response.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/CancelTask200Response.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRun200Response.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRun200Response.model.ts index 62e3689d5d..d0c1450785 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRun200Response.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRun200Response.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRun200ResponseAllOf.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRun200ResponseAllOf.model.ts deleted file mode 100644 index 5b6c2ff9c7..0000000000 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRun200ResponseAllOf.model.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2025 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. - */ - -// ****************************************************************** -// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * -// ****************************************************************** -import { DryRun200ResponseAllOfDirectoryContentsInner } from '../models/DryRun200ResponseAllOfDirectoryContentsInner.model'; -import { DryRun200ResponseAllOfStepsInner } from '../models/DryRun200ResponseAllOfStepsInner.model'; - -/** - * @public - */ -export interface DryRun200ResponseAllOf { - steps: Array; - directoryContents?: Array; -} diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRun200ResponseAllOfDirectoryContentsInner.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRun200ResponseAllOfDirectoryContentsInner.model.ts index 2646ca49f9..ced04f2ae6 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRun200ResponseAllOfDirectoryContentsInner.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRun200ResponseAllOfDirectoryContentsInner.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRun200ResponseAllOfStepsInner.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRun200ResponseAllOfStepsInner.model.ts index 2a462edefa..9818ca581e 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRun200ResponseAllOfStepsInner.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRun200ResponseAllOfStepsInner.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -23,7 +23,6 @@ */ export interface DryRun200ResponseAllOfStepsInner { [key: string]: any; - id: string; name: string; action: string; diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunRequest.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunRequest.model.ts index 212b36c26b..254605a6b4 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunRequest.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunRequest.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunRequestDirectoryContentsInner.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunRequestDirectoryContentsInner.model.ts index ddcae4fd9d..f01e2d18c8 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunRequestDirectoryContentsInner.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunRequestDirectoryContentsInner.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunResult.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunResult.model.ts index 6e2ad23ef4..cfdcf163bd 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunResult.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunResult.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunResultLogInner.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunResultLogInner.model.ts index 4c6b786d82..496650d8ba 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunResultLogInner.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunResultLogInner.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunResultLogInnerBody.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunResultLogInnerBody.model.ts index e3b19be045..a56e7b1107 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunResultLogInnerBody.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunResultLogInnerBody.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunResultLogInnerBodyAllOf.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunResultLogInnerBodyAllOf.model.ts deleted file mode 100644 index e67240ee54..0000000000 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/DryRunResultLogInnerBodyAllOf.model.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2025 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. - */ - -// ****************************************************************** -// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * -// ****************************************************************** -import { TaskStatus } from '../models/TaskStatus.model'; - -/** - * @public - */ -export interface DryRunResultLogInnerBodyAllOf { - message: string; - status?: TaskStatus; - stepId?: string; -} diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/ErrorError.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/ErrorError.model.ts index e0265e95d7..853f88cc14 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/ErrorError.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/ErrorError.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/ErrorRequest.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/ErrorRequest.model.ts index 3eb5e15740..1591911bc9 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/ErrorRequest.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/ErrorRequest.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/ErrorResponse.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/ErrorResponse.model.ts index edbcc32df7..1eff0557ed 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/ErrorResponse.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/ErrorResponse.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/JsonPrimitive.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/JsonPrimitive.model.ts index 6aa6394c14..0142269c5b 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/JsonPrimitive.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/JsonPrimitive.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -22,4 +22,4 @@ * A type representing all allowed JSON primitive values. * @public */ -export type JsonPrimitive = any | boolean | number | string; +export type JsonPrimitive = boolean | number | string; diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/JsonValue.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/JsonValue.model.ts index 9fe2ac9de3..a706c3c93e 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/JsonValue.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/JsonValue.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/ListTasksResponse.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/ListTasksResponse.model.ts index 9347c766a9..0f641660fe 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/ListTasksResponse.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/ListTasksResponse.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/ListTemplatingExtensionsResponse.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/ListTemplatingExtensionsResponse.model.ts index 74b7cd3780..6c65af534c 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/ListTemplatingExtensionsResponse.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/ListTemplatingExtensionsResponse.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/ListTemplatingExtensionsResponseGlobals.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/ListTemplatingExtensionsResponseGlobals.model.ts index 1f022a0675..b827a9f083 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/ListTemplatingExtensionsResponseGlobals.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/ListTemplatingExtensionsResponseGlobals.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/ModelError.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/ModelError.model.ts index 958fde7d0b..9d5c36325e 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/ModelError.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/ModelError.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -26,7 +26,6 @@ import { ErrorResponse } from '../models/ErrorResponse.model'; */ export interface ModelError { [key: string]: any; - error: ErrorError; request?: ErrorRequest; response: ErrorResponse; diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/RetryRequest.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/RetryRequest.model.ts index 858fa67566..b25d0a2ed5 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/RetryRequest.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/RetryRequest.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/Scaffold201Response.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/Scaffold201Response.model.ts index 1271642e81..b69aa7b00c 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/Scaffold201Response.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/Scaffold201Response.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/Scaffold400Response.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/Scaffold400Response.model.ts index e3cb7eaa45..d42caec5a4 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/Scaffold400Response.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/Scaffold400Response.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/ScaffolderScaffoldOptions.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/ScaffolderScaffoldOptions.model.ts index 93f4ae71c0..dbcc372253 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/ScaffolderScaffoldOptions.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/ScaffolderScaffoldOptions.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/ScaffolderUsageExample.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/ScaffolderUsageExample.model.ts index 3e0f4ef866..7e664963eb 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/ScaffolderUsageExample.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/ScaffolderUsageExample.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/SerializedFile.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/SerializedFile.model.ts index 65a3c714a7..74ee62f05a 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/SerializedFile.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/SerializedFile.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/SerializedTask.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/SerializedTask.model.ts index 67cbf14279..779efcab87 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/SerializedTask.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/SerializedTask.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/SerializedTaskEvent.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/SerializedTaskEvent.model.ts index 6e4ddaa296..da412a5839 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/SerializedTaskEvent.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/SerializedTaskEvent.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/TaskEventType.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/TaskEventType.model.ts index d32d77a448..daa28d1d62 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/TaskEventType.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/TaskEventType.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/TaskSecrets.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/TaskSecrets.model.ts index c78c39c1ec..0cbaa38a55 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/TaskSecrets.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/TaskSecrets.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/TaskSecretsAllOf.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/TaskSecretsAllOf.model.ts deleted file mode 100644 index 0b33852cc9..0000000000 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/TaskSecretsAllOf.model.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2025 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. - */ - -// ****************************************************************** -// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * -// ****************************************************************** - -/** - * @public - */ -export interface TaskSecretsAllOf { - backstageToken?: string; -} diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/TaskStatus.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/TaskStatus.model.ts index 1f209a3656..75df8d3679 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/TaskStatus.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/TaskStatus.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateFilter.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateFilter.model.ts index 7c631978e6..3339c61a77 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateFilter.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateFilter.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateFilterSchema.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateFilterSchema.model.ts index 5a95a58ead..930a9760d9 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateFilterSchema.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateFilterSchema.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateGlobalFunction.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateGlobalFunction.model.ts index ee19ce723b..7567b3112d 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateGlobalFunction.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateGlobalFunction.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateGlobalFunctionSchema.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateGlobalFunctionSchema.model.ts index b3a39c3b24..731cf53496 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateGlobalFunctionSchema.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateGlobalFunctionSchema.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateGlobalValue.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateGlobalValue.model.ts index 95d177a05a..d85fe0c395 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateGlobalValue.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateGlobalValue.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateParameterSchema.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateParameterSchema.model.ts index 8638ee8114..dd71410c86 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateParameterSchema.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateParameterSchema.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -25,7 +25,6 @@ import { TemplateParameterSchemaStepsInner } from '../models/TemplateParameterSc */ export interface TemplateParameterSchema { [key: string]: any; - title: string; description?: string; steps: Array; diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateParameterSchemaStepsInner.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateParameterSchemaStepsInner.model.ts index 2f7892fd41..ef94e58643 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateParameterSchemaStepsInner.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/TemplateParameterSchemaStepsInner.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/ValidationError.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/ValidationError.model.ts index 7e762f616c..43c45c8351 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/ValidationError.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/ValidationError.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -25,7 +25,6 @@ import { ValidationErrorPathInner } from '../models/ValidationErrorPathInner.mod */ export interface ValidationError { [key: string]: any; - path: Array; property: string; message: string; diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/ValidationErrorArgument.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/ValidationErrorArgument.model.ts index 85c9576fd0..123b2a0d76 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/ValidationErrorArgument.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/ValidationErrorArgument.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/ValidationErrorPathInner.model.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/ValidationErrorPathInner.model.ts index 4535c735db..53d3b9d2e7 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/ValidationErrorPathInner.model.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/ValidationErrorPathInner.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/models/index.ts b/plugins/scaffolder-common/src/schema/openapi/generated/models/index.ts index 1bc447fa3d..3d5ceab140 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/models/index.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/models/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -23,7 +23,6 @@ export * from '../models/Autocomplete400Response.model'; export * from '../models/AutocompleteRequest.model'; export * from '../models/CancelTask200Response.model'; export * from '../models/DryRun200Response.model'; -export * from '../models/DryRun200ResponseAllOf.model'; export * from '../models/DryRun200ResponseAllOfDirectoryContentsInner.model'; export * from '../models/DryRun200ResponseAllOfStepsInner.model'; export * from '../models/DryRunRequest.model'; @@ -31,7 +30,6 @@ export * from '../models/DryRunRequestDirectoryContentsInner.model'; export * from '../models/DryRunResult.model'; export * from '../models/DryRunResultLogInner.model'; export * from '../models/DryRunResultLogInnerBody.model'; -export * from '../models/DryRunResultLogInnerBodyAllOf.model'; export * from '../models/ErrorError.model'; export * from '../models/ErrorRequest.model'; export * from '../models/ErrorResponse.model'; @@ -51,7 +49,6 @@ export * from '../models/SerializedTask.model'; export * from '../models/SerializedTaskEvent.model'; export * from '../models/TaskEventType.model'; export * from '../models/TaskSecrets.model'; -export * from '../models/TaskSecretsAllOf.model'; export * from '../models/TaskStatus.model'; export * from '../models/TemplateFilter.model'; export * from '../models/TemplateFilterSchema.model'; diff --git a/plugins/scaffolder-common/src/schema/openapi/generated/pluginId.ts b/plugins/scaffolder-common/src/schema/openapi/generated/pluginId.ts index b898028be5..fcfaf1d7c0 100644 --- a/plugins/scaffolder-common/src/schema/openapi/generated/pluginId.ts +++ b/plugins/scaffolder-common/src/schema/openapi/generated/pluginId.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/scaffolder-common/src/schema/openapi/index.ts b/plugins/scaffolder-common/src/schema/openapi/index.ts index 196aad553a..fb49a2b9c0 100644 --- a/plugins/scaffolder-common/src/schema/openapi/index.ts +++ b/plugins/scaffolder-common/src/schema/openapi/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/search-backend/src/schema/openapi.yaml b/plugins/search-backend/src/schema/openapi.yaml index d0257a7ce0..7cb9da72c1 100644 --- a/plugins/search-backend/src/schema/openapi.yaml +++ b/plugins/search-backend/src/schema/openapi.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.1.0 info: title: search version: '1' diff --git a/plugins/search-backend/src/schema/openapi/generated/apis/Api.server.ts b/plugins/search-backend/src/schema/openapi/generated/apis/Api.server.ts index 26652de2cd..d3aa0447a8 100644 --- a/plugins/search-backend/src/schema/openapi/generated/apis/Api.server.ts +++ b/plugins/search-backend/src/schema/openapi/generated/apis/Api.server.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/search-backend/src/schema/openapi/generated/apis/index.ts b/plugins/search-backend/src/schema/openapi/generated/apis/index.ts index 8d81cbaf39..9a0ffed740 100644 --- a/plugins/search-backend/src/schema/openapi/generated/apis/index.ts +++ b/plugins/search-backend/src/schema/openapi/generated/apis/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/search-backend/src/schema/openapi/generated/index.ts b/plugins/search-backend/src/schema/openapi/generated/index.ts index dec4b8804e..58fc52487a 100644 --- a/plugins/search-backend/src/schema/openapi/generated/index.ts +++ b/plugins/search-backend/src/schema/openapi/generated/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/search-backend/src/schema/openapi/generated/models/ErrorError.model.ts b/plugins/search-backend/src/schema/openapi/generated/models/ErrorError.model.ts index 809cd3fa80..d72822b815 100644 --- a/plugins/search-backend/src/schema/openapi/generated/models/ErrorError.model.ts +++ b/plugins/search-backend/src/schema/openapi/generated/models/ErrorError.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/search-backend/src/schema/openapi/generated/models/ErrorRequest.model.ts b/plugins/search-backend/src/schema/openapi/generated/models/ErrorRequest.model.ts index 3eb5e15740..1591911bc9 100644 --- a/plugins/search-backend/src/schema/openapi/generated/models/ErrorRequest.model.ts +++ b/plugins/search-backend/src/schema/openapi/generated/models/ErrorRequest.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/search-backend/src/schema/openapi/generated/models/ErrorResponse.model.ts b/plugins/search-backend/src/schema/openapi/generated/models/ErrorResponse.model.ts index edbcc32df7..1eff0557ed 100644 --- a/plugins/search-backend/src/schema/openapi/generated/models/ErrorResponse.model.ts +++ b/plugins/search-backend/src/schema/openapi/generated/models/ErrorResponse.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/search-backend/src/schema/openapi/generated/models/ModelError.model.ts b/plugins/search-backend/src/schema/openapi/generated/models/ModelError.model.ts index 3914d73531..c4af31b48c 100644 --- a/plugins/search-backend/src/schema/openapi/generated/models/ModelError.model.ts +++ b/plugins/search-backend/src/schema/openapi/generated/models/ModelError.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/search-backend/src/schema/openapi/generated/models/Query200Response.model.ts b/plugins/search-backend/src/schema/openapi/generated/models/Query200Response.model.ts index 190ab8dc59..08abce9f46 100644 --- a/plugins/search-backend/src/schema/openapi/generated/models/Query200Response.model.ts +++ b/plugins/search-backend/src/schema/openapi/generated/models/Query200Response.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/search-backend/src/schema/openapi/generated/models/Query200ResponseResultsInner.model.ts b/plugins/search-backend/src/schema/openapi/generated/models/Query200ResponseResultsInner.model.ts index 7a1c9c155a..f7c9951f50 100644 --- a/plugins/search-backend/src/schema/openapi/generated/models/Query200ResponseResultsInner.model.ts +++ b/plugins/search-backend/src/schema/openapi/generated/models/Query200ResponseResultsInner.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/search-backend/src/schema/openapi/generated/models/Query200ResponseResultsInnerDocument.model.ts b/plugins/search-backend/src/schema/openapi/generated/models/Query200ResponseResultsInnerDocument.model.ts index 004ce76587..99f36fd9a4 100644 --- a/plugins/search-backend/src/schema/openapi/generated/models/Query200ResponseResultsInnerDocument.model.ts +++ b/plugins/search-backend/src/schema/openapi/generated/models/Query200ResponseResultsInnerDocument.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/search-backend/src/schema/openapi/generated/models/index.ts b/plugins/search-backend/src/schema/openapi/generated/models/index.ts index fc9f1408f7..e8ada0c030 100644 --- a/plugins/search-backend/src/schema/openapi/generated/models/index.ts +++ b/plugins/search-backend/src/schema/openapi/generated/models/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. diff --git a/plugins/search-backend/src/schema/openapi/generated/router.ts b/plugins/search-backend/src/schema/openapi/generated/router.ts index a2510346ca..17f0f727e9 100644 --- a/plugins/search-backend/src/schema/openapi/generated/router.ts +++ b/plugins/search-backend/src/schema/openapi/generated/router.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. @@ -21,7 +21,7 @@ import { createValidatedOpenApiRouterFromGeneratedEndpointMap } from '@backstage import { EndpointMap } from './apis'; export const spec = { - openapi: '3.0.3', + openapi: '3.1.0', info: { title: 'search', version: '1', diff --git a/plugins/search-backend/src/schema/openapi/index.ts b/plugins/search-backend/src/schema/openapi/index.ts index 196aad553a..fb49a2b9c0 100644 --- a/plugins/search-backend/src/schema/openapi/index.ts +++ b/plugins/search-backend/src/schema/openapi/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright 2026 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. From 0e7d8f9091ad9127291cc0e495a19eeaa1503039 Mon Sep 17 00:00:00 2001 From: Kurt King Date: Sat, 28 Feb 2026 07:14:47 -0700 Subject: [PATCH 18/26] Refactor scheduler to use metrics service (#32992) * Migrate scheduler metrics to MetricsService Signed-off-by: Kurt King * Add missing changeset Signed-off-by: Kurt King * Update API report Signed-off-by: Kurt King * Release as minor with breaking change verbiage Signed-off-by: Kurt King * Apply suggestion from @aramissennyeydd Signed-off-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com> * fix prettier Signed-off-by: aramissennyeydd --------- Signed-off-by: Kurt King Signed-off-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com> Signed-off-by: aramissennyeydd Co-authored-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com> Co-authored-by: aramissennyeydd --- .changeset/deep-files-clap.md | 5 +++ .../backend-defaults/report-scheduler.api.md | 2 ++ .../lib/DefaultSchedulerService.test.ts | 4 +++ .../scheduler/lib/DefaultSchedulerService.ts | 3 ++ .../lib/PluginTaskSchedulerImpl.test.ts | 2 ++ .../scheduler/lib/PluginTaskSchedulerImpl.ts | 35 ++++++++++++------- .../scheduler/schedulerServiceFactory.ts | 4 +++ 7 files changed, 42 insertions(+), 13 deletions(-) create mode 100644 .changeset/deep-files-clap.md diff --git a/.changeset/deep-files-clap.md b/.changeset/deep-files-clap.md new file mode 100644 index 0000000000..a3ab54eb63 --- /dev/null +++ b/.changeset/deep-files-clap.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-defaults': minor +--- + +The scheduler service now uses the metrics service to create metrics, providing plugin-scoped attribution. diff --git a/packages/backend-defaults/report-scheduler.api.md b/packages/backend-defaults/report-scheduler.api.md index e0a85710a5..44a503d18c 100644 --- a/packages/backend-defaults/report-scheduler.api.md +++ b/packages/backend-defaults/report-scheduler.api.md @@ -6,6 +6,7 @@ import { DatabaseService } from '@backstage/backend-plugin-api'; import { HttpRouterService } from '@backstage/backend-plugin-api'; import { LoggerService } from '@backstage/backend-plugin-api'; +import { MetricsService } from '@backstage/backend-plugin-api/alpha'; import { PluginMetadataService } from '@backstage/backend-plugin-api'; import { RootLifecycleService } from '@backstage/backend-plugin-api'; import { SchedulerService } from '@backstage/backend-plugin-api'; @@ -17,6 +18,7 @@ export class DefaultSchedulerService { static create(options: { database: DatabaseService; logger: LoggerService; + metrics: MetricsService; rootLifecycle: RootLifecycleService; httpRouter: HttpRouterService; pluginMetadata: PluginMetadataService; diff --git a/packages/backend-defaults/src/entrypoints/scheduler/lib/DefaultSchedulerService.test.ts b/packages/backend-defaults/src/entrypoints/scheduler/lib/DefaultSchedulerService.test.ts index 61f9bd0639..3de69ba566 100644 --- a/packages/backend-defaults/src/entrypoints/scheduler/lib/DefaultSchedulerService.test.ts +++ b/packages/backend-defaults/src/entrypoints/scheduler/lib/DefaultSchedulerService.test.ts @@ -20,6 +20,7 @@ import waitForExpect from 'wait-for-expect'; import { DefaultSchedulerService } from './DefaultSchedulerService'; import { createTestScopedSignal } from './__testUtils__/createTestScopedSignal'; import { PluginMetadataService } from '@backstage/backend-plugin-api'; +import { metricsServiceMock } from '@backstage/backend-test-utils/alpha'; jest.setTimeout(60_000); @@ -32,6 +33,7 @@ describe('TaskScheduler', () => { getId: () => 'test', } satisfies PluginMetadataService; const testScopedSignal = createTestScopedSignal(); + const metrics = metricsServiceMock.mock(); it.each(databases.eachSupportedId())( 'can return a working v1 plugin impl, %p', @@ -42,6 +44,7 @@ describe('TaskScheduler', () => { const manager = DefaultSchedulerService.create({ database, logger, + metrics, rootLifecycle, httpRouter, pluginMetadata, @@ -71,6 +74,7 @@ describe('TaskScheduler', () => { const manager = DefaultSchedulerService.create({ database, logger, + metrics, rootLifecycle, httpRouter, pluginMetadata, diff --git a/packages/backend-defaults/src/entrypoints/scheduler/lib/DefaultSchedulerService.ts b/packages/backend-defaults/src/entrypoints/scheduler/lib/DefaultSchedulerService.ts index 0a7b9fbb87..07531cffc8 100644 --- a/packages/backend-defaults/src/entrypoints/scheduler/lib/DefaultSchedulerService.ts +++ b/packages/backend-defaults/src/entrypoints/scheduler/lib/DefaultSchedulerService.ts @@ -27,6 +27,7 @@ import { Duration } from 'luxon'; import { migrateBackendTasks } from '../database/migrateBackendTasks'; import { PluginTaskSchedulerImpl } from './PluginTaskSchedulerImpl'; import { PluginTaskSchedulerJanitor } from './PluginTaskSchedulerJanitor'; +import { MetricsService } from '@backstage/backend-plugin-api/alpha'; /** * Default implementation of the task scheduler service. @@ -37,6 +38,7 @@ export class DefaultSchedulerService { static create(options: { database: DatabaseService; logger: LoggerService; + metrics: MetricsService; rootLifecycle: RootLifecycleService; httpRouter: HttpRouterService; pluginMetadata: PluginMetadataService; @@ -67,6 +69,7 @@ export class DefaultSchedulerService { options.pluginMetadata.getId(), databaseFactory, options.logger, + options.metrics, options.rootLifecycle, ); diff --git a/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.test.ts b/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.test.ts index 5872ae793e..2148148c9e 100644 --- a/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.test.ts +++ b/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.test.ts @@ -27,6 +27,7 @@ import { parseDuration, } from './PluginTaskSchedulerImpl'; import { createDeferred } from '@backstage/types'; +import { metricsServiceMock } from '@backstage/backend-test-utils/alpha'; jest.setTimeout(60_000); @@ -56,6 +57,7 @@ describe('PluginTaskManagerImpl', () => { 'myplugin', async () => knex, mockServices.logger.mock(), + metricsServiceMock.mock(), { addShutdownHook, addBeforeShutdownHook: jest.fn(), diff --git a/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.ts b/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.ts index 90f5d08e4a..e711744123 100644 --- a/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.ts +++ b/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.ts @@ -24,7 +24,13 @@ import { SchedulerServiceTaskRunner, SchedulerServiceTaskScheduleDefinition, } from '@backstage/backend-plugin-api'; -import { Counter, Histogram, Gauge, metrics, trace } from '@opentelemetry/api'; +import { trace } from '@opentelemetry/api'; +import { + MetricsService, + MetricsServiceCounter, + MetricsServiceGauge, + MetricsServiceHistogram, +} from '@backstage/backend-plugin-api/alpha'; import { Knex } from 'knex'; import { Duration } from 'luxon'; import express from 'express'; @@ -45,10 +51,10 @@ export class PluginTaskSchedulerImpl implements SchedulerService { private readonly allScheduledTasks: SchedulerServiceTaskDescriptor[] = []; private readonly shutdownInitiated: Promise; - private readonly counter: Counter; - private readonly duration: Histogram; - private readonly lastStarted: Gauge; - private readonly lastCompleted: Gauge; + private readonly counter: MetricsServiceCounter; + private readonly duration: MetricsServiceHistogram; + private readonly lastStarted: MetricsServiceGauge; + private readonly lastCompleted: MetricsServiceGauge; private readonly pluginId: string; private readonly databaseFactory: () => Promise; @@ -58,24 +64,27 @@ export class PluginTaskSchedulerImpl implements SchedulerService { pluginId: string, databaseFactory: () => Promise, logger: LoggerService, + metrics: MetricsService, rootLifecycle: RootLifecycleService, ) { this.pluginId = pluginId; this.databaseFactory = databaseFactory; this.logger = logger; - const meter = metrics.getMeter('default'); - this.counter = meter.createCounter('backend_tasks.task.runs.count', { + this.counter = metrics.createCounter('backend_tasks.task.runs.count', { description: 'Total number of times a task has been run', }); - this.duration = meter.createHistogram('backend_tasks.task.runs.duration', { - description: 'Histogram of task run durations', - unit: 'seconds', - }); - this.lastStarted = meter.createGauge('backend_tasks.task.runs.started', { + this.duration = metrics.createHistogram( + 'backend_tasks.task.runs.duration', + { + description: 'Histogram of task run durations', + unit: 'seconds', + }, + ); + this.lastStarted = metrics.createGauge('backend_tasks.task.runs.started', { description: 'Epoch timestamp seconds when the task was last started', unit: 'seconds', }); - this.lastCompleted = meter.createGauge( + this.lastCompleted = metrics.createGauge( 'backend_tasks.task.runs.completed', { description: 'Epoch timestamp seconds when the task was last completed', diff --git a/packages/backend-defaults/src/entrypoints/scheduler/schedulerServiceFactory.ts b/packages/backend-defaults/src/entrypoints/scheduler/schedulerServiceFactory.ts index 186e5f6940..8aacdc0005 100644 --- a/packages/backend-defaults/src/entrypoints/scheduler/schedulerServiceFactory.ts +++ b/packages/backend-defaults/src/entrypoints/scheduler/schedulerServiceFactory.ts @@ -18,6 +18,7 @@ import { coreServices, createServiceFactory, } from '@backstage/backend-plugin-api'; +import { metricsServiceRef } from '@backstage/backend-plugin-api/alpha'; import { DefaultSchedulerService } from './lib/DefaultSchedulerService'; /** @@ -37,6 +38,7 @@ export const schedulerServiceFactory = createServiceFactory({ rootLifecycle: coreServices.rootLifecycle, httpRouter: coreServices.httpRouter, pluginMetadata: coreServices.pluginMetadata, + metrics: metricsServiceRef, }, async factory({ database, @@ -44,6 +46,7 @@ export const schedulerServiceFactory = createServiceFactory({ rootLifecycle, httpRouter, pluginMetadata, + metrics, }) { return DefaultSchedulerService.create({ database, @@ -51,6 +54,7 @@ export const schedulerServiceFactory = createServiceFactory({ rootLifecycle, httpRouter, pluginMetadata, + metrics, }); }, }); From cd0c36ffde4fd894bab1e49088a3fedd2d826c34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Sun, 1 Mar 2026 11:17:56 +0100 Subject: [PATCH 19/26] docs: Fix inverted owner relation type in descriptor format docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `spec.owner` relation tables for all entity kinds incorrectly listed `ownerOf` as the generated relation with `ownedBy` as the reverse. The entity emitting the relation is owned by the target, so the outgoing relation is `ownedBy` and the reverse is `ownerOf`. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Fredrik Adelöw --- docs/features/software-catalog/descriptor-format.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/features/software-catalog/descriptor-format.md b/docs/features/software-catalog/descriptor-format.md index 7fdb9056ab..f9ab41e37a 100644 --- a/docs/features/software-catalog/descriptor-format.md +++ b/docs/features/software-catalog/descriptor-format.md @@ -607,7 +607,7 @@ component, but there will always be one ultimate owner. | [`kind`](#apiversion-and-kind-required) | Default [`namespace`](#namespace-optional) | Generated [relation](well-known-relations.md) type | | ------------------------------------------------------ | ------------------------------------------ | ------------------------------------------------------------------------------- | -| [`Group`](#kind-group) (default), [`User`](#kind-user) | Same as this entity, typically `default` | [`ownerOf`, and reverse `ownedBy`](well-known-relations.md#ownedby-and-ownerof) | +| [`Group`](#kind-group) (default), [`User`](#kind-user) | Same as this entity, typically `default` | [`ownedBy`, and reverse `ownerOf`](well-known-relations.md#ownedby-and-ownerof) | ### `spec.system` [optional] @@ -811,7 +811,7 @@ Template, but there will always be one ultimate owner. | [`kind`](#apiversion-and-kind-required) | Default [`namespace`](#namespace-optional) | Generated [relation](well-known-relations.md) type | | ------------------------------------------------------ | ------------------------------------------ | ------------------------------------------------------------------------------- | -| [`Group`](#kind-group) (default), [`User`](#kind-user) | Same as this entity, typically `default` | [`ownerOf`, and reverse `ownedBy`](well-known-relations.md#ownedby-and-ownerof) | +| [`Group`](#kind-group) (default), [`User`](#kind-user) | Same as this entity, typically `default` | [`ownedBy`, and reverse `ownerOf`](well-known-relations.md#ownedby-and-ownerof) | ## Kind: API @@ -921,7 +921,7 @@ one ultimate owner. | [`kind`](#apiversion-and-kind-required) | Default [`namespace`](#namespace-optional) | Generated [relation](well-known-relations.md) type | | ------------------------------------------------------ | ------------------------------------------ | ------------------------------------------------------------------------------- | -| [`Group`](#kind-group) (default), [`User`](#kind-user) | Same as this entity, typically `default` | [`ownerOf`, and reverse `ownedBy`](well-known-relations.md#ownedby-and-ownerof) | +| [`Group`](#kind-group) (default), [`User`](#kind-user) | Same as this entity, typically `default` | [`ownedBy`, and reverse `ownerOf`](well-known-relations.md#ownedby-and-ownerof) | ### `spec.system` [optional] @@ -1164,7 +1164,7 @@ resource, but there will always be one ultimate owner. | [`kind`](#apiversion-and-kind-required) | Default [`namespace`](#namespace-optional) | Generated [relation](well-known-relations.md) type | | ------------------------------------------------------ | ------------------------------------------ | ------------------------------------------------------------------------------- | -| [`Group`](#kind-group) (default), [`User`](#kind-user) | Same as this entity, typically `default` | [`ownerOf`, and reverse `ownedBy`](well-known-relations.md#ownedby-and-ownerof) | +| [`Group`](#kind-group) (default), [`User`](#kind-user) | Same as this entity, typically `default` | [`ownedBy`, and reverse `ownerOf`](well-known-relations.md#ownedby-and-ownerof) | ### `spec.type` [required] @@ -1262,7 +1262,7 @@ but there will always be one ultimate owner. | [`kind`](#apiversion-and-kind-required) | Default [`namespace`](#namespace-optional) | Generated [relation](well-known-relations.md) type | | ------------------------------------------------------ | ------------------------------------------ | ------------------------------------------------------------------------------- | -| [`Group`](#kind-group) (default), [`User`](#kind-user) | Same as this entity, typically `default` | [`ownerOf`, and reverse `ownedBy`](well-known-relations.md#ownedby-and-ownerof) | +| [`Group`](#kind-group) (default), [`User`](#kind-user) | Same as this entity, typically `default` | [`ownedBy`, and reverse `ownerOf`](well-known-relations.md#ownedby-and-ownerof) | ### `spec.domain` [optional] @@ -1334,7 +1334,7 @@ but there will always be one ultimate owner. | [`kind`](#apiversion-and-kind-required) | Default [`namespace`](#namespace-optional) | Generated [relation](well-known-relations.md) type | | ------------------------------------------------------ | ------------------------------------------ | ------------------------------------------------------------------------------- | -| [`Group`](#kind-group) (default), [`User`](#kind-user) | Same as this entity, typically `default` | [`ownerOf`, and reverse `ownedBy`](well-known-relations.md#ownedby-and-ownerof) | +| [`Group`](#kind-group) (default), [`User`](#kind-user) | Same as this entity, typically `default` | [`ownedBy`, and reverse `ownerOf`](well-known-relations.md#ownedby-and-ownerof) | ### `spec.subdomainOf` [optional] From 507c26855add96fd079cbf4f7e69f6b9db963ba5 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 1 Mar 2026 14:01:40 +0100 Subject: [PATCH 20/26] Added elaine-mattos to the Org Member list Signed-off-by: Patrik Oldsberg Made-with: Cursor --- OWNERS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/OWNERS.md b/OWNERS.md index e09a0a24c3..4d535fc4b2 100644 --- a/OWNERS.md +++ b/OWNERS.md @@ -283,6 +283,7 @@ Scope: The Scaffolder frontend and backend plugins, and related tooling. | Carlos Esteban Lopez Jaramillo | VMWare | [luchillo17](https://github.com/luchillo17) | `luchillo17#8777` | | David Tuite | Roadie.io | [dtuite](https://github.com/dtuite) | `David Tuite (roadie.io)#1010` | | Deepankumar Loganathan | | [deepan10](https://github.com/deepan10) | `deepan10` | +| Elaine Mattos | DB Systel | [elaine-mattos](https://github.com/elaine-mattos) | `elaine_mattos` | | Gabriel Dugny | Believe | [GabDug](https://github.com/GabDug) | `GabDug` | | Heikki Hellgren | OP Financial Group | [drodil](https://github.com/drodil) | `deathammer` | | Himanshu Mishra | Harness.io | [OrkoHunter](https://github.com/OrkoHunter) | `OrkoHunter#1520` | From ccc20cf1bc6ad686c8b6f64d14782db367df3e2a Mon Sep 17 00:00:00 2001 From: Stephanie Cao Date: Mon, 2 Mar 2026 04:41:42 -0500 Subject: [PATCH 21/26] feat(scaffolder): Create scaffolder mcp action to dry run scaffolder template (#32914) * dry run action Signed-off-by: Stephanie * add tests Signed-off-by: Stephanie * add changeset Signed-off-by: Stephanie * adjust review comments Signed-off-by: Stephanie * update error handling Signed-off-by: Stephanie * remove unnecessary import Signed-off-by: Stephanie * replace ScaffolderClient with scaffolderServiceRef Signed-off-by: benjdlambert --------- Signed-off-by: Stephanie Signed-off-by: benjdlambert Co-authored-by: benjdlambert --- .changeset/two-lies-leave.md | 5 + .../src/ScaffolderPlugin.ts | 16 +- .../createDryRunTemplateAction.test.ts | 267 ++++++++++++++++++ .../src/actions/createDryRunTemplateAction.ts | 156 ++++++++++ .../scaffolder-backend/src/actions/index.ts | 25 ++ 5 files changed, 468 insertions(+), 1 deletion(-) create mode 100644 .changeset/two-lies-leave.md create mode 100644 plugins/scaffolder-backend/src/actions/createDryRunTemplateAction.test.ts create mode 100644 plugins/scaffolder-backend/src/actions/createDryRunTemplateAction.ts create mode 100644 plugins/scaffolder-backend/src/actions/index.ts diff --git a/.changeset/two-lies-leave.md b/.changeset/two-lies-leave.md new file mode 100644 index 0000000000..2d83758940 --- /dev/null +++ b/.changeset/two-lies-leave.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +create scaffolder MCP action to dry run a provided scaffolder template diff --git a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts index 39bab85c7e..6fdbb3e269 100644 --- a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts +++ b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts @@ -23,6 +23,7 @@ import { catalogServiceRef } from '@backstage/plugin-catalog-node'; import { eventsServiceRef } from '@backstage/plugin-events-node'; import { scaffolderActionsExtensionPoint, + scaffolderServiceRef, TaskBroker, TemplateAction, } from '@backstage/plugin-scaffolder-node'; @@ -59,7 +60,11 @@ import { convertFiltersToRecord, convertGlobalsToRecord, } from './util/templating'; -import { actionsServiceRef } from '@backstage/backend-plugin-api/alpha'; +import { + actionsServiceRef, + actionsRegistryServiceRef, +} from '@backstage/backend-plugin-api/alpha'; +import { createScaffolderActions } from './actions'; /** * Scaffolder plugin @@ -144,6 +149,8 @@ export const scaffolderPlugin = createBackendPlugin({ catalog: catalogServiceRef, events: eventsServiceRef, actionsRegistry: actionsServiceRef, + actionsRegistryService: actionsRegistryServiceRef, + scaffolderService: scaffolderServiceRef, }, async init({ logger, @@ -159,6 +166,8 @@ export const scaffolderPlugin = createBackendPlugin({ events, auditor, actionsRegistry, + actionsRegistryService, + scaffolderService, }) { const log = loggerToWinstonLogger(logger); const integrations = ScmIntegrations.fromConfig(config); @@ -211,6 +220,11 @@ export const scaffolderPlugin = createBackendPlugin({ `Starting scaffolder with the following actions enabled ${actionIds}`, ); + createScaffolderActions({ + actionsRegistry: actionsRegistryService, + scaffolderService, + }); + const router = await createRouter({ logger, config, diff --git a/plugins/scaffolder-backend/src/actions/createDryRunTemplateAction.test.ts b/plugins/scaffolder-backend/src/actions/createDryRunTemplateAction.test.ts new file mode 100644 index 0000000000..cdd69d1541 --- /dev/null +++ b/plugins/scaffolder-backend/src/actions/createDryRunTemplateAction.test.ts @@ -0,0 +1,267 @@ +/* + * Copyright 2026 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 { createDryRunTemplateAction } from './createDryRunTemplateAction'; +import { actionsRegistryServiceMock } from '@backstage/backend-test-utils/alpha'; +import { scaffolderServiceMock } from '@backstage/plugin-scaffolder-node/testUtils'; + +type DryRunTemplateOutput = { + valid: boolean; + message: string; + errors?: string[]; + log?: Array<{ message: string; stepId?: string; status?: string }>; + output?: Record; + steps?: Array<{ id: string; name: string; action: string }>; +}; + +const validTemplateYaml = ` +apiVersion: scaffolder.backstage.io/v1beta3 +kind: Template +metadata: + name: test-template + namespace: default + title: Test Template +spec: + type: service + steps: + - id: step-1 + name: Step One + action: debug:log + input: + message: hello +`; + +const invalidYaml = ` +apiVersion: scaffolder.backstage.io/v1beta3 +kind: Template +metadata: + name: test + invalid: yaml: syntax: error +spec: + type: service + steps: [ +`; + +describe('createDryRunTemplateAction', () => { + const mockScaffolderService = scaffolderServiceMock.mock(); + + beforeEach(() => { + jest.resetAllMocks(); + }); + + it('should return success with logs when dry-run succeeds', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + const dryRunResult = { + log: [ + { + body: { + message: 'Step completed', + stepId: 'step-1', + status: 'completed' as const, + }, + }, + ], + output: { result: 'ok' }, + steps: [{ id: 'step-1', name: 'Step One', action: 'debug:log' }], + directoryContents: [], + }; + + mockScaffolderService.dryRun.mockResolvedValue(dryRunResult); + + createDryRunTemplateAction({ + actionsRegistry: mockActionsRegistry, + scaffolderService: mockScaffolderService, + }); + + const result = await mockActionsRegistry.invoke({ + id: 'test:dry-run-template', + input: { templateYaml: validTemplateYaml }, + }); + + expect(result.output).toEqual({ + valid: true, + message: 'Template validation successful', + log: [ + { + message: 'Step completed', + stepId: 'step-1', + status: 'completed', + }, + ], + output: { result: 'ok' }, + steps: [{ id: 'step-1', name: 'Step One', action: 'debug:log' }], + }); + + expect(mockScaffolderService.dryRun).toHaveBeenCalledWith( + { + template: expect.objectContaining({ + apiVersion: 'scaffolder.backstage.io/v1beta3', + kind: 'Template', + metadata: expect.objectContaining({ + name: 'test-template', + }), + }), + values: {}, + directoryContents: [], + }, + { credentials: expect.anything() }, + ); + }); + + it('should pass values and files to the scaffolder service', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + mockScaffolderService.dryRun.mockResolvedValue({ + log: [], + output: {}, + steps: [], + directoryContents: [], + }); + + createDryRunTemplateAction({ + actionsRegistry: mockActionsRegistry, + scaffolderService: mockScaffolderService, + }); + + const values = { name: 'my-app' }; + const files = [ + { + path: 'README.md', + content: 'hello', + }, + ]; + + await mockActionsRegistry.invoke({ + id: 'test:dry-run-template', + input: { + templateYaml: validTemplateYaml, + values, + files, + }, + }); + + expect(mockScaffolderService.dryRun).toHaveBeenCalledWith( + { + template: expect.any(Object), + values, + directoryContents: [ + { + path: 'README.md', + base64Content: Buffer.from('hello').toString('base64'), + }, + ], + }, + { credentials: expect.anything() }, + ); + }); + + it('should return validation errors when YAML is invalid', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + + createDryRunTemplateAction({ + actionsRegistry: mockActionsRegistry, + scaffolderService: mockScaffolderService, + }); + + const result = await mockActionsRegistry.invoke({ + id: 'test:dry-run-template', + input: { templateYaml: invalidYaml }, + }); + + expect(result.output).toEqual({ + valid: false, + message: 'Failed to parse YAML template', + errors: expect.arrayContaining([ + expect.stringContaining('YAML parsing error'), + ]), + }); + + expect(mockScaffolderService.dryRun).not.toHaveBeenCalled(); + }); + + it('should propagate errors from the scaffolder service', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + + mockScaffolderService.dryRun.mockRejectedValue( + new Error('Authentication error'), + ); + + createDryRunTemplateAction({ + actionsRegistry: mockActionsRegistry, + scaffolderService: mockScaffolderService, + }); + + await expect( + mockActionsRegistry.invoke({ + id: 'test:dry-run-template', + input: { templateYaml: validTemplateYaml }, + }), + ).rejects.toThrow('Authentication error'); + }); + + it('should use default empty values and files when not provided', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + mockScaffolderService.dryRun.mockResolvedValue({ + log: [], + output: {}, + steps: [], + directoryContents: [], + }); + + createDryRunTemplateAction({ + actionsRegistry: mockActionsRegistry, + scaffolderService: mockScaffolderService, + }); + + await mockActionsRegistry.invoke({ + id: 'test:dry-run-template', + input: { templateYaml: validTemplateYaml }, + }); + + expect(mockScaffolderService.dryRun).toHaveBeenCalledWith( + { + template: expect.any(Object), + values: {}, + directoryContents: [], + }, + { credentials: expect.anything() }, + ); + }); + + it('should map log entries from body fields', async () => { + const mockActionsRegistry = actionsRegistryServiceMock(); + mockScaffolderService.dryRun.mockResolvedValue({ + log: [{ body: { message: 'Plain log message' } }], + output: {}, + steps: [], + directoryContents: [], + }); + + createDryRunTemplateAction({ + actionsRegistry: mockActionsRegistry, + scaffolderService: mockScaffolderService, + }); + + const result = await mockActionsRegistry.invoke({ + id: 'test:dry-run-template', + input: { templateYaml: validTemplateYaml }, + }); + + const output = result.output as DryRunTemplateOutput; + expect(output.valid).toBe(true); + expect(output.log).toEqual([ + { message: 'Plain log message', stepId: undefined, status: undefined }, + ]); + }); +}); diff --git a/plugins/scaffolder-backend/src/actions/createDryRunTemplateAction.ts b/plugins/scaffolder-backend/src/actions/createDryRunTemplateAction.ts new file mode 100644 index 0000000000..a96e52fb4d --- /dev/null +++ b/plugins/scaffolder-backend/src/actions/createDryRunTemplateAction.ts @@ -0,0 +1,156 @@ +/* + * Copyright 2026 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 { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha'; +import { ScaffolderService } from '@backstage/plugin-scaffolder-node'; +import { JsonObject } from '@backstage/types'; +import yaml from 'yaml'; + +const MAX_CONTENT_SIZE = 64 * 1024; + +function base64EncodeContent(content: string): string { + if (content.length > MAX_CONTENT_SIZE) { + return Buffer.from('', 'utf8').toString('base64'); + } + return Buffer.from(content, 'utf8').toString('base64'); +} + +export const createDryRunTemplateAction = ({ + actionsRegistry, + scaffolderService, +}: { + actionsRegistry: ActionsRegistryService; + scaffolderService: ScaffolderService; +}) => { + actionsRegistry.register({ + name: 'dry-run-template', + title: 'Dry Run Scaffolder Template', + attributes: { + destructive: false, + readOnly: true, + idempotent: true, + }, + description: + 'Dry-runs a scaffolder template to validate it without making changes. Returns success with execution logs, or errors for validation failures.', + schema: { + input: z => + z.object({ + templateYaml: z + .string() + .describe( + 'The YAML content of the scaffolder template to validate', + ), + values: z + .record(z.unknown()) + .optional() + .describe('Input values for template parameters'), + files: z + .array( + z.object({ + path: z + .string() + .describe('File path relative to template root'), + content: z.string().describe('File content'), + }), + ) + .optional() + .describe('Files required for running the template'), + }), + output: z => + z.object({ + valid: z.boolean().describe('Whether the template is valid'), + message: z + .string() + .describe('Success message or validation error details'), + errors: z + .array(z.string()) + .optional() + .describe('List of validation errors'), + log: z + .array( + z.object({ + message: z.string(), + stepId: z.string().optional(), + status: z.string().optional(), + }), + ) + .optional() + .describe('Execution log from dry-run'), + output: z + .record(z.unknown()) + .optional() + .describe('Template output values'), + steps: z + .array( + z.object({ + id: z.string(), + name: z.string(), + action: z.string(), + }), + ) + .optional() + .describe('Parsed template steps'), + }), + }, + action: async ({ input, credentials }) => { + const { templateYaml, values = {}, files = [] } = input; + + let template; + try { + template = yaml.parse(templateYaml); + } catch (parseError) { + const yamlError = parseError as yaml.YAMLParseError; + return { + output: { + valid: false, + message: 'Failed to parse YAML template', + errors: [ + `YAML parsing error: ${yamlError.message}`, + yamlError.linePos + ? `At line ${yamlError.linePos[0].line}, column ${yamlError.linePos[0].col}` + : '', + ].filter(Boolean), + }, + }; + } + + const result = await scaffolderService.dryRun( + { + template, + values: values as JsonObject, + directoryContents: files.map(file => ({ + path: file.path, + base64Content: base64EncodeContent(file.content), + })), + }, + { credentials }, + ); + + return { + output: { + valid: true, + message: 'Template validation successful', + log: result.log?.map(entry => ({ + message: entry.body.message, + stepId: entry.body.stepId, + status: entry.body.status, + })), + output: result.output, + steps: result.steps, + }, + }; + }, + }); +}; diff --git a/plugins/scaffolder-backend/src/actions/index.ts b/plugins/scaffolder-backend/src/actions/index.ts new file mode 100644 index 0000000000..8539ae5b78 --- /dev/null +++ b/plugins/scaffolder-backend/src/actions/index.ts @@ -0,0 +1,25 @@ +/* + * Copyright 2026 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 { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha'; +import { ScaffolderService } from '@backstage/plugin-scaffolder-node'; +import { createDryRunTemplateAction } from './createDryRunTemplateAction'; + +export const createScaffolderActions = (options: { + actionsRegistry: ActionsRegistryService; + scaffolderService: ScaffolderService; +}) => { + createDryRunTemplateAction(options); +}; From 426edbef9ce836f1f891c479ec32dab93f015c7c Mon Sep 17 00:00:00 2001 From: Johan Persson Date: Mon, 2 Mar 2026 11:28:06 +0100 Subject: [PATCH 22/26] fix(repo-tools): allow excess arguments for generate-catalog-info command Re-add `.allowExcessArguments(true)` which was dropped during conflict resolution in the Commander v14 upgrade (PR #32583). lint-staged passes staged file paths as extra arguments when invoking `generate-catalog-info` via the pre-commit hook, causing Commander v14 to reject them with "too many arguments". Signed-off-by: Johan Persson --- .changeset/bright-items-see.md | 5 +++++ packages/repo-tools/src/commands/index.ts | 1 + 2 files changed, 6 insertions(+) create mode 100644 .changeset/bright-items-see.md diff --git a/.changeset/bright-items-see.md b/.changeset/bright-items-see.md new file mode 100644 index 0000000000..ea3ba17cdf --- /dev/null +++ b/.changeset/bright-items-see.md @@ -0,0 +1,5 @@ +--- +'@backstage/repo-tools': patch +--- + +Fixed `generate-catalog-info` command failing with "too many arguments" when invoked by lint-staged via the pre-commit hook. diff --git a/packages/repo-tools/src/commands/index.ts b/packages/repo-tools/src/commands/index.ts index dab7d6df0d..371d0609ff 100644 --- a/packages/repo-tools/src/commands/index.ts +++ b/packages/repo-tools/src/commands/index.ts @@ -226,6 +226,7 @@ export function registerCommands(program: Command) { 'CI run checks that there are no changes to catalog-info.yaml files', ) .description('Create or fix info yaml files for all backstage packages') + .allowExcessArguments(true) .action( lazy( () => import('./generate-catalog-info/generate-catalog-info'), From da54fd24ef3df1d8e33b19e757c294d2211dc172 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 2 Mar 2026 12:43:44 +0000 Subject: [PATCH 23/26] Update tokens.css Signed-off-by: Charles de Dreuille --- packages/ui/src/css/tokens.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ui/src/css/tokens.css b/packages/ui/src/css/tokens.css index 3d5deac4cc..166548db0a 100644 --- a/packages/ui/src/css/tokens.css +++ b/packages/ui/src/css/tokens.css @@ -80,8 +80,8 @@ --bui-bg-app: #f8f8f8; --bui-bg-neutral-1: #fff; - --bui-bg-neutral-1-hover: oklch(0% 0 0 / 12%); - --bui-bg-neutral-1-pressed: oklch(0% 0 0 / 16%); + --bui-bg-neutral-1-hover: oklch(0% 0 0 / 6%); + --bui-bg-neutral-1-pressed: oklch(0% 0 0 / 12%); --bui-bg-neutral-1-disabled: oklch(0% 0 0 / 6%); --bui-bg-neutral-2: oklch(0% 0 0 / 6%); From 58224d347645baf7edccbcb1a91ef267c57acf55 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 2 Mar 2026 12:52:54 +0000 Subject: [PATCH 24/26] Create bumpy-colts-teach.md Signed-off-by: Charles de Dreuille --- .changeset/bumpy-colts-teach.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/bumpy-colts-teach.md diff --git a/.changeset/bumpy-colts-teach.md b/.changeset/bumpy-colts-teach.md new file mode 100644 index 0000000000..e3457127ce --- /dev/null +++ b/.changeset/bumpy-colts-teach.md @@ -0,0 +1,5 @@ +--- +'@backstage/ui': patch +--- + +Fixed neutral-1 hover & pressed state in light mode. From d4fa5b4ee091e8f92317c3fe7ee3dc45a80beff9 Mon Sep 17 00:00:00 2001 From: Johan Persson Date: Fri, 27 Feb 2026 10:44:04 +0100 Subject: [PATCH 25/26] fix(ui): strip query params from tab href before active-state matching Tab matchStrategy ('exact' and 'prefix') compared the raw tab href against location.pathname, which never includes query params. This meant tabs with query params in their href could never be matched as active. Extract an hrefPathname helper that strips query params and hash fragments, and use it in both isTabActive and the segment count computation. Signed-off-by: Johan Persson --- .changeset/fix-tab-match-query-params.md | 7 +++ .../ui/src/components/Tabs/Tabs.stories.tsx | 45 +++++++++++++++++++ packages/ui/src/components/Tabs/Tabs.tsx | 16 +++++-- 3 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 .changeset/fix-tab-match-query-params.md diff --git a/.changeset/fix-tab-match-query-params.md b/.changeset/fix-tab-match-query-params.md new file mode 100644 index 0000000000..6e01a202f5 --- /dev/null +++ b/.changeset/fix-tab-match-query-params.md @@ -0,0 +1,7 @@ +--- +'@backstage/ui': patch +--- + +Fixed tab `matchStrategy` matching to ignore query parameters and hash fragments in tab `href` values. Previously, tabs with query params in their `href` (e.g., `/page?group=foo`) would never show as active since matching compared the full `href` string against `location.pathname` which never includes query params. + +**Affected components:** Tabs, PluginHeader diff --git a/packages/ui/src/components/Tabs/Tabs.stories.tsx b/packages/ui/src/components/Tabs/Tabs.stories.tsx index 2a02bedc8c..fcc919f294 100644 --- a/packages/ui/src/components/Tabs/Tabs.stories.tsx +++ b/packages/ui/src/components/Tabs/Tabs.stories.tsx @@ -454,6 +454,51 @@ export const RootPathMatching = meta.story({ ), }); +export const HrefWithQueryParams = meta.story({ + args: { + children: '', + }, + render: () => ( + + + + + Dashboard + + + Alerts + + + + + + Current URL: /cost-insights/dashboard?group=bar + + + Tab hrefs include query params (e.g., ?group=foo) but the current URL + has different query params (?group=bar). + + + • "Dashboard" tab: IS active — matching ignores query params and + compares only the pathname. + + + • "Alerts" tab: NOT active — pathname /cost-insights/alerts doesn't + match /cost-insights/dashboard. + + + + ), +}); + export const AutoSelectionOfTabs = meta.story({ args: { children: '', diff --git a/packages/ui/src/components/Tabs/Tabs.tsx b/packages/ui/src/components/Tabs/Tabs.tsx index cf6263b9a4..d625d2abf0 100644 --- a/packages/ui/src/components/Tabs/Tabs.tsx +++ b/packages/ui/src/components/Tabs/Tabs.tsx @@ -79,6 +79,12 @@ const TabSelectionContext = createContext( null, ); +/** + * Strips query params and hash from a href, leaving only the pathname. + * Tab matching always compares against location.pathname which never includes them. + */ +const hrefPathname = (href: string) => href.split('?')[0].split('#')[0]; + /** * Utility function to determine if a tab should be active based on the matching strategy. * This follows the pattern used in WorkaroundNavLink from the sidebar. @@ -88,18 +94,20 @@ const isTabActive = ( currentPathname: string, matchStrategy: 'exact' | 'prefix', ): boolean => { + const pathname = hrefPathname(tabHref); + if (matchStrategy === 'exact') { - return tabHref === currentPathname; + return pathname === currentPathname; } // Prefix matching - similar to WorkaroundNavLink behavior - if (tabHref === currentPathname) { + if (pathname === currentPathname) { return true; } // Check if current path starts with tab href followed by a slash // This prevents /foo matching /foobar - return currentPathname.startsWith(`${tabHref}/`); + return currentPathname.startsWith(`${pathname}/`); }; /** @@ -304,7 +312,7 @@ function RoutedTabEffects({ // Register as active tab when URL matches (for tab selection) const isActive = isTabActive(href, location.pathname, matchStrategy); - const segmentCount = href.split('/').filter(Boolean).length; + const segmentCount = hrefPathname(href).split('/').filter(Boolean).length; useEffect(() => { if (isActive && selectionCtx) { From a0e4d38f4bcfbbee277d5585f867e6860cf44141 Mon Sep 17 00:00:00 2001 From: Johan Persson Date: Fri, 27 Feb 2026 10:58:24 +0100 Subject: [PATCH 26/26] fix(ui): use Text as="p" in Tabs stories for proper line breaks Story description text was rendering inline without line breaks between elements. Add as="p" to Text components so each renders as a block-level paragraph. Signed-off-by: Johan Persson --- .../ui/src/components/Tabs/Tabs.stories.tsx | 74 ++++++++++--------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/packages/ui/src/components/Tabs/Tabs.stories.tsx b/packages/ui/src/components/Tabs/Tabs.stories.tsx index fcc919f294..55cdf7c446 100644 --- a/packages/ui/src/components/Tabs/Tabs.stories.tsx +++ b/packages/ui/src/components/Tabs/Tabs.stories.tsx @@ -125,10 +125,10 @@ export const WithMockedURLTab3 = meta.story({ - + Current URL is mocked to be: /tab3 - + Notice how the "Tab 3 With long title" tab is selected (highlighted) because it matches the current path. @@ -157,14 +157,14 @@ export const WithMockedURLNoMatch = meta.story({ - + Current URL is mocked to be: /some-other-page - + No tab is selected because the current path doesn't match any tab's href. - + Tabs without href (like "Tab 1", "Tab 2", "Tab 3 With long title") fall back to React Aria's internal state. @@ -195,14 +195,14 @@ export const ExactMatchingDefault = meta.story({ - + Current URL: /mentorship/events - + Using default exact matching, only the "Events" tab is active because it exactly matches the URL. - + The "Mentorship" tab is NOT active even though the URL contains "/mentorship". @@ -231,18 +231,18 @@ export const PrefixMatchingForNestedRoutes = meta.story({ - + Current URL: /mentorship/events - + The "Mentorship" tab uses prefix matching and IS active because "/mentorship/events" starts with "/mentorship". - + The "Events" tab uses exact matching and is also active because it exactly matches. - + The "Catalog" tab uses prefix matching but is NOT active because the URL doesn't start with "/catalog". @@ -313,22 +313,22 @@ export const MixedMatchingStrategies = meta.story({ - + Current URL: /dashboard/analytics/reports - + • "Overview" tab: exact matching, NOT active (doesn't exactly match "/dashboard") - + • "Analytics" tab: prefix matching, IS active (URL starts with "/dashboard/analytics") - + • "Settings" tab: prefix matching, NOT active (URL doesn't start with "/dashboard/settings") - + • "Help" tab: exact matching, NOT active (doesn't exactly match "/help") @@ -357,20 +357,20 @@ export const PrefixMatchingEdgeCases = meta.story({ - + Current URL: /foobar - + • "Foo" tab (prefix): NOT active - prevents "/foo" from matching "/foobar" - + • "Foobar" tab (exact): IS active - exactly matches "/foobar" - + • "Foo (exact)" tab: NOT active - doesn't exactly match "/foobar" - + This shows that prefix matching properly requires a "/" separator to prevent false matches. @@ -399,20 +399,20 @@ export const PrefixMatchingWithSlash = meta.story({ - + Current URL: /foo/bar - + • "Foo" tab (prefix): IS active - "/foo/bar" starts with "/foo/" - + • "Foobar" tab (exact): NOT active - doesn't exactly match "/foobar" - + • "Bar" tab (prefix): NOT active - "/foo/bar" doesn't start with "/bar" - + This demonstrates proper prefix matching with the "/" separator. @@ -440,12 +440,14 @@ export const RootPathMatching = meta.story({ - + Current URL: / - • "Home" tab (exact): IS active - exactly matches "/" - • "Home (prefix)" tab: IS active - "/" matches "/" - + + • "Home" tab (exact): IS active - exactly matches "/" + + • "Home (prefix)" tab: IS active - "/" matches "/" + • "Catalog" tab (prefix): NOT active - "/" doesn't start with "/catalog" @@ -533,10 +535,12 @@ export const AutoSelectionOfTabs = meta.story({ {/* With hrefs */} - - {' '} - Case 2: With hrefs By default no selection is shown - because the URL doesn't match any tab's href.{' '} + + Case 2: With hrefs + + + By default no selection is shown because the URL doesn't match any + tab's href.