From ac3560b42d1306f16b8fc4e1fdd9c9f9c83a59f9 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Thu, 26 Nov 2020 18:16:53 +0100 Subject: [PATCH 01/98] Remove implementsApis This was deprecated in #3449. This should not be merged sooner then Dec 14th, 2020! --- .changeset/thirty-fans-hammer.md | 7 +++++++ .../software-catalog/descriptor-format.md | 15 ------------- .../components/petstore-component.yaml | 2 +- .../src/kinds/ComponentEntityV1alpha1.test.ts | 21 ------------------- .../src/kinds/ComponentEntityV1alpha1.ts | 7 ------- .../BuiltinKindsEntityProcessor.test.ts | 19 +---------------- .../processors/BuiltinKindsEntityProcessor.ts | 6 ------ 7 files changed, 9 insertions(+), 68 deletions(-) create mode 100644 .changeset/thirty-fans-hammer.md diff --git a/.changeset/thirty-fans-hammer.md b/.changeset/thirty-fans-hammer.md new file mode 100644 index 0000000000..45fb398f8c --- /dev/null +++ b/.changeset/thirty-fans-hammer.md @@ -0,0 +1,7 @@ +--- +'@backstage/catalog-model': minor +'@backstage/plugin-catalog-backend': minor +--- + +Remove `implementsApis` from `Component` entities. Deprecation happened in [#3449](https://github.com/backstage/backstage/pull/3449). +Use `providesApis` instead. diff --git a/docs/features/software-catalog/descriptor-format.md b/docs/features/software-catalog/descriptor-format.md index 19c5c74f68..3702f972d3 100644 --- a/docs/features/software-catalog/descriptor-format.md +++ b/docs/features/software-catalog/descriptor-format.md @@ -444,21 +444,6 @@ Apart from being a string, the software catalog leaves the format of this field open to implementers to choose. Most commonly, it is set to the ID or email of a group of people in an organizational structure. -### `spec.implementsApis` [optional] - -**NOTE**: This field was marked for deprecation on Nov 25nd, 2020. It will be -removed entirely from the model on Dec 14th, 2020 in the repository and will not -be present in released packages following the next release after that. Please -update your code to not consume this field before the removal date. - -Links APIs that are implemented by the component, e.g. `artist-api`. This field -is optional. - -The software catalog expects a list of one or more strings that references the -names of other entities of the `kind` `API`. - -This field has the same behavior as `spec.providesApis`. - ### `spec.providesApis` [optional] Links APIs that are provided by the component, e.g. `artist-api`. This field is diff --git a/packages/catalog-model/examples/components/petstore-component.yaml b/packages/catalog-model/examples/components/petstore-component.yaml index e6dd56c274..acbb2f82b0 100644 --- a/packages/catalog-model/examples/components/petstore-component.yaml +++ b/packages/catalog-model/examples/components/petstore-component.yaml @@ -7,7 +7,7 @@ spec: type: service lifecycle: experimental owner: team-c - implementsApis: + providesApis: - petstore - streetlights - hello-world diff --git a/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts b/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts index 8eec63daac..030c99c151 100644 --- a/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts +++ b/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts @@ -33,7 +33,6 @@ describe('ComponentV1alpha1Validator', () => { type: 'service', lifecycle: 'production', owner: 'me', - implementsApis: ['api-0'], providesApis: ['api-0'], consumesApis: ['api-0'], }, @@ -104,26 +103,6 @@ describe('ComponentV1alpha1Validator', () => { await expect(validator.check(entity)).rejects.toThrow(/owner/); }); - it('accepts missing implementsApis', async () => { - delete (entity as any).spec.implementsApis; - await expect(validator.check(entity)).resolves.toBe(true); - }); - - it('rejects empty implementsApis', async () => { - (entity as any).spec.implementsApis = ['']; - await expect(validator.check(entity)).rejects.toThrow(/implementsApis/); - }); - - it('rejects undefined implementsApis', async () => { - (entity as any).spec.implementsApis = [undefined]; - await expect(validator.check(entity)).rejects.toThrow(/implementsApis/); - }); - - it('accepts no implementsApis', async () => { - (entity as any).spec.implementsApis = []; - await expect(validator.check(entity)).resolves.toBe(true); - }); - it('accepts missing providesApis', async () => { delete (entity as any).spec.providesApis; await expect(validator.check(entity)).resolves.toBe(true); diff --git a/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.ts b/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.ts index 680674f16e..e511dcb24a 100644 --- a/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.ts +++ b/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.ts @@ -29,7 +29,6 @@ const schema = yup.object>({ type: yup.string().required().min(1), lifecycle: yup.string().required().min(1), owner: yup.string().required().min(1), - implementsApis: yup.array(yup.string().required()).notRequired(), providesApis: yup.array(yup.string().required()).notRequired(), consumesApis: yup.array(yup.string().required()).notRequired(), }) @@ -43,12 +42,6 @@ export interface ComponentEntityV1alpha1 extends Entity { type: string; lifecycle: string; owner: string; - /** - * @deprecated This field will disappear on Dec 14th, 2020. Please remove - * any consuming code. The new field providesApis provides the - * same functionality like before. - */ - implementsApis?: string[]; providesApis?: string[]; consumesApis?: string[]; }; diff --git a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts index e456dfd7a2..ca5328230e 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts @@ -67,7 +67,6 @@ describe('BuiltinKindsEntityProcessor', () => { type: 'service', owner: 'o', lifecycle: 'l', - implementsApis: ['a'], providesApis: ['b'], consumesApis: ['c'], }, @@ -75,7 +74,7 @@ describe('BuiltinKindsEntityProcessor', () => { await processor.postProcessEntity(entity, location, emit); - expect(emit).toBeCalledTimes(8); + expect(emit).toBeCalledTimes(6); expect(emit).toBeCalledWith({ type: 'relation', relation: { @@ -92,22 +91,6 @@ describe('BuiltinKindsEntityProcessor', () => { target: { kind: 'Group', namespace: 'default', name: 'o' }, }, }); - expect(emit).toBeCalledWith({ - type: 'relation', - relation: { - source: { kind: 'API', namespace: 'default', name: 'a' }, - type: 'apiProvidedBy', - target: { kind: 'Component', namespace: 'default', name: 'n' }, - }, - }); - expect(emit).toBeCalledWith({ - type: 'relation', - relation: { - source: { kind: 'Component', namespace: 'default', name: 'n' }, - type: 'providesApi', - target: { kind: 'API', namespace: 'default', name: 'a' }, - }, - }); expect(emit).toBeCalledWith({ type: 'relation', relation: { diff --git a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts index 62b496dd65..c6c7435216 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts @@ -134,12 +134,6 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor { RELATION_OWNED_BY, RELATION_OWNER_OF, ); - doEmit( - component.spec.implementsApis, - { defaultKind: 'API', defaultNamespace: selfRef.namespace }, - RELATION_PROVIDES_API, - RELATION_API_PROVIDED_BY, - ); doEmit( component.spec.providesApis, { defaultKind: 'API', defaultNamespace: selfRef.namespace }, From f63f1aff888ef5b29076b0dac357448dc51b9bd1 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 10 Dec 2020 14:44:32 -0500 Subject: [PATCH 02/98] Add body content to catalog import PR --- .../catalog-import/src/api/CatalogImportClient.ts | 15 ++++++++++++++- plugins/catalog-import/src/plugin.ts | 11 ++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/plugins/catalog-import/src/api/CatalogImportClient.ts b/plugins/catalog-import/src/api/CatalogImportClient.ts index 4ac015ffbf..029f7f7fb5 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.ts @@ -15,7 +15,7 @@ */ import { Octokit } from '@octokit/rest'; -import { DiscoveryApi, OAuthApi } from '@backstage/core'; +import { DiscoveryApi, OAuthApi, ConfigApi } from '@backstage/core'; import { CatalogImportApi } from './CatalogImportApi'; import { AnalyzeLocationResponse } from '@backstage/plugin-catalog-backend'; import { PartialEntity } from '../util/types'; @@ -24,13 +24,16 @@ import { GitHubIntegrationConfig } from '@backstage/integration'; export class CatalogImportClient implements CatalogImportApi { private readonly discoveryApi: DiscoveryApi; private readonly githubAuthApi: OAuthApi; + private readonly configApi: ConfigApi; constructor(options: { discoveryApi: DiscoveryApi; githubAuthApi: OAuthApi; + configApi: ConfigApi; }) { this.discoveryApi = options.discoveryApi; this.githubAuthApi = options.githubAuthApi; + this.configApi = options.configApi; } async generateEntityDefinitions({ @@ -164,12 +167,22 @@ export class CatalogImportClient implements CatalogImportApi { ); }); + const appTitle = this.configApi.getString('app.title'); + const appBaseUrl = this.configApi.getString('app.baseUrl'); + + const prBody = `This pull request adds a **Backstage entity metadata file** \ +to this repository so that the component can be added to the \ +${appTitle} software catalog.\n\nAfter you merge this pull request, \ +you can [return to Backstage](${appBaseUrl}/catalog-import) \ +to register the component with the direct URL to the ${fileName} file.`; + const pullRequestResponse = await octo.pulls .create({ owner, repo, title: `Add ${fileName} config file`, head: branchName, + body: prBody, base: repoData.data.default_branch, }) .catch(e => { diff --git a/plugins/catalog-import/src/plugin.ts b/plugins/catalog-import/src/plugin.ts index 3ce4918553..829be22045 100644 --- a/plugins/catalog-import/src/plugin.ts +++ b/plugins/catalog-import/src/plugin.ts @@ -20,6 +20,7 @@ import { createRouteRef, discoveryApiRef, githubAuthApiRef, + configApiRef, } from '@backstage/core'; import { catalogImportApiRef } from './api/CatalogImportApi'; import { CatalogImportClient } from './api/CatalogImportClient'; @@ -34,9 +35,13 @@ export const plugin = createPlugin({ apis: [ createApiFactory({ api: catalogImportApiRef, - deps: { discoveryApi: discoveryApiRef, githubAuthApi: githubAuthApiRef }, - factory: ({ discoveryApi, githubAuthApi }) => - new CatalogImportClient({ discoveryApi, githubAuthApi }), + deps: { + discoveryApi: discoveryApiRef, + githubAuthApi: githubAuthApiRef, + configApi: configApiRef, + }, + factory: ({ discoveryApi, githubAuthApi, configApi }) => + new CatalogImportClient({ discoveryApi, githubAuthApi, configApi }), }), ], }); From f3e75508d66f6dd55b218d683776ee0ed8d55d16 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 10 Dec 2020 14:45:55 -0500 Subject: [PATCH 03/98] Add changeset --- .changeset/loud-icons-itch.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/loud-icons-itch.md diff --git a/.changeset/loud-icons-itch.md b/.changeset/loud-icons-itch.md new file mode 100644 index 0000000000..c5741c5d0b --- /dev/null +++ b/.changeset/loud-icons-itch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +Add description to Pull Request when registering a new component From 803e6df7d122cf63c9320019818935160539ba2f Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 10 Dec 2020 14:50:29 -0500 Subject: [PATCH 04/98] Wrap filename in code fence --- plugins/catalog-import/src/api/CatalogImportClient.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-import/src/api/CatalogImportClient.ts b/plugins/catalog-import/src/api/CatalogImportClient.ts index 029f7f7fb5..185221ba93 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.ts @@ -174,7 +174,7 @@ export class CatalogImportClient implements CatalogImportApi { to this repository so that the component can be added to the \ ${appTitle} software catalog.\n\nAfter you merge this pull request, \ you can [return to Backstage](${appBaseUrl}/catalog-import) \ -to register the component with the direct URL to the ${fileName} file.`; +to register the component with the direct URL to the \`${fileName}\` file.`; const pullRequestResponse = await octo.pulls .create({ From 483c98bbf0840d9993c06734cd9e93f7e384310f Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 10 Dec 2020 14:55:24 -0500 Subject: [PATCH 05/98] Allow for optional string --- plugins/catalog-import/src/api/CatalogImportClient.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/catalog-import/src/api/CatalogImportClient.ts b/plugins/catalog-import/src/api/CatalogImportClient.ts index 185221ba93..d9cf4f1327 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.ts @@ -167,7 +167,8 @@ export class CatalogImportClient implements CatalogImportApi { ); }); - const appTitle = this.configApi.getString('app.title'); + const appTitle = + this.configApi.getOptionalString('app.title') ?? 'Backstage'; const appBaseUrl = this.configApi.getString('app.baseUrl'); const prBody = `This pull request adds a **Backstage entity metadata file** \ From dbd1d73653821bd0bdac872cc977567b35831788 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 10 Dec 2020 15:10:28 -0500 Subject: [PATCH 06/98] Update PR wording --- plugins/catalog-import/src/api/CatalogImportClient.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/catalog-import/src/api/CatalogImportClient.ts b/plugins/catalog-import/src/api/CatalogImportClient.ts index d9cf4f1327..0e3ea2e1d6 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.ts @@ -173,9 +173,9 @@ export class CatalogImportClient implements CatalogImportApi { const prBody = `This pull request adds a **Backstage entity metadata file** \ to this repository so that the component can be added to the \ -${appTitle} software catalog.\n\nAfter you merge this pull request, \ -you can [return to Backstage](${appBaseUrl}/catalog-import) \ -to register the component with the direct URL to the \`${fileName}\` file.`; +[${appTitle} software catalog](${appBaseUrl}).\n\nAfter this pull request is merged, \ +the component will become available.\n\nFor more information, read an \ +[overview of the Backstage software catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview).`; const pullRequestResponse = await octo.pulls .create({ From c7507fe2404952e4c6e15e115fdd3955125316ea Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 13 Dec 2020 13:15:01 +0100 Subject: [PATCH 07/98] docs: initial cli docs skeleton + commands extraction --- docs/cli/commands.md | 312 +++++++++++++++++++++++++++++++++++++ docs/cli/index.md | 31 ++++ docs/cli/under-the-hood.md | 7 + microsite/sidebars.json | 5 + 4 files changed, 355 insertions(+) create mode 100644 docs/cli/commands.md create mode 100644 docs/cli/index.md create mode 100644 docs/cli/under-the-hood.md diff --git a/docs/cli/commands.md b/docs/cli/commands.md new file mode 100644 index 0000000000..f10186a829 --- /dev/null +++ b/docs/cli/commands.md @@ -0,0 +1,312 @@ +--- +id: commands +title: Commands +description: Descriptions of all commands available in the CLI. +--- + +## Summary + +```text +app:build [options] Build an app for a production release +app:diff [options] Diff an existing app with the creation template +app:serve [options] Serve an app for local development + +backend:build Build a backend plugin +backend:build-image [options] Bundles the package into a docker image. All extra args are forwarded to `docker image build`. +backend:dev [options] Start local development server with HMR for the backend + +plugin:build Build a plugin +plugin:diff [options] Diff an existing plugin with the creation template +plugin:serve [options] Serves the dev/ folder of a plugin + +build [options] Build a package for publishing +build-workspace Builds a temporary dist workspace from the provided packages +lint [options] Lint a package +test Run tests, forwarding args to Jest, defaulting to watch mode +clean Delete cache directories + +create-plugin [options] Creates a new plugin in the current repository +remove-plugin Removes plugin in the current repository + +config:print [options] Print the app configuration for the current package +config:check [options] Validate that the given configuration loads and matches schema + +versions:bump Bump Backstage packages to the latest versions +versions:check [options] Check Backstage package versioning + +prepack Prepares a package for packaging before publishing +postpack Restores the changes made by the prepack command + +help [command] display help for command +``` + +## app:build + +Build an app for a production release + +```text +Usage: backstage-cli app:build [options] + +Options: + --stats Write bundle stats to output directory + --config Config files to load instead of app-config.yaml (default: []) + -h, --help display help for command +``` + +## app:diff + +Diff an existing app with the creation template + +```text +Usage: backstage-cli app:diff [options] + +Options: + --check Fail if changes are required + --yes Apply all changes + -h, --help display help for command +``` + +## app:serve + +Serve an app for local development + +```text +Usage: backstage-cli app:serve [options] + +Options: + --check Enable type checking and linting + --config Config files to load instead of app-config.yaml (default: []) + -h, --help display help for command +``` + +## backend:build + +Build a backend plugin + +```text +Usage: backstage-cli backend:build [options] + +Options: + -h, --help display help for command +``` + +## backend:build-image + +Bundles the package into a docker image. All extra args are forwarded to +`docker image build`. + +```text +Usage: backstage-cli backend:build-image [options] + +Options: + --build Build packages before packing them into the image + --backstage-cli-help display help for command +``` + +## backend:dev + +Start local development server with HMR for the backend + +```text +Usage: backstage-cli backend:dev [options] + +Options: + --check Enable type checking and linting + --inspect Enable debugger + --config Config files to load instead of app-config.yaml (default: []) + -h, --help display help for command +``` + +## create-plugin + +Creates a new plugin in the current repository + +```text +Usage: backstage-cli create-plugin [options] + +Options: + --backend Create plugin with the backend dependencies as default + --scope npm scope + --npm-registry npm registry URL + --no-private Public npm package + -h, --help display help for command +``` + +## remove-plugin + +Removes plugin in the current repository + +```text +Usage: backstage-cli remove-plugin [options] + +Options: + -h, --help display help for command +``` + +## plugin:build + +Build a plugin + +```text +Usage: backstage-cli plugin:build [options] + +Options: + -h, --help display help for command +``` + +## plugin:serve + +Serves the dev/ folder of a plugin + +```text +Usage: backstage-cli plugin:serve [options] + +Options: + --check Enable type checking and linting + --config Config files to load instead of app-config.yaml (default: []) + -h, --help display help for command +``` + +## plugin:diff + +Diff an existing plugin with the creation template + +```text +Usage: backstage-cli plugin:diff [options] + +Options: + --check Fail if changes are required + --yes Apply all changes + -h, --help display help for command +``` + +## build + +Build a package for publishing + +```text +Usage: backstage-cli build [options] + +Options: + --outputs List of formats to output [types,cjs,esm] + -h, --help display help for command +``` + +## lint + +Lint a package + +```text +Usage: backstage-cli lint [options] + +Options: + --format Lint report output format (default: "eslint-formatter-friendly") + --fix Attempt to automatically fix violations + -h, --help display help for command +``` + +## test + +Run tests, forwarding args to Jest, defaulting to watch mode + +```text +Usage: backstage-cli test [options] + +Options: + --backstage-cli-help display help for command +``` + +## config:print + +Print the app configuration for the current package + +```text +Usage: backstage-cli config:print [options] + +Options: + --package Only load config schema that applies to the given package + --frontend Print only the frontend configuration + --with-secrets Include secrets in the printed configuration + --format Format to print the configuration in, either json or yaml [yaml] + --config Config files to load instead of app-config.yaml (default: []) + -h, --help display help for command +``` + +## config:check + +Validate that the given configuration loads and matches schema + +```text +Usage: backstage-cli config:check [options] + +Options: + --package Only load config schema that applies to the given package + --config Config files to load instead of app-config.yaml (default: []) + -h, --help display help for command +``` + +## versions:bump + +Bump Backstage packages to the latest versions + +```text +Usage: backstage-cli versions:bump [options] + +Options: + -h, --help display help for command +``` + +## versions:check + +Check Backstage package versioning + +```text +Usage: backstage-cli versions:check [options] + +Options: + --fix Fix any auto-fixable versioning problems + -h, --help display help for command +``` + +## prepack + +Prepares a package for packaging before publishing + +```text +Usage: backstage-cli prepack [options] + +Options: + -h, --help display help for command +``` + +## postpack + +Restores the changes made by the prepack command + +```text +Usage: backstage-cli postpack [options] + +Options: + -h, --help display help for command +``` + +## clean + +Delete cache directories + +```text +Usage: backstage-cli clean [options] + +Options: + -h, --help display help for command +``` + +## build-workspace + +Builds a temporary dist workspace from the provided packages + +```text +Usage: backstage-cli build-workspace [options] + +Options: +``` diff --git a/docs/cli/index.md b/docs/cli/index.md new file mode 100644 index 0000000000..9532e05993 --- /dev/null +++ b/docs/cli/index.md @@ -0,0 +1,31 @@ +--- +id: index +title: Overview +description: Overview of the Backstage CLI +--- + +## Summary + +Backstage ships its own CLI tooling + +Tooling both for bundling deployment artifacts, as well as building individual +packages for publishing. + +Under the hook we use [webpack](https://webpack.js.org/) for bundling, +[rollup](https://rollupjs.org/) for building packages, +[jest](https://jestjs.io/) for testing, and [eslint](https://eslint.org/) for +linting. + +## Glossary + +- **Package** - A package in the Node.js ecosystem, often published to a package + registry such as [NPM](https://www.npmjs.com/). +- **Monorepo** - A project layout that consists of multiple packages within a + single project, where packages are able to have local dependencies on each + other. Often enabled through tooling such as [lerna](https://lerna.js.org/) + and [yarn workspaces](https://classic.yarnpkg.com/en/docs/workspaces/) +- **Local Package** - One of the packages within a monorepo. These package may + or may not also be published to a package registry. +- **Bundle** - A collection of the deployment artifacts. The output of the + bundling process, which brings a collection of packages into a single + collection of deployment artifacts. diff --git a/docs/cli/under-the-hood.md b/docs/cli/under-the-hood.md new file mode 100644 index 0000000000..f7400b2037 --- /dev/null +++ b/docs/cli/under-the-hood.md @@ -0,0 +1,7 @@ +--- +id: under-the-hood +title: Under the Hook +description: A dive into the implementation of the Backstage CLI +--- + +## Summary diff --git a/microsite/sidebars.json b/microsite/sidebars.json index 91112dd3b3..8d2c382b9a 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -34,6 +34,11 @@ ] } ], + "CLI": [ + "cli/index", + "cli/commands", + "cli/under-the-hood" + ], "Core Features": [ { "type": "subcategory", From 4e45c5953138cb4bcca7fcdde4cab333702e1de8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 13 Dec 2020 14:15:56 +0100 Subject: [PATCH 08/98] docs/cli: flesh out index page --- docs/cli/index.md | 62 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/docs/cli/index.md b/docs/cli/index.md index 9532e05993..eb0678aad8 100644 --- a/docs/cli/index.md +++ b/docs/cli/index.md @@ -6,15 +6,65 @@ description: Overview of the Backstage CLI ## Summary -Backstage ships its own CLI tooling +Backstage provides an opinionated set of tooling for both frontend and backend +development. It is delivered through the `@backstage/cli` package and executed +either directly through `yarn backstage-cli ` or within yarn scripts. +When creating an app using `@backstage/create-app` it contains package scripts +for executing the most common commands. -Tooling both for bundling deployment artifacts, as well as building individual -packages for publishing. - -Under the hook we use [webpack](https://webpack.js.org/) for bundling, +Under the hood the CLI uses [webpack](https://webpack.js.org/) for bundling, [rollup](https://rollupjs.org/) for building packages, [jest](https://jestjs.io/) for testing, and [eslint](https://eslint.org/) for -linting. +linting. It also includes custom tooling for working within Backstage apps, for +example for keeping the app up to date and verifying static configuration. + +## Introduction + +A goal of Backstage is to provide a delightful developer experience in and +around the project. Creating new apps and plugins should be simple, iteration +speed should be fast, and the overhead of maintaining custom tooling should be +minimal. As a part of accomplishing this goal, Backstage provides its own set of +opinionated tooling, delivered primarily through the `@backstage/cli` package. + +The `@backstage/cli` package provides a single `bin` script, `backstage-cli`, +which you can execute directly with `yarn` or within a script in `package.json`. +If you have a Backstage app set up, you can try out the following command to +print the top-level help page of the CLI: + +```bash +yarn backstage-cli --help +``` + +If you are familiar with `create-react-app` you may recognize this pattern, as +it uses a package called `react-scripts` to bring most of the functionality into +the created project. The Backstage equivalent of `create-react-app` is +`@backstage/create-app`, and the equivalent of `react-scripts` is +`@backstage/cli`. There are however a couple of key differences between the two. +Most notably, Backstage apps are monorepos and the CLI is tailored for that +environment. It provides tooling both for bundling and developing full end-user +apps, but also for developing, building and publishing individual packages +within the monorepo. + +## Opinionated + +The Backstage CLI is highly opinionated in what tools to use and how they are +configured. It is tailored for development in large TypeScript monorepos with +hundreds of separate plugins, but with the ability to have edits anywhere in the +codebase reflected within a few seconds. The build output is also optimized for +this setup, and aims for an excellent user experience with fast page load times +in modern browsers, rather than a wide range of support. + +While the Backstage tooling is opinionated in how to develop and build packages, +it is also possible to use your own tooling either partially or fully. For +example, the CLI provides a command for building a plugin package for +publishing, but the output is a pretty regular `types+js` output that you see in +many packages, which can easily be achieved with many other sets of tooling. + +Just like `react-scripts`, the Backstage CLI does not provide many hooks for +overriding or customizing the build process. This is to allow for evolution of +the CLI without having to take a wide API surface into account. Allowing us to +more quickly iterate and improve the tooling, as well more easily keeping +dependencies up to date. ## Glossary From e548156182a973ed4b459e18533afc22c85ffff8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 13 Dec 2020 15:03:01 +0100 Subject: [PATCH 09/98] docs/cli: add some opinions --- docs/cli/index.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/cli/index.md b/docs/cli/index.md index eb0678aad8..bfd9ac80da 100644 --- a/docs/cli/index.md +++ b/docs/cli/index.md @@ -66,6 +66,22 @@ the CLI without having to take a wide API surface into account. Allowing us to more quickly iterate and improve the tooling, as well more easily keeping dependencies up to date. +## Opinions + +In no particular order, this is a list of opinions and goals that guide the +design and development of the Backstage CLI: + +- All you need for development is `yarn start`, there should be no need to + manually build packages or run other tasks on the side. +- Development experience comes first. The toolchain is optimized for keeping + development smooth, rather than making it easy to for example build and + publish packages. +- TypeChecking and linting is left for editors and CI. Most code editors provide + tooling for these checks, and running them again during compilation would slow + down iteration speed and consume more resources. +- Backstage is run in modern browsers. We keep transpilation lightweight and + rely on modern technology such as HTTP/2 to optimize frontend speed. + ## Glossary - **Package** - A package in the Node.js ecosystem, often published to a package From aec651f8204c476026a260f63bd0c878a79c6284 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 13 Dec 2020 15:45:01 +0100 Subject: [PATCH 10/98] docs/cli: add detailed descriptions for a couple of commands --- docs/cli/commands.md | 75 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 4 deletions(-) diff --git a/docs/cli/commands.md b/docs/cli/commands.md index f10186a829..ef35f0ad8f 100644 --- a/docs/cli/commands.md +++ b/docs/cli/commands.md @@ -42,7 +42,43 @@ help [command] display help for command ## app:build -Build an app for a production release +Creates a bundle of static content from the app, which can then be served via +and static web server such as `nginx`, or via the `app-backend` plugin directly +from a Backstage backend instance. + +The command also reads and injects static configuration into the bundle. It is +important to note that when deploying with your own static content hosting +solution, this will be the final configuration used in the frontend, unless you +for example hook in configuration loading from the backend. When using the +`nginx` image in this repo along with its included run script, `APP_CONFIG_` +environment variables will be injected into the frontend, and when serving using +the `app-backend` plugin, the configuration is completely injected from the +backend and the configuration at the time of calling this command will not be +used. + +Note that even when injecting configuration at runtime, it is not possible to +change the base path of the app. For example, if you at build time have +`app.baseUrl` set to `http://dev-app.com/my-app`, you're can change that to +`https://prod-app.com/my-app`, but not to `https://prod-app.com`, as that would +change the path. + +During the build, the following variables are set: + +```java +process.env.NODE_ENV = 'production'; +process.env.BUILD_INFO = { + cliVersion: '0.4.0', // The version of the CLI package + gitVersion: 'v0.4.0-86-ge54815618', // output of `git describe --always` + packageVersion: '1.0.5', // The version of the app package itself + timestamp: 1678900000000, // Date.now() when the build started + commit: 'e548156182a973ed4b459e18533afc22c85ffff8', // output of `git rev-parse HEAD` +}; +``` + +Some CI environments do not properly report correct resource limits, potentially +leading to errors such as `ENOMEM` during compilation. If you run into this you +can manually limit the parallelization of the build process by setting the +environment variable `BACKSTAGE_CLI_BUILD_PARALLEL` to for example `2`. ```text Usage: backstage-cli app:build [options] @@ -55,7 +91,13 @@ Options: ## app:diff -Diff an existing app with the creation template +Diff an existing app with the template used in `@backstage/create-app`. This +will verify that your app package has not diverged from the template, and can be +useful to run after updating the version of `@backstage/cli` in your app. + +This command is experimental and may be removed in the future. Compared to the +`plugin:diff` command this one is less valuable, as we have found fewer useful +checks to carry out. ```text Usage: backstage-cli app:diff [options] @@ -68,7 +110,29 @@ Options: ## app:serve -Serve an app for local development +Serve an app for local development. This starts up a local development server, +using a bundling config that is quite similar to the `app:build` command, but +with development features such as React Hot Module Replacement, faster +sourcemaps, no minification, etc. + +The serve configuration is controlled through the static configuration, by +default in `app-config.yaml`. The schema in the `app.baseUrl` determines whether +HTTP or HTTPS is used, and the listening host and port port is also determined +from the URL. It is possible to explicitly override the listening host and port +if needed by setting `app.listen.host` and `app.listen.port`. + +The static configuration is injected into the frontend as well, but there it +does not support watching, meaning that changes in for example `app-config.yaml` +are not reflected until the serve process is restarted. + +During the build, the following variables are set: + +```java +process.env.NODE_ENV = 'development'; +process.env.BUILD_INFO = { /* See app:build */ }; +``` + +By default the ```text Usage: backstage-cli app:serve [options] @@ -81,7 +145,10 @@ Options: ## backend:build -Build a backend plugin +This builds a backend package for publish and use in production. The build +output is written to `dist/`. Be sure to list any additional file that the +package depends on at runtime in the `"files"` field inside `package.json`, a +common example being the `migrations/` directory. ```text Usage: backstage-cli backend:build [options] From 2b29cb9eecdb3b5a97a62a0daf006eb1a2cb8f69 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 13 Dec 2020 17:30:02 +0100 Subject: [PATCH 11/98] docs/cli: detailed descriptions for all commands --- docs/cli/commands.md | 138 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 119 insertions(+), 19 deletions(-) diff --git a/docs/cli/commands.md b/docs/cli/commands.md index ef35f0ad8f..8f8cb74ed7 100644 --- a/docs/cli/commands.md +++ b/docs/cli/commands.md @@ -159,8 +159,38 @@ Options: ## backend:build-image -Bundles the package into a docker image. All extra args are forwarded to -`docker image build`. +Builds a Docker image of the backend package and forwards all unknown options to +`docker image build`. For example: + +```bash +yarn backstage-cli backend:build-image --build --tag my-backend-image +``` + +The image is built with the backend package along with all of its local package +dependencies. This uses a `Dockerfile` that is expected to exist at the root of +the backend package. The `Dockerfile` will end up being executed from the root +of the monorepo, rather than the backend package itself. + +The Dockerfile is **NOT** executed within the package or repo itself. Because +the packages in the repo itself are configured for development instead of +production use, the final Docker build happens in a separate temporary +directory, to which the backend package and dependencies have been copied over. +Only files listed within the `"files"` field within each package's +`package.json` are copied over, along with the root `package.json`, `yarn.lock`, +and any `app-config.*.yaml` files. + +During the build a `skeleton.tar` file is created and put at the repo root. This +file contains the `package.json` of each included package, which together with +the root `package.json` and `yarn.lock` can be used to run a cached +`yarn install` before the full production builds of all the packages are copied +over, providing a significant speedup if Docker build layer caching available. + +This command is experimental and we hope to be able to replace it with one that +is less integrated directly with Docker, and also supports multi-stage Docker +builds. It is possible to replicate most of what this command does by manually +building each package, then use the `build-workspace` to create the temporary +workspace, and finally copy over any additional files to the workspace and +execute the Docker build within it. ```text Usage: backstage-cli backend:build-image [options] @@ -172,7 +202,8 @@ Options: ## backend:dev -Start local development server with HMR for the backend +Starts a backend package in development mode, with watch mode enabled for all +local packages. ```text Usage: backstage-cli backend:dev [options] @@ -186,7 +217,10 @@ Options: ## create-plugin -Creates a new plugin in the current repository +Creates a new plugin within the repository. This command is typically wrapped up +in the root `package.json` to be executed with `yarn create-plugin`, using +options that are appropriate for the organization that owns the app repo. A +recommended scope for internal packages is `@internal`. ```text Usage: backstage-cli create-plugin [options] @@ -201,7 +235,11 @@ Options: ## remove-plugin -Removes plugin in the current repository +A utility to remove a plugin from a repo, essentially undoing everything that +was done by `create-plugin`. + +This is primarily intended as a utility for manual tests and end to end testing +scripts. ```text Usage: backstage-cli remove-plugin [options] @@ -212,7 +250,15 @@ Options: ## plugin:build -Build a plugin +Build a frontend plugin for publishing to a package registry. There is no need +to run this command during development or even in CI unless the package is being +published. The `app:bundle` command does not use the output for this command +when bundling local package dependencies. + +The output is written to a `dist/` folder. It also outputs type declarations for +the plugin, and therefore requires `yarn tsc` to have been run first. The input +type declarations are expected to be found within `dist-types` at the root of +the monorepo. ```text Usage: backstage-cli plugin:build [options] @@ -223,7 +269,13 @@ Options: ## plugin:serve -Serves the dev/ folder of a plugin +Serves a frontend plugin by itself for isolated development. The serve task +itself is essentially identical to `app:serve`, but the entrypoint is instead +set to the `dev/` folder within the plugin. + +The `dev/` folder typically contains a small wrapper script that hooks up any +necessary mock APIs or other things that are needed for the plugin to function. +The `@backstage/dev-utils` package provides utilities to that end. ```text Usage: backstage-cli plugin:serve [options] @@ -236,7 +288,10 @@ Options: ## plugin:diff -Diff an existing plugin with the creation template +Compares a frontend plugin to the `create-plugin` template, making sure that it +hasn't diverged from the template and recommending updates when it has. A good +practice is to run this command after updating the version of the CLI in a +project. ```text Usage: backstage-cli plugin:diff [options] @@ -249,7 +304,15 @@ Options: ## build -Build a package for publishing +Build a single package for publishing, just like the `plugin:build` and +`backend:build` commands. This command is intended for standalone packages that +aren't plugins, and for example support building of isomorphic packages for +usage in both the frontend and backend. + +For frontend packages you'll want to include `esm` output, and for backend +packages `cjs`. Whether to include `types` depends on if you need type +declarations for the package, and also requires `yarn tsc` to have been run +first. ```text Usage: backstage-cli build [options] @@ -261,7 +324,9 @@ Options: ## lint -Lint a package +Lint a package. In addition to the default `eslint` behavior, this command will +include TypeScript files, treat warnings as errors, and default to linting the +entire directory of no specific files are listed. ```text Usage: backstage-cli lint [options] @@ -274,7 +339,7 @@ Options: ## test -Run tests, forwarding args to Jest, defaulting to watch mode +Run tests, forwarding all unknown options to Jest, and defaulting to watch mode. ```text Usage: backstage-cli test [options] @@ -285,7 +350,15 @@ Options: ## config:print -Print the app configuration for the current package +Print the static configuration, defaulting to reading `app-config.yaml` in the +repo root, using schema collected from all local packages in the repo. + +For example, to validate that a given configuration value is visible in the +frontend when building the `my-app` package, you can use the following: + +```bash +yarn backstage-cli config:print --frontend --package my-app +``` ```text Usage: backstage-cli config:print [options] @@ -301,7 +374,9 @@ Options: ## config:check -Validate that the given configuration loads and matches schema +Validate that static configuration loads and matches schema, defaulting to +reading `app-config.yaml` in the repo root and using schema collected from all +local packages in the repo. ```text Usage: backstage-cli config:check [options] @@ -314,7 +389,9 @@ Options: ## versions:bump -Bump Backstage packages to the latest versions +Bump all `@backstage` packages to the latest versions. This check for updates in +the package registry, and will update entries both in `yarn.lock` and +`package.json` files when necessary. ```text Usage: backstage-cli versions:bump [options] @@ -325,7 +402,14 @@ Options: ## versions:check -Check Backstage package versioning +Validate `@backstage` dependencies within the repo, making sure that there are +no duplicates of packages that might lead to breakages. For example, +`@backstage/core` must not be loaded in twice, so having two different versions +of it installed will cause this command to exit with an error. + +By supplying the `--fix` flag the command will attempt to fix any conflict that +can be resolved by editing `yarn.lock`, but will not attempt to search for +remote updates or modify any `package.json` files. ```text Usage: backstage-cli versions:check [options] @@ -337,7 +421,20 @@ Options: ## prepack -Prepares a package for packaging before publishing +This command should be added as `scripts.prepack` in all packages. It enables +packaging- and publish-time overrides for fields inside `packages.json`. + +The checked in version of all packages in a Backstage monorepo are tailored for +local development, and as such `main` and similar fields inside `package.json` +point to development source, i.e. `src/index.ts`. Using this when publishing +would lead to a broken package, since `src/` is not included in the published +package and we instead need to point to files in the `dist/` directory. This +command allows for those fields to be rewritten when needed, and does so by +copying all fields within `publishConfig` to the top-level of each +`package.json`, skipping `access`, `registry`, and `tag`. + +The need for this command may be removed in the future, as this exact method of +overriding fields for publishing is already supported by some package managers. ```text Usage: backstage-cli prepack [options] @@ -348,7 +445,8 @@ Options: ## postpack -Restores the changes made by the prepack command +This should be added as `scripts.postpack` in all packages.return. It restores +`package.json` to what it looked like before calling the `prepack` command. ```text Usage: backstage-cli postpack [options] @@ -359,7 +457,7 @@ Options: ## clean -Delete cache directories +Remove cache and output directories. ```text Usage: backstage-cli clean [options] @@ -370,7 +468,9 @@ Options: ## build-workspace -Builds a temporary dist workspace from the provided packages +Builds a mirror of the workspace using the packaged production version of each +package. This essentially calls `yarn pack` in each included package and unpacks +the resulting archive in the target `workspace-dir`. ```text Usage: backstage-cli build-workspace [options] From 6b3b1fb55fe07cec30673076d23c45f93b5eae6a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 13 Dec 2020 17:44:24 +0100 Subject: [PATCH 12/98] docs/cli: tweak commands doc and add scope of each command --- docs/cli/commands.md | 128 +++++++++++++++++++++++++++++++------------ 1 file changed, 93 insertions(+), 35 deletions(-) diff --git a/docs/cli/commands.md b/docs/cli/commands.md index 8f8cb74ed7..5fc9608ff0 100644 --- a/docs/cli/commands.md +++ b/docs/cli/commands.md @@ -4,44 +4,61 @@ title: Commands description: Descriptions of all commands available in the CLI. --- -## Summary +This page lists all commands provided by the Backstage CLI, what they're for, +and where to use them. + +The documentation for each command begins with specifying its scope, this +indicates where the command should be used by selecting from the following list: + +- `app` - A frontend app package, such as `packages/app`. +- `backend` - A backend package, such as `packages/backend`. +- `frontend-plugin` - A frontend plugin package. +- `backend-plugin` - A backend plugin package. +- `any` - Any kind of package. +- `root` - The monorepo root, not specific to any one package. + +## help + +The following is a cleaned up output of of `yarn backstage-cli --help`: ```text -app:build [options] Build an app for a production release -app:diff [options] Diff an existing app with the creation template -app:serve [options] Serve an app for local development +app:build Build an app for a production release +app:diff Diff an existing app with the creation template +app:serve Serve an app for local development -backend:build Build a backend plugin -backend:build-image [options] Bundles the package into a docker image. All extra args are forwarded to `docker image build`. -backend:dev [options] Start local development server with HMR for the backend +backend:build Build a backend plugin +backend:build-image Bundles the package into a docker image +backend:dev Start local development server with HMR for the backend -plugin:build Build a plugin -plugin:diff [options] Diff an existing plugin with the creation template -plugin:serve [options] Serves the dev/ folder of a plugin +plugin:build Build a plugin +plugin:diff Diff an existing plugin with the creation template +plugin:serve Serves the dev/ folder of a plugin -build [options] Build a package for publishing -build-workspace Builds a temporary dist workspace from the provided packages -lint [options] Lint a package -test Run tests, forwarding args to Jest, defaulting to watch mode -clean Delete cache directories +build Build a package for publishing +build-workspace Builds a temporary dist workspace from the provided packages +lint Lint a package +test Run tests, forwarding args to Jest, defaulting to watch mode +clean Delete cache directories -create-plugin [options] Creates a new plugin in the current repository -remove-plugin Removes plugin in the current repository +create-plugin Creates a new plugin in the current repository +remove-plugin Removes plugin in the current repository -config:print [options] Print the app configuration for the current package -config:check [options] Validate that the given configuration loads and matches schema +config:print Print the app configuration for the current package +config:check Validate that the given configuration loads and matches schema -versions:bump Bump Backstage packages to the latest versions -versions:check [options] Check Backstage package versioning +versions:bump Bump Backstage packages to the latest versions +versions:check Check Backstage package versioning -prepack Prepares a package for packaging before publishing -postpack Restores the changes made by the prepack command +prepack Prepares a package for packaging before publishing +postpack Restores the changes made by the prepack command -help [command] display help for command +help [command] display help for command ``` ## app:build +Scope: `app` + Creates a bundle of static content from the app, which can then be served via and static web server such as `nginx`, or via the `app-backend` plugin directly from a Backstage backend instance. @@ -81,7 +98,7 @@ can manually limit the parallelization of the build process by setting the environment variable `BACKSTAGE_CLI_BUILD_PARALLEL` to for example `2`. ```text -Usage: backstage-cli app:build [options] +Usage: backstage-cli app:build Options: --stats Write bundle stats to output directory @@ -91,6 +108,8 @@ Options: ## app:diff +Scope: `app` + Diff an existing app with the template used in `@backstage/create-app`. This will verify that your app package has not diverged from the template, and can be useful to run after updating the version of `@backstage/cli` in your app. @@ -100,7 +119,7 @@ This command is experimental and may be removed in the future. Compared to the checks to carry out. ```text -Usage: backstage-cli app:diff [options] +Usage: backstage-cli app:diff Options: --check Fail if changes are required @@ -110,17 +129,13 @@ Options: ## app:serve +Scope: `app` + Serve an app for local development. This starts up a local development server, using a bundling config that is quite similar to the `app:build` command, but with development features such as React Hot Module Replacement, faster sourcemaps, no minification, etc. -The serve configuration is controlled through the static configuration, by -default in `app-config.yaml`. The schema in the `app.baseUrl` determines whether -HTTP or HTTPS is used, and the listening host and port port is also determined -from the URL. It is possible to explicitly override the listening host and port -if needed by setting `app.listen.host` and `app.listen.port`. - The static configuration is injected into the frontend as well, but there it does not support watching, meaning that changes in for example `app-config.yaml` are not reflected until the serve process is restarted. @@ -132,7 +147,11 @@ process.env.NODE_ENV = 'development'; process.env.BUILD_INFO = { /* See app:build */ }; ``` -By default the +The serve configuration is controlled through the static configuration, by +default in `app-config.yaml`. The protocol of `app.baseUrl` determines whether +HTTP or HTTPS is used, and the listening host and port is also determined by the +URL. It is possible to override the listening host and port if needed by setting +`app.listen.host` and `app.listen.port`. ```text Usage: backstage-cli app:serve [options] @@ -145,10 +164,13 @@ Options: ## backend:build -This builds a backend package for publish and use in production. The build +Scope: `backend`, `backend-plugin` (To be replaced by `backend:bundle` for +`backend`) + +This builds a backend package for publishing and use in production. The build output is written to `dist/`. Be sure to list any additional file that the package depends on at runtime in the `"files"` field inside `package.json`, a -common example being the `migrations/` directory. +common example being the `migrations` directory. ```text Usage: backstage-cli backend:build [options] @@ -159,6 +181,8 @@ Options: ## backend:build-image +Scope: `backend` + Builds a Docker image of the backend package and forwards all unknown options to `docker image build`. For example: @@ -202,6 +226,8 @@ Options: ## backend:dev +Scope: `backend`, `backend-plugin` + Starts a backend package in development mode, with watch mode enabled for all local packages. @@ -217,6 +243,8 @@ Options: ## create-plugin +Scope: `root` + Creates a new plugin within the repository. This command is typically wrapped up in the root `package.json` to be executed with `yarn create-plugin`, using options that are appropriate for the organization that owns the app repo. A @@ -235,6 +263,8 @@ Options: ## remove-plugin +Scope: `root` + A utility to remove a plugin from a repo, essentially undoing everything that was done by `create-plugin`. @@ -250,6 +280,8 @@ Options: ## plugin:build +Scope: `frontend-plugin` + Build a frontend plugin for publishing to a package registry. There is no need to run this command during development or even in CI unless the package is being published. The `app:bundle` command does not use the output for this command @@ -269,6 +301,8 @@ Options: ## plugin:serve +Scope: `frontend-plugin` + Serves a frontend plugin by itself for isolated development. The serve task itself is essentially identical to `app:serve`, but the entrypoint is instead set to the `dev/` folder within the plugin. @@ -288,6 +322,8 @@ Options: ## plugin:diff +Scope: `frontend-plugin` + Compares a frontend plugin to the `create-plugin` template, making sure that it hasn't diverged from the template and recommending updates when it has. A good practice is to run this command after updating the version of the CLI in a @@ -304,6 +340,8 @@ Options: ## build +Scope: `any` + Build a single package for publishing, just like the `plugin:build` and `backend:build` commands. This command is intended for standalone packages that aren't plugins, and for example support building of isomorphic packages for @@ -324,6 +362,8 @@ Options: ## lint +Scope: `any` + Lint a package. In addition to the default `eslint` behavior, this command will include TypeScript files, treat warnings as errors, and default to linting the entire directory of no specific files are listed. @@ -339,6 +379,8 @@ Options: ## test +Scope: `any` + Run tests, forwarding all unknown options to Jest, and defaulting to watch mode. ```text @@ -350,6 +392,8 @@ Options: ## config:print +Scope: `root` + Print the static configuration, defaulting to reading `app-config.yaml` in the repo root, using schema collected from all local packages in the repo. @@ -374,6 +418,8 @@ Options: ## config:check +Scope: `root` + Validate that static configuration loads and matches schema, defaulting to reading `app-config.yaml` in the repo root and using schema collected from all local packages in the repo. @@ -389,6 +435,8 @@ Options: ## versions:bump +Scope: `root` + Bump all `@backstage` packages to the latest versions. This check for updates in the package registry, and will update entries both in `yarn.lock` and `package.json` files when necessary. @@ -402,6 +450,8 @@ Options: ## versions:check +Scope: `root` + Validate `@backstage` dependencies within the repo, making sure that there are no duplicates of packages that might lead to breakages. For example, `@backstage/core` must not be loaded in twice, so having two different versions @@ -421,6 +471,8 @@ Options: ## prepack +Scope: `any` + This command should be added as `scripts.prepack` in all packages. It enables packaging- and publish-time overrides for fields inside `packages.json`. @@ -445,6 +497,8 @@ Options: ## postpack +Scope: `any` + This should be added as `scripts.postpack` in all packages.return. It restores `package.json` to what it looked like before calling the `prepack` command. @@ -457,6 +511,8 @@ Options: ## clean +Scope: `any` + Remove cache and output directories. ```text @@ -468,6 +524,8 @@ Options: ## build-workspace +Scope: `any` + Builds a mirror of the workspace using the packaged production version of each package. This essentially calls `yarn pack` in each included package and unpacks the resulting archive in the target `workspace-dir`. From 842f745fbd8b249ac3fa84cea629f0de4a24d450 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 13 Dec 2020 18:58:48 +0100 Subject: [PATCH 13/98] docs/cli: more docs for the test command --- docs/cli/commands.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/cli/commands.md b/docs/cli/commands.md index 5fc9608ff0..4f3f43376c 100644 --- a/docs/cli/commands.md +++ b/docs/cli/commands.md @@ -382,6 +382,30 @@ Options: Scope: `any` Run tests, forwarding all unknown options to Jest, and defaulting to watch mode. +When executing the tests, `process.env.NODE_ENV` will be set to `"test"`. + +This command uses a default Jest configuration that is included in the CLI, +which is set up with similar goals for speed, scale, and working within a +monorepo. The configuration sets the `src` as the root directory, enforces the +`.test.` infix for tests, and uses `src/setupTests.ts` as the test setup +location. + +If needed, the configuration can be extended using a `"jest"` field in +`package.json`, both within the target package and the monorepo root, with +configuration in the target package taking precedence. Refer to the +[Jest configuration](https://jestjs.io/docs/en/configuration) for a full list of +configuration options. + +In addition to the Jest configuration there's an optional `transformModules` +option, which is an array of module names to transform. Normally modules inside +`node_modules` are not transformed, but there are cases were published packages +are not transpiled far enough to be supported by jest, in which case you need to +enable transforms of them. + +Another way to override the Jest configuration is to place a `jest.config.js` or +`jest.config.ts` file in the package. As opposed to the `package.json` way of +overriding config, this completely removes the base config, and so you need to +set it up from scratch. ```text Usage: backstage-cli test [options] From e0426d00edb528bf82e74b3a65c960b8f3c0ffa0 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 13 Dec 2020 19:00:44 +0100 Subject: [PATCH 14/98] docs/cli: skip under the hood docs for now --- docs/cli/under-the-hood.md | 7 ------- microsite/sidebars.json | 6 +----- 2 files changed, 1 insertion(+), 12 deletions(-) delete mode 100644 docs/cli/under-the-hood.md diff --git a/docs/cli/under-the-hood.md b/docs/cli/under-the-hood.md deleted file mode 100644 index f7400b2037..0000000000 --- a/docs/cli/under-the-hood.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -id: under-the-hood -title: Under the Hook -description: A dive into the implementation of the Backstage CLI ---- - -## Summary diff --git a/microsite/sidebars.json b/microsite/sidebars.json index 8d2c382b9a..b31f0ccdf3 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -34,11 +34,7 @@ ] } ], - "CLI": [ - "cli/index", - "cli/commands", - "cli/under-the-hood" - ], + "CLI": ["cli/index", "cli/commands"], "Core Features": [ { "type": "subcategory", From 436202b20efb763130e14430a422ca1ffe975704 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 13 Dec 2020 19:48:22 +0100 Subject: [PATCH 15/98] docs/cli: text fixes --- docs/cli/commands.md | 124 +++++++++++++++++++++---------------------- docs/cli/index.md | 81 ++++++++++++++++------------ 2 files changed, 108 insertions(+), 97 deletions(-) diff --git a/docs/cli/commands.md b/docs/cli/commands.md index 4f3f43376c..dc226c6e2e 100644 --- a/docs/cli/commands.md +++ b/docs/cli/commands.md @@ -14,12 +14,13 @@ indicates where the command should be used by selecting from the following list: - `backend` - A backend package, such as `packages/backend`. - `frontend-plugin` - A frontend plugin package. - `backend-plugin` - A backend plugin package. -- `any` - Any kind of package. -- `root` - The monorepo root, not specific to any one package. +- `root` - The monorepo root. +- `any` - Any kind of package, but not the repo root. ## help -The following is a cleaned up output of of `yarn backstage-cli --help`: +This command displays you a help summary or detailed help screens for each +command. Below is a cleaned up output of `yarn backstage-cli --help`. ```text app:build Build an app for a production release @@ -59,13 +60,14 @@ help [command] display help for command Scope: `app` -Creates a bundle of static content from the app, which can then be served via -and static web server such as `nginx`, or via the `app-backend` plugin directly -from a Backstage backend instance. +Builds a bundle of static content from the app, which can then be served via any +static web server such as `nginx`, or via the +[`app-backend`](https://www.npmjs.com/package/@backstage/plugin-app-backend) +plugin directly from a Backstage backend instance. The command also reads and injects static configuration into the bundle. It is -important to note that when deploying with your own static content hosting -solution, this will be the final configuration used in the frontend, unless you +important to note that when deploying using your own static content hosting +solution, this will be the final configuration used in the frontend unless you for example hook in configuration loading from the backend. When using the `nginx` image in this repo along with its included run script, `APP_CONFIG_` environment variables will be injected into the frontend, and when serving using @@ -75,7 +77,7 @@ used. Note that even when injecting configuration at runtime, it is not possible to change the base path of the app. For example, if you at build time have -`app.baseUrl` set to `http://dev-app.com/my-app`, you're can change that to +`app.baseUrl` set to `http://dev-app.com/my-app`, you can change that to `https://prod-app.com/my-app`, but not to `https://prod-app.com`, as that would change the path. @@ -93,16 +95,18 @@ process.env.BUILD_INFO = { ``` Some CI environments do not properly report correct resource limits, potentially -leading to errors such as `ENOMEM` during compilation. If you run into this you -can manually limit the parallelization of the build process by setting the -environment variable `BACKSTAGE_CLI_BUILD_PARALLEL` to for example `2`. +leading to errors such as `ENOMEM` during compilation. If you run into this +issue you can limit the parallelization of the build process by setting the +environment variable `BACKSTAGE_CLI_BUILD_PARALLEL`. You can set it to `false` +or `1` to completely disable parallelization, but usually a low value such as +`2` is enough. ```text Usage: backstage-cli app:build Options: --stats Write bundle stats to output directory - --config Config files to load instead of app-config.yaml (default: []) + --config <path> Config files to load instead of app-config.yaml (default: []) -h, --help display help for command ``` @@ -114,9 +118,7 @@ Diff an existing app with the template used in `@backstage/create-app`. This will verify that your app package has not diverged from the template, and can be useful to run after updating the version of `@backstage/cli` in your app. -This command is experimental and may be removed in the future. Compared to the -`plugin:diff` command this one is less valuable, as we have found fewer useful -checks to carry out. +This command is experimental and may be removed in the future. ```text Usage: backstage-cli app:diff @@ -132,13 +134,13 @@ Options: Scope: `app` Serve an app for local development. This starts up a local development server, -using a bundling config that is quite similar to the `app:build` command, but -with development features such as React Hot Module Replacement, faster -sourcemaps, no minification, etc. +using a bundling configuration that is quite similar to that of the `app:build` +command, but with development features such as React Hot Module Replacement, +faster sourcemaps, no minification, etc. -The static configuration is injected into the frontend as well, but there it -does not support watching, meaning that changes in for example `app-config.yaml` -are not reflected until the serve process is restarted. +The static configuration is injected into the frontend, but it does not support +watching, meaning that changes in for example `app-config.yaml` are not +reflected until the serve process is restarted. During the build, the following variables are set: @@ -147,18 +149,17 @@ process.env.NODE_ENV = 'development'; process.env.BUILD_INFO = { /* See app:build */ }; ``` -The serve configuration is controlled through the static configuration, by -default in `app-config.yaml`. The protocol of `app.baseUrl` determines whether -HTTP or HTTPS is used, and the listening host and port is also determined by the -URL. It is possible to override the listening host and port if needed by setting -`app.listen.host` and `app.listen.port`. +The server listening configuration is controlled through the static +configuration. The `app.baseUrl` determines the listening host and port, as well +as whether HTTPS is used or not. It is also possible to override the listening +host and port if needed by setting `app.listen.host` and `app.listen.port`. ```text Usage: backstage-cli app:serve [options] Options: --check Enable type checking and linting - --config Config files to load instead of app-config.yaml (default: []) + --config <path> Config files to load instead of app-config.yaml (default: []) -h, --help display help for command ``` @@ -183,25 +184,24 @@ Options: Scope: `backend` -Builds a Docker image of the backend package and forwards all unknown options to +Builds a Docker image of the backend package, forwarding all unknown options to `docker image build`. For example: ```bash yarn backstage-cli backend:build-image --build --tag my-backend-image ``` -The image is built with the backend package along with all of its local package -dependencies. This uses a `Dockerfile` that is expected to exist at the root of -the backend package. The `Dockerfile` will end up being executed from the root -of the monorepo, rather than the backend package itself. +The image is built using the backend package along with all of its local package +dependencies. It expects to find a `Dockerfile` at the root of the backend +package, which will be used during the build. The Dockerfile is **NOT** executed within the package or repo itself. Because the packages in the repo itself are configured for development instead of production use, the final Docker build happens in a separate temporary -directory, to which the backend package and dependencies have been copied over. -Only files listed within the `"files"` field within each package's -`package.json` are copied over, along with the root `package.json`, `yarn.lock`, -and any `app-config.*.yaml` files. +directory, to which the backend package and dependencies have been copied. Only +files listed within the `"files"` field within each package's `package.json` are +copied over, along with the root `package.json`, `yarn.lock`, and any +`app-config.*.yaml` files. During the build a `skeleton.tar` file is created and put at the repo root. This file contains the `package.json` of each included package, which together with @@ -212,9 +212,9 @@ over, providing a significant speedup if Docker build layer caching available. This command is experimental and we hope to be able to replace it with one that is less integrated directly with Docker, and also supports multi-stage Docker builds. It is possible to replicate most of what this command does by manually -building each package, then use the `build-workspace` to create the temporary -workspace, and finally copy over any additional files to the workspace and -execute the Docker build within it. +building each package, and then use the `build-workspace` to create the +temporary workspace, and finally copy over any additional files to the workspace +and execute the Docker build within it. ```text Usage: backstage-cli backend:build-image [options] @@ -237,7 +237,7 @@ Usage: backstage-cli backend:dev [options] Options: --check Enable type checking and linting --inspect Enable debugger - --config Config files to load instead of app-config.yaml (default: []) + --config <path> Config files to load instead of app-config.yaml (default: []) -h, --help display help for command ``` @@ -255,8 +255,8 @@ Usage: backstage-cli create-plugin [options] Options: --backend Create plugin with the backend dependencies as default - --scope npm scope - --npm-registry npm registry URL + --scope <scope> npm scope + --npm-registry <URL> npm registry URL --no-private Public npm package -h, --help display help for command ``` @@ -289,7 +289,7 @@ when bundling local package dependencies. The output is written to a `dist/` folder. It also outputs type declarations for the plugin, and therefore requires `yarn tsc` to have been run first. The input -type declarations are expected to be found within `dist-types` at the root of +type declarations are expected to be found within `dist-types/` at the root of the monorepo. ```text @@ -316,7 +316,7 @@ Usage: backstage-cli plugin:serve [options] Options: --check Enable type checking and linting - --config Config files to load instead of app-config.yaml (default: []) + --config <path> Config files to load instead of app-config.yaml (default: []) -h, --help display help for command ``` @@ -356,7 +356,7 @@ first. Usage: backstage-cli build [options] Options: - --outputs List of formats to output [types,cjs,esm] + --outputs <formats> List of formats to output [types,cjs,esm] -h, --help display help for command ``` @@ -372,7 +372,7 @@ entire directory of no specific files are listed. Usage: backstage-cli lint [options] Options: - --format Lint report output format (default: "eslint-formatter-friendly") + --format <format> Lint report output format (default: "eslint-formatter-friendly") --fix Attempt to automatically fix violations -h, --help display help for command ``` @@ -397,15 +397,15 @@ configuration in the target package taking precedence. Refer to the configuration options. In addition to the Jest configuration there's an optional `transformModules` -option, which is an array of module names to transform. Normally modules inside -`node_modules` are not transformed, but there are cases were published packages -are not transpiled far enough to be supported by jest, in which case you need to -enable transforms of them. +option, which is an array of module names to include in transformations. +Normally modules inside `node_modules` are not transformed, but there are cases +were published packages are not transpiled far enough to be usable by Jest, in +which case you need to enable transform of them. Another way to override the Jest configuration is to place a `jest.config.js` or -`jest.config.ts` file in the package. As opposed to the `package.json` way of -overriding config, this completely removes the base config, and so you need to -set it up from scratch. +`jest.config.ts` file in the package root. As opposed to the `package.json` way +of overriding config, this completely removes the base config, and so you need +to set it up from scratch. ```text Usage: backstage-cli test [options] @@ -432,11 +432,11 @@ yarn backstage-cli config:print --frontend --package my-app Usage: backstage-cli config:print [options] Options: - --package Only load config schema that applies to the given package + --package <name> Only load config schema that applies to the given package --frontend Print only the frontend configuration --with-secrets Include secrets in the printed configuration - --format Format to print the configuration in, either json or yaml [yaml] - --config Config files to load instead of app-config.yaml (default: []) + --format <format> Format to print the configuration in, either json or yaml [yaml] + --config <path> Config files to load instead of app-config.yaml (default: []) -h, --help display help for command ``` @@ -452,8 +452,8 @@ local packages in the repo. Usage: backstage-cli config:check [options] Options: - --package Only load config schema that applies to the given package - --config Config files to load instead of app-config.yaml (default: []) + --package <name> Only load config schema that applies to the given package + --config <path> Config files to load instead of app-config.yaml (default: []) -h, --help display help for command ``` @@ -523,7 +523,7 @@ Options: Scope: `any` -This should be added as `scripts.postpack` in all packages.return. It restores +This should be added as `scripts.postpack` in all packages. It restores `package.json` to what it looked like before calling the `prepack` command. ```text @@ -548,14 +548,14 @@ Options: ## build-workspace -Scope: `any` +Scope: `any`, `root` Builds a mirror of the workspace using the packaged production version of each package. This essentially calls `yarn pack` in each included package and unpacks the resulting archive in the target `workspace-dir`. ```text -Usage: backstage-cli build-workspace [options] +Usage: backstage-cli build-workspace [options] <workspace-dir> Options: ``` diff --git a/docs/cli/index.md b/docs/cli/index.md index bfd9ac80da..064c1451b9 100644 --- a/docs/cli/index.md +++ b/docs/cli/index.md @@ -7,10 +7,12 @@ description: Overview of the Backstage CLI ## Summary Backstage provides an opinionated set of tooling for both frontend and backend -development. It is delivered through the `@backstage/cli` package and executed -either directly through `yarn backstage-cli ` or within yarn scripts. -When creating an app using `@backstage/create-app` it contains package scripts -for executing the most common commands. +development. It is delivered through the +[`@backstage/cli`](https://www.npmjs.com/package/@backstage/cli) package and +executed either directly through `yarn backstage-cli ` or within +`package.json` scripts. When creating an app using +[`@backstage/create-app`](https://www.npmjs.com/package/@backstage/create-app) +it contains package scripts for executing the most common commands. Under the hood the CLI uses [webpack](https://webpack.js.org/) for bundling, [rollup](https://rollupjs.org/) for building packages, @@ -18,69 +20,78 @@ Under the hood the CLI uses [webpack](https://webpack.js.org/) for bundling, linting. It also includes custom tooling for working within Backstage apps, for example for keeping the app up to date and verifying static configuration. +For a full list of CLI commands, see the [commands](./commands.md) page. + ## Introduction A goal of Backstage is to provide a delightful developer experience in and around the project. Creating new apps and plugins should be simple, iteration speed should be fast, and the overhead of maintaining custom tooling should be minimal. As a part of accomplishing this goal, Backstage provides its own set of -opinionated tooling, delivered primarily through the `@backstage/cli` package. +opinionated tooling, delivered primarily through the +[`@backstage/cli`](https://www.npmjs.com/package/@backstage/cli) package. -The `@backstage/cli` package provides a single `bin` script, `backstage-cli`, -which you can execute directly with `yarn` or within a script in `package.json`. -If you have a Backstage app set up, you can try out the following command to -print the top-level help page of the CLI: +The `@backstage/cli` package provides a single executable script, +`backstage-cli`, which you can run directly with `yarn` or within a script in +`package.json`. If you have a Backstage app set up, you can try out the +following command to print the top-level help page of the CLI: -```bash +```text yarn backstage-cli --help ``` -If you are familiar with `create-react-app` you may recognize this pattern, as -it uses a package called `react-scripts` to bring most of the functionality into -the created project. The Backstage equivalent of `create-react-app` is -`@backstage/create-app`, and the equivalent of `react-scripts` is -`@backstage/cli`. There are however a couple of key differences between the two. -Most notably, Backstage apps are monorepos and the CLI is tailored for that -environment. It provides tooling both for bundling and developing full end-user -apps, but also for developing, building and publishing individual packages -within the monorepo. +If you are familiar with [`create-react-app`](https://create-react-app.dev/) you +may recognize the pattern of bundling tooling up as a CLI, as it uses a package +called [`react-scripts`](https://www.npmjs.com/package/react-scripts) to bring +most of the functionality into the created project. The Backstage equivalent of +`create-react-app` is +[`@backstage/create-app`](https://www.npmjs.com/package/@backstage/create-app), +and the equivalent of `react-scripts` is `@backstage/cli`. There are however a +couple of key differences between the two. Most notably, Backstage apps are +monorepos and the CLI is tailored for that environment. It provides tooling both +for bundling and developing full end-user apps, but also for developing, +building and publishing individual packages within the monorepo, as well as +tooling that is more unique to Backstage, such as commands for working with +static configuration. -## Opinionated +## Opinionated Tooling -The Backstage CLI is highly opinionated in what tools to use and how they are +The Backstage CLI is highly opinionated in what tools are used and how they are configured. It is tailored for development in large TypeScript monorepos with -hundreds of separate plugins, but with the ability to have edits anywhere in the -codebase reflected within a few seconds. The build output is also optimized for -this setup, and aims for an excellent user experience with fast page load times -in modern browsers, rather than a wide range of support. +hundreds of separate packages, but with the ability to have edits anywhere in +the codebase reflected within a few seconds. The build output is also optimized +for this setup, and aims to provide an excellent user experience with fast page +load times in modern browsers, rather than a wide range of support. While the Backstage tooling is opinionated in how to develop and build packages, it is also possible to use your own tooling either partially or fully. For example, the CLI provides a command for building a plugin package for -publishing, but the output is a pretty regular `types+js` output that you see in -many packages, which can easily be achieved with many other sets of tooling. +publishing, but the output is a quite standard combination of transpiled +JavaScript and TypeScript type declarations. The usage of the command from the +CLI can therefore easily be replaced with other tools if necessary. Just like `react-scripts`, the Backstage CLI does not provide many hooks for overriding or customizing the build process. This is to allow for evolution of the CLI without having to take a wide API surface into account. Allowing us to -more quickly iterate and improve the tooling, as well more easily keeping -dependencies up to date. +quickly iterate and improve the tooling, as well more easily keep dependencies +up to date. -## Opinions +## Opinions & Goals In no particular order, this is a list of opinions and goals that guide the design and development of the Backstage CLI: - All you need for development is `yarn start`, there should be no need to - manually build packages or run other tasks on the side. + manually build packages or run other separate tasks. - Development experience comes first. The toolchain is optimized for keeping development smooth, rather than making it easy to for example build and publish packages. -- TypeChecking and linting is left for editors and CI. Most code editors provide - tooling for these checks, and running them again during compilation would slow - down iteration speed and consume more resources. +- Type checking and linting is left for text editors and Continuous Integration. + Most text editors provide tooling for these checks, and running them a second + time during compilation slows down iteration speed and consumes more system + resources. - Backstage is run in modern browsers. We keep transpilation lightweight and - rely on modern technology such as HTTP/2 to optimize frontend speed. + rely on modern technologies such as HTTP/2 to optimize frontend speed. ## Glossary From a9d6779f38b7f5ff6d5f80359d3454aac695ad0d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 13 Dec 2020 19:52:09 +0100 Subject: [PATCH 16/98] docs/cli: vocab updates --- .github/styles/vocab.txt | 6 ++++++ docs/cli/index.md | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index 5008e88dae..d00ef23437 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -139,14 +139,17 @@ Oldsberg onboarding Onboarding pagerduty +parallelization Patrik Phoen plantuml Pomaceous postgres +postpack pre prebaked preconfigured +prepack Preprarer Prerequisities productional @@ -184,6 +187,7 @@ Serverless Sinon smartsymobls Snyk +sourcemaps sparklines Spotifiers spotify @@ -217,6 +221,8 @@ toolsets tooltip tooltips touchpoints +transpiled +transpilation ui untracked upvote diff --git a/docs/cli/index.md b/docs/cli/index.md index 064c1451b9..4a60a1bf1b 100644 --- a/docs/cli/index.md +++ b/docs/cli/index.md @@ -14,9 +14,9 @@ executed either directly through `yarn backstage-cli ` or within [`@backstage/create-app`](https://www.npmjs.com/package/@backstage/create-app) it contains package scripts for executing the most common commands. -Under the hood the CLI uses [webpack](https://webpack.js.org/) for bundling, -[rollup](https://rollupjs.org/) for building packages, -[jest](https://jestjs.io/) for testing, and [eslint](https://eslint.org/) for +Under the hood the CLI uses [Webpack](https://webpack.js.org/) for bundling, +[Rollup](https://rollupjs.org/) for building packages, +[Jest](https://jestjs.io/) for testing, and [eslint](https://eslint.org/) for linting. It also includes custom tooling for working within Backstage apps, for example for keeping the app up to date and verifying static configuration. From 1c3f510cd75e4a2f58243f1e34c2380b70889be5 Mon Sep 17 00:00:00 2001 From: Lee Mills Date: Mon, 14 Dec 2020 18:37:43 +0100 Subject: [PATCH 17/98] Update roadmap.md Updating the Backstage roadmap with current and upcoming work through H1 2021. --- docs/overview/roadmap.md | 58 +++++++++++++++------------------------- 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/docs/overview/roadmap.md b/docs/overview/roadmap.md index 71612cc5e4..0e5332f379 100644 --- a/docs/overview/roadmap.md +++ b/docs/overview/roadmap.md @@ -47,55 +47,34 @@ guidelines to get started. ### Ongoing work 🚧 -- **[Plugins for managing micro services end-2-end](https://github.com/backstage/backstage/milestone/14)** - Out of the box Backstage will ship with a set of plugins (Overview, CI, API - and Docs) that will demonstrate how a user can manage a micro service and - follow a change all the way out in production. Completing this work will make - it much easier to see how a plugin can be built that integrates with the - Backstage Service Catalog. - -- **[Users and teams](https://github.com/backstage/backstage/issues/1807)** - Ownership is a central concept in Backstage. It should be easy to import your - existing organizational data, such as users and groups/teams, into Backstage. - A user the logs into Backstage should see software components owned by the - team(s) they are in. - - **[Backstage platform is stable](https://github.com/backstage/backstage/milestone/19)** - - The platform APIs and features are stable and can be depended on for - production use. After this plugins will require little to no maintenance. + The core of Backstage and its features are stable and can be depended on for production use. After this plugins will require little to no maintenance. -* **[Improved Kubernetes plugin](https://github.com/backstage/backstage/issues/2857)** - +- **[Improved Kubernetes plugin](https://github.com/backstage/backstage/issues/2857)** - Native support for Kubernetes, making it easier for developers to see and manage their services running in k8s. -- Further improvements to platform documentation. Examples include a Golden Path - for plugin development. +- **[Global search]()** - + Extend the basic search available in the Backstage Service Catalog with a + global search experience. + +- **[Software Templates V2](https://github.com/backstage/backstage/issues/2771)** - + Expanding the templates to make steps more composable, by adding the ability to add more steps for custom logic like webhooks and using authorization from integrations. ### Future work 🔮 -- **Deploy a product demo at `demo.backstage.io`** - Deploy a typical Backstage - deployment available publicly so that people can click around and get a feel - for the product without having to install anything. +- **[Golden Path for Plugin Development]()** - + Creating an easy, standardized way for developers to build plugins will encourage contributions and lead to a richer ecosystem for everyone. -- **[Global search](https://github.com/backstage/backstage/issues/1499)** - - Extend the basic search available in the Backstage Service Catalog with a - global search experience. Long term this search solution should be extensible, - making it possible for you add custom search results. - -- **[[TechDocs V.2] Stabilization release](https://github.com/backstage/backstage/milestone/17)** - - Platform stability and compatibility improvements. - -- **Additional auth providers** - Backstage should work for most (all!) auth - solutions. Since Backstage can be used by companies regardless of what cloud - (or on prem) you are using we are especially keen to get auth support for - [AWS](https://github.com/backstage/backstage/issues/290), - [Azure](https://github.com/backstage/backstage/issues/348) and others. - -- **[Initial GraphQL API](https://github.com/backstage/backstage/milestone/13)** - +- **[GraphQL API](https://github.com/backstage/backstage/milestone/13)** - A GraphQL API will open up the rich metadata provided by Backstage in a single query. Plugins can easily query this API as well as extend the model where needed. +- **Inter Plugin Communication** - **[Under consideration]** Establish more clearly defined patterns for plugins to communicate. +Improved Access Control - [Under consideration] Provide finer grained access controls and management making it possible for you to better control the platforms user experience. + +- **Improved Access Control** - **[Under consideration]** Provide finer grained access controls and management making it possible for you to better control the platforms user experience. ### Plugins Building and maintaining [plugins](https://backstage.io/plugins) is the work of @@ -110,8 +89,15 @@ Are you missing a plugin for your favorite tool? Please [suggest a new one](https://github.com/backstage/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME). Chances are that someone will jump in and help build it. +### Community Initiatives 🧑‍🤝‍🧑 (Coming soon) +- **Backstage Monthly Meetup** - +A space for the community to come together to share and learn about the latest happenings in Backstage. + +- **Backstage Hackathons** - +Open to everyone in our Backstage community, a celebration of you, the project and building awesome things together ### Completed milestones ✅ +- [Deploy a product demo at `demo.backstage.io`](https://demo.backstage.io) - [Kubernetes plugin - v1](https://github.com/backstage/backstage/tree/master/plugins/kubernetes) - [Helm charts](https://github.com/backstage/backstage/tree/master/contrib/chart/backstage) - [Backstage Design System 💅](https://backstage.io/blog/2020/09/30/backstage-design-system) From 3d8ddf47462b9e1c9c3739c950f0536d40da250d Mon Sep 17 00:00:00 2001 From: Lee Mills Date: Mon, 14 Dec 2020 19:10:33 +0100 Subject: [PATCH 18/98] Update roadmap.md removed blank links --- docs/overview/roadmap.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/overview/roadmap.md b/docs/overview/roadmap.md index 0e5332f379..ae715e301f 100644 --- a/docs/overview/roadmap.md +++ b/docs/overview/roadmap.md @@ -54,7 +54,7 @@ guidelines to get started. Native support for Kubernetes, making it easier for developers to see and manage their services running in k8s. -- **[Global search]()** - +- **Global search** - Extend the basic search available in the Backstage Service Catalog with a global search experience. @@ -63,7 +63,7 @@ guidelines to get started. ### Future work 🔮 -- **[Golden Path for Plugin Development]()** - +- **Golden Path for Plugin Development** - Creating an easy, standardized way for developers to build plugins will encourage contributions and lead to a richer ecosystem for everyone. - **[GraphQL API](https://github.com/backstage/backstage/milestone/13)** - From c983e6ebfff916684ffd69af4138b041633ebf7e Mon Sep 17 00:00:00 2001 From: Fidel Coria Date: Mon, 14 Dec 2020 18:24:49 -0600 Subject: [PATCH 19/98] customizable storage key --- .../implementations/auth/github/GithubAuth.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/core-api/src/apis/implementations/auth/github/GithubAuth.ts b/packages/core-api/src/apis/implementations/auth/github/GithubAuth.ts index 812032a8a3..a32f77fb88 100644 --- a/packages/core-api/src/apis/implementations/auth/github/GithubAuth.ts +++ b/packages/core-api/src/apis/implementations/auth/github/GithubAuth.ts @@ -50,13 +50,16 @@ const DEFAULT_PROVIDER = { }; class GithubAuth implements OAuthApi, SessionApi { - static create({ - discoveryApi, - environment = 'development', - provider = DEFAULT_PROVIDER, - oauthRequestApi, - defaultScopes = ['read:user'], - }: OAuthApiCreateOptions) { + static create( + { + discoveryApi, + environment = 'development', + provider = DEFAULT_PROVIDER, + oauthRequestApi, + defaultScopes = ['read:user'], + }: OAuthApiCreateOptions, + storageKey = 'githubSession', + ) { const connector = new DefaultAuthConnector({ discoveryApi, environment, @@ -84,7 +87,7 @@ class GithubAuth implements OAuthApi, SessionApi { const authSessionStore = new AuthSessionStore({ manager: sessionManager, - storageKey: 'githubSession', + storageKey: storageKey, sessionScopes: (session: GithubSession) => session.providerInfo.scopes, }); From 7dd2ef7d1c4d7be069e15e92fce8e2c9ab288b0b Mon Sep 17 00:00:00 2001 From: Fidel Coria Date: Mon, 14 Dec 2020 18:45:54 -0600 Subject: [PATCH 20/98] add change log --- .changeset/sour-badgers-cry.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/sour-badgers-cry.md diff --git a/.changeset/sour-badgers-cry.md b/.changeset/sour-badgers-cry.md new file mode 100644 index 0000000000..41bb0be6ec --- /dev/null +++ b/.changeset/sour-badgers-cry.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-api': patch +--- + +Add argument for storage key to GitHub Auth Api for customizing it's value. From 6baef24bcf62384b6ddf94a1373e4d77322502e0 Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Mon, 14 Dec 2020 22:09:55 +0100 Subject: [PATCH 21/98] Update TechDocs documentation, overview, gettings started, support status, concepts, etc. 1. Add a table of all the platforms that are supported and that are in pipeline. Add issue to trac k their progress. 2. Update concepts about publisher, and add preparer and generator 3. Getting started is now complete, describes both backend and frontend, and has better setting the configuration section. 4. Some typos and code comments --- docs/features/techdocs/README.md | 45 ++-- docs/features/techdocs/concepts.md | 49 +++- docs/features/techdocs/getting-started.md | 233 ++++++++++++++---- docs/features/techdocs/using-cloud-storage.md | 4 +- packages/backend/src/plugins/techdocs.ts | 14 +- 5 files changed, 262 insertions(+), 83 deletions(-) diff --git a/docs/features/techdocs/README.md b/docs/features/techdocs/README.md index 16131a1ded..50cadc7b27 100644 --- a/docs/features/techdocs/README.md +++ b/docs/features/techdocs/README.md @@ -96,26 +96,38 @@ Build a widget (plugin) framework so that contributors can easily contribute features to TechDocs - that others can use. And, also, so that we can easily migrate Spotify's existing TechDocs features to open source. -## Structure +## Platforms Supported -- [Getting Started] -- [Concepts] -- [Creating and Publishing Documentation] -- [FAQ] +See [TechDocs Architecture](architecture.md) to get an overview of where these +providers are used. + +| Source Code Hosting Provider | Support Status | +| ---------------------------- | -------------- | +| GitHub | Yes ✅ | +| GitHub Enterprise | Yes ✅ | +| BitBucket | Yes ✅ | +| Azure DevOps | Yes ✅ | +| GitLab | Yes ✅ | +| GitLab Enterprise | Yes ✅ | + +| File Storage Provider | Support Status | Track status | +| --------------------------------- | -------------- | ----------------------------------------------------------- | +| Local Filesystem of Backstage app | Yes ✅ | | +| Google Cloud Storage (GCS) | Yes ✅ | | +| Amazon Web Services (AWS) S3 | No ❌ | [#3714](https://github.com/backstage/backstage/issues/3714) | +| Azure Storage | No ❌ | | + +[Reach out to us](#feedback) if you want to request more platforms. ## Tech Stack -| Stack | Location | -| ------------------------------------------- | -------------------------------------------------------- | -| Frontend | [`@backstage/plugin-techdocs`][techdocs/frontend] | -| Backend | [`@backstage/plugin-techdocs-backend`][techdocs/backend] | -| Docker Container (for generating doc sites) | [`techdocs-container`][techdocs/container] | -| CLI (for local development) | [`@techdocs/cli`][techdocs/cli] | +| Stack | Location | +| ----------------------------------------------- | -------------------------------------------------------- | +| Frontend Plugin | [`@backstage/plugin-techdocs`][techdocs/frontend] | +| Backend Plugin | [`@backstage/plugin-techdocs-backend`][techdocs/backend] | +| CLI (for local development and generating docs) | [`@techdocs/cli`][techdocs/cli] | +| Docker Container (for generating docs) | [`techdocs-container`][techdocs/container] | -[getting started]: getting-started.md -[concepts]: concepts.md -[creating and publishing documentation]: creating-and-publishing.md -[faq]: FAQ.md 'Frequently asked questions' [techdocs/frontend]: https://github.com/backstage/backstage/blob/master/plugins/techdocs [techdocs/backend]: @@ -131,3 +143,6 @@ https://docs.google.com/forms/d/e/1FAIpQLSdn5Vn3MQhCdyYRuW8cMzZkMQF0bFxXYN168gZR This is to gather inputs from you (the Backstage community) which will help us best serve TechDocs adopters and existing users. Your inputs will shape our roadmap and we will share it in the open. + +For any other general queries, reach out to us in the `#docs-like-code` channel +of our [Discord chatroom](https://github.com/backstage/backstage#community). diff --git a/docs/features/techdocs/concepts.md b/docs/features/techdocs/concepts.md index 1675c64288..06e77ba168 100644 --- a/docs/features/techdocs/concepts.md +++ b/docs/features/techdocs/concepts.md @@ -8,13 +8,41 @@ Spotify's docs-like-code solution in Backstage This page describes concepts that are introduced with Spotify's docs-like-code solution in Backstage. -### TechDocs Core Plugin +### TechDocs Preparer -The TechDocs Core Plugin is an [MkDocs](https://www.mkdocs.org/) plugin created -as a wrapper around multiple MkDocs plugins and Python Markdown extensions to -standardize the configuration of MkDocs used for TechDocs. +Prepare is the first step of generating documentation for an entity. It fetches +the source markdown files from the source code hosting provider (GitHub, GitLab, +etc.) and passes the files to the generator for next steps. -[TechDocs Core](https://github.com/backstage/mkdocs-techdocs-core) +There are two kinds of preparers available - + +1. Common Git Preparer - Uses `git clone` on any repository url. +2. Url Reader - Uses source code hosting provider's API to download files. + (Faster and recommended) + +## TechDocs Generator + +Generation is the second step after preparing the markdown source files. This +step either runs the TechDocs container (defined below) or runs `mkdocs` CLI to +generate static HTML files and its assets. + +### TechDocs Publisher + +Publish is the third and final step after preparing and generating docs. +TechDocs Publisher uploads the generated files to a storage. + +The `techdocs-backend` plugin currently comes with two publishers - Google Cloud +Storage and Local Filesystem. You can configure them in your Backstage app. +[See here](./configuration.md). + +A TechDocs publisher is responsible for two things (two-way communication +between `techdocs-backend` and the storage) + +1. Publish generated static files to a storage (Configured by + `techdocs.builder`) +2. Read files from the storage when users visit a TechDocs site + +[TechDocs Backend](https://github.com/backstage/backstage/tree/master/plugins/techdocs-backend) ### TechDocs container @@ -25,14 +53,13 @@ MkDocs. [TechDocs Container](https://github.com/backstage/techdocs-container) -### TechDocs publisher +### TechDocs Core Plugin -The `techdocs-backend` plugin currently comes with one publisher - -`LocalPublish`. +The TechDocs Core Plugin is an [MkDocs](https://www.mkdocs.org/) plugin created +as a wrapper around multiple MkDocs plugins and Python Markdown extensions to +standardize the configuration of MkDocs used for TechDocs. -[TechDocs Backend](https://github.com/backstage/backstage/tree/master/plugins/techdocs-backend) - -More standalone publishers will come in the near future... +[TechDocs Core](https://github.com/backstage/mkdocs-techdocs-core) ### TechDocs CLI diff --git a/docs/features/techdocs/getting-started.md b/docs/features/techdocs/getting-started.md index e51c6a122e..b9ba5bcf4f 100644 --- a/docs/features/techdocs/getting-started.md +++ b/docs/features/techdocs/getting-started.md @@ -1,7 +1,7 @@ --- id: getting-started title: Getting Started -description: Getting Started Guidelines +description: Getting Started Documentation --- TechDocs functions as a plugin to Backstage, so you will need to use Backstage @@ -10,50 +10,154 @@ to use TechDocs. If you haven't setup Backstage already, start [here](../../getting-started/index.md). -## Installing TechDocs +> If you used `npx @backstage/create-app`, TechDocs may already be present. +> +> You should skip to `Setting the Configuration` below. -TechDocs is provided with the Backstage application by default. If you want to -set up TechDocs manually, keep following the instructions below. - -### Adding the package +## Adding TechDocs frontend plugin The first step is to add the TechDocs plugin to your Backstage application. -Navigate to your new Backstage application folder: - -```bash -cd hello-world/ -``` - -Then navigate to your `packages/app` folder to install TechDocs: +Navigate to your new Backstage application directory. And then to your +`packages/app` directory, and install the `@backstage/plugin-techdocs` package. ```bash +cd my-backstage-app/ cd packages/app yarn add @backstage/plugin-techdocs ``` -After a short while, the TechDocs plugin should be successfully installed. +Once the package has been installed, you need to import the plugin in your app. -Next, you need to set up some basic configuration. Enter the following command: - -```bash -yarn install -``` - -Add this to `packages/app/src/plugins.ts`: +Add the following to `packages/app/src/plugins.ts`: ```typescript export { plugin as TechDocs } from '@backstage/plugin-techdocs'; ``` -### Setting the configuration +Now let us embed the TechDocs router in our main Backstage frontend router. In +`packages/app/src/App.tsx`, import the TechDocs router and add the following to +`AppRoutes`: -TechDocs allows for configuration of the docs storage URL through your -`app-config.yaml` file. We provide two different values to be configured, -`requestUrl` and `storageUrl`. The `requestUrl` is what the reader will request -its data from, and `storageUrl` is where the backend can find the stored -documentation. +```tsx +import { Router as DocsRouter } from '@backstage/plugin-techdocs'; -The default storage and request URLs: +// ... + +const AppRoutes = () => { + + // ... other plugin routes + } /> + ; +}; +``` + +That's it! But now, we need the TechDocs Backend plugin for the frontend to +work. + +## Adding TechDocs backend plugin + +Navigate to `packages/backend` of your Backstage app, and install the +`@backstage/plugin-techdocs-backend` package. + +```bash +cd my-backstage-app/ +cd packages/backend +yarn add @backstage/plugin-techdocs-backend +``` + +Create a file called `techdocs.ts` inside `packages/backend/src/plugins/` and +add the following + +```typescript +import { + createRouter, + DirectoryPreparer, + Preparers, + Generators, + TechdocsGenerator, + CommonGitPreparer, + UrlPreparer, + Publisher, +} from '@backstage/plugin-techdocs-backend'; +import { PluginEnvironment } from '../types'; +import Docker from 'dockerode'; + +export default async function createPlugin({ + logger, + config, + discovery, + reader, +}: PluginEnvironment) { + // Preparers are responsible for fetching source files for documentation. + const preparers = new Preparers(); + + const directoryPreparer = new DirectoryPreparer(logger); + preparers.register('dir', directoryPreparer); + + const commonGitPreparer = new CommonGitPreparer(logger); + preparers.register('github', commonGitPreparer); + preparers.register('gitlab', commonGitPreparer); + preparers.register('azure/api', commonGitPreparer); + + const urlPreparer = new UrlPreparer(reader, logger); + preparers.register('url', urlPreparer); + + // Generators are used for generating documentation sites. + const generators = new Generators(); + const techdocsGenerator = new TechdocsGenerator(logger, config); + generators.register('techdocs', techdocsGenerator); + + // Publishers are used for + // 1. Publishing generated files to storage + // 2. Fetching files from storage and passing them to TechDocs frontend. + const publisher = Publisher.fromConfig(config, logger, discovery); + + // Docker client used by the generators. + const dockerClient = new Docker(); + + return await createRouter({ + preparers, + generators, + publisher, + dockerClient, + logger, + config, + discovery, + }); +} +``` + +You may need to install the `dockerode` package. But you may already have it in +your backend since Scaffolder plugin also uses it. + +See [Concepts](concepts.md) and [TechDocs Architecture](architecture.md) to +learn more about how preparers, generators and publishers work. + +Final step is to import the techdocs backend plugin in Backstage app backend. +Add the following to your `packages/backend/src/index.ts`: + +```typescript +import techdocs from './plugins/techdocs'; + +// .... main should already be present. +async function main() { + // ... other backend plugin envs + const techdocsEnv = useHotMemoize(module, () => createEnv('techdocs')); + + // ... other backend plugin routes + apiRouter.use('/techdocs', await techdocs(techdocsEnv)); +} +``` + +That's it! TechDocs frontend and backend have now been added to your Backstage +app. Now let us tweak some configurations to suit your needs. + +## Setting the configuration + +**See [TechDocs Configuration Options](configuration.md) for complete +configuration reference.** + +### Setting TechDocs URLs ```yaml techdocs: @@ -61,17 +165,54 @@ techdocs: requestUrl: http://localhost:7000/api/techdocs/ ``` -If you want `techdocs-backend` to manage building and publishing, you want -`requestUrl` to point to the default value (or wherever `techdocs-backend` is -hosted). `storageUrl` should be where your publisher publishes your docs. Using -the default `LocalPublish` that is the default value. +`requestUrl` is used by TechDocs frontend plugin to discover techdocs-backend +endpoints, and the `storageUrl` is another endpoint in `techdocs-backend` which +acts as a middleware between TechDocs and the storage (where the static +generated docs site are stored). These default values should mostly work for +you. These options will soon be optional to set. -If you have a setup where you are not using `techdocs-backend` for managing -building and publishing of your documentation, you want to change the -`requestUrl` to point to your storage. In this case `storageUrl` is not -required. +### Should Backstage generate docs? -### Disable Docker in Docker situation (Optional) +```yaml +techdocs: + storageUrl: http://localhost:7000/api/techdocs/static/docs + requestUrl: http://localhost:7000/api/techdocs/ + builder: 'local' +``` + +Set `techdocs.builder` to `'local'` if you want your Backstage app to be +responsible for generating documentation sites. If set to `'external'`, +Backstage will assume that the sites are being generated on each entity's CI/CD +pipeline, and are being stored in a storage somewhere. + +When `techdocs.builder` is set to `'external'`, TechDocs becomes more or less a +read-only experience where it serves static files from a storage containing all +the generated documentation. Read more in the "Basic" and "Recommended" setup of +TechDocs [here](architecture.md) + +### Choosing storage (publisher) + +TechDocs needs to know where to store generated documentation sites and where to +fetch the sites from. This is managed by a +[Publisher](./concepts.md#techdocs-publisher). Examples: Google Cloud Storage, +Amazon S3, or local filesystem of Backstage server. + +It is okay to use the local filesystem in a "Basic" setup when you are trying +out Backstage for the first time. Using Cloud Storage is documented +[here](./using-cloud-storage.md). + +```yaml +techdocs: + storageUrl: http://localhost:7000/api/techdocs/static/docs + requestUrl: http://localhost:7000/api/techdocs/ + builder: 'local' + publisher: + type: 'local' +``` + +### Disabling Docker in Docker situation (Optional) + +You can skip this if your `techdocs.builder` is set to `'external'`. The TechDocs backend plugin runs a docker container with mkdocs installed to generate the frontend of the docs from source files (Markdown). If you are @@ -110,21 +251,11 @@ Python packages. ## Run Backstage locally -Change folder to `/packages/backend` and run the -following command: +Start the frontend and the backend app by +[running backstage locally](../../getting-started/running-backstage-locally.md). -```bash -yarn start -``` - -Open a new command line window. Change directory to your Backstage application -root and run the following command: - -```bash -yarn start -``` - -Open your browser at [http://localhost:3000/docs/](http://localhost:3000/docs/). +Open your browser at [http://localhost:3000/docs/](http://localhost:3000/docs/) +to see all your documentation sites. ## Additional reading diff --git a/docs/features/techdocs/using-cloud-storage.md b/docs/features/techdocs/using-cloud-storage.md index 55352b6c00..c7b5ec9a9f 100644 --- a/docs/features/techdocs/using-cloud-storage.md +++ b/docs/features/techdocs/using-cloud-storage.md @@ -40,7 +40,7 @@ techdocs: publisher: type: 'googleGcs' googleGcs: - projectId: 'gcp-project-id + projectId: 'gcp-project-id' ``` **3. Service account API key** @@ -76,7 +76,7 @@ Create a dedicated bucket for TechDocs sites. techdocs-backend will publish documentation to this bucket. TechDocs will fetch files from here to serve documentation in Backstage. -Set the name of the bucket to `techdocs.publisher +Set the name of the bucket to `techdocs.publisher.googleGcs.bucketName`. ```yaml techdocs: diff --git a/packages/backend/src/plugins/techdocs.ts b/packages/backend/src/plugins/techdocs.ts index 4720b2568e..4822de9c5c 100644 --- a/packages/backend/src/plugins/techdocs.ts +++ b/packages/backend/src/plugins/techdocs.ts @@ -32,10 +32,7 @@ export default async function createPlugin({ discovery, reader, }: PluginEnvironment) { - const generators = new Generators(); - const techdocsGenerator = new TechdocsGenerator(logger, config); - generators.register('techdocs', techdocsGenerator); - + // Preparers are responsible for fetching source files for documentation. const preparers = new Preparers(); const directoryPreparer = new DirectoryPreparer(logger); @@ -49,8 +46,17 @@ export default async function createPlugin({ const urlPreparer = new UrlPreparer(reader, logger); preparers.register('url', urlPreparer); + // Generators are used for generating documentation sites. + const generators = new Generators(); + const techdocsGenerator = new TechdocsGenerator(logger, config); + generators.register('techdocs', techdocsGenerator); + + // Publishers are used for + // 1. Publishing generated files to storage + // 2. Fetching files from storage and passing them to TechDocs frontend. const publisher = Publisher.fromConfig(config, logger, discovery); + // Docker client used by the generators. const dockerClient = new Docker(); return await createRouter({ From f8b58228ac81705f9acbecba61024433d6ada84d Mon Sep 17 00:00:00 2001 From: Lee Mills Date: Tue, 15 Dec 2020 09:11:25 +0100 Subject: [PATCH 22/98] Update roadmap.md Fix duplicate bullet --- docs/overview/roadmap.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/overview/roadmap.md b/docs/overview/roadmap.md index ae715e301f..500b0fecae 100644 --- a/docs/overview/roadmap.md +++ b/docs/overview/roadmap.md @@ -72,9 +72,9 @@ guidelines to get started. needed. - **Inter Plugin Communication** - **[Under consideration]** Establish more clearly defined patterns for plugins to communicate. -Improved Access Control - [Under consideration] Provide finer grained access controls and management making it possible for you to better control the platforms user experience. -- **Improved Access Control** - **[Under consideration]** Provide finer grained access controls and management making it possible for you to better control the platforms user experience. +- **Improved Access Control** - **[Under consideration]** Provide finer grained access controls and management making it possible for you to better control the platforms user experience. + ### Plugins Building and maintaining [plugins](https://backstage.io/plugins) is the work of From bc899c13eb36d6aefe784f818d775bb8e6a2db0d Mon Sep 17 00:00:00 2001 From: Lee Mills Date: Tue, 15 Dec 2020 09:56:52 +0100 Subject: [PATCH 23/98] adding composable to vocab.txt --- .github/styles/vocab.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index 3b7e2a9e2d..8ae06b7ec7 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -35,6 +35,7 @@ Codecov codehilite Codehilite codeowners +composable config Config configmaps From 05651c14315aba13951c8d728d4a5a855a08cb89 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 15 Dec 2020 10:00:43 +0100 Subject: [PATCH 24/98] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw --- docs/cli/commands.md | 12 ++++++------ docs/cli/index.md | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/cli/commands.md b/docs/cli/commands.md index dc226c6e2e..6e814406ef 100644 --- a/docs/cli/commands.md +++ b/docs/cli/commands.md @@ -19,7 +19,7 @@ indicates where the command should be used by selecting from the following list: ## help -This command displays you a help summary or detailed help screens for each +This command displays a help summary or detailed help screens for each command. Below is a cleaned up output of `yarn backstage-cli --help`. ```text @@ -69,7 +69,7 @@ The command also reads and injects static configuration into the bundle. It is important to note that when deploying using your own static content hosting solution, this will be the final configuration used in the frontend unless you for example hook in configuration loading from the backend. When using the -`nginx` image in this repo along with its included run script, `APP_CONFIG_` +`nginx` based Dockerfile in this repo along with its included run script, `APP_CONFIG_` environment variables will be injected into the frontend, and when serving using the `app-backend` plugin, the configuration is completely injected from the backend and the configuration at the time of calling this command will not be @@ -229,7 +229,7 @@ Options: Scope: `backend`, `backend-plugin` Starts a backend package in development mode, with watch mode enabled for all -local packages. +local dependencies. ```text Usage: backstage-cli backend:dev [options] @@ -366,7 +366,7 @@ Scope: `any` Lint a package. In addition to the default `eslint` behavior, this command will include TypeScript files, treat warnings as errors, and default to linting the -entire directory of no specific files are listed. +entire directory if no specific files are listed. ```text Usage: backstage-cli lint [options] @@ -393,7 +393,7 @@ location. If needed, the configuration can be extended using a `"jest"` field in `package.json`, both within the target package and the monorepo root, with configuration in the target package taking precedence. Refer to the -[Jest configuration](https://jestjs.io/docs/en/configuration) for a full list of +[Jest configuration documentation](https://jestjs.io/docs/en/configuration) for a full list of configuration options. In addition to the Jest configuration there's an optional `transformModules` @@ -461,7 +461,7 @@ Options: Scope: `root` -Bump all `@backstage` packages to the latest versions. This check for updates in +Bump all `@backstage` packages to the latest versions. This checks for updates in the package registry, and will update entries both in `yarn.lock` and `package.json` files when necessary. diff --git a/docs/cli/index.md b/docs/cli/index.md index 4a60a1bf1b..9e5954f839 100644 --- a/docs/cli/index.md +++ b/docs/cli/index.md @@ -72,8 +72,8 @@ CLI can therefore easily be replaced with other tools if necessary. Just like `react-scripts`, the Backstage CLI does not provide many hooks for overriding or customizing the build process. This is to allow for evolution of -the CLI without having to take a wide API surface into account. Allowing us to -quickly iterate and improve the tooling, as well more easily keep dependencies +the CLI without having to take a wide API surface into account. This allows us to +quickly iterate and improve the tooling, as well as to more easily keep dependencies up to date. ## Opinions & Goals From 7a43e613d425dab7be75adb927fa1b66e24e940f Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 15 Dec 2020 10:02:25 +0100 Subject: [PATCH 25/98] chore: prettier roadmap --- docs/overview/roadmap.md | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/docs/overview/roadmap.md b/docs/overview/roadmap.md index 500b0fecae..a75c000b8a 100644 --- a/docs/overview/roadmap.md +++ b/docs/overview/roadmap.md @@ -48,32 +48,38 @@ guidelines to get started. ### Ongoing work 🚧 - **[Backstage platform is stable](https://github.com/backstage/backstage/milestone/19)** - - The core of Backstage and its features are stable and can be depended on for production use. After this plugins will require little to no maintenance. + The core of Backstage and its features are stable and can be depended on for + production use. After this plugins will require little to no maintenance. - **[Improved Kubernetes plugin](https://github.com/backstage/backstage/issues/2857)** - Native support for Kubernetes, making it easier for developers to see and manage their services running in k8s. -- **Global search** - - Extend the basic search available in the Backstage Service Catalog with a - global search experience. +- **Global search** - Extend the basic search available in the Backstage Service + Catalog with a global search experience. - **[Software Templates V2](https://github.com/backstage/backstage/issues/2771)** - - Expanding the templates to make steps more composable, by adding the ability to add more steps for custom logic like webhooks and using authorization from integrations. + Expanding the templates to make steps more composable, by adding the ability + to add more steps for custom logic like webhooks and using authorization from + integrations. ### Future work 🔮 -- **Golden Path for Plugin Development** - - Creating an easy, standardized way for developers to build plugins will encourage contributions and lead to a richer ecosystem for everyone. +- **Golden Path for Plugin Development** - Creating an easy, standardized way + for developers to build plugins will encourage contributions and lead to a + richer ecosystem for everyone. -- **[GraphQL API](https://github.com/backstage/backstage/milestone/13)** - - A GraphQL API will open up the rich metadata provided by Backstage in a single +- **[GraphQL API](https://github.com/backstage/backstage/milestone/13)** - A + GraphQL API will open up the rich metadata provided by Backstage in a single query. Plugins can easily query this API as well as extend the model where needed. -- **Inter Plugin Communication** - **[Under consideration]** Establish more clearly defined patterns for plugins to communicate. +- **Inter Plugin Communication** - **[Under consideration]** Establish more + clearly defined patterns for plugins to communicate. -- **Improved Access Control** - **[Under consideration]** Provide finer grained access controls and management making it possible for you to better control the platforms user experience. +- **Improved Access Control** - **[Under consideration]** Provide finer grained + access controls and management making it possible for you to better control + the platforms user experience. ### Plugins @@ -90,11 +96,13 @@ Are you missing a plugin for your favorite tool? Please Chances are that someone will jump in and help build it. ### Community Initiatives 🧑‍🤝‍🧑 (Coming soon) -- **Backstage Monthly Meetup** - -A space for the community to come together to share and learn about the latest happenings in Backstage. -- **Backstage Hackathons** - -Open to everyone in our Backstage community, a celebration of you, the project and building awesome things together +- **Backstage Monthly Meetup** - A space for the community to come together to + share and learn about the latest happenings in Backstage. + +- **Backstage Hackathons** - Open to everyone in our Backstage community, a + celebration of you, the project and building awesome things together + ### Completed milestones ✅ - [Deploy a product demo at `demo.backstage.io`](https://demo.backstage.io) From 15dce70a5d508cee660f5a6e2642e8c0573892c0 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 15 Dec 2020 10:16:57 +0100 Subject: [PATCH 26/98] docs/cli: review updates --- docs/cli/commands.md | 34 ++++++++++++++++------------------ docs/cli/index.md | 6 +++--- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/docs/cli/commands.md b/docs/cli/commands.md index 6e814406ef..c505bf8ae7 100644 --- a/docs/cli/commands.md +++ b/docs/cli/commands.md @@ -19,8 +19,8 @@ indicates where the command should be used by selecting from the following list: ## help -This command displays a help summary or detailed help screens for each -command. Below is a cleaned up output of `yarn backstage-cli --help`. +This command displays a help summary or detailed help screens for each command. +Below is a cleaned up output of `yarn backstage-cli --help`. ```text app:build Build an app for a production release @@ -69,11 +69,11 @@ The command also reads and injects static configuration into the bundle. It is important to note that when deploying using your own static content hosting solution, this will be the final configuration used in the frontend unless you for example hook in configuration loading from the backend. When using the -`nginx` based Dockerfile in this repo along with its included run script, `APP_CONFIG_` -environment variables will be injected into the frontend, and when serving using -the `app-backend` plugin, the configuration is completely injected from the -backend and the configuration at the time of calling this command will not be -used. +`nginx` based Dockerfile in this repo along with its included run script, +`APP_CONFIG_` environment variables will be injected into the frontend, and when +serving using the `app-backend` plugin, the configuration is completely injected +from the backend and the configuration at the time of calling this command will +not be used. Note that even when injecting configuration at runtime, it is not possible to change the base path of the app. For example, if you at build time have @@ -97,9 +97,10 @@ process.env.BUILD_INFO = { Some CI environments do not properly report correct resource limits, potentially leading to errors such as `ENOMEM` during compilation. If you run into this issue you can limit the parallelization of the build process by setting the -environment variable `BACKSTAGE_CLI_BUILD_PARALLEL`. You can set it to `false` -or `1` to completely disable parallelization, but usually a low value such as -`2` is enough. +environment variable `BACKSTAGE_CLI_BUILD_PARALLEL`, which is forwarded to the +[`terser-webpack-plugin`](https://github.com/webpack-contrib/terser-webpack-plugin#parallel). +You can set it to `false` or `1` to completely disable parallelization, but +usually a low value such as `2` is enough. ```text Usage: backstage-cli app:build @@ -165,8 +166,7 @@ Options: ## backend:build -Scope: `backend`, `backend-plugin` (To be replaced by `backend:bundle` for -`backend`) +Scope: `backend`, `backend-plugin` This builds a backend package for publishing and use in production. The build output is written to `dist/`. Be sure to list any additional file that the @@ -393,8 +393,8 @@ location. If needed, the configuration can be extended using a `"jest"` field in `package.json`, both within the target package and the monorepo root, with configuration in the target package taking precedence. Refer to the -[Jest configuration documentation](https://jestjs.io/docs/en/configuration) for a full list of -configuration options. +[Jest configuration documentation](https://jestjs.io/docs/en/configuration) for +a full list of configuration options. In addition to the Jest configuration there's an optional `transformModules` option, which is an array of module names to include in transformations. @@ -461,8 +461,8 @@ Options: Scope: `root` -Bump all `@backstage` packages to the latest versions. This checks for updates in -the package registry, and will update entries both in `yarn.lock` and +Bump all `@backstage` packages to the latest versions. This checks for updates +in the package registry, and will update entries both in `yarn.lock` and `package.json` files when necessary. ```text @@ -556,6 +556,4 @@ the resulting archive in the target `workspace-dir`. ```text Usage: backstage-cli build-workspace [options] <workspace-dir> - -Options: ``` diff --git a/docs/cli/index.md b/docs/cli/index.md index 9e5954f839..1b2e01be62 100644 --- a/docs/cli/index.md +++ b/docs/cli/index.md @@ -72,9 +72,9 @@ CLI can therefore easily be replaced with other tools if necessary. Just like `react-scripts`, the Backstage CLI does not provide many hooks for overriding or customizing the build process. This is to allow for evolution of -the CLI without having to take a wide API surface into account. This allows us to -quickly iterate and improve the tooling, as well as to more easily keep dependencies -up to date. +the CLI without having to take a wide API surface into account. This allows us +to quickly iterate and improve the tooling, as well as to more easily keep +dependencies up to date. ## Opinions & Goals From ef63d159dfb13f4948d89105f24713270d28d137 Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Tue, 15 Dec 2020 11:27:38 +0100 Subject: [PATCH 27/98] docs: 1. Techdocs Backend everywhere 2. TechDocs Backend instead Backstage 3. Link to scaffolder --- docs/features/techdocs/getting-started.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/features/techdocs/getting-started.md b/docs/features/techdocs/getting-started.md index b9ba5bcf4f..0437f3ca47 100644 --- a/docs/features/techdocs/getting-started.md +++ b/docs/features/techdocs/getting-started.md @@ -54,7 +54,7 @@ const AppRoutes = () => { That's it! But now, we need the TechDocs Backend plugin for the frontend to work. -## Adding TechDocs backend plugin +## Adding TechDocs Backend plugin Navigate to `packages/backend` of your Backstage app, and install the `@backstage/plugin-techdocs-backend` package. @@ -128,7 +128,8 @@ export default async function createPlugin({ ``` You may need to install the `dockerode` package. But you may already have it in -your backend since Scaffolder plugin also uses it. +your backend since [Scaffolder plugin](../software-templates/index.md) also uses +it. See [Concepts](concepts.md) and [TechDocs Architecture](architecture.md) to learn more about how preparers, generators and publishers work. @@ -171,7 +172,7 @@ acts as a middleware between TechDocs and the storage (where the static generated docs site are stored). These default values should mostly work for you. These options will soon be optional to set. -### Should Backstage generate docs? +### Should TechDocs Backend generate docs? ```yaml techdocs: @@ -180,7 +181,7 @@ techdocs: builder: 'local' ``` -Set `techdocs.builder` to `'local'` if you want your Backstage app to be +Set `techdocs.builder` to `'local'` if you want your TechDocs Backend to be responsible for generating documentation sites. If set to `'external'`, Backstage will assume that the sites are being generated on each entity's CI/CD pipeline, and are being stored in a storage somewhere. @@ -214,10 +215,10 @@ techdocs: You can skip this if your `techdocs.builder` is set to `'external'`. -The TechDocs backend plugin runs a docker container with mkdocs installed to +The TechDocs Backend plugin runs a docker container with mkdocs installed to generate the frontend of the docs from source files (Markdown). If you are deploying Backstage using Docker, this will mean that your Backstage Docker -container will try to run another Docker container for TechDocs backend. +container will try to run another Docker container for TechDocs Backend. To avoid this problem, we have a configuration available. You can set a value in your `app-config.yaml` that tells the techdocs generator if it should run the From 354686239909b38d8d872a1d8defbcb40c5f42a5 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 15 Dec 2020 13:22:17 +0100 Subject: [PATCH 28/98] chore: update git-url-parse dependency --- packages/backend-common/package.json | 2 +- packages/integration/package.json | 2 +- packages/techdocs-common/package.json | 2 +- plugins/catalog-backend/package.json | 2 +- plugins/catalog-import/package.json | 2 +- plugins/catalog/package.json | 2 +- plugins/scaffolder-backend/package.json | 2 +- yarn.lock | 8 ++++---- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 02b7e6e836..395183104d 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -43,7 +43,7 @@ "express": "^4.17.1", "express-promise-router": "^3.0.3", "fs-extra": "^9.0.1", - "git-url-parse": "^11.4.0", + "git-url-parse": "^11.4.3", "helmet": "^4.0.0", "knex": "^0.21.6", "lodash": "^4.17.15", diff --git a/packages/integration/package.json b/packages/integration/package.json index 78112de311..3c241fee89 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -31,7 +31,7 @@ "dependencies": { "@backstage/config": "^0.1.2", "cross-fetch": "^3.0.6", - "git-url-parse": "^11.4.0" + "git-url-parse": "^11.4.3" }, "devDependencies": { "@backstage/cli": "^0.4.1", diff --git a/packages/techdocs-common/package.json b/packages/techdocs-common/package.json index 4bda9f768a..adb138bdd9 100644 --- a/packages/techdocs-common/package.json +++ b/packages/techdocs-common/package.json @@ -46,7 +46,7 @@ "dockerode": "^3.2.1", "express": "^4.17.1", "fs-extra": "^9.0.1", - "git-url-parse": "^11.4.0", + "git-url-parse": "^11.4.3", "js-yaml": "^3.14.0", "mock-fs": "^4.13.0", "nodegit": "^0.27.0", diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 1a5b24f64c..180956c986 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -42,7 +42,7 @@ "express": "^4.17.1", "express-promise-router": "^3.0.3", "fs-extra": "^9.0.0", - "git-url-parse": "^11.4.0", + "git-url-parse": "^11.4.3", "knex": "^0.21.6", "ldapjs": "^2.2.0", "lodash": "^4.17.15", diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 6eb744cea4..e2ddf0101e 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -40,7 +40,7 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", "@octokit/rest": "^18.0.6", - "git-url-parse": "^11.4.0", + "git-url-parse": "^11.4.3", "react": "^16.13.1", "react-dom": "^16.13.1", "react-hook-form": "^6.6.0", diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index ad9cff8ed8..924115eb82 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -41,7 +41,7 @@ "@material-ui/lab": "4.0.0-alpha.45", "@types/react": "^16.9", "classnames": "^2.2.6", - "git-url-parse": "^11.4.0", + "git-url-parse": "^11.4.3", "moment": "^2.26.0", "react": "^16.13.1", "react-dom": "^16.13.1", diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index edf0a46a25..50bddaaf41 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -45,7 +45,7 @@ "express": "^4.17.1", "express-promise-router": "^3.0.3", "fs-extra": "^9.0.0", - "git-url-parse": "^11.4.0", + "git-url-parse": "^11.4.3", "globby": "^11.0.0", "helmet": "^4.0.0", "jsonschema": "^1.2.6", diff --git a/yarn.lock b/yarn.lock index d4491ff0ad..77689961e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13252,10 +13252,10 @@ git-url-parse@^11.1.2: dependencies: git-up "^4.0.0" -git-url-parse@^11.4.0: - version "11.4.0" - resolved "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.4.0.tgz#f2bb1f2b00f05552540e95a62e31399a639a6aa6" - integrity sha512-KlIa5jvMYLjXMQXkqpFzobsyD/V2K5DRHl5OAf+6oDFPlPLxrGDVQlIdI63c4/Kt6kai4kALENSALlzTGST3GQ== +git-url-parse@^11.4.3: + version "11.4.3" + resolved "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.4.3.tgz#1610284edf1f14964180f5b3399ec68b692cfd87" + integrity sha512-LZTTk0nqJnKN48YRtOpR8H5SEfp1oM2tls90NuZmBxN95PnCvmuXGzqQ4QmVirBgKx2KPYfPGteX3/raWjKenQ== dependencies: git-up "^4.0.0" From 541bd0e97c3da00262a49d92e23d9dc7e434f760 Mon Sep 17 00:00:00 2001 From: Peter Colapietro Date: Mon, 14 Dec 2020 09:58:36 -0500 Subject: [PATCH 29/98] feat(storybook): upgrade to 6.1.11 see: https://github.com/storybookjs/storybook/releases/tag/v6.1.11 --- packages/storybook/.storybook/main.js | 2 +- packages/storybook/package.json | 12 +- yarn.lock | 1175 ++++++++++++------------- 3 files changed, 551 insertions(+), 638 deletions(-) diff --git a/packages/storybook/.storybook/main.js b/packages/storybook/.storybook/main.js index 136b3945da..77bafdd231 100644 --- a/packages/storybook/.storybook/main.js +++ b/packages/storybook/.storybook/main.js @@ -22,7 +22,7 @@ module.exports = { // Remove the default babel-loader for js files, we're using sucrase instead const [jsLoader] = config.module.rules.splice(0, 1); - if (jsLoader.use[0].loader !== 'babel-loader') { + if (!jsLoader.use[0].loader.includes('babel-loader')) { throw new Error( `Unexpected loader removed from storybook config, ${jsLoader.use[0].loader}`, ); diff --git a/packages/storybook/package.json b/packages/storybook/package.json index f143596a9a..01aabac0de 100644 --- a/packages/storybook/package.json +++ b/packages/storybook/package.json @@ -17,11 +17,11 @@ "@backstage/theme": "^0.2.0" }, "devDependencies": { - "@storybook/addon-actions": "^6.0.21", - "@storybook/addon-links": "^6.0.21", - "@storybook/addon-storysource": "^6.0.21", - "@storybook/addons": "^6.0.21", - "@storybook/react": "^6.0.21", - "storybook-dark-mode": "^1.0.2" + "@storybook/addon-actions": "^6.1.11", + "@storybook/addon-links": "^6.1.11", + "@storybook/addon-storysource": "^6.1.11", + "@storybook/addons": "^6.1.11", + "@storybook/react": "^6.1.11", + "storybook-dark-mode": "^1.0.3" } } diff --git a/yarn.lock b/yarn.lock index d4491ff0ad..021ab60896 100644 --- a/yarn.lock +++ b/yarn.lock @@ -196,6 +196,13 @@ dependencies: "@babel/types" "^7.10.4" +"@babel/helper-annotate-as-pure@^7.12.10": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz#54ab9b000e60a93644ce17b3f37d313aaf1d115d" + integrity sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ== + dependencies: + "@babel/types" "^7.12.10" + "@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": version "7.10.4" resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" @@ -213,6 +220,15 @@ "@babel/helper-module-imports" "^7.10.4" "@babel/types" "^7.10.5" +"@babel/helper-builder-react-jsx-experimental@^7.12.10": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.12.10.tgz#a58cb96a793dc0fcd5c9ed3bb36d62fdc60534c2" + integrity sha512-3Kcr2LGpL7CTRDTTYm1bzeor9qZbxbvU2AxsLA6mUG9gYarSfIKMK0UlU+azLWI+s0+BH768bwyaziWB2NOJlQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.12.10" + "@babel/helper-module-imports" "^7.12.5" + "@babel/types" "^7.12.10" + "@babel/helper-builder-react-jsx-experimental@^7.12.4": version "7.12.4" resolved "https://registry.npmjs.org/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.12.4.tgz#55fc1ead5242caa0ca2875dcb8eed6d311e50f48" @@ -240,7 +256,7 @@ browserslist "^4.14.5" semver "^5.5.0" -"@babel/helper-create-class-features-plugin@^7.10.4", "@babel/helper-create-class-features-plugin@^7.10.5": +"@babel/helper-create-class-features-plugin@^7.10.4": version "7.10.5" resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" integrity sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A== @@ -532,7 +548,7 @@ "@babel/helper-remap-async-to-generator" "^7.12.1" "@babel/plugin-syntax-async-generators" "^7.8.0" -"@babel/plugin-proposal-class-properties@^7.0.0", "@babel/plugin-proposal-class-properties@^7.8.3": +"@babel/plugin-proposal-class-properties@^7.0.0": version "7.10.4" resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz#a33bf632da390a59c7a8c570045d1115cd778807" integrity sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg== @@ -548,14 +564,14 @@ "@babel/helper-create-class-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-proposal-decorators@^7.8.3": - version "7.10.5" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.10.5.tgz#42898bba478bc4b1ae242a703a953a7ad350ffb4" - integrity sha512-Sc5TAQSZuLzgY0664mMDn24Vw2P8g/VhyLyGPaWiHahhgLqeZvcGeyBZOrJW0oSKIK2mvQ22a1ENXBIQLhrEiQ== +"@babel/plugin-proposal-decorators@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.12.1.tgz#59271439fed4145456c41067450543aee332d15f" + integrity sha512-knNIuusychgYN8fGJHONL0RbFxLGawhXOJNLBk75TniTsZZeA+wdkDuv6wp4lGwzQEKjZi6/WYtnb3udNPmQmQ== dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.5" + "@babel/helper-create-class-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-decorators" "^7.10.4" + "@babel/plugin-syntax-decorators" "^7.12.1" "@babel/plugin-proposal-dynamic-import@^7.12.1": version "7.12.1" @@ -565,13 +581,13 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" -"@babel/plugin-proposal-export-default-from@^7.8.3": - version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.10.4.tgz#08f66eef0067cbf6a7bc036977dcdccecaf0c6c5" - integrity sha512-G1l00VvDZ7Yk2yRlC5D8Ybvu3gmeHS3rCHoUYdjrqGYUtdeOBoRypnvDZ5KQqxyaiiGHWnVDeSEzA5F9ozItig== +"@babel/plugin-proposal-export-default-from@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.12.1.tgz#c6e62d668a8abcfe0d28b82f560395fecb611c5a" + integrity sha512-z5Q4Ke7j0AexQRfgUvnD+BdCSgpTEKnqQ3kskk2jWtOBulxICzd1X9BGt7kmWftxZ2W3++OZdt5gtmC8KLxdRQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-export-default-from" "^7.10.4" + "@babel/plugin-syntax-export-default-from" "^7.12.1" "@babel/plugin-proposal-export-namespace-from@^7.12.1": version "7.12.1" @@ -597,14 +613,6 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.10.1": - version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz#02a7e961fc32e6d5b2db0649e01bf80ddee7e04a" - integrity sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - "@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1": version "7.12.1" resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz#3ed4fff31c015e7f3f1467f190dbe545cd7b046c" @@ -621,7 +629,7 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@^7.0.0", "@babel/plugin-proposal-object-rest-spread@^7.9.6": +"@babel/plugin-proposal-object-rest-spread@^7.0.0": version "7.11.0" resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz#bd81f95a1f746760ea43b6c2d3d62b11790ad0af" integrity sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA== @@ -647,16 +655,7 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.10.1": - version "7.11.0" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz#de5866d0646f6afdaab8a566382fe3a221755076" - integrity sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - -"@babel/plugin-proposal-optional-chaining@^7.12.7": +"@babel/plugin-proposal-optional-chaining@^7.12.1", "@babel/plugin-proposal-optional-chaining@^7.12.7": version "7.12.7" resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz#e02f0ea1b5dc59d401ec16fb824679f683d3303c" integrity sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA== @@ -673,14 +672,6 @@ "@babel/helper-create-class-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-proposal-private-methods@^7.8.3": - version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz#b160d972b8fdba5c7d111a145fc8c421fc2a6909" - integrity sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-proposal-unicode-property-regex@^7.12.1": version "7.12.1" resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz#2a183958d417765b9eae334f47758e5d6a82e072" @@ -725,10 +716,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-decorators@^7.10.4": - version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.10.4.tgz#6853085b2c429f9d322d02f5a635018cdeb2360c" - integrity sha512-2NaoC6fAk2VMdhY1eerkfHV+lVYC1u8b+jmRJISqANCJlTxYy19HGdIkkQtix2UtkcPuPu+IlDgrVseZnU03bw== +"@babel/plugin-syntax-decorators@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.12.1.tgz#81a8b535b284476c41be6de06853a8802b98c5dd" + integrity sha512-ir9YW5daRrTYiy9UJ2TzdNIJEZu8KclVzDcfSt4iEmOtwQ4llPtWInNKJyKnVXp1vE4bbVd5S31M/im3mYMO1w== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -739,10 +730,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-export-default-from@^7.10.4": - version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.10.4.tgz#e5494f95006355c10292a0ff1ce42a5746002ec8" - integrity sha512-79V6r6Pgudz0RnuMGp5xidu6Z+bPFugh8/Q9eDHonmLp4wKFAZDwygJwYgCzuDu8lFA/sYyT+mc5y2wkd7bTXA== +"@babel/plugin-syntax-export-default-from@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.12.1.tgz#a9eb31881f4f9a1115a3d2c6d64ac3f6016b5a9d" + integrity sha512-dP5eGg6tHEkhnRD2/vRG/KJKRSg8gtxu2i+P/8/yFPJn/CfPU5G0/7Gks2i3M6IOVAPQekmsLN9LPsmXFFL4Uw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -760,12 +751,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-flow@^7.8.3": - version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.8.3.tgz#f2c883bd61a6316f2c89380ae5122f923ba4527f" - integrity sha512-innAx3bUbA0KSYj2E2MNFSn9hiCeowOFLxlsuhXzw8hMQnzkDomUr9QCD7E9VF60NmnG1sNTuuv6Qf4f8INYsg== +"@babel/plugin-syntax-flow@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.12.1.tgz#a77670d9abe6d63e8acadf4c31bb1eb5a506bbdd" + integrity sha512-1lBLLmtxrwpm4VKmtVFselI/P3pX+G63fAtUUt6b2Nzgao77KNDwyuRt90Mj2/9pKobtt68FdvjfqohZjg/FCA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" @@ -851,14 +842,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-typescript@^7.10.4": - version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.10.4.tgz#2f55e770d3501e83af217d782cb7517d7bb34d25" - integrity sha512-oSAEz1YkBCAKr5Yiq8/BNtvSAPwkp/IyUnwZogd8p+F0RuYQQrLeRUzIQhueQTTBy/F+a40uS7OFKxnkRvmvFQ== +"@babel/plugin-syntax-typescript@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.12.1.tgz#460ba9d77077653803c3dd2e673f76d66b4029e5" + integrity sha512-UZNEcCY+4Dp9yYRCAHrHDU+9ZXLYaY9MgBXSRLkB9WjYFRR6quJBumfVrEkUxrePPBwFcpWfNKXqVRQQtm7mMA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-arrow-functions@^7.0.0", "@babel/plugin-transform-arrow-functions@^7.8.3": +"@babel/plugin-transform-arrow-functions@^7.0.0": version "7.10.4" resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd" integrity sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA== @@ -895,7 +886,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-block-scoping@^7.0.0", "@babel/plugin-transform-block-scoping@^7.8.3": +"@babel/plugin-transform-block-scoping@^7.0.0": version "7.11.1" resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz#5b7efe98852bef8d652c0b28144cd93a9e4b5215" integrity sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew== @@ -909,7 +900,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-classes@^7.0.0", "@babel/plugin-transform-classes@^7.9.5": +"@babel/plugin-transform-classes@^7.0.0": version "7.10.4" resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz#405136af2b3e218bc4a1926228bc917ab1a0adc7" integrity sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA== @@ -951,7 +942,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-destructuring@^7.0.0", "@babel/plugin-transform-destructuring@^7.9.5": +"@babel/plugin-transform-destructuring@^7.0.0": version "7.10.4" resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz#70ddd2b3d1bea83d01509e9bb25ddb3a74fc85e5" integrity sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA== @@ -1004,15 +995,15 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-flow" "^7.10.4" -"@babel/plugin-transform-flow-strip-types@^7.9.0": - version "7.9.0" - resolved "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.9.0.tgz#8a3538aa40434e000b8f44a3c5c9ac7229bd2392" - integrity sha512-7Qfg0lKQhEHs93FChxVLAvhBshOPQDtJUTVHr/ZwQNRccCm4O9D79r9tVSoV8iNwjP1YgfD+e/fgHcPkN1qEQg== +"@babel/plugin-transform-flow-strip-types@^7.12.1": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.12.10.tgz#d85e30ecfa68093825773b7b857e5085bbd32c95" + integrity sha512-0ti12wLTLeUIzu9U7kjqIn4MyOL7+Wibc7avsHhj4o1l5C0ATs8p2IMHrVYjm9t9wzhfEO6S3kxax0Rpdo8LTg== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-flow" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-flow" "^7.12.1" -"@babel/plugin-transform-for-of@^7.0.0", "@babel/plugin-transform-for-of@^7.9.0": +"@babel/plugin-transform-for-of@^7.0.0": version "7.10.4" resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz#c08892e8819d3a5db29031b115af511dbbfebae9" integrity sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ== @@ -1148,7 +1139,7 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-replace-supers" "^7.12.1" -"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.10.4", "@babel/plugin-transform-parameters@^7.9.5": +"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.10.4": version "7.10.5" resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz#59d339d58d0b1950435f4043e74e2510005e2c4a" integrity sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw== @@ -1231,6 +1222,16 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-jsx" "^7.10.4" +"@babel/plugin-transform-react-jsx@^7.12.10": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.10.tgz#a7af3097c73479123594c8c8fe39545abebd44e3" + integrity sha512-MM7/BC8QdHXM7Qc1wdnuk73R4gbuOpfrSUgfV/nODGc86sPY1tgmY2M9E9uAnf2e4DOIp8aKGWqgZfQxnTNGuw== + dependencies: + "@babel/helper-builder-react-jsx" "^7.10.4" + "@babel/helper-builder-react-jsx-experimental" "^7.12.10" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.12.1" + "@babel/plugin-transform-react-jsx@^7.12.7": version "7.12.7" resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.7.tgz#8b14d45f6eccd41b7f924bcb65c021e9f0a06f7f" @@ -1263,7 +1264,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-shorthand-properties@^7.0.0", "@babel/plugin-transform-shorthand-properties@^7.8.3": +"@babel/plugin-transform-shorthand-properties@^7.0.0": version "7.10.4" resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6" integrity sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q== @@ -1277,7 +1278,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-spread@^7.0.0", "@babel/plugin-transform-spread@^7.8.3": +"@babel/plugin-transform-spread@^7.0.0": version "7.11.0" resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz#fa84d300f5e4f57752fe41a6d1b3c554f13f17cc" integrity sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw== @@ -1300,7 +1301,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-template-literals@^7.0.0", "@babel/plugin-transform-template-literals@^7.8.3": +"@babel/plugin-transform-template-literals@^7.0.0": version "7.10.5" resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz#78bc5d626a6642db3312d9d0f001f5e7639fde8c" integrity sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw== @@ -1322,14 +1323,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-typescript@^7.10.4": - version "7.11.0" - resolved "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.11.0.tgz#2b4879676af37342ebb278216dd090ac67f13abb" - integrity sha512-edJsNzTtvb3MaXQwj8403B7mZoGu9ElDJQZOKjGUnvilquxBA3IQoEIOvkX/1O8xfAsnHS/oQhe2w/IXrr+w0w== +"@babel/plugin-transform-typescript@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.12.1.tgz#d92cc0af504d510e26a754a7dbc2e5c8cd9c7ab4" + integrity sha512-VrsBByqAIntM+EYMqSm59SiMEf7qkmI9dqMt6RbD/wlwueWmYcI0FFK5Fj47pP6DRZm+3teXjosKlwcZJ5lIMw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.5" + "@babel/helper-create-class-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-typescript" "^7.10.4" + "@babel/plugin-syntax-typescript" "^7.12.1" "@babel/plugin-transform-unicode-escapes@^7.12.1": version "7.12.1" @@ -1346,7 +1347,7 @@ "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/preset-env@^7.12.1", "@babel/preset-env@^7.9.5", "@babel/preset-env@^7.9.6": +"@babel/preset-env@^7.12.1", "@babel/preset-env@^7.9.5": version "7.12.7" resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.7.tgz#54ea21dbe92caf6f10cb1a0a576adc4ebf094b55" integrity sha512-OnNdfAr1FUQg7ksb7bmbKoby4qFOHw6DKWWUNB9KqnnCldxhxJlP+21dpyaWFmf2h0rTbOkXJtAGevY3XW1eew== @@ -1418,13 +1419,13 @@ core-js-compat "^3.7.0" semver "^5.5.0" -"@babel/preset-flow@^7.0.0": - version "7.9.0" - resolved "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.9.0.tgz#fee847c3e090b0b2d9227c1949e4da1d1379280d" - integrity sha512-88uSmlshIrlmPkNkEcx3UpSZ6b8n0UGBq0/0ZMZCF/uxAW0XIAUuDHBhIOAh0pvweafH4RxOwi/H3rWhtqOYPA== +"@babel/preset-flow@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.12.1.tgz#1a81d376c5a9549e75352a3888f8c273455ae940" + integrity sha512-UAoyMdioAhM6H99qPoKvpHMzxmNVXno8GYU/7vZmGaHk6/KqfDYL1W0NxszVbJ2EP271b7e6Ox+Vk2A9QsB3Sw== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-transform-flow-strip-types" "^7.9.0" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-flow-strip-types" "^7.12.1" "@babel/preset-modules@^0.1.3": version "0.1.3" @@ -1437,7 +1438,18 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-react@^7.0.0", "@babel/preset-react@^7.12.5", "@babel/preset-react@^7.8.3", "@babel/preset-react@^7.9.4": +"@babel/preset-react@^7.12.1": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.12.10.tgz#4fed65f296cbb0f5fb09de6be8cddc85cc909be9" + integrity sha512-vtQNjaHRl4DUpp+t+g4wvTHsLQuye+n0H/wsXIZRn69oz/fvNC7gQ4IK73zGJBaxvHoxElDvnYCthMcT7uzFoQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-react-display-name" "^7.12.1" + "@babel/plugin-transform-react-jsx" "^7.12.10" + "@babel/plugin-transform-react-jsx-development" "^7.12.7" + "@babel/plugin-transform-react-pure-annotations" "^7.12.1" + +"@babel/preset-react@^7.12.5", "@babel/preset-react@^7.9.4": version "7.12.7" resolved "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.12.7.tgz#36d61d83223b07b6ac4ec55cf016abb0f70be83b" integrity sha512-wKeTdnGUP5AEYCYQIMeXMMwU7j+2opxrG0WzuZfxuuW9nhKvvALBjl67653CWamZJVefuJGI219G591RSldrqQ== @@ -1450,18 +1462,19 @@ "@babel/plugin-transform-react-jsx-source" "^7.12.1" "@babel/plugin-transform-react-pure-annotations" "^7.12.1" -"@babel/preset-typescript@^7.9.0": - version "7.10.4" - resolved "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.10.4.tgz#7d5d052e52a682480d6e2cc5aa31be61c8c25e36" - integrity sha512-SdYnvGPv+bLlwkF2VkJnaX/ni1sMNetcGI1+nThF1gyv6Ph8Qucc4ZZAjM5yZcE/AKRXIOTZz7eSRDWOEjPyRQ== +"@babel/preset-typescript@^7.12.1": + version "7.12.7" + resolved "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.12.7.tgz#fc7df8199d6aae747896f1e6c61fc872056632a3" + integrity sha512-nOoIqIqBmHBSEgBXWR4Dv/XBehtIFcw9PqZw6rFYuKrzsZmOQm3PR5siLBnKZFEsDb03IegG8nSjU/iXXXYRmw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-transform-typescript" "^7.10.4" + "@babel/helper-validator-option" "^7.12.1" + "@babel/plugin-transform-typescript" "^7.12.1" -"@babel/register@^7.10.5": - version "7.11.5" - resolved "https://registry.npmjs.org/@babel/register/-/register-7.11.5.tgz#79becf89e0ddd0fba8b92bc279bc0f5d2d7ce2ea" - integrity sha512-CAml0ioKX+kOAvBQDHa/+t1fgOt3qkTIz0TrRtRAT6XY0m5qYZXR85k6/sLCNPMGhYDlCFHCYuU0ybTJbvlC6w== +"@babel/register@^7.12.1": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/register/-/register-7.12.10.tgz#19b87143f17128af4dbe7af54c735663b3999f60" + integrity sha512-EvX/BvMMJRAA3jZgILWgbsrHwBQvllC5T8B29McyME8DvkdOxk4ujESfrMvME8IHSDvWXrmMXxPvA/lx2gqPLQ== dependencies: find-cache-dir "^2.0.0" lodash "^4.17.19" @@ -1485,7 +1498,7 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.10.4", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.10.4", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.12.5" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== @@ -1621,6 +1634,15 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" +"@babel/types@^7.12.10": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.12.10.tgz#7965e4a7260b26f09c56bcfcb0498af1f6d9b260" + integrity sha512-sf6wboJV5mGyip2hIpDSKsr80RszPinEFjsHTalMxZAZkoQ2/2yQzxlcFN52SJqsyPfLtPmenL4g2KB3KJXPDw== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + "@backstage/catalog-model@^0.2.0": version "0.5.0" dependencies: @@ -1953,7 +1975,7 @@ "@emotion/utils" "0.11.3" "@emotion/weak-memoize" "0.2.5" -"@emotion/core@^10.0.0", "@emotion/core@^10.0.20", "@emotion/core@^10.0.28": +"@emotion/core@^10.0.0", "@emotion/core@^10.0.28": version "10.0.28" resolved "https://registry.npmjs.org/@emotion/core/-/core-10.0.28.tgz#bb65af7262a234593a9e952c041d0f1c9b9bef3d" integrity sha512-pH8UueKYO5jgg0Iq+AmCLxBsvuGtvlmiDCOuv8fGNYn3cowFpLN98L8zO56U0H1PjDIyAlXymgL3Wu7u7v6hbA== @@ -1965,6 +1987,18 @@ "@emotion/sheet" "0.9.4" "@emotion/utils" "0.11.3" +"@emotion/core@^10.1.1": + version "10.1.1" + resolved "https://registry.npmjs.org/@emotion/core/-/core-10.1.1.tgz#c956c1365f2f2481960064bcb8c4732e5fb612c3" + integrity sha512-ZMLG6qpXR8x031NXD8HJqugy/AZSkAuMxxqB46pmAR7ze47MhNJ56cdoX243QPZdGctrdfo+s08yZTiwaUcRKA== + dependencies: + "@babel/runtime" "^7.5.5" + "@emotion/cache" "^10.0.27" + "@emotion/css" "^10.0.27" + "@emotion/serialize" "^0.11.15" + "@emotion/sheet" "0.9.4" + "@emotion/utils" "0.11.3" + "@emotion/css@^10.0.27": version "10.0.27" resolved "https://registry.npmjs.org/@emotion/css/-/css-10.0.27.tgz#3a7458198fbbebb53b01b2b87f64e5e21241e14c" @@ -2017,7 +2051,7 @@ "@emotion/serialize" "^0.11.15" "@emotion/utils" "0.11.3" -"@emotion/styled@^10.0.0", "@emotion/styled@^10.0.17": +"@emotion/styled@^10.0.0", "@emotion/styled@^10.0.23": version "10.0.27" resolved "https://registry.npmjs.org/@emotion/styled/-/styled-10.0.27.tgz#12cb67e91f7ad7431e1875b1d83a94b814133eaf" integrity sha512-iK/8Sh7+NLJzyp9a5+vIQIXTYxfT4yB/OJbjzQanB2RZpvmzBQOHZWhpAMZWYEKRNNbsD6WfBw5sVWkb6WzS/Q== @@ -4054,6 +4088,23 @@ resolved "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz#dd55ae7b8129e02049f009408b97c61ccf9032f6" integrity sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw== +"@pmmmwh/react-refresh-webpack-plugin@^0.4.2": + version "0.4.3" + resolved "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.4.3.tgz#1eec460596d200c0236bf195b078a5d1df89b766" + integrity sha512-br5Qwvh8D2OQqSXpd1g/xqXKnK0r+Jz6qVKBbWmpUcrbGOxUrf39V5oZ1876084CGn18uMdR5uvPqBv9UqtBjQ== + dependencies: + ansi-html "^0.0.7" + error-stack-parser "^2.0.6" + html-entities "^1.2.1" + native-url "^0.2.6" + schema-utils "^2.6.5" + source-map "^0.7.3" + +"@popperjs/core@^2.5.4": + version "2.5.4" + resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.5.4.tgz#de25b5da9f727985a3757fd59b5d028aba75841a" + integrity sha512-ZpKr+WTb8zsajqgDkvCEWgp6d5eJT6Q63Ng2neTbzBO76Lbe91vX/iVIW9dikq+Fs3yEo+ls4cxeXABD2LtcbQ== + "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" @@ -4348,265 +4399,170 @@ resolved "https://registry.npmjs.org/@spotify/prettier-config/-/prettier-config-8.0.0.tgz#8b6c2bd579ddc54887155a0721fe04e96c89f7f2" integrity sha512-so8w32ZV42CHWxOEXcBtbNO/hLXFrQNXVmhfzhUI6dVB9cq2xjRaiqu8GjFj8LvKbWpPj+S+KwTIS4aDVWqrFQ== -"@storybook/addon-actions@^6.0.21": - version "6.0.26" - resolved "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.0.26.tgz#d0de9e4d78a8f8f5bf8730c04d0b6d1741c29273" - integrity sha512-9tWbAqSwzWWVz8zwAndZFusZYjIcRYgZUC0LqC8QlH79DgF3ASjw9y97+w1VTTAzdb6LYnsMuSpX6+8m5hrR4g== +"@storybook/addon-actions@^6.1.11": + version "6.1.11" + resolved "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.1.11.tgz#73e91cc95c45ea477cfd4f3603f6b95f5829eab6" + integrity sha512-J44XLx2G732OG7Az79Cpk5UlI5SyXHeQqdykwT/4IEQXSBXAYWSTIJJjpJdcjR/D+zpklab1QDSiWxCrKbe81A== dependencies: - "@storybook/addons" "6.0.26" - "@storybook/api" "6.0.26" - "@storybook/client-api" "6.0.26" - "@storybook/components" "6.0.26" - "@storybook/core-events" "6.0.26" - "@storybook/theming" "6.0.26" + "@storybook/addons" "6.1.11" + "@storybook/api" "6.1.11" + "@storybook/client-api" "6.1.11" + "@storybook/components" "6.1.11" + "@storybook/core-events" "6.1.11" + "@storybook/theming" "6.1.11" core-js "^3.0.1" fast-deep-equal "^3.1.1" global "^4.3.2" lodash "^4.17.15" polished "^3.4.4" prop-types "^15.7.2" - react "^16.8.3" react-inspector "^5.0.1" - regenerator-runtime "^0.13.3" - ts-dedent "^1.1.1" + regenerator-runtime "^0.13.7" + ts-dedent "^2.0.0" util-deprecate "^1.0.2" uuid "^8.0.0" -"@storybook/addon-links@^6.0.21": - version "6.0.21" - resolved "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-6.0.21.tgz#6d4497933d560615617eaffeacec00ad8a788b01" - integrity sha512-5cRFxXS9BviDbS+DCKElr1vSafDcRhX74iIAWl/yOBUldUZvR+gX3WOZ7bO+OBSlQ1NJkt1NUAMag3aiJa4UUw== +"@storybook/addon-links@^6.1.11": + version "6.1.11" + resolved "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-6.1.11.tgz#84b20b0c13bbfc8270cdf52389ce52f98c415b6a" + integrity sha512-OIBeOdTHNr/egIuyOUEtEBtZJXVp9PEPQ4MDxvKsCgpnXruPhjenPNW+mQKxm4SefpePW7zkx6k1ubpYVJUeag== dependencies: - "@storybook/addons" "6.0.21" - "@storybook/client-logger" "6.0.21" - "@storybook/core-events" "6.0.21" + "@storybook/addons" "6.1.11" + "@storybook/client-logger" "6.1.11" + "@storybook/core-events" "6.1.11" "@storybook/csf" "0.0.1" - "@storybook/router" "6.0.21" + "@storybook/router" "6.1.11" "@types/qs" "^6.9.0" core-js "^3.0.1" global "^4.3.2" prop-types "^15.7.2" qs "^6.6.0" - regenerator-runtime "^0.13.3" - ts-dedent "^1.1.1" + regenerator-runtime "^0.13.7" + ts-dedent "^2.0.0" -"@storybook/addon-storysource@^6.0.21": - version "6.0.21" - resolved "https://registry.npmjs.org/@storybook/addon-storysource/-/addon-storysource-6.0.21.tgz#fce9a6de8b276239dbb49b809f3b5efd9fbcecb4" - integrity sha512-h8bu2twPfBRbWlxg8LRtCM5/r2FxWahJa0RC70qDX6eNdzDw6Xv0B8bZsVxKPWqBNQbwYPz5ui44ym53dFDM/Q== +"@storybook/addon-storysource@^6.1.11": + version "6.1.11" + resolved "https://registry.npmjs.org/@storybook/addon-storysource/-/addon-storysource-6.1.11.tgz#f5413a51262f62eed3b399c4d9861b873f2c2827" + integrity sha512-uscKgALJa/inMFPb/Fpe9LXB6c6WlrGOfaUiAdrahn9gZbDAG9qunaSkAZ9EPWckSosq3RuV59HMCQ2Bolh/lQ== dependencies: - "@storybook/addons" "6.0.21" - "@storybook/api" "6.0.21" - "@storybook/client-logger" "6.0.21" - "@storybook/components" "6.0.21" - "@storybook/router" "6.0.21" - "@storybook/source-loader" "6.0.21" - "@storybook/theming" "6.0.21" + "@storybook/addons" "6.1.11" + "@storybook/api" "6.1.11" + "@storybook/client-logger" "6.1.11" + "@storybook/components" "6.1.11" + "@storybook/router" "6.1.11" + "@storybook/source-loader" "6.1.11" + "@storybook/theming" "6.1.11" core-js "^3.0.1" estraverse "^4.2.0" loader-utils "^2.0.0" prettier "~2.0.5" prop-types "^15.7.2" - react "^16.9.17" - react-syntax-highlighter "^12.2.1" - regenerator-runtime "^0.13.3" + react-syntax-highlighter "^13.5.0" + regenerator-runtime "^0.13.7" -"@storybook/addons@6.0.21": - version "6.0.21" - resolved "https://registry.npmjs.org/@storybook/addons/-/addons-6.0.21.tgz#bd5229652102c3aed59b78ef6920ff6b482b4d78" - integrity sha512-yDttNLc3vXqBxwK795ykgzTC6MpvuXDQuF4LHSlHZQe6wsMu1m3fljnbYdafJWdx6cNZwUblU3KYcR11PqhkPg== +"@storybook/addons@6.1.11", "@storybook/addons@^6.1.11": + version "6.1.11" + resolved "https://registry.npmjs.org/@storybook/addons/-/addons-6.1.11.tgz#cb4578411ca00ccb206b484df5a171ccaca34719" + integrity sha512-OZXsdmn60dVe482l9zWxzOqqJApD2jggk/8QJKn3/Ub9posmqdqg712bW6v71BBe0UXXG/QfkZA7gcyiyEENbw== dependencies: - "@storybook/api" "6.0.21" - "@storybook/channels" "6.0.21" - "@storybook/client-logger" "6.0.21" - "@storybook/core-events" "6.0.21" - "@storybook/router" "6.0.21" - "@storybook/theming" "6.0.21" + "@storybook/api" "6.1.11" + "@storybook/channels" "6.1.11" + "@storybook/client-logger" "6.1.11" + "@storybook/core-events" "6.1.11" + "@storybook/router" "6.1.11" + "@storybook/theming" "6.1.11" core-js "^3.0.1" global "^4.3.2" - regenerator-runtime "^0.13.3" + regenerator-runtime "^0.13.7" -"@storybook/addons@6.0.26", "@storybook/addons@^6.0.21": - version "6.0.26" - resolved "https://registry.npmjs.org/@storybook/addons/-/addons-6.0.26.tgz#343cbea3eee2d39413b80bc2d66535a7f61488fc" - integrity sha512-OhAApFKgsj9an7FLYfHI4cJQuZ4Zm6yoGOpaxhOvKQMw7dXUPsLvbCyw/6dZOLvaFhjJjQiXtbxtZG+UjR8nvA== - dependencies: - "@storybook/api" "6.0.26" - "@storybook/channels" "6.0.26" - "@storybook/client-logger" "6.0.26" - "@storybook/core-events" "6.0.26" - "@storybook/router" "6.0.26" - "@storybook/theming" "6.0.26" - core-js "^3.0.1" - global "^4.3.2" - regenerator-runtime "^0.13.3" - -"@storybook/api@6.0.21": - version "6.0.21" - resolved "https://registry.npmjs.org/@storybook/api/-/api-6.0.21.tgz#a25a1eb4d07dc43500e03c856db43baba46726f1" - integrity sha512-cRRGf/KGFwYiDouTouEcDdp45N1AbYnAfvLqYZ3KuUTGZ+CiU/PN/vavkp07DQeM4FIQO8TLhzHdsLFpLT7Lkw== +"@storybook/api@6.1.11": + version "6.1.11" + resolved "https://registry.npmjs.org/@storybook/api/-/api-6.1.11.tgz#1e0b798203df823ac21184386258cf8b5f17f440" + integrity sha512-/p4QW/p3uWO0AKVveNezX3I/CotyBKaJ5ui8PuvSPsl7yvqcsK41qI4evKOw7GMQn6oP+2enRbzHpGuCUgQSjA== dependencies: "@reach/router" "^1.3.3" - "@storybook/channels" "6.0.21" - "@storybook/client-logger" "6.0.21" - "@storybook/core-events" "6.0.21" + "@storybook/channels" "6.1.11" + "@storybook/client-logger" "6.1.11" + "@storybook/core-events" "6.1.11" "@storybook/csf" "0.0.1" - "@storybook/router" "6.0.21" + "@storybook/router" "6.1.11" "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.0.21" + "@storybook/theming" "6.1.11" "@types/reach__router" "^1.3.5" core-js "^3.0.1" fast-deep-equal "^3.1.1" global "^4.3.2" lodash "^4.17.15" memoizerific "^1.11.3" - react "^16.8.3" - regenerator-runtime "^0.13.3" + regenerator-runtime "^0.13.7" store2 "^2.7.1" telejson "^5.0.2" - ts-dedent "^1.1.1" + ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/api@6.0.26": - version "6.0.26" - resolved "https://registry.npmjs.org/@storybook/api/-/api-6.0.26.tgz#c45222c132eb8bc2e383536adfebbeb7a89867d0" - integrity sha512-aszDoz1c6T+eRtTUwWvySoyd3gRXmQxsingD084NnEp4VfFLA5H7VS/0sre0ZvU5GWh8d9COxY0DS2Ry/QSKvw== +"@storybook/channel-postmessage@6.1.11": + version "6.1.11" + resolved "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.1.11.tgz#62c1079f04870dd27925bd538a2020e7380daa2e" + integrity sha512-voW4Z2SUacDOxwN2q1NEBL//8OpgvL2C5CeoG1VQyEllKM8Vg9t1Nxo2FFTJBzv5LeEX7VIJKeBoB25DYvKyng== dependencies: - "@reach/router" "^1.3.3" - "@storybook/channels" "6.0.26" - "@storybook/client-logger" "6.0.26" - "@storybook/core-events" "6.0.26" - "@storybook/csf" "0.0.1" - "@storybook/router" "6.0.26" - "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.0.26" - "@types/reach__router" "^1.3.5" - core-js "^3.0.1" - fast-deep-equal "^3.1.1" - global "^4.3.2" - lodash "^4.17.15" - memoizerific "^1.11.3" - react "^16.8.3" - regenerator-runtime "^0.13.3" - store2 "^2.7.1" - telejson "^5.0.2" - ts-dedent "^1.1.1" - util-deprecate "^1.0.2" - -"@storybook/channel-postmessage@6.0.21": - version "6.0.21" - resolved "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.0.21.tgz#97e8f43c1b66f84c7b8271e447d45d4f66d355d1" - integrity sha512-ArRnoaS+b7qpAku/SO27z/yjRDCXb37mCPYGX0ntPbiQajootUbGO7otfnjFkaP44hCEC9uDYlOfMU1hYU1N6A== - dependencies: - "@storybook/channels" "6.0.21" - "@storybook/client-logger" "6.0.21" - "@storybook/core-events" "6.0.21" + "@storybook/channels" "6.1.11" + "@storybook/client-logger" "6.1.11" + "@storybook/core-events" "6.1.11" core-js "^3.0.1" global "^4.3.2" qs "^6.6.0" telejson "^5.0.2" -"@storybook/channel-postmessage@6.0.26": - version "6.0.26" - resolved "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.0.26.tgz#a98a0132d6bdf06741afac2607e9feabe34ab98b" - integrity sha512-FT6lC8M5JlNBxPT0rYfmF1yl9mBv04nfYs82TZpp1CzpLxf7wxdCBZ8SSRmvWIVBoNwGZPDhIk5+6JWyDEISBg== - dependencies: - "@storybook/channels" "6.0.26" - "@storybook/client-logger" "6.0.26" - "@storybook/core-events" "6.0.26" - core-js "^3.0.1" - global "^4.3.2" - qs "^6.6.0" - telejson "^5.0.2" - -"@storybook/channels@6.0.21": - version "6.0.21" - resolved "https://registry.npmjs.org/@storybook/channels/-/channels-6.0.21.tgz#bc0951efacbaa5f8827693fba4fe7c2290b5772c" - integrity sha512-G6gjcEotSwDmOlxSmOMgsO3VhQ42RLJK7kFp6D5eg0Q6S8vsypltdT8orxdu+6+AbcBrL+5Sla8lThzaCvXsVQ== +"@storybook/channels@6.1.11": + version "6.1.11" + resolved "https://registry.npmjs.org/@storybook/channels/-/channels-6.1.11.tgz#a93a83746ad78dd40e1c056029f6d93b17bb66bc" + integrity sha512-NvjWzQ95TSV1e18jaQBCOGoe+vptKH2NOKZ7QRQ7I0O5OoHKr47IXoh+MQ5C8CRD9FTdLE/xWdn1sVVEPRyHEw== dependencies: core-js "^3.0.1" - ts-dedent "^1.1.1" + ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/channels@6.0.26": - version "6.0.26" - resolved "https://registry.npmjs.org/@storybook/channels/-/channels-6.0.26.tgz#3e8678b4b40085081257a39b9e85fab13a19943c" - integrity sha512-H0iUorayYqS+zfhbjd+cYRzAdRLGLWUeWFu2Aa+oJ4/zeAQNL+DafWboHc567RQ4Vb5KqE5QZoCFskWUUYqJYA== +"@storybook/client-api@6.1.11": + version "6.1.11" + resolved "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.1.11.tgz#d25aac484ca84a1acb01d450e756a62408f00c1a" + integrity sha512-DodJQzGCR+PYs26klvbquTjfBgkw5nvCZd3jpgWQtOrYaY/cMY1LLkVkKqrm2ENW8f7vf7tiw78RtxaXy7xeIQ== dependencies: - core-js "^3.0.1" - ts-dedent "^1.1.1" - util-deprecate "^1.0.2" - -"@storybook/client-api@6.0.21": - version "6.0.21" - resolved "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.0.21.tgz#6a652dea67d219a31d18af0e05b9f17ba6c7c316" - integrity sha512-emBXd/ml6pc3G8gP3MsR9zQsAq1zZbqof9MxB51tG/jpTXdqWQ8ce1pt1tJS8Xj0QDM072jR6wsY+mmro0GZnA== - dependencies: - "@storybook/addons" "6.0.21" - "@storybook/channel-postmessage" "6.0.21" - "@storybook/channels" "6.0.21" - "@storybook/client-logger" "6.0.21" - "@storybook/core-events" "6.0.21" + "@storybook/addons" "6.1.11" + "@storybook/channel-postmessage" "6.1.11" + "@storybook/channels" "6.1.11" + "@storybook/client-logger" "6.1.11" + "@storybook/core-events" "6.1.11" "@storybook/csf" "0.0.1" "@types/qs" "^6.9.0" - "@types/webpack-env" "^1.15.2" + "@types/webpack-env" "^1.15.3" core-js "^3.0.1" global "^4.3.2" lodash "^4.17.15" memoizerific "^1.11.3" qs "^6.6.0" + regenerator-runtime "^0.13.7" stable "^0.1.8" store2 "^2.7.1" - ts-dedent "^1.1.1" + ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/client-api@6.0.26": - version "6.0.26" - resolved "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.0.26.tgz#ac9334ba86834e5cb23fc4fb577de60bda66164d" - integrity sha512-Qd5wR5b5lio/EchuJMhAmmJAE1pfvnEyu+JnyFGwMZLV9mN9NSspz+YsqbSCCDZsYcP5ewvPEnumIWqmj/wagQ== +"@storybook/client-logger@6.1.11": + version "6.1.11" + resolved "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.1.11.tgz#5dd092e4293e5f58f7e89ddbc6eb2511b7d60954" + integrity sha512-dSc+VKLW1UaiMPMhlZYRqhynrrHdHFiBEgU28+8LcmoZ1yhZBwLkcKdSD4YTT0CbMJAG1/+NUW5kRI8Geeg+rA== dependencies: - "@storybook/addons" "6.0.26" - "@storybook/channel-postmessage" "6.0.26" - "@storybook/channels" "6.0.26" - "@storybook/client-logger" "6.0.26" - "@storybook/core-events" "6.0.26" + core-js "^3.0.1" + global "^4.3.2" + +"@storybook/components@6.1.11": + version "6.1.11" + resolved "https://registry.npmjs.org/@storybook/components/-/components-6.1.11.tgz#edd5db7fe43f47b5a7ab515840795a89d931512e" + integrity sha512-DGDl76uONTkg0rpsa36TpVuXv4K7rFYe8GnQ/Q8n4By5tvldC4s9YXwcDRYHVrfnYybKzuZ/+jv2ZAp4/8ZaeA== + dependencies: + "@popperjs/core" "^2.5.4" + "@storybook/client-logger" "6.1.11" "@storybook/csf" "0.0.1" - "@types/qs" "^6.9.0" - "@types/webpack-env" "^1.15.2" - core-js "^3.0.1" - global "^4.3.2" - lodash "^4.17.15" - memoizerific "^1.11.3" - qs "^6.6.0" - stable "^0.1.8" - store2 "^2.7.1" - ts-dedent "^1.1.1" - util-deprecate "^1.0.2" - -"@storybook/client-logger@6.0.21": - version "6.0.21" - resolved "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.0.21.tgz#20369addf9eb79fc0c85a2e0dcb48f5a1a544532" - integrity sha512-8aUEbhjXV+UMYQWukVYnp+kZafF+LD4Dm7eMo37IUZvt3VIjV1VvhxIDVJtqjk2vv0KZTepESFBkZQLmBzI9Zg== - dependencies: - core-js "^3.0.1" - global "^4.3.2" - -"@storybook/client-logger@6.0.26": - version "6.0.26" - resolved "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.0.26.tgz#e3d28bd8dc02ec2c53a9d69773a68189590b746f" - integrity sha512-VNoL6/oehVhn3hZi9vrTNT+C/3oAZKV+smfZFnPtsCR/Fq7CKbmsBd0pGPL57f81RU8e8WygwrIlAGJTDSNIjw== - dependencies: - core-js "^3.0.1" - global "^4.3.2" - -"@storybook/components@6.0.21": - version "6.0.21" - resolved "https://registry.npmjs.org/@storybook/components/-/components-6.0.21.tgz#2f355370f993e0b7b9062094a03dffc2cdda91db" - integrity sha512-r6btqFW/rcXIU5v231EifZfdh9O0fy7bJDXwwDf8zVUgLx8JRc0VnSs3nvK3Is9HF1wZ9vjx/7Lh4rTIDZAjgg== - dependencies: - "@storybook/client-logger" "6.0.21" - "@storybook/csf" "0.0.1" - "@storybook/theming" "6.0.21" + "@storybook/theming" "6.1.11" "@types/overlayscrollbars" "^1.9.0" "@types/react-color" "^3.0.1" "@types/react-syntax-highlighter" "11.0.4" @@ -4618,97 +4574,60 @@ memoizerific "^1.11.3" overlayscrollbars "^1.10.2" polished "^3.4.4" - popper.js "^1.14.7" - react "^16.8.3" react-color "^2.17.0" - react-dom "^16.8.3" - react-popper-tooltip "^2.11.0" - react-syntax-highlighter "^12.2.1" + react-popper-tooltip "^3.1.1" + react-syntax-highlighter "^13.5.0" react-textarea-autosize "^8.1.1" - ts-dedent "^1.1.1" + ts-dedent "^2.0.0" -"@storybook/components@6.0.26": - version "6.0.26" - resolved "https://registry.npmjs.org/@storybook/components/-/components-6.0.26.tgz#e1f6e16aae850a71c9ac7bdd1d44a068ec9cfdc1" - integrity sha512-8wigI1pDFJO1m1IQWPguOK+nOsaAVRWkVdu+2te/rDcIR9QNvMzzou0+Lhfp3zKSVT4E6mEoGB/TWXXF5Iq0sQ== - dependencies: - "@storybook/client-logger" "6.0.26" - "@storybook/csf" "0.0.1" - "@storybook/theming" "6.0.26" - "@types/overlayscrollbars" "^1.9.0" - "@types/react-color" "^3.0.1" - "@types/react-syntax-highlighter" "11.0.4" - core-js "^3.0.1" - fast-deep-equal "^3.1.1" - global "^4.3.2" - lodash "^4.17.15" - markdown-to-jsx "^6.11.4" - memoizerific "^1.11.3" - overlayscrollbars "^1.10.2" - polished "^3.4.4" - popper.js "^1.14.7" - react "^16.8.3" - react-color "^2.17.0" - react-dom "^16.8.3" - react-popper-tooltip "^2.11.0" - react-syntax-highlighter "^12.2.1" - react-textarea-autosize "^8.1.1" - ts-dedent "^1.1.1" - -"@storybook/core-events@6.0.21": - version "6.0.21" - resolved "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.0.21.tgz#2ce51e6d7524e7543dbb29571beac1dbeb4e5f40" - integrity sha512-p84fbPcsAhnqDhp+HJ4P8+vI2BqJus4IRoVAemLAwuPjyPElrV9UvOa/RHy1BN8Z6jXwFA+FFzfGl2kPJ3WYcA== +"@storybook/core-events@6.1.11": + version "6.1.11" + resolved "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.1.11.tgz#d50e8ec90490f9a7180a8c8a83afb6dcfe47ed66" + integrity sha512-hTib81W8PxepM7iXVvl3pBXSaGpChl5LTzaLCoIRO9sSB8dy0/x2DLAHzbQvShk/l1wqUc3TtOLIxq+eC9l3wg== dependencies: core-js "^3.0.1" -"@storybook/core-events@6.0.26": - version "6.0.26" - resolved "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.0.26.tgz#61181c9a8610d26cc85d47f133a563879044ca2d" - integrity sha512-nWjS/+kMiw31OPgeJQaiFsJk9ZJJo3/d4c+kc6GOl2iC1H3Q4/5cm3NvJBn/7bUtKHmSFwfbDouj+XjUk5rZbQ== +"@storybook/core@6.1.11": + version "6.1.11" + resolved "https://registry.npmjs.org/@storybook/core/-/core-6.1.11.tgz#ed9d3b513794c604ab11180f6a014924b871179e" + integrity sha512-pYOOQwiNJ5myLRn6p6nnLUjjjISHK/N55vS4HFnETYSaRLA++h1coN1jk7Zwt89dOQTdF0EsTJn+6snYOC+lxQ== dependencies: - core-js "^3.0.1" - -"@storybook/core@6.0.21": - version "6.0.21" - resolved "https://registry.npmjs.org/@storybook/core/-/core-6.0.21.tgz#105c2b90ab27e7b478cb1b7d10e9fe5aba5e0708" - integrity sha512-/Et5NLabB12dnuPdhHDA/Q1pj0Mm2DGdL3KiLO4IC2VZeICCLGmU3/EGJBgjLK+anQ59pkclOiQ8i9eMXFiJ6A== - dependencies: - "@babel/plugin-proposal-class-properties" "^7.8.3" - "@babel/plugin-proposal-decorators" "^7.8.3" - "@babel/plugin-proposal-export-default-from" "^7.8.3" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.1" - "@babel/plugin-proposal-object-rest-spread" "^7.9.6" - "@babel/plugin-proposal-optional-chaining" "^7.10.1" - "@babel/plugin-proposal-private-methods" "^7.8.3" + "@babel/core" "^7.12.3" + "@babel/plugin-proposal-class-properties" "^7.12.1" + "@babel/plugin-proposal-decorators" "^7.12.1" + "@babel/plugin-proposal-export-default-from" "^7.12.1" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" + "@babel/plugin-proposal-object-rest-spread" "^7.12.1" + "@babel/plugin-proposal-optional-chaining" "^7.12.1" + "@babel/plugin-proposal-private-methods" "^7.12.1" "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-transform-arrow-functions" "^7.8.3" - "@babel/plugin-transform-block-scoping" "^7.8.3" - "@babel/plugin-transform-classes" "^7.9.5" - "@babel/plugin-transform-destructuring" "^7.9.5" - "@babel/plugin-transform-for-of" "^7.9.0" - "@babel/plugin-transform-parameters" "^7.9.5" - "@babel/plugin-transform-shorthand-properties" "^7.8.3" - "@babel/plugin-transform-spread" "^7.8.3" - "@babel/plugin-transform-template-literals" "^7.8.3" - "@babel/preset-env" "^7.9.6" - "@babel/preset-react" "^7.8.3" - "@babel/preset-typescript" "^7.9.0" - "@babel/register" "^7.10.5" - "@storybook/addons" "6.0.21" - "@storybook/api" "6.0.21" - "@storybook/channel-postmessage" "6.0.21" - "@storybook/channels" "6.0.21" - "@storybook/client-api" "6.0.21" - "@storybook/client-logger" "6.0.21" - "@storybook/components" "6.0.21" - "@storybook/core-events" "6.0.21" + "@babel/plugin-transform-arrow-functions" "^7.12.1" + "@babel/plugin-transform-block-scoping" "^7.12.1" + "@babel/plugin-transform-classes" "^7.12.1" + "@babel/plugin-transform-destructuring" "^7.12.1" + "@babel/plugin-transform-for-of" "^7.12.1" + "@babel/plugin-transform-parameters" "^7.12.1" + "@babel/plugin-transform-shorthand-properties" "^7.12.1" + "@babel/plugin-transform-spread" "^7.12.1" + "@babel/plugin-transform-template-literals" "^7.12.1" + "@babel/preset-env" "^7.12.1" + "@babel/preset-react" "^7.12.1" + "@babel/preset-typescript" "^7.12.1" + "@babel/register" "^7.12.1" + "@storybook/addons" "6.1.11" + "@storybook/api" "6.1.11" + "@storybook/channel-postmessage" "6.1.11" + "@storybook/channels" "6.1.11" + "@storybook/client-api" "6.1.11" + "@storybook/client-logger" "6.1.11" + "@storybook/components" "6.1.11" + "@storybook/core-events" "6.1.11" "@storybook/csf" "0.0.1" - "@storybook/node-logger" "6.0.21" - "@storybook/router" "6.0.21" + "@storybook/node-logger" "6.1.11" + "@storybook/router" "6.1.11" "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.0.21" - "@storybook/ui" "6.0.21" + "@storybook/theming" "6.1.11" + "@storybook/ui" "6.1.11" "@types/glob-base" "^0.3.0" "@types/micromatch" "^4.0.1" "@types/node-fetch" "^2.5.4" @@ -4726,6 +4645,7 @@ cli-table3 "0.6.0" commander "^5.0.0" core-js "^3.0.1" + cpy "^8.1.1" css-loader "^3.5.3" detect-port "^1.3.0" dotenv-webpack "^1.7.0" @@ -4756,19 +4676,21 @@ qs "^6.6.0" raw-loader "^4.0.1" react-dev-utils "^10.0.0" - regenerator-runtime "^0.13.3" + regenerator-runtime "^0.13.7" resolve-from "^5.0.0" serve-favicon "^2.5.0" - shelljs "^0.8.3" + shelljs "^0.8.4" stable "^0.1.8" style-loader "^1.2.1" + telejson "^5.0.2" terser-webpack-plugin "^3.0.0" - ts-dedent "^1.1.1" + ts-dedent "^2.0.0" unfetch "^4.1.0" url-loader "^4.0.0" util-deprecate "^1.0.2" - webpack "^4.43.0" + webpack "^4.44.2" webpack-dev-middleware "^3.7.0" + webpack-filter-warnings-plugin "^1.2.1" webpack-hot-middleware "^2.25.0" webpack-virtual-modules "^0.2.2" @@ -4779,10 +4701,10 @@ dependencies: lodash "^4.17.15" -"@storybook/node-logger@6.0.21": - version "6.0.21" - resolved "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.0.21.tgz#5b8ba589d5cca6a67c69ee8f5258755b7e1dbc08" - integrity sha512-KRBf+Fz7fgtwHdnYt70JTZbcYMZ1pQPtDyqbrFYCjwkbx5GPX5vMOozlxCIj9elseqPIsF8CKgHOW7cFHVyWYw== +"@storybook/node-logger@6.1.11": + version "6.1.11" + resolved "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.1.11.tgz#8e0d058b4804f2fea03c9d7d331b8e2d02f3b7ff" + integrity sha512-MASonXDWpSMU9HF9mqbGOR1Ps/DTJ8AVmYD50+OnB9kXl4M42Dliobeq7JwKFMnZ42RelUCCSXdWW80hGrUKKA== dependencies: "@types/npmlog" "^4.1.2" chalk "^4.0.0" @@ -4790,48 +4712,37 @@ npmlog "^4.1.2" pretty-hrtime "^1.0.3" -"@storybook/react@^6.0.21": - version "6.0.21" - resolved "https://registry.npmjs.org/@storybook/react/-/react-6.0.21.tgz#68f8a318e9940305b06eb894896624a35a9868b0" - integrity sha512-L3PcoBJq5aK1aTaJNfwsSJ8Kxgcyk0WknN4TDqhP7a+oXmuMY1YEi96hEvQVIm0TBCkQxs61K70/T7vlilEtHg== +"@storybook/react@^6.1.11": + version "6.1.11" + resolved "https://registry.npmjs.org/@storybook/react/-/react-6.1.11.tgz#e94403cd878c66b445df993bad9bec9023db3ebe" + integrity sha512-EmR7yvVW6z6AYhfzAgJMGR/5+igeBGa1EePaEIibn51r5uboSB72N12NaADyF2OaycIdV+0sW6vP9Zvlvexa/w== dependencies: - "@babel/preset-flow" "^7.0.0" - "@babel/preset-react" "^7.0.0" - "@storybook/addons" "6.0.21" - "@storybook/core" "6.0.21" - "@storybook/node-logger" "6.0.21" + "@babel/preset-flow" "^7.12.1" + "@babel/preset-react" "^7.12.1" + "@pmmmwh/react-refresh-webpack-plugin" "^0.4.2" + "@storybook/addons" "6.1.11" + "@storybook/core" "6.1.11" + "@storybook/node-logger" "6.1.11" "@storybook/semver" "^7.3.2" - "@svgr/webpack" "^5.4.0" - "@types/webpack-env" "^1.15.2" + "@types/webpack-env" "^1.15.3" babel-plugin-add-react-displayname "^0.0.5" babel-plugin-named-asset-import "^0.3.1" - babel-plugin-react-docgen "^4.1.0" + babel-plugin-react-docgen "^4.2.1" core-js "^3.0.1" global "^4.3.2" lodash "^4.17.15" prop-types "^15.7.2" react-dev-utils "^10.0.0" - react-docgen-typescript-plugin "^0.5.2" - regenerator-runtime "^0.13.3" - ts-dedent "^1.1.1" - webpack "^4.43.0" + react-docgen-typescript-plugin "^0.6.2" + react-refresh "^0.8.3" + regenerator-runtime "^0.13.7" + ts-dedent "^2.0.0" + webpack "^4.44.2" -"@storybook/router@6.0.21": - version "6.0.21" - resolved "https://registry.npmjs.org/@storybook/router/-/router-6.0.21.tgz#0f22261d4782c72a5a13e80cfcd8d50aed1f98c6" - integrity sha512-46SsKJfcd12lRrISnfrWhicJx8EylkgGDGohfH0n5p7inkkGOkKV8QFZoYPRKZueMXmUKpzJ0Z3HmVsLTCrCDw== - dependencies: - "@reach/router" "^1.3.3" - "@types/reach__router" "^1.3.5" - core-js "^3.0.1" - global "^4.3.2" - memoizerific "^1.11.3" - qs "^6.6.0" - -"@storybook/router@6.0.26": - version "6.0.26" - resolved "https://registry.npmjs.org/@storybook/router/-/router-6.0.26.tgz#5b991001afa7d7eb5e40c53cd4c58266b6f9edfd" - integrity sha512-kQ1LF/2gX3IkjS1wX7CsoeBc9ptHQzOsyax16rUyJa769DT5vMNtFtQxjNXMqSiSapPg2yrXJFKQNaoWvKgQEQ== +"@storybook/router@6.1.11": + version "6.1.11" + resolved "https://registry.npmjs.org/@storybook/router/-/router-6.1.11.tgz#d58e0c8324d8b16d71e09c017a4e3c844b1a4139" + integrity sha512-YEYOoKMo/WI13MZCkdqI9X3H1G0Oj5OUxi7So4qd3khX3zcCjSr3LjiMDBcmIVZpFo5VAvzjhIY4KqpgvzTG0A== dependencies: "@reach/router" "^1.3.3" "@types/reach__router" "^1.3.5" @@ -4848,13 +4759,13 @@ core-js "^3.6.5" find-up "^4.1.0" -"@storybook/source-loader@6.0.21": - version "6.0.21" - resolved "https://registry.npmjs.org/@storybook/source-loader/-/source-loader-6.0.21.tgz#f4ae0fa3f3d119f9ace1d3364df21f8f7cf65bd7" - integrity sha512-Duzpz8udadR7wzH8/4F3GnMRe23oBOxTm4jBZw/T8NA+HqBtd9Y16swWw4BfwsRwfdZS4EVw3PtWgsAfoqF7ow== +"@storybook/source-loader@6.1.11": + version "6.1.11" + resolved "https://registry.npmjs.org/@storybook/source-loader/-/source-loader-6.1.11.tgz#26e0ba30d5b9d1828ed10ccb76eb38bf48aad304" + integrity sha512-pEMWGn3XwZYAXwIrtmd7ziH5d1zN8NCpJM8vNJssntZFW45rDo69xgGM/PrTLPDca6f/Mhv+vqzR99tdfarJSw== dependencies: - "@storybook/addons" "6.0.21" - "@storybook/client-logger" "6.0.21" + "@storybook/addons" "6.1.11" + "@storybook/client-logger" "6.1.11" "@storybook/csf" "0.0.1" core-js "^3.0.1" estraverse "^4.2.0" @@ -4862,17 +4773,18 @@ loader-utils "^2.0.0" lodash "^4.17.15" prettier "~2.0.5" - regenerator-runtime "^0.13.3" + regenerator-runtime "^0.13.7" + source-map "^0.7.3" -"@storybook/theming@6.0.21": - version "6.0.21" - resolved "https://registry.npmjs.org/@storybook/theming/-/theming-6.0.21.tgz#d56051c0b8679c2b701ce08385660ab4146cf15f" - integrity sha512-n97DfB9kG6WrV1xBGDyeQibTrh8pBBCp3dSL3UTGH+KX3C2+4sm6QHlTgyekbi5FrbFEbnuZOKAS3YbLVONsRQ== +"@storybook/theming@6.1.11": + version "6.1.11" + resolved "https://registry.npmjs.org/@storybook/theming/-/theming-6.1.11.tgz#0e757e0562aedefc96bd1d12714d4c8e92823467" + integrity sha512-zRChacVgKoU2BmpvwK1ntiF3KIpc8QblJT7IGiKfP/BNpy9gNeXbLPLk3g/tkHszOvVYtkaZhEXni4Od8tqy1A== dependencies: - "@emotion/core" "^10.0.20" + "@emotion/core" "^10.1.1" "@emotion/is-prop-valid" "^0.8.6" - "@emotion/styled" "^10.0.17" - "@storybook/client-logger" "6.0.21" + "@emotion/styled" "^10.0.23" + "@storybook/client-logger" "6.1.11" core-js "^3.0.1" deep-object-diff "^1.1.0" emotion-theming "^10.0.19" @@ -4880,45 +4792,28 @@ memoizerific "^1.11.3" polished "^3.4.4" resolve-from "^5.0.0" - ts-dedent "^1.1.1" + ts-dedent "^2.0.0" -"@storybook/theming@6.0.26": - version "6.0.26" - resolved "https://registry.npmjs.org/@storybook/theming/-/theming-6.0.26.tgz#e5b545fb2653dfd1b043b567197d490b1c3c0da3" - integrity sha512-9yon2ofb9a+RT1pdvn8Njydy7XRw0qXcIsMqGsJRKoZecmRRozqB6DxH9Gbdf1vRSbM9gYUUDjbiMDFz7+4RiQ== +"@storybook/ui@6.1.11": + version "6.1.11" + resolved "https://registry.npmjs.org/@storybook/ui/-/ui-6.1.11.tgz#2e5a5df010f2bb75a09a0fd0439fc8e62f8c89e5" + integrity sha512-Qth2dxS5+VbKHcqgkiKpeD+xr/hRUuUIDUA/2Ierh/BaA8Up/krlso/mCLaQOa5E8Og9WJAdDFO0cUbt939c2Q== dependencies: - "@emotion/core" "^10.0.20" - "@emotion/is-prop-valid" "^0.8.6" - "@emotion/styled" "^10.0.17" - "@storybook/client-logger" "6.0.26" - core-js "^3.0.1" - deep-object-diff "^1.1.0" - emotion-theming "^10.0.19" - global "^4.3.2" - memoizerific "^1.11.3" - polished "^3.4.4" - resolve-from "^5.0.0" - ts-dedent "^1.1.1" - -"@storybook/ui@6.0.21": - version "6.0.21" - resolved "https://registry.npmjs.org/@storybook/ui/-/ui-6.0.21.tgz#5dac2b68a30f5dba5457e0315f58977e07138968" - integrity sha512-50QYF8tHUgpVq7B7PWp7kmyf79NySWJO0piQFjHv027vV8GfbXMWVswAXwo3IfCihPlnLKe01WbsigM/9T1HCQ== - dependencies: - "@emotion/core" "^10.0.20" - "@storybook/addons" "6.0.21" - "@storybook/api" "6.0.21" - "@storybook/channels" "6.0.21" - "@storybook/client-logger" "6.0.21" - "@storybook/components" "6.0.21" - "@storybook/core-events" "6.0.21" - "@storybook/router" "6.0.21" + "@emotion/core" "^10.1.1" + "@storybook/addons" "6.1.11" + "@storybook/api" "6.1.11" + "@storybook/channels" "6.1.11" + "@storybook/client-logger" "6.1.11" + "@storybook/components" "6.1.11" + "@storybook/core-events" "6.1.11" + "@storybook/router" "6.1.11" "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.0.21" + "@storybook/theming" "6.1.11" "@types/markdown-to-jsx" "^6.11.0" copy-to-clipboard "^3.0.8" core-js "^3.0.1" core-js-pure "^3.0.1" + downshift "^6.0.6" emotion-theming "^10.0.19" fuse.js "^3.6.1" global "^4.3.2" @@ -4927,13 +4822,11 @@ memoizerific "^1.11.3" polished "^3.4.4" qs "^6.6.0" - react "^16.8.3" - react-dom "^16.8.3" react-draggable "^4.0.3" react-helmet-async "^1.0.2" react-hotkeys "2.0.0" react-sizeme "^2.6.7" - regenerator-runtime "^0.13.3" + regenerator-runtime "^0.13.7" resolve-from "^5.0.0" store2 "^2.7.1" @@ -5191,7 +5084,7 @@ "@svgr/plugin-svgo" "^5.5.0" rollup-pluginutils "^2.8.2" -"@svgr/webpack@5.4.x", "@svgr/webpack@^5.4.0": +"@svgr/webpack@5.4.x": version "5.4.0" resolved "https://registry.npmjs.org/@svgr/webpack/-/webpack-5.4.0.tgz#b68bc86e29cf007292b96ced65f80971175632e0" integrity sha512-LjepnS/BSAvelnOnnzr6Gg0GcpLmnZ9ThGFK5WJtm1xOqdBE/1IACZU7MMdVzjyUkfFqGz87eRE4hFaSLiUwYg== @@ -6566,6 +6459,11 @@ resolved "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.15.3.tgz#fb602cd4c2f0b7c0fb857e922075fdf677d25d84" integrity sha512-5oiXqR7kwDGZ6+gmzIO2lTC+QsriNuQXZDWNYRV3l2XRN/zmPgnC21DLSx2D05zvD8vnXW6qUg7JnXZ4I6qLVQ== +"@types/webpack-env@^1.15.3": + version "1.16.0" + resolved "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.16.0.tgz#8c0a9435dfa7b3b1be76562f3070efb3f92637b4" + integrity sha512-Fx+NpfOO0CpeYX2g9bkvX8O5qh9wrU1sOF4g8sft4Mu7z+qfe387YlyY8w8daDyDsKY5vUxM0yxkAYnbkRbZEw== + "@types/webpack-node-externals@^2.5.0": version "2.5.0" resolved "https://registry.npmjs.org/@types/webpack-node-externals/-/webpack-node-externals-2.5.0.tgz#bcd161af84a4960416e5850e06931b35321c6654" @@ -6906,18 +6804,6 @@ "@webassemblyjs/wast-parser" "1.9.0" "@xtuc/long" "4.2.2" -"@webpack-contrib/schema-utils@^1.0.0-beta.0": - version "1.0.0-beta.0" - resolved "https://registry.npmjs.org/@webpack-contrib/schema-utils/-/schema-utils-1.0.0-beta.0.tgz#bf9638c9464d177b48209e84209e23bee2eb4f65" - integrity sha512-LonryJP+FxQQHsjGBi6W786TQB1Oym+agTpY0c+Kj8alnIw+DLUJb6SI8Y1GHGhLCH1yPRrucjObUmxNICQ1pg== - dependencies: - ajv "^6.1.0" - ajv-keywords "^3.1.0" - chalk "^2.3.2" - strip-ansi "^4.0.0" - text-table "^0.2.0" - webpack-log "^1.1.2" - "@wry/equality@^0.1.2": version "0.1.11" resolved "https://registry.npmjs.org/@wry/equality/-/equality-0.1.11.tgz#35cb156e4a96695aa81a9ecc4d03787bc17f1790" @@ -7168,7 +7054,7 @@ ansi-escapes@^4.2.1, ansi-escapes@^4.3.0, ansi-escapes@^4.3.1: dependencies: type-fest "^0.11.0" -ansi-html@0.0.7: +ansi-html@0.0.7, ansi-html@^0.0.7: version "0.0.7" resolved "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4= @@ -7715,16 +7601,18 @@ ast-types-flow@0.0.7, ast-types-flow@^0.0.7: resolved "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= -ast-types@0.11.3: - version "0.11.3" - resolved "https://registry.npmjs.org/ast-types/-/ast-types-0.11.3.tgz#c20757fe72ee71278ea0ff3d87e5c2ca30d9edf8" - integrity sha512-XA5o5dsNw8MhyW0Q7MWXJWc4oOzZKbdsEJq45h7c8q/d9DwWZ5F2ugUc1PuMLPGsUnphCt/cNDHu8JeBbxf1qA== - ast-types@^0.13.2: version "0.13.2" resolved "https://registry.npmjs.org/ast-types/-/ast-types-0.13.2.tgz#df39b677a911a83f3a049644fb74fdded23cea48" integrity sha512-uWMHxJxtfj/1oZClOxDEV1sQ1HCDkA4MG8Gr69KKeBjEVH0R84WlejZ0y2DcwyBlpAEMltmVYkVgqfLFb2oyiA== +ast-types@^0.14.2: + version "0.14.2" + resolved "https://registry.npmjs.org/ast-types/-/ast-types-0.14.2.tgz#600b882df8583e3cd4f2df5fa20fa83759d4bdfd" + integrity sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA== + dependencies: + tslib "^2.0.1" + astral-regex@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" @@ -8060,14 +7948,14 @@ babel-plugin-named-asset-import@^0.3.1: resolved "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.6.tgz#c9750a1b38d85112c9e166bf3ef7c5dbc605f4be" integrity sha512-1aGDUfL1qOOIoqk9QKGIo2lANk+C7ko/fqH0uIyC71x3PEGz0uVP8ISgfEsFuG+FKmjHTvFK/nNM8dowpmUxLA== -babel-plugin-react-docgen@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/babel-plugin-react-docgen/-/babel-plugin-react-docgen-4.1.0.tgz#1dfa447dac9ca32d625a123df5733a9e47287c26" - integrity sha512-vzpnBlfGv8XOhJM2zbPyyqw2OLEbelgZZsaaRRTpVwNKuYuc+pUg4+dy7i9gCRms0uOQn4osX571HRcCJMJCmA== +babel-plugin-react-docgen@^4.2.1: + version "4.2.1" + resolved "https://registry.npmjs.org/babel-plugin-react-docgen/-/babel-plugin-react-docgen-4.2.1.tgz#7cc8e2f94e8dc057a06e953162f0810e4e72257b" + integrity sha512-UQ0NmGHj/HAqi5Bew8WvNfCk8wSsmdgNd8ZdMjBCICtyCJCq9LiqgqvjCYe570/Wg7AQArSq1VQ60Dd/CHN7mQ== dependencies: + ast-types "^0.14.2" lodash "^4.17.15" react-docgen "^5.0.0" - recast "^0.14.7" babel-plugin-syntax-jsx@^6.18.0: version "6.18.0" @@ -9062,7 +8950,7 @@ chainsaw@~0.1.0: dependencies: traverse ">=0.3.0 <0.4" -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -9658,6 +9546,11 @@ compute-lcm@^1.1.0: validate.io-function "^1.0.2" validate.io-integer-array "^1.0.0" +compute-scroll-into-view@^1.0.16: + version "1.0.16" + resolved "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.16.tgz#5b7bf4f7127ea2c19b750353d7ce6776a90ee088" + integrity sha512-a85LHKY81oQnikatZYA90pufpZ6sQx++BoCxOEMsjpZx+ZnaKGQnCyCehTRr/1p9GBIAHTjcU9k71kSYWloLiQ== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -9986,6 +9879,31 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" +cp-file@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/cp-file/-/cp-file-7.0.0.tgz#b9454cfd07fe3b974ab9ea0e5f29655791a9b8cd" + integrity sha512-0Cbj7gyvFVApzpK/uhCtQ/9kE9UnYpxMzaq5nQQC/Dh4iaj5fxp7iEFIullrYwzj8nf0qnsI1Qsx34hAeAebvw== + dependencies: + graceful-fs "^4.1.2" + make-dir "^3.0.0" + nested-error-stacks "^2.0.0" + p-event "^4.1.0" + +cpy@^8.1.1: + version "8.1.1" + resolved "https://registry.npmjs.org/cpy/-/cpy-8.1.1.tgz#066ed4c6eaeed9577df96dae4db9438c1a90df62" + integrity sha512-vqHT+9o67sMwJ5hUd/BAOYeemkU+MuFRsK2c36Xc3eefQpAsp1kAsyDxEDcc5JS1+y9l/XHPrIsVTcyGGmkUUQ== + dependencies: + arrify "^2.0.1" + cp-file "^7.0.0" + globby "^9.2.0" + has-glob "^1.0.0" + junk "^3.1.0" + nested-error-stacks "^2.1.0" + p-all "^2.1.0" + p-filter "^2.1.0" + p-map "^3.0.0" + crc32-stream@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.0.tgz#05b7ca047d831e98c215538666f372b756d91893" @@ -10040,7 +9958,7 @@ create-react-class@^15.5.1: loose-envify "^1.3.1" object-assign "^4.1.1" -create-react-context@0.3.0, create-react-context@^0.3.0: +create-react-context@0.3.0: version "0.3.0" resolved "https://registry.npmjs.org/create-react-context/-/create-react-context-0.3.0.tgz#546dede9dc422def0d3fc2fe03afe0bc0f4f7d8c" integrity sha512-dNldIoSuNSvlTJ7slIKC/ZFGKexBMBrrcc+TTe1NdmROnaASuLPvqpwj9v4XS4uXZ8+YPu0sNmShX2rXI5LNsw== @@ -10814,7 +10732,7 @@ dedent@^0.7.0: resolved "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= -deep-equal@^1.0.1, deep-equal@^1.1.1: +deep-equal@^1.0.1: version "1.1.1" resolved "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== @@ -11327,6 +11245,16 @@ dotenv@^8.0.0, dotenv@^8.2.0: resolved "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== +downshift@^6.0.6: + version "6.0.7" + resolved "https://registry.npmjs.org/downshift/-/downshift-6.0.7.tgz#05ef58b991e4467cdb8cd36e7a87a011d0bada5c" + integrity sha512-+rqgx3JTSs8b4V9q++hsLvaP8mhMOdX7u+jy5S2etg7+Y7uFLVzZaI0S7Xo2yEnNDmTcNnYZZ/vFjdWuJ2kZdg== + dependencies: + "@babel/runtime" "^7.12.5" + compute-scroll-into-view "^1.0.16" + prop-types "^15.7.2" + react-is "^17.0.1" + duplexer2@~0.1.4: version "0.1.4" resolved "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" @@ -11987,7 +11915,7 @@ espree@^7.3.0: acorn-jsx "^5.2.0" eslint-visitor-keys "^1.3.0" -esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: +esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== @@ -12455,7 +12383,7 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -fault@^1.0.0, fault@^1.0.2: +fault@^1.0.0: version "1.0.4" resolved "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz#eafcfc0a6d214fc94601e170df29954a4f842f13" integrity sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA== @@ -13847,6 +13775,13 @@ has-flag@^4.0.0: resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has-glob@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/has-glob/-/has-glob-1.0.0.tgz#9aaa9eedbffb1ba3990a7b0010fb678ee0081207" + integrity sha1-mqqe7b/7G6OZCnsAEPtnjuAIEgc= + dependencies: + is-glob "^3.0.0" + has-symbols@^1.0.0, has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" @@ -13977,11 +13912,6 @@ highlight.js@^10.4.1, highlight.js@~10.4.0: resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-10.4.1.tgz#d48fbcf4a9971c4361b3f95f302747afe19dbad0" integrity sha512-yR5lWvNz7c85OhVAEAeFhVCc/GV4C30Fjzc/rCP0aCWzc1UUOPUk55dK/qdwTZHBvMZo+eZ2jpk62ndX/xMFlg== -highlight.js@~9.15.0, highlight.js@~9.15.1: - version "9.15.10" - resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.10.tgz#7b18ed75c90348c045eef9ed08ca1319a2219ad2" - integrity sha512-RoV7OkQm0T3os3Dd2VHLNMoaoDVx77Wygln3n9l5YV172XonWG6rgQD3XnF/BuFFZw9A0TJgmMSO8FEWQgvcXw== - history@^4.9.0: version "4.10.1" resolved "https://registry.npmjs.org/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" @@ -14078,6 +14008,11 @@ html-entities@^1.2.0, html-entities@^1.3.1: resolved "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz#fb9a1a4b5b14c5daba82d3e34c6ae4fe701a0e44" integrity sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA== +html-entities@^1.2.1: + version "1.3.3" + resolved "https://registry.npmjs.org/html-entities/-/html-entities-1.3.3.tgz#3dca638a43ee7de316fc23067398491152ad4736" + integrity sha512-/VulV3SYni1taM7a4RMdceqzJWR39gpZHjBwUnsCFKWV/GJkD14CJ5F7eWcZozmHJK0/f/H5U3b3SiPkuvxMgg== + html-escaper@^2.0.0: version "2.0.1" resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.1.tgz#beed86b5d2b921e92533aa11bce6d8e3b583dee7" @@ -14924,7 +14859,7 @@ is-glob@^2.0.0: dependencies: is-extglob "^1.0.0" -is-glob@^3.1.0: +is-glob@^3.0.0, is-glob@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= @@ -16192,6 +16127,11 @@ jsx-ast-utils@^2.2.1: array-includes "^3.1.1" object.assign "^4.1.1" +junk@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1" + integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ== + jwa@^1.4.1: version "1.4.1" resolved "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" @@ -16840,13 +16780,6 @@ log-symbols@^1.0.2: dependencies: chalk "^1.0.0" -log-symbols@^2.1.0: - version "2.2.0" - resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== - dependencies: - chalk "^2.0.1" - log-symbols@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" @@ -16896,14 +16829,6 @@ loglevel@^1.6.7, loglevel@^1.6.8: resolved "https://registry.npmjs.org/loglevel/-/loglevel-1.6.8.tgz#8a25fb75d092230ecd4457270d80b54e28011171" integrity sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA== -loglevelnext@^1.0.1: - version "1.0.5" - resolved "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz#36fc4f5996d6640f539ff203ba819641680d75a2" - integrity sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A== - dependencies: - es6-symbol "^3.1.1" - object.assign "^4.1.0" - long@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" @@ -16946,14 +16871,6 @@ lowercase-keys@^2.0.0: resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== -lowlight@1.12.1: - version "1.12.1" - resolved "https://registry.npmjs.org/lowlight/-/lowlight-1.12.1.tgz#014acf8dd73a370e02ff1cc61debcde3bb1681eb" - integrity sha512-OqaVxMGIESnawn+TU/QMV5BJLbUghUfjDWPAtFqDYDmDtr4FnB+op8xM+pR7nKlauHNUHXGt0VgWatFB8voS5w== - dependencies: - fault "^1.0.2" - highlight.js "~9.15.0" - lowlight@^1.14.0: version "1.14.0" resolved "https://registry.npmjs.org/lowlight/-/lowlight-1.14.0.tgz#83ebc143fec0f9e6c0d3deffe01be129ce56b108" @@ -17921,6 +17838,13 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" +native-url@^0.2.6: + version "0.2.6" + resolved "https://registry.npmjs.org/native-url/-/native-url-0.2.6.tgz#ca1258f5ace169c716ff44eccbddb674e10399ae" + integrity sha512-k4bDC87WtgrdD362gZz6zoiXQrl40kYlBmpfmSjwRO1VU0V5ccwJTlxuE72F6m3V0vc1xOf6n3UCP9QyerRqmA== + dependencies: + querystring "^0.2.0" + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -17945,6 +17869,11 @@ neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1: resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== +nested-error-stacks@^2.0.0, nested-error-stacks@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz#0fbdcf3e13fe4994781280524f8b96b0cdff9c61" + integrity sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug== + next-tick@1: version "1.1.0" resolved "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" @@ -18751,6 +18680,13 @@ overlayscrollbars@^1.10.2: resolved "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-1.13.0.tgz#1edb436328133b94877b558f77966d5497ca36a7" integrity sha512-p8oHrMeRAKxXDMPI/EBNITj/zTVHKNnAnM59Im+xnoZUlV07FyTg46wom2286jJlXGGfcPFG/ba5NUiCwWNd4w== +p-all@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/p-all/-/p-all-2.1.0.tgz#91419be56b7dee8fe4c5db875d55e0da084244a0" + integrity sha512-HbZxz5FONzz/z2gJfk6bFca0BCiSRF8jU3yCsWOen/vR6lZjfPOu/e7L3uFzTW1i0H8TlC3vqQstEJPQL4/uLA== + dependencies: + p-map "^2.0.0" + p-any@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/p-any/-/p-any-3.0.0.tgz#79847aeed70b5d3a10ea625296c0c3d2e90a87b9" @@ -18774,7 +18710,7 @@ p-each-series@^2.1.0: resolved "https://registry.npmjs.org/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48" integrity sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ== -p-event@^4.0.0: +p-event@^4.0.0, p-event@^4.1.0: version "4.2.0" resolved "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz#af4b049c8acd91ae81083ebd1e6f5cae2044c1b5" integrity sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ== @@ -19010,18 +18946,6 @@ parse-asn1@^5.0.0: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" -parse-entities@^1.1.2: - version "1.2.2" - resolved "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz#c31bf0f653b6661354f8973559cb86dd1d5edf50" - integrity sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg== - dependencies: - character-entities "^1.0.0" - character-entities-legacy "^1.0.0" - character-reference-invalid "^1.0.0" - is-alphanumerical "^1.0.0" - is-decimal "^1.0.0" - is-hexadecimal "^1.0.0" - parse-entities@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" @@ -19599,11 +19523,6 @@ popper.js@1.16.1-lts: resolved "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz#cf6847b807da3799d80ee3d6d2f90df8a3f50b05" integrity sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA== -popper.js@^1.14.4, popper.js@^1.14.7: - version "1.16.1" - resolved "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" - integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== - portfinder@^1.0.26: version "1.0.28" resolved "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" @@ -20130,7 +20049,7 @@ pretty-hrtime@^1.0.3: resolved "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= -prismjs@^1.21.0, prismjs@^1.8.4, prismjs@~1.21.0: +prismjs@^1.21.0, prismjs@~1.21.0: version "1.21.0" resolved "https://registry.npmjs.org/prismjs/-/prismjs-1.21.0.tgz#36c086ec36b45319ec4218ee164c110f9fc015a3" integrity sha512-uGdSIu1nk3kej2iZsLyDoJ7e9bnPzIgY0naW/HdknGj61zScaprVEVGHrPoXqI+M9sP0NDnTK2jpkvmldpuqDw== @@ -20144,14 +20063,7 @@ prismjs@^1.22.0, prismjs@~1.22.0: optionalDependencies: clipboard "^2.0.0" -prismjs@~1.17.0: - version "1.17.1" - resolved "https://registry.npmjs.org/prismjs/-/prismjs-1.17.1.tgz#e669fcbd4cdd873c35102881c33b14d0d68519be" - integrity sha512-PrEDJAFdUGbOP6xK/UsfkC5ghJsPJviKgnQOoxaDbBjwc8op68Quupwt1DeAFoG8GImPhiKXAvvsH7wDSLsu1Q== - optionalDependencies: - clipboard "^2.0.0" - -private@^0.1.8, private@~0.1.5: +private@^0.1.8: version "0.1.8" resolved "https://registry.npmjs.org/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== @@ -20635,31 +20547,21 @@ react-dev-utils@^10.0.0, react-dev-utils@^10.2.1: strip-ansi "6.0.0" text-table "0.2.0" -react-docgen-typescript-loader@^3.7.2: - version "3.7.2" - resolved "https://registry.npmjs.org/react-docgen-typescript-loader/-/react-docgen-typescript-loader-3.7.2.tgz#45cb2305652c0602767242a8700ad1ebd66bbbbd" - integrity sha512-fNzUayyUGzSyoOl7E89VaPKJk9dpvdSgyXg81cUkwy0u+NBvkzQG3FC5WBIlXda0k/iaxS+PWi+OC+tUiGxzPA== - dependencies: - "@webpack-contrib/schema-utils" "^1.0.0-beta.0" - loader-utils "^1.2.3" - react-docgen-typescript "^1.15.0" - -react-docgen-typescript-plugin@^0.5.2: - version "0.5.2" - resolved "https://registry.npmjs.org/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-0.5.2.tgz#2b294d75ef3145c36303da82be5d447cb67dc0dc" - integrity sha512-NQfWyWLmzUnedkiN2nPDb6Nkm68ik6fqbC3UvgjqYSeZsbKijXUA4bmV6aU7qICOXdop9PevPdjEgJuAN0nNVQ== +react-docgen-typescript-plugin@^0.6.2: + version "0.6.3" + resolved "https://registry.npmjs.org/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-0.6.3.tgz#664b22601df083597ecb1e60bd21beca60125fdf" + integrity sha512-av1S/fmWBNFGgNa4qtkidFjjOz23eEi6EdCtwSWo9WNhGzUMyMygbD/DosMWoeFlZpk9R3MXPkRE7PDH6j5GMQ== dependencies: debug "^4.1.1" endent "^2.0.1" micromatch "^4.0.2" - react-docgen-typescript "^1.20.1" - react-docgen-typescript-loader "^3.7.2" + react-docgen-typescript "^1.20.5" tslib "^2.0.0" -react-docgen-typescript@^1.15.0, react-docgen-typescript@^1.20.1: - version "1.20.4" - resolved "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-1.20.4.tgz#9a5655986077ccfc58c1a447f92c3d19f7a875bf" - integrity sha512-gE2SeseJd6+o981qr9VQJRbvFJ5LjLSKQiwhHsuLN4flt+lheKtG1jp2BPzrv2MKR5gmbLwpmNtK4wbLCPSZAw== +react-docgen-typescript@^1.20.5: + version "1.20.5" + resolved "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-1.20.5.tgz#fb8d78a707243498436c2952bd3f6f488a68d4f3" + integrity sha512-AbLGMtn76bn7SYBJSSaKJrZ0lgNRRR3qL60PucM5M4v/AXyC8221cKBXW5Pyt9TfDRfe+LDnPNlg7TibxX0ovA== react-docgen@^5.0.0: version "5.3.0" @@ -20675,7 +20577,7 @@ react-docgen@^5.0.0: node-dir "^0.1.10" strip-indent "^3.0.0" -react-dom@^16.12.0, react-dom@^16.13.1, react-dom@^16.8.3: +react-dom@^16.12.0, react-dom@^16.13.1: version "16.13.1" resolved "https://registry.npmjs.org/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f" integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag== @@ -20708,7 +20610,7 @@ react-fast-compare@^2.0.4: resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== -react-fast-compare@^3.1.1: +react-fast-compare@^3.0.1, react-fast-compare@^3.1.1: version "3.2.0" resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== @@ -20845,25 +20747,21 @@ react-motion@^0.5.2: prop-types "^15.5.8" raf "^3.1.0" -react-popper-tooltip@^2.11.0: - version "2.11.1" - resolved "https://registry.npmjs.org/react-popper-tooltip/-/react-popper-tooltip-2.11.1.tgz#3c4bdfd8bc10d1c2b9a162e859bab8958f5b2644" - integrity sha512-04A2f24GhyyMicKvg/koIOQ5BzlrRbKiAgP6L+Pdj1MVX3yJ1NeZ8+EidndQsbejFT55oW1b++wg2Z8KlAyhfQ== +react-popper-tooltip@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/react-popper-tooltip/-/react-popper-tooltip-3.1.1.tgz#329569eb7b287008f04fcbddb6370452ad3f9eac" + integrity sha512-EnERAnnKRptQBJyaee5GJScWNUKQPDD2ywvzZyUjst/wj5U64C8/CnSYLNEmP2hG0IJ3ZhtDxE8oDN+KOyavXQ== dependencies: - "@babel/runtime" "^7.9.2" - react-popper "^1.3.7" + "@babel/runtime" "^7.12.5" + "@popperjs/core" "^2.5.4" + react-popper "^2.2.4" -react-popper@^1.3.7: - version "1.3.7" - resolved "https://registry.npmjs.org/react-popper/-/react-popper-1.3.7.tgz#f6a3471362ef1f0d10a4963673789de1baca2324" - integrity sha512-nmqYTx7QVjCm3WUZLeuOomna138R1luC4EqkW3hxJUrAe+3eNz3oFCLYdnPwILfn0mX1Ew2c3wctrjlUMYYUww== +react-popper@^2.2.4: + version "2.2.4" + resolved "https://registry.npmjs.org/react-popper/-/react-popper-2.2.4.tgz#d2ad3d2474ac9f1abf93df3099d408e5aa6a2e22" + integrity sha512-NacOu4zWupdQjVXq02XpTD3yFPSfg5a7fex0wa3uGKVkFK7UN6LvVxgcb+xYr56UCuWiNPMH20tntdVdJRwYew== dependencies: - "@babel/runtime" "^7.1.2" - create-react-context "^0.3.0" - deep-equal "^1.1.1" - popper.js "^1.14.4" - prop-types "^15.6.1" - typed-styles "^0.0.7" + react-fast-compare "^3.0.1" warning "^4.0.2" react-redux@=4.4.10: @@ -20889,6 +20787,11 @@ react-redux@^7.1.1: prop-types "^15.7.2" react-is "^16.9.0" +react-refresh@^0.8.3: + version "0.8.3" + resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" + integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg== + react-resize-detector@^2.3.0: version "2.3.0" resolved "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-2.3.0.tgz#57bad1ae26a28a62a2ddb678ba6ffdf8fa2b599c" @@ -20982,16 +20885,16 @@ react-string-replace@^0.4.1: dependencies: lodash "^4.17.4" -react-syntax-highlighter@^12.2.1: - version "12.2.1" - resolved "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-12.2.1.tgz#14d78352da1c1c3f93c6698b70ec7c706b83493e" - integrity sha512-CTsp0ZWijwKRYFg9xhkWD4DSpQqE4vb2NKVMdPAkomnILSmsNBHE0n5GuI5zB+PU3ySVvXvdt9jo+ViD9XibCA== +react-syntax-highlighter@^13.5.0: + version "13.5.3" + resolved "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-13.5.3.tgz#9712850f883a3e19eb858cf93fad7bb357eea9c6" + integrity sha512-crPaF+QGPeHNIblxxCdf2Lg936NAHKhNhuMzRL3F9ct6aYXL3NcZtCL0Rms9+qVo6Y1EQLdXGypBNSbPL/r+qg== dependencies: "@babel/runtime" "^7.3.1" - highlight.js "~9.15.1" - lowlight "1.12.1" - prismjs "^1.8.4" - refractor "^2.4.1" + highlight.js "^10.1.1" + lowlight "^1.14.0" + prismjs "^1.21.0" + refractor "^3.1.0" react-syntax-highlighter@^13.5.1: version "13.5.1" @@ -21113,7 +21016,7 @@ react-wait@^0.3.0: resolved "https://registry.npmjs.org/react-wait/-/react-wait-0.3.0.tgz#0cdd4d919012451a5bc3ab0a16d00c6fd9a8c10b" integrity sha512-kB5x/kMKWcn0uVr9gBdNz21/oGbQwEQnF3P9p6E9yLfJ9DRcKS0fagbgYMFI0YFOoyKDj+2q6Rwax0kTYJF37g== -react@^16.0.0, react@^16.12.0, react@^16.13.1, react@^16.8.3, react@^16.9.17: +react@^16.0.0, react@^16.12.0, react@^16.13.1: version "16.13.1" resolved "https://registry.npmjs.org/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w== @@ -21308,16 +21211,6 @@ readdirp@~3.5.0: dependencies: picomatch "^2.2.1" -recast@^0.14.7: - version "0.14.7" - resolved "https://registry.npmjs.org/recast/-/recast-0.14.7.tgz#4f1497c2b5826d42a66e8e3c9d80c512983ff61d" - integrity sha512-/nwm9pkrcWagN40JeJhkPaRxiHXBRkXyRh/hgU088Z/v+qCy+zIHHY6bC6o7NaKAxPqtE6nD8zBH1LfU0/Wx6A== - dependencies: - ast-types "0.11.3" - esprima "~4.0.0" - private "~0.1.5" - source-map "~0.6.1" - recharts-scale@^0.4.2: version "0.4.3" resolved "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.3.tgz#040b4f638ed687a530357292ecac880578384b59" @@ -21426,15 +21319,6 @@ reflect-metadata@^0.1.13: resolved "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08" integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg== -refractor@^2.4.1: - version "2.10.1" - resolved "https://registry.npmjs.org/refractor/-/refractor-2.10.1.tgz#166c32f114ed16fd96190ad21d5193d3afc7d34e" - integrity sha512-Xh9o7hQiQlDbxo5/XkOX6H+x/q8rmlmZKr97Ie1Q8ZM32IRRd3B/UxuA/yXDW79DBSXGWxm2yRTbcTVmAciJRw== - dependencies: - hastscript "^5.0.0" - parse-entities "^1.1.2" - prismjs "~1.17.0" - refractor@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/refractor/-/refractor-3.1.0.tgz#b05a43c8a1b4fccb30001ffcbd5cd781f7f06f78" @@ -21475,6 +21359,11 @@ regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4, regenerator-runtime@^0 resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== +regenerator-runtime@^0.13.7: + version "0.13.7" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== + regenerator-transform@^0.14.2: version "0.14.4" resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.4.tgz#5266857896518d1616a78a0479337a30ea974cc7" @@ -22398,7 +22287,7 @@ shell-quote@1.7.2: resolved "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== -shelljs@^0.8.2, shelljs@^0.8.3, shelljs@^0.8.4: +shelljs@^0.8.2, shelljs@^0.8.4: version "0.8.4" resolved "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz#de7684feeb767f8716b326078a8a00875890e3c2" integrity sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ== @@ -22959,7 +22848,7 @@ store2@^2.7.1: resolved "https://registry.npmjs.org/store2/-/store2-2.10.0.tgz#46b82bb91878daf1b0d56dec2f1d41e54d5103cf" integrity sha512-tWEpK0snS2RPUq1i3R6OahfJNjWCQYNxq0+by1amCSuw0mXtymJpzmZIeYpA1UAa+7B0grCpNYIbDcd7AgTbFg== -storybook-dark-mode@^1.0.2: +storybook-dark-mode@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/storybook-dark-mode/-/storybook-dark-mode-1.0.3.tgz#8d58a874b6107ff1a7f29ebb0e6726b8036eee08" integrity sha512-mjHLrv/dwtqKmbOoQ2CMtGKDttWSnUybutujsIPxLcEC77EujjWiRBFv46LtXAZEyZLm8sGFUz0s6HJJfJ3tSw== @@ -24099,10 +23988,10 @@ tryer@^1.0.1: resolved "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== -ts-dedent@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/ts-dedent/-/ts-dedent-1.1.1.tgz#68fad040d7dbd53a90f545b450702340e17d18f3" - integrity sha512-UGTRZu1evMw4uTPyYF66/KFd22XiU+jMaIuHrkIHQ2GivAXVlLV0v/vHrpOuTRf9BmpNHi/SO7Vd0rLu0y57jg== +ts-dedent@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.0.0.tgz#47c5eb23d9096f3237cc413bc82d387d36dbe690" + integrity sha512-DfxKjSFQfw9+uf7N9Cy8Ebx9fv5fquK4hZ6SD3Rzr+1jKP6AVA6H8+B5457ZpUs0JKsGpGqIevbpZ9DMQJDp1A== ts-easing@^0.2.0: version "0.2.0" @@ -24206,6 +24095,11 @@ tslib@^1.10.0, tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: resolved "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== +tslib@^2.0.1: + version "2.0.3" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c" + integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ== + tsutils@^3.17.1: version "3.17.1" resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" @@ -24318,11 +24212,6 @@ typed-rest-client@^1.7.3: tunnel "0.0.6" underscore "1.8.3" -typed-styles@^0.0.7: - version "0.0.7" - resolved "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.7.tgz#93392a008794c4595119ff62dde6809dbc40a3d9" - integrity sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q== - typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -25058,6 +24947,11 @@ webpack-dev-server@^3.11.0: ws "^6.2.1" yargs "^13.3.2" +webpack-filter-warnings-plugin@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/webpack-filter-warnings-plugin/-/webpack-filter-warnings-plugin-1.2.1.tgz#dc61521cf4f9b4a336fbc89108a75ae1da951cdb" + integrity sha512-Ez6ytc9IseDMLPo0qCuNNYzgtUl8NovOqjIq4uAU8LTD4uoa1w1KpZyyzFtLTEMZpkkOkLfL9eN+KGYdk1Qtwg== + webpack-hot-middleware@^2.25.0: version "2.25.0" resolved "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.25.0.tgz#4528a0a63ec37f8f8ef565cf9e534d57d09fe706" @@ -25068,16 +24962,6 @@ webpack-hot-middleware@^2.25.0: querystring "^0.2.0" strip-ansi "^3.0.0" -webpack-log@^1.1.2: - version "1.2.0" - resolved "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz#a4b34cda6b22b518dbb0ab32e567962d5c72a43d" - integrity sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA== - dependencies: - chalk "^2.1.0" - log-symbols "^2.1.0" - loglevelnext "^1.0.1" - uuid "^3.1.0" - webpack-log@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" @@ -25106,7 +24990,7 @@ webpack-virtual-modules@^0.2.2: dependencies: debug "^3.0.0" -webpack@^4.41.6, webpack@^4.43.0: +webpack@^4.41.6: version "4.44.1" resolved "https://registry.npmjs.org/webpack/-/webpack-4.44.1.tgz#17e69fff9f321b8f117d1fda714edfc0b939cc21" integrity sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ== @@ -25135,6 +25019,35 @@ webpack@^4.41.6, webpack@^4.43.0: watchpack "^1.7.4" webpack-sources "^1.4.1" +webpack@^4.44.2: + version "4.44.2" + resolved "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz#6bfe2b0af055c8b2d1e90ed2cd9363f841266b72" + integrity sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/wasm-edit" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + acorn "^6.4.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" + chrome-trace-event "^1.0.2" + enhanced-resolve "^4.3.0" + eslint-scope "^4.0.3" + json-parse-better-errors "^1.0.2" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.3" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" + schema-utils "^1.0.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.3" + watchpack "^1.7.4" + webpack-sources "^1.4.1" + websocket-driver@0.6.5: version "0.6.5" resolved "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz#5cb2556ceb85f4373c6d8238aa691c8454e13a36" From 1499741e3bca21c3527b1d1179e35b86635baa0f Mon Sep 17 00:00:00 2001 From: Peter Colapietro Date: Mon, 14 Dec 2020 10:49:04 -0500 Subject: [PATCH 30/98] build(yarn): run dedupe tool for just webpack ran `npx yarn-deduplicate yarn.lock --packages webpack` --- yarn.lock | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/yarn.lock b/yarn.lock index 021ab60896..4d42ef8fb7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24990,36 +24990,7 @@ webpack-virtual-modules@^0.2.2: dependencies: debug "^3.0.0" -webpack@^4.41.6: - version "4.44.1" - resolved "https://registry.npmjs.org/webpack/-/webpack-4.44.1.tgz#17e69fff9f321b8f117d1fda714edfc0b939cc21" - integrity sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-module-context" "1.9.0" - "@webassemblyjs/wasm-edit" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" - acorn "^6.4.1" - ajv "^6.10.2" - ajv-keywords "^3.4.1" - chrome-trace-event "^1.0.2" - enhanced-resolve "^4.3.0" - eslint-scope "^4.0.3" - json-parse-better-errors "^1.0.2" - loader-runner "^2.4.0" - loader-utils "^1.2.3" - memory-fs "^0.4.1" - micromatch "^3.1.10" - mkdirp "^0.5.3" - neo-async "^2.6.1" - node-libs-browser "^2.2.1" - schema-utils "^1.0.0" - tapable "^1.1.3" - terser-webpack-plugin "^1.4.3" - watchpack "^1.7.4" - webpack-sources "^1.4.1" - -webpack@^4.44.2: +webpack@^4.41.6, webpack@^4.44.2: version "4.44.2" resolved "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz#6bfe2b0af055c8b2d1e90ed2cd9363f841266b72" integrity sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q== From 45c26e50ff75f53e9613fc5252c2fad86f19260e Mon Sep 17 00:00:00 2001 From: Peter Colapietro Date: Mon, 14 Dec 2020 10:28:42 -0500 Subject: [PATCH 31/98] build(yarn): add @octokit/openapi-types avoids: ``` node_modules/@octokit/core/node_modules/@octokit/types/dist-types/generated/Endpoints.d.ts:1:23 - error TS2307: Cannot find module '@octokit/openapi-types' or its corresponding type declarations. 1 import { paths } from "@octokit/openapi-types"; ~~~~~~~~~~~~~~~~~~~~~~~~ Found 1 error. error Command failed with exit code 1. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. ``` --- package.json | 1 + yarn.lock | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/package.json b/package.json index b89ac76d9e..887b256628 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "version": "1.0.0", "devDependencies": { "@changesets/cli": "^2.11.0", + "@octokit/openapi-types": "^2.0.0", "@spotify/eslint-config-oss": "^1.0.1", "@spotify/prettier-config": "^8.0.0", "command-exists": "^1.2.9", diff --git a/yarn.lock b/yarn.lock index 4d42ef8fb7..9f03f6eb10 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3920,6 +3920,11 @@ "@octokit/types" "^5.0.0" universal-user-agent "^6.0.0" +"@octokit/openapi-types@^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-2.0.0.tgz#6d8f8ad9db3b75a39115f5def2654df8bed39f28" + integrity sha512-J4bfM7lf8oZvEAdpS71oTvC1ofKxfEZgU5vKVwzZKi4QPiL82udjpseJwxPid9Pu2FNmyRQOX4iEj6W1iOSnPw== + "@octokit/plugin-enterprise-rest@^6.0.1": version "6.0.1" resolved "https://registry.npmjs.org/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz#e07896739618dab8da7d4077c658003775f95437" From 3d493a4bceab80dcd5514096ea81e47bbe5b44c2 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 15 Dec 2020 15:59:56 +0100 Subject: [PATCH 32/98] chore: updating the tests to be a little nicer --- packages/integration/src/bitbucket/core.test.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/integration/src/bitbucket/core.test.ts b/packages/integration/src/bitbucket/core.test.ts index c6fe5ddf6c..39707976fe 100644 --- a/packages/integration/src/bitbucket/core.test.ts +++ b/packages/integration/src/bitbucket/core.test.ts @@ -144,8 +144,7 @@ describe('bitbucket core', () => { }; worker.use( rest.get( - // TODO: Change URL to https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/branches/default when git-url-parse bug is fixed - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/projects/backstage/repos/mock/repos/browse/branches/default', + 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/branches/default', (_, res, ctx) => res( ctx.status(200), @@ -159,13 +158,13 @@ describe('bitbucket core', () => { apiBaseUrl: 'https://api.bitbucket.mycompany.net/rest/api/1.0', }; const result = await getBitbucketDownloadUrl( - 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse?at=main', + 'https://bitbucket.mycompany.net/projects/backstage/repos/mock/browse', config, ); - expect(new URL(result).searchParams.get('format')).toEqual('zip'); - expect(new URL(result).searchParams.get('at')).toEqual('main'); - expect(new URL(result).searchParams.get('prefix')).not.toBeNull(); - expect(new URL(result).searchParams.get('path')).toBeNull(); + + expect(result).toEqual( + 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/archive?format=zip&at=main&prefix=backstage-mock', + ); }); it('get by branch for Bitbucket Server', async () => { From 1da7d2c6574540255689a8eabc19284ee2e9130f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 15 Dec 2020 19:04:50 +0100 Subject: [PATCH 33/98] plugins,packages: replace usages of ConfigReader.from --- .../src/database/SingleConnection.test.ts | 10 +-- .../src/database/connection.test.ts | 20 ++---- .../src/database/postgres.test.ts | 10 +-- .../src/database/sqlite3.test.ts | 10 +-- .../src/service/lib/config.test.ts | 12 +--- packages/config/src/reader.ts | 2 +- .../src/azure/AzureIntegration.test.ts | 21 +++---- packages/integration/src/azure/config.test.ts | 6 +- .../bitbucket/BitbucketIntegration.test.ts | 27 ++++---- .../integration/src/bitbucket/config.test.ts | 6 +- .../src/github/GitHubIntegration.test.ts | 25 +++----- .../integration/src/github/config.test.ts | 6 +- .../src/gitlab/GitLabIntegration.test.ts | 21 +++---- .../integration/src/gitlab/config.test.ts | 6 +- packages/storybook/.storybook/apis.js | 2 +- .../src/stages/generate/generators.test.ts | 5 +- .../src/stages/publish/googleStorage.test.ts | 25 +++----- .../src/stages/publish/local.test.ts | 15 ++--- .../src/stages/publish/publish.test.ts | 55 ++++++---------- .../GithubOrgReaderProcessor.test.ts | 11 +--- .../ingestion/processors/ldap/config.test.ts | 8 +-- .../processors/microsoftGraph/config.test.ts | 8 +-- .../src/service/CatalogBuilder.test.ts | 2 +- .../src/graphql/module.test.ts | 13 ++-- plugins/graphql/src/service/router.test.ts | 4 +- .../ConfigClusterLocator.test.ts | 63 ++++++++----------- .../src/cluster-locator/index.test.ts | 2 +- .../src/service/standaloneApplication.ts | 2 +- .../src/service/router.test.ts | 4 +- .../scaffolder/stages/prepare/azure.test.ts | 25 +++----- .../scaffolder/stages/prepare/gitlab.test.ts | 25 +++----- .../src/service/router.test.ts | 15 ++--- .../src/service/standaloneServer.ts | 15 ++--- .../AuthProviders/AuthProviders.test.tsx | 15 ++--- 34 files changed, 174 insertions(+), 322 deletions(-) diff --git a/packages/backend-common/src/database/SingleConnection.test.ts b/packages/backend-common/src/database/SingleConnection.test.ts index 6278e4ecad..3466b0f79d 100644 --- a/packages/backend-common/src/database/SingleConnection.test.ts +++ b/packages/backend-common/src/database/SingleConnection.test.ts @@ -21,14 +21,6 @@ import { SingleConnectionDatabaseManager } from './SingleConnection'; jest.mock('./connection'); describe('SingleConnectionDatabaseManager', () => { - const createConfig = (data: any) => - ConfigReader.fromConfigs([ - { - context: '', - data, - }, - ]); - const defaultConfigOptions = { backend: { database: { @@ -42,7 +34,7 @@ describe('SingleConnectionDatabaseManager', () => { }, }, }; - const defaultConfig = () => createConfig(defaultConfigOptions); + const defaultConfig = () => new ConfigReader(defaultConfigOptions); // This is similar to the ts-jest `mocked` helper. const mocked = (f: Function) => f as jest.Mock; diff --git a/packages/backend-common/src/database/connection.test.ts b/packages/backend-common/src/database/connection.test.ts index de0b0e40dc..9810ff9bef 100644 --- a/packages/backend-common/src/database/connection.test.ts +++ b/packages/backend-common/src/database/connection.test.ts @@ -18,19 +18,11 @@ import { ConfigReader } from '@backstage/config'; import { createDatabaseClient } from './connection'; describe('database connection', () => { - const createConfig = (data: any) => - ConfigReader.fromConfigs([ - { - context: '', - data, - }, - ]); - describe('createDatabaseClient', () => { it('returns a postgres connection', () => { expect( createDatabaseClient( - createConfig({ + new ConfigReader({ client: 'pg', connection: { host: 'acme', @@ -46,7 +38,7 @@ describe('database connection', () => { it('returns an sqlite connection', () => { expect( createDatabaseClient( - createConfig({ + new ConfigReader({ client: 'sqlite3', connection: ':memory:', }), @@ -57,7 +49,7 @@ describe('database connection', () => { it('tries to create a mysql connection as a passthrough', () => { expect(() => createDatabaseClient( - createConfig({ + new ConfigReader({ client: 'mysql', connection: { host: '127.0.0.1', @@ -73,7 +65,7 @@ describe('database connection', () => { it('accepts overrides', () => { expect( createDatabaseClient( - createConfig({ + new ConfigReader({ client: 'pg', connection: { host: 'acme', @@ -94,7 +86,7 @@ describe('database connection', () => { it('throws an error without a client', () => { expect(() => createDatabaseClient( - createConfig({ + new ConfigReader({ connection: '', }), ), @@ -104,7 +96,7 @@ describe('database connection', () => { it('throws an error without a connection', () => { expect(() => createDatabaseClient( - createConfig({ + new ConfigReader({ client: 'pg', }), ), diff --git a/packages/backend-common/src/database/postgres.test.ts b/packages/backend-common/src/database/postgres.test.ts index 8d139e4481..59c135f309 100644 --- a/packages/backend-common/src/database/postgres.test.ts +++ b/packages/backend-common/src/database/postgres.test.ts @@ -34,15 +34,7 @@ describe('postgres', () => { 'postgresql://foo:bar@acme:5432/foodb'; const createConfig = (connection: any): Config => - ConfigReader.fromConfigs([ - { - context: '', - data: { - client: 'pg', - connection, - }, - }, - ]); + new ConfigReader({ client: 'pg', connection }); describe('buildPgDatabaseConfig', () => { it('builds a postgres config', () => { diff --git a/packages/backend-common/src/database/sqlite3.test.ts b/packages/backend-common/src/database/sqlite3.test.ts index a3ab331c2d..a6b8e5d84d 100644 --- a/packages/backend-common/src/database/sqlite3.test.ts +++ b/packages/backend-common/src/database/sqlite3.test.ts @@ -22,15 +22,7 @@ import { describe('sqlite3', () => { const createConfig = (connection: any) => - ConfigReader.fromConfigs([ - { - context: '', - data: { - client: 'sqlite3', - connection, - }, - }, - ]); + new ConfigReader({ client: 'sqlite3', connection }); describe('buildSqliteDatabaseConfig', () => { it('buidls a string connection', () => { diff --git a/packages/backend-common/src/service/lib/config.test.ts b/packages/backend-common/src/service/lib/config.test.ts index 8a35f147ca..75252357d6 100644 --- a/packages/backend-common/src/service/lib/config.test.ts +++ b/packages/backend-common/src/service/lib/config.test.ts @@ -20,9 +20,7 @@ import { readCspOptions } from './config'; describe('config', () => { describe('readCspOptions', () => { it('reads valid values', () => { - const config = ConfigReader.fromConfigs([ - { context: '', data: { csp: { key: ['value'] } } }, - ]); + const config = new ConfigReader({ csp: { key: ['value'] } }); expect(readCspOptions(config)).toEqual( expect.objectContaining({ key: ['value'], @@ -31,9 +29,7 @@ describe('config', () => { }); it('accepts false', () => { - const config = ConfigReader.fromConfigs([ - { context: '', data: { csp: { key: false } } }, - ]); + const config = new ConfigReader({ csp: { key: false } }); expect(readCspOptions(config)).toEqual( expect.objectContaining({ key: false, @@ -42,9 +38,7 @@ describe('config', () => { }); it('rejects invalid value types', () => { - const config = ConfigReader.fromConfigs([ - { context: '', data: { csp: { key: [4] } } }, - ]); + const config = new ConfigReader({ csp: { key: [4] } }); expect(() => readCspOptions(config)).toThrow(/wanted string-array/); }); }); diff --git a/packages/config/src/reader.ts b/packages/config/src/reader.ts index cd0a6f3221..c690e0bbc9 100644 --- a/packages/config/src/reader.ts +++ b/packages/config/src/reader.ts @@ -69,7 +69,7 @@ export class ConfigReader implements Config { constructor( private readonly data: JsonObject | undefined, - private readonly context: string = 'empty-config', + private readonly context: string = 'mock-config', private readonly fallback?: ConfigReader, private readonly prefix: string = '', ) {} diff --git a/packages/integration/src/azure/AzureIntegration.test.ts b/packages/integration/src/azure/AzureIntegration.test.ts index aec37ce905..4a0c32badb 100644 --- a/packages/integration/src/azure/AzureIntegration.test.ts +++ b/packages/integration/src/azure/AzureIntegration.test.ts @@ -20,21 +20,16 @@ import { AzureIntegration } from './AzureIntegration'; describe('AzureIntegration', () => { it('has a working factory', () => { const integrations = AzureIntegration.factory({ - config: ConfigReader.fromConfigs([ - { - context: '', - data: { - integrations: { - azure: [ - { - host: 'h.com', - token: 'token', - }, - ], + config: new ConfigReader({ + integrations: { + azure: [ + { + host: 'h.com', + token: 'token', }, - }, + ], }, - ]), + }), }); expect(integrations.length).toBe(2); // including default expect(integrations[0].predicate(new URL('https://h.com/a'))).toBe(true); diff --git a/packages/integration/src/azure/config.test.ts b/packages/integration/src/azure/config.test.ts index 0b943f2081..eed88f09f6 100644 --- a/packages/integration/src/azure/config.test.ts +++ b/packages/integration/src/azure/config.test.ts @@ -23,7 +23,7 @@ import { describe('readAzureIntegrationConfig', () => { function buildConfig(data: Partial): Config { - return ConfigReader.fromConfigs([{ context: '', data }]); + return new ConfigReader(data); } it('reads all values', () => { @@ -60,9 +60,7 @@ describe('readAzureIntegrationConfig', () => { describe('readAzureIntegrationConfigs', () => { function buildConfig(data: Partial[]): Config[] { - return data.map(item => - ConfigReader.fromConfigs([{ context: '', data: item }]), - ); + return data.map(item => new ConfigReader(item)); } it('reads all values', () => { diff --git a/packages/integration/src/bitbucket/BitbucketIntegration.test.ts b/packages/integration/src/bitbucket/BitbucketIntegration.test.ts index 174b6ab232..87dbac2263 100644 --- a/packages/integration/src/bitbucket/BitbucketIntegration.test.ts +++ b/packages/integration/src/bitbucket/BitbucketIntegration.test.ts @@ -20,24 +20,19 @@ import { BitbucketIntegration } from './BitbucketIntegration'; describe('BitbucketIntegration', () => { it('has a working factory', () => { const integrations = BitbucketIntegration.factory({ - config: ConfigReader.fromConfigs([ - { - context: '', - data: { - integrations: { - bitbucket: [ - { - host: 'h.com', - apiBaseUrl: 'a', - token: 't', - username: 'u', - appPassword: 'p', - }, - ], + config: new ConfigReader({ + integrations: { + bitbucket: [ + { + host: 'h.com', + apiBaseUrl: 'a', + token: 't', + username: 'u', + appPassword: 'p', }, - }, + ], }, - ]), + }), }); expect(integrations.length).toBe(2); // including default expect(integrations[0].predicate(new URL('https://h.com/a'))).toBe(true); diff --git a/packages/integration/src/bitbucket/config.test.ts b/packages/integration/src/bitbucket/config.test.ts index 775a8b7d2d..9106afbe4f 100644 --- a/packages/integration/src/bitbucket/config.test.ts +++ b/packages/integration/src/bitbucket/config.test.ts @@ -23,7 +23,7 @@ import { describe('readBitbucketIntegrationConfig', () => { function buildConfig(data: Partial): Config { - return ConfigReader.fromConfigs([{ context: '', data }]); + return new ConfigReader(data); } it('reads all values', () => { @@ -83,9 +83,7 @@ describe('readBitbucketIntegrationConfig', () => { describe('readBitbucketIntegrationConfigs', () => { function buildConfig(data: Partial[]): Config[] { - return data.map(item => - ConfigReader.fromConfigs([{ context: '', data: item }]), - ); + return data.map(item => new ConfigReader(item)); } it('reads all values', () => { diff --git a/packages/integration/src/github/GitHubIntegration.test.ts b/packages/integration/src/github/GitHubIntegration.test.ts index 3383c9ebe7..0c326d81cd 100644 --- a/packages/integration/src/github/GitHubIntegration.test.ts +++ b/packages/integration/src/github/GitHubIntegration.test.ts @@ -20,23 +20,18 @@ import { GitHubIntegration } from './GitHubIntegration'; describe('GitHubIntegration', () => { it('has a working factory', () => { const integrations = GitHubIntegration.factory({ - config: ConfigReader.fromConfigs([ - { - context: '', - data: { - integrations: { - github: [ - { - host: 'h.com', - apiBaseUrl: 'a', - rawBaseUrl: 'r', - token: 't', - }, - ], + config: new ConfigReader({ + integrations: { + github: [ + { + host: 'h.com', + apiBaseUrl: 'a', + rawBaseUrl: 'r', + token: 't', }, - }, + ], }, - ]), + }), }); expect(integrations.length).toBe(2); // including default expect(integrations[0].predicate(new URL('https://h.com/a'))).toBe(true); diff --git a/packages/integration/src/github/config.test.ts b/packages/integration/src/github/config.test.ts index d33cffb7be..bcac7dc82c 100644 --- a/packages/integration/src/github/config.test.ts +++ b/packages/integration/src/github/config.test.ts @@ -23,7 +23,7 @@ import { describe('readGitHubIntegrationConfig', () => { function buildConfig(provider: Partial) { - return ConfigReader.fromConfigs([{ context: '', data: provider }]); + return new ConfigReader(provider); } it('reads all values', () => { @@ -80,9 +80,7 @@ describe('readGitHubIntegrationConfigs', () => { function buildConfig( providers: Partial[], ): Config[] { - return providers.map(provider => - ConfigReader.fromConfigs([{ context: '', data: provider }]), - ); + return providers.map(provider => new ConfigReader(provider)); } it('reads all values', () => { diff --git a/packages/integration/src/gitlab/GitLabIntegration.test.ts b/packages/integration/src/gitlab/GitLabIntegration.test.ts index 4a23f55816..260afd23d8 100644 --- a/packages/integration/src/gitlab/GitLabIntegration.test.ts +++ b/packages/integration/src/gitlab/GitLabIntegration.test.ts @@ -20,21 +20,16 @@ import { GitLabIntegration } from './GitLabIntegration'; describe('GitLabIntegration', () => { it('has a working factory', () => { const integrations = GitLabIntegration.factory({ - config: ConfigReader.fromConfigs([ - { - context: '', - data: { - integrations: { - gitlab: [ - { - host: 'h.com', - token: 't', - }, - ], + config: new ConfigReader({ + integrations: { + gitlab: [ + { + host: 'h.com', + token: 't', }, - }, + ], }, - ]), + }), }); expect(integrations.length).toBe(2); // including default expect(integrations[0].predicate(new URL('https://h.com/a'))).toBe(true); diff --git a/packages/integration/src/gitlab/config.test.ts b/packages/integration/src/gitlab/config.test.ts index 9998a530c6..2c4224a2c4 100644 --- a/packages/integration/src/gitlab/config.test.ts +++ b/packages/integration/src/gitlab/config.test.ts @@ -23,7 +23,7 @@ import { describe('readGitLabIntegrationConfig', () => { function buildConfig(data: Partial): Config { - return ConfigReader.fromConfigs([{ context: '', data }]); + return new ConfigReader(data); } it('reads all values', () => { @@ -60,9 +60,7 @@ describe('readGitLabIntegrationConfig', () => { describe('readGitLabIntegrationConfigs', () => { function buildConfig(data: Partial[]): Config[] { - return data.map(item => - ConfigReader.fromConfigs([{ context: '', data: item }]), - ); + return data.map(item => new ConfigReader(item)); } it('reads all values', () => { diff --git a/packages/storybook/.storybook/apis.js b/packages/storybook/.storybook/apis.js index 878256ff5c..128ccfc67a 100644 --- a/packages/storybook/.storybook/apis.js +++ b/packages/storybook/.storybook/apis.js @@ -26,7 +26,7 @@ import { const builder = ApiRegistry.builder(); -builder.add(configApiRef, ConfigReader.fromConfigs([])); +builder.add(configApiRef, new ConfigReader({})); const alertApi = builder.add(alertApiRef, new AlertApiForwarder()); diff --git a/packages/techdocs-common/src/stages/generate/generators.test.ts b/packages/techdocs-common/src/stages/generate/generators.test.ts index 7f4a964ec7..3b59d6d007 100644 --- a/packages/techdocs-common/src/stages/generate/generators.test.ts +++ b/packages/techdocs-common/src/stages/generate/generators.test.ts @@ -39,10 +39,7 @@ describe('generators', () => { it('should return correct registered generator', async () => { const generators = new Generators(); - const techdocs = new TechdocsGenerator( - logger, - ConfigReader.fromConfigs([]), - ); + const techdocs = new TechdocsGenerator(logger, new ConfigReader({})); generators.register('techdocs', techdocs); diff --git a/packages/techdocs-common/src/stages/publish/googleStorage.test.ts b/packages/techdocs-common/src/stages/publish/googleStorage.test.ts index 2268ea3fcc..43375b72d0 100644 --- a/packages/techdocs-common/src/stages/publish/googleStorage.test.ts +++ b/packages/techdocs-common/src/stages/publish/googleStorage.test.ts @@ -38,24 +38,19 @@ jest.spyOn(logger, 'info').mockReturnValue(logger); let publisher: PublisherBase; beforeEach(() => { - const mockConfig = ConfigReader.fromConfigs([ - { - context: '', - data: { - techdocs: { - requestUrl: 'http://localhost:7000', - publisher: { - type: 'googleGcs', - googleGcs: { - credentials: '{}', - projectId: 'gcp-project-id', - bucketName: 'bucketName', - }, - }, + const mockConfig = new ConfigReader({ + techdocs: { + requestUrl: 'http://localhost:7000', + publisher: { + type: 'googleGcs', + googleGcs: { + credentials: '{}', + projectId: 'gcp-project-id', + bucketName: 'bucketName', }, }, }, - ]); + }); publisher = GoogleGCSPublish.fromConfig(mockConfig, logger); }); diff --git a/packages/techdocs-common/src/stages/publish/local.test.ts b/packages/techdocs-common/src/stages/publish/local.test.ts index 665ba28c52..efd56285ef 100644 --- a/packages/techdocs-common/src/stages/publish/local.test.ts +++ b/packages/techdocs-common/src/stages/publish/local.test.ts @@ -63,17 +63,12 @@ describe('local publisher', () => { getExternalBaseUrl: jest.fn(), }; - const mockConfig = ConfigReader.fromConfigs([ - { - context: '', - data: { - techdocs: { - requestUrl: 'http://localhost:7000', - storageUrl: 'http://localhost:7000/static/docs', - }, - }, + const mockConfig = new ConfigReader({ + techdocs: { + requestUrl: 'http://localhost:7000', + storageUrl: 'http://localhost:7000/static/docs', }, - ]); + }); const publisher = new LocalPublish(mockConfig, logger, testDiscovery); const mockEntity = createMockEntity(); diff --git a/packages/techdocs-common/src/stages/publish/publish.test.ts b/packages/techdocs-common/src/stages/publish/publish.test.ts index 244a606129..dbced6db29 100644 --- a/packages/techdocs-common/src/stages/publish/publish.test.ts +++ b/packages/techdocs-common/src/stages/publish/publish.test.ts @@ -30,59 +30,44 @@ const testDiscovery: jest.Mocked = { describe('Publisher', () => { it('should create local publisher by default', () => { - const mockConfig = ConfigReader.fromConfigs([ - { - context: '', - data: { - techdocs: { - requestUrl: 'http://localhost:7000', - }, - }, + const mockConfig = new ConfigReader({ + techdocs: { + requestUrl: 'http://localhost:7000', }, - ]); + }); const publisher = Publisher.fromConfig(mockConfig, logger, testDiscovery); expect(publisher).toBeInstanceOf(LocalPublish); }); it('should create local publisher from config', () => { - const mockConfig = ConfigReader.fromConfigs([ - { - context: '', - data: { - techdocs: { - requestUrl: 'http://localhost:7000', - publisher: { - type: 'local', - }, - }, + const mockConfig = new ConfigReader({ + techdocs: { + requestUrl: 'http://localhost:7000', + publisher: { + type: 'local', }, }, - ]); + }); const publisher = Publisher.fromConfig(mockConfig, logger, testDiscovery); expect(publisher).toBeInstanceOf(LocalPublish); }); it('should create google gcs publisher from config', () => { - const mockConfig = ConfigReader.fromConfigs([ - { - context: '', - data: { - techdocs: { - requestUrl: 'http://localhost:7000', - publisher: { - type: 'googleGcs', - googleGcs: { - credentials: '{}', - projectId: 'gcp-project-id', - bucketName: 'bucketName', - }, - }, + const mockConfig = new ConfigReader({ + techdocs: { + requestUrl: 'http://localhost:7000', + publisher: { + type: 'googleGcs', + googleGcs: { + credentials: '{}', + projectId: 'gcp-project-id', + bucketName: 'bucketName', }, }, }, - ]); + }); const publisher = Publisher.fromConfig(mockConfig, logger, testDiscovery); expect(publisher).toBeInstanceOf(GoogleGCSPublish); diff --git a/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.test.ts index fdba32ef7e..a6a05b15ba 100644 --- a/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.test.ts @@ -28,14 +28,9 @@ describe('GithubOrgReaderProcessor', () => { function config( providers: { target: string; apiBaseUrl?: string; token?: string }[], ) { - return ConfigReader.fromConfigs([ - { - context: '', - data: { - catalog: { processors: { githubOrg: { providers } } }, - }, - }, - ]); + return new ConfigReader({ + catalog: { processors: { githubOrg: { providers } } }, + }); } it('adds a default GitHub entry when missing', () => { diff --git a/plugins/catalog-backend/src/ingestion/processors/ldap/config.test.ts b/plugins/catalog-backend/src/ingestion/processors/ldap/config.test.ts index cc43827d87..5e293766aa 100644 --- a/plugins/catalog-backend/src/ingestion/processors/ldap/config.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/ldap/config.test.ts @@ -32,9 +32,7 @@ describe('readLdapConfig', () => { }, ], }; - const actual = readLdapConfig( - ConfigReader.fromConfigs([{ context: '', data: config }]), - ); + const actual = readLdapConfig(new ConfigReader(config)); const expected = [ { target: 'target', @@ -125,9 +123,7 @@ describe('readLdapConfig', () => { }, ], }; - const actual = readLdapConfig( - ConfigReader.fromConfigs([{ context: '', data: config }]), - ); + const actual = readLdapConfig(new ConfigReader(config)); const expected = [ { target: 'target', diff --git a/plugins/catalog-backend/src/ingestion/processors/microsoftGraph/config.test.ts b/plugins/catalog-backend/src/ingestion/processors/microsoftGraph/config.test.ts index 11c63828d4..4671fd23ae 100644 --- a/plugins/catalog-backend/src/ingestion/processors/microsoftGraph/config.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/microsoftGraph/config.test.ts @@ -29,9 +29,7 @@ describe('readMicrosoftGraphConfig', () => { }, ], }; - const actual = readMicrosoftGraphConfig( - ConfigReader.fromConfigs([{ context: '', data: config }]), - ); + const actual = readMicrosoftGraphConfig(new ConfigReader(config)); const expected = [ { target: 'target', @@ -60,9 +58,7 @@ describe('readMicrosoftGraphConfig', () => { }, ], }; - const actual = readMicrosoftGraphConfig( - ConfigReader.fromConfigs([{ context: '', data: config }]), - ); + const actual = readMicrosoftGraphConfig(new ConfigReader(config)); const expected = [ { target: 'target', diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.test.ts b/plugins/catalog-backend/src/service/CatalogBuilder.test.ts index 58897a10a7..37337f76f1 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.test.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.test.ts @@ -47,7 +47,7 @@ describe('CatalogBuilder', () => { const env: CatalogEnvironment = { logger: getVoidLogger(), database: { getClient: async () => db }, - config: ConfigReader.fromConfigs([]), + config: new ConfigReader({}), reader, }; diff --git a/plugins/catalog-graphql/src/graphql/module.test.ts b/plugins/catalog-graphql/src/graphql/module.test.ts index b359c4396b..e6e9d59df7 100644 --- a/plugins/catalog-graphql/src/graphql/module.test.ts +++ b/plugins/catalog-graphql/src/graphql/module.test.ts @@ -27,16 +27,11 @@ import { gql } from 'apollo-server'; describe('Catalog Module', () => { const worker = setupServer(); const mockCatalogBaseUrl = 'http://im.mock'; - const mockConfig = ConfigReader.fromConfigs([ - { - context: '', - data: { - backend: { - baseUrl: mockCatalogBaseUrl, - }, - }, + const mockConfig = new ConfigReader({ + backend: { + baseUrl: mockCatalogBaseUrl, }, - ]); + }); msw.setupDefaultHandlers(worker); diff --git a/plugins/graphql/src/service/router.test.ts b/plugins/graphql/src/service/router.test.ts index 983fbbb761..3bc52b0548 100644 --- a/plugins/graphql/src/service/router.test.ts +++ b/plugins/graphql/src/service/router.test.ts @@ -22,9 +22,7 @@ import express from 'express'; describe('Router', () => { describe('/health', () => { it('should return ok', async () => { - const config = ConfigReader.fromConfigs([ - { data: { backend: { baseUrl: 'lol' } }, context: 'something' }, - ]); + const config = new ConfigReader({ backend: { baseUrl: 'lol' } }); const router = await createRouter({ config, logger: createLogger() }); const app = express().use(router); diff --git a/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.test.ts b/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.test.ts index 550703e430..339f886a53 100644 --- a/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.test.ts +++ b/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.test.ts @@ -20,12 +20,9 @@ import { ConfigClusterLocator } from './ConfigClusterLocator'; describe('ConfigClusterLocator', () => { it('empty clusters returns empty cluster details', async () => { - const config: Config = new ConfigReader( - { - clusters: [], - }, - 'ctx', - ); + const config: Config = new ConfigReader({ + clusters: [], + }); const sut = ConfigClusterLocator.fromConfig( config.getConfigArray('clusters'), @@ -37,18 +34,15 @@ describe('ConfigClusterLocator', () => { }); it('one clusters returns one cluster details', async () => { - const config: Config = new ConfigReader( - { - clusters: [ - { - name: 'cluster1', - url: 'http://localhost:8080', - authProvider: 'serviceAccount', - }, - ], - }, - 'ctx', - ); + const config: Config = new ConfigReader({ + clusters: [ + { + name: 'cluster1', + url: 'http://localhost:8080', + authProvider: 'serviceAccount', + }, + ], + }); const sut = ConfigClusterLocator.fromConfig( config.getConfigArray('clusters'), @@ -67,24 +61,21 @@ describe('ConfigClusterLocator', () => { }); it('two clusters returns two cluster details', async () => { - const config: Config = new ConfigReader( - { - clusters: [ - { - name: 'cluster1', - serviceAccountToken: 'token', - url: 'http://localhost:8080', - authProvider: 'serviceAccount', - }, - { - name: 'cluster2', - url: 'http://localhost:8081', - authProvider: 'google', - }, - ], - }, - 'ctx', - ); + const config: Config = new ConfigReader({ + clusters: [ + { + name: 'cluster1', + serviceAccountToken: 'token', + url: 'http://localhost:8080', + authProvider: 'serviceAccount', + }, + { + name: 'cluster2', + url: 'http://localhost:8081', + authProvider: 'google', + }, + ], + }); const sut = ConfigClusterLocator.fromConfig( config.getConfigArray('clusters'), diff --git a/plugins/kubernetes-backend/src/cluster-locator/index.test.ts b/plugins/kubernetes-backend/src/cluster-locator/index.test.ts index 5677fa2d0d..63018cd338 100644 --- a/plugins/kubernetes-backend/src/cluster-locator/index.test.ts +++ b/plugins/kubernetes-backend/src/cluster-locator/index.test.ts @@ -60,7 +60,7 @@ describe('getCombinedClusterDetails', () => { it('throws an error when using an unsupported cluster locator', async () => { await expect( - getCombinedClusterDetails(['magic' as any], new ConfigReader({}, 'ctx')), + getCombinedClusterDetails(['magic' as any], new ConfigReader({})), ).rejects.toStrictEqual( new Error('Unsupported kubernetes.clusterLocatorMethods: "magic"'), ); diff --git a/plugins/kubernetes-backend/src/service/standaloneApplication.ts b/plugins/kubernetes-backend/src/service/standaloneApplication.ts index e23e87a7a2..50563023d0 100644 --- a/plugins/kubernetes-backend/src/service/standaloneApplication.ts +++ b/plugins/kubernetes-backend/src/service/standaloneApplication.ts @@ -36,7 +36,7 @@ export async function createStandaloneApplication( options: ApplicationOptions, ): Promise { const { enableCors, logger } = options; - const config = ConfigReader.fromConfigs([]); + const config = new ConfigReader({}); const app = express(); app.use(helmet()); diff --git a/plugins/rollbar-backend/src/service/router.test.ts b/plugins/rollbar-backend/src/service/router.test.ts index c3f1c73e09..fb47e4ab7c 100644 --- a/plugins/rollbar-backend/src/service/router.test.ts +++ b/plugins/rollbar-backend/src/service/router.test.ts @@ -38,9 +38,7 @@ describe('createRouter', () => { const router = await createRouter({ rollbarApi, logger: getVoidLogger(), - config: ConfigReader.fromConfigs([ - { context: 'abc', data: { rollbar: { accountToken: 'foo' } } }, - ]), + config: new ConfigReader({ rollbar: { accountToken: 'foo' } }), }); app = express().use(router); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts index db3a110384..4d19069b5e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts @@ -78,7 +78,7 @@ describe('AzurePreparer', () => { }); it('calls the clone command with the correct arguments for a repository', async () => { - const preparer = new AzurePreparer(ConfigReader.fromConfigs([])); + const preparer = new AzurePreparer(new ConfigReader({})); await preparer.prepare(mockEntity, { logger: getVoidLogger() }); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, @@ -90,20 +90,15 @@ describe('AzurePreparer', () => { it('calls the clone command with the correct arguments if an access token is provided for a repository', async () => { const preparer = new AzurePreparer( - ConfigReader.fromConfigs([ - { - context: '', - data: { - scaffolder: { - azure: { - api: { - token: 'fake-token', - }, - }, + new ConfigReader({ + scaffolder: { + azure: { + api: { + token: 'fake-token', }, }, }, - ]), + }), ); await preparer.prepare(mockEntity, { logger: getVoidLogger() }); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( @@ -121,7 +116,7 @@ describe('AzurePreparer', () => { }); it('calls the clone command with the correct arguments for a repository when no path is provided', async () => { - const preparer = new AzurePreparer(ConfigReader.fromConfigs([])); + const preparer = new AzurePreparer(new ConfigReader({})); delete mockEntity.spec.path; await preparer.prepare(mockEntity, { logger: getVoidLogger() }); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( @@ -133,7 +128,7 @@ describe('AzurePreparer', () => { }); it('return the temp directory with the path to the folder if it is specified', async () => { - const preparer = new AzurePreparer(ConfigReader.fromConfigs([])); + const preparer = new AzurePreparer(new ConfigReader({})); mockEntity.spec.path = './template/test/1/2/3'; const response = await preparer.prepare(mockEntity, { logger: getVoidLogger(), @@ -145,7 +140,7 @@ describe('AzurePreparer', () => { }); it('return the working directory with the path to the folder if it is specified', async () => { - const preparer = new AzurePreparer(ConfigReader.fromConfigs([])); + const preparer = new AzurePreparer(new ConfigReader({})); mockEntity.spec.path = './template/test/1/2/3'; const response = await preparer.prepare(mockEntity, { logger: getVoidLogger(), diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts index a86a51e0dc..3d8d7faf7a 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts @@ -78,7 +78,7 @@ describe('GitLabPreparer', () => { ['gitlab', 'gitlab/api'].forEach(protocol => { it(`calls the clone command with the correct arguments for a repository using the ${protocol} protocol`, async () => { - const preparer = new GitlabPreparer(ConfigReader.fromConfigs([])); + const preparer = new GitlabPreparer(new ConfigReader({})); mockEntity = mockEntityWithProtocol(protocol); await preparer.prepare(mockEntity, { logger: getVoidLogger() }); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( @@ -91,20 +91,15 @@ describe('GitLabPreparer', () => { it(`calls the clone command with the correct arguments if an access token is provided for a repository using the ${protocol} protocol`, async () => { const preparer = new GitlabPreparer( - ConfigReader.fromConfigs([ - { - context: '', - data: { - catalog: { - processors: { - gitlabApi: { - privateToken: 'fake-token', - }, - }, + new ConfigReader({ + catalog: { + processors: { + gitlabApi: { + privateToken: 'fake-token', }, }, }, - ]), + }), ); mockEntity = mockEntityWithProtocol(protocol); await preparer.prepare(mockEntity, { logger: getVoidLogger() }); @@ -123,7 +118,7 @@ describe('GitLabPreparer', () => { }); it(`calls the clone command with the correct arguments for a repository when no path is provided using the ${protocol} protocol`, async () => { - const preparer = new GitlabPreparer(ConfigReader.fromConfigs([])); + const preparer = new GitlabPreparer(new ConfigReader({})); mockEntity = mockEntityWithProtocol(protocol); delete mockEntity.spec.path; await preparer.prepare(mockEntity, { logger: getVoidLogger() }); @@ -136,7 +131,7 @@ describe('GitLabPreparer', () => { }); it(`return the temp directory with the path to the folder if it is specified using the ${protocol} protocol`, async () => { - const preparer = new GitlabPreparer(ConfigReader.fromConfigs([])); + const preparer = new GitlabPreparer(new ConfigReader({})); mockEntity = mockEntityWithProtocol(protocol); mockEntity.spec.path = './template/test/1/2/3'; const response = await preparer.prepare(mockEntity, { @@ -149,7 +144,7 @@ describe('GitLabPreparer', () => { }); it('return the working directory with the path to the folder if it is specified', async () => { - const preparer = new GitlabPreparer(ConfigReader.fromConfigs([])); + const preparer = new GitlabPreparer(new ConfigReader({})); mockEntity.spec.path = './template/test/1/2/3'; const response = await preparer.prepare(mockEntity, { logger: getVoidLogger(), diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index 633d16b2a4..4d610299eb 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -55,11 +55,8 @@ describe('createRouter - working directory', () => { }); const workDirConfig = (path: string) => ({ - context: '', - data: { - backend: { - workingDirectory: path, - }, + backend: { + workingDirectory: path, }, }); @@ -91,7 +88,7 @@ describe('createRouter - working directory', () => { preparers: new Preparers(), templaters: new Templaters(), publishers: new Publishers(), - config: ConfigReader.fromConfigs([workDirConfig('/path')]), + config: new ConfigReader(workDirConfig('/path')), dockerClient: new Docker(), entityClient: mockedEntityClient, }), @@ -104,7 +101,7 @@ describe('createRouter - working directory', () => { preparers: mockPreparers, templaters: new Templaters(), publishers: new Publishers(), - config: ConfigReader.fromConfigs([workDirConfig('/path')]), + config: new ConfigReader(workDirConfig('/path')), dockerClient: new Docker(), entityClient: mockedEntityClient, }); @@ -127,7 +124,7 @@ describe('createRouter - working directory', () => { preparers: mockPreparers, templaters: new Templaters(), publishers: new Publishers(), - config: ConfigReader.fromConfigs([]), + config: new ConfigReader({}), dockerClient: new Docker(), entityClient: mockedEntityClient, }); @@ -190,7 +187,7 @@ describe('createRouter', () => { preparers: new Preparers(), templaters: new Templaters(), publishers: new Publishers(), - config: ConfigReader.fromConfigs([]), + config: new ConfigReader({}), dockerClient: new Docker(), entityClient: generateEntityClient(template), }); diff --git a/plugins/techdocs-backend/src/service/standaloneServer.ts b/plugins/techdocs-backend/src/service/standaloneServer.ts index c1c4dba8d1..3faf736ca0 100644 --- a/plugins/techdocs-backend/src/service/standaloneServer.ts +++ b/plugins/techdocs-backend/src/service/standaloneServer.ts @@ -41,18 +41,13 @@ export async function startStandaloneServer( options: ServerOptions, ): Promise { const logger = options.logger.child({ service: 'techdocs-backend' }); - const config = ConfigReader.fromConfigs([ - { - context: '', - data: { - techdocs: { - publisher: { - type: 'local', - }, - }, + const config = new ConfigReader({ + techdocs: { + publisher: { + type: 'local', }, }, - ]); + }); const discovery = SingleHostDiscovery.fromConfig(config); logger.debug('Creating application...'); diff --git a/plugins/user-settings/src/components/AuthProviders/AuthProviders.test.tsx b/plugins/user-settings/src/components/AuthProviders/AuthProviders.test.tsx index 4399b6bd3e..072c90ddac 100644 --- a/plugins/user-settings/src/components/AuthProviders/AuthProviders.test.tsx +++ b/plugins/user-settings/src/components/AuthProviders/AuthProviders.test.tsx @@ -37,18 +37,13 @@ const mockGoogleAuth = { }; const createConfig = () => - ConfigReader.fromConfigs([ - { - context: '', - data: { - auth: { - providers: { - google: { development: {} }, - }, - }, + new ConfigReader({ + auth: { + providers: { + google: { development: {} }, }, }, - ]); + }); const config = createConfig(); From 6dedcbddb03ec4eae3ef6357a3a4c1bb10fe0ffa Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Tue, 15 Dec 2020 19:28:50 +0100 Subject: [PATCH 34/98] Set correct MIME Type for all types of files served from techdocs-backend --- packages/techdocs-common/package.json | 2 + .../src/stages/publish/googleStorage.ts | 3 +- .../src/stages/publish/helpers.test.ts | 40 +++++++++---------- .../src/stages/publish/helpers.ts | 29 ++++---------- yarn.lock | 7 +++- 5 files changed, 35 insertions(+), 46 deletions(-) diff --git a/packages/techdocs-common/package.json b/packages/techdocs-common/package.json index adb138bdd9..fd767b4a64 100644 --- a/packages/techdocs-common/package.json +++ b/packages/techdocs-common/package.json @@ -48,6 +48,7 @@ "fs-extra": "^9.0.1", "git-url-parse": "^11.4.3", "js-yaml": "^3.14.0", + "mime-types": "^2.1.27", "mock-fs": "^4.13.0", "nodegit": "^0.27.0", "recursive-readdir": "^2.2.2", @@ -58,6 +59,7 @@ "@types/fs-extra": "^9.0.5", "@types/git-url-parse": "^9.0.0", "@types/js-yaml": "^3.12.5", + "@types/mime-types": "^2.1.0", "@types/mock-fs": "^4.13.0", "@types/nodegit": "^0.26.12", "@types/recursive-readdir": "^2.2.0" diff --git a/packages/techdocs-common/src/stages/publish/googleStorage.ts b/packages/techdocs-common/src/stages/publish/googleStorage.ts index 5f8dc6a3fc..b33e2bfbe0 100644 --- a/packages/techdocs-common/src/stages/publish/googleStorage.ts +++ b/packages/techdocs-common/src/stages/publish/googleStorage.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import path from 'path'; import express from 'express'; import { Storage, @@ -167,7 +168,7 @@ export class GoogleGCSPublish implements PublisherBase { const filePath = req.path.replace(/^\//, ''); // Files with different extensions (CSS, HTML) need to be served with different headers - const fileExtension = filePath.split('.')[filePath.split('.').length - 1]; + const fileExtension = path.extname(filePath); const responseHeaders = getHeadersForFileExtension(fileExtension); const fileStreamChunks: Array = []; diff --git a/packages/techdocs-common/src/stages/publish/helpers.test.ts b/packages/techdocs-common/src/stages/publish/helpers.test.ts index e4f0c12b79..3b01f5ac43 100644 --- a/packages/techdocs-common/src/stages/publish/helpers.test.ts +++ b/packages/techdocs-common/src/stages/publish/helpers.test.ts @@ -17,29 +17,25 @@ import mockFs from 'mock-fs'; import { getFileTreeRecursively, getHeadersForFileExtension } from './helpers'; describe('getHeadersForFileExtension', () => { - it('returns correct header for default extensions', () => { - const headers = getHeadersForFileExtension('xyz'); - const expectedHeaders = { - 'Content-Type': 'text/plain', - }; - expect(headers).toEqual(expectedHeaders); - }); + const correctMapOfExtensions = [ + ['.html', 'text/html; charset=utf-8'], + ['.css', 'text/css; charset=utf-8'], + ['.png', 'image/png'], + ['.jpg', 'image/jpeg'], + ['.jpeg', 'image/jpeg'], + ['.svg', 'image/svg+xml'], + ['.json', 'application/json; charset=utf-8'], + ['.this-in-not-an-extension', 'text/plain; charset=utf-8'], + ]; - it('returns correct header for html', () => { - const headers = getHeadersForFileExtension('html'); - const expectedHeaders = { - 'Content-Type': 'text/html; charset=UTF-8', - }; - expect(headers).toEqual(expectedHeaders); - }); - - it('returns correct header for css', () => { - const headers = getHeadersForFileExtension('css'); - const expectedHeaders = { - 'Content-Type': 'text/css; charset=UTF-8', - }; - expect(headers).toEqual(expectedHeaders); - }); + test.each(correctMapOfExtensions)( + 'check content-type for %s extension', + (extension, expectedContentType) => { + const headers = getHeadersForFileExtension(extension); + expect(headers).toHaveProperty('Content-Type'); + expect(headers['Content-Type'].toLowerCase()).toBe(expectedContentType); + }, + ); }); describe('getFileTreeRecursively', () => { diff --git a/packages/techdocs-common/src/stages/publish/helpers.ts b/packages/techdocs-common/src/stages/publish/helpers.ts index 38ff27e0a0..4d9e2d327e 100644 --- a/packages/techdocs-common/src/stages/publish/helpers.ts +++ b/packages/techdocs-common/src/stages/publish/helpers.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import mime from 'mime-types'; import recursiveReadDir from 'recursive-readdir'; export type responseHeadersType = { @@ -22,32 +23,16 @@ export type responseHeadersType = { /** * Some files need special headers to be used correctly by the frontend. This function * generates headers in the response to those file requests. - * @param {string} fileExtension html, css, js etc. + * @param {string} fileExtension .html, .css, .js, .png etc. */ export const getHeadersForFileExtension = ( fileExtension: string, ): responseHeadersType => { - const headersCommon = { - 'Content-Type': 'text/plain', - }; - const headersHTML = { - ...headersCommon, - 'Content-Type': 'text/html; charset=UTF-8', - }; - - const headersCSS = { - ...headersCommon, - 'Content-Type': 'text/css; charset=UTF-8', - }; - - switch (fileExtension) { - case 'html': - return headersHTML; - case 'css': - return headersCSS; - default: - return headersCommon; - } + return { + 'Content-Type': mime.contentType(fileExtension) + ? mime.contentType(fileExtension) + : 'text/plain; charset=utf-8', + } as responseHeadersType; }; /** diff --git a/yarn.lock b/yarn.lock index 3bbeea245d..c01ad2c05b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5887,6 +5887,11 @@ dependencies: "@types/braces" "*" +"@types/mime-types@^2.1.0": + version "2.1.0" + resolved "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz#9ca52cda363f699c69466c2a6ccdaad913ea7a73" + integrity sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM= + "@types/mime@*": version "2.0.1" resolved "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d" @@ -17416,7 +17421,7 @@ mime-db@1.44.0, "mime-db@>= 1.43.0 < 2": resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== -mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.26, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: +mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.26, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.27" resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== From 2e9734a3c198a6d55ae0a42fc8506a79b086ba5e Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Tue, 15 Dec 2020 19:55:18 +0100 Subject: [PATCH 35/98] docs: Level up header types in techdocs concepts page --- docs/features/techdocs/concepts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/techdocs/concepts.md b/docs/features/techdocs/concepts.md index 06e77ba168..48204342a9 100644 --- a/docs/features/techdocs/concepts.md +++ b/docs/features/techdocs/concepts.md @@ -20,7 +20,7 @@ There are two kinds of preparers available - 2. Url Reader - Uses source code hosting provider's API to download files. (Faster and recommended) -## TechDocs Generator +### TechDocs Generator Generation is the second step after preparing the markdown source files. This step either runs the TechDocs container (defined below) or runs `mkdocs` CLI to From 8db771faa06820c81d879f9967de35012066edc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 15 Dec 2020 21:14:02 +0100 Subject: [PATCH 36/98] catalog-model: use relative location targets in examples --- .../catalog-model/examples-relative/README.md | 10 - .../examples-relative/acme-corp.yaml | 8 - .../acme/backstage-group.yaml | 15 - .../acme/boxoffice-group.yaml | 15 - .../acme/infrastructure-group.yaml | 12 - .../examples-relative/acme/org.yaml | 30 - .../examples-relative/acme/team-a-group.yaml | 62 - .../examples-relative/acme/team-b-group.yaml | 70 - .../examples-relative/acme/team-c-group.yaml | 70 - .../examples-relative/acme/team-d-group.yaml | 37 - .../examples-relative/all-apis.yaml | 14 - .../examples-relative/all-components.yaml | 18 - .../apis/hello-world-api.yaml | 48 - .../examples-relative/apis/petstore-api.yaml | 124 -- .../examples-relative/apis/spotify-api.yaml | 17 - .../apis/streetlights-api.yaml | 221 ---- .../examples-relative/apis/swapi-graphql.yaml | 1176 ----------------- .../components/artist-lookup-component.yaml | 12 - .../components/petstore-component.yaml | 13 - .../components/playback-lib-component.yaml | 9 - .../components/playback-order-component.yaml | 12 - .../components/podcast-api-component.yaml | 11 - .../components/queue-proxy-component.yaml | 12 - .../components/searcher-component.yaml | 11 - .../components/shuffle-api-component.yaml | 11 - .../components/www-artist-component.yaml | 9 - packages/catalog-model/examples/README.md | 7 +- .../catalog-model/examples/acme-corp.yaml | 3 +- .../examples/acme/backstage-group.yaml | 4 + .../examples/acme/boxoffice-group.yaml | 4 + .../examples/acme/infrastructure-group.yaml | 1 + packages/catalog-model/examples/acme/org.yaml | 19 +- .../examples/acme/team-a-group.yaml | 6 +- .../examples/acme/team-b-group.yaml | 4 + .../examples/acme/team-c-group.yaml | 4 + .../examples/acme/team-d-group.yaml | 4 + packages/catalog-model/examples/all-apis.yaml | 13 +- .../examples/all-components.yaml | 21 +- .../apis/wayback-archive-api.yaml | 2 +- .../apis/wayback-search-api.yaml | 2 +- .../components/wayback-archive-component.yaml | 2 +- .../components/wayback-search-component.yaml | 2 +- 42 files changed, 62 insertions(+), 2083 deletions(-) delete mode 100644 packages/catalog-model/examples-relative/README.md delete mode 100644 packages/catalog-model/examples-relative/acme-corp.yaml delete mode 100644 packages/catalog-model/examples-relative/acme/backstage-group.yaml delete mode 100644 packages/catalog-model/examples-relative/acme/boxoffice-group.yaml delete mode 100644 packages/catalog-model/examples-relative/acme/infrastructure-group.yaml delete mode 100644 packages/catalog-model/examples-relative/acme/org.yaml delete mode 100644 packages/catalog-model/examples-relative/acme/team-a-group.yaml delete mode 100644 packages/catalog-model/examples-relative/acme/team-b-group.yaml delete mode 100644 packages/catalog-model/examples-relative/acme/team-c-group.yaml delete mode 100644 packages/catalog-model/examples-relative/acme/team-d-group.yaml delete mode 100644 packages/catalog-model/examples-relative/all-apis.yaml delete mode 100644 packages/catalog-model/examples-relative/all-components.yaml delete mode 100644 packages/catalog-model/examples-relative/apis/hello-world-api.yaml delete mode 100644 packages/catalog-model/examples-relative/apis/petstore-api.yaml delete mode 100644 packages/catalog-model/examples-relative/apis/spotify-api.yaml delete mode 100644 packages/catalog-model/examples-relative/apis/streetlights-api.yaml delete mode 100644 packages/catalog-model/examples-relative/apis/swapi-graphql.yaml delete mode 100644 packages/catalog-model/examples-relative/components/artist-lookup-component.yaml delete mode 100644 packages/catalog-model/examples-relative/components/petstore-component.yaml delete mode 100644 packages/catalog-model/examples-relative/components/playback-lib-component.yaml delete mode 100644 packages/catalog-model/examples-relative/components/playback-order-component.yaml delete mode 100644 packages/catalog-model/examples-relative/components/podcast-api-component.yaml delete mode 100644 packages/catalog-model/examples-relative/components/queue-proxy-component.yaml delete mode 100644 packages/catalog-model/examples-relative/components/searcher-component.yaml delete mode 100644 packages/catalog-model/examples-relative/components/shuffle-api-component.yaml delete mode 100644 packages/catalog-model/examples-relative/components/www-artist-component.yaml rename packages/catalog-model/{examples-relative => examples}/apis/wayback-archive-api.yaml (91%) rename packages/catalog-model/{examples-relative => examples}/apis/wayback-search-api.yaml (91%) rename packages/catalog-model/{examples-relative => examples}/components/wayback-archive-component.yaml (88%) rename packages/catalog-model/{examples-relative => examples}/components/wayback-search-component.yaml (89%) diff --git a/packages/catalog-model/examples-relative/README.md b/packages/catalog-model/examples-relative/README.md deleted file mode 100644 index 3ed63a0e00..0000000000 --- a/packages/catalog-model/examples-relative/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Examples with relative paths - -These examples use Location entities with relative paths -[see #3513](https://github.com/backstage/backstage/pull/3513). - -The `examples` sibling directory will be replaced with these contents no sooner -than December 16 2020, to give consumers time to adopt the above change. - -The contents of this directory is here for consumers who are on the edge and -want to use the new facility before December 16. diff --git a/packages/catalog-model/examples-relative/acme-corp.yaml b/packages/catalog-model/examples-relative/acme-corp.yaml deleted file mode 100644 index 6449d548e0..0000000000 --- a/packages/catalog-model/examples-relative/acme-corp.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Location -metadata: - name: acme-corp - description: A collection of all Backstage example Groups -spec: - targets: - - ./acme/org.yaml diff --git a/packages/catalog-model/examples-relative/acme/backstage-group.yaml b/packages/catalog-model/examples-relative/acme/backstage-group.yaml deleted file mode 100644 index 1cfd469e99..0000000000 --- a/packages/catalog-model/examples-relative/acme/backstage-group.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Group -metadata: - name: backstage - description: The backstage sub-department -spec: - type: sub-department - profile: - displayName: Backstage - email: backstage@example.com - picture: https://example.com/groups/backstage.jpeg - parent: infrastructure - ancestors: [infrastructure, acme-corp] - children: [team-a, team-b] - descendants: [team-a, team-b] diff --git a/packages/catalog-model/examples-relative/acme/boxoffice-group.yaml b/packages/catalog-model/examples-relative/acme/boxoffice-group.yaml deleted file mode 100644 index 4bb742bdb1..0000000000 --- a/packages/catalog-model/examples-relative/acme/boxoffice-group.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Group -metadata: - name: boxoffice - description: The boxoffice sub-department -spec: - type: sub-department - profile: - displayName: Box Office - email: boxoffice@example.com - # Intentional no picture for testing - parent: infrastructure - ancestors: [infrastructure, acme-corp] - children: [team-c, team-d] - descendants: [team-c, team-d] diff --git a/packages/catalog-model/examples-relative/acme/infrastructure-group.yaml b/packages/catalog-model/examples-relative/acme/infrastructure-group.yaml deleted file mode 100644 index acfeef642c..0000000000 --- a/packages/catalog-model/examples-relative/acme/infrastructure-group.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Group -metadata: - name: infrastructure - description: The infra department -spec: - type: department - # Intentional no profile for testing - parent: acme-corp - ancestors: [acme-corp] - children: [backstage, boxoffice] - descendants: [backstage, boxoffice, team-a, team-b, team-c, team-d] diff --git a/packages/catalog-model/examples-relative/acme/org.yaml b/packages/catalog-model/examples-relative/acme/org.yaml deleted file mode 100644 index 58cce827ff..0000000000 --- a/packages/catalog-model/examples-relative/acme/org.yaml +++ /dev/null @@ -1,30 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Group -metadata: - name: acme-corp - description: The acme-corp organization -spec: - type: organization - profile: - displayName: ACME Corp - email: info@example.com - picture: https://example.com/logo.jpeg - ancestors: [] - children: [infrastructure] - descendants: - [infrastructure, backstage, boxoffice, team-a, team-b, team-c, team-d] ---- -apiVersion: backstage.io/v1alpha1 -kind: Location -metadata: - name: example-groups - description: A collection of all Backstage example Groups -spec: - targets: - - ./infrastructure-group.yaml - - ./boxoffice-group.yaml - - ./backstage-group.yaml - - ./team-a-group.yaml - - ./team-b-group.yaml - - ./team-c-group.yaml - - ./team-d-group.yaml diff --git a/packages/catalog-model/examples-relative/acme/team-a-group.yaml b/packages/catalog-model/examples-relative/acme/team-a-group.yaml deleted file mode 100644 index 53d4bb8d80..0000000000 --- a/packages/catalog-model/examples-relative/acme/team-a-group.yaml +++ /dev/null @@ -1,62 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Group -metadata: - name: team-a - description: Team A -spec: - type: team - profile: - # Intentional no displayName for testing - email: team-a@example.com - picture: https://example.com/groups/team-a.jpeg - parent: backstage - ancestors: [backstage, infrastructure, acme-corp] - children: [] - descendants: [] ---- -apiVersion: backstage.io/v1alpha1 -kind: User -metadata: - name: breanna.davison -spec: - profile: - # Intentional no displayName for testing - email: breanna-davison@example.com - picture: https://example.com/staff/breanna.jpeg - memberOf: [team-a] ---- -apiVersion: backstage.io/v1alpha1 -kind: User -metadata: - name: janelle.dawe -spec: - profile: - displayName: Janelle Dawe - email: janelle-dawe@example.com - picture: https://example.com/staff/janelle.jpeg - memberOf: [team-a] ---- -apiVersion: backstage.io/v1alpha1 -kind: User -metadata: - name: nigel.manning -spec: - profile: - displayName: Nigel Manning - email: nigel-manning@example.com - picture: https://example.com/staff/nigel.jpeg - memberOf: [team-a] ---- -# This user is added as an example, to make it more easy for the "Guest" -# sign-in option to demonstrate some entities being owned. In a regular org, -# a guest user would probably not be registered like this. -apiVersion: backstage.io/v1alpha1 -kind: User -metadata: - name: guest -spec: - profile: - displayName: Guest User - email: guest@example.com - picture: https://example.com/staff/the-ceos-dog.jpeg - memberOf: [team-a] diff --git a/packages/catalog-model/examples-relative/acme/team-b-group.yaml b/packages/catalog-model/examples-relative/acme/team-b-group.yaml deleted file mode 100644 index a59a24317d..0000000000 --- a/packages/catalog-model/examples-relative/acme/team-b-group.yaml +++ /dev/null @@ -1,70 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Group -metadata: - name: team-b - description: Team B -spec: - type: team - profile: - displayName: Team B - email: team-b@example.com - picture: https://example.com/groups/team-b.jpeg - parent: backstage - ancestors: [backstage, infrastructure, acme-corp] - children: [] - descendants: [] ---- -apiVersion: backstage.io/v1alpha1 -kind: User -metadata: - name: amelia.park -spec: - profile: - displayName: Amelia Park - email: amelia-park@example.com - picture: https://example.com/staff/amelia.jpeg - memberOf: [team-b] ---- -apiVersion: backstage.io/v1alpha1 -kind: User -metadata: - name: colette.brock -spec: - profile: - displayName: Colette Brock - email: colette-brock@example.com - picture: https://example.com/staff/colette.jpeg - memberOf: [team-b] ---- -apiVersion: backstage.io/v1alpha1 -kind: User -metadata: - name: jenny.doe -spec: - profile: - displayName: Jenny Doe - email: jenny-doe@example.com - picture: https://example.com/staff/jenny.jpeg - memberOf: [team-b] ---- -apiVersion: backstage.io/v1alpha1 -kind: User -metadata: - name: jonathon.page -spec: - profile: - displayName: Jonathon Page - email: jonathon-page@example.com - picture: https://example.com/staff/jonathon.jpeg - memberOf: [team-b] ---- -apiVersion: backstage.io/v1alpha1 -kind: User -metadata: - name: justine.barrow -spec: - profile: - displayName: Justine Barrow - email: justine-barrow@example.com - picture: https://example.com/staff/justine.jpeg - memberOf: [team-b] diff --git a/packages/catalog-model/examples-relative/acme/team-c-group.yaml b/packages/catalog-model/examples-relative/acme/team-c-group.yaml deleted file mode 100644 index 31f67ac362..0000000000 --- a/packages/catalog-model/examples-relative/acme/team-c-group.yaml +++ /dev/null @@ -1,70 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Group -metadata: - name: team-c - description: Team C -spec: - type: team - profile: - displayName: Team C - email: team-c@example.com - picture: https://example.com/groups/team-c.jpeg - parent: boxoffice - ancestors: [boxoffice, infrastructure, acme-corp] - children: [] - descendants: [] ---- -apiVersion: backstage.io/v1alpha1 -kind: User -metadata: - name: calum.leavy -spec: - profile: - displayName: Calum Leavy - email: calum-leavy@example.com - picture: https://example.com/staff/calum.jpeg - memberOf: [team-c] ---- -apiVersion: backstage.io/v1alpha1 -kind: User -metadata: - name: frank.tiernan -spec: - profile: - displayName: Frank Tiernan - email: frank-tiernan@example.com - picture: https://example.com/staff/frank.jpeg - memberOf: [team-c] ---- -apiVersion: backstage.io/v1alpha1 -kind: User -metadata: - name: peadar.macmahon -spec: - profile: - displayName: Peadar MacMahon - email: peadar-macmahon@example.com - picture: https://example.com/staff/peadar.jpeg - memberOf: [team-c] ---- -apiVersion: backstage.io/v1alpha1 -kind: User -metadata: - name: sarah.gilroy -spec: - profile: - displayName: Sarah Gilroy - email: sarah-gilroy@example.com - picture: https://example.com/staff/sarah.jpeg - memberOf: [team-c] ---- -apiVersion: backstage.io/v1alpha1 -kind: User -metadata: - name: tara.macgovern -spec: - profile: - displayName: Tara MacGovern - email: tara-macgovern@example.com - picture: https://example.com/staff/tara.jpeg - memberOf: [team-c] diff --git a/packages/catalog-model/examples-relative/acme/team-d-group.yaml b/packages/catalog-model/examples-relative/acme/team-d-group.yaml deleted file mode 100644 index c4f87b3ac3..0000000000 --- a/packages/catalog-model/examples-relative/acme/team-d-group.yaml +++ /dev/null @@ -1,37 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Group -metadata: - name: team-d - description: Team D -spec: - type: team - profile: - displayName: Team D - email: team-d@example.com - picture: https://example.com/groups/team-d.jpeg - parent: boxoffice - ancestors: [boxoffice, infrastructure, acme-corp] - children: [] - descendants: [] ---- -apiVersion: backstage.io/v1alpha1 -kind: User -metadata: - name: eva.macdowell -spec: - profile: - displayName: Eva MacDowell - email: eva-macdowell@example.com - picture: https://example.com/staff/eva.jpeg - memberOf: [team-d] ---- -apiVersion: backstage.io/v1alpha1 -kind: User -metadata: - name: lucy.sheehan -spec: - profile: - displayName: Lucy Sheehan - email: lucy-sheehan@example.com - picture: https://example.com/staff/lucy.jpeg - memberOf: [team-d] diff --git a/packages/catalog-model/examples-relative/all-apis.yaml b/packages/catalog-model/examples-relative/all-apis.yaml deleted file mode 100644 index e23f1b3656..0000000000 --- a/packages/catalog-model/examples-relative/all-apis.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Location -metadata: - name: example-apis - description: A collection of all Backstage example APIs -spec: - targets: - - ./apis/hello-world-api.yaml - - ./apis/petstore-api.yaml - - ./apis/spotify-api.yaml - - ./apis/streetlights-api.yaml - - ./apis/swapi-graphql.yaml - - ./apis/wayback-archive-api.yaml - - ./apis/wayback-search-api.yaml diff --git a/packages/catalog-model/examples-relative/all-components.yaml b/packages/catalog-model/examples-relative/all-components.yaml deleted file mode 100644 index 5db5825b20..0000000000 --- a/packages/catalog-model/examples-relative/all-components.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Location -metadata: - name: example-components - description: A collection of all Backstage example components -spec: - targets: - - ./components/artist-lookup-component.yaml - - ./components/petstore-component.yaml - - ./components/playback-order-component.yaml - - ./components/podcast-api-component.yaml - - ./components/queue-proxy-component.yaml - - ./components/searcher-component.yaml - - ./components/playback-lib-component.yaml - - ./components/www-artist-component.yaml - - ./components/shuffle-api-component.yaml - - ./components/wayback-archive-component.yaml - - ./components/wayback-search-component.yaml diff --git a/packages/catalog-model/examples-relative/apis/hello-world-api.yaml b/packages/catalog-model/examples-relative/apis/hello-world-api.yaml deleted file mode 100644 index 0f9786329f..0000000000 --- a/packages/catalog-model/examples-relative/apis/hello-world-api.yaml +++ /dev/null @@ -1,48 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: API -metadata: - name: hello-world - description: Hello World example for gRPC -spec: - type: grpc - lifecycle: deprecated - owner: team-c - definition: | - // Copyright 2015 gRPC 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. - - syntax = "proto3"; - - option java_multiple_files = true; - option java_package = "io.grpc.examples.helloworld"; - option java_outer_classname = "HelloWorldProto"; - option objc_class_prefix = "HLW"; - - package helloworld; - - // The greeting service definition. - service Greeter { - // Sends a greeting - rpc SayHello (HelloRequest) returns (HelloReply) {} - } - - // The request message containing the user's name. - message HelloRequest { - string name = 1; - } - - // The response message containing the greetings - message HelloReply { - string message = 1; - } diff --git a/packages/catalog-model/examples-relative/apis/petstore-api.yaml b/packages/catalog-model/examples-relative/apis/petstore-api.yaml deleted file mode 100644 index a314b4e255..0000000000 --- a/packages/catalog-model/examples-relative/apis/petstore-api.yaml +++ /dev/null @@ -1,124 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: API -metadata: - name: petstore - description: The petstore API - tags: - - store - - rest -spec: - type: openapi - lifecycle: experimental - owner: team-c - definition: | - openapi: "3.0.0" - info: - version: 1.0.0 - title: Swagger Petstore - license: - name: MIT - servers: - - url: http://petstore.swagger.io/v1 - paths: - /pets: - get: - summary: List all pets - operationId: listPets - tags: - - pets - parameters: - - name: limit - in: query - description: How many items to return at one time (max 100) - required: false - schema: - type: integer - format: int32 - responses: - '200': - description: A paged array of pets - headers: - x-next: - description: A link to the next page of responses - schema: - type: string - content: - application/json: - schema: - $ref: "#/components/schemas/Pets" - default: - description: unexpected error - content: - application/json: - schema: - $ref: "#/components/schemas/Error" - post: - summary: Create a pet - operationId: createPets - tags: - - pets - responses: - '201': - description: Null response - default: - description: unexpected error - content: - application/json: - schema: - $ref: "#/components/schemas/Error" - /pets/{petId}: - get: - summary: Info for a specific pet - operationId: showPetById - tags: - - pets - parameters: - - name: petId - in: path - required: true - description: The id of the pet to retrieve - schema: - type: string - responses: - '200': - description: Expected response to a valid request - content: - application/json: - schema: - $ref: "#/components/schemas/Pet" - default: - description: unexpected error - content: - application/json: - schema: - $ref: "#/components/schemas/Error" - components: - schemas: - Pet: - type: object - required: - - id - - name - properties: - id: - type: integer - format: int64 - name: - type: string - tag: - type: string - Pets: - type: array - items: - $ref: "#/components/schemas/Pet" - Error: - type: object - required: - - code - - message - properties: - code: - type: integer - format: int32 - message: - type: string diff --git a/packages/catalog-model/examples-relative/apis/spotify-api.yaml b/packages/catalog-model/examples-relative/apis/spotify-api.yaml deleted file mode 100644 index 0b8e80b86e..0000000000 --- a/packages/catalog-model/examples-relative/apis/spotify-api.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: API -metadata: - name: spotify - description: The Spotify web API - tags: - - spotify - - rest - annotations: - # The annotation is deprecated, we use placeholders (see below) instead, remove it later. - backstage.io/definition-at-location: 'url:https://raw.githubusercontent.com/APIs-guru/openapi-directory/master/APIs/spotify.com/v1/swagger.yaml' -spec: - type: openapi - lifecycle: production - owner: team-a - definition: - $text: https://github.com/APIs-guru/openapi-directory/blob/master/APIs/spotify.com/v1/swagger.yaml diff --git a/packages/catalog-model/examples-relative/apis/streetlights-api.yaml b/packages/catalog-model/examples-relative/apis/streetlights-api.yaml deleted file mode 100644 index 725811d0cc..0000000000 --- a/packages/catalog-model/examples-relative/apis/streetlights-api.yaml +++ /dev/null @@ -1,221 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: API -metadata: - name: streetlights - description: The Smartylighting Streetlights API allows you to remotely manage the city lights. - tags: - - mqtt -spec: - type: asyncapi - lifecycle: production - owner: team-c - definition: | - asyncapi: 2.0.0 - info: - title: Streetlights API - version: '1.0.0' - description: | - The Smartylighting Streetlights API allows you to remotely manage the city lights. - - ### Check out its awesome features: - - * Turn a specific streetlight on/off 🌃 - * Dim a specific streetlight 😎 - * Receive real-time information about environmental lighting conditions 📈 - license: - name: Apache 2.0 - url: https://www.apache.org/licenses/LICENSE-2.0 - - servers: - production: - url: api.streetlights.smartylighting.com:{port} - protocol: mqtt - description: Test broker - variables: - port: - description: Secure connection (TLS) is available through port 8883. - default: '1883' - enum: - - '1883' - - '8883' - security: - - apiKey: [] - - supportedOauthFlows: - - streetlights:on - - streetlights:off - - streetlights:dim - - openIdConnectWellKnown: [] - - defaultContentType: application/json - - channels: - smartylighting/streetlights/1/0/event/{streetlightId}/lighting/measured: - description: The topic on which measured values may be produced and consumed. - parameters: - streetlightId: - $ref: '#/components/parameters/streetlightId' - subscribe: - summary: Receive information about environmental lighting conditions of a particular streetlight. - operationId: receiveLightMeasurement - traits: - - $ref: '#/components/operationTraits/kafka' - message: - $ref: '#/components/messages/lightMeasured' - - smartylighting/streetlights/1/0/action/{streetlightId}/turn/on: - parameters: - streetlightId: - $ref: '#/components/parameters/streetlightId' - publish: - operationId: turnOn - traits: - - $ref: '#/components/operationTraits/kafka' - message: - $ref: '#/components/messages/turnOnOff' - - smartylighting/streetlights/1/0/action/{streetlightId}/turn/off: - parameters: - streetlightId: - $ref: '#/components/parameters/streetlightId' - publish: - operationId: turnOff - traits: - - $ref: '#/components/operationTraits/kafka' - message: - $ref: '#/components/messages/turnOnOff' - - smartylighting/streetlights/1/0/action/{streetlightId}/dim: - parameters: - streetlightId: - $ref: '#/components/parameters/streetlightId' - publish: - operationId: dimLight - traits: - - $ref: '#/components/operationTraits/kafka' - message: - $ref: '#/components/messages/dimLight' - - components: - messages: - lightMeasured: - name: lightMeasured - title: Light measured - summary: Inform about environmental lighting conditions for a particular streetlight. - contentType: application/json - traits: - - $ref: '#/components/messageTraits/commonHeaders' - payload: - $ref: "#/components/schemas/lightMeasuredPayload" - turnOnOff: - name: turnOnOff - title: Turn on/off - summary: Command a particular streetlight to turn the lights on or off. - traits: - - $ref: '#/components/messageTraits/commonHeaders' - payload: - $ref: "#/components/schemas/turnOnOffPayload" - dimLight: - name: dimLight - title: Dim light - summary: Command a particular streetlight to dim the lights. - traits: - - $ref: '#/components/messageTraits/commonHeaders' - payload: - $ref: "#/components/schemas/dimLightPayload" - - schemas: - lightMeasuredPayload: - type: object - properties: - lumens: - type: integer - minimum: 0 - description: Light intensity measured in lumens. - sentAt: - $ref: "#/components/schemas/sentAt" - turnOnOffPayload: - type: object - properties: - command: - type: string - enum: - - on - - off - description: Whether to turn on or off the light. - sentAt: - $ref: "#/components/schemas/sentAt" - dimLightPayload: - type: object - properties: - percentage: - type: integer - description: Percentage to which the light should be dimmed to. - minimum: 0 - maximum: 100 - sentAt: - $ref: "#/components/schemas/sentAt" - sentAt: - type: string - format: date-time - description: Date and time when the message was sent. - - securitySchemes: - apiKey: - type: apiKey - in: user - description: Provide your API key as the user and leave the password empty. - supportedOauthFlows: - type: oauth2 - description: Flows to support OAuth 2.0 - flows: - implicit: - authorizationUrl: 'https://authserver.example/auth' - scopes: - 'streetlights:on': Ability to switch lights on - 'streetlights:off': Ability to switch lights off - 'streetlights:dim': Ability to dim the lights - password: - tokenUrl: 'https://authserver.example/token' - scopes: - 'streetlights:on': Ability to switch lights on - 'streetlights:off': Ability to switch lights off - 'streetlights:dim': Ability to dim the lights - clientCredentials: - tokenUrl: 'https://authserver.example/token' - scopes: - 'streetlights:on': Ability to switch lights on - 'streetlights:off': Ability to switch lights off - 'streetlights:dim': Ability to dim the lights - authorizationCode: - authorizationUrl: 'https://authserver.example/auth' - tokenUrl: 'https://authserver.example/token' - refreshUrl: 'https://authserver.example/refresh' - scopes: - 'streetlights:on': Ability to switch lights on - 'streetlights:off': Ability to switch lights off - 'streetlights:dim': Ability to dim the lights - openIdConnectWellKnown: - type: openIdConnect - openIdConnectUrl: 'https://authserver.example/.well-known' - - parameters: - streetlightId: - description: The ID of the streetlight. - schema: - type: string - - messageTraits: - commonHeaders: - headers: - type: object - properties: - my-app-header: - type: integer - minimum: 0 - maximum: 100 - - operationTraits: - kafka: - bindings: - kafka: - clientId: my-app-id diff --git a/packages/catalog-model/examples-relative/apis/swapi-graphql.yaml b/packages/catalog-model/examples-relative/apis/swapi-graphql.yaml deleted file mode 100644 index 0c1f7af5a4..0000000000 --- a/packages/catalog-model/examples-relative/apis/swapi-graphql.yaml +++ /dev/null @@ -1,1176 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: API -metadata: - name: starwars-graphql - description: SWAPI GraphQL Schema -spec: - type: graphql - lifecycle: production - owner: team-b - definition: | - schema { - query: Root - } - - """A single film.""" - type Film implements Node { - """The title of this film.""" - title: String - - """The episode number of this film.""" - episodeID: Int - - """The opening paragraphs at the beginning of this film.""" - openingCrawl: String - - """The name of the director of this film.""" - director: String - - """The name(s) of the producer(s) of this film.""" - producers: [String] - - """The ISO 8601 date format of film release at original creator country.""" - releaseDate: String - speciesConnection(after: String, first: Int, before: String, last: Int): FilmSpeciesConnection - starshipConnection(after: String, first: Int, before: String, last: Int): FilmStarshipsConnection - vehicleConnection(after: String, first: Int, before: String, last: Int): FilmVehiclesConnection - characterConnection(after: String, first: Int, before: String, last: Int): FilmCharactersConnection - planetConnection(after: String, first: Int, before: String, last: Int): FilmPlanetsConnection - - """The ISO 8601 date format of the time that this resource was created.""" - created: String - - """The ISO 8601 date format of the time that this resource was edited.""" - edited: String - - """The ID of an object""" - id: ID! - } - - """A connection to a list of items.""" - type FilmCharactersConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [FilmCharactersEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - characters: [Person] - } - - """An edge in a connection.""" - type FilmCharactersEdge { - """The item at the end of the edge""" - node: Person - - """A cursor for use in pagination""" - cursor: String! - } - - """A connection to a list of items.""" - type FilmPlanetsConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [FilmPlanetsEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - planets: [Planet] - } - - """An edge in a connection.""" - type FilmPlanetsEdge { - """The item at the end of the edge""" - node: Planet - - """A cursor for use in pagination""" - cursor: String! - } - - """A connection to a list of items.""" - type FilmsConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [FilmsEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - films: [Film] - } - - """An edge in a connection.""" - type FilmsEdge { - """The item at the end of the edge""" - node: Film - - """A cursor for use in pagination""" - cursor: String! - } - - """A connection to a list of items.""" - type FilmSpeciesConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [FilmSpeciesEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - species: [Species] - } - - """An edge in a connection.""" - type FilmSpeciesEdge { - """The item at the end of the edge""" - node: Species - - """A cursor for use in pagination""" - cursor: String! - } - - """A connection to a list of items.""" - type FilmStarshipsConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [FilmStarshipsEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - starships: [Starship] - } - - """An edge in a connection.""" - type FilmStarshipsEdge { - """The item at the end of the edge""" - node: Starship - - """A cursor for use in pagination""" - cursor: String! - } - - """A connection to a list of items.""" - type FilmVehiclesConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [FilmVehiclesEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - vehicles: [Vehicle] - } - - """An edge in a connection.""" - type FilmVehiclesEdge { - """The item at the end of the edge""" - node: Vehicle - - """A cursor for use in pagination""" - cursor: String! - } - - """An object with an ID""" - interface Node { - """The id of the object.""" - id: ID! - } - - """Information about pagination in a connection.""" - type PageInfo { - """When paginating forwards, are there more items?""" - hasNextPage: Boolean! - - """When paginating backwards, are there more items?""" - hasPreviousPage: Boolean! - - """When paginating backwards, the cursor to continue.""" - startCursor: String - - """When paginating forwards, the cursor to continue.""" - endCursor: String - } - - """A connection to a list of items.""" - type PeopleConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [PeopleEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - people: [Person] - } - - """An edge in a connection.""" - type PeopleEdge { - """The item at the end of the edge""" - node: Person - - """A cursor for use in pagination""" - cursor: String! - } - - """An individual person or character within the Star Wars universe.""" - type Person implements Node { - """The name of this person.""" - name: String - - """ - The birth year of the person, using the in-universe standard of BBY or ABY - - Before the Battle of Yavin or After the Battle of Yavin. The Battle of Yavin is - a battle that occurs at the end of Star Wars episode IV: A New Hope. - """ - birthYear: String - - """ - The eye color of this person. Will be "unknown" if not known or "n/a" if the - person does not have an eye. - """ - eyeColor: String - - """ - The gender of this person. Either "Male", "Female" or "unknown", - "n/a" if the person does not have a gender. - """ - gender: String - - """ - The hair color of this person. Will be "unknown" if not known or "n/a" if the - person does not have hair. - """ - hairColor: String - - """The height of the person in centimeters.""" - height: Int - - """The mass of the person in kilograms.""" - mass: Float - - """The skin color of this person.""" - skinColor: String - - """A planet that this person was born on or inhabits.""" - homeworld: Planet - filmConnection(after: String, first: Int, before: String, last: Int): PersonFilmsConnection - - """The species that this person belongs to, or null if unknown.""" - species: Species - starshipConnection(after: String, first: Int, before: String, last: Int): PersonStarshipsConnection - vehicleConnection(after: String, first: Int, before: String, last: Int): PersonVehiclesConnection - - """The ISO 8601 date format of the time that this resource was created.""" - created: String - - """The ISO 8601 date format of the time that this resource was edited.""" - edited: String - - """The ID of an object""" - id: ID! - } - - """A connection to a list of items.""" - type PersonFilmsConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [PersonFilmsEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - films: [Film] - } - - """An edge in a connection.""" - type PersonFilmsEdge { - """The item at the end of the edge""" - node: Film - - """A cursor for use in pagination""" - cursor: String! - } - - """A connection to a list of items.""" - type PersonStarshipsConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [PersonStarshipsEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - starships: [Starship] - } - - """An edge in a connection.""" - type PersonStarshipsEdge { - """The item at the end of the edge""" - node: Starship - - """A cursor for use in pagination""" - cursor: String! - } - - """A connection to a list of items.""" - type PersonVehiclesConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [PersonVehiclesEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - vehicles: [Vehicle] - } - - """An edge in a connection.""" - type PersonVehiclesEdge { - """The item at the end of the edge""" - node: Vehicle - - """A cursor for use in pagination""" - cursor: String! - } - - """ - A large mass, planet or planetoid in the Star Wars Universe, at the time of - 0 ABY. - """ - type Planet implements Node { - """The name of this planet.""" - name: String - - """The diameter of this planet in kilometers.""" - diameter: Int - - """ - The number of standard hours it takes for this planet to complete a single - rotation on its axis. - """ - rotationPeriod: Int - - """ - The number of standard days it takes for this planet to complete a single orbit - of its local star. - """ - orbitalPeriod: Int - - """ - A number denoting the gravity of this planet, where "1" is normal or 1 standard - G. "2" is twice or 2 standard Gs. "0.5" is half or 0.5 standard Gs. - """ - gravity: String - - """The average population of sentient beings inhabiting this planet.""" - population: Float - - """The climates of this planet.""" - climates: [String] - - """The terrains of this planet.""" - terrains: [String] - - """ - The percentage of the planet surface that is naturally occuring water or bodies - of water. - """ - surfaceWater: Float - residentConnection(after: String, first: Int, before: String, last: Int): PlanetResidentsConnection - filmConnection(after: String, first: Int, before: String, last: Int): PlanetFilmsConnection - - """The ISO 8601 date format of the time that this resource was created.""" - created: String - - """The ISO 8601 date format of the time that this resource was edited.""" - edited: String - - """The ID of an object""" - id: ID! - } - - """A connection to a list of items.""" - type PlanetFilmsConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [PlanetFilmsEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - films: [Film] - } - - """An edge in a connection.""" - type PlanetFilmsEdge { - """The item at the end of the edge""" - node: Film - - """A cursor for use in pagination""" - cursor: String! - } - - """A connection to a list of items.""" - type PlanetResidentsConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [PlanetResidentsEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - residents: [Person] - } - - """An edge in a connection.""" - type PlanetResidentsEdge { - """The item at the end of the edge""" - node: Person - - """A cursor for use in pagination""" - cursor: String! - } - - """A connection to a list of items.""" - type PlanetsConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [PlanetsEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - planets: [Planet] - } - - """An edge in a connection.""" - type PlanetsEdge { - """The item at the end of the edge""" - node: Planet - - """A cursor for use in pagination""" - cursor: String! - } - - type Root { - allFilms(after: String, first: Int, before: String, last: Int): FilmsConnection - film(id: ID, filmID: ID): Film - allPeople(after: String, first: Int, before: String, last: Int): PeopleConnection - person(id: ID, personID: ID): Person - allPlanets(after: String, first: Int, before: String, last: Int): PlanetsConnection - planet(id: ID, planetID: ID): Planet - allSpecies(after: String, first: Int, before: String, last: Int): SpeciesConnection - species(id: ID, speciesID: ID): Species - allStarships(after: String, first: Int, before: String, last: Int): StarshipsConnection - starship(id: ID, starshipID: ID): Starship - allVehicles(after: String, first: Int, before: String, last: Int): VehiclesConnection - vehicle(id: ID, vehicleID: ID): Vehicle - - """Fetches an object given its ID""" - node( - """The ID of an object""" - id: ID! - ): Node - } - - """A type of person or character within the Star Wars Universe.""" - type Species implements Node { - """The name of this species.""" - name: String - - """The classification of this species, such as "mammal" or "reptile".""" - classification: String - - """The designation of this species, such as "sentient".""" - designation: String - - """The average height of this species in centimeters.""" - averageHeight: Float - - """The average lifespan of this species in years, null if unknown.""" - averageLifespan: Int - - """ - Common eye colors for this species, null if this species does not typically - have eyes. - """ - eyeColors: [String] - - """ - Common hair colors for this species, null if this species does not typically - have hair. - """ - hairColors: [String] - - """ - Common skin colors for this species, null if this species does not typically - have skin. - """ - skinColors: [String] - - """The language commonly spoken by this species.""" - language: String - - """A planet that this species originates from.""" - homeworld: Planet - personConnection(after: String, first: Int, before: String, last: Int): SpeciesPeopleConnection - filmConnection(after: String, first: Int, before: String, last: Int): SpeciesFilmsConnection - - """The ISO 8601 date format of the time that this resource was created.""" - created: String - - """The ISO 8601 date format of the time that this resource was edited.""" - edited: String - - """The ID of an object""" - id: ID! - } - - """A connection to a list of items.""" - type SpeciesConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [SpeciesEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - species: [Species] - } - - """An edge in a connection.""" - type SpeciesEdge { - """The item at the end of the edge""" - node: Species - - """A cursor for use in pagination""" - cursor: String! - } - - """A connection to a list of items.""" - type SpeciesFilmsConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [SpeciesFilmsEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - films: [Film] - } - - """An edge in a connection.""" - type SpeciesFilmsEdge { - """The item at the end of the edge""" - node: Film - - """A cursor for use in pagination""" - cursor: String! - } - - """A connection to a list of items.""" - type SpeciesPeopleConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [SpeciesPeopleEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - people: [Person] - } - - """An edge in a connection.""" - type SpeciesPeopleEdge { - """The item at the end of the edge""" - node: Person - - """A cursor for use in pagination""" - cursor: String! - } - - """A single transport craft that has hyperdrive capability.""" - type Starship implements Node { - """The name of this starship. The common name, such as "Death Star".""" - name: String - - """ - The model or official name of this starship. Such as "T-65 X-wing" or "DS-1 - Orbital Battle Station". - """ - model: String - - """ - The class of this starship, such as "Starfighter" or "Deep Space Mobile - Battlestation" - """ - starshipClass: String - - """The manufacturers of this starship.""" - manufacturers: [String] - - """The cost of this starship new, in galactic credits.""" - costInCredits: Float - - """The length of this starship in meters.""" - length: Float - - """The number of personnel needed to run or pilot this starship.""" - crew: String - - """The number of non-essential people this starship can transport.""" - passengers: String - - """ - The maximum speed of this starship in atmosphere. null if this starship is - incapable of atmosphering flight. - """ - maxAtmospheringSpeed: Int - - """The class of this starships hyperdrive.""" - hyperdriveRating: Float - - """ - The Maximum number of Megalights this starship can travel in a standard hour. - A "Megalight" is a standard unit of distance and has never been defined before - within the Star Wars universe. This figure is only really useful for measuring - the difference in speed of starships. We can assume it is similar to AU, the - distance between our Sun (Sol) and Earth. - """ - MGLT: Int - - """The maximum number of kilograms that this starship can transport.""" - cargoCapacity: Float - - """ - The maximum length of time that this starship can provide consumables for its - entire crew without having to resupply. - """ - consumables: String - pilotConnection(after: String, first: Int, before: String, last: Int): StarshipPilotsConnection - filmConnection(after: String, first: Int, before: String, last: Int): StarshipFilmsConnection - - """The ISO 8601 date format of the time that this resource was created.""" - created: String - - """The ISO 8601 date format of the time that this resource was edited.""" - edited: String - - """The ID of an object""" - id: ID! - } - - """A connection to a list of items.""" - type StarshipFilmsConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [StarshipFilmsEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - films: [Film] - } - - """An edge in a connection.""" - type StarshipFilmsEdge { - """The item at the end of the edge""" - node: Film - - """A cursor for use in pagination""" - cursor: String! - } - - """A connection to a list of items.""" - type StarshipPilotsConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [StarshipPilotsEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - pilots: [Person] - } - - """An edge in a connection.""" - type StarshipPilotsEdge { - """The item at the end of the edge""" - node: Person - - """A cursor for use in pagination""" - cursor: String! - } - - """A connection to a list of items.""" - type StarshipsConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [StarshipsEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - starships: [Starship] - } - - """An edge in a connection.""" - type StarshipsEdge { - """The item at the end of the edge""" - node: Starship - - """A cursor for use in pagination""" - cursor: String! - } - - """A single transport craft that does not have hyperdrive capability""" - type Vehicle implements Node { - """ - The name of this vehicle. The common name, such as "Sand Crawler" or "Speeder - bike". - """ - name: String - - """ - The model or official name of this vehicle. Such as "All-Terrain Attack - Transport". - """ - model: String - - """The class of this vehicle, such as "Wheeled" or "Repulsorcraft".""" - vehicleClass: String - - """The manufacturers of this vehicle.""" - manufacturers: [String] - - """The cost of this vehicle new, in Galactic Credits.""" - costInCredits: Float - - """The length of this vehicle in meters.""" - length: Float - - """The number of personnel needed to run or pilot this vehicle.""" - crew: String - - """The number of non-essential people this vehicle can transport.""" - passengers: String - - """The maximum speed of this vehicle in atmosphere.""" - maxAtmospheringSpeed: Int - - """The maximum number of kilograms that this vehicle can transport.""" - cargoCapacity: Float - - """ - The maximum length of time that this vehicle can provide consumables for its - entire crew without having to resupply. - """ - consumables: String - pilotConnection(after: String, first: Int, before: String, last: Int): VehiclePilotsConnection - filmConnection(after: String, first: Int, before: String, last: Int): VehicleFilmsConnection - - """The ISO 8601 date format of the time that this resource was created.""" - created: String - - """The ISO 8601 date format of the time that this resource was edited.""" - edited: String - - """The ID of an object""" - id: ID! - } - - """A connection to a list of items.""" - type VehicleFilmsConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [VehicleFilmsEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - films: [Film] - } - - """An edge in a connection.""" - type VehicleFilmsEdge { - """The item at the end of the edge""" - node: Film - - """A cursor for use in pagination""" - cursor: String! - } - - """A connection to a list of items.""" - type VehiclePilotsConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [VehiclePilotsEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - pilots: [Person] - } - - """An edge in a connection.""" - type VehiclePilotsEdge { - """The item at the end of the edge""" - node: Person - - """A cursor for use in pagination""" - cursor: String! - } - - """A connection to a list of items.""" - type VehiclesConnection { - """Information to aid in pagination.""" - pageInfo: PageInfo! - - """A list of edges.""" - edges: [VehiclesEdge] - - """ - A count of the total number of objects in this connection, ignoring pagination. - This allows a client to fetch the first five objects by passing "5" as the - argument to "first", then fetch the total count so it could display "5 of 83", - for example. - """ - totalCount: Int - - """ - A list of all of the objects returned in the connection. This is a convenience - field provided for quickly exploring the API; rather than querying for - "{ edges { node } }" when no edge data is needed, this field can be be used - instead. Note that when clients like Relay need to fetch the "cursor" field on - the edge to enable efficient pagination, this shortcut cannot be used, and the - full "{ edges { node } }" version should be used instead. - """ - vehicles: [Vehicle] - } - - """An edge in a connection.""" - type VehiclesEdge { - """The item at the end of the edge""" - node: Vehicle - - """A cursor for use in pagination""" - cursor: String! - } diff --git a/packages/catalog-model/examples-relative/components/artist-lookup-component.yaml b/packages/catalog-model/examples-relative/components/artist-lookup-component.yaml deleted file mode 100644 index 257344be3d..0000000000 --- a/packages/catalog-model/examples-relative/components/artist-lookup-component.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: artist-lookup - description: Artist Lookup - tags: - - java - - data -spec: - type: service - lifecycle: experimental - owner: team-a diff --git a/packages/catalog-model/examples-relative/components/petstore-component.yaml b/packages/catalog-model/examples-relative/components/petstore-component.yaml deleted file mode 100644 index e6dd56c274..0000000000 --- a/packages/catalog-model/examples-relative/components/petstore-component.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: petstore - description: Petstore -spec: - type: service - lifecycle: experimental - owner: team-c - implementsApis: - - petstore - - streetlights - - hello-world diff --git a/packages/catalog-model/examples-relative/components/playback-lib-component.yaml b/packages/catalog-model/examples-relative/components/playback-lib-component.yaml deleted file mode 100644 index f7d7670b5d..0000000000 --- a/packages/catalog-model/examples-relative/components/playback-lib-component.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: playback-sdk - description: Audio and video playback SDK -spec: - type: library - lifecycle: experimental - owner: team-c diff --git a/packages/catalog-model/examples-relative/components/playback-order-component.yaml b/packages/catalog-model/examples-relative/components/playback-order-component.yaml deleted file mode 100644 index c4f41b2b58..0000000000 --- a/packages/catalog-model/examples-relative/components/playback-order-component.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: playback-order - description: Playback Order - tags: - - java - - playback -spec: - type: service - lifecycle: production - owner: user:guest diff --git a/packages/catalog-model/examples-relative/components/podcast-api-component.yaml b/packages/catalog-model/examples-relative/components/podcast-api-component.yaml deleted file mode 100644 index b89ff48c48..0000000000 --- a/packages/catalog-model/examples-relative/components/podcast-api-component.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: podcast-api - description: Podcast API - tags: - - java -spec: - type: service - lifecycle: experimental - owner: team-b diff --git a/packages/catalog-model/examples-relative/components/queue-proxy-component.yaml b/packages/catalog-model/examples-relative/components/queue-proxy-component.yaml deleted file mode 100644 index 7f7fcbd527..0000000000 --- a/packages/catalog-model/examples-relative/components/queue-proxy-component.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: queue-proxy - description: Queue Proxy - tags: - - go - - website -spec: - type: website - lifecycle: production - owner: team-b diff --git a/packages/catalog-model/examples-relative/components/searcher-component.yaml b/packages/catalog-model/examples-relative/components/searcher-component.yaml deleted file mode 100644 index 77150c96f0..0000000000 --- a/packages/catalog-model/examples-relative/components/searcher-component.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: searcher - description: Searcher - tags: - - go -spec: - type: service - lifecycle: production - owner: user:guest diff --git a/packages/catalog-model/examples-relative/components/shuffle-api-component.yaml b/packages/catalog-model/examples-relative/components/shuffle-api-component.yaml deleted file mode 100644 index 1c2da03511..0000000000 --- a/packages/catalog-model/examples-relative/components/shuffle-api-component.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: shuffle-api - description: Shuffle API - tags: - - go -spec: - type: service - lifecycle: production - owner: user:guest diff --git a/packages/catalog-model/examples-relative/components/www-artist-component.yaml b/packages/catalog-model/examples-relative/components/www-artist-component.yaml deleted file mode 100644 index c333eb8c09..0000000000 --- a/packages/catalog-model/examples-relative/components/www-artist-component.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: www-artist - description: Artist main website -spec: - type: website - lifecycle: production - owner: team-a diff --git a/packages/catalog-model/examples/README.md b/packages/catalog-model/examples/README.md index abf4934f3f..77e1084899 100644 --- a/packages/catalog-model/examples/README.md +++ b/packages/catalog-model/examples/README.md @@ -1,7 +1,4 @@ # Example Entities -NOTE: These are being replaced with the contents of the `examples-relative` -sibling directory, after December 16 2020. If you are using this example data -you will need to be using a released version of the catalog backend which -supports relative targets in Location entities -[see #3513](https://github.com/backstage/backstage/pull/3513) after that time. +This is a set of example entities that you can make use of to demonstrate basic +Backstage features. diff --git a/packages/catalog-model/examples/acme-corp.yaml b/packages/catalog-model/examples/acme-corp.yaml index e8047fc143..6449d548e0 100644 --- a/packages/catalog-model/examples/acme-corp.yaml +++ b/packages/catalog-model/examples/acme-corp.yaml @@ -4,6 +4,5 @@ metadata: name: acme-corp description: A collection of all Backstage example Groups spec: - type: github targets: - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme/org.yaml + - ./acme/org.yaml diff --git a/packages/catalog-model/examples/acme/backstage-group.yaml b/packages/catalog-model/examples/acme/backstage-group.yaml index be5baf091e..3aecfa0023 100644 --- a/packages/catalog-model/examples/acme/backstage-group.yaml +++ b/packages/catalog-model/examples/acme/backstage-group.yaml @@ -5,5 +5,9 @@ metadata: description: The backstage sub-department spec: type: sub-department + profile: + displayName: Backstage + email: backstage@example.com + picture: https://example.com/groups/backstage.jpeg parent: infrastructure children: [team-a, team-b] diff --git a/packages/catalog-model/examples/acme/boxoffice-group.yaml b/packages/catalog-model/examples/acme/boxoffice-group.yaml index 37e9816b50..fbd454c56e 100644 --- a/packages/catalog-model/examples/acme/boxoffice-group.yaml +++ b/packages/catalog-model/examples/acme/boxoffice-group.yaml @@ -5,5 +5,9 @@ metadata: description: The boxoffice sub-department spec: type: sub-department + profile: + displayName: Box Office + email: boxoffice@example.com + # Intentional no picture for testing parent: infrastructure children: [team-c, team-d] diff --git a/packages/catalog-model/examples/acme/infrastructure-group.yaml b/packages/catalog-model/examples/acme/infrastructure-group.yaml index 45bad12b7e..584578e6ce 100644 --- a/packages/catalog-model/examples/acme/infrastructure-group.yaml +++ b/packages/catalog-model/examples/acme/infrastructure-group.yaml @@ -5,5 +5,6 @@ metadata: description: The infra department spec: type: department + # Intentional no profile for testing parent: acme-corp children: [backstage, boxoffice] diff --git a/packages/catalog-model/examples/acme/org.yaml b/packages/catalog-model/examples/acme/org.yaml index 21a890a1aa..2b44183bc5 100644 --- a/packages/catalog-model/examples/acme/org.yaml +++ b/packages/catalog-model/examples/acme/org.yaml @@ -5,6 +5,10 @@ metadata: description: The acme-corp organization spec: type: organization + profile: + displayName: ACME Corp + email: info@example.com + picture: https://example.com/logo.jpeg children: [infrastructure] --- apiVersion: backstage.io/v1alpha1 @@ -13,12 +17,11 @@ metadata: name: example-groups description: A collection of all Backstage example Groups spec: - type: github targets: - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme/infrastructure-group.yaml - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme/boxoffice-group.yaml - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme/backstage-group.yaml - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme/team-a-group.yaml - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme/team-b-group.yaml - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme/team-c-group.yaml - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme/team-d-group.yaml + - ./infrastructure-group.yaml + - ./boxoffice-group.yaml + - ./backstage-group.yaml + - ./team-a-group.yaml + - ./team-b-group.yaml + - ./team-c-group.yaml + - ./team-d-group.yaml diff --git a/packages/catalog-model/examples/acme/team-a-group.yaml b/packages/catalog-model/examples/acme/team-a-group.yaml index c3c2c590a1..ed736dce50 100644 --- a/packages/catalog-model/examples/acme/team-a-group.yaml +++ b/packages/catalog-model/examples/acme/team-a-group.yaml @@ -5,6 +5,10 @@ metadata: description: Team A spec: type: team + profile: + # Intentional no displayName for testing + email: team-a@example.com + picture: https://example.com/groups/team-a.jpeg parent: backstage children: [] --- @@ -14,7 +18,7 @@ metadata: name: breanna.davison spec: profile: - displayName: Breanna Davison + # Intentional no displayName for testing email: breanna-davison@example.com picture: https://example.com/staff/breanna.jpeg memberOf: [team-a] diff --git a/packages/catalog-model/examples/acme/team-b-group.yaml b/packages/catalog-model/examples/acme/team-b-group.yaml index 0c6604ff79..9ed50b04c2 100644 --- a/packages/catalog-model/examples/acme/team-b-group.yaml +++ b/packages/catalog-model/examples/acme/team-b-group.yaml @@ -5,6 +5,10 @@ metadata: description: Team B spec: type: team + profile: + displayName: Team B + email: team-b@example.com + picture: https://example.com/groups/team-b.jpeg parent: backstage children: [] --- diff --git a/packages/catalog-model/examples/acme/team-c-group.yaml b/packages/catalog-model/examples/acme/team-c-group.yaml index ccc95b7f60..7f151dbb1e 100644 --- a/packages/catalog-model/examples/acme/team-c-group.yaml +++ b/packages/catalog-model/examples/acme/team-c-group.yaml @@ -5,6 +5,10 @@ metadata: description: Team C spec: type: team + profile: + displayName: Team C + email: team-c@example.com + picture: https://example.com/groups/team-c.jpeg parent: boxoffice children: [] --- diff --git a/packages/catalog-model/examples/acme/team-d-group.yaml b/packages/catalog-model/examples/acme/team-d-group.yaml index e032ab8b9e..a0d3c2351a 100644 --- a/packages/catalog-model/examples/acme/team-d-group.yaml +++ b/packages/catalog-model/examples/acme/team-d-group.yaml @@ -5,6 +5,10 @@ metadata: description: Team D spec: type: team + profile: + displayName: Team D + email: team-d@example.com + picture: https://example.com/groups/team-d.jpeg parent: boxoffice children: [] --- diff --git a/packages/catalog-model/examples/all-apis.yaml b/packages/catalog-model/examples/all-apis.yaml index 0278fc3078..e23f1b3656 100644 --- a/packages/catalog-model/examples/all-apis.yaml +++ b/packages/catalog-model/examples/all-apis.yaml @@ -4,10 +4,11 @@ metadata: name: example-apis description: A collection of all Backstage example APIs spec: - type: github targets: - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/apis/hello-world-api.yaml - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/apis/petstore-api.yaml - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/apis/spotify-api.yaml - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/apis/streetlights-api.yaml - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/apis/swapi-graphql.yaml + - ./apis/hello-world-api.yaml + - ./apis/petstore-api.yaml + - ./apis/spotify-api.yaml + - ./apis/streetlights-api.yaml + - ./apis/swapi-graphql.yaml + - ./apis/wayback-archive-api.yaml + - ./apis/wayback-search-api.yaml diff --git a/packages/catalog-model/examples/all-components.yaml b/packages/catalog-model/examples/all-components.yaml index 06c44b59d7..5db5825b20 100644 --- a/packages/catalog-model/examples/all-components.yaml +++ b/packages/catalog-model/examples/all-components.yaml @@ -4,14 +4,15 @@ metadata: name: example-components description: A collection of all Backstage example components spec: - type: github targets: - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/components/artist-lookup-component.yaml - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/components/petstore-component.yaml - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/components/playback-order-component.yaml - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/components/podcast-api-component.yaml - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/components/queue-proxy-component.yaml - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/components/searcher-component.yaml - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/components/playback-lib-component.yaml - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/components/www-artist-component.yaml - - https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/components/shuffle-api-component.yaml + - ./components/artist-lookup-component.yaml + - ./components/petstore-component.yaml + - ./components/playback-order-component.yaml + - ./components/podcast-api-component.yaml + - ./components/queue-proxy-component.yaml + - ./components/searcher-component.yaml + - ./components/playback-lib-component.yaml + - ./components/www-artist-component.yaml + - ./components/shuffle-api-component.yaml + - ./components/wayback-archive-component.yaml + - ./components/wayback-search-component.yaml diff --git a/packages/catalog-model/examples-relative/apis/wayback-archive-api.yaml b/packages/catalog-model/examples/apis/wayback-archive-api.yaml similarity index 91% rename from packages/catalog-model/examples-relative/apis/wayback-archive-api.yaml rename to packages/catalog-model/examples/apis/wayback-archive-api.yaml index 82610eae24..dbed93dbe8 100644 --- a/packages/catalog-model/examples-relative/apis/wayback-archive-api.yaml +++ b/packages/catalog-model/examples/apis/wayback-archive-api.yaml @@ -6,6 +6,6 @@ metadata: spec: type: openapi lifecycle: production - owner: archive@example.com + owner: team-a definition: $text: https://github.com/APIs-guru/openapi-directory/blob/master/APIs/archive.org/wayback/1.0.0/openapi.yaml diff --git a/packages/catalog-model/examples-relative/apis/wayback-search-api.yaml b/packages/catalog-model/examples/apis/wayback-search-api.yaml similarity index 91% rename from packages/catalog-model/examples-relative/apis/wayback-search-api.yaml rename to packages/catalog-model/examples/apis/wayback-search-api.yaml index 6eb5cae54b..b39b5df468 100644 --- a/packages/catalog-model/examples-relative/apis/wayback-search-api.yaml +++ b/packages/catalog-model/examples/apis/wayback-search-api.yaml @@ -6,6 +6,6 @@ metadata: spec: type: openapi lifecycle: production - owner: archive@example.com + owner: team-a definition: $text: https://github.com/APIs-guru/openapi-directory/blob/master/APIs/archive.org/search/1.0.0/openapi.yaml diff --git a/packages/catalog-model/examples-relative/components/wayback-archive-component.yaml b/packages/catalog-model/examples/components/wayback-archive-component.yaml similarity index 88% rename from packages/catalog-model/examples-relative/components/wayback-archive-component.yaml rename to packages/catalog-model/examples/components/wayback-archive-component.yaml index ea5ef10a17..5d558db64a 100644 --- a/packages/catalog-model/examples-relative/components/wayback-archive-component.yaml +++ b/packages/catalog-model/examples/components/wayback-archive-component.yaml @@ -6,6 +6,6 @@ metadata: spec: type: service lifecycle: production - owner: archive@example.com + owner: team-a providesApis: - wayback-archive diff --git a/packages/catalog-model/examples-relative/components/wayback-search-component.yaml b/packages/catalog-model/examples/components/wayback-search-component.yaml similarity index 89% rename from packages/catalog-model/examples-relative/components/wayback-search-component.yaml rename to packages/catalog-model/examples/components/wayback-search-component.yaml index def136ff2f..0187e4441f 100644 --- a/packages/catalog-model/examples-relative/components/wayback-search-component.yaml +++ b/packages/catalog-model/examples/components/wayback-search-component.yaml @@ -6,7 +6,7 @@ metadata: spec: type: service lifecycle: production - owner: archive@example.com + owner: team-a providesApis: - wayback-search consumesApis: From 639883d468c1e70b9f2d83c2458d60bcfa18baeb Mon Sep 17 00:00:00 2001 From: Fidel Coria Date: Tue, 15 Dec 2020 14:30:06 -0600 Subject: [PATCH 37/98] use provider.id instead of arg --- .../implementations/auth/github/GithubAuth.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/packages/core-api/src/apis/implementations/auth/github/GithubAuth.ts b/packages/core-api/src/apis/implementations/auth/github/GithubAuth.ts index a32f77fb88..a7c945a907 100644 --- a/packages/core-api/src/apis/implementations/auth/github/GithubAuth.ts +++ b/packages/core-api/src/apis/implementations/auth/github/GithubAuth.ts @@ -50,16 +50,13 @@ const DEFAULT_PROVIDER = { }; class GithubAuth implements OAuthApi, SessionApi { - static create( - { - discoveryApi, - environment = 'development', - provider = DEFAULT_PROVIDER, - oauthRequestApi, - defaultScopes = ['read:user'], - }: OAuthApiCreateOptions, - storageKey = 'githubSession', - ) { + static create({ + discoveryApi, + environment = 'development', + provider = DEFAULT_PROVIDER, + oauthRequestApi, + defaultScopes = ['read:user'], + }: OAuthApiCreateOptions) { const connector = new DefaultAuthConnector({ discoveryApi, environment, @@ -87,7 +84,7 @@ class GithubAuth implements OAuthApi, SessionApi { const authSessionStore = new AuthSessionStore({ manager: sessionManager, - storageKey: storageKey, + storageKey: `${provider.id}Session`, sessionScopes: (session: GithubSession) => session.providerInfo.scopes, }); From 7952667abf1ebf5caef7015b0435196c78c11a4e Mon Sep 17 00:00:00 2001 From: Fidel Coria Date: Tue, 15 Dec 2020 14:35:40 -0600 Subject: [PATCH 38/98] update changelog --- .changeset/sour-badgers-cry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/sour-badgers-cry.md b/.changeset/sour-badgers-cry.md index 41bb0be6ec..cd5aaf7afb 100644 --- a/.changeset/sour-badgers-cry.md +++ b/.changeset/sour-badgers-cry.md @@ -2,4 +2,4 @@ '@backstage/core-api': patch --- -Add argument for storage key to GitHub Auth Api for customizing it's value. +GitHub Auth Api uses provider.id to build storage key name. From 243ee1db84a7b0df41dd350db983a4e84cfc7a84 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 15 Dec 2020 21:46:02 +0100 Subject: [PATCH 39/98] scaffolder-backend: switch location type of example templates to url --- plugins/scaffolder-backend/sample-templates/all-templates.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend/sample-templates/all-templates.yaml b/plugins/scaffolder-backend/sample-templates/all-templates.yaml index 6866543ab0..e4e81fbcb3 100644 --- a/plugins/scaffolder-backend/sample-templates/all-templates.yaml +++ b/plugins/scaffolder-backend/sample-templates/all-templates.yaml @@ -4,7 +4,7 @@ metadata: name: example-templates description: A collection of all Backstage example templates spec: - type: github + type: url targets: - https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml - https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/springboot-grpc-template/template.yaml From ef4927baf659fc4f209460dfc7274da13a902d5e Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Tue, 15 Dec 2020 22:19:03 +0100 Subject: [PATCH 40/98] techdocs-common: Use || operator instead of full if-else checks --- packages/techdocs-common/src/stages/publish/helpers.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/techdocs-common/src/stages/publish/helpers.ts b/packages/techdocs-common/src/stages/publish/helpers.ts index 4d9e2d327e..138ec611e0 100644 --- a/packages/techdocs-common/src/stages/publish/helpers.ts +++ b/packages/techdocs-common/src/stages/publish/helpers.ts @@ -29,9 +29,8 @@ export const getHeadersForFileExtension = ( fileExtension: string, ): responseHeadersType => { return { - 'Content-Type': mime.contentType(fileExtension) - ? mime.contentType(fileExtension) - : 'text/plain; charset=utf-8', + 'Content-Type': + mime.contentType(fileExtension) || 'text/plain; charset=utf-8', } as responseHeadersType; }; From f9bc88ddb8fcfa0100a5a8939b94bc7493bf14b5 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Tue, 15 Dec 2020 20:57:16 -0500 Subject: [PATCH 41/98] Wrap entity cards on smaller screens --- .../org/src/components/Cards/OwnershipCard/OwnershipCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.tsx b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.tsx index 16a833cf56..a61dd55161 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.tsx +++ b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.tsx @@ -179,7 +179,7 @@ export const OwnershipCard = ({ {componentsWithCounters?.map(c => ( - + Date: Tue, 15 Dec 2020 20:57:45 -0500 Subject: [PATCH 42/98] Add changeset --- .changeset/chilly-pumpkins-retire.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/chilly-pumpkins-retire.md diff --git a/.changeset/chilly-pumpkins-retire.md b/.changeset/chilly-pumpkins-retire.md new file mode 100644 index 0000000000..b206cb6fe7 --- /dev/null +++ b/.changeset/chilly-pumpkins-retire.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-org': patch +--- + +Wrap entity cards on smaller screens From 86c8e9e32b3dd1a50339653374e58510a92b94a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Dec 2020 04:39:22 +0000 Subject: [PATCH 43/98] build(deps-dev): bump @spotify/prettier-config from 8.0.0 to 9.0.0 Bumps [@spotify/prettier-config](https://github.com/spotify/web-scripts) from 8.0.0 to 9.0.0. - [Release notes](https://github.com/spotify/web-scripts/releases) - [Changelog](https://github.com/spotify/web-scripts/blob/master/CHANGELOG.md) - [Commits](https://github.com/spotify/web-scripts/compare/v8.0.0...v9.0.0) Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 887b256628..caf19b0311 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "@changesets/cli": "^2.11.0", "@octokit/openapi-types": "^2.0.0", "@spotify/eslint-config-oss": "^1.0.1", - "@spotify/prettier-config": "^8.0.0", + "@spotify/prettier-config": "^9.0.0", "command-exists": "^1.2.9", "concurrently": "^5.2.0", "fs-extra": "^9.0.0", diff --git a/yarn.lock b/yarn.lock index 3bbeea245d..2b7df4630a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4399,10 +4399,10 @@ resolved "https://registry.npmjs.org/@spotify/eslint-config-typescript/-/eslint-config-typescript-9.0.0.tgz#be68cfaf212599f0bfeb6536c7c58ec05d2b6fba" integrity sha512-ZsXTwMA68ZCz943U4N8XwprdWcc7ErOO/IW8PewLK5lycCZtLnmRkOvAbae7O5qNJPD8b/l0iUMTLaZuwjXWwg== -"@spotify/prettier-config@^8.0.0": - version "8.0.0" - resolved "https://registry.npmjs.org/@spotify/prettier-config/-/prettier-config-8.0.0.tgz#8b6c2bd579ddc54887155a0721fe04e96c89f7f2" - integrity sha512-so8w32ZV42CHWxOEXcBtbNO/hLXFrQNXVmhfzhUI6dVB9cq2xjRaiqu8GjFj8LvKbWpPj+S+KwTIS4aDVWqrFQ== +"@spotify/prettier-config@^9.0.0": + version "9.0.0" + resolved "https://registry.npmjs.org/@spotify/prettier-config/-/prettier-config-9.0.0.tgz#7b562d56573c6fc0094446fbc92b22bc318945dc" + integrity sha512-In1q0tIiqTYKAGe3KOHDcFDdZRFISyQeSeipeTHGfki23ebHRZcjxvqj5SSdBkw65D4VpSREMi0s9i5iJiMcTw== "@storybook/addon-actions@^6.1.11": version "6.1.11" From fa38dd0beaea76699e067feaf08043a5cab0d05f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Dec 2020 04:39:36 +0000 Subject: [PATCH 44/98] build(deps-dev): bump husky from 4.3.0 to 4.3.6 Bumps [husky](https://github.com/typicode/husky) from 4.3.0 to 4.3.6. - [Release notes](https://github.com/typicode/husky/releases) - [Commits](https://github.com/typicode/husky/compare/v4.3.0...v4.3.6) Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 3bbeea245d..fb55eb6ec1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14255,9 +14255,9 @@ humanize-ms@^1.2.1: ms "^2.0.0" husky@^4.2.3: - version "4.3.0" - resolved "https://registry.npmjs.org/husky/-/husky-4.3.0.tgz#0b2ec1d66424e9219d359e26a51c58ec5278f0de" - integrity sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA== + version "4.3.6" + resolved "https://registry.npmjs.org/husky/-/husky-4.3.6.tgz#ebd9dd8b9324aa851f1587318db4cccb7665a13c" + integrity sha512-o6UjVI8xtlWRL5395iWq9LKDyp/9TE7XMOTvIpEVzW638UcGxTmV5cfel6fsk/jbZSTlvfGVJf2svFtybcIZag== dependencies: chalk "^4.0.0" ci-info "^2.0.0" From 8c52dd48088c813cf613d3128fe338f89c9abb66 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Dec 2020 05:01:40 +0000 Subject: [PATCH 45/98] build(deps): bump rollup-plugin-peer-deps-external from 2.2.3 to 2.2.4 Bumps [rollup-plugin-peer-deps-external](https://github.com/pmowrer/rollup-plugin-peer-deps-external) from 2.2.3 to 2.2.4. - [Release notes](https://github.com/pmowrer/rollup-plugin-peer-deps-external/releases) - [Commits](https://github.com/pmowrer/rollup-plugin-peer-deps-external/compare/v2.2.3...v2.2.4) Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 3bbeea245d..700623b8df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21857,9 +21857,9 @@ rollup-plugin-esbuild@2.6.x: strip-json-comments "^3.1.1" rollup-plugin-peer-deps-external@^2.2.2: - version "2.2.3" - resolved "https://registry.npmjs.org/rollup-plugin-peer-deps-external/-/rollup-plugin-peer-deps-external-2.2.3.tgz#059a8aec1eefb48a475e9fcedc3b9e3deb521213" - integrity sha512-W6IePXTExGXVDAlfZbNUUrx3GxUOZP248u5n4a4ID1XZMrbQ+uGeNiEfapvdzwx0qZi5DNH/hDLiPUP+pzFIxg== + version "2.2.4" + resolved "https://registry.npmjs.org/rollup-plugin-peer-deps-external/-/rollup-plugin-peer-deps-external-2.2.4.tgz#8a420bbfd6dccc30aeb68c9bf57011f2f109570d" + integrity sha512-AWdukIM1+k5JDdAqV/Cxd+nejvno2FVLVeZ74NKggm3Q5s9cbbcOgUPGdbxPi4BXu7xGaZ8HG12F+thImYu/0g== rollup-plugin-postcss@^3.1.1: version "3.1.8" From 4c603b06cdd94ba3ecb1bf8ce6848b0032de3b24 Mon Sep 17 00:00:00 2001 From: keshan Date: Wed, 16 Dec 2020 13:55:49 +0530 Subject: [PATCH 46/98] Adding PagerDuty plugin to marketplace --- microsite/data/plugins/pager-duty.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 microsite/data/plugins/pager-duty.yaml diff --git a/microsite/data/plugins/pager-duty.yaml b/microsite/data/plugins/pager-duty.yaml new file mode 100644 index 0000000000..94946b9959 --- /dev/null +++ b/microsite/data/plugins/pager-duty.yaml @@ -0,0 +1,13 @@ +--- +title: PageDuty +author: Spotify +authorUrl: https://github.com/spotify +category: Discovery +description: PagerDuty offers a simple way to identify any active incidents for an entity and the escalation policy. +documentation: https://github.com/backstage/backstage/tree/master/plugins/pagerduty +iconUrl: https://avatars2.githubusercontent.com/u/766800?s=200&v=4 +npmPackageName: '@backstage/plugin-pagerduty' +tags: + - monitoring + - errors + - alerting From 378918d86b0a8592826ad020ad0e0895a9a6c8d5 Mon Sep 17 00:00:00 2001 From: keshan Date: Wed, 16 Dec 2020 14:55:18 +0530 Subject: [PATCH 47/98] change in category --- microsite/data/plugins/pager-duty.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/data/plugins/pager-duty.yaml b/microsite/data/plugins/pager-duty.yaml index 94946b9959..e8a0a1b0d9 100644 --- a/microsite/data/plugins/pager-duty.yaml +++ b/microsite/data/plugins/pager-duty.yaml @@ -2,7 +2,7 @@ title: PageDuty author: Spotify authorUrl: https://github.com/spotify -category: Discovery +category: Monitoring description: PagerDuty offers a simple way to identify any active incidents for an entity and the escalation policy. documentation: https://github.com/backstage/backstage/tree/master/plugins/pagerduty iconUrl: https://avatars2.githubusercontent.com/u/766800?s=200&v=4 From 21a3d3dcac11906600ff5730f05368fc50865c5c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 2 Dec 2020 18:31:59 +0100 Subject: [PATCH 48/98] cost-insights: refactor plugin creation to call createPlugin directly Co-authored-by: blam --- plugins/cost-insights/dev/index.tsx | 23 +++++++++-------------- plugins/cost-insights/src/plugin.ts | 8 +++----- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/plugins/cost-insights/dev/index.tsx b/plugins/cost-insights/dev/index.tsx index fe208d5bb8..bdbb4450fa 100644 --- a/plugins/cost-insights/dev/index.tsx +++ b/plugins/cost-insights/dev/index.tsx @@ -14,20 +14,15 @@ * limitations under the License. */ import { createDevApp } from '@backstage/dev-utils'; -import { createPlugin, createApiFactory } from '@backstage/core'; import { costInsightsApiRef } from '../src/api'; import { ExampleCostInsightsClient } from '../src/client'; -import { pluginConfig } from '../src/plugin'; +import { plugin } from '../src/plugin'; -const devPlugin = createPlugin({ - ...pluginConfig, - apis: [ - createApiFactory({ - api: costInsightsApiRef, - deps: {}, - factory: () => new ExampleCostInsightsClient(), - }), - ], -}); - -createDevApp().registerPlugin(devPlugin).render(); +createDevApp() + .registerPlugin(plugin) + .registerApi({ + api: costInsightsApiRef, + deps: {}, + factory: () => new ExampleCostInsightsClient(), + }) + .render(); diff --git a/plugins/cost-insights/src/plugin.ts b/plugins/cost-insights/src/plugin.ts index 58465f6711..7006d5bf5d 100644 --- a/plugins/cost-insights/src/plugin.ts +++ b/plugins/cost-insights/src/plugin.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { createPlugin, createRouteRef, PluginConfig } from '@backstage/core'; +import { createPlugin, createRouteRef } from '@backstage/core'; import { CostInsightsPage } from './components/CostInsightsPage'; import { ProjectGrowthInstructionsPage } from './components/ProjectGrowthInstructionsPage'; import { LabelDataflowInstructionsPage } from './components/LabelDataflowInstructionsPage'; @@ -34,7 +34,7 @@ export const unlabeledDataflowAlertRef = createRouteRef({ title: 'Labeling Dataflow Jobs', }); -export const pluginConfig: PluginConfig = { +export const plugin = createPlugin({ id: 'cost-insights', register({ router, featureFlags }) { router.addRoute(rootRouteRef, CostInsightsPage); @@ -42,6 +42,4 @@ export const pluginConfig: PluginConfig = { router.addRoute(unlabeledDataflowAlertRef, LabelDataflowInstructionsPage); featureFlags.register('cost-insights-currencies'); }, -}; - -export const plugin = createPlugin(pluginConfig); +}); From 47930a36f79bc09890bdf9c1bd3dae3a7c01e074 Mon Sep 17 00:00:00 2001 From: mateiidavid Date: Thu, 10 Dec 2020 12:34:09 +0000 Subject: [PATCH 49/98] Implement readTree for GitlabReader (#3547) * This change adds an implementation for the readTree method in GitlabReader. The implementation is similar to the readTree method in GithubReader with the exception of the 'path' variable used for subpaths in the archive. To facilitate this, GitlabIntegrationConfig now has an apiUrl field which was missing for Gitlab but was present for Bitbucket & GH. * As part of this change, there are also new tests added to GitlabReader to mirror what has been done with the GH reader. For now the archive format chosen is 'zip', follow-up action includes having a look at whether tar.gz is preferable. Signed-off-by: Matei David --- .../src/reading/GitlabUrlReader.test.ts | 286 ++++++++++++------ .../src/reading/GitlabUrlReader.ts | 66 +++- packages/integration/src/gitlab/config.ts | 20 +- 3 files changed, 273 insertions(+), 99 deletions(-) diff --git a/packages/backend-common/src/reading/GitlabUrlReader.test.ts b/packages/backend-common/src/reading/GitlabUrlReader.test.ts index 3a76c0631b..6cc5e30dbd 100644 --- a/packages/backend-common/src/reading/GitlabUrlReader.test.ts +++ b/packages/backend-common/src/reading/GitlabUrlReader.test.ts @@ -14,12 +14,14 @@ * limitations under the License. */ +import { ConfigReader } from '@backstage/config'; +import { msw } from '@backstage/test-utils'; +import fs from 'fs'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; -import { ConfigReader } from '@backstage/config'; +import path from 'path'; import { getVoidLogger } from '../logging'; import { GitlabUrlReader } from './GitlabUrlReader'; -import { msw } from '@backstage/test-utils'; import { ReadTreeResponseFactory } from './tree'; const logger = getVoidLogger(); @@ -30,105 +32,207 @@ const treeResponseFactory = ReadTreeResponseFactory.create({ describe('GitlabUrlReader', () => { const worker = setupServer(); - msw.setupDefaultHandlers(worker); - beforeEach(() => { - worker.use( - rest.get('*/api/v4/projects/:name', (_, res, ctx) => - res(ctx.status(200), ctx.json({ id: 12345 })), - ), - rest.get('*', (req, res, ctx) => - res( - ctx.status(200), - ctx.json({ - url: req.url.toString(), - headers: req.headers.getAllHeaders(), - }), + describe('implementation', () => { + beforeEach(() => { + worker.use( + rest.get('*/api/v4/projects/:name', (_, res, ctx) => + res(ctx.status(200), ctx.json({ id: 12345 })), ), - ), - ); - }); - - const createConfig = (token?: string) => - new ConfigReader( - { - integrations: { gitlab: [{ host: 'gitlab.com', token }] }, - }, - 'test-config', - ); - - it.each([ - // Project URLs - { - url: - 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/my/path/to/file.yaml', - config: createConfig(), - response: expect.objectContaining({ - url: - 'https://gitlab.com/api/v4/projects/12345/repository/files/my%2Fpath%2Fto%2Ffile.yaml/raw?ref=branch', - headers: expect.objectContaining({ - 'private-token': '', - }), - }), - }, - { - url: - 'https://gitlab.example.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/my/path/to/file.yaml', - config: createConfig('0123456789'), - response: expect.objectContaining({ - url: - 'https://gitlab.example.com/api/v4/projects/12345/repository/files/my%2Fpath%2Fto%2Ffile.yaml/raw?ref=branch', - headers: expect.objectContaining({ - 'private-token': '0123456789', - }), - }), - }, - { - url: - 'https://gitlab.com/groupA/teams/teamA/repoA/-/blob/branch/my/path/to/file.yaml', // Repo not in subgroup - config: createConfig(), - response: expect.objectContaining({ - url: - 'https://gitlab.com/api/v4/projects/12345/repository/files/my%2Fpath%2Fto%2Ffile.yaml/raw?ref=branch', - }), - }, - - // Raw URLs - { - url: 'https://gitlab.example.com/a/b/blob/master/c.yaml', - config: createConfig(), - response: expect.objectContaining({ - url: 'https://gitlab.example.com/a/b/raw/master/c.yaml', - }), - }, - ])('should handle happy path %#', async ({ url, config, response }) => { - const [{ reader }] = GitlabUrlReader.factory({ - config, - logger, - treeResponseFactory, + rest.get('*', (req, res, ctx) => + res( + ctx.status(200), + ctx.json({ + url: req.url.toString(), + headers: req.headers.getAllHeaders(), + }), + ), + ), + ); }); - const data = await reader.read(url); - const res = await JSON.parse(data.toString('utf-8')); - expect(res).toEqual(response); - }); + const createConfig = (token?: string) => + new ConfigReader( + { + integrations: { gitlab: [{ host: 'gitlab.com', token }] }, + }, + 'test-config', + ); - it.each([ - { - url: '', - config: createConfig(''), - error: - "Invalid type in config for key 'integrations.gitlab[0].token' in 'test-config', got empty-string, wanted string", - }, - ])('should handle error path %#', async ({ url, config, error }) => { - await expect(async () => { + it.each([ + // Project URLs + { + url: + 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/my/path/to/file.yaml', + config: createConfig(), + response: expect.objectContaining({ + url: + 'https://gitlab.com/api/v4/projects/12345/repository/files/my%2Fpath%2Fto%2Ffile.yaml/raw?ref=branch', + headers: expect.objectContaining({ + 'private-token': '', + }), + }), + }, + { + url: + 'https://gitlab.example.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/my/path/to/file.yaml', + config: createConfig('0123456789'), + response: expect.objectContaining({ + url: + 'https://gitlab.example.com/api/v4/projects/12345/repository/files/my%2Fpath%2Fto%2Ffile.yaml/raw?ref=branch', + headers: expect.objectContaining({ + 'private-token': '0123456789', + }), + }), + }, + { + url: + 'https://gitlab.com/groupA/teams/teamA/repoA/-/blob/branch/my/path/to/file.yaml', // Repo not in subgroup + config: createConfig(), + response: expect.objectContaining({ + url: + 'https://gitlab.com/api/v4/projects/12345/repository/files/my%2Fpath%2Fto%2Ffile.yaml/raw?ref=branch', + }), + }, + + // Raw URLs + { + url: 'https://gitlab.example.com/a/b/blob/master/c.yaml', + config: createConfig(), + response: expect.objectContaining({ + url: 'https://gitlab.example.com/a/b/raw/master/c.yaml', + }), + }, + ])('should handle happy path %#', async ({ url, config, response }) => { const [{ reader }] = GitlabUrlReader.factory({ config, logger, treeResponseFactory, }); - await reader.read(url); - }).rejects.toThrow(error); + + const data = await reader.read(url); + const res = await JSON.parse(data.toString('utf-8')); + expect(res).toEqual(response); + }); + + it.each([ + { + url: '', + config: createConfig(''), + error: + "Invalid type in config for key 'integrations.gitlab[0].token' in 'test-config', got empty-string, wanted string", + }, + ])('should handle error path %#', async ({ url, config, error }) => { + await expect(async () => { + const [{ reader }] = GitlabUrlReader.factory({ + config, + logger, + treeResponseFactory, + }); + await reader.read(url); + }).rejects.toThrow(error); + }); + }); + + describe('readTree', () => { + const repoBuffer = fs.readFileSync( + path.resolve('src', 'reading', '__fixtures__', 'repo.zip'), + ); + + beforeEach(() => { + worker.use( + rest.get( + 'https://gitlab.com/backstage/mock/-/archive/repo/mock-repo.zip', + (_, res, ctx) => + res( + ctx.status(200), + ctx.set('Content-Type', 'application/zip'), + ctx.body(repoBuffer), + ), + ), + ); + }); + + it('returns the wanted files from an archive', async () => { + const processor = new GitlabUrlReader( + { host: 'gitlab.com' }, + { treeResponseFactory }, + ); + + const response = await processor.readTree( + 'https://gitlab.com/backstage/mock/tree/repo', + ); + + const files = await response.files(); + expect(files.length).toBe(2); + + const indexMarkdownFile = await files[0].content(); + const mkDocsFile = await files[1].content(); + + expect(mkDocsFile.toString()).toBe('site_name: Test\n'); + expect(indexMarkdownFile.toString()).toBe('# Test\n'); + }); + + it('returns the wanted files from hosted gitlab', async () => { + worker.use( + rest.get( + 'https://git.mycompany.com/backstage/mock/-/archive/repo/mock-repo.zip', + (_, res, ctx) => + res( + ctx.status(200), + ctx.set('Content-Type', 'application/zip'), + ctx.body(repoBuffer), + ), + ), + ); + + const processor = new GitlabUrlReader( + { host: 'git.mycompany.com' }, + { treeResponseFactory }, + ); + + const response = await processor.readTree( + 'https://git.mycompany.com/backstage/mock/tree/repo/docs', + ); + + const files = await response.files(); + + expect(files.length).toBe(1); + const indexMarkdownFile = await files[0].content(); + + expect(indexMarkdownFile.toString()).toBe('# Test\n'); + }); + + it('throws an error when branch is not specified', async () => { + const processor = new GitlabUrlReader( + { host: 'gitlab.com' }, + { treeResponseFactory }, + ); + + await expect( + processor.readTree('https://gitlab.com/backstage/mock'), + ).rejects.toThrow( + 'GitLab URL must contain a branch to be able to fetch its tree', + ); + }); + + it('returns the wanted files from an archive with a subpath', async () => { + const processor = new GitlabUrlReader( + { host: 'gitlab.com' }, + { treeResponseFactory }, + ); + + const response = await processor.readTree( + 'https://gitlab.com/backstage/mock/tree/repo/docs', + ); + + const files = await response.files(); + + expect(files.length).toBe(1); + const indexMarkdownFile = await files[0].content(); + + expect(indexMarkdownFile.toString()).toBe('# Test\n'); + }); }); }); diff --git a/packages/backend-common/src/reading/GitlabUrlReader.ts b/packages/backend-common/src/reading/GitlabUrlReader.ts index d6d1da5cbb..d51e8dc090 100644 --- a/packages/backend-common/src/reading/GitlabUrlReader.ts +++ b/packages/backend-common/src/reading/GitlabUrlReader.ts @@ -21,22 +21,37 @@ import { readGitLabIntegrationConfigs, } from '@backstage/integration'; import fetch from 'cross-fetch'; -import { NotFoundError } from '../errors'; -import { ReaderFactory, ReadTreeResponse, UrlReader } from './types'; +import { InputError, NotFoundError } from '../errors'; +import { ReadTreeResponseFactory } from './tree'; +import { + ReaderFactory, + ReadTreeOptions, + ReadTreeResponse, + UrlReader, +} from './types'; +import parseGitUri from 'git-url-parse'; +import { Readable } from 'stream'; export class GitlabUrlReader implements UrlReader { - static factory: ReaderFactory = ({ config }) => { + private readonly treeResponseFactory: ReadTreeResponseFactory; + + static factory: ReaderFactory = ({ config, treeResponseFactory }) => { const configs = readGitLabIntegrationConfigs( config.getOptionalConfigArray('integrations.gitlab') ?? [], ); return configs.map(options => { - const reader = new GitlabUrlReader(options); + const reader = new GitlabUrlReader(options, { treeResponseFactory }); const predicate = (url: URL) => url.host === options.host; return { reader, predicate }; }); }; - constructor(private readonly options: GitLabIntegrationConfig) {} + constructor( + private readonly options: GitLabIntegrationConfig, + deps: { treeResponseFactory: ReadTreeResponseFactory }, + ) { + this.treeResponseFactory = deps.treeResponseFactory; + } async read(url: string): Promise { const builtUrl = await getGitLabFileFetchUrl(url, this.options); @@ -59,8 +74,45 @@ export class GitlabUrlReader implements UrlReader { throw new Error(message); } - readTree(): Promise { - throw new Error('GitlabUrlReader does not implement readTree'); + async readTree( + url: string, + options?: ReadTreeOptions, + ): Promise { + const { + name: repoName, + ref, + protocol, + resource, + full_name, + filepath, + } = parseGitUri(url); + + if (!ref) { + throw new InputError( + 'GitLab URL must contain a branch to be able to fetch its tree', + ); + } + + const archive = `${protocol}://${resource}/${full_name}/-/archive/${ref}/${repoName}-${ref}.zip`; + const response = await fetch( + archive, + getGitLabRequestOptions(this.options), + ); + if (!response.ok) { + const msg = `Failed to read tree from ${url}, ${response.status} ${response.statusText}`; + if (response.status === 404) { + throw new NotFoundError(msg); + } + throw new Error(msg); + } + + const path = filepath ? `${repoName}-${ref}/${filepath}/` : ''; + + return this.treeResponseFactory.fromZipArchive({ + stream: (response.body as unknown) as Readable, + path, + filter: options?.filter, + }); } toString() { diff --git a/packages/integration/src/gitlab/config.ts b/packages/integration/src/gitlab/config.ts index a38312d01a..2d9f4b39ab 100644 --- a/packages/integration/src/gitlab/config.ts +++ b/packages/integration/src/gitlab/config.ts @@ -18,6 +18,7 @@ import { Config } from '@backstage/config'; import { isValidHost } from '../helpers'; const GITLAB_HOST = 'gitlab.com'; +const GITLAB_API_BASE_URL = 'gitlab.com/api/v4'; /** * The configuration parameters for a single GitLab integration. @@ -28,6 +29,17 @@ export type GitLabIntegrationConfig = { */ host: string; + /** + * The base URL of the API of this provider, e.g. "https://gitlab.com/api/v4", + * with no trailing slash. + * + * May be omitted specifically for GitLab; then it will be deduced. + * + * The API will always be preferred if both its base URL and a token are + * present. + */ + apiBaseUrl?: string; + /** * The authorization token to use for requests this provider. * @@ -45,6 +57,7 @@ export function readGitLabIntegrationConfig( config: Config, ): GitLabIntegrationConfig { const host = config.getOptionalString('host') ?? GITLAB_HOST; + let apiBaseUrl = config.getOptionalString('apiBaseUrl'); const token = config.getOptionalString('token'); if (!isValidHost(host)) { @@ -53,7 +66,12 @@ export function readGitLabIntegrationConfig( ); } - return { host, token }; + if (apiBaseUrl) { + apiBaseUrl = apiBaseUrl.replace(/\/+$/, ''); + } else if (host === GITLAB_HOST) { + apiBaseUrl = GITLAB_API_BASE_URL; + } + return { host, token, apiBaseUrl }; } /** From 19f5c5e9905178ee19f44ddab6e6c2302176531a Mon Sep 17 00:00:00 2001 From: mateiidavid Date: Tue, 15 Dec 2020 12:56:39 +0000 Subject: [PATCH 50/98] Change Gitlab config test to include apiBaseurl --- packages/integration/src/gitlab/config.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/integration/src/gitlab/config.test.ts b/packages/integration/src/gitlab/config.test.ts index 2c4224a2c4..e817465b83 100644 --- a/packages/integration/src/gitlab/config.test.ts +++ b/packages/integration/src/gitlab/config.test.ts @@ -41,7 +41,10 @@ describe('readGitLabIntegrationConfig', () => { it('inserts the defaults if missing', () => { const output = readGitLabIntegrationConfig(buildConfig({})); - expect(output).toEqual({ host: 'gitlab.com' }); + expect(output).toEqual({ + host: 'gitlab.com', + apiBaseUrl: 'gitlab.com/api/v4', + }); }); it('rejects funky configs', () => { From 4eafdec4a05aedb48fc69473014b86b1048d3107 Mon Sep 17 00:00:00 2001 From: mateiidavid Date: Wed, 16 Dec 2020 14:17:37 +0000 Subject: [PATCH 51/98] Create changeset --- .changeset/pink-ravens-destroy.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/pink-ravens-destroy.md diff --git a/.changeset/pink-ravens-destroy.md b/.changeset/pink-ravens-destroy.md new file mode 100644 index 0000000000..84a2c4a964 --- /dev/null +++ b/.changeset/pink-ravens-destroy.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-common': minor +'@backstage/integration': minor +--- + +Introduce readTree method for GitLab URL Reader From eb39a633e8adf3c3cbd5715efeba6ec86115ab11 Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Wed, 16 Dec 2020 15:42:26 +0100 Subject: [PATCH 52/98] docs: Improvements suggested by Anders --- docs/features/techdocs/concepts.md | 22 ++++++++++++---------- docs/features/techdocs/getting-started.md | 5 +++-- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/docs/features/techdocs/concepts.md b/docs/features/techdocs/concepts.md index 48204342a9..26254a7e12 100644 --- a/docs/features/techdocs/concepts.md +++ b/docs/features/techdocs/concepts.md @@ -8,11 +8,13 @@ Spotify's docs-like-code solution in Backstage This page describes concepts that are introduced with Spotify's docs-like-code solution in Backstage. +## Generating TechDocs Steps + ### TechDocs Preparer -Prepare is the first step of generating documentation for an entity. It fetches -the source markdown files from the source code hosting provider (GitHub, GitLab, -etc.) and passes the files to the generator for next steps. +Preparing is the first step of generating documentation for an entity. It +fetches the source markdown files from the source code hosting provider (GitHub, +GitLab, etc.) and passes the files to the generator for next steps. There are two kinds of preparers available - @@ -22,13 +24,13 @@ There are two kinds of preparers available - ### TechDocs Generator -Generation is the second step after preparing the markdown source files. This +Generating is the second step after preparing the markdown source files. This step either runs the TechDocs container (defined below) or runs `mkdocs` CLI to generate static HTML files and its assets. ### TechDocs Publisher -Publish is the third and final step after preparing and generating docs. +Publishing is the third and final step after preparing and generating docs. TechDocs Publisher uploads the generated files to a storage. The `techdocs-backend` plugin currently comes with two publishers - Google Cloud @@ -44,7 +46,7 @@ between `techdocs-backend` and the storage) [TechDocs Backend](https://github.com/backstage/backstage/tree/master/plugins/techdocs-backend) -### TechDocs container +## TechDocs Container The TechDocs container is a Docker container available at [DockerHub](https://hub.docker.com/r/spotify/techdocs). It builds static HTML @@ -53,7 +55,7 @@ MkDocs. [TechDocs Container](https://github.com/backstage/techdocs-container) -### TechDocs Core Plugin +## TechDocs Core Plugin The TechDocs Core Plugin is an [MkDocs](https://www.mkdocs.org/) plugin created as a wrapper around multiple MkDocs plugins and Python Markdown extensions to @@ -61,7 +63,7 @@ standardize the configuration of MkDocs used for TechDocs. [TechDocs Core](https://github.com/backstage/mkdocs-techdocs-core) -### TechDocs CLI +## TechDocs CLI The TechDocs CLI was created to make it easy to write, generate and preview documentation for publishing. Currently it mostly acts as a wrapper around the @@ -70,7 +72,7 @@ container. [TechDocs CLI](https://github.com/backstage/techdocs-cli) -### TechDocs Reader +## TechDocs Reader Documentation generated by TechDocs is generated as static HTML sites. The TechDocs Reader was therefore created to be able to integrate pre-generated HTML @@ -82,7 +84,7 @@ TechDocs widgets for a customized full-featured TechDocs experience. [TechDocs Reader](https://github.com/backstage/backstage/blob/master/plugins/techdocs/src/reader/README.md) -### Transformers +## Transformers Transformers are different pieces of functionality used inside the TechDocs Reader. The reason why transformers were introduced was to provide a way to diff --git a/docs/features/techdocs/getting-started.md b/docs/features/techdocs/getting-started.md index 0437f3ca47..c82bc8b95b 100644 --- a/docs/features/techdocs/getting-started.md +++ b/docs/features/techdocs/getting-started.md @@ -12,7 +12,8 @@ If you haven't setup Backstage already, start > If you used `npx @backstage/create-app`, TechDocs may already be present. > -> You should skip to `Setting the Configuration` below. +> You should skip to [`Setting the Configuration`](#setting-the-configuration) +> below. ## Adding TechDocs frontend plugin @@ -250,7 +251,7 @@ the dependencies. For example, we want `Markdown` version to be You can also explicitly install `Markdown==3.2.2` after installing all other Python packages. -## Run Backstage locally +## Running Backstage locally Start the frontend and the backend app by [running backstage locally](../../getting-started/running-backstage-locally.md). From e7496dc3e2841b5cf2303acdfc700fc5079e7447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 16 Dec 2020 16:23:37 +0100 Subject: [PATCH 53/98] catalog-backend: break out github org config for consistency --- .changeset/good-news-return.md | 5 ++ .../GithubOrgReaderProcessor.test.ts | 62 +------------- .../processors/GithubOrgReaderProcessor.ts | 76 ++--------------- .../processors/github/config.test.ts | 79 +++++++++++++++++ .../src/ingestion/processors/github/config.ts | 84 +++++++++++++++++++ .../src/ingestion/processors/github/index.ts | 2 + 6 files changed, 178 insertions(+), 130 deletions(-) create mode 100644 .changeset/good-news-return.md create mode 100644 plugins/catalog-backend/src/ingestion/processors/github/config.test.ts create mode 100644 plugins/catalog-backend/src/ingestion/processors/github/config.ts diff --git a/.changeset/good-news-return.md b/.changeset/good-news-return.md new file mode 100644 index 0000000000..6cb02e6e82 --- /dev/null +++ b/.changeset/good-news-return.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Break out GithubOrgReaderProcessor config into its own file for consistency with the other org processors. diff --git a/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.test.ts index a6a05b15ba..19a08d219f 100644 --- a/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.test.ts @@ -16,69 +16,9 @@ import { getVoidLogger } from '@backstage/backend-common'; import { LocationSpec } from '@backstage/catalog-model'; -import { ConfigReader } from '@backstage/config'; -import { - GithubOrgReaderProcessor, - parseUrl, - readConfig, -} from './GithubOrgReaderProcessor'; +import { GithubOrgReaderProcessor, parseUrl } from './GithubOrgReaderProcessor'; describe('GithubOrgReaderProcessor', () => { - describe('readConfig', () => { - function config( - providers: { target: string; apiBaseUrl?: string; token?: string }[], - ) { - return new ConfigReader({ - catalog: { processors: { githubOrg: { providers } } }, - }); - } - - it('adds a default GitHub entry when missing', () => { - const output = readConfig(config([])); - expect(output).toEqual([ - { - target: 'https://github.com', - apiBaseUrl: 'https://api.github.com', - }, - ]); - }); - - it('injects the correct GitHub API base URL when missing', () => { - const output = readConfig(config([{ target: 'https://github.com' }])); - expect(output).toEqual([ - { - target: 'https://github.com', - apiBaseUrl: 'https://api.github.com', - }, - ]); - }); - - it('rejects custom targets with no base URLs', () => { - expect(() => - readConfig(config([{ target: 'https://ghe.company.com' }])), - ).toThrow( - 'Provider at https://ghe.company.com must configure an explicit apiBaseUrl', - ); - }); - - it('rejects funky configs', () => { - expect(() => readConfig(config([{ target: 7 } as any]))).toThrow( - /target/, - ); - expect(() => readConfig(config([{ noTarget: '7' } as any]))).toThrow( - /target/, - ); - expect(() => - readConfig( - config([{ target: 'https://github.com', apiBaseUrl: 7 } as any]), - ), - ).toThrow(/apiBaseUrl/); - expect(() => - readConfig(config([{ target: 'https://github.com', token: 7 } as any])), - ).toThrow(/token/); - }); - }); - describe('parseUrl', () => { it('only supports clean org urls, and decodes them', () => { expect(() => parseUrl('https://github.com')).toThrow(); diff --git a/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.ts index ab6e3aa008..6a83d705f6 100644 --- a/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.ts @@ -18,7 +18,12 @@ import { LocationSpec } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import { graphql } from '@octokit/graphql'; import { Logger } from 'winston'; -import { getOrganizationTeams, getOrganizationUsers } from './github'; +import { + getOrganizationTeams, + getOrganizationUsers, + ProviderConfig, + readGithubConfig, +} from './github'; import * as results from './results'; import { CatalogProcessor, CatalogProcessorEmit } from './types'; import { buildOrgHierarchy } from './util/org'; @@ -33,7 +38,7 @@ export class GithubOrgReaderProcessor implements CatalogProcessor { static fromConfig(config: Config, options: { logger: Logger }) { return new GithubOrgReaderProcessor({ ...options, - providers: readConfig(config), + providers: readGithubConfig(config), }); } @@ -113,73 +118,6 @@ export class GithubOrgReaderProcessor implements CatalogProcessor { * Helpers */ -/** - * The configuration parameters for a single GitHub API provider. - */ -type ProviderConfig = { - /** - * The prefix of the target that this matches on, e.g. "https://github.com", - * with no trailing slash. - */ - target: string; - - /** - * The base URL of the API of this provider, e.g. "https://api.github.com", - * with no trailing slash. - * - * May be omitted specifically for GitHub; then it will be deduced. - */ - apiBaseUrl?: string; - - /** - * The authorization token to use for requests to this provider. - * - * If no token is specified, anonymous access is used. - */ - token?: string; -}; - -// TODO(freben): Break out common code and config from here and GithubReaderProcessor -export function readConfig(config: Config): ProviderConfig[] { - const providers: ProviderConfig[] = []; - - const providerConfigs = - config.getOptionalConfigArray('catalog.processors.githubOrg.providers') ?? - []; - - // First read all the explicit providers - for (const providerConfig of providerConfigs) { - const target = providerConfig.getString('target').replace(/\/+$/, ''); - let apiBaseUrl = providerConfig.getOptionalString('apiBaseUrl'); - const token = providerConfig.getOptionalString('token'); - - if (apiBaseUrl) { - apiBaseUrl = apiBaseUrl.replace(/\/+$/, ''); - } else if (target === 'https://github.com') { - apiBaseUrl = 'https://api.github.com'; - } - - if (!apiBaseUrl) { - throw new Error( - `Provider at ${target} must configure an explicit apiBaseUrl`, - ); - } - - providers.push({ target, apiBaseUrl, token }); - } - - // If no explicit github.com provider was added, put one in the list as - // a convenience - if (!providers.some(p => p.target === 'https://github.com')) { - providers.push({ - target: 'https://github.com', - apiBaseUrl: 'https://api.github.com', - }); - } - - return providers; -} - export function parseUrl(urlString: string): { org: string } { const path = new URL(urlString).pathname.substr(1).split('/'); diff --git a/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts b/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts new file mode 100644 index 0000000000..14f3caa42c --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts @@ -0,0 +1,79 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { readGithubConfig } from './config'; + +describe('config', () => { + describe('readGithubConfig', () => { + function config( + providers: { target: string; apiBaseUrl?: string; token?: string }[], + ) { + return new ConfigReader({ + catalog: { processors: { githubOrg: { providers } } }, + }); + } + + it('adds a default GitHub entry when missing', () => { + const output = readGithubConfig(config([])); + expect(output).toEqual([ + { + target: 'https://github.com', + apiBaseUrl: 'https://api.github.com', + }, + ]); + }); + + it('injects the correct GitHub API base URL when missing', () => { + const output = readGithubConfig( + config([{ target: 'https://github.com' }]), + ); + expect(output).toEqual([ + { + target: 'https://github.com', + apiBaseUrl: 'https://api.github.com', + }, + ]); + }); + + it('rejects custom targets with no base URLs', () => { + expect(() => + readGithubConfig(config([{ target: 'https://ghe.company.com' }])), + ).toThrow( + 'Provider at https://ghe.company.com must configure an explicit apiBaseUrl', + ); + }); + + it('rejects funky configs', () => { + expect(() => readGithubConfig(config([{ target: 7 } as any]))).toThrow( + /target/, + ); + expect(() => + readGithubConfig(config([{ noTarget: '7' } as any])), + ).toThrow(/target/); + expect(() => + readGithubConfig( + config([{ target: 'https://github.com', apiBaseUrl: 7 } as any]), + ), + ).toThrow(/apiBaseUrl/); + expect(() => + readGithubConfig( + config([{ target: 'https://github.com', token: 7 } as any]), + ), + ).toThrow(/token/); + }); + }); +}); diff --git a/plugins/catalog-backend/src/ingestion/processors/github/config.ts b/plugins/catalog-backend/src/ingestion/processors/github/config.ts new file mode 100644 index 0000000000..88f2f96218 --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/processors/github/config.ts @@ -0,0 +1,84 @@ +/* + * Copyright 2020 Spotify AB + * + * 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'; + +/** + * The configuration parameters for a single GitHub API provider. + */ +export type ProviderConfig = { + /** + * The prefix of the target that this matches on, e.g. "https://github.com", + * with no trailing slash. + */ + target: string; + + /** + * The base URL of the API of this provider, e.g. "https://api.github.com", + * with no trailing slash. + * + * May be omitted specifically for GitHub; then it will be deduced. + */ + apiBaseUrl?: string; + + /** + * The authorization token to use for requests to this provider. + * + * If no token is specified, anonymous access is used. + */ + token?: string; +}; + +// TODO(freben): Break out common code and config from here and GithubReaderProcessor +export function readGithubConfig(config: Config): ProviderConfig[] { + const providers: ProviderConfig[] = []; + + const providerConfigs = + config.getOptionalConfigArray('catalog.processors.githubOrg.providers') ?? + []; + + // First read all the explicit providers + for (const providerConfig of providerConfigs) { + const target = providerConfig.getString('target').replace(/\/+$/, ''); + let apiBaseUrl = providerConfig.getOptionalString('apiBaseUrl'); + const token = providerConfig.getOptionalString('token'); + + if (apiBaseUrl) { + apiBaseUrl = apiBaseUrl.replace(/\/+$/, ''); + } else if (target === 'https://github.com') { + apiBaseUrl = 'https://api.github.com'; + } + + if (!apiBaseUrl) { + throw new Error( + `Provider at ${target} must configure an explicit apiBaseUrl`, + ); + } + + providers.push({ target, apiBaseUrl, token }); + } + + // If no explicit github.com provider was added, put one in the list as + // a convenience + if (!providers.some(p => p.target === 'https://github.com')) { + providers.push({ + target: 'https://github.com', + apiBaseUrl: 'https://api.github.com', + }); + } + + return providers; +} diff --git a/plugins/catalog-backend/src/ingestion/processors/github/index.ts b/plugins/catalog-backend/src/ingestion/processors/github/index.ts index e903ab669a..e424d7bafb 100644 --- a/plugins/catalog-backend/src/ingestion/processors/github/index.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/index.ts @@ -14,4 +14,6 @@ * limitations under the License. */ +export { readGithubConfig } from './config'; +export type { ProviderConfig } from './config'; export { getOrganizationTeams, getOrganizationUsers } from './github'; From d8e9b75dc7cafa5357bb727b48178a2e82385d99 Mon Sep 17 00:00:00 2001 From: mateiidavid Date: Wed, 16 Dec 2020 16:46:59 +0000 Subject: [PATCH 54/98] Change changeset to patch --- .changeset/pink-ravens-destroy.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/pink-ravens-destroy.md b/.changeset/pink-ravens-destroy.md index 84a2c4a964..647ccd9f37 100644 --- a/.changeset/pink-ravens-destroy.md +++ b/.changeset/pink-ravens-destroy.md @@ -1,6 +1,6 @@ --- -'@backstage/backend-common': minor -'@backstage/integration': minor +'@backstage/backend-common': patch +'@backstage/integration': patch --- Introduce readTree method for GitLab URL Reader From c0a55d0968656e36cdedf1a99c25b807eb352322 Mon Sep 17 00:00:00 2001 From: AlleyWei <64219471+AlleyWei@users.noreply.github.com> Date: Wed, 16 Dec 2020 12:47:53 -0500 Subject: [PATCH 55/98] Update roadmap.md --- docs/overview/roadmap.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/overview/roadmap.md b/docs/overview/roadmap.md index a75c000b8a..8d6f6587c5 100644 --- a/docs/overview/roadmap.md +++ b/docs/overview/roadmap.md @@ -47,26 +47,27 @@ guidelines to get started. ### Ongoing work 🚧 -- **[Backstage platform is stable](https://github.com/backstage/backstage/milestone/19)** - - The core of Backstage and its features are stable and can be depended on for - production use. After this plugins will require little to no maintenance. +- **[Platform stabilization](https://github.com/backstage/backstage/milestone/19)** - + Stabilize the core of Backstage, including its core features, so that the platform can be + depended on for production use. After this, plugins will require little-to-no maintenance. -- **[Improved Kubernetes plugin](https://github.com/backstage/backstage/issues/2857)** - - Native support for Kubernetes, making it easier for developers to see and - manage their services running in k8s. +- **[Kubernetes plugin for service owners](https://github.com/backstage/backstage/issues/2857)** - + Improve native support for Kubernetes, making it easier for service owners to see and + manage their services running in K8s, regardless if that's locally, in AWS, GCS, Azure, + or elsewhere. -- **Global search** - Extend the basic search available in the Backstage Service - Catalog with a global search experience. +- **Global search** - Extend the basic search functionality currently available in the + Backstage Service Catalog to become a global search experience. - **[Software Templates V2](https://github.com/backstage/backstage/issues/2771)** - - Expanding the templates to make steps more composable, by adding the ability - to add more steps for custom logic like webhooks and using authorization from + Expand the templates to make the steps more composable by adding the ability + to add more steps for custom logic, including webhooks and using authorization from integrations. ### Future work 🔮 -- **Golden Path for Plugin Development** - Creating an easy, standardized way - for developers to build plugins will encourage contributions and lead to a +- **Golden Path for Plugin Development** - Create an easy, standardized way + for developers to build plugins that will encourage contributions and lead to a richer ecosystem for everyone. - **[GraphQL API](https://github.com/backstage/backstage/milestone/13)** - A @@ -74,12 +75,11 @@ guidelines to get started. query. Plugins can easily query this API as well as extend the model where needed. -- **Inter Plugin Communication** - **[Under consideration]** Establish more +- **Inter-Plugin Communication** - **[Under consideration]** Establish more clearly defined patterns for plugins to communicate. - **Improved Access Control** - **[Under consideration]** Provide finer grained - access controls and management making it possible for you to better control - the platforms user experience. + access controls and management for better control of the platform user experience. ### Plugins From 90f22cc2db1b2301b9a134ae87f69e11ecf14510 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 17 Dec 2020 01:29:51 +0100 Subject: [PATCH 56/98] chore: when serving with app-backend, the frontend needs unsafe-eval for the patterns in react-jsonschema-form or ajv validation --- packages/backend-common/src/service/lib/ServiceBuilderImpl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts index 778e25f71c..46bf23beef 100644 --- a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts +++ b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts @@ -52,7 +52,7 @@ const DEFAULT_CSP = { 'frame-ancestors': ["'self'"], 'img-src': ["'self'", 'data:'], 'object-src': ["'none'"], - 'script-src': ["'self'"], + 'script-src': ["'self'", "'unsafe-eval'"], 'script-src-attr': ["'none'"], 'style-src': ["'self'", 'https:', "'unsafe-inline'"], 'upgrade-insecure-requests': [] as string[], From 30d6c78fb2a79cd9b58e3366ec2950e509715279 Mon Sep 17 00:00:00 2001 From: keshan Date: Wed, 16 Dec 2020 12:13:21 +0530 Subject: [PATCH 57/98] Introduced config schema for plugins/catalog-backend --- .changeset/slimy-penguins-sing.md | 5 ++++ plugins/catalog-backend/config.d.ts | 44 ++++++++++++++++++++++++++++ plugins/catalog-backend/package.json | 6 ++-- 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 .changeset/slimy-penguins-sing.md create mode 100644 plugins/catalog-backend/config.d.ts diff --git a/.changeset/slimy-penguins-sing.md b/.changeset/slimy-penguins-sing.md new file mode 100644 index 0000000000..62b27a1ce6 --- /dev/null +++ b/.changeset/slimy-penguins-sing.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Added configuration schema for the commonly used properties diff --git a/plugins/catalog-backend/config.d.ts b/plugins/catalog-backend/config.d.ts new file mode 100644 index 0000000000..1978b573f6 --- /dev/null +++ b/plugins/catalog-backend/config.d.ts @@ -0,0 +1,44 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface Config { + /** Configuration options for the catalog plugin */ + + catalog?: { + rules?: Array<{ + allow: Array; + }>; + processors?: { + githubOrg?: { + providers: Array<{ + [key: string]: string; + }>; + }; + ldapOrg?: { + providers: { + target: string; + bind?: { [key: string]: string }; + users: { [key: string]: string | { [key: string]: string } }; + groups: { [key: string]: string | { [key: string]: string } }; + }; + }; + microsoftGraphOrg?: { + providers: { [key: string]: string }; + }; + }; + locations?: Array<{ [key: string]: string }>; + }; +} diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 180956c986..d8c8641a85 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -70,6 +70,8 @@ }, "files": [ "dist", - "migrations/**/*.{js,d.ts}" - ] + "migrations/**/*.{js,d.ts}", + "config.d.ts" + ], + "configSchema": "config.d.ts" } From 2aa1998525e2f543c95462239f65b43d8230354a Mon Sep 17 00:00:00 2001 From: keshan Date: Thu, 17 Dec 2020 13:08:21 +0530 Subject: [PATCH 58/98] Updated catalog schema based on feedback --- plugins/catalog-backend/config.d.ts | 208 +++++++++++++++++++++++++++- 1 file changed, 201 insertions(+), 7 deletions(-) diff --git a/plugins/catalog-backend/config.d.ts b/plugins/catalog-backend/config.d.ts index 1978b573f6..581d00a006 100644 --- a/plugins/catalog-backend/config.d.ts +++ b/plugins/catalog-backend/config.d.ts @@ -14,31 +14,225 @@ * limitations under the License. */ +import { JsonValue } from '@backstage/config'; +import { StringLocale } from 'yup'; + export interface Config { /** Configuration options for the catalog plugin */ - catalog?: { + /** + * Rules to apply to catalog entities - accepts an array of objects with below attributes + * attr: 'allow' - accepts an array of string. e.g. [Component, API, Group, User, Template, Location] + * opt-attr: 'locations' - accepts an array of key, value pair objects. + * keys: 'target', 'type' + * e.g.[{type: url, target: https://github.com}] + */ rules?: Array<{ allow: Array; + locations?: Array<{ [key: string]: string }>; }>; + /** + * List of processor options and attributes + */ processors?: { + /** + * Github processor configuration + */ githubOrg?: { + /** + * attr: 'providers' - accepts an array of objects with below attributes + */ providers: Array<{ - [key: string]: string; + /** + * attr: 'target' - accepts url string + * e.g. https://ghe.example.net + */ + target: string; + /** + * opt-attr: 'apiBaseUrl' - accepts baseurl string + * e.g. https://ghe.example.net/api + */ + apiBaseUrl?: string; + /** + * opt-attr: 'token' - secret token to authenticate + * e.g. {"$env": "GITHUB_TOKEN"} + * @visibility secret + * */ + token?: string; }>; }; + /** + * LdapOrg processor configuration + */ ldapOrg?: { + /** + * attr: 'providers' - accepts an array of objects with below attributes + */ providers: { + /** + * attr: 'target' - accepts url string e.g. ldaps://ds.example.net + */ target: string; - bind?: { [key: string]: string }; - users: { [key: string]: string | { [key: string]: string } }; - groups: { [key: string]: string | { [key: string]: string } }; + /** + * The settings to use for the a command + * opt-attr: 'bind' - accepts key value pair object + * e.g. {"dn": "uid=ldap-reader-user","secret": {"$secret": {"env": "LDAP_SECRET"}}} + */ + bind?: { + /** + * attr: 'dn' - accepts string with ldap related parameters + * e.g. "dn": "uid=ldap-reader-user,ou=people,ou=example,dc=example,dc=net" + */ + dn: string; + /** + * secret used to authenticate. + * e.g. {"$secret": {"env": "LDAP_SECRET"} + * @visibility secret + * */ + secret: Object; + }; + /** + * The settings that govern the reading and interpretation of users. + * attr: 'users' - accepts key value pair object + */ + users: { + /** + * attr: 'dn' - accepts string with user governing parameters + * e.g. "dn": "ou=people,ou=example,dc=example,dc=net" + */ + + dn: string; + /** + * attr: 'options' - accepts an object of key value pair + * keys: 'scope', 'filter', 'attributes', 'sizeLimit', 'timeLimit', 'derefAliases', 'typesOnly', 'paged' + */ + options: { [key: string]: string | boolean | number }; + /** + * opt-attr: 'set - accepts an object of key value pair + * keys: 'path', 'value' + */ + set?: { [key: string]: string | JsonValue }; + /** + * attr: 'map' - accepts an object og key value pair + * keys: 'rdn', 'name', 'description', 'displayName', 'email', 'picture', 'memberOf' + */ + map: { [key: string]: string }; + }; + /** + * The settings that govern the reading and interpretation of groups. + * attr: 'groups' - accepts key value pair object + */ + groups: { + /** + * attr: 'dn' - accepts string with user governing parameters + * e.g. "dn": "ou=people,ou=example,dc=example,dc=net" + */ + + dn: string; + /** + * attr: 'options' - accepts an object of key value pair + * keys: 'scope', 'filter', 'attributes', 'sizeLimit', 'timeLimit', 'derefAliases', 'typesOnly', 'paged' + */ + options: { [key: string]: string | boolean | number }; + /** + * opt-attr: 'set - accepts an object of key value pair + * keys: 'path', 'value' + */ + set?: { [key: string]: string | JsonValue }; + /** + * attr: 'map' - accepts an object og key value pair + * keys: 'rdn', 'name', 'description', 'displayName', 'email', 'picture', 'memberOf' + */ + map: { [key: string]: string }; + }; }; }; + /** + * microsoftGraphOrg processor configuration + */ microsoftGraphOrg?: { - providers: { [key: string]: string }; + /** + * attr: 'providers' - accepts object with below attributes + */ + providers: { + /** + * attr: 'target' - accepts string + * e.g. https://graph.microsoft.com/v1.0 + */ + + target: string; + /** + * attr: 'authority' - accepts string + * e.g. https://login.microsoftonline.com + */ + + authority: string; + /** + * attr: 'tenantId' - accepts string + * e.g. {"$env": "MICROSOFT_GRAPH_TENANT_ID"} + * @visibility secret + */ + + tenantId: string; + /** + * attr: 'clientId' - accepts string + * e.g. {"$env": "MICROSOFT_GRAPH_CLIENT_ID"} + * @visibility secret + */ + + clientId: string; + /** + * attr: 'clientSecret' - accepts string + * e.g. {"$env": "MICROSOFT_GRAPH_CLIENT_SECRET_TOKEN"} + * @visibility secret + */ + + clientSecret: string; + /** + * opt-attr: 'userFilter' - accepts string + * e.g. accountEnabled eq true and userType eq 'member' + */ + + userFilter?: string; + /** + * opt-attr: 'groupFilter' - accepts string + * e.g. securityEnabled eq false and mailEnabled eq true + */ + + groupFilter?: string; + }; }; }; - locations?: Array<{ [key: string]: string }>; + /** + * Location specific rules used in catalog entities - accepts array of objects with below attributes + */ + locations?: Array<{ + /** + * attr: 'type' - accepts string + * e.g. url + */ + type: string; + /** + * attr: 'target' - accepts string + * e.g. https://github.com/org/repo/blob/master/users.yaml + */ + target: string; + /** + * opt-attr: 'rules' - accepts an array of objects with below attributes + */ + rules?: Array<{ + /** + * attr: 'allow' - accepts an array of string. + * e.g. [Component, API, Group, User, Template, Location] + */ + allow: Array; + /** + * opt-attr: 'locations' - accepts an array of key, value pair objects. + * keys: 'target', 'type' + * e.g.[{type: url, target: https://github.com}] + */ + locations?: Array<{ [key: string]: string }>; + }>; + }>; }; } From 8e12093fe80c87b35a108dcd86559d122aab97d8 Mon Sep 17 00:00:00 2001 From: keshan Date: Thu, 17 Dec 2020 13:13:34 +0530 Subject: [PATCH 59/98] removed unused import to avoid CI failure --- plugins/catalog-backend/config.d.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/catalog-backend/config.d.ts b/plugins/catalog-backend/config.d.ts index 581d00a006..09ec4222b4 100644 --- a/plugins/catalog-backend/config.d.ts +++ b/plugins/catalog-backend/config.d.ts @@ -15,7 +15,6 @@ */ import { JsonValue } from '@backstage/config'; -import { StringLocale } from 'yup'; export interface Config { /** Configuration options for the catalog plugin */ From 01c38fe1547db776fbaab635000f6f15dc218073 Mon Sep 17 00:00:00 2001 From: Lee Mills Date: Thu, 17 Dec 2020 08:53:56 +0100 Subject: [PATCH 60/98] Updating the owners file to add new friends of backstage --- OWNERS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OWNERS.md b/OWNERS.md index 8e5002fc0a..f1649c50b8 100644 --- a/OWNERS.md +++ b/OWNERS.md @@ -22,3 +22,6 @@ People that have made significant contributions to the project and earned write - Andrew Thauer - Wealthsimple (GitHub: [andrewthauer](https://github.com/andrewthauer)) - Oliver Sand - SDA SE (GitHub: [Fox32](https://github.com/Fox32)) +- David Tuite - Roadie (GitHub: [dtuite](https://github.com/dtuite)) +- Adam Harvey - DXC Technology (GitHub: [adamdmharvey](https://github.com/adamdmharvey)) +- Dominik Henneke - SDA SE (GitHub: [dhenneke](https://github.com/dhenneke)) From 2e30e6f920dd110d01c2627f5196d6856599070f Mon Sep 17 00:00:00 2001 From: Lee Mills Date: Thu, 17 Dec 2020 08:59:31 +0100 Subject: [PATCH 61/98] Update vocab.txt Updating vocab.txt --- .github/styles/vocab.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index 595d79aa9a..b4be37c057 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -1,4 +1,5 @@ abc +adamdmharvey andrewthauer Apdex api @@ -49,6 +50,7 @@ deadnaming destructured dev devs +dhenneke discoverability Discoverability dls @@ -57,6 +59,8 @@ Dockerfile Dockerize dockerode Docusaurus +Dominik +dtuite dzolotusky eg Ek @@ -80,6 +84,7 @@ graphviz Gustavsson Hackathons haproxy +Henneke heroku Heroku horizontalpodautoscalers @@ -225,6 +230,7 @@ tooltips touchpoints transpiled transpilation +Tuite ui untracked upvote From ebdb772fa78cee9bf4a11cf112f2c53a03ee2666 Mon Sep 17 00:00:00 2001 From: Lee Mills Date: Thu, 17 Dec 2020 09:02:24 +0100 Subject: [PATCH 62/98] Update ADOPTERS.md Updating adopters file Spotify contact --- ADOPTERS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ADOPTERS.md b/ADOPTERS.md index 304512ee7e..419bf1de36 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -1,6 +1,6 @@ | Organization | Contact | Description of Use | | -------------------------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | -| [Spotify](https://www.spotify.com) | [@stefanalund](https://github.com/stefanalund) | Main interface towards all of Spotify's infrastructure and technical documentation. | +| [Spotify](https://www.spotify.com) | [@leemills83](https://github.com/leemills83) | Main interface towards all of Spotify's infrastructure and technical documentation. | | [bol.com](https://www.bol.com) | [@RoyJacobs](https://github.com/RoyJacobs) | Initial work being done to unify platform tooling. | | [DFDS](https://www.dfds.com) | [@carlsendk](https://github.com/carlsendk) | V2 self-service platform. | | [Roadie](https://roadie.io) | [@dtuite](https://github.com/dtuite) | Hosted, managed Backstage with easy set-up | From 25bbdccba62930450bfc913dca6b55c9ea30de54 Mon Sep 17 00:00:00 2001 From: keshan Date: Thu, 17 Dec 2020 13:33:28 +0530 Subject: [PATCH 63/98] updates on the comments section --- plugins/catalog-backend/config.d.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/plugins/catalog-backend/config.d.ts b/plugins/catalog-backend/config.d.ts index 09ec4222b4..54427eae36 100644 --- a/plugins/catalog-backend/config.d.ts +++ b/plugins/catalog-backend/config.d.ts @@ -21,13 +21,18 @@ export interface Config { catalog?: { /** * Rules to apply to catalog entities - accepts an array of objects with below attributes - * attr: 'allow' - accepts an array of string. e.g. [Component, API, Group, User, Template, Location] - * opt-attr: 'locations' - accepts an array of key, value pair objects. - * keys: 'target', 'type' - * e.g.[{type: url, target: https://github.com}] */ rules?: Array<{ + /** + * attr: 'allow' - accepts an array of string. e.g. [Component, API, Group, User, Template, Location] + */ allow: Array; + /** + * opt-attr: 'locations' - accepts an array of key, value pair objects. + * keys: 'target', 'type' + * e.g.[{type: url, target: https://github.com}] + * + */ locations?: Array<{ [key: string]: string }>; }>; /** From 02b097f6ff6023ad7492b7cee62a96c8bef8f983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 17 Dec 2020 09:07:12 +0100 Subject: [PATCH 64/98] Update ADOPTERS.md --- ADOPTERS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ADOPTERS.md b/ADOPTERS.md index 419bf1de36..3d5914d97b 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -1,6 +1,6 @@ | Organization | Contact | Description of Use | | -------------------------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | -| [Spotify](https://www.spotify.com) | [@leemills83](https://github.com/leemills83) | Main interface towards all of Spotify's infrastructure and technical documentation. | +| [Spotify](https://www.spotify.com) | [@leemills83](https://github.com/leemills83) | Main interface towards all of Spotify's infrastructure and technical documentation. | | [bol.com](https://www.bol.com) | [@RoyJacobs](https://github.com/RoyJacobs) | Initial work being done to unify platform tooling. | | [DFDS](https://www.dfds.com) | [@carlsendk](https://github.com/carlsendk) | V2 self-service platform. | | [Roadie](https://roadie.io) | [@dtuite](https://github.com/dtuite) | Hosted, managed Backstage with easy set-up | From 0fc432f202fb654211e8781197a245b1a205f0ed Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 17 Dec 2020 10:31:05 +0100 Subject: [PATCH 65/98] chore: removing the images for now to get the verify link script to pass --- .changeset/groups_profile.png | Bin 683337 -> 0 bytes scripts/verify-links.js | 1 + 2 files changed, 1 insertion(+) delete mode 100644 .changeset/groups_profile.png diff --git a/.changeset/groups_profile.png b/.changeset/groups_profile.png deleted file mode 100644 index 417faaa4af7316082453babad3cc21401afc8b48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 683337 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%0DuKc3b{v6Uwu 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

3C(FHNUAi&a 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¥BrW3N%hZkVTmM8vj2aUZsPOb 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%0Dc4 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 diff --git a/scripts/verify-links.js b/scripts/verify-links.js index 75e7a8c1d0..917571b937 100755 --- a/scripts/verify-links.js +++ b/scripts/verify-links.js @@ -149,6 +149,7 @@ async function main() { badUrls.push(...badFileUrls); } + console.warn(docPages); if (badUrls.length) { console.log(`Found ${badUrls.length} bad links within repo`); for (const { url, basePath, problem } of badUrls) { From 86e53c6deef3db9db506756a65068266d636f869 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 17 Dec 2020 10:37:27 +0100 Subject: [PATCH 66/98] chore: actually remove the image and changeset entry --- .changeset/tender-coats-unite.md | 2 -- scripts/verify-links.js | 1 - 2 files changed, 3 deletions(-) diff --git a/.changeset/tender-coats-unite.md b/.changeset/tender-coats-unite.md index 018660bcfa..4b87720f2f 100644 --- a/.changeset/tender-coats-unite.md +++ b/.changeset/tender-coats-unite.md @@ -5,7 +5,5 @@ Display the new `profile` fields (`displayName`, `email`, and `picture`) for groups on the `GroupProfileCard`. -![Groups Profile Section](./groups_profile.png) - This also resolves some cases where `profile` fields are missing for users or groups and for example falls back to displaying the entity name. Adds additional test data to the ACME Corp dataset. diff --git a/scripts/verify-links.js b/scripts/verify-links.js index 917571b937..75e7a8c1d0 100755 --- a/scripts/verify-links.js +++ b/scripts/verify-links.js @@ -149,7 +149,6 @@ async function main() { badUrls.push(...badFileUrls); } - console.warn(docPages); if (badUrls.length) { console.log(`Found ${badUrls.length} bad links within repo`); for (const { url, basePath, problem } of badUrls) { From 34eecc8b41bda507a6f1fb15c812e3563e730e9d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 17 Dec 2020 10:53:31 +0100 Subject: [PATCH 67/98] core-api: unique storage of saml sessions as well --- .changeset/sour-badgers-cry.md | 2 +- .../core-api/src/apis/implementations/auth/saml/SamlAuth.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/sour-badgers-cry.md b/.changeset/sour-badgers-cry.md index cd5aaf7afb..901294bf03 100644 --- a/.changeset/sour-badgers-cry.md +++ b/.changeset/sour-badgers-cry.md @@ -2,4 +2,4 @@ '@backstage/core-api': patch --- -GitHub Auth Api uses provider.id to build storage key name. +Use auth provider ID to create unique session storage keys for GitHub and SAML Auth. diff --git a/packages/core-api/src/apis/implementations/auth/saml/SamlAuth.ts b/packages/core-api/src/apis/implementations/auth/saml/SamlAuth.ts index da5f082c9b..e05f6266d6 100644 --- a/packages/core-api/src/apis/implementations/auth/saml/SamlAuth.ts +++ b/packages/core-api/src/apis/implementations/auth/saml/SamlAuth.ts @@ -63,7 +63,7 @@ class SamlAuth implements ProfileInfoApi, BackstageIdentityApi, SessionApi { const authSessionStore = new AuthSessionStore({ manager: sessionManager, - storageKey: 'samlSession', + storageKey: `${provider.id}Session`, }); return new SamlAuth(authSessionStore); From e56022c3bdffb92b8135e012feb14d14c0079dcc Mon Sep 17 00:00:00 2001 From: AdnCodez Date: Thu, 17 Dec 2020 11:14:15 +0100 Subject: [PATCH 68/98] fix(microsite): make the anchor link icon show up --- microsite/static/css/custom.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/microsite/static/css/custom.css b/microsite/static/css/custom.css index c07285ed8c..8805625286 100644 --- a/microsite/static/css/custom.css +++ b/microsite/static/css/custom.css @@ -48,6 +48,14 @@ h6 { color: $textColor; } +h2:hover .hash-link { + opacity: 1 +} + +.hash-link { + fill: white; +} + /* body elements */ p, ul, From 6e9f4d4a157459edd868e3577425287d519731a4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 17 Dec 2020 10:16:33 +0000 Subject: [PATCH 69/98] Version Packages --- .changeset/calm-scissors-jam.md | 5 -- .changeset/chilly-pumpkins-retire.md | 5 -- .changeset/cost-insights-tasty-years-laugh.md | 5 -- .changeset/curvy-dodos-fry.md | 5 -- .changeset/dirty-melons-retire.md | 6 -- .changeset/dirty-wolves-wink.md | 7 --- .changeset/early-dots-drive.md | 6 -- .changeset/friendly-carpets-repeat.md | 45 -------------- .changeset/friendly-olives-breathe.md | 5 -- .changeset/good-news-return.md | 5 -- .changeset/gorgeous-scissors-jog.md | 6 -- .changeset/grumpy-elephants-press.md | 6 -- .changeset/heavy-ducks-raise.md | 5 -- .changeset/loud-icons-itch.md | 5 -- .changeset/nice-trains-punch.md | 5 -- .changeset/odd-mugs-build.md | 6 -- .changeset/pink-ravens-destroy.md | 6 -- .changeset/purple-cycles-switch.md | 26 --------- .changeset/rare-peas-accept.md | 5 -- .changeset/rotten-pandas-draw.md | 5 -- .changeset/shiny-grapes-tan.md | 5 -- .changeset/six-mugs-camp.md | 20 ------- .changeset/sour-badgers-cry.md | 5 -- .changeset/swift-sheep-ring.md | 5 -- .changeset/tender-coats-unite.md | 9 --- .changeset/thirty-fans-hammer.md | 7 --- .changeset/weak-sloths-prove.md | 5 -- .changeset/wet-garlics-shave.md | 5 -- .changeset/witty-scissors-divide.md | 7 --- packages/app/CHANGELOG.md | 39 +++++++++++++ packages/app/package.json | 44 +++++++------- packages/backend-common/CHANGELOG.md | 11 ++++ packages/backend-common/package.json | 6 +- packages/backend/CHANGELOG.md | 30 ++++++++++ packages/backend/package.json | 20 +++---- packages/catalog-client/CHANGELOG.md | 9 +++ packages/catalog-client/package.json | 6 +- packages/catalog-model/CHANGELOG.md | 13 +++++ packages/catalog-model/package.json | 4 +- packages/cli/CHANGELOG.md | 6 ++ packages/cli/package.json | 6 +- packages/core-api/CHANGELOG.md | 6 ++ packages/core-api/package.json | 4 +- packages/core/CHANGELOG.md | 8 +++ packages/core/package.json | 6 +- packages/create-app/CHANGELOG.md | 21 +++++++ packages/create-app/package.json | 34 +++++------ packages/integration/CHANGELOG.md | 8 +++ packages/integration/package.json | 4 +- packages/techdocs-common/CHANGELOG.md | 55 ++++++++++++++++++ packages/techdocs-common/package.json | 8 +-- plugins/api-docs/CHANGELOG.md | 12 ++++ plugins/api-docs/package.json | 10 ++-- plugins/auth-backend/CHANGELOG.md | 14 +++++ plugins/auth-backend/package.json | 10 ++-- plugins/catalog-backend/CHANGELOG.md | 53 +++++++++++++++++ plugins/catalog-backend/package.json | 8 +-- plugins/catalog-graphql/CHANGELOG.md | 12 ++++ plugins/catalog-graphql/package.json | 8 +-- plugins/catalog-import/CHANGELOG.md | 27 +++++++++ plugins/catalog-import/package.json | 14 ++--- plugins/catalog/CHANGELOG.md | 15 +++++ plugins/catalog/package.json | 14 ++--- plugins/circleci/CHANGELOG.md | 12 ++++ plugins/circleci/package.json | 10 ++-- plugins/cloudbuild/CHANGELOG.md | 12 ++++ plugins/cloudbuild/package.json | 10 ++-- plugins/cost-insights/CHANGELOG.md | 8 +++ plugins/cost-insights/package.json | 6 +- plugins/github-actions/CHANGELOG.md | 14 +++++ plugins/github-actions/package.json | 12 ++-- plugins/jenkins/CHANGELOG.md | 12 ++++ plugins/jenkins/package.json | 10 ++-- plugins/kubernetes-backend/CHANGELOG.md | 12 ++++ plugins/kubernetes-backend/package.json | 8 +-- plugins/kubernetes/CHANGELOG.md | 12 ++++ plugins/kubernetes/package.json | 10 ++-- plugins/lighthouse/CHANGELOG.md | 14 +++++ plugins/lighthouse/package.json | 12 ++-- plugins/org/CHANGELOG.md | 22 +++++++ plugins/org/package.json | 10 ++-- plugins/pagerduty/CHANGELOG.md | 12 ++++ plugins/pagerduty/package.json | 8 +-- plugins/register-component/CHANGELOG.md | 12 ++++ plugins/register-component/package.json | 10 ++-- plugins/rollbar/CHANGELOG.md | 12 ++++ plugins/rollbar/package.json | 10 ++-- plugins/scaffolder-backend/CHANGELOG.md | 13 +++++ plugins/scaffolder-backend/package.json | 8 +-- plugins/scaffolder/CHANGELOG.md | 12 ++++ plugins/scaffolder/package.json | 10 ++-- plugins/search/CHANGELOG.md | 12 ++++ plugins/search/package.json | 10 ++-- plugins/sentry/CHANGELOG.md | 12 ++++ plugins/sentry/package.json | 8 +-- plugins/sonarqube/CHANGELOG.md | 11 ++++ plugins/sonarqube/package.json | 8 +-- plugins/techdocs-backend/CHANGELOG.md | 56 ++++++++++++++++++ plugins/techdocs-backend/package.json | 10 ++-- plugins/techdocs/CHANGELOG.md | 58 +++++++++++++++++++ plugins/techdocs/package.json | 14 ++--- 101 files changed, 862 insertions(+), 432 deletions(-) delete mode 100644 .changeset/calm-scissors-jam.md delete mode 100644 .changeset/chilly-pumpkins-retire.md delete mode 100644 .changeset/cost-insights-tasty-years-laugh.md delete mode 100644 .changeset/curvy-dodos-fry.md delete mode 100644 .changeset/dirty-melons-retire.md delete mode 100644 .changeset/dirty-wolves-wink.md delete mode 100644 .changeset/early-dots-drive.md delete mode 100644 .changeset/friendly-carpets-repeat.md delete mode 100644 .changeset/friendly-olives-breathe.md delete mode 100644 .changeset/good-news-return.md delete mode 100644 .changeset/gorgeous-scissors-jog.md delete mode 100644 .changeset/grumpy-elephants-press.md delete mode 100644 .changeset/heavy-ducks-raise.md delete mode 100644 .changeset/loud-icons-itch.md delete mode 100644 .changeset/nice-trains-punch.md delete mode 100644 .changeset/odd-mugs-build.md delete mode 100644 .changeset/pink-ravens-destroy.md delete mode 100644 .changeset/purple-cycles-switch.md delete mode 100644 .changeset/rare-peas-accept.md delete mode 100644 .changeset/rotten-pandas-draw.md delete mode 100644 .changeset/shiny-grapes-tan.md delete mode 100644 .changeset/six-mugs-camp.md delete mode 100644 .changeset/sour-badgers-cry.md delete mode 100644 .changeset/swift-sheep-ring.md delete mode 100644 .changeset/tender-coats-unite.md delete mode 100644 .changeset/thirty-fans-hammer.md delete mode 100644 .changeset/weak-sloths-prove.md delete mode 100644 .changeset/wet-garlics-shave.md delete mode 100644 .changeset/witty-scissors-divide.md create mode 100644 packages/techdocs-common/CHANGELOG.md diff --git a/.changeset/calm-scissors-jam.md b/.changeset/calm-scissors-jam.md deleted file mode 100644 index c815670fd0..0000000000 --- a/.changeset/calm-scissors-jam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Add support for Github Enterprise in GitHubOrgReaderProcessor so you can properly ingest users of a GHE organization. diff --git a/.changeset/chilly-pumpkins-retire.md b/.changeset/chilly-pumpkins-retire.md deleted file mode 100644 index b206cb6fe7..0000000000 --- a/.changeset/chilly-pumpkins-retire.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-org': patch ---- - -Wrap entity cards on smaller screens diff --git a/.changeset/cost-insights-tasty-years-laugh.md b/.changeset/cost-insights-tasty-years-laugh.md deleted file mode 100644 index 3728514fb1..0000000000 --- a/.changeset/cost-insights-tasty-years-laugh.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-cost-insights': patch ---- - -pin all projects selection to the top of menu list diff --git a/.changeset/curvy-dodos-fry.md b/.changeset/curvy-dodos-fry.md deleted file mode 100644 index 80ab333e38..0000000000 --- a/.changeset/curvy-dodos-fry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Break the refresh loop into several smaller transactions diff --git a/.changeset/dirty-melons-retire.md b/.changeset/dirty-melons-retire.md deleted file mode 100644 index 2b92b44678..0000000000 --- a/.changeset/dirty-melons-retire.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/catalog-model': patch ---- - -Introduce a `profile` section for group entities that can optional include a -`displayName`, `email` and `picture`. diff --git a/.changeset/dirty-wolves-wink.md b/.changeset/dirty-wolves-wink.md deleted file mode 100644 index 77f1a62aff..0000000000 --- a/.changeset/dirty-wolves-wink.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Support `profile` of groups including `displayName`, `email`, and `picture` in -`LdapOrgReaderProcessor`. The source fields for them can be configured in the -`ldapOrg` provider. diff --git a/.changeset/early-dots-drive.md b/.changeset/early-dots-drive.md deleted file mode 100644 index 7a5eedec78..0000000000 --- a/.changeset/early-dots-drive.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-org': patch ---- - -Ensure a name is always displayed for user entities in the org plugin. This can happen when there is no profile -displayName provided (e.g. a GitHub user that has not added a name to their profile) diff --git a/.changeset/friendly-carpets-repeat.md b/.changeset/friendly-carpets-repeat.md deleted file mode 100644 index 7fb0d2f6eb..0000000000 --- a/.changeset/friendly-carpets-repeat.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -'@backstage/techdocs-common': minor -'@backstage/plugin-techdocs': minor -'@backstage/plugin-techdocs-backend': minor ---- - -_Breaking changes_ - -1. Added option to use Google Cloud Storage as a choice to store the static generated files for TechDocs. - It can be configured using `techdocs.publisher.type` option in `app-config.yaml`. - Step-by-step guide to configure GCS is available here https://backstage.io/docs/features/techdocs/using-cloud-storage - Set `techdocs.publisher.type` to `'local'` if you want to continue using local filesystem to store TechDocs files. - -2. `techdocs.builder` is now required and can be set to `'local'` or `'external'`. (Set it to `'local'` for now, since CI/CD build - workflow for TechDocs will be available soon (in few weeks)). - If builder is set to 'local' and you open a TechDocs page, `techdocs-backend` will try to generate the docs, publish to storage and - show the generated docs afterwords. - If builder is set to `'external'`, `techdocs-backend` will only fetch the docs and will NOT try to generate and publish. In this case of `'external'`, - we assume that docs are being built in the CI/CD pipeline of the repository. - TechDocs will not assume a default value for `techdocs.builder`. It is better to explicitly define it in the `app-config.yaml`. - -3. When configuring TechDocs in your backend, there is a difference in how a new publisher is created. - -``` ---- const publisher = new LocalPublish(logger, discovery); -+++ const publisher = Publisher.fromConfig(config, logger, discovery); -``` - -Based on the config `techdocs.publisher.type`, the publisher could be either Local publisher or Google Cloud Storage publisher. - -4. `techdocs.storageUrl` is now a required config. Should be `http://localhost:7000/api/techdocs/static/docs` in most setups. - -5. Parts of `@backstage/plugin-techdocs-backend` have been moved to a new package `@backstage/techdocs-common` to generate docs. Also to publish docs - to-and-fro between TechDocs and a storage (either local or external). However, a Backstage app does NOT need to import the `techdocs-common` package - - app should only import `@backstage/plugin-techdocs` and `@backstage/plugin-techdocs-backend`. - -_Patch changes_ - -1. See all of TechDocs config options and its documentation https://backstage.io/docs/features/techdocs/configuration - -2. Logic about serving static files and metadata retrieval have been abstracted away from the router in `techdocs-backend` to the instance of publisher. - -3. Removed Material UI Spinner from TechDocs header. Spinners cause unnecessary UX distraction. - Case 1 (when docs are built and are to be served): Spinners appear for a split second before the name of site shows up. This unnecessarily distracts eyes because spinners increase the size of the Header. A dot (.) would do fine. Definitely more can be done. - Case 2 (when docs are being generated): There is already a linear progress bar (which is recommended in Storybook). diff --git a/.changeset/friendly-olives-breathe.md b/.changeset/friendly-olives-breathe.md deleted file mode 100644 index 9dce3b9709..0000000000 --- a/.changeset/friendly-olives-breathe.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-backend': patch ---- - -Added configuration schema for the commonly used properties diff --git a/.changeset/good-news-return.md b/.changeset/good-news-return.md deleted file mode 100644 index 6cb02e6e82..0000000000 --- a/.changeset/good-news-return.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Break out GithubOrgReaderProcessor config into its own file for consistency with the other org processors. diff --git a/.changeset/gorgeous-scissors-jog.md b/.changeset/gorgeous-scissors-jog.md deleted file mode 100644 index 3f192808c1..0000000000 --- a/.changeset/gorgeous-scissors-jog.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/core': patch -'@backstage/plugin-org': patch ---- - -Add a `` component to `@backstage/core`. diff --git a/.changeset/grumpy-elephants-press.md b/.changeset/grumpy-elephants-press.md deleted file mode 100644 index d85d36e609..0000000000 --- a/.changeset/grumpy-elephants-press.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/backend-common': patch -'@backstage/integration': patch ---- - -Implement readTree on BitBucketUrlReader and getBitbucketDownloadUrl diff --git a/.changeset/heavy-ducks-raise.md b/.changeset/heavy-ducks-raise.md deleted file mode 100644 index 71a16da512..0000000000 --- a/.changeset/heavy-ducks-raise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/catalog-model': patch ---- - -Ignore relations when comparing entities. This stops the refresh loop from rewriting entities over and over. diff --git a/.changeset/loud-icons-itch.md b/.changeset/loud-icons-itch.md deleted file mode 100644 index c5741c5d0b..0000000000 --- a/.changeset/loud-icons-itch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-import': patch ---- - -Add description to Pull Request when registering a new component diff --git a/.changeset/nice-trains-punch.md b/.changeset/nice-trains-punch.md deleted file mode 100644 index 71225ac97c..0000000000 --- a/.changeset/nice-trains-punch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-pagerduty': patch ---- - -Supporting Timezones diff --git a/.changeset/odd-mugs-build.md b/.changeset/odd-mugs-build.md deleted file mode 100644 index bf95d23410..0000000000 --- a/.changeset/odd-mugs-build.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Support `profile` of groups including `displayName` and `picture` in -`GithubOrgReaderProcessor`. Fixes the import of `description` for groups. diff --git a/.changeset/pink-ravens-destroy.md b/.changeset/pink-ravens-destroy.md deleted file mode 100644 index 647ccd9f37..0000000000 --- a/.changeset/pink-ravens-destroy.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/backend-common': patch -'@backstage/integration': patch ---- - -Introduce readTree method for GitLab URL Reader diff --git a/.changeset/purple-cycles-switch.md b/.changeset/purple-cycles-switch.md deleted file mode 100644 index c7594e4254..0000000000 --- a/.changeset/purple-cycles-switch.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -Write relations directly as part of batch add / update of entities. - -Slight change of the `CommonDatabase` contract: - -## `addEntity` removed - -This method was unused by the core, and rendered unnecessary when `addEntities` -exists. - -If you were a user of `addEntity`, please call `addEntities` instead, with an -array of one element. - -## `DbEntityRequest` has a new field `relations` - -This is the structure that is passed to `addEntities` and `updateEntity`. It -used to be the case that you needed to call `setRelations` separately, but now -this instead happens directly when you call `addEntities` or `updateEntity`. - -If you were using `addEntities` or `updateEntity` directly, please adapt your -code to add the `relations` array to each request. If you were calling -`setRelations` separately next to these methods, you no longer need to do so, -after adding the relations to the `DbEntityRequest`s. diff --git a/.changeset/rare-peas-accept.md b/.changeset/rare-peas-accept.md deleted file mode 100644 index 74597dda11..0000000000 --- a/.changeset/rare-peas-accept.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Batch the writing of statuses after refreshes. This reduced the runtime on sqlite from 16s to 0.2s, and on pg from 60s to 1s on my machine, for the huge LDAP set. diff --git a/.changeset/rotten-pandas-draw.md b/.changeset/rotten-pandas-draw.md deleted file mode 100644 index 85b3feeaec..0000000000 --- a/.changeset/rotten-pandas-draw.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Add index to foreign key columns. Postgres (and others) do not do this on the "source" side of a foreign key relation, which was what led to the slowness on large datasets. The full LDAP dataset ingestion now takes two minutes, which is not optimal yet but still a huge improvement over before when it basically never finished :) diff --git a/.changeset/shiny-grapes-tan.md b/.changeset/shiny-grapes-tan.md deleted file mode 100644 index b7361bb970..0000000000 --- a/.changeset/shiny-grapes-tan.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/integration': patch ---- - -Validate that integration config contains a valid host diff --git a/.changeset/six-mugs-camp.md b/.changeset/six-mugs-camp.md deleted file mode 100644 index 373edd340a..0000000000 --- a/.changeset/six-mugs-camp.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -In the techdocs-backend plugin (`packages/backend/src/plugins/techdocs.ts`), create a publisher using - -``` - const publisher = Publisher.fromConfig(config, logger, discovery); -``` - -instead of - -``` - const publisher = new LocalPublish(logger, discovery); -``` - -An instance of `publisher` can either be a local filesystem publisher or a Google Cloud Storage publisher. - -Read more about the configs here https://backstage.io/docs/features/techdocs/configuration -(You will also have to update `techdocs.storage.type` to `local` or `googleGcs`. And `techdocs.builder` to either `local` or `external`.) diff --git a/.changeset/sour-badgers-cry.md b/.changeset/sour-badgers-cry.md deleted file mode 100644 index 901294bf03..0000000000 --- a/.changeset/sour-badgers-cry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-api': patch ---- - -Use auth provider ID to create unique session storage keys for GitHub and SAML Auth. diff --git a/.changeset/swift-sheep-ring.md b/.changeset/swift-sheep-ring.md deleted file mode 100644 index f4cf92c29d..0000000000 --- a/.changeset/swift-sheep-ring.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Re-enable symlink resolution during bundling, and switch to using a resolve plugin for external linked packages. diff --git a/.changeset/tender-coats-unite.md b/.changeset/tender-coats-unite.md deleted file mode 100644 index 4b87720f2f..0000000000 --- a/.changeset/tender-coats-unite.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/plugin-org': patch ---- - -Display the new `profile` fields (`displayName`, `email`, and `picture`) for -groups on the `GroupProfileCard`. - -This also resolves some cases where `profile` fields are missing for users or -groups and for example falls back to displaying the entity name. Adds additional test data to the ACME Corp dataset. diff --git a/.changeset/thirty-fans-hammer.md b/.changeset/thirty-fans-hammer.md deleted file mode 100644 index 45fb398f8c..0000000000 --- a/.changeset/thirty-fans-hammer.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/catalog-model': minor -'@backstage/plugin-catalog-backend': minor ---- - -Remove `implementsApis` from `Component` entities. Deprecation happened in [#3449](https://github.com/backstage/backstage/pull/3449). -Use `providesApis` instead. diff --git a/.changeset/weak-sloths-prove.md b/.changeset/weak-sloths-prove.md deleted file mode 100644 index bfecb385c8..0000000000 --- a/.changeset/weak-sloths-prove.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Added configuration schema for the commonly used properties diff --git a/.changeset/wet-garlics-shave.md b/.changeset/wet-garlics-shave.md deleted file mode 100644 index 86b42541eb..0000000000 --- a/.changeset/wet-garlics-shave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-sentry': patch ---- - -Added configuration schema for the commonly used properties diff --git a/.changeset/witty-scissors-divide.md b/.changeset/witty-scissors-divide.md deleted file mode 100644 index f288088ef2..0000000000 --- a/.changeset/witty-scissors-divide.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Support `profile` of groups including `displayName` and `email` in -`MicrosoftGraphOrgReaderProcessor`. Importing `picture` doesn't work yet, as -the Microsoft Graph API does not expose them correctly. diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 03958c831c..799895ef56 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,44 @@ # example-app +## 0.2.7 + +### Patch Changes + +- Updated dependencies [c0fac6163] +- Updated dependencies [48c305e69] +- Updated dependencies [c911061b7] +- Updated dependencies [ab805860a] +- Updated dependencies [dae4f3983] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [f3e75508d] +- Updated dependencies [3b50f833d] +- Updated dependencies [c36a01b4c] +- Updated dependencies [c5297baeb] +- Updated dependencies [ac3560b42] +- Updated dependencies [962d1ad66] + - @backstage/plugin-org@0.3.2 + - @backstage/plugin-cost-insights@0.5.2 + - @backstage/catalog-model@0.6.0 + - @backstage/plugin-techdocs@0.5.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog-import@0.3.2 + - @backstage/plugin-pagerduty@0.2.3 + - @backstage/cli@0.4.2 + - @backstage/plugin-sentry@0.3.1 + - @backstage/plugin-api-docs@0.4.1 + - @backstage/plugin-catalog@0.2.7 + - @backstage/plugin-circleci@0.2.5 + - @backstage/plugin-cloudbuild@0.2.5 + - @backstage/plugin-github-actions@0.2.5 + - @backstage/plugin-jenkins@0.3.4 + - @backstage/plugin-kubernetes@0.3.3 + - @backstage/plugin-lighthouse@0.2.6 + - @backstage/plugin-register-component@0.2.5 + - @backstage/plugin-rollbar@0.2.7 + - @backstage/plugin-scaffolder@0.3.4 + - @backstage/plugin-search@0.2.4 + ## 0.2.6 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 9d05ae659a..63710a5c28 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,36 +1,36 @@ { "name": "example-app", - "version": "0.2.6", + "version": "0.2.7", "private": true, "bundled": true, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/cli": "^0.4.1", - "@backstage/core": "^0.4.0", - "@backstage/plugin-api-docs": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", - "@backstage/plugin-catalog-import": "^0.3.1", - "@backstage/plugin-circleci": "^0.2.4", - "@backstage/plugin-cloudbuild": "^0.2.4", - "@backstage/plugin-cost-insights": "^0.5.0", + "@backstage/catalog-model": "^0.6.0", + "@backstage/cli": "^0.4.2", + "@backstage/core": "^0.4.1", + "@backstage/plugin-api-docs": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", + "@backstage/plugin-catalog-import": "^0.3.2", + "@backstage/plugin-circleci": "^0.2.5", + "@backstage/plugin-cloudbuild": "^0.2.5", + "@backstage/plugin-cost-insights": "^0.5.2", "@backstage/plugin-explore": "^0.2.2", "@backstage/plugin-gcp-projects": "^0.2.2", - "@backstage/plugin-github-actions": "^0.2.4", + "@backstage/plugin-github-actions": "^0.2.5", "@backstage/plugin-gitops-profiles": "^0.2.2", "@backstage/plugin-graphiql": "^0.2.2", - "@backstage/plugin-org": "^0.3.1", - "@backstage/plugin-jenkins": "^0.3.3", - "@backstage/plugin-kubernetes": "^0.3.2", - "@backstage/plugin-lighthouse": "^0.2.5", + "@backstage/plugin-org": "^0.3.2", + "@backstage/plugin-jenkins": "^0.3.4", + "@backstage/plugin-kubernetes": "^0.3.3", + "@backstage/plugin-lighthouse": "^0.2.6", "@backstage/plugin-newrelic": "^0.2.2", - "@backstage/plugin-pagerduty": "0.2.2", - "@backstage/plugin-register-component": "^0.2.4", - "@backstage/plugin-rollbar": "^0.2.6", - "@backstage/plugin-scaffolder": "^0.3.3", - "@backstage/plugin-sentry": "^0.3.0", - "@backstage/plugin-search": "^0.2.3", + "@backstage/plugin-pagerduty": "0.2.3", + "@backstage/plugin-register-component": "^0.2.5", + "@backstage/plugin-rollbar": "^0.2.7", + "@backstage/plugin-scaffolder": "^0.3.4", + "@backstage/plugin-sentry": "^0.3.1", + "@backstage/plugin-search": "^0.2.4", "@backstage/plugin-tech-radar": "^0.3.1", - "@backstage/plugin-techdocs": "^0.4.0", + "@backstage/plugin-techdocs": "^0.5.0", "@backstage/plugin-user-settings": "^0.2.3", "@backstage/plugin-welcome": "^0.2.3", "@backstage/test-utils": "^0.1.5", diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index 702b1dcbf2..0e0a3074a4 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/backend-common +## 0.4.1 + +### Patch Changes + +- 1d1c2860f: Implement readTree on BitBucketUrlReader and getBitbucketDownloadUrl +- 4eafdec4a: Introduce readTree method for GitLab URL Reader +- Updated dependencies [1d1c2860f] +- Updated dependencies [4eafdec4a] +- Updated dependencies [178e09323] + - @backstage/integration@0.1.4 + ## 0.4.0 ### Minor Changes diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 395183104d..e65edba0a5 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-common", "description": "Common functionality library for Backstage backends", - "version": "0.4.0", + "version": "0.4.1", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -32,7 +32,7 @@ "@backstage/cli-common": "^0.1.1", "@backstage/config": "^0.1.2", "@backstage/config-loader": "^0.4.0", - "@backstage/integration": "^0.1.3", + "@backstage/integration": "^0.1.4", "@types/cors": "^2.8.6", "@types/express": "^4.17.6", "archiver": "^5.0.2", @@ -65,7 +65,7 @@ } }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/test-utils": "^0.1.5", "@types/archiver": "^3.1.1", "@types/compression": "^1.7.0", diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index d0a8f4112a..3f053accfa 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,35 @@ # example-backend +## 0.2.7 + +### Patch Changes + +- Updated dependencies [c6eeefa35] +- Updated dependencies [fb386b760] +- Updated dependencies [c911061b7] +- Updated dependencies [7c3ffc0cd] +- Updated dependencies [dae4f3983] +- Updated dependencies [7b15cc271] +- Updated dependencies [e7496dc3e] +- Updated dependencies [1d1c2860f] +- Updated dependencies [0e6298f7e] +- Updated dependencies [8dd0a906d] +- Updated dependencies [4eafdec4a] +- Updated dependencies [6b37c95bf] +- Updated dependencies [8c31c681c] +- Updated dependencies [7b98e7fee] +- Updated dependencies [ac3560b42] +- Updated dependencies [94c65a9d4] +- Updated dependencies [0097057ed] + - @backstage/plugin-catalog-backend@0.5.0 + - @backstage/catalog-model@0.6.0 + - @backstage/plugin-techdocs-backend@0.4.0 + - @backstage/plugin-auth-backend@0.2.7 + - @backstage/backend-common@0.4.1 + - @backstage/plugin-scaffolder-backend@0.3.5 + - example-app@0.2.7 + - @backstage/plugin-kubernetes-backend@0.2.3 + ## 0.2.6 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index 74b459d691..718b008c7b 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.6", + "version": "0.2.7", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", @@ -27,23 +27,23 @@ "migrate:create": "knex migrate:make -x ts" }, "dependencies": { - "@backstage/backend-common": "^0.4.0", - "@backstage/catalog-model": "^0.5.0", + "@backstage/backend-common": "^0.4.1", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", "@backstage/plugin-app-backend": "^0.3.3", - "@backstage/plugin-auth-backend": "^0.2.6", - "@backstage/plugin-catalog-backend": "^0.4.0", + "@backstage/plugin-auth-backend": "^0.2.7", + "@backstage/plugin-catalog-backend": "^0.5.0", "@backstage/plugin-graphql-backend": "^0.1.4", - "@backstage/plugin-kubernetes-backend": "^0.2.2", + "@backstage/plugin-kubernetes-backend": "^0.2.3", "@backstage/plugin-proxy-backend": "^0.2.3", "@backstage/plugin-rollbar-backend": "^0.1.5", - "@backstage/plugin-scaffolder-backend": "^0.3.4", - "@backstage/plugin-techdocs-backend": "^0.3.2", + "@backstage/plugin-scaffolder-backend": "^0.3.5", + "@backstage/plugin-techdocs-backend": "^0.4.0", "@gitbeaker/node": "^25.2.0", "@octokit/rest": "^18.0.0", "azure-devops-node-api": "^10.1.1", "dockerode": "^3.2.1", - "example-app": "^0.2.6", + "example-app": "^0.2.7", "express": "^4.17.1", "express-promise-router": "^3.0.3", "knex": "^0.21.6", @@ -53,7 +53,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@types/dockerode": "^3.2.1", "@types/express": "^4.17.6", "@types/express-serve-static-core": "^4.17.5", diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index e649db0f22..c99f72e376 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/catalog-client +## 0.3.4 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + ## 0.3.3 ### Patch Changes diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index 36500c7c23..c878119a35 100644 --- a/packages/catalog-client/package.json +++ b/packages/catalog-client/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/catalog-client", - "version": "0.3.3", + "version": "0.3.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,12 +29,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", "cross-fetch": "^3.0.6" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@types/jest": "^26.0.7", "msw": "^0.21.2" }, diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md index 7316836a71..f6c2477d6c 100644 --- a/packages/catalog-model/CHANGELOG.md +++ b/packages/catalog-model/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/catalog-model +## 0.6.0 + +### Minor Changes + +- ac3560b42: Remove `implementsApis` from `Component` entities. Deprecation happened in [#3449](https://github.com/backstage/backstage/pull/3449). + Use `providesApis` instead. + +### Patch Changes + +- c911061b7: Introduce a `profile` section for group entities that can optional include a + `displayName`, `email` and `picture`. +- 0e6298f7e: Ignore relations when comparing entities. This stops the refresh loop from rewriting entities over and over. + ## 0.5.0 ### Minor Changes diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index ad0a2740f7..4fad95e122 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/catalog-model", - "version": "0.5.0", + "version": "0.6.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -38,7 +38,7 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@types/express": "^4.17.6", "@types/jest": "^26.0.7", "@types/lodash": "^4.14.151", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index ddf7a7ee76..8f73247301 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/cli +## 0.4.2 + +### Patch Changes + +- c36a01b4c: Re-enable symlink resolution during bundling, and switch to using a resolve plugin for external linked packages. + ## 0.4.1 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index a71e4c8b10..c284b81e2e 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli", "description": "CLI for developing Backstage plugins and apps", - "version": "0.4.1", + "version": "0.4.2", "private": false, "publishConfig": { "access": "public" @@ -111,9 +111,9 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-common": "^0.4.0", + "@backstage/backend-common": "^0.4.1", "@backstage/config": "^0.1.2", - "@backstage/core": "^0.4.0", + "@backstage/core": "^0.4.1", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@backstage/theme": "^0.2.2", diff --git a/packages/core-api/CHANGELOG.md b/packages/core-api/CHANGELOG.md index 79aa22f481..de997bf065 100644 --- a/packages/core-api/CHANGELOG.md +++ b/packages/core-api/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/core-api +## 0.2.6 + +### Patch Changes + +- 7dd2ef7d1: Use auth provider ID to create unique session storage keys for GitHub and SAML Auth. + ## 0.2.5 ### Patch Changes diff --git a/packages/core-api/package.json b/packages/core-api/package.json index 05acadffd5..fa8bd7a086 100644 --- a/packages/core-api/package.json +++ b/packages/core-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-api", "description": "Internal Core API used by Backstage plugins and apps", - "version": "0.2.5", + "version": "0.2.6", "private": false, "publishConfig": { "access": "public", @@ -43,7 +43,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/test-utils-core": "^0.1.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index aeb1c961b7..d4eb0a0a95 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/core +## 0.4.1 + +### Patch Changes + +- 8ef71ed32: Add a `` component to `@backstage/core`. +- Updated dependencies [7dd2ef7d1] + - @backstage/core-api@0.2.6 + ## 0.4.0 ### Minor Changes diff --git a/packages/core/package.json b/packages/core/package.json index 54d4b1a267..3c636a0d80 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core", "description": "Core API used by Backstage plugins and apps", - "version": "0.4.0", + "version": "0.4.1", "private": false, "publishConfig": { "access": "public", @@ -30,7 +30,7 @@ }, "dependencies": { "@backstage/config": "^0.1.2", - "@backstage/core-api": "^0.2.5", + "@backstage/core-api": "^0.2.6", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -65,7 +65,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index b8b630d2e4..8e9b3692af 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/create-app +## 0.2.5 + +### Patch Changes + +- 2783ec018: In the techdocs-backend plugin (`packages/backend/src/plugins/techdocs.ts`), create a publisher using + + ``` + const publisher = Publisher.fromConfig(config, logger, discovery); + ``` + + instead of + + ``` + const publisher = new LocalPublish(logger, discovery); + ``` + + An instance of `publisher` can either be a local filesystem publisher or a Google Cloud Storage publisher. + + Read more about the configs here https://backstage.io/docs/features/techdocs/configuration + (You will also have to update `techdocs.storage.type` to `local` or `googleGcs`. And `techdocs.builder` to either `local` or `external`.) + ## 0.2.4 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 5b7484b575..64f7e83ae4 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/create-app", "description": "Create app package for Backstage", - "version": "0.2.4", + "version": "0.2.5", "private": false, "publishConfig": { "access": "public" @@ -37,28 +37,28 @@ "recursive-readdir": "^2.2.2" }, "devDependencies": { - "@backstage/backend-common": "^0.4.0", - "@backstage/catalog-model": "^0.5.0", - "@backstage/cli": "^0.4.1", + "@backstage/backend-common": "^0.4.1", + "@backstage/catalog-model": "^0.6.0", + "@backstage/cli": "^0.4.2", "@backstage/config": "^0.1.2", - "@backstage/core": "^0.4.0", - "@backstage/plugin-api-docs": "^0.4.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-api-docs": "^0.4.1", "@backstage/plugin-app-backend": "^0.3.3", - "@backstage/plugin-auth-backend": "^0.2.6", - "@backstage/plugin-catalog": "^0.2.6", - "@backstage/plugin-catalog-backend": "^0.4.0", - "@backstage/plugin-circleci": "^0.2.4", + "@backstage/plugin-auth-backend": "^0.2.7", + "@backstage/plugin-catalog": "^0.2.7", + "@backstage/plugin-catalog-backend": "^0.5.0", + "@backstage/plugin-circleci": "^0.2.5", "@backstage/plugin-explore": "^0.2.2", - "@backstage/plugin-github-actions": "^0.2.4", - "@backstage/plugin-lighthouse": "^0.2.5", + "@backstage/plugin-github-actions": "^0.2.5", + "@backstage/plugin-lighthouse": "^0.2.6", "@backstage/plugin-proxy-backend": "^0.2.3", - "@backstage/plugin-register-component": "^0.2.4", + "@backstage/plugin-register-component": "^0.2.5", "@backstage/plugin-rollbar-backend": "^0.1.5", - "@backstage/plugin-scaffolder": "^0.3.3", - "@backstage/plugin-scaffolder-backend": "^0.3.4", + "@backstage/plugin-scaffolder": "^0.3.4", + "@backstage/plugin-scaffolder-backend": "^0.3.5", "@backstage/plugin-tech-radar": "^0.3.1", - "@backstage/plugin-techdocs": "^0.4.0", - "@backstage/plugin-techdocs-backend": "^0.3.2", + "@backstage/plugin-techdocs": "^0.5.0", + "@backstage/plugin-techdocs-backend": "^0.4.0", "@backstage/plugin-user-settings": "^0.2.3", "@backstage/test-utils": "^0.1.5", "@backstage/theme": "^0.2.2", diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md index f080685efe..5559c5230d 100644 --- a/packages/integration/CHANGELOG.md +++ b/packages/integration/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/integration +## 0.1.4 + +### Patch Changes + +- 1d1c2860f: Implement readTree on BitBucketUrlReader and getBitbucketDownloadUrl +- 4eafdec4a: Introduce readTree method for GitLab URL Reader +- 178e09323: Validate that integration config contains a valid host + ## 0.1.3 ### Patch Changes diff --git a/packages/integration/package.json b/packages/integration/package.json index 3c241fee89..fe5bd60905 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/integration", - "version": "0.1.3", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,7 +34,7 @@ "git-url-parse": "^11.4.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/test-utils": "^0.1.5", "@types/jest": "^26.0.7", "msw": "^0.21.2" diff --git a/packages/techdocs-common/CHANGELOG.md b/packages/techdocs-common/CHANGELOG.md new file mode 100644 index 0000000000..af3da478a5 --- /dev/null +++ b/packages/techdocs-common/CHANGELOG.md @@ -0,0 +1,55 @@ +# @backstage/techdocs-common + +## 0.2.0 + +### Minor Changes + +- dae4f3983: _Breaking changes_ + + 1. Added option to use Google Cloud Storage as a choice to store the static generated files for TechDocs. + It can be configured using `techdocs.publisher.type` option in `app-config.yaml`. + Step-by-step guide to configure GCS is available here https://backstage.io/docs/features/techdocs/using-cloud-storage + Set `techdocs.publisher.type` to `'local'` if you want to continue using local filesystem to store TechDocs files. + + 2. `techdocs.builder` is now required and can be set to `'local'` or `'external'`. (Set it to `'local'` for now, since CI/CD build + workflow for TechDocs will be available soon (in few weeks)). + If builder is set to 'local' and you open a TechDocs page, `techdocs-backend` will try to generate the docs, publish to storage and + show the generated docs afterwords. + If builder is set to `'external'`, `techdocs-backend` will only fetch the docs and will NOT try to generate and publish. In this case of `'external'`, + we assume that docs are being built in the CI/CD pipeline of the repository. + TechDocs will not assume a default value for `techdocs.builder`. It is better to explicitly define it in the `app-config.yaml`. + + 3. When configuring TechDocs in your backend, there is a difference in how a new publisher is created. + + ``` + --- const publisher = new LocalPublish(logger, discovery); + +++ const publisher = Publisher.fromConfig(config, logger, discovery); + ``` + + Based on the config `techdocs.publisher.type`, the publisher could be either Local publisher or Google Cloud Storage publisher. + + 4. `techdocs.storageUrl` is now a required config. Should be `http://localhost:7000/api/techdocs/static/docs` in most setups. + + 5. Parts of `@backstage/plugin-techdocs-backend` have been moved to a new package `@backstage/techdocs-common` to generate docs. Also to publish docs + to-and-fro between TechDocs and a storage (either local or external). However, a Backstage app does NOT need to import the `techdocs-common` package - + app should only import `@backstage/plugin-techdocs` and `@backstage/plugin-techdocs-backend`. + + _Patch changes_ + + 1. See all of TechDocs config options and its documentation https://backstage.io/docs/features/techdocs/configuration + + 2. Logic about serving static files and metadata retrieval have been abstracted away from the router in `techdocs-backend` to the instance of publisher. + + 3. Removed Material UI Spinner from TechDocs header. Spinners cause unnecessary UX distraction. + Case 1 (when docs are built and are to be served): Spinners appear for a split second before the name of site shows up. This unnecessarily distracts eyes because spinners increase the size of the Header. A dot (.) would do fine. Definitely more can be done. + Case 2 (when docs are being generated): There is already a linear progress bar (which is recommended in Storybook). + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [1d1c2860f] +- Updated dependencies [0e6298f7e] +- Updated dependencies [4eafdec4a] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/backend-common@0.4.1 diff --git a/packages/techdocs-common/package.json b/packages/techdocs-common/package.json index fd767b4a64..d0c09919a0 100644 --- a/packages/techdocs-common/package.json +++ b/packages/techdocs-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/techdocs-common", "description": "Common functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", - "version": "0.1.1", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -36,8 +36,8 @@ "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/backend-common": "^0.4.0", - "@backstage/catalog-model": "^0.5.0", + "@backstage/backend-common": "^0.4.1", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", "@google-cloud/storage": "^5.6.0", "@types/dockerode": "^3.2.1", @@ -55,7 +55,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@types/fs-extra": "^9.0.5", "@types/git-url-parse": "^9.0.0", "@types/js-yaml": "^3.12.5", diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index 53e1da905b..dc1c38ef49 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-api-docs +## 0.4.1 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog@0.2.7 + ## 0.4.0 ### Minor Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 944903067b..7346722550 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-api-docs", - "version": "0.4.0", + "version": "0.4.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,9 +29,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@kyma-project/asyncapi-react": "^0.14.2", "@material-icons/font": "^1.0.2", @@ -49,7 +49,7 @@ "swagger-ui-react": "^3.37.2" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index d0e0b63706..f011d224b4 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-auth-backend +## 0.2.7 + +### Patch Changes + +- 7b15cc271: Added configuration schema for the commonly used properties +- Updated dependencies [c911061b7] +- Updated dependencies [1d1c2860f] +- Updated dependencies [0e6298f7e] +- Updated dependencies [4eafdec4a] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/backend-common@0.4.1 + - @backstage/catalog-client@0.3.4 + ## 0.2.6 ### Patch Changes diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index a31460fea0..c55d4e508f 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend", - "version": "0.2.6", + "version": "0.2.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,9 +29,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.4.0", - "@backstage/catalog-client": "^0.3.3", - "@backstage/catalog-model": "^0.5.0", + "@backstage/backend-common": "^0.4.1", + "@backstage/catalog-client": "^0.3.4", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", "@types/express": "^4.17.6", "compression": "^1.7.4", @@ -64,7 +64,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@types/body-parser": "^1.19.0", "@types/cookie-parser": "^1.4.2", "@types/express-session": "^1.17.2", diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 43a07252b8..95fea0ef3e 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,58 @@ # @backstage/plugin-catalog-backend +## 0.5.0 + +### Minor Changes + +- 6b37c95bf: Write relations directly as part of batch add / update of entities. + + Slight change of the `CommonDatabase` contract: + + ## `addEntity` removed + + This method was unused by the core, and rendered unnecessary when `addEntities` + exists. + + If you were a user of `addEntity`, please call `addEntities` instead, with an + array of one element. + + ## `DbEntityRequest` has a new field `relations` + + This is the structure that is passed to `addEntities` and `updateEntity`. It + used to be the case that you needed to call `setRelations` separately, but now + this instead happens directly when you call `addEntities` or `updateEntity`. + + If you were using `addEntities` or `updateEntity` directly, please adapt your + code to add the `relations` array to each request. If you were calling + `setRelations` separately next to these methods, you no longer need to do so, + after adding the relations to the `DbEntityRequest`s. + +- ac3560b42: Remove `implementsApis` from `Component` entities. Deprecation happened in [#3449](https://github.com/backstage/backstage/pull/3449). + Use `providesApis` instead. + +### Patch Changes + +- c6eeefa35: Add support for Github Enterprise in GitHubOrgReaderProcessor so you can properly ingest users of a GHE organization. +- fb386b760: Break the refresh loop into several smaller transactions +- 7c3ffc0cd: Support `profile` of groups including `displayName`, `email`, and `picture` in + `LdapOrgReaderProcessor`. The source fields for them can be configured in the + `ldapOrg` provider. +- e7496dc3e: Break out GithubOrgReaderProcessor config into its own file for consistency with the other org processors. +- 8dd0a906d: Support `profile` of groups including `displayName` and `picture` in + `GithubOrgReaderProcessor`. Fixes the import of `description` for groups. +- 8c31c681c: Batch the writing of statuses after refreshes. This reduced the runtime on sqlite from 16s to 0.2s, and on pg from 60s to 1s on my machine, for the huge LDAP set. +- 7b98e7fee: Add index to foreign key columns. Postgres (and others) do not do this on the "source" side of a foreign key relation, which was what led to the slowness on large datasets. The full LDAP dataset ingestion now takes two minutes, which is not optimal yet but still a huge improvement over before when it basically never finished :) +- 0097057ed: Support `profile` of groups including `displayName` and `email` in + `MicrosoftGraphOrgReaderProcessor`. Importing `picture` doesn't work yet, as + the Microsoft Graph API does not expose them correctly. +- Updated dependencies [c911061b7] +- Updated dependencies [1d1c2860f] +- Updated dependencies [0e6298f7e] +- Updated dependencies [4eafdec4a] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/backend-common@0.4.1 + ## 0.4.0 ### Minor Changes diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 180956c986..d3500263ca 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend", - "version": "0.4.0", + "version": "0.5.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,8 +30,8 @@ }, "dependencies": { "@azure/msal-node": "^1.0.0-alpha.8", - "@backstage/backend-common": "^0.4.0", - "@backstage/catalog-model": "^0.5.0", + "@backstage/backend-common": "^0.4.1", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", "@octokit/graphql": "^4.5.6", "@types/express": "^4.17.6", @@ -57,7 +57,7 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/test-utils": "^0.1.5", "@types/core-js": "^2.5.4", "@types/git-url-parse": "^9.0.0", diff --git a/plugins/catalog-graphql/CHANGELOG.md b/plugins/catalog-graphql/CHANGELOG.md index 7cef0b765a..ceee335db0 100644 --- a/plugins/catalog-graphql/CHANGELOG.md +++ b/plugins/catalog-graphql/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-graphql +## 0.2.5 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [1d1c2860f] +- Updated dependencies [0e6298f7e] +- Updated dependencies [4eafdec4a] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/backend-common@0.4.1 + ## 0.2.4 ### Patch Changes diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index fa6bd7c4d4..fb013f53c3 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graphql", - "version": "0.2.4", + "version": "0.2.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,8 +30,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.4.0", - "@backstage/catalog-model": "^0.5.0", + "@backstage/backend-common": "^0.4.1", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", "@graphql-modules/core": "^0.7.17", "apollo-server": "^2.16.1", @@ -42,7 +42,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/test-utils": "^0.1.5", "@graphql-codegen/cli": "^1.17.7", "@graphql-codegen/typescript": "^1.17.7", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index bc86a6ac0c..a7301e43a3 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-catalog-import +## 0.3.2 + +### Patch Changes + +- f3e75508d: Add description to Pull Request when registering a new component +- Updated dependencies [c6eeefa35] +- Updated dependencies [fb386b760] +- Updated dependencies [c911061b7] +- Updated dependencies [7c3ffc0cd] +- Updated dependencies [e7496dc3e] +- Updated dependencies [8ef71ed32] +- Updated dependencies [1d1c2860f] +- Updated dependencies [0e6298f7e] +- Updated dependencies [8dd0a906d] +- Updated dependencies [4eafdec4a] +- Updated dependencies [6b37c95bf] +- Updated dependencies [8c31c681c] +- Updated dependencies [7b98e7fee] +- Updated dependencies [178e09323] +- Updated dependencies [ac3560b42] +- Updated dependencies [0097057ed] + - @backstage/plugin-catalog-backend@0.5.0 + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/integration@0.1.4 + - @backstage/plugin-catalog@0.2.7 + ## 0.3.1 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index e2ddf0101e..25010268f9 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-import", - "version": "0.3.1", + "version": "0.3.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,11 +30,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", - "@backstage/plugin-catalog-backend": "^0.4.0", - "@backstage/integration": "^0.1.3", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", + "@backstage/plugin-catalog-backend": "^0.5.0", + "@backstage/integration": "^0.1.4", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -50,7 +50,7 @@ "yaml": "^1.10.0" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index e47808bfa0..73f38582ff 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog +## 0.2.7 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [dae4f3983] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/plugin-techdocs@0.5.0 + - @backstage/core@0.4.1 + - @backstage/catalog-client@0.3.4 + - @backstage/plugin-scaffolder@0.3.4 + ## 0.2.6 ### Patch Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 924115eb82..142ef4a1e6 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog", - "version": "0.2.6", + "version": "0.2.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,11 +30,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-client": "^0.3.3", - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-scaffolder": "^0.3.3", - "@backstage/plugin-techdocs": "^0.4.0", + "@backstage/catalog-client": "^0.3.4", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-scaffolder": "^0.3.4", + "@backstage/plugin-techdocs": "^0.5.0", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -52,7 +52,7 @@ "swr": "^0.3.0" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@microsoft/microsoft-graph-types": "^1.25.0", diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md index dc3bf0d5ca..240ea488a7 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-circleci +## 0.2.5 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog@0.2.7 + ## 0.2.4 ### Patch Changes diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 76fc13df52..d52e5d7414 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-circleci", - "version": "0.2.4", + "version": "0.2.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,9 +31,9 @@ "postpack": "backstage-cli postpack" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -50,7 +50,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md index f2a636cc4c..64e1fe2937 100644 --- a/plugins/cloudbuild/CHANGELOG.md +++ b/plugins/cloudbuild/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-cloudbuild +## 0.2.5 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog@0.2.7 + ## 0.2.4 ### Patch Changes diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index dd040c6cea..80e7404831 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-cloudbuild", - "version": "0.2.4", + "version": "0.2.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,9 +30,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -49,7 +49,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index 0524f66e69..e664883910 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-cost-insights +## 0.5.2 + +### Patch Changes + +- 48c305e69: pin all projects selection to the top of menu list +- Updated dependencies [8ef71ed32] + - @backstage/core@0.4.1 + ## 0.5.1 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 2ff9ab7d1d..d03d698a69 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-cost-insights", - "version": "0.5.1", + "version": "0.5.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,7 +31,7 @@ }, "dependencies": { "@backstage/config": "^0.1.2", - "@backstage/core": "^0.4.0", + "@backstage/core": "^0.4.1", "@backstage/test-utils": "^0.1.5", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", @@ -56,7 +56,7 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index e9edcf76c3..d51c9bd489 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-github-actions +## 0.2.5 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [7dd2ef7d1] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/core-api@0.2.6 + - @backstage/plugin-catalog@0.2.7 + ## 0.2.4 ### Patch Changes diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 6c01a592d8..cfa30bfd77 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-actions", - "version": "0.2.4", + "version": "0.2.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,10 +32,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/core-api": "^0.2.5", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/core-api": "^0.2.6", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -51,7 +51,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/jenkins/CHANGELOG.md b/plugins/jenkins/CHANGELOG.md index c922be67b2..78792789cf 100644 --- a/plugins/jenkins/CHANGELOG.md +++ b/plugins/jenkins/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-jenkins +## 0.3.4 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog@0.2.7 + ## 0.3.3 ### Patch Changes diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index f6c6466236..4c3799d550 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-jenkins", - "version": "0.3.3", + "version": "0.3.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,9 +31,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -46,7 +46,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index b97bc82242..9b247c174f 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-kubernetes-backend +## 0.2.3 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [1d1c2860f] +- Updated dependencies [0e6298f7e] +- Updated dependencies [4eafdec4a] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/backend-common@0.4.1 + ## 0.2.2 ### Patch Changes diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 2a6f56ef33..66a36f8395 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-backend", - "version": "0.2.2", + "version": "0.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,8 +31,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.4.0", - "@backstage/catalog-model": "^0.5.0", + "@backstage/backend-common": "^0.4.1", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", "@kubernetes/client-node": "^0.12.1", "@types/express": "^4.17.6", @@ -49,7 +49,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "supertest": "^4.0.2" }, "files": [ diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index 7ad72103a3..ef5b51cfb9 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-kubernetes +## 0.3.3 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-kubernetes-backend@0.2.3 + ## 0.3.2 ### Patch Changes diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index a7b6da2ce3..649df8353f 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes", - "version": "0.3.2", + "version": "0.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,10 +31,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", - "@backstage/core": "^0.4.0", - "@backstage/plugin-kubernetes-backend": "^0.2.2", + "@backstage/core": "^0.4.1", + "@backstage/plugin-kubernetes-backend": "^0.2.3", "@backstage/theme": "^0.2.2", "@kubernetes/client-node": "^0.12.1", "@material-ui/core": "^4.11.0", @@ -46,7 +46,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md index 3d1d1a491d..42035d1209 100644 --- a/plugins/lighthouse/CHANGELOG.md +++ b/plugins/lighthouse/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-lighthouse +## 0.2.6 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [7dd2ef7d1] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/core-api@0.2.6 + - @backstage/plugin-catalog@0.2.7 + ## 0.2.5 ### Patch Changes diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index 6a5082fcab..93c4d53c21 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-lighthouse", - "version": "0.2.5", + "version": "0.2.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,11 +31,11 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", - "@backstage/core": "^0.4.0", - "@backstage/core-api": "^0.2.5", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/core": "^0.4.1", + "@backstage/core-api": "^0.2.6", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -47,7 +47,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index 541c11b35b..13025d8e83 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-org +## 0.3.2 + +### Patch Changes + +- c0fac6163: Wrap entity cards on smaller screens +- ab805860a: Ensure a name is always displayed for user entities in the org plugin. This can happen when there is no profile + displayName provided (e.g. a GitHub user that has not added a name to their profile) +- 8ef71ed32: Add a `` component to `@backstage/core`. +- c5297baeb: Display the new `profile` fields (`displayName`, `email`, and `picture`) for + groups on the `GroupProfileCard`. + + This also resolves some cases where `profile` fields are missing for users or + groups and for example falls back to displaying the entity name. Adds additional test data to the ACME Corp dataset. + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog@0.2.7 + ## 0.3.1 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index 010fad775e..c81b44756e 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-org", - "version": "0.3.1", + "version": "0.3.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,9 +20,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -33,7 +33,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index d4a5439072..efcd8fbe37 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-pagerduty +## 0.2.3 + +### Patch Changes + +- 3b50f833d: Supporting Timezones +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + ## 0.2.2 ### Patch Changes diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index e1db22c0cd..aa6da07a02 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-pagerduty", - "version": "0.2.2", + "version": "0.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,8 +30,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -44,7 +44,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/register-component/CHANGELOG.md b/plugins/register-component/CHANGELOG.md index 2f4fe297db..488d45ec0e 100644 --- a/plugins/register-component/CHANGELOG.md +++ b/plugins/register-component/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-register-component +## 0.2.5 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog@0.2.7 + ## 0.2.4 ### Patch Changes diff --git a/plugins/register-component/package.json b/plugins/register-component/package.json index 08b56a8c05..bca520b5bc 100644 --- a/plugins/register-component/package.json +++ b/plugins/register-component/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-register-component", - "version": "0.2.4", + "version": "0.2.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,9 +30,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -45,7 +45,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md index 50ed3e75b1..aaa7e704d9 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-rollbar +## 0.2.7 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog@0.2.7 + ## 0.2.6 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 7a479deba3..ff60787109 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-rollbar", - "version": "0.2.6", + "version": "0.2.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,9 +31,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -47,7 +47,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index 2962476b72..b8585e0aec 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-scaffolder-backend +## 0.3.5 + +### Patch Changes + +- 94c65a9d4: Added configuration schema for the commonly used properties +- Updated dependencies [c911061b7] +- Updated dependencies [1d1c2860f] +- Updated dependencies [0e6298f7e] +- Updated dependencies [4eafdec4a] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/backend-common@0.4.1 + ## 0.3.4 ### Patch Changes diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 50bddaaf41..d5f5a5c56b 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend", - "version": "0.3.4", + "version": "0.3.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,8 +29,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.4.0", - "@backstage/catalog-model": "^0.5.0", + "@backstage/backend-common": "^0.4.1", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", "@gitbeaker/core": "^25.2.0", "@gitbeaker/node": "^25.2.0", @@ -57,7 +57,7 @@ "cross-fetch": "^3.0.6" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@octokit/types": "^5.4.1", "@types/fs-extra": "^9.0.1", "@types/git-url-parse": "^9.0.0", diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index 08915241e0..f7d68369ae 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-scaffolder +## 0.3.4 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog@0.2.7 + ## 0.3.3 ### Patch Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 6c802d8130..6b3c64c26d 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder", - "version": "0.3.3", + "version": "0.3.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,9 +30,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -50,7 +50,7 @@ "swr": "^0.3.0" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index f00437b19a..f85c13b47c 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-search +## 0.2.4 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog@0.2.7 + ## 0.2.3 ### Patch Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index ffafbafbbd..a66a9ba323 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search", - "version": "0.2.3", + "version": "0.2.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,9 +29,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", - "@backstage/catalog-model": "^0.5.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", + "@backstage/catalog-model": "^0.6.0", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -43,7 +43,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index 862dfd30eb..f5b5f5efd8 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-sentry +## 0.3.1 + +### Patch Changes + +- 962d1ad66: Added configuration schema for the commonly used properties +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + ## 0.3.0 ### Minor Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index 7b4ca9f083..404ff90f34 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sentry", - "version": "0.3.0", + "version": "0.3.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,8 +31,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -45,7 +45,7 @@ "timeago.js": "^4.0.2" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index bccff558c8..62f9d857a7 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-sonarqube +## 0.1.7 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + ## 0.1.6 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index 7d9467b42b..c5d6433871 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube", - "version": "0.1.6", + "version": "0.1.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,8 +32,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -46,7 +46,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index 92901f7e42..9d57ebc481 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,61 @@ # @backstage/plugin-techdocs-backend +## 0.4.0 + +### Minor Changes + +- dae4f3983: _Breaking changes_ + + 1. Added option to use Google Cloud Storage as a choice to store the static generated files for TechDocs. + It can be configured using `techdocs.publisher.type` option in `app-config.yaml`. + Step-by-step guide to configure GCS is available here https://backstage.io/docs/features/techdocs/using-cloud-storage + Set `techdocs.publisher.type` to `'local'` if you want to continue using local filesystem to store TechDocs files. + + 2. `techdocs.builder` is now required and can be set to `'local'` or `'external'`. (Set it to `'local'` for now, since CI/CD build + workflow for TechDocs will be available soon (in few weeks)). + If builder is set to 'local' and you open a TechDocs page, `techdocs-backend` will try to generate the docs, publish to storage and + show the generated docs afterwords. + If builder is set to `'external'`, `techdocs-backend` will only fetch the docs and will NOT try to generate and publish. In this case of `'external'`, + we assume that docs are being built in the CI/CD pipeline of the repository. + TechDocs will not assume a default value for `techdocs.builder`. It is better to explicitly define it in the `app-config.yaml`. + + 3. When configuring TechDocs in your backend, there is a difference in how a new publisher is created. + + ``` + --- const publisher = new LocalPublish(logger, discovery); + +++ const publisher = Publisher.fromConfig(config, logger, discovery); + ``` + + Based on the config `techdocs.publisher.type`, the publisher could be either Local publisher or Google Cloud Storage publisher. + + 4. `techdocs.storageUrl` is now a required config. Should be `http://localhost:7000/api/techdocs/static/docs` in most setups. + + 5. Parts of `@backstage/plugin-techdocs-backend` have been moved to a new package `@backstage/techdocs-common` to generate docs. Also to publish docs + to-and-fro between TechDocs and a storage (either local or external). However, a Backstage app does NOT need to import the `techdocs-common` package - + app should only import `@backstage/plugin-techdocs` and `@backstage/plugin-techdocs-backend`. + + _Patch changes_ + + 1. See all of TechDocs config options and its documentation https://backstage.io/docs/features/techdocs/configuration + + 2. Logic about serving static files and metadata retrieval have been abstracted away from the router in `techdocs-backend` to the instance of publisher. + + 3. Removed Material UI Spinner from TechDocs header. Spinners cause unnecessary UX distraction. + Case 1 (when docs are built and are to be served): Spinners appear for a split second before the name of site shows up. This unnecessarily distracts eyes because spinners increase the size of the Header. A dot (.) would do fine. Definitely more can be done. + Case 2 (when docs are being generated): There is already a linear progress bar (which is recommended in Storybook). + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [dae4f3983] +- Updated dependencies [1d1c2860f] +- Updated dependencies [0e6298f7e] +- Updated dependencies [4eafdec4a] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/techdocs-common@0.2.0 + - @backstage/backend-common@0.4.1 + ## 0.3.2 ### Patch Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index fc11122ead..5552d87f3f 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-backend", - "version": "0.3.2", + "version": "0.4.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,10 +30,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.4.0", - "@backstage/catalog-model": "^0.5.0", + "@backstage/backend-common": "^0.4.1", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", - "@backstage/techdocs-common": "^0.1.1", + "@backstage/techdocs-common": "^0.2.0", "@types/dockerode": "^3.2.1", "@types/express": "^4.17.6", "cross-fetch": "^3.0.6", @@ -44,7 +44,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "supertest": "^4.0.2" }, "files": [ diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 26ee57fb86..d7bb8506b2 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,63 @@ # @backstage/plugin-techdocs +## 0.5.0 + +### Minor Changes + +- dae4f3983: _Breaking changes_ + + 1. Added option to use Google Cloud Storage as a choice to store the static generated files for TechDocs. + It can be configured using `techdocs.publisher.type` option in `app-config.yaml`. + Step-by-step guide to configure GCS is available here https://backstage.io/docs/features/techdocs/using-cloud-storage + Set `techdocs.publisher.type` to `'local'` if you want to continue using local filesystem to store TechDocs files. + + 2. `techdocs.builder` is now required and can be set to `'local'` or `'external'`. (Set it to `'local'` for now, since CI/CD build + workflow for TechDocs will be available soon (in few weeks)). + If builder is set to 'local' and you open a TechDocs page, `techdocs-backend` will try to generate the docs, publish to storage and + show the generated docs afterwords. + If builder is set to `'external'`, `techdocs-backend` will only fetch the docs and will NOT try to generate and publish. In this case of `'external'`, + we assume that docs are being built in the CI/CD pipeline of the repository. + TechDocs will not assume a default value for `techdocs.builder`. It is better to explicitly define it in the `app-config.yaml`. + + 3. When configuring TechDocs in your backend, there is a difference in how a new publisher is created. + + ``` + --- const publisher = new LocalPublish(logger, discovery); + +++ const publisher = Publisher.fromConfig(config, logger, discovery); + ``` + + Based on the config `techdocs.publisher.type`, the publisher could be either Local publisher or Google Cloud Storage publisher. + + 4. `techdocs.storageUrl` is now a required config. Should be `http://localhost:7000/api/techdocs/static/docs` in most setups. + + 5. Parts of `@backstage/plugin-techdocs-backend` have been moved to a new package `@backstage/techdocs-common` to generate docs. Also to publish docs + to-and-fro between TechDocs and a storage (either local or external). However, a Backstage app does NOT need to import the `techdocs-common` package - + app should only import `@backstage/plugin-techdocs` and `@backstage/plugin-techdocs-backend`. + + _Patch changes_ + + 1. See all of TechDocs config options and its documentation https://backstage.io/docs/features/techdocs/configuration + + 2. Logic about serving static files and metadata retrieval have been abstracted away from the router in `techdocs-backend` to the instance of publisher. + + 3. Removed Material UI Spinner from TechDocs header. Spinners cause unnecessary UX distraction. + Case 1 (when docs are built and are to be served): Spinners appear for a split second before the name of site shows up. This unnecessarily distracts eyes because spinners increase the size of the Header. A dot (.) would do fine. Definitely more can be done. + Case 2 (when docs are being generated): There is already a linear progress bar (which is recommended in Storybook). + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [dae4f3983] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [7dd2ef7d1] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/techdocs-common@0.2.0 + - @backstage/core@0.4.1 + - @backstage/core-api@0.2.6 + - @backstage/plugin-catalog@0.2.7 + ## 0.4.0 ### Minor Changes diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 15325ed7bc..361825e71a 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs", - "version": "0.4.0", + "version": "0.5.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,13 +31,13 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/core-api": "^0.2.5", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/core-api": "^0.2.6", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/test-utils": "^0.1.5", "@backstage/theme": "^0.2.2", - "@backstage/techdocs-common": "^0.1.1", + "@backstage/techdocs-common": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -50,7 +50,7 @@ "sanitize-html": "^1.27.0" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", From 0d02fb2a59fa051eee36078242d7cdb3f9dc4e12 Mon Sep 17 00:00:00 2001 From: AdnCodez Date: Thu, 17 Dec 2020 11:36:39 +0100 Subject: [PATCH 70/98] fix(microsite): make the anchor link icon show up --- microsite/static/css/custom.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/static/css/custom.css b/microsite/static/css/custom.css index 8805625286..46b2aa3470 100644 --- a/microsite/static/css/custom.css +++ b/microsite/static/css/custom.css @@ -49,7 +49,7 @@ h6 { } h2:hover .hash-link { - opacity: 1 + opacity: 1; } .hash-link { From fd15959d6cb3847e1b94878fa4455de56bceef7f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 17 Dec 2020 10:48:05 +0000 Subject: [PATCH 71/98] Version Packages --- .changeset/calm-scissors-jam.md | 5 -- .changeset/chilly-pumpkins-retire.md | 5 -- .changeset/cost-insights-tasty-years-laugh.md | 5 -- .changeset/curvy-dodos-fry.md | 5 -- .changeset/dirty-melons-retire.md | 6 -- .changeset/dirty-wolves-wink.md | 7 --- .changeset/early-dots-drive.md | 6 -- .changeset/friendly-carpets-repeat.md | 45 -------------- .changeset/friendly-olives-breathe.md | 5 -- .changeset/good-news-return.md | 5 -- .changeset/gorgeous-scissors-jog.md | 6 -- .changeset/grumpy-elephants-press.md | 6 -- .changeset/heavy-ducks-raise.md | 5 -- .changeset/loud-icons-itch.md | 5 -- .changeset/nice-trains-punch.md | 5 -- .changeset/odd-mugs-build.md | 6 -- .changeset/pink-ravens-destroy.md | 6 -- .changeset/purple-cycles-switch.md | 26 --------- .changeset/rare-peas-accept.md | 5 -- .changeset/rotten-pandas-draw.md | 5 -- .changeset/shiny-grapes-tan.md | 5 -- .changeset/six-mugs-camp.md | 20 ------- .changeset/sour-badgers-cry.md | 5 -- .changeset/swift-sheep-ring.md | 5 -- .changeset/tender-coats-unite.md | 9 --- .changeset/thirty-fans-hammer.md | 7 --- .changeset/weak-sloths-prove.md | 5 -- .changeset/wet-garlics-shave.md | 5 -- .changeset/witty-scissors-divide.md | 7 --- packages/app/CHANGELOG.md | 39 +++++++++++++ packages/app/package.json | 44 +++++++------- packages/backend-common/CHANGELOG.md | 11 ++++ packages/backend-common/package.json | 6 +- packages/backend/CHANGELOG.md | 30 ++++++++++ packages/backend/package.json | 20 +++---- packages/catalog-client/CHANGELOG.md | 9 +++ packages/catalog-client/package.json | 6 +- packages/catalog-model/CHANGELOG.md | 13 +++++ packages/catalog-model/package.json | 4 +- packages/cli/CHANGELOG.md | 6 ++ packages/cli/package.json | 6 +- packages/core-api/CHANGELOG.md | 6 ++ packages/core-api/package.json | 4 +- packages/core/CHANGELOG.md | 8 +++ packages/core/package.json | 6 +- packages/create-app/CHANGELOG.md | 21 +++++++ packages/create-app/package.json | 34 +++++------ packages/integration/CHANGELOG.md | 8 +++ packages/integration/package.json | 4 +- packages/techdocs-common/CHANGELOG.md | 55 ++++++++++++++++++ packages/techdocs-common/package.json | 8 +-- plugins/api-docs/CHANGELOG.md | 12 ++++ plugins/api-docs/package.json | 10 ++-- plugins/auth-backend/CHANGELOG.md | 14 +++++ plugins/auth-backend/package.json | 10 ++-- plugins/catalog-backend/CHANGELOG.md | 53 +++++++++++++++++ plugins/catalog-backend/package.json | 8 +-- plugins/catalog-graphql/CHANGELOG.md | 12 ++++ plugins/catalog-graphql/package.json | 8 +-- plugins/catalog-import/CHANGELOG.md | 27 +++++++++ plugins/catalog-import/package.json | 14 ++--- plugins/catalog/CHANGELOG.md | 15 +++++ plugins/catalog/package.json | 14 ++--- plugins/circleci/CHANGELOG.md | 12 ++++ plugins/circleci/package.json | 10 ++-- plugins/cloudbuild/CHANGELOG.md | 12 ++++ plugins/cloudbuild/package.json | 10 ++-- plugins/cost-insights/CHANGELOG.md | 8 +++ plugins/cost-insights/package.json | 6 +- plugins/github-actions/CHANGELOG.md | 14 +++++ plugins/github-actions/package.json | 12 ++-- plugins/jenkins/CHANGELOG.md | 12 ++++ plugins/jenkins/package.json | 10 ++-- plugins/kubernetes-backend/CHANGELOG.md | 12 ++++ plugins/kubernetes-backend/package.json | 8 +-- plugins/kubernetes/CHANGELOG.md | 12 ++++ plugins/kubernetes/package.json | 10 ++-- plugins/lighthouse/CHANGELOG.md | 14 +++++ plugins/lighthouse/package.json | 12 ++-- plugins/org/CHANGELOG.md | 22 +++++++ plugins/org/package.json | 10 ++-- plugins/pagerduty/CHANGELOG.md | 12 ++++ plugins/pagerduty/package.json | 8 +-- plugins/register-component/CHANGELOG.md | 12 ++++ plugins/register-component/package.json | 10 ++-- plugins/rollbar/CHANGELOG.md | 12 ++++ plugins/rollbar/package.json | 10 ++-- plugins/scaffolder-backend/CHANGELOG.md | 13 +++++ plugins/scaffolder-backend/package.json | 8 +-- plugins/scaffolder/CHANGELOG.md | 12 ++++ plugins/scaffolder/package.json | 10 ++-- plugins/search/CHANGELOG.md | 12 ++++ plugins/search/package.json | 10 ++-- plugins/sentry/CHANGELOG.md | 12 ++++ plugins/sentry/package.json | 8 +-- plugins/sonarqube/CHANGELOG.md | 11 ++++ plugins/sonarqube/package.json | 8 +-- plugins/techdocs-backend/CHANGELOG.md | 56 ++++++++++++++++++ plugins/techdocs-backend/package.json | 10 ++-- plugins/techdocs/CHANGELOG.md | 58 +++++++++++++++++++ plugins/techdocs/package.json | 14 ++--- 101 files changed, 862 insertions(+), 432 deletions(-) delete mode 100644 .changeset/calm-scissors-jam.md delete mode 100644 .changeset/chilly-pumpkins-retire.md delete mode 100644 .changeset/cost-insights-tasty-years-laugh.md delete mode 100644 .changeset/curvy-dodos-fry.md delete mode 100644 .changeset/dirty-melons-retire.md delete mode 100644 .changeset/dirty-wolves-wink.md delete mode 100644 .changeset/early-dots-drive.md delete mode 100644 .changeset/friendly-carpets-repeat.md delete mode 100644 .changeset/friendly-olives-breathe.md delete mode 100644 .changeset/good-news-return.md delete mode 100644 .changeset/gorgeous-scissors-jog.md delete mode 100644 .changeset/grumpy-elephants-press.md delete mode 100644 .changeset/heavy-ducks-raise.md delete mode 100644 .changeset/loud-icons-itch.md delete mode 100644 .changeset/nice-trains-punch.md delete mode 100644 .changeset/odd-mugs-build.md delete mode 100644 .changeset/pink-ravens-destroy.md delete mode 100644 .changeset/purple-cycles-switch.md delete mode 100644 .changeset/rare-peas-accept.md delete mode 100644 .changeset/rotten-pandas-draw.md delete mode 100644 .changeset/shiny-grapes-tan.md delete mode 100644 .changeset/six-mugs-camp.md delete mode 100644 .changeset/sour-badgers-cry.md delete mode 100644 .changeset/swift-sheep-ring.md delete mode 100644 .changeset/tender-coats-unite.md delete mode 100644 .changeset/thirty-fans-hammer.md delete mode 100644 .changeset/weak-sloths-prove.md delete mode 100644 .changeset/wet-garlics-shave.md delete mode 100644 .changeset/witty-scissors-divide.md create mode 100644 packages/techdocs-common/CHANGELOG.md diff --git a/.changeset/calm-scissors-jam.md b/.changeset/calm-scissors-jam.md deleted file mode 100644 index c815670fd0..0000000000 --- a/.changeset/calm-scissors-jam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Add support for Github Enterprise in GitHubOrgReaderProcessor so you can properly ingest users of a GHE organization. diff --git a/.changeset/chilly-pumpkins-retire.md b/.changeset/chilly-pumpkins-retire.md deleted file mode 100644 index b206cb6fe7..0000000000 --- a/.changeset/chilly-pumpkins-retire.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-org': patch ---- - -Wrap entity cards on smaller screens diff --git a/.changeset/cost-insights-tasty-years-laugh.md b/.changeset/cost-insights-tasty-years-laugh.md deleted file mode 100644 index 3728514fb1..0000000000 --- a/.changeset/cost-insights-tasty-years-laugh.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-cost-insights': patch ---- - -pin all projects selection to the top of menu list diff --git a/.changeset/curvy-dodos-fry.md b/.changeset/curvy-dodos-fry.md deleted file mode 100644 index 80ab333e38..0000000000 --- a/.changeset/curvy-dodos-fry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Break the refresh loop into several smaller transactions diff --git a/.changeset/dirty-melons-retire.md b/.changeset/dirty-melons-retire.md deleted file mode 100644 index 2b92b44678..0000000000 --- a/.changeset/dirty-melons-retire.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/catalog-model': patch ---- - -Introduce a `profile` section for group entities that can optional include a -`displayName`, `email` and `picture`. diff --git a/.changeset/dirty-wolves-wink.md b/.changeset/dirty-wolves-wink.md deleted file mode 100644 index 77f1a62aff..0000000000 --- a/.changeset/dirty-wolves-wink.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Support `profile` of groups including `displayName`, `email`, and `picture` in -`LdapOrgReaderProcessor`. The source fields for them can be configured in the -`ldapOrg` provider. diff --git a/.changeset/early-dots-drive.md b/.changeset/early-dots-drive.md deleted file mode 100644 index 7a5eedec78..0000000000 --- a/.changeset/early-dots-drive.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-org': patch ---- - -Ensure a name is always displayed for user entities in the org plugin. This can happen when there is no profile -displayName provided (e.g. a GitHub user that has not added a name to their profile) diff --git a/.changeset/friendly-carpets-repeat.md b/.changeset/friendly-carpets-repeat.md deleted file mode 100644 index 7fb0d2f6eb..0000000000 --- a/.changeset/friendly-carpets-repeat.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -'@backstage/techdocs-common': minor -'@backstage/plugin-techdocs': minor -'@backstage/plugin-techdocs-backend': minor ---- - -_Breaking changes_ - -1. Added option to use Google Cloud Storage as a choice to store the static generated files for TechDocs. - It can be configured using `techdocs.publisher.type` option in `app-config.yaml`. - Step-by-step guide to configure GCS is available here https://backstage.io/docs/features/techdocs/using-cloud-storage - Set `techdocs.publisher.type` to `'local'` if you want to continue using local filesystem to store TechDocs files. - -2. `techdocs.builder` is now required and can be set to `'local'` or `'external'`. (Set it to `'local'` for now, since CI/CD build - workflow for TechDocs will be available soon (in few weeks)). - If builder is set to 'local' and you open a TechDocs page, `techdocs-backend` will try to generate the docs, publish to storage and - show the generated docs afterwords. - If builder is set to `'external'`, `techdocs-backend` will only fetch the docs and will NOT try to generate and publish. In this case of `'external'`, - we assume that docs are being built in the CI/CD pipeline of the repository. - TechDocs will not assume a default value for `techdocs.builder`. It is better to explicitly define it in the `app-config.yaml`. - -3. When configuring TechDocs in your backend, there is a difference in how a new publisher is created. - -``` ---- const publisher = new LocalPublish(logger, discovery); -+++ const publisher = Publisher.fromConfig(config, logger, discovery); -``` - -Based on the config `techdocs.publisher.type`, the publisher could be either Local publisher or Google Cloud Storage publisher. - -4. `techdocs.storageUrl` is now a required config. Should be `http://localhost:7000/api/techdocs/static/docs` in most setups. - -5. Parts of `@backstage/plugin-techdocs-backend` have been moved to a new package `@backstage/techdocs-common` to generate docs. Also to publish docs - to-and-fro between TechDocs and a storage (either local or external). However, a Backstage app does NOT need to import the `techdocs-common` package - - app should only import `@backstage/plugin-techdocs` and `@backstage/plugin-techdocs-backend`. - -_Patch changes_ - -1. See all of TechDocs config options and its documentation https://backstage.io/docs/features/techdocs/configuration - -2. Logic about serving static files and metadata retrieval have been abstracted away from the router in `techdocs-backend` to the instance of publisher. - -3. Removed Material UI Spinner from TechDocs header. Spinners cause unnecessary UX distraction. - Case 1 (when docs are built and are to be served): Spinners appear for a split second before the name of site shows up. This unnecessarily distracts eyes because spinners increase the size of the Header. A dot (.) would do fine. Definitely more can be done. - Case 2 (when docs are being generated): There is already a linear progress bar (which is recommended in Storybook). diff --git a/.changeset/friendly-olives-breathe.md b/.changeset/friendly-olives-breathe.md deleted file mode 100644 index 9dce3b9709..0000000000 --- a/.changeset/friendly-olives-breathe.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-backend': patch ---- - -Added configuration schema for the commonly used properties diff --git a/.changeset/good-news-return.md b/.changeset/good-news-return.md deleted file mode 100644 index 6cb02e6e82..0000000000 --- a/.changeset/good-news-return.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Break out GithubOrgReaderProcessor config into its own file for consistency with the other org processors. diff --git a/.changeset/gorgeous-scissors-jog.md b/.changeset/gorgeous-scissors-jog.md deleted file mode 100644 index 3f192808c1..0000000000 --- a/.changeset/gorgeous-scissors-jog.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/core': patch -'@backstage/plugin-org': patch ---- - -Add a `` component to `@backstage/core`. diff --git a/.changeset/grumpy-elephants-press.md b/.changeset/grumpy-elephants-press.md deleted file mode 100644 index d85d36e609..0000000000 --- a/.changeset/grumpy-elephants-press.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/backend-common': patch -'@backstage/integration': patch ---- - -Implement readTree on BitBucketUrlReader and getBitbucketDownloadUrl diff --git a/.changeset/heavy-ducks-raise.md b/.changeset/heavy-ducks-raise.md deleted file mode 100644 index 71a16da512..0000000000 --- a/.changeset/heavy-ducks-raise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/catalog-model': patch ---- - -Ignore relations when comparing entities. This stops the refresh loop from rewriting entities over and over. diff --git a/.changeset/loud-icons-itch.md b/.changeset/loud-icons-itch.md deleted file mode 100644 index c5741c5d0b..0000000000 --- a/.changeset/loud-icons-itch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-import': patch ---- - -Add description to Pull Request when registering a new component diff --git a/.changeset/nice-trains-punch.md b/.changeset/nice-trains-punch.md deleted file mode 100644 index 71225ac97c..0000000000 --- a/.changeset/nice-trains-punch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-pagerduty': patch ---- - -Supporting Timezones diff --git a/.changeset/odd-mugs-build.md b/.changeset/odd-mugs-build.md deleted file mode 100644 index bf95d23410..0000000000 --- a/.changeset/odd-mugs-build.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Support `profile` of groups including `displayName` and `picture` in -`GithubOrgReaderProcessor`. Fixes the import of `description` for groups. diff --git a/.changeset/pink-ravens-destroy.md b/.changeset/pink-ravens-destroy.md deleted file mode 100644 index 647ccd9f37..0000000000 --- a/.changeset/pink-ravens-destroy.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/backend-common': patch -'@backstage/integration': patch ---- - -Introduce readTree method for GitLab URL Reader diff --git a/.changeset/purple-cycles-switch.md b/.changeset/purple-cycles-switch.md deleted file mode 100644 index c7594e4254..0000000000 --- a/.changeset/purple-cycles-switch.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -Write relations directly as part of batch add / update of entities. - -Slight change of the `CommonDatabase` contract: - -## `addEntity` removed - -This method was unused by the core, and rendered unnecessary when `addEntities` -exists. - -If you were a user of `addEntity`, please call `addEntities` instead, with an -array of one element. - -## `DbEntityRequest` has a new field `relations` - -This is the structure that is passed to `addEntities` and `updateEntity`. It -used to be the case that you needed to call `setRelations` separately, but now -this instead happens directly when you call `addEntities` or `updateEntity`. - -If you were using `addEntities` or `updateEntity` directly, please adapt your -code to add the `relations` array to each request. If you were calling -`setRelations` separately next to these methods, you no longer need to do so, -after adding the relations to the `DbEntityRequest`s. diff --git a/.changeset/rare-peas-accept.md b/.changeset/rare-peas-accept.md deleted file mode 100644 index 74597dda11..0000000000 --- a/.changeset/rare-peas-accept.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Batch the writing of statuses after refreshes. This reduced the runtime on sqlite from 16s to 0.2s, and on pg from 60s to 1s on my machine, for the huge LDAP set. diff --git a/.changeset/rotten-pandas-draw.md b/.changeset/rotten-pandas-draw.md deleted file mode 100644 index 85b3feeaec..0000000000 --- a/.changeset/rotten-pandas-draw.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Add index to foreign key columns. Postgres (and others) do not do this on the "source" side of a foreign key relation, which was what led to the slowness on large datasets. The full LDAP dataset ingestion now takes two minutes, which is not optimal yet but still a huge improvement over before when it basically never finished :) diff --git a/.changeset/shiny-grapes-tan.md b/.changeset/shiny-grapes-tan.md deleted file mode 100644 index b7361bb970..0000000000 --- a/.changeset/shiny-grapes-tan.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/integration': patch ---- - -Validate that integration config contains a valid host diff --git a/.changeset/six-mugs-camp.md b/.changeset/six-mugs-camp.md deleted file mode 100644 index 373edd340a..0000000000 --- a/.changeset/six-mugs-camp.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -In the techdocs-backend plugin (`packages/backend/src/plugins/techdocs.ts`), create a publisher using - -``` - const publisher = Publisher.fromConfig(config, logger, discovery); -``` - -instead of - -``` - const publisher = new LocalPublish(logger, discovery); -``` - -An instance of `publisher` can either be a local filesystem publisher or a Google Cloud Storage publisher. - -Read more about the configs here https://backstage.io/docs/features/techdocs/configuration -(You will also have to update `techdocs.storage.type` to `local` or `googleGcs`. And `techdocs.builder` to either `local` or `external`.) diff --git a/.changeset/sour-badgers-cry.md b/.changeset/sour-badgers-cry.md deleted file mode 100644 index 901294bf03..0000000000 --- a/.changeset/sour-badgers-cry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-api': patch ---- - -Use auth provider ID to create unique session storage keys for GitHub and SAML Auth. diff --git a/.changeset/swift-sheep-ring.md b/.changeset/swift-sheep-ring.md deleted file mode 100644 index f4cf92c29d..0000000000 --- a/.changeset/swift-sheep-ring.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Re-enable symlink resolution during bundling, and switch to using a resolve plugin for external linked packages. diff --git a/.changeset/tender-coats-unite.md b/.changeset/tender-coats-unite.md deleted file mode 100644 index 4b87720f2f..0000000000 --- a/.changeset/tender-coats-unite.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/plugin-org': patch ---- - -Display the new `profile` fields (`displayName`, `email`, and `picture`) for -groups on the `GroupProfileCard`. - -This also resolves some cases where `profile` fields are missing for users or -groups and for example falls back to displaying the entity name. Adds additional test data to the ACME Corp dataset. diff --git a/.changeset/thirty-fans-hammer.md b/.changeset/thirty-fans-hammer.md deleted file mode 100644 index 45fb398f8c..0000000000 --- a/.changeset/thirty-fans-hammer.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/catalog-model': minor -'@backstage/plugin-catalog-backend': minor ---- - -Remove `implementsApis` from `Component` entities. Deprecation happened in [#3449](https://github.com/backstage/backstage/pull/3449). -Use `providesApis` instead. diff --git a/.changeset/weak-sloths-prove.md b/.changeset/weak-sloths-prove.md deleted file mode 100644 index bfecb385c8..0000000000 --- a/.changeset/weak-sloths-prove.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Added configuration schema for the commonly used properties diff --git a/.changeset/wet-garlics-shave.md b/.changeset/wet-garlics-shave.md deleted file mode 100644 index 86b42541eb..0000000000 --- a/.changeset/wet-garlics-shave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-sentry': patch ---- - -Added configuration schema for the commonly used properties diff --git a/.changeset/witty-scissors-divide.md b/.changeset/witty-scissors-divide.md deleted file mode 100644 index f288088ef2..0000000000 --- a/.changeset/witty-scissors-divide.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Support `profile` of groups including `displayName` and `email` in -`MicrosoftGraphOrgReaderProcessor`. Importing `picture` doesn't work yet, as -the Microsoft Graph API does not expose them correctly. diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 03958c831c..799895ef56 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,44 @@ # example-app +## 0.2.7 + +### Patch Changes + +- Updated dependencies [c0fac6163] +- Updated dependencies [48c305e69] +- Updated dependencies [c911061b7] +- Updated dependencies [ab805860a] +- Updated dependencies [dae4f3983] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [f3e75508d] +- Updated dependencies [3b50f833d] +- Updated dependencies [c36a01b4c] +- Updated dependencies [c5297baeb] +- Updated dependencies [ac3560b42] +- Updated dependencies [962d1ad66] + - @backstage/plugin-org@0.3.2 + - @backstage/plugin-cost-insights@0.5.2 + - @backstage/catalog-model@0.6.0 + - @backstage/plugin-techdocs@0.5.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog-import@0.3.2 + - @backstage/plugin-pagerduty@0.2.3 + - @backstage/cli@0.4.2 + - @backstage/plugin-sentry@0.3.1 + - @backstage/plugin-api-docs@0.4.1 + - @backstage/plugin-catalog@0.2.7 + - @backstage/plugin-circleci@0.2.5 + - @backstage/plugin-cloudbuild@0.2.5 + - @backstage/plugin-github-actions@0.2.5 + - @backstage/plugin-jenkins@0.3.4 + - @backstage/plugin-kubernetes@0.3.3 + - @backstage/plugin-lighthouse@0.2.6 + - @backstage/plugin-register-component@0.2.5 + - @backstage/plugin-rollbar@0.2.7 + - @backstage/plugin-scaffolder@0.3.4 + - @backstage/plugin-search@0.2.4 + ## 0.2.6 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 9d05ae659a..63710a5c28 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,36 +1,36 @@ { "name": "example-app", - "version": "0.2.6", + "version": "0.2.7", "private": true, "bundled": true, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/cli": "^0.4.1", - "@backstage/core": "^0.4.0", - "@backstage/plugin-api-docs": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", - "@backstage/plugin-catalog-import": "^0.3.1", - "@backstage/plugin-circleci": "^0.2.4", - "@backstage/plugin-cloudbuild": "^0.2.4", - "@backstage/plugin-cost-insights": "^0.5.0", + "@backstage/catalog-model": "^0.6.0", + "@backstage/cli": "^0.4.2", + "@backstage/core": "^0.4.1", + "@backstage/plugin-api-docs": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", + "@backstage/plugin-catalog-import": "^0.3.2", + "@backstage/plugin-circleci": "^0.2.5", + "@backstage/plugin-cloudbuild": "^0.2.5", + "@backstage/plugin-cost-insights": "^0.5.2", "@backstage/plugin-explore": "^0.2.2", "@backstage/plugin-gcp-projects": "^0.2.2", - "@backstage/plugin-github-actions": "^0.2.4", + "@backstage/plugin-github-actions": "^0.2.5", "@backstage/plugin-gitops-profiles": "^0.2.2", "@backstage/plugin-graphiql": "^0.2.2", - "@backstage/plugin-org": "^0.3.1", - "@backstage/plugin-jenkins": "^0.3.3", - "@backstage/plugin-kubernetes": "^0.3.2", - "@backstage/plugin-lighthouse": "^0.2.5", + "@backstage/plugin-org": "^0.3.2", + "@backstage/plugin-jenkins": "^0.3.4", + "@backstage/plugin-kubernetes": "^0.3.3", + "@backstage/plugin-lighthouse": "^0.2.6", "@backstage/plugin-newrelic": "^0.2.2", - "@backstage/plugin-pagerduty": "0.2.2", - "@backstage/plugin-register-component": "^0.2.4", - "@backstage/plugin-rollbar": "^0.2.6", - "@backstage/plugin-scaffolder": "^0.3.3", - "@backstage/plugin-sentry": "^0.3.0", - "@backstage/plugin-search": "^0.2.3", + "@backstage/plugin-pagerduty": "0.2.3", + "@backstage/plugin-register-component": "^0.2.5", + "@backstage/plugin-rollbar": "^0.2.7", + "@backstage/plugin-scaffolder": "^0.3.4", + "@backstage/plugin-sentry": "^0.3.1", + "@backstage/plugin-search": "^0.2.4", "@backstage/plugin-tech-radar": "^0.3.1", - "@backstage/plugin-techdocs": "^0.4.0", + "@backstage/plugin-techdocs": "^0.5.0", "@backstage/plugin-user-settings": "^0.2.3", "@backstage/plugin-welcome": "^0.2.3", "@backstage/test-utils": "^0.1.5", diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index 702b1dcbf2..0e0a3074a4 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/backend-common +## 0.4.1 + +### Patch Changes + +- 1d1c2860f: Implement readTree on BitBucketUrlReader and getBitbucketDownloadUrl +- 4eafdec4a: Introduce readTree method for GitLab URL Reader +- Updated dependencies [1d1c2860f] +- Updated dependencies [4eafdec4a] +- Updated dependencies [178e09323] + - @backstage/integration@0.1.4 + ## 0.4.0 ### Minor Changes diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 395183104d..e65edba0a5 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-common", "description": "Common functionality library for Backstage backends", - "version": "0.4.0", + "version": "0.4.1", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -32,7 +32,7 @@ "@backstage/cli-common": "^0.1.1", "@backstage/config": "^0.1.2", "@backstage/config-loader": "^0.4.0", - "@backstage/integration": "^0.1.3", + "@backstage/integration": "^0.1.4", "@types/cors": "^2.8.6", "@types/express": "^4.17.6", "archiver": "^5.0.2", @@ -65,7 +65,7 @@ } }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/test-utils": "^0.1.5", "@types/archiver": "^3.1.1", "@types/compression": "^1.7.0", diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index d0a8f4112a..3f053accfa 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,35 @@ # example-backend +## 0.2.7 + +### Patch Changes + +- Updated dependencies [c6eeefa35] +- Updated dependencies [fb386b760] +- Updated dependencies [c911061b7] +- Updated dependencies [7c3ffc0cd] +- Updated dependencies [dae4f3983] +- Updated dependencies [7b15cc271] +- Updated dependencies [e7496dc3e] +- Updated dependencies [1d1c2860f] +- Updated dependencies [0e6298f7e] +- Updated dependencies [8dd0a906d] +- Updated dependencies [4eafdec4a] +- Updated dependencies [6b37c95bf] +- Updated dependencies [8c31c681c] +- Updated dependencies [7b98e7fee] +- Updated dependencies [ac3560b42] +- Updated dependencies [94c65a9d4] +- Updated dependencies [0097057ed] + - @backstage/plugin-catalog-backend@0.5.0 + - @backstage/catalog-model@0.6.0 + - @backstage/plugin-techdocs-backend@0.4.0 + - @backstage/plugin-auth-backend@0.2.7 + - @backstage/backend-common@0.4.1 + - @backstage/plugin-scaffolder-backend@0.3.5 + - example-app@0.2.7 + - @backstage/plugin-kubernetes-backend@0.2.3 + ## 0.2.6 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index 74b459d691..718b008c7b 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.6", + "version": "0.2.7", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", @@ -27,23 +27,23 @@ "migrate:create": "knex migrate:make -x ts" }, "dependencies": { - "@backstage/backend-common": "^0.4.0", - "@backstage/catalog-model": "^0.5.0", + "@backstage/backend-common": "^0.4.1", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", "@backstage/plugin-app-backend": "^0.3.3", - "@backstage/plugin-auth-backend": "^0.2.6", - "@backstage/plugin-catalog-backend": "^0.4.0", + "@backstage/plugin-auth-backend": "^0.2.7", + "@backstage/plugin-catalog-backend": "^0.5.0", "@backstage/plugin-graphql-backend": "^0.1.4", - "@backstage/plugin-kubernetes-backend": "^0.2.2", + "@backstage/plugin-kubernetes-backend": "^0.2.3", "@backstage/plugin-proxy-backend": "^0.2.3", "@backstage/plugin-rollbar-backend": "^0.1.5", - "@backstage/plugin-scaffolder-backend": "^0.3.4", - "@backstage/plugin-techdocs-backend": "^0.3.2", + "@backstage/plugin-scaffolder-backend": "^0.3.5", + "@backstage/plugin-techdocs-backend": "^0.4.0", "@gitbeaker/node": "^25.2.0", "@octokit/rest": "^18.0.0", "azure-devops-node-api": "^10.1.1", "dockerode": "^3.2.1", - "example-app": "^0.2.6", + "example-app": "^0.2.7", "express": "^4.17.1", "express-promise-router": "^3.0.3", "knex": "^0.21.6", @@ -53,7 +53,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@types/dockerode": "^3.2.1", "@types/express": "^4.17.6", "@types/express-serve-static-core": "^4.17.5", diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index e649db0f22..c99f72e376 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/catalog-client +## 0.3.4 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + ## 0.3.3 ### Patch Changes diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index 36500c7c23..c878119a35 100644 --- a/packages/catalog-client/package.json +++ b/packages/catalog-client/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/catalog-client", - "version": "0.3.3", + "version": "0.3.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,12 +29,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", "cross-fetch": "^3.0.6" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@types/jest": "^26.0.7", "msw": "^0.21.2" }, diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md index 7316836a71..f6c2477d6c 100644 --- a/packages/catalog-model/CHANGELOG.md +++ b/packages/catalog-model/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/catalog-model +## 0.6.0 + +### Minor Changes + +- ac3560b42: Remove `implementsApis` from `Component` entities. Deprecation happened in [#3449](https://github.com/backstage/backstage/pull/3449). + Use `providesApis` instead. + +### Patch Changes + +- c911061b7: Introduce a `profile` section for group entities that can optional include a + `displayName`, `email` and `picture`. +- 0e6298f7e: Ignore relations when comparing entities. This stops the refresh loop from rewriting entities over and over. + ## 0.5.0 ### Minor Changes diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index ad0a2740f7..4fad95e122 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/catalog-model", - "version": "0.5.0", + "version": "0.6.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -38,7 +38,7 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@types/express": "^4.17.6", "@types/jest": "^26.0.7", "@types/lodash": "^4.14.151", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index ddf7a7ee76..8f73247301 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/cli +## 0.4.2 + +### Patch Changes + +- c36a01b4c: Re-enable symlink resolution during bundling, and switch to using a resolve plugin for external linked packages. + ## 0.4.1 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index a71e4c8b10..c284b81e2e 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli", "description": "CLI for developing Backstage plugins and apps", - "version": "0.4.1", + "version": "0.4.2", "private": false, "publishConfig": { "access": "public" @@ -111,9 +111,9 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-common": "^0.4.0", + "@backstage/backend-common": "^0.4.1", "@backstage/config": "^0.1.2", - "@backstage/core": "^0.4.0", + "@backstage/core": "^0.4.1", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@backstage/theme": "^0.2.2", diff --git a/packages/core-api/CHANGELOG.md b/packages/core-api/CHANGELOG.md index 79aa22f481..de997bf065 100644 --- a/packages/core-api/CHANGELOG.md +++ b/packages/core-api/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/core-api +## 0.2.6 + +### Patch Changes + +- 7dd2ef7d1: Use auth provider ID to create unique session storage keys for GitHub and SAML Auth. + ## 0.2.5 ### Patch Changes diff --git a/packages/core-api/package.json b/packages/core-api/package.json index 05acadffd5..fa8bd7a086 100644 --- a/packages/core-api/package.json +++ b/packages/core-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-api", "description": "Internal Core API used by Backstage plugins and apps", - "version": "0.2.5", + "version": "0.2.6", "private": false, "publishConfig": { "access": "public", @@ -43,7 +43,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/test-utils-core": "^0.1.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index aeb1c961b7..d4eb0a0a95 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/core +## 0.4.1 + +### Patch Changes + +- 8ef71ed32: Add a `` component to `@backstage/core`. +- Updated dependencies [7dd2ef7d1] + - @backstage/core-api@0.2.6 + ## 0.4.0 ### Minor Changes diff --git a/packages/core/package.json b/packages/core/package.json index 54d4b1a267..3c636a0d80 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core", "description": "Core API used by Backstage plugins and apps", - "version": "0.4.0", + "version": "0.4.1", "private": false, "publishConfig": { "access": "public", @@ -30,7 +30,7 @@ }, "dependencies": { "@backstage/config": "^0.1.2", - "@backstage/core-api": "^0.2.5", + "@backstage/core-api": "^0.2.6", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -65,7 +65,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index b8b630d2e4..8e9b3692af 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/create-app +## 0.2.5 + +### Patch Changes + +- 2783ec018: In the techdocs-backend plugin (`packages/backend/src/plugins/techdocs.ts`), create a publisher using + + ``` + const publisher = Publisher.fromConfig(config, logger, discovery); + ``` + + instead of + + ``` + const publisher = new LocalPublish(logger, discovery); + ``` + + An instance of `publisher` can either be a local filesystem publisher or a Google Cloud Storage publisher. + + Read more about the configs here https://backstage.io/docs/features/techdocs/configuration + (You will also have to update `techdocs.storage.type` to `local` or `googleGcs`. And `techdocs.builder` to either `local` or `external`.) + ## 0.2.4 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 5b7484b575..64f7e83ae4 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/create-app", "description": "Create app package for Backstage", - "version": "0.2.4", + "version": "0.2.5", "private": false, "publishConfig": { "access": "public" @@ -37,28 +37,28 @@ "recursive-readdir": "^2.2.2" }, "devDependencies": { - "@backstage/backend-common": "^0.4.0", - "@backstage/catalog-model": "^0.5.0", - "@backstage/cli": "^0.4.1", + "@backstage/backend-common": "^0.4.1", + "@backstage/catalog-model": "^0.6.0", + "@backstage/cli": "^0.4.2", "@backstage/config": "^0.1.2", - "@backstage/core": "^0.4.0", - "@backstage/plugin-api-docs": "^0.4.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-api-docs": "^0.4.1", "@backstage/plugin-app-backend": "^0.3.3", - "@backstage/plugin-auth-backend": "^0.2.6", - "@backstage/plugin-catalog": "^0.2.6", - "@backstage/plugin-catalog-backend": "^0.4.0", - "@backstage/plugin-circleci": "^0.2.4", + "@backstage/plugin-auth-backend": "^0.2.7", + "@backstage/plugin-catalog": "^0.2.7", + "@backstage/plugin-catalog-backend": "^0.5.0", + "@backstage/plugin-circleci": "^0.2.5", "@backstage/plugin-explore": "^0.2.2", - "@backstage/plugin-github-actions": "^0.2.4", - "@backstage/plugin-lighthouse": "^0.2.5", + "@backstage/plugin-github-actions": "^0.2.5", + "@backstage/plugin-lighthouse": "^0.2.6", "@backstage/plugin-proxy-backend": "^0.2.3", - "@backstage/plugin-register-component": "^0.2.4", + "@backstage/plugin-register-component": "^0.2.5", "@backstage/plugin-rollbar-backend": "^0.1.5", - "@backstage/plugin-scaffolder": "^0.3.3", - "@backstage/plugin-scaffolder-backend": "^0.3.4", + "@backstage/plugin-scaffolder": "^0.3.4", + "@backstage/plugin-scaffolder-backend": "^0.3.5", "@backstage/plugin-tech-radar": "^0.3.1", - "@backstage/plugin-techdocs": "^0.4.0", - "@backstage/plugin-techdocs-backend": "^0.3.2", + "@backstage/plugin-techdocs": "^0.5.0", + "@backstage/plugin-techdocs-backend": "^0.4.0", "@backstage/plugin-user-settings": "^0.2.3", "@backstage/test-utils": "^0.1.5", "@backstage/theme": "^0.2.2", diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md index f080685efe..5559c5230d 100644 --- a/packages/integration/CHANGELOG.md +++ b/packages/integration/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/integration +## 0.1.4 + +### Patch Changes + +- 1d1c2860f: Implement readTree on BitBucketUrlReader and getBitbucketDownloadUrl +- 4eafdec4a: Introduce readTree method for GitLab URL Reader +- 178e09323: Validate that integration config contains a valid host + ## 0.1.3 ### Patch Changes diff --git a/packages/integration/package.json b/packages/integration/package.json index 3c241fee89..fe5bd60905 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/integration", - "version": "0.1.3", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,7 +34,7 @@ "git-url-parse": "^11.4.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/test-utils": "^0.1.5", "@types/jest": "^26.0.7", "msw": "^0.21.2" diff --git a/packages/techdocs-common/CHANGELOG.md b/packages/techdocs-common/CHANGELOG.md new file mode 100644 index 0000000000..af3da478a5 --- /dev/null +++ b/packages/techdocs-common/CHANGELOG.md @@ -0,0 +1,55 @@ +# @backstage/techdocs-common + +## 0.2.0 + +### Minor Changes + +- dae4f3983: _Breaking changes_ + + 1. Added option to use Google Cloud Storage as a choice to store the static generated files for TechDocs. + It can be configured using `techdocs.publisher.type` option in `app-config.yaml`. + Step-by-step guide to configure GCS is available here https://backstage.io/docs/features/techdocs/using-cloud-storage + Set `techdocs.publisher.type` to `'local'` if you want to continue using local filesystem to store TechDocs files. + + 2. `techdocs.builder` is now required and can be set to `'local'` or `'external'`. (Set it to `'local'` for now, since CI/CD build + workflow for TechDocs will be available soon (in few weeks)). + If builder is set to 'local' and you open a TechDocs page, `techdocs-backend` will try to generate the docs, publish to storage and + show the generated docs afterwords. + If builder is set to `'external'`, `techdocs-backend` will only fetch the docs and will NOT try to generate and publish. In this case of `'external'`, + we assume that docs are being built in the CI/CD pipeline of the repository. + TechDocs will not assume a default value for `techdocs.builder`. It is better to explicitly define it in the `app-config.yaml`. + + 3. When configuring TechDocs in your backend, there is a difference in how a new publisher is created. + + ``` + --- const publisher = new LocalPublish(logger, discovery); + +++ const publisher = Publisher.fromConfig(config, logger, discovery); + ``` + + Based on the config `techdocs.publisher.type`, the publisher could be either Local publisher or Google Cloud Storage publisher. + + 4. `techdocs.storageUrl` is now a required config. Should be `http://localhost:7000/api/techdocs/static/docs` in most setups. + + 5. Parts of `@backstage/plugin-techdocs-backend` have been moved to a new package `@backstage/techdocs-common` to generate docs. Also to publish docs + to-and-fro between TechDocs and a storage (either local or external). However, a Backstage app does NOT need to import the `techdocs-common` package - + app should only import `@backstage/plugin-techdocs` and `@backstage/plugin-techdocs-backend`. + + _Patch changes_ + + 1. See all of TechDocs config options and its documentation https://backstage.io/docs/features/techdocs/configuration + + 2. Logic about serving static files and metadata retrieval have been abstracted away from the router in `techdocs-backend` to the instance of publisher. + + 3. Removed Material UI Spinner from TechDocs header. Spinners cause unnecessary UX distraction. + Case 1 (when docs are built and are to be served): Spinners appear for a split second before the name of site shows up. This unnecessarily distracts eyes because spinners increase the size of the Header. A dot (.) would do fine. Definitely more can be done. + Case 2 (when docs are being generated): There is already a linear progress bar (which is recommended in Storybook). + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [1d1c2860f] +- Updated dependencies [0e6298f7e] +- Updated dependencies [4eafdec4a] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/backend-common@0.4.1 diff --git a/packages/techdocs-common/package.json b/packages/techdocs-common/package.json index fd767b4a64..d0c09919a0 100644 --- a/packages/techdocs-common/package.json +++ b/packages/techdocs-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/techdocs-common", "description": "Common functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", - "version": "0.1.1", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -36,8 +36,8 @@ "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/backend-common": "^0.4.0", - "@backstage/catalog-model": "^0.5.0", + "@backstage/backend-common": "^0.4.1", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", "@google-cloud/storage": "^5.6.0", "@types/dockerode": "^3.2.1", @@ -55,7 +55,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@types/fs-extra": "^9.0.5", "@types/git-url-parse": "^9.0.0", "@types/js-yaml": "^3.12.5", diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index 53e1da905b..dc1c38ef49 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-api-docs +## 0.4.1 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog@0.2.7 + ## 0.4.0 ### Minor Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 944903067b..7346722550 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-api-docs", - "version": "0.4.0", + "version": "0.4.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,9 +29,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@kyma-project/asyncapi-react": "^0.14.2", "@material-icons/font": "^1.0.2", @@ -49,7 +49,7 @@ "swagger-ui-react": "^3.37.2" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index d0e0b63706..f011d224b4 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-auth-backend +## 0.2.7 + +### Patch Changes + +- 7b15cc271: Added configuration schema for the commonly used properties +- Updated dependencies [c911061b7] +- Updated dependencies [1d1c2860f] +- Updated dependencies [0e6298f7e] +- Updated dependencies [4eafdec4a] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/backend-common@0.4.1 + - @backstage/catalog-client@0.3.4 + ## 0.2.6 ### Patch Changes diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index a31460fea0..c55d4e508f 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend", - "version": "0.2.6", + "version": "0.2.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,9 +29,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.4.0", - "@backstage/catalog-client": "^0.3.3", - "@backstage/catalog-model": "^0.5.0", + "@backstage/backend-common": "^0.4.1", + "@backstage/catalog-client": "^0.3.4", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", "@types/express": "^4.17.6", "compression": "^1.7.4", @@ -64,7 +64,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@types/body-parser": "^1.19.0", "@types/cookie-parser": "^1.4.2", "@types/express-session": "^1.17.2", diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 43a07252b8..95fea0ef3e 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,58 @@ # @backstage/plugin-catalog-backend +## 0.5.0 + +### Minor Changes + +- 6b37c95bf: Write relations directly as part of batch add / update of entities. + + Slight change of the `CommonDatabase` contract: + + ## `addEntity` removed + + This method was unused by the core, and rendered unnecessary when `addEntities` + exists. + + If you were a user of `addEntity`, please call `addEntities` instead, with an + array of one element. + + ## `DbEntityRequest` has a new field `relations` + + This is the structure that is passed to `addEntities` and `updateEntity`. It + used to be the case that you needed to call `setRelations` separately, but now + this instead happens directly when you call `addEntities` or `updateEntity`. + + If you were using `addEntities` or `updateEntity` directly, please adapt your + code to add the `relations` array to each request. If you were calling + `setRelations` separately next to these methods, you no longer need to do so, + after adding the relations to the `DbEntityRequest`s. + +- ac3560b42: Remove `implementsApis` from `Component` entities. Deprecation happened in [#3449](https://github.com/backstage/backstage/pull/3449). + Use `providesApis` instead. + +### Patch Changes + +- c6eeefa35: Add support for Github Enterprise in GitHubOrgReaderProcessor so you can properly ingest users of a GHE organization. +- fb386b760: Break the refresh loop into several smaller transactions +- 7c3ffc0cd: Support `profile` of groups including `displayName`, `email`, and `picture` in + `LdapOrgReaderProcessor`. The source fields for them can be configured in the + `ldapOrg` provider. +- e7496dc3e: Break out GithubOrgReaderProcessor config into its own file for consistency with the other org processors. +- 8dd0a906d: Support `profile` of groups including `displayName` and `picture` in + `GithubOrgReaderProcessor`. Fixes the import of `description` for groups. +- 8c31c681c: Batch the writing of statuses after refreshes. This reduced the runtime on sqlite from 16s to 0.2s, and on pg from 60s to 1s on my machine, for the huge LDAP set. +- 7b98e7fee: Add index to foreign key columns. Postgres (and others) do not do this on the "source" side of a foreign key relation, which was what led to the slowness on large datasets. The full LDAP dataset ingestion now takes two minutes, which is not optimal yet but still a huge improvement over before when it basically never finished :) +- 0097057ed: Support `profile` of groups including `displayName` and `email` in + `MicrosoftGraphOrgReaderProcessor`. Importing `picture` doesn't work yet, as + the Microsoft Graph API does not expose them correctly. +- Updated dependencies [c911061b7] +- Updated dependencies [1d1c2860f] +- Updated dependencies [0e6298f7e] +- Updated dependencies [4eafdec4a] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/backend-common@0.4.1 + ## 0.4.0 ### Minor Changes diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 180956c986..d3500263ca 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend", - "version": "0.4.0", + "version": "0.5.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,8 +30,8 @@ }, "dependencies": { "@azure/msal-node": "^1.0.0-alpha.8", - "@backstage/backend-common": "^0.4.0", - "@backstage/catalog-model": "^0.5.0", + "@backstage/backend-common": "^0.4.1", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", "@octokit/graphql": "^4.5.6", "@types/express": "^4.17.6", @@ -57,7 +57,7 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/test-utils": "^0.1.5", "@types/core-js": "^2.5.4", "@types/git-url-parse": "^9.0.0", diff --git a/plugins/catalog-graphql/CHANGELOG.md b/plugins/catalog-graphql/CHANGELOG.md index 7cef0b765a..ceee335db0 100644 --- a/plugins/catalog-graphql/CHANGELOG.md +++ b/plugins/catalog-graphql/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-graphql +## 0.2.5 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [1d1c2860f] +- Updated dependencies [0e6298f7e] +- Updated dependencies [4eafdec4a] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/backend-common@0.4.1 + ## 0.2.4 ### Patch Changes diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index fa6bd7c4d4..fb013f53c3 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graphql", - "version": "0.2.4", + "version": "0.2.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,8 +30,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.4.0", - "@backstage/catalog-model": "^0.5.0", + "@backstage/backend-common": "^0.4.1", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", "@graphql-modules/core": "^0.7.17", "apollo-server": "^2.16.1", @@ -42,7 +42,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/test-utils": "^0.1.5", "@graphql-codegen/cli": "^1.17.7", "@graphql-codegen/typescript": "^1.17.7", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index bc86a6ac0c..a7301e43a3 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-catalog-import +## 0.3.2 + +### Patch Changes + +- f3e75508d: Add description to Pull Request when registering a new component +- Updated dependencies [c6eeefa35] +- Updated dependencies [fb386b760] +- Updated dependencies [c911061b7] +- Updated dependencies [7c3ffc0cd] +- Updated dependencies [e7496dc3e] +- Updated dependencies [8ef71ed32] +- Updated dependencies [1d1c2860f] +- Updated dependencies [0e6298f7e] +- Updated dependencies [8dd0a906d] +- Updated dependencies [4eafdec4a] +- Updated dependencies [6b37c95bf] +- Updated dependencies [8c31c681c] +- Updated dependencies [7b98e7fee] +- Updated dependencies [178e09323] +- Updated dependencies [ac3560b42] +- Updated dependencies [0097057ed] + - @backstage/plugin-catalog-backend@0.5.0 + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/integration@0.1.4 + - @backstage/plugin-catalog@0.2.7 + ## 0.3.1 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index e2ddf0101e..25010268f9 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-import", - "version": "0.3.1", + "version": "0.3.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,11 +30,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", - "@backstage/plugin-catalog-backend": "^0.4.0", - "@backstage/integration": "^0.1.3", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", + "@backstage/plugin-catalog-backend": "^0.5.0", + "@backstage/integration": "^0.1.4", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -50,7 +50,7 @@ "yaml": "^1.10.0" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index e47808bfa0..73f38582ff 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog +## 0.2.7 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [dae4f3983] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/plugin-techdocs@0.5.0 + - @backstage/core@0.4.1 + - @backstage/catalog-client@0.3.4 + - @backstage/plugin-scaffolder@0.3.4 + ## 0.2.6 ### Patch Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 924115eb82..142ef4a1e6 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog", - "version": "0.2.6", + "version": "0.2.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,11 +30,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-client": "^0.3.3", - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-scaffolder": "^0.3.3", - "@backstage/plugin-techdocs": "^0.4.0", + "@backstage/catalog-client": "^0.3.4", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-scaffolder": "^0.3.4", + "@backstage/plugin-techdocs": "^0.5.0", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -52,7 +52,7 @@ "swr": "^0.3.0" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@microsoft/microsoft-graph-types": "^1.25.0", diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md index dc3bf0d5ca..240ea488a7 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-circleci +## 0.2.5 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog@0.2.7 + ## 0.2.4 ### Patch Changes diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 76fc13df52..d52e5d7414 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-circleci", - "version": "0.2.4", + "version": "0.2.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,9 +31,9 @@ "postpack": "backstage-cli postpack" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -50,7 +50,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md index f2a636cc4c..64e1fe2937 100644 --- a/plugins/cloudbuild/CHANGELOG.md +++ b/plugins/cloudbuild/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-cloudbuild +## 0.2.5 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog@0.2.7 + ## 0.2.4 ### Patch Changes diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index dd040c6cea..80e7404831 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-cloudbuild", - "version": "0.2.4", + "version": "0.2.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,9 +30,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -49,7 +49,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index 0524f66e69..e664883910 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-cost-insights +## 0.5.2 + +### Patch Changes + +- 48c305e69: pin all projects selection to the top of menu list +- Updated dependencies [8ef71ed32] + - @backstage/core@0.4.1 + ## 0.5.1 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 2ff9ab7d1d..d03d698a69 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-cost-insights", - "version": "0.5.1", + "version": "0.5.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,7 +31,7 @@ }, "dependencies": { "@backstage/config": "^0.1.2", - "@backstage/core": "^0.4.0", + "@backstage/core": "^0.4.1", "@backstage/test-utils": "^0.1.5", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", @@ -56,7 +56,7 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index e9edcf76c3..d51c9bd489 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-github-actions +## 0.2.5 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [7dd2ef7d1] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/core-api@0.2.6 + - @backstage/plugin-catalog@0.2.7 + ## 0.2.4 ### Patch Changes diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 6c01a592d8..cfa30bfd77 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-actions", - "version": "0.2.4", + "version": "0.2.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,10 +32,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/core-api": "^0.2.5", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/core-api": "^0.2.6", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -51,7 +51,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/jenkins/CHANGELOG.md b/plugins/jenkins/CHANGELOG.md index c922be67b2..78792789cf 100644 --- a/plugins/jenkins/CHANGELOG.md +++ b/plugins/jenkins/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-jenkins +## 0.3.4 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog@0.2.7 + ## 0.3.3 ### Patch Changes diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index f6c6466236..4c3799d550 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-jenkins", - "version": "0.3.3", + "version": "0.3.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,9 +31,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -46,7 +46,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index b97bc82242..9b247c174f 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-kubernetes-backend +## 0.2.3 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [1d1c2860f] +- Updated dependencies [0e6298f7e] +- Updated dependencies [4eafdec4a] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/backend-common@0.4.1 + ## 0.2.2 ### Patch Changes diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 2a6f56ef33..66a36f8395 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-backend", - "version": "0.2.2", + "version": "0.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,8 +31,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.4.0", - "@backstage/catalog-model": "^0.5.0", + "@backstage/backend-common": "^0.4.1", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", "@kubernetes/client-node": "^0.12.1", "@types/express": "^4.17.6", @@ -49,7 +49,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "supertest": "^4.0.2" }, "files": [ diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index 7ad72103a3..ef5b51cfb9 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-kubernetes +## 0.3.3 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-kubernetes-backend@0.2.3 + ## 0.3.2 ### Patch Changes diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index a7b6da2ce3..649df8353f 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes", - "version": "0.3.2", + "version": "0.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,10 +31,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", - "@backstage/core": "^0.4.0", - "@backstage/plugin-kubernetes-backend": "^0.2.2", + "@backstage/core": "^0.4.1", + "@backstage/plugin-kubernetes-backend": "^0.2.3", "@backstage/theme": "^0.2.2", "@kubernetes/client-node": "^0.12.1", "@material-ui/core": "^4.11.0", @@ -46,7 +46,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md index 3d1d1a491d..42035d1209 100644 --- a/plugins/lighthouse/CHANGELOG.md +++ b/plugins/lighthouse/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-lighthouse +## 0.2.6 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [7dd2ef7d1] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/core-api@0.2.6 + - @backstage/plugin-catalog@0.2.7 + ## 0.2.5 ### Patch Changes diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index 6a5082fcab..93c4d53c21 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-lighthouse", - "version": "0.2.5", + "version": "0.2.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,11 +31,11 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", - "@backstage/core": "^0.4.0", - "@backstage/core-api": "^0.2.5", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/core": "^0.4.1", + "@backstage/core-api": "^0.2.6", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -47,7 +47,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index 541c11b35b..13025d8e83 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-org +## 0.3.2 + +### Patch Changes + +- c0fac6163: Wrap entity cards on smaller screens +- ab805860a: Ensure a name is always displayed for user entities in the org plugin. This can happen when there is no profile + displayName provided (e.g. a GitHub user that has not added a name to their profile) +- 8ef71ed32: Add a `` component to `@backstage/core`. +- c5297baeb: Display the new `profile` fields (`displayName`, `email`, and `picture`) for + groups on the `GroupProfileCard`. + + This also resolves some cases where `profile` fields are missing for users or + groups and for example falls back to displaying the entity name. Adds additional test data to the ACME Corp dataset. + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog@0.2.7 + ## 0.3.1 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index 010fad775e..c81b44756e 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-org", - "version": "0.3.1", + "version": "0.3.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,9 +20,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -33,7 +33,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index d4a5439072..efcd8fbe37 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-pagerduty +## 0.2.3 + +### Patch Changes + +- 3b50f833d: Supporting Timezones +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + ## 0.2.2 ### Patch Changes diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index e1db22c0cd..aa6da07a02 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-pagerduty", - "version": "0.2.2", + "version": "0.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,8 +30,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -44,7 +44,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/register-component/CHANGELOG.md b/plugins/register-component/CHANGELOG.md index 2f4fe297db..488d45ec0e 100644 --- a/plugins/register-component/CHANGELOG.md +++ b/plugins/register-component/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-register-component +## 0.2.5 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog@0.2.7 + ## 0.2.4 ### Patch Changes diff --git a/plugins/register-component/package.json b/plugins/register-component/package.json index 08b56a8c05..bca520b5bc 100644 --- a/plugins/register-component/package.json +++ b/plugins/register-component/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-register-component", - "version": "0.2.4", + "version": "0.2.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,9 +30,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -45,7 +45,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md index 50ed3e75b1..aaa7e704d9 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-rollbar +## 0.2.7 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog@0.2.7 + ## 0.2.6 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 7a479deba3..ff60787109 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-rollbar", - "version": "0.2.6", + "version": "0.2.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,9 +31,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -47,7 +47,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index 2962476b72..b8585e0aec 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-scaffolder-backend +## 0.3.5 + +### Patch Changes + +- 94c65a9d4: Added configuration schema for the commonly used properties +- Updated dependencies [c911061b7] +- Updated dependencies [1d1c2860f] +- Updated dependencies [0e6298f7e] +- Updated dependencies [4eafdec4a] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/backend-common@0.4.1 + ## 0.3.4 ### Patch Changes diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 50bddaaf41..d5f5a5c56b 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend", - "version": "0.3.4", + "version": "0.3.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,8 +29,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.4.0", - "@backstage/catalog-model": "^0.5.0", + "@backstage/backend-common": "^0.4.1", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", "@gitbeaker/core": "^25.2.0", "@gitbeaker/node": "^25.2.0", @@ -57,7 +57,7 @@ "cross-fetch": "^3.0.6" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@octokit/types": "^5.4.1", "@types/fs-extra": "^9.0.1", "@types/git-url-parse": "^9.0.0", diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index 08915241e0..f7d68369ae 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-scaffolder +## 0.3.4 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog@0.2.7 + ## 0.3.3 ### Patch Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 6c802d8130..6b3c64c26d 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder", - "version": "0.3.3", + "version": "0.3.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,9 +30,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -50,7 +50,7 @@ "swr": "^0.3.0" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index f00437b19a..f85c13b47c 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-search +## 0.2.4 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + - @backstage/plugin-catalog@0.2.7 + ## 0.2.3 ### Patch Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index ffafbafbbd..a66a9ba323 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search", - "version": "0.2.3", + "version": "0.2.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,9 +29,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.4.0", - "@backstage/plugin-catalog": "^0.2.6", - "@backstage/catalog-model": "^0.5.0", + "@backstage/core": "^0.4.1", + "@backstage/plugin-catalog": "^0.2.7", + "@backstage/catalog-model": "^0.6.0", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -43,7 +43,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index 862dfd30eb..f5b5f5efd8 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-sentry +## 0.3.1 + +### Patch Changes + +- 962d1ad66: Added configuration schema for the commonly used properties +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + ## 0.3.0 ### Minor Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index 7b4ca9f083..404ff90f34 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sentry", - "version": "0.3.0", + "version": "0.3.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,8 +31,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -45,7 +45,7 @@ "timeago.js": "^4.0.2" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index bccff558c8..62f9d857a7 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-sonarqube +## 0.1.7 + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/core@0.4.1 + ## 0.1.6 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index 7d9467b42b..c5d6433871 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube", - "version": "0.1.6", + "version": "0.1.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,8 +32,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -46,7 +46,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index 92901f7e42..9d57ebc481 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,61 @@ # @backstage/plugin-techdocs-backend +## 0.4.0 + +### Minor Changes + +- dae4f3983: _Breaking changes_ + + 1. Added option to use Google Cloud Storage as a choice to store the static generated files for TechDocs. + It can be configured using `techdocs.publisher.type` option in `app-config.yaml`. + Step-by-step guide to configure GCS is available here https://backstage.io/docs/features/techdocs/using-cloud-storage + Set `techdocs.publisher.type` to `'local'` if you want to continue using local filesystem to store TechDocs files. + + 2. `techdocs.builder` is now required and can be set to `'local'` or `'external'`. (Set it to `'local'` for now, since CI/CD build + workflow for TechDocs will be available soon (in few weeks)). + If builder is set to 'local' and you open a TechDocs page, `techdocs-backend` will try to generate the docs, publish to storage and + show the generated docs afterwords. + If builder is set to `'external'`, `techdocs-backend` will only fetch the docs and will NOT try to generate and publish. In this case of `'external'`, + we assume that docs are being built in the CI/CD pipeline of the repository. + TechDocs will not assume a default value for `techdocs.builder`. It is better to explicitly define it in the `app-config.yaml`. + + 3. When configuring TechDocs in your backend, there is a difference in how a new publisher is created. + + ``` + --- const publisher = new LocalPublish(logger, discovery); + +++ const publisher = Publisher.fromConfig(config, logger, discovery); + ``` + + Based on the config `techdocs.publisher.type`, the publisher could be either Local publisher or Google Cloud Storage publisher. + + 4. `techdocs.storageUrl` is now a required config. Should be `http://localhost:7000/api/techdocs/static/docs` in most setups. + + 5. Parts of `@backstage/plugin-techdocs-backend` have been moved to a new package `@backstage/techdocs-common` to generate docs. Also to publish docs + to-and-fro between TechDocs and a storage (either local or external). However, a Backstage app does NOT need to import the `techdocs-common` package - + app should only import `@backstage/plugin-techdocs` and `@backstage/plugin-techdocs-backend`. + + _Patch changes_ + + 1. See all of TechDocs config options and its documentation https://backstage.io/docs/features/techdocs/configuration + + 2. Logic about serving static files and metadata retrieval have been abstracted away from the router in `techdocs-backend` to the instance of publisher. + + 3. Removed Material UI Spinner from TechDocs header. Spinners cause unnecessary UX distraction. + Case 1 (when docs are built and are to be served): Spinners appear for a split second before the name of site shows up. This unnecessarily distracts eyes because spinners increase the size of the Header. A dot (.) would do fine. Definitely more can be done. + Case 2 (when docs are being generated): There is already a linear progress bar (which is recommended in Storybook). + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [dae4f3983] +- Updated dependencies [1d1c2860f] +- Updated dependencies [0e6298f7e] +- Updated dependencies [4eafdec4a] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/techdocs-common@0.2.0 + - @backstage/backend-common@0.4.1 + ## 0.3.2 ### Patch Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index fc11122ead..5552d87f3f 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-backend", - "version": "0.3.2", + "version": "0.4.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,10 +30,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.4.0", - "@backstage/catalog-model": "^0.5.0", + "@backstage/backend-common": "^0.4.1", + "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", - "@backstage/techdocs-common": "^0.1.1", + "@backstage/techdocs-common": "^0.2.0", "@types/dockerode": "^3.2.1", "@types/express": "^4.17.6", "cross-fetch": "^3.0.6", @@ -44,7 +44,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "supertest": "^4.0.2" }, "files": [ diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 26ee57fb86..d7bb8506b2 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,63 @@ # @backstage/plugin-techdocs +## 0.5.0 + +### Minor Changes + +- dae4f3983: _Breaking changes_ + + 1. Added option to use Google Cloud Storage as a choice to store the static generated files for TechDocs. + It can be configured using `techdocs.publisher.type` option in `app-config.yaml`. + Step-by-step guide to configure GCS is available here https://backstage.io/docs/features/techdocs/using-cloud-storage + Set `techdocs.publisher.type` to `'local'` if you want to continue using local filesystem to store TechDocs files. + + 2. `techdocs.builder` is now required and can be set to `'local'` or `'external'`. (Set it to `'local'` for now, since CI/CD build + workflow for TechDocs will be available soon (in few weeks)). + If builder is set to 'local' and you open a TechDocs page, `techdocs-backend` will try to generate the docs, publish to storage and + show the generated docs afterwords. + If builder is set to `'external'`, `techdocs-backend` will only fetch the docs and will NOT try to generate and publish. In this case of `'external'`, + we assume that docs are being built in the CI/CD pipeline of the repository. + TechDocs will not assume a default value for `techdocs.builder`. It is better to explicitly define it in the `app-config.yaml`. + + 3. When configuring TechDocs in your backend, there is a difference in how a new publisher is created. + + ``` + --- const publisher = new LocalPublish(logger, discovery); + +++ const publisher = Publisher.fromConfig(config, logger, discovery); + ``` + + Based on the config `techdocs.publisher.type`, the publisher could be either Local publisher or Google Cloud Storage publisher. + + 4. `techdocs.storageUrl` is now a required config. Should be `http://localhost:7000/api/techdocs/static/docs` in most setups. + + 5. Parts of `@backstage/plugin-techdocs-backend` have been moved to a new package `@backstage/techdocs-common` to generate docs. Also to publish docs + to-and-fro between TechDocs and a storage (either local or external). However, a Backstage app does NOT need to import the `techdocs-common` package - + app should only import `@backstage/plugin-techdocs` and `@backstage/plugin-techdocs-backend`. + + _Patch changes_ + + 1. See all of TechDocs config options and its documentation https://backstage.io/docs/features/techdocs/configuration + + 2. Logic about serving static files and metadata retrieval have been abstracted away from the router in `techdocs-backend` to the instance of publisher. + + 3. Removed Material UI Spinner from TechDocs header. Spinners cause unnecessary UX distraction. + Case 1 (when docs are built and are to be served): Spinners appear for a split second before the name of site shows up. This unnecessarily distracts eyes because spinners increase the size of the Header. A dot (.) would do fine. Definitely more can be done. + Case 2 (when docs are being generated): There is already a linear progress bar (which is recommended in Storybook). + +### Patch Changes + +- Updated dependencies [c911061b7] +- Updated dependencies [dae4f3983] +- Updated dependencies [8ef71ed32] +- Updated dependencies [0e6298f7e] +- Updated dependencies [7dd2ef7d1] +- Updated dependencies [ac3560b42] + - @backstage/catalog-model@0.6.0 + - @backstage/techdocs-common@0.2.0 + - @backstage/core@0.4.1 + - @backstage/core-api@0.2.6 + - @backstage/plugin-catalog@0.2.7 + ## 0.4.0 ### Minor Changes diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 15325ed7bc..361825e71a 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs", - "version": "0.4.0", + "version": "0.5.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,13 +31,13 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.5.0", - "@backstage/core": "^0.4.0", - "@backstage/core-api": "^0.2.5", - "@backstage/plugin-catalog": "^0.2.6", + "@backstage/catalog-model": "^0.6.0", + "@backstage/core": "^0.4.1", + "@backstage/core-api": "^0.2.6", + "@backstage/plugin-catalog": "^0.2.7", "@backstage/test-utils": "^0.1.5", "@backstage/theme": "^0.2.2", - "@backstage/techdocs-common": "^0.1.1", + "@backstage/techdocs-common": "^0.2.0", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -50,7 +50,7 @@ "sanitize-html": "^1.27.0" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", From 606b988cd937a269dd708427ade9d01c6784b6d2 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 17 Dec 2020 11:51:43 +0100 Subject: [PATCH 72/98] bump some packages --- plugins/explore/package.json | 4 ++-- plugins/gcp-projects/package.json | 4 ++-- plugins/gitops-profiles/package.json | 4 ++-- plugins/graphiql/package.json | 4 ++-- plugins/newrelic/package.json | 4 ++-- plugins/tech-radar/package.json | 4 ++-- plugins/user-settings/package.json | 4 ++-- plugins/welcome/package.json | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 0b4b35e0cd..4ba7d93887 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -30,7 +30,7 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core": "^0.4.0", + "@backstage/core": "^0.4.1", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -42,7 +42,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 35852458bf..9de4a38d1d 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -30,7 +30,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.4.0", + "@backstage/core": "^0.4.1", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -41,7 +41,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index 4422aab210..86a7befc77 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.4.0", + "@backstage/core": "^0.4.1", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -42,7 +42,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 367258b7f7..b6e7ca72ed 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.4.0", + "@backstage/core": "^0.4.1", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -43,7 +43,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 05995acafd..2984bba457 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.4.0", + "@backstage/core": "^0.4.1", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -41,7 +41,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index f10eef259d..471f195381 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -30,7 +30,7 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core": "^0.4.0", + "@backstage/core": "^0.4.1", "@backstage/test-utils": "^0.1.5", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", @@ -44,7 +44,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 57aff26d27..fed2b4d3f7 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -30,7 +30,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.4.0", + "@backstage/core": "^0.4.1", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -41,7 +41,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/welcome/package.json b/plugins/welcome/package.json index d61935ef6e..b8658ea2f8 100644 --- a/plugins/welcome/package.json +++ b/plugins/welcome/package.json @@ -30,7 +30,7 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core": "^0.4.0", + "@backstage/core": "^0.4.1", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -41,7 +41,7 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.2", "@backstage/dev-utils": "^0.1.6", "@backstage/test-utils": "^0.1.5", "@testing-library/jest-dom": "^5.10.1", From e1335a221fcedb59beb851bfa7174035776da330 Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Thu, 17 Dec 2020 11:58:11 +0100 Subject: [PATCH 73/98] docs: Add integration and techdocs-common to project structure --- docs/support/project-structure.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/support/project-structure.md b/docs/support/project-structure.md index 190259841c..bbba127c9a 100644 --- a/docs/support/project-structure.md +++ b/docs/support/project-structure.md @@ -169,11 +169,19 @@ are separated out into their own folder, see further down. packages, publish them, created a new app, and the run it. CI uses this for e2e-tests. +- [`integration/`](https://github.com/backstage/backstage/tree/master/packages/integration) - + Common functionalities of integrations like GitHub, GitLab, etc. + - [`storybook/`](https://github.com/backstage/backstage/tree/master/packages/storybook) - This folder contains only the storybook config. Stories are within the core package. The Backstage Storybook is found [here](https://backstage.io/storybook) +- [`techdocs-common/`](https://github.com/backstage/backstage/tree/master/packages/techdocs-common) - + Common functionalities for TechDocs, to be shared between + [techdocs-backend](https://github.com/backstage/backstage/tree/master/plugins/techdocs-backend) + plugin and [techdocs-cli](https://github.com/backstage/techdocs-cli). + - [`test-utils-core/`](https://github.com/backstage/backstage/tree/master/packages/test-utils-core) - [`test-utils/`](https://github.com/backstage/backstage/tree/master/packages/test-utils) From e2aa76f19b4dcdc673cfe343011587faa3e51fc8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 2 Dec 2020 11:43:30 +0100 Subject: [PATCH 74/98] core-api: initial implementation of external route refs Co-authored-by: blam --- packages/core-api/src/routing/RouteRef.ts | 10 ++++++ packages/core-api/src/routing/hooks.test.tsx | 37 +++++++++++++++++--- packages/core-api/src/routing/hooks.tsx | 19 ++++++++-- 3 files changed, 59 insertions(+), 7 deletions(-) diff --git a/packages/core-api/src/routing/RouteRef.ts b/packages/core-api/src/routing/RouteRef.ts index 0fbc57c6f1..c7db48045a 100644 --- a/packages/core-api/src/routing/RouteRef.ts +++ b/packages/core-api/src/routing/RouteRef.ts @@ -53,3 +53,13 @@ export function createRouteRef< >(config: RouteRefConfig): RouteRef { return new AbsoluteRouteRef(config); } + +export class ExternalRouteRef { + toString() { + return `externalRouteRef{}`; + } +} + +export function createExternalRouteRef(): ExternalRouteRef { + return new ExternalRouteRef(); +} diff --git a/packages/core-api/src/routing/hooks.test.tsx b/packages/core-api/src/routing/hooks.test.tsx index ae1053b58d..6bc80b7c08 100644 --- a/packages/core-api/src/routing/hooks.test.tsx +++ b/packages/core-api/src/routing/hooks.test.tsx @@ -35,7 +35,11 @@ import { validateRoutes, RouteFunc, } from './hooks'; -import { createRouteRef } from './RouteRef'; +import { + createRouteRef, + createExternalRouteRef, + ExternalRouteRef, +} from './RouteRef'; import { RouteRef, RouteRefConfig } from './types'; const mockConfig = (extra?: Partial>) => ({ @@ -52,10 +56,13 @@ const ref2 = createRouteRef(mockConfig({ path: '/wat2' })); const ref3 = createRouteRef(mockConfig({ path: '/wat3' })); const ref4 = createRouteRef(mockConfig({ path: '/wat4' })); const ref5 = createRouteRef(mockConfig({ path: '/wat5' })); +const eRefA = createExternalRouteRef(); +const eRefB = createExternalRouteRef(); +const eRefC = createExternalRouteRef(); const MockRouteSource = (props: { name: string; - routeRef: RouteRef; + routeRef: RouteRef | ExternalRouteRef; params?: T; }) => { try { @@ -90,7 +97,10 @@ const Extension5 = plugin.provide( createRoutableExtension({ component: MockComponent, mountPoint: ref5 }), ); -function withRoutingProvider(root: ReactElement) { +function withRoutingProvider( + root: ReactElement, + routeBindings: [ExternalRouteRef, RouteRef][] = [], +) { const { routePaths, routeParents, routeObjects } = traverseElementTree({ root, discoverers: [childDiscoverer, routeElementDiscoverer], @@ -106,6 +116,7 @@ function withRoutingProvider(root: ReactElement) { routePaths={routePaths} routeParents={routeParents} routeObjects={routeObjects} + routeBindings={new Map(routeBindings)} > {root} @@ -119,17 +130,35 @@ describe('discovery', () => { + + + ); - const rendered = render(withRoutingProvider(root)); + const rendered = render( + withRoutingProvider(root, [ + [eRefA, ref3], + [eRefB, ref1], + [eRefC, ref2], + ]), + ); expect(rendered.getByText('Path at inside: /foo/bar')).toBeInTheDocument(); + expect( + rendered.getByText('Path at insideExternal: /baz'), + ).toBeInTheDocument(); expect(rendered.getByText('Path at outside: /foo/bar')).toBeInTheDocument(); + expect( + rendered.getByText('Path at outsideExternal1: /foo'), + ).toBeInTheDocument(); + expect( + rendered.getByText('Path at outsideExternal2: /foo/bar'), + ).toBeInTheDocument(); }); it('should handle routeRefs with parameters', () => { diff --git a/packages/core-api/src/routing/hooks.tsx b/packages/core-api/src/routing/hooks.tsx index 563bc84a76..55fde89de2 100644 --- a/packages/core-api/src/routing/hooks.tsx +++ b/packages/core-api/src/routing/hooks.tsx @@ -17,6 +17,7 @@ import React, { createContext, ReactNode, useContext, useMemo } from 'react'; import { AnyRouteRef, BackstageRouteObject, RouteRef } from './types'; import { generatePath, matchRoutes, useLocation } from 'react-router-dom'; +import { ExternalRouteRef } from './RouteRef'; // The extra TS magic here is to require a single params argument if the RouteRef // had at least one param defined, but require 0 arguments if there are no params defined. @@ -34,12 +35,17 @@ class RouteResolver { private readonly routePaths: Map, private readonly routeParents: Map, private readonly routeObjects: BackstageRouteObject[], + private readonly routeBindings: Map, ) {} resolve( - routeRef: RouteRef, + routeRefOrExternalRouteRef: RouteRef | ExternalRouteRef, sourceLocation: ReturnType, ): RouteFunc { + const routeRef = + this.routeBindings.get(routeRefOrExternalRouteRef) ?? + (routeRefOrExternalRouteRef as RouteRef); + const match = matchRoutes(this.routeObjects, sourceLocation) ?? []; const lastPath = this.routePaths.get(routeRef); @@ -106,7 +112,7 @@ class RouteResolver { const RoutingContext = createContext(undefined); export function useRouteRef( - routeRef: RouteRef, + routeRef: RouteRef | ExternalRouteRef, ): RouteFunc { const sourceLocation = useLocation(); const resolver = useContext(RoutingContext); @@ -126,6 +132,7 @@ type ProviderProps = { routePaths: Map; routeParents: Map; routeObjects: BackstageRouteObject[]; + routeBindings: Map; children: ReactNode; }; @@ -133,9 +140,15 @@ export const RoutingProvider = ({ routePaths, routeParents, routeObjects, + routeBindings, children, }: ProviderProps) => { - const resolver = new RouteResolver(routePaths, routeParents, routeObjects); + const resolver = new RouteResolver( + routePaths, + routeParents, + routeObjects, + routeBindings, + ); return ( {children} From c78bc66cfba1954a27a46fcf5e680116b12eb7b5 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 2 Dec 2020 18:31:59 +0100 Subject: [PATCH 75/98] core-api: add routes and externalRoutes to plugin interface Co-authored-by: blam --- packages/core-api/src/app/App.tsx | 6 ++--- packages/core-api/src/app/types.ts | 4 ++-- .../core-api/src/extensions/extensions.tsx | 2 +- packages/core-api/src/plugin/Plugin.tsx | 24 ++++++++++++++++--- packages/core-api/src/plugin/collectors.ts | 7 ++++-- packages/core-api/src/plugin/types.ts | 21 +++++++++++++--- 6 files changed, 50 insertions(+), 14 deletions(-) diff --git a/packages/core-api/src/app/App.tsx b/packages/core-api/src/app/App.tsx index 3ca91966bf..b42278e4a6 100644 --- a/packages/core-api/src/app/App.tsx +++ b/packages/core-api/src/app/App.tsx @@ -59,7 +59,7 @@ import { ApiResolver, ApiFactoryRegistry } from '../apis/system'; type FullAppOptions = { apis: Iterable; icons: SystemIcons; - plugins: BackstagePlugin[]; + plugins: BackstagePlugin[]; components: AppComponents; themes: AppTheme[]; configLoader?: AppConfigLoader; @@ -107,7 +107,7 @@ export class PrivateAppImpl implements BackstageApp { private readonly apis: Iterable; private readonly icons: SystemIcons; - private readonly plugins: BackstagePlugin[]; + private readonly plugins: BackstagePlugin[]; private readonly components: AppComponents; private readonly themes: AppTheme[]; private readonly configLoader?: AppConfigLoader; @@ -125,7 +125,7 @@ export class PrivateAppImpl implements BackstageApp { this.defaultApis = options.defaultApis; } - getPlugins(): BackstagePlugin[] { + getPlugins(): BackstagePlugin[] { return this.plugins; } diff --git a/packages/core-api/src/app/types.ts b/packages/core-api/src/app/types.ts index 8a1eb92e8e..aa432bd005 100644 --- a/packages/core-api/src/app/types.ts +++ b/packages/core-api/src/app/types.ts @@ -93,7 +93,7 @@ export type AppOptions = { /** * A list of all plugins to include in the app. */ - plugins?: BackstagePlugin[]; + plugins?: BackstagePlugin[]; /** * Supply components to the app to override the default ones. @@ -140,7 +140,7 @@ export type BackstageApp = { /** * Returns all plugins registered for the app. */ - getPlugins(): BackstagePlugin[]; + getPlugins(): BackstagePlugin[]; /** * Get a common icon for this app. diff --git a/packages/core-api/src/extensions/extensions.tsx b/packages/core-api/src/extensions/extensions.tsx index 4087d5f963..079fec4597 100644 --- a/packages/core-api/src/extensions/extensions.tsx +++ b/packages/core-api/src/extensions/extensions.tsx @@ -54,7 +54,7 @@ export function createReactExtension(options: { }): Extension> { const { component: Component, data = {} } = options; return { - expose(plugin: BackstagePlugin): NamedExoticComponent { + expose(plugin: BackstagePlugin): NamedExoticComponent { const Result = (props: Props) => ; attachComponentData(Result, 'core.plugin', plugin); diff --git a/packages/core-api/src/plugin/Plugin.tsx b/packages/core-api/src/plugin/Plugin.tsx index f477674f4d..797dcd852e 100644 --- a/packages/core-api/src/plugin/Plugin.tsx +++ b/packages/core-api/src/plugin/Plugin.tsx @@ -19,13 +19,18 @@ import { PluginOutput, BackstagePlugin, Extension, + AnyRoutes, + AnyExternalRoutes, } from './types'; import { AnyApiFactory } from '../apis'; -export class PluginImpl implements BackstagePlugin { +export class PluginImpl< + Routes extends AnyRoutes, + ExternalRoutes extends AnyExternalRoutes +> implements BackstagePlugin { private storedOutput?: PluginOutput[]; - constructor(private readonly config: PluginConfig) {} + constructor(private readonly config: PluginConfig) {} getId(): string { return this.config.id; @@ -35,6 +40,14 @@ export class PluginImpl implements BackstagePlugin { return this.config.apis ?? []; } + get routes(): Routes { + return this.config.routes ?? ({} as Routes); + } + + get externalRoutes(): ExternalRoutes { + return this.config.externalRoutes ?? ({} as ExternalRoutes); + } + output(): PluginOutput[] { if (this.storedOutput) { return this.storedOutput; @@ -79,6 +92,11 @@ export class PluginImpl implements BackstagePlugin { } } -export function createPlugin(config: PluginConfig): BackstagePlugin { +export function createPlugin< + Routes extends AnyRoutes, + ExternalRoutes extends AnyExternalRoutes +>( + config: PluginConfig, +): BackstagePlugin { return new PluginImpl(config); } diff --git a/packages/core-api/src/plugin/collectors.ts b/packages/core-api/src/plugin/collectors.ts index 3eadfc0185..b04c7b41c4 100644 --- a/packages/core-api/src/plugin/collectors.ts +++ b/packages/core-api/src/plugin/collectors.ts @@ -34,9 +34,12 @@ import { getComponentData } from '../extensions'; import { createCollector } from '../extensions/traversal'; export const pluginCollector = createCollector( - () => new Set(), + () => new Set>(), (acc, node) => { - const plugin = getComponentData(node, 'core.plugin'); + const plugin = getComponentData>( + node, + 'core.plugin', + ); if (plugin) { acc.add(plugin); } diff --git a/packages/core-api/src/plugin/types.ts b/packages/core-api/src/plugin/types.ts index dd19948a0a..e3f2e38972 100644 --- a/packages/core-api/src/plugin/types.ts +++ b/packages/core-api/src/plugin/types.ts @@ -17,6 +17,7 @@ import { ComponentType } from 'react'; import { RouteRef } from '../routing'; import { AnyApiFactory } from '../apis/system'; +import { ExternalRouteRef } from '../routing/RouteRef'; export type RouteOptions = { // Whether the route path must match exactly, defaults to true. @@ -67,20 +68,34 @@ export type PluginOutput = | FeatureFlagOutput; export type Extension = { - expose(plugin: BackstagePlugin): T; + expose(plugin: BackstagePlugin): T; }; -export type BackstagePlugin = { +export type AnyRoutes = { [name: string]: RouteRef }; + +export type AnyExternalRoutes = { [name: string]: ExternalRouteRef }; + +export type BackstagePlugin< + Routes extends AnyRoutes, + ExternalRoutes extends AnyExternalRoutes +> = { getId(): string; output(): PluginOutput[]; getApis(): Iterable; provide(extension: Extension): T; + routes: Routes; + externalRoutes: ExternalRoutes; }; -export type PluginConfig = { +export type PluginConfig< + Routes extends AnyRoutes, + ExternalRoutes extends AnyExternalRoutes +> = { id: string; apis?: Iterable; register?(hooks: PluginHooks): void; + routes?: Routes; + externalRoutes?: ExternalRoutes; }; export type PluginHooks = { From ad5eab923cb1cb2aa7b00e121e5664aa38064f4e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 3 Dec 2020 10:43:20 +0100 Subject: [PATCH 76/98] core-api: add unused optional bindRoutes method to AppOptions --- packages/core-api/src/app/types.ts | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/packages/core-api/src/app/types.ts b/packages/core-api/src/app/types.ts index aa432bd005..d121a2e2a0 100644 --- a/packages/core-api/src/app/types.ts +++ b/packages/core-api/src/app/types.ts @@ -16,7 +16,8 @@ import { ComponentType } from 'react'; import { IconComponent, SystemIconKey, SystemIcons } from '../icons'; -import { BackstagePlugin } from '../plugin'; +import { BackstagePlugin, AnyExternalRoutes } from '../plugin'; +import { RouteRef } from '../routing'; import { AnyApiFactory } from '../apis'; import { AppTheme, ProfileInfo } from '../apis/definitions'; import { AppConfig } from '@backstage/config'; @@ -78,6 +79,11 @@ export type AppComponents = { */ export type AppConfigLoader = () => Promise; +type BindRouteFunc = ( + externalRoutes: T, + targetRoutes: { [key in keyof T]: RouteRef }, +) => void; + export type AppOptions = { /** * A collection of ApiFactories to register in the application to either @@ -134,6 +140,26 @@ export type AppOptions = { * that was packaged by the backstage-cli and default docker container boot script. */ configLoader?: AppConfigLoader; + + /** + * A function that is used to register associations between cross-plugin route + * references, enabling plugins to navigate between each other. + * + * The `bind` function that is passed in should be used to bind all external + * routes of all used plugins. + * + * ```ts + * bindRoutes({ bind }) { + * bind(docsPlugin.externalRoutes, { + * homePage: managePlugin.routes.managePage, + * }) + * bind(homePagePlugin.externalRoutes, { + * settingsPage: settingsPlugin.routes.settingsPage, + * }) + * } + * ``` + */ + bindRoutes?(context: { bind: BindRouteFunc }): void; }; export type BackstageApp = { From 5d52e20a44f5b9d79e2af9fccd5dd6a34f948222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 7 Dec 2020 15:59:37 +0100 Subject: [PATCH 77/98] core-api: run bindRoutes in the app impl and inject provider --- packages/core-api/src/app/App.test.ts | 40 ++++++ packages/core-api/src/app/App.tsx | 115 +++++++++++++----- packages/core-api/src/app/types.ts | 2 +- packages/core/src/api-wrappers/createApp.tsx | 1 + .../test-utils/src/testUtils/appWrappers.tsx | 1 + 5 files changed, 130 insertions(+), 29 deletions(-) create mode 100644 packages/core-api/src/app/App.test.ts diff --git a/packages/core-api/src/app/App.test.ts b/packages/core-api/src/app/App.test.ts new file mode 100644 index 0000000000..a25256491b --- /dev/null +++ b/packages/core-api/src/app/App.test.ts @@ -0,0 +1,40 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { createExternalRouteRef, createRouteRef } from '../routing/RouteRef'; +import { generateBoundRoutes } from './App'; + +describe('generateBoundRoutes', () => { + it('runs happy path', () => { + const external = { myRoute: createExternalRouteRef() }; + const ref = createRouteRef({ path: '', title: '' }); + const result = generateBoundRoutes(({ bind }) => { + bind(external, { myRoute: ref }); + }); + + expect(result.get(external.myRoute)).toBe(ref); + }); + + it('throws on unknown keys', () => { + const external = { myRoute: createExternalRouteRef() }; + const ref = createRouteRef({ path: '', title: '' }); + expect(() => + generateBoundRoutes(({ bind }) => { + bind(external, { someOtherRoute: ref } as any); + }), + ).toThrow('Key someOtherRoute is not an existing external route'); + }); +}); diff --git a/packages/core-api/src/app/App.tsx b/packages/core-api/src/app/App.tsx index b42278e4a6..b7265fb5ac 100644 --- a/packages/core-api/src/app/App.tsx +++ b/packages/core-api/src/app/App.tsx @@ -15,46 +15,82 @@ */ import React, { ComponentType, + PropsWithChildren, + ReactElement, useMemo, useState, - ReactElement, - PropsWithChildren, } from 'react'; -import { Route, Routes, Navigate } from 'react-router-dom'; -import { AppContextProvider } from './AppContext'; -import { - BackstageApp, - AppComponents, - AppConfigLoader, - SignInResult, - SignInPageProps, -} from './types'; -import { BackstagePlugin } from '../plugin'; -import { - featureFlagsApiRef, - AppThemeApi, - ConfigApi, - identityApiRef, -} from '../apis/definitions'; -import { AppThemeProvider } from './AppThemeProvider'; - -import { IconComponent, SystemIcons, SystemIconKey } from '../icons'; +import { Navigate, Route, Routes } from 'react-router-dom'; +import { useAsync } from 'react-use'; import { + AnyApiFactory, + ApiHolder, ApiProvider, ApiRegistry, AppTheme, - AppThemeSelector, appThemeApiRef, + AppThemeSelector, configApiRef, ConfigReader, - useApi, - AnyApiFactory, - ApiHolder, LocalStorageFeatureFlags, + useApi, } from '../apis'; -import { useAsync } from 'react-use'; +import { + AppThemeApi, + ConfigApi, + featureFlagsApiRef, + identityApiRef, +} from '../apis/definitions'; +import { ApiFactoryRegistry, ApiResolver } from '../apis/system'; +import { + childDiscoverer, + routeElementDiscoverer, + traverseElementTree, +} from '../extensions/traversal'; +import { IconComponent, SystemIconKey, SystemIcons } from '../icons'; +import { BackstagePlugin } from '../plugin'; +import { RouteRef } from '../routing'; +import { + routeObjectCollector, + routeParentCollector, + routePathCollector, +} from '../routing/collectors'; +import { RoutingProvider } from '../routing/hooks'; +import { ExternalRouteRef } from '../routing/RouteRef'; +import { AppContextProvider } from './AppContext'; import { AppIdentity } from './AppIdentity'; -import { ApiResolver, ApiFactoryRegistry } from '../apis/system'; +import { AppThemeProvider } from './AppThemeProvider'; +import { + AppComponents, + AppConfigLoader, + AppOptions, + BackstageApp, + BindRouteFunc, + SignInPageProps, + SignInResult, +} from './types'; + +export function generateBoundRoutes( + bindRoutes: AppOptions['bindRoutes'], +): Map { + const result = new Map(); + + if (bindRoutes) { + const bind: BindRouteFunc = (externalRoutes, targetRoutes) => { + for (const [key, value] of Object.entries(targetRoutes)) { + const externalRoute = externalRoutes[key]; + if (!externalRoute) { + throw new Error(`Key ${key} is not an existing external route`); + } + + result.set(externalRoute, value); + } + }; + bindRoutes({ bind }); + } + + return result; +} type FullAppOptions = { apis: Iterable; @@ -64,6 +100,7 @@ type FullAppOptions = { themes: AppTheme[]; configLoader?: AppConfigLoader; defaultApis: Iterable; + bindRoutes?: AppOptions['bindRoutes']; }; function useConfigLoader( @@ -112,6 +149,7 @@ export class PrivateAppImpl implements BackstageApp { private readonly themes: AppTheme[]; private readonly configLoader?: AppConfigLoader; private readonly defaultApis: Iterable; + private readonly bindRoutes: AppOptions['bindRoutes']; private readonly identityApi = new AppIdentity(); @@ -123,6 +161,7 @@ export class PrivateAppImpl implements BackstageApp { this.themes = options.themes; this.configLoader = options.configLoader; this.defaultApis = options.defaultApis; + this.bindRoutes = options.bindRoutes; } getPlugins(): BackstagePlugin[] { @@ -202,6 +241,17 @@ export class PrivateAppImpl implements BackstageApp { [], ); + // Probably want to memo this? + const { routePaths, routeParents, routeObjects } = traverseElementTree({ + root: children, + discoverers: [childDiscoverer, routeElementDiscoverer], + collectors: { + routePaths: routePathCollector, + routeParents: routeParentCollector, + routeObjects: routeObjectCollector, + }, + }); + const loadedConfig = useConfigLoader( this.configLoader, this.components, @@ -218,7 +268,16 @@ export class PrivateAppImpl implements BackstageApp { return ( - {children} + + + {children} + + ); diff --git a/packages/core-api/src/app/types.ts b/packages/core-api/src/app/types.ts index d121a2e2a0..3eeac72a30 100644 --- a/packages/core-api/src/app/types.ts +++ b/packages/core-api/src/app/types.ts @@ -79,7 +79,7 @@ export type AppComponents = { */ export type AppConfigLoader = () => Promise; -type BindRouteFunc = ( +export type BindRouteFunc = ( externalRoutes: T, targetRoutes: { [key in keyof T]: RouteRef }, ) => void; diff --git a/packages/core/src/api-wrappers/createApp.tsx b/packages/core/src/api-wrappers/createApp.tsx index c99ba0ed03..9a8f7a36df 100644 --- a/packages/core/src/api-wrappers/createApp.tsx +++ b/packages/core/src/api-wrappers/createApp.tsx @@ -142,6 +142,7 @@ export function createApp(options?: AppOptions) { themes, configLoader, defaultApis, + bindRoutes: options?.bindRoutes, }); app.verify(); diff --git a/packages/test-utils/src/testUtils/appWrappers.tsx b/packages/test-utils/src/testUtils/appWrappers.tsx index 22bc8ceee4..1f6c7622b8 100644 --- a/packages/test-utils/src/testUtils/appWrappers.tsx +++ b/packages/test-utils/src/testUtils/appWrappers.tsx @@ -80,6 +80,7 @@ export function wrapInTestApp( }, ], defaultApis: mockApis, + bindRoutes: () => {}, }); let Wrapper: ComponentType; From 797d170873db7bd3df67471dcfd7a0cdf78104c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 7 Dec 2020 16:45:30 +0100 Subject: [PATCH 78/98] core-api: add full PrivateAppImpl test for bindRoutes --- packages/core-api/src/app/App.test.ts | 40 -------- packages/core-api/src/app/App.test.tsx | 128 +++++++++++++++++++++++++ packages/core-api/src/app/App.tsx | 1 + 3 files changed, 129 insertions(+), 40 deletions(-) delete mode 100644 packages/core-api/src/app/App.test.ts create mode 100644 packages/core-api/src/app/App.test.tsx diff --git a/packages/core-api/src/app/App.test.ts b/packages/core-api/src/app/App.test.ts deleted file mode 100644 index a25256491b..0000000000 --- a/packages/core-api/src/app/App.test.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * 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 { createExternalRouteRef, createRouteRef } from '../routing/RouteRef'; -import { generateBoundRoutes } from './App'; - -describe('generateBoundRoutes', () => { - it('runs happy path', () => { - const external = { myRoute: createExternalRouteRef() }; - const ref = createRouteRef({ path: '', title: '' }); - const result = generateBoundRoutes(({ bind }) => { - bind(external, { myRoute: ref }); - }); - - expect(result.get(external.myRoute)).toBe(ref); - }); - - it('throws on unknown keys', () => { - const external = { myRoute: createExternalRouteRef() }; - const ref = createRouteRef({ path: '', title: '' }); - expect(() => - generateBoundRoutes(({ bind }) => { - bind(external, { someOtherRoute: ref } as any); - }), - ).toThrow('Key someOtherRoute is not an existing external route'); - }); -}); diff --git a/packages/core-api/src/app/App.test.tsx b/packages/core-api/src/app/App.test.tsx new file mode 100644 index 0000000000..431ffa5959 --- /dev/null +++ b/packages/core-api/src/app/App.test.tsx @@ -0,0 +1,128 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { renderWithEffects } from '@backstage/test-utils'; +import { lightTheme } from '@backstage/theme'; +import { screen } from '@testing-library/react'; +import React from 'react'; +import { BrowserRouter, Routes } from 'react-router-dom'; +import { createRoutableExtension } from '../extensions'; +import { defaultSystemIcons } from '../icons'; +import { createPlugin } from '../plugin'; +import { useRouteRef } from '../routing/hooks'; +import { createExternalRouteRef, createRouteRef } from '../routing/RouteRef'; +import { generateBoundRoutes, PrivateAppImpl } from './App'; + +describe('generateBoundRoutes', () => { + it('runs happy path', () => { + const external = { myRoute: createExternalRouteRef() }; + const ref = createRouteRef({ path: '', title: '' }); + const result = generateBoundRoutes(({ bind }) => { + bind(external, { myRoute: ref }); + }); + + expect(result.get(external.myRoute)).toBe(ref); + }); + + it('throws on unknown keys', () => { + const external = { myRoute: createExternalRouteRef() }; + const ref = createRouteRef({ path: '', title: '' }); + expect(() => + generateBoundRoutes(({ bind }) => { + bind(external, { someOtherRoute: ref } as any); + }), + ).toThrow('Key someOtherRoute is not an existing external route'); + }); +}); + +describe('Integration Test', () => { + const plugin1RouteRef = createRouteRef({ path: '/blah1', title: '' }); + const plugin2RouteRef = createRouteRef({ path: '/blah2', title: '' }); + const externalRouteRef = createExternalRouteRef(); + + const plugin1 = createPlugin({ + id: 'blob', + externalRoutes: { + foo: externalRouteRef, + }, + }); + + const plugin2 = createPlugin({ + id: 'plugin2', + }); + + const HiddenComponent = plugin2.provide( + createRoutableExtension({ + component: () => null, + mountPoint: plugin2RouteRef, + }), + ); + + const ExposedComponent = plugin1.provide( + createRoutableExtension({ + component: () => { + // eslint-disable-next-line react-hooks/rules-of-hooks + const routeRefFunction = useRouteRef(externalRouteRef); + return
Our Route Is: {routeRefFunction({})}
; + }, + mountPoint: plugin1RouteRef, + }), + ); + + it('runs happy path', () => { + const components = { + NotFoundErrorPage: () => null, + BootErrorPage: () => null, + Progress: () => null, + Router: BrowserRouter, + }; + + const app = new PrivateAppImpl({ + apis: [], + defaultApis: [], + themes: [ + { + id: 'light', + title: 'Light Theme', + variant: 'light', + theme: lightTheme, + }, + ], + icons: defaultSystemIcons, + plugins: [], + components, + bindRoutes: ({ bind }) => { + bind(plugin1.externalRoutes, { foo: plugin2RouteRef }); + }, + }); + + const Provider = app.getProvider(); + const Router = app.getRouter(); + + renderWithEffects( + + + + + + + + , + ); + + expect(screen.getByText('Our Route Is: /foo/bar')).toBeInTheDocument(); + }); +}); diff --git a/packages/core-api/src/app/App.tsx b/packages/core-api/src/app/App.tsx index b7265fb5ac..82b224fe59 100644 --- a/packages/core-api/src/app/App.tsx +++ b/packages/core-api/src/app/App.tsx @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import React, { ComponentType, PropsWithChildren, From ad66d1c8c43642985b14b07d89a35cd0292dd999 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 8 Dec 2020 15:56:34 +0100 Subject: [PATCH 79/98] core-api,plugins/graphiql: export extension APIs from core-api and port the graphiql plugin Co-authored-by: blam --- packages/app/src/App.tsx | 4 ++-- packages/core-api/src/public.ts | 1 + packages/core-api/src/routing/index.ts | 1 + plugins/graphiql/src/index.ts | 2 +- plugins/graphiql/src/plugin.ts | 15 ++++++++++++++- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 627b5d19aa..a58bf45f9c 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -29,7 +29,7 @@ import { hot } from 'react-hot-loader/root'; import { providers } from './identityProviders'; import { Router as CatalogRouter } from '@backstage/plugin-catalog'; import { Router as DocsRouter } from '@backstage/plugin-techdocs'; -import { Router as GraphiQLRouter } from '@backstage/plugin-graphiql'; +import { GraphiQLPage } from '@backstage/plugin-graphiql'; import { Router as TechRadarRouter } from '@backstage/plugin-tech-radar'; import { Router as LighthouseRouter } from '@backstage/plugin-lighthouse'; import { Router as RegisterComponentRouter } from '@backstage/plugin-register-component'; @@ -81,7 +81,7 @@ const AppRoutes = () => ( path="/tech-radar" element={} /> - } /> + } /> } /> Date: Wed, 16 Dec 2020 12:03:17 +0100 Subject: [PATCH 80/98] core-api: rename BindRouteFunc to AppRouteBinder --- packages/core-api/src/app/App.tsx | 4 ++-- packages/core-api/src/app/types.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core-api/src/app/App.tsx b/packages/core-api/src/app/App.tsx index 82b224fe59..4a23c26bba 100644 --- a/packages/core-api/src/app/App.tsx +++ b/packages/core-api/src/app/App.tsx @@ -65,8 +65,8 @@ import { AppComponents, AppConfigLoader, AppOptions, + AppRouteBinder, BackstageApp, - BindRouteFunc, SignInPageProps, SignInResult, } from './types'; @@ -77,7 +77,7 @@ export function generateBoundRoutes( const result = new Map(); if (bindRoutes) { - const bind: BindRouteFunc = (externalRoutes, targetRoutes) => { + const bind: AppRouteBinder = (externalRoutes, targetRoutes) => { for (const [key, value] of Object.entries(targetRoutes)) { const externalRoute = externalRoutes[key]; if (!externalRoute) { diff --git a/packages/core-api/src/app/types.ts b/packages/core-api/src/app/types.ts index 3eeac72a30..898f4d978b 100644 --- a/packages/core-api/src/app/types.ts +++ b/packages/core-api/src/app/types.ts @@ -79,7 +79,7 @@ export type AppComponents = { */ export type AppConfigLoader = () => Promise; -export type BindRouteFunc = ( +export type AppRouteBinder = ( externalRoutes: T, targetRoutes: { [key in keyof T]: RouteRef }, ) => void; @@ -159,7 +159,7 @@ export type AppOptions = { * } * ``` */ - bindRoutes?(context: { bind: BindRouteFunc }): void; + bindRoutes?(context: { bind: AppRouteBinder }): void; }; export type BackstageApp = { From eb6a928eb0f0f1f7057437a3b28dc14552511a0d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 16 Dec 2020 16:12:29 +0100 Subject: [PATCH 81/98] core-api: avoid exporting AnyRoutes, AnyExternalRoutes, and ExternalRouteRef constructor --- packages/core-api/src/app/types.ts | 2 +- packages/core-api/src/plugin/index.ts | 17 ++++++++++++++++- packages/core-api/src/routing/RouteRef.ts | 10 +++++++++- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/packages/core-api/src/app/types.ts b/packages/core-api/src/app/types.ts index 898f4d978b..b6b1002d12 100644 --- a/packages/core-api/src/app/types.ts +++ b/packages/core-api/src/app/types.ts @@ -16,7 +16,7 @@ import { ComponentType } from 'react'; import { IconComponent, SystemIconKey, SystemIcons } from '../icons'; -import { BackstagePlugin, AnyExternalRoutes } from '../plugin'; +import { BackstagePlugin, AnyExternalRoutes } from '../plugin/types'; import { RouteRef } from '../routing'; import { AnyApiFactory } from '../apis'; import { AppTheme, ProfileInfo } from '../apis/definitions'; diff --git a/packages/core-api/src/plugin/index.ts b/packages/core-api/src/plugin/index.ts index 79b0575755..bbeeca4824 100644 --- a/packages/core-api/src/plugin/index.ts +++ b/packages/core-api/src/plugin/index.ts @@ -15,4 +15,19 @@ */ export { createPlugin } from './Plugin'; -export * from './types'; +export type { + BackstagePlugin, + Extension, + FeatureFlagOutput, + FeatureFlagsHooks, + LegacyRedirectRouteOutput, + LegacyRouteOutput, + PluginConfig, + PluginHooks, + PluginOutput, + RedirectRouteOutput, + RouteOptions, + RouteOutput, + RoutePath, + RouterHooks, +} from './types'; diff --git a/packages/core-api/src/routing/RouteRef.ts b/packages/core-api/src/routing/RouteRef.ts index c7db48045a..f89634e0ec 100644 --- a/packages/core-api/src/routing/RouteRef.ts +++ b/packages/core-api/src/routing/RouteRef.ts @@ -54,12 +54,20 @@ export function createRouteRef< return new AbsoluteRouteRef(config); } +const create = Symbol('create-external-route-ref'); + export class ExternalRouteRef { + static [create]() { + return new ExternalRouteRef(); + } + + private constructor() {} + toString() { return `externalRouteRef{}`; } } export function createExternalRouteRef(): ExternalRouteRef { - return new ExternalRouteRef(); + return ExternalRouteRef[create](); } From 1dc445e8937c5e48b07d21114ed80cbacc2e6c95 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 16 Dec 2020 18:06:08 +0100 Subject: [PATCH 82/98] changeset: add changesets for new plugin extension API --- .changeset/quiet-pants-happen.md | 7 +++++++ .changeset/short-dancers-explode.md | 5 +++++ 2 files changed, 12 insertions(+) create mode 100644 .changeset/quiet-pants-happen.md create mode 100644 .changeset/short-dancers-explode.md diff --git a/.changeset/quiet-pants-happen.md b/.changeset/quiet-pants-happen.md new file mode 100644 index 0000000000..165e3ae12c --- /dev/null +++ b/.changeset/quiet-pants-happen.md @@ -0,0 +1,7 @@ +--- +'@backstage/core': patch +'@backstage/test-utils': patch +'@backstage/plugin-graphiql': patch +--- + +Update to use new plugin extension API diff --git a/.changeset/short-dancers-explode.md b/.changeset/short-dancers-explode.md new file mode 100644 index 0000000000..56fee63fe7 --- /dev/null +++ b/.changeset/short-dancers-explode.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-api': patch +--- + +Introduce new plugin extension API From 6d263b0bdf5663bc57a89dbf8ad3993934935d7d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 16 Dec 2020 21:21:28 +0100 Subject: [PATCH 83/98] core-api: default type parameters for BackstagePlugin to avoid breakage Co-authored-by: blam --- packages/core-api/src/plugin/Plugin.tsx | 4 ++-- packages/core-api/src/plugin/types.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core-api/src/plugin/Plugin.tsx b/packages/core-api/src/plugin/Plugin.tsx index 797dcd852e..dd6d7960ac 100644 --- a/packages/core-api/src/plugin/Plugin.tsx +++ b/packages/core-api/src/plugin/Plugin.tsx @@ -93,8 +93,8 @@ export class PluginImpl< } export function createPlugin< - Routes extends AnyRoutes, - ExternalRoutes extends AnyExternalRoutes + Routes extends AnyRoutes = {}, + ExternalRoutes extends AnyExternalRoutes = {} >( config: PluginConfig, ): BackstagePlugin { diff --git a/packages/core-api/src/plugin/types.ts b/packages/core-api/src/plugin/types.ts index e3f2e38972..94bd4e8172 100644 --- a/packages/core-api/src/plugin/types.ts +++ b/packages/core-api/src/plugin/types.ts @@ -76,8 +76,8 @@ export type AnyRoutes = { [name: string]: RouteRef }; export type AnyExternalRoutes = { [name: string]: ExternalRouteRef }; export type BackstagePlugin< - Routes extends AnyRoutes, - ExternalRoutes extends AnyExternalRoutes + Routes extends AnyRoutes = {}, + ExternalRoutes extends AnyExternalRoutes = {} > = { getId(): string; output(): PluginOutput[]; From aeb9fb254ee7b0c88a9caa0b760fef1ee2f03f69 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 17 Dec 2020 13:49:21 +0100 Subject: [PATCH 84/98] core-api: add route validation to app + test Co-authored-by: blam --- packages/core-api/src/app/App.test.tsx | 60 +++++++++++++++++++++++++- packages/core-api/src/app/App.tsx | 4 +- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/packages/core-api/src/app/App.test.tsx b/packages/core-api/src/app/App.test.tsx index 431ffa5959..7ab4928abf 100644 --- a/packages/core-api/src/app/App.test.tsx +++ b/packages/core-api/src/app/App.test.tsx @@ -14,9 +14,9 @@ * limitations under the License. */ -import { renderWithEffects } from '@backstage/test-utils'; +import { renderWithEffects, withLogCollector } from '@backstage/test-utils'; import { lightTheme } from '@backstage/theme'; -import { screen } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import React from 'react'; import { BrowserRouter, Routes } from 'react-router-dom'; import { createRoutableExtension } from '../extensions'; @@ -125,4 +125,60 @@ describe('Integration Test', () => { expect(screen.getByText('Our Route Is: /foo/bar')).toBeInTheDocument(); }); + + it('should throw some error when the route has duplicate params', () => { + const components = { + NotFoundErrorPage: () => null, + BootErrorPage: () => null, + Progress: () => null, + Router: BrowserRouter, + }; + + const app = new PrivateAppImpl({ + apis: [], + defaultApis: [], + themes: [ + { + id: 'light', + title: 'Light Theme', + variant: 'light', + theme: lightTheme, + }, + ], + icons: defaultSystemIcons, + plugins: [], + components, + bindRoutes: ({ bind }) => { + bind(plugin1.externalRoutes, { foo: plugin2RouteRef }); + }, + }); + + const Provider = app.getProvider(); + const Router = app.getRouter(); + const { error: errorLogs } = withLogCollector(() => { + expect(() => + render( + + + + + + + + + , + ), + ).toThrow( + 'Parameter :thing is duplicated in path /test/:thing/some/:thing', + ); + }); + expect(errorLogs).toEqual([ + expect.stringContaining( + 'Parameter :thing is duplicated in path /test/:thing/some/:thing', + ), + expect.stringContaining( + 'The above error occurred in the component', + ), + ]); + }); }); diff --git a/packages/core-api/src/app/App.tsx b/packages/core-api/src/app/App.tsx index 4a23c26bba..08393f3e9e 100644 --- a/packages/core-api/src/app/App.tsx +++ b/packages/core-api/src/app/App.tsx @@ -56,7 +56,7 @@ import { routeParentCollector, routePathCollector, } from '../routing/collectors'; -import { RoutingProvider } from '../routing/hooks'; +import { RoutingProvider, validateRoutes } from '../routing/hooks'; import { ExternalRouteRef } from '../routing/RouteRef'; import { AppContextProvider } from './AppContext'; import { AppIdentity } from './AppIdentity'; @@ -253,6 +253,8 @@ export class PrivateAppImpl implements BackstageApp { }, }); + validateRoutes(routePaths, routeParents); + const loadedConfig = useConfigLoader( this.configLoader, this.components, From adb1afdc2bad5bf2ed4157b5155fec48e9ef34df Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 17 Dec 2020 16:11:00 +0100 Subject: [PATCH 85/98] core-api: refactor createReactExtension to forward component types directly and avoid @types/react dependency Co-authored-by: blam --- packages/core-api/src/app/App.test.tsx | 6 +-- .../src/extensions/extensions.test.tsx | 4 +- .../core-api/src/extensions/extensions.tsx | 43 ++++++++----------- .../core-api/src/plugin/collectors.test.tsx | 4 +- .../core-api/src/routing/collectors.test.tsx | 4 +- packages/core-api/src/routing/hooks.test.tsx | 5 ++- 6 files changed, 33 insertions(+), 33 deletions(-) diff --git a/packages/core-api/src/app/App.test.tsx b/packages/core-api/src/app/App.test.tsx index 7ab4928abf..4050343bbf 100644 --- a/packages/core-api/src/app/App.test.tsx +++ b/packages/core-api/src/app/App.test.tsx @@ -17,7 +17,7 @@ import { renderWithEffects, withLogCollector } from '@backstage/test-utils'; import { lightTheme } from '@backstage/theme'; import { render, screen } from '@testing-library/react'; -import React from 'react'; +import React, { PropsWithChildren } from 'react'; import { BrowserRouter, Routes } from 'react-router-dom'; import { createRoutableExtension } from '../extensions'; import { defaultSystemIcons } from '../icons'; @@ -66,14 +66,14 @@ describe('Integration Test', () => { const HiddenComponent = plugin2.provide( createRoutableExtension({ - component: () => null, + component: (_: { path?: string }) =>
, mountPoint: plugin2RouteRef, }), ); const ExposedComponent = plugin1.provide( createRoutableExtension({ - component: () => { + component: (_: PropsWithChildren<{ path?: string }>) => { // eslint-disable-next-line react-hooks/rules-of-hooks const routeRefFunction = useRouteRef(externalRouteRef); return
Our Route Is: {routeRefFunction({})}
; diff --git a/packages/core-api/src/extensions/extensions.test.tsx b/packages/core-api/src/extensions/extensions.test.tsx index 92fcecebc4..861045fb3d 100644 --- a/packages/core-api/src/extensions/extensions.test.tsx +++ b/packages/core-api/src/extensions/extensions.test.tsx @@ -30,7 +30,7 @@ const plugin = createPlugin({ describe('extensions', () => { it('should create a react extension with component data', () => { - const Component = () => null; + const Component = () =>
; const extension = createReactExtension({ component: Component, @@ -47,7 +47,7 @@ describe('extensions', () => { }); it('should create react extensions of different types', () => { - const Component = () => null; + const Component = () =>
; const routeRef = createRouteRef({ path: '/foo', title: 'Foo' }); const extension1 = createComponentExtension({ diff --git a/packages/core-api/src/extensions/extensions.tsx b/packages/core-api/src/extensions/extensions.tsx index 079fec4597..aca29e87dc 100644 --- a/packages/core-api/src/extensions/extensions.tsx +++ b/packages/core-api/src/extensions/extensions.tsx @@ -14,24 +14,14 @@ * limitations under the License. */ -import React, { - NamedExoticComponent, - ComponentType, - PropsWithChildren, -} from 'react'; +import React from 'react'; import { RouteRef } from '../routing'; import { attachComponentData } from './componentData'; import { Extension, BackstagePlugin } from '../plugin/types'; -export function createRoutableExtension(options: { - component: ComponentType; - mountPoint: RouteRef; - // TODO(Rugvip): We want to carry forward the exact props type from the inner component, with - // or without children. ComponentType stops us from doing that though, as it always - // adds children to the props internally. We may want to work around this with custom types. -}): Extension< - NamedExoticComponent> -> { +export function createRoutableExtension< + T extends (props: any) => JSX.Element +>(options: { component: T; mountPoint: RouteRef }): Extension { const { component, mountPoint } = options; return createReactExtension({ component, @@ -41,21 +31,24 @@ export function createRoutableExtension(options: { }); } -export function createComponentExtension(options: { - component: ComponentType; -}): Extension> { +export function createComponentExtension< + T extends (props: any) => JSX.Element +>(options: { component: T }): Extension { const { component } = options; return createReactExtension({ component }); } -export function createReactExtension(options: { - component: ComponentType; - data?: Record; -}): Extension> { - const { component: Component, data = {} } = options; +export function createReactExtension< + T extends (props: any) => JSX.Element +>(options: { component: T; data?: Record }): Extension { + const { data = {} } = options; + const Component = options.component as T & { + displayName?: string; + }; + return { - expose(plugin: BackstagePlugin): NamedExoticComponent { - const Result = (props: Props) => ; + expose(plugin: BackstagePlugin) { + const Result: any = (props: any) => ; attachComponentData(Result, 'core.plugin', plugin); for (const [key, value] of Object.entries(data)) { @@ -66,7 +59,7 @@ export function createReactExtension(options: { if (name) { Result.displayName = `Extension(${name})`; } - return Result as NamedExoticComponent; + return Result; }, }; } diff --git a/packages/core-api/src/plugin/collectors.test.tsx b/packages/core-api/src/plugin/collectors.test.tsx index f040cfd433..e5f8a123e3 100644 --- a/packages/core-api/src/plugin/collectors.test.tsx +++ b/packages/core-api/src/plugin/collectors.test.tsx @@ -30,7 +30,9 @@ import { import { pluginCollector } from './collectors'; const mockConfig = () => ({ path: '/foo', title: 'Foo' }); -const MockComponent = ({ children }: PropsWithChildren<{}>) => <>{children}; +const MockComponent = ({ children }: PropsWithChildren<{ path?: string }>) => ( + <>{children} +); const pluginA = createPlugin({ id: 'my-plugin-a' }); const pluginB = createPlugin({ id: 'my-plugin-b' }); diff --git a/packages/core-api/src/routing/collectors.test.tsx b/packages/core-api/src/routing/collectors.test.tsx index 2595b8c0a0..e44474565c 100644 --- a/packages/core-api/src/routing/collectors.test.tsx +++ b/packages/core-api/src/routing/collectors.test.tsx @@ -28,7 +28,9 @@ import { createRoutableExtension } from '../extensions'; import { MemoryRouter, Routes, Route } from 'react-router-dom'; const mockConfig = () => ({ path: '/foo', title: 'Foo' }); -const MockComponent = ({ children }: PropsWithChildren<{}>) => <>{children}; +const MockComponent = ({ children }: PropsWithChildren<{ path?: string }>) => ( + <>{children} +); const plugin = createPlugin({ id: 'my-plugin' }); diff --git a/packages/core-api/src/routing/hooks.test.tsx b/packages/core-api/src/routing/hooks.test.tsx index 6bc80b7c08..a29e263e14 100644 --- a/packages/core-api/src/routing/hooks.test.tsx +++ b/packages/core-api/src/routing/hooks.test.tsx @@ -47,7 +47,9 @@ const mockConfig = (extra?: Partial>) => ({ title: 'Unused', ...extra, }); -const MockComponent = ({ children }: PropsWithChildren<{}>) => <>{children}; +const MockComponent = ({ children }: PropsWithChildren<{ path?: string }>) => ( + <>{children} +); const plugin = createPlugin({ id: 'my-plugin' }); @@ -61,6 +63,7 @@ const eRefB = createExternalRouteRef(); const eRefC = createExternalRouteRef(); const MockRouteSource = (props: { + path?: string; name: string; routeRef: RouteRef | ExternalRouteRef; params?: T; From 039e2ae1219f0b51bc5a36cb7b5b3e2c9f40a3aa Mon Sep 17 00:00:00 2001 From: Lee Mills Date: Thu, 17 Dec 2020 18:12:02 +0100 Subject: [PATCH 86/98] run prettier on the roadmap --- docs/overview/roadmap.md | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/docs/overview/roadmap.md b/docs/overview/roadmap.md index 8d6f6587c5..b0c031689d 100644 --- a/docs/overview/roadmap.md +++ b/docs/overview/roadmap.md @@ -48,26 +48,27 @@ guidelines to get started. ### Ongoing work 🚧 - **[Platform stabilization](https://github.com/backstage/backstage/milestone/19)** - - Stabilize the core of Backstage, including its core features, so that the platform can be - depended on for production use. After this, plugins will require little-to-no maintenance. + Stabilize the core of Backstage, including its core features, so that the + platform can be depended on for production use. After this, plugins will + require little-to-no maintenance. - **[Kubernetes plugin for service owners](https://github.com/backstage/backstage/issues/2857)** - - Improve native support for Kubernetes, making it easier for service owners to see and - manage their services running in K8s, regardless if that's locally, in AWS, GCS, Azure, - or elsewhere. + Improve native support for Kubernetes, making it easier for service owners to + see and manage their services running in K8s, regardless if that's locally, in + AWS, GCS, Azure, or elsewhere. -- **Global search** - Extend the basic search functionality currently available in the - Backstage Service Catalog to become a global search experience. +- **Global search** - Extend the basic search functionality currently available + in the Backstage Service Catalog to become a global search experience. - **[Software Templates V2](https://github.com/backstage/backstage/issues/2771)** - Expand the templates to make the steps more composable by adding the ability - to add more steps for custom logic, including webhooks and using authorization from - integrations. + to add more steps for custom logic, including webhooks and using authorization + from integrations. ### Future work 🔮 -- **Golden Path for Plugin Development** - Create an easy, standardized way - for developers to build plugins that will encourage contributions and lead to a +- **Golden Path for Plugin Development** - Create an easy, standardized way for + developers to build plugins that will encourage contributions and lead to a richer ecosystem for everyone. - **[GraphQL API](https://github.com/backstage/backstage/milestone/13)** - A @@ -79,7 +80,8 @@ guidelines to get started. clearly defined patterns for plugins to communicate. - **Improved Access Control** - **[Under consideration]** Provide finer grained - access controls and management for better control of the platform user experience. + access controls and management for better control of the platform user + experience. ### Plugins From d681db2b5035e0ae932c7631c889eee24d9780a2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 17 Dec 2020 15:29:44 +0100 Subject: [PATCH 87/98] core-api: add MutableSessionManager and fix AuthSessionStore not properly updating session state --- .changeset/giant-rice-jump.md | 5 +++++ .../src/lib/AuthSessionManager/AuthSessionStore.test.ts | 7 +++++++ .../src/lib/AuthSessionManager/AuthSessionStore.ts | 6 ++++-- .../lib/AuthSessionManager/StaticAuthSessionManager.ts | 9 +++++++-- packages/core-api/src/lib/AuthSessionManager/types.ts | 7 +++++++ 5 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 .changeset/giant-rice-jump.md diff --git a/.changeset/giant-rice-jump.md b/.changeset/giant-rice-jump.md new file mode 100644 index 0000000000..20a574176e --- /dev/null +++ b/.changeset/giant-rice-jump.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-api': patch +--- + +Fix for GitHub and SAML auth not properly updating session state when already logged in. diff --git a/packages/core-api/src/lib/AuthSessionManager/AuthSessionStore.test.ts b/packages/core-api/src/lib/AuthSessionManager/AuthSessionStore.test.ts index 4572b923dd..5c960f7876 100644 --- a/packages/core-api/src/lib/AuthSessionManager/AuthSessionStore.test.ts +++ b/packages/core-api/src/lib/AuthSessionManager/AuthSessionStore.test.ts @@ -36,6 +36,7 @@ class LocalStorage { } class MockManager implements SessionManager { + setSession = jest.fn(); getSession = jest.fn(); removeSession = jest.fn(); sessionState$ = jest.fn(); @@ -59,6 +60,7 @@ describe('GheAuth AuthSessionStore', () => { await expect(store.getSession({})).resolves.toBe('a b c'); expect(manager.getSession).not.toHaveBeenCalled(); + expect(manager.setSession).toHaveBeenCalledWith('a b c'); }); it('should not use session without enough scope', async () => { @@ -72,6 +74,7 @@ describe('GheAuth AuthSessionStore', () => { 'a b c d', ); expect(manager.getSession).toHaveBeenCalledTimes(1); + expect(manager.setSession).not.toHaveBeenCalled(); }); it('should not use expired session', async () => { @@ -87,6 +90,7 @@ describe('GheAuth AuthSessionStore', () => { await expect(store.getSession({})).resolves.toBe('123'); expect(manager.getSession).toHaveBeenCalledTimes(1); + expect(manager.setSession).not.toHaveBeenCalled(); }); it('should not load missing session', async () => { @@ -96,6 +100,7 @@ describe('GheAuth AuthSessionStore', () => { await expect(store.getSession({})).resolves.toBe('123'); expect(manager.getSession).toHaveBeenCalledTimes(1); + expect(manager.setSession).not.toHaveBeenCalled(); expect(localStorage.getItem('my-key')).toBe('"123"'); }); @@ -109,6 +114,7 @@ describe('GheAuth AuthSessionStore', () => { await expect(store.getSession({})).resolves.toBe('123'); expect(manager.getSession).toHaveBeenCalledTimes(1); + expect(manager.setSession).not.toHaveBeenCalled(); }); it('should clear session', () => { @@ -119,6 +125,7 @@ describe('GheAuth AuthSessionStore', () => { store.removeSession(); expect(localStorage.getItem('my-key')).toBe(null); + expect(manager.removeSession).toHaveBeenCalled(); }); it('should forward sessionState calls', () => { diff --git a/packages/core-api/src/lib/AuthSessionManager/AuthSessionStore.ts b/packages/core-api/src/lib/AuthSessionManager/AuthSessionStore.ts index e82557b1ce..224036d283 100644 --- a/packages/core-api/src/lib/AuthSessionManager/AuthSessionStore.ts +++ b/packages/core-api/src/lib/AuthSessionManager/AuthSessionStore.ts @@ -16,6 +16,7 @@ import { SessionManager, + MutableSessionManager, SessionScopesFunc, SessionShouldRefreshFunc, GetSessionOptions, @@ -24,7 +25,7 @@ import { SessionScopeHelper } from './common'; type Options = { /** The connector used for acting on the auth session */ - manager: SessionManager; + manager: MutableSessionManager; /** Storage key to use to store sessions */ storageKey: string; /** Used to get the scope of the session */ @@ -40,7 +41,7 @@ type Options = { * Session is serialized to JSON with special support for following types: Set. */ export class AuthSessionStore implements SessionManager { - private readonly manager: SessionManager; + private readonly manager: MutableSessionManager; private readonly storageKey: string; private readonly sessionShouldRefreshFunc: SessionShouldRefreshFunc; private readonly helper: SessionScopeHelper; @@ -70,6 +71,7 @@ export class AuthSessionStore implements SessionManager { const shouldRefresh = this.sessionShouldRefreshFunc(session!); if (!shouldRefresh) { + this.manager.setSession(session!); return session!; } } diff --git a/packages/core-api/src/lib/AuthSessionManager/StaticAuthSessionManager.ts b/packages/core-api/src/lib/AuthSessionManager/StaticAuthSessionManager.ts index e02b600828..e4f144b0a9 100644 --- a/packages/core-api/src/lib/AuthSessionManager/StaticAuthSessionManager.ts +++ b/packages/core-api/src/lib/AuthSessionManager/StaticAuthSessionManager.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { SessionManager, GetSessionOptions } from './types'; +import { MutableSessionManager, GetSessionOptions } from './types'; import { AuthConnector } from '../AuthConnector'; import { SessionScopeHelper } from './common'; import { SessionStateTracker } from './SessionStateTracker'; @@ -31,7 +31,7 @@ type Options = { /** * StaticAuthSessionManager manages an underlying session that does not expire. */ -export class StaticAuthSessionManager implements SessionManager { +export class StaticAuthSessionManager implements MutableSessionManager { private readonly connector: AuthConnector; private readonly helper: SessionScopeHelper; private readonly stateTracker = new SessionStateTracker(); @@ -45,6 +45,11 @@ export class StaticAuthSessionManager implements SessionManager { this.helper = new SessionScopeHelper({ sessionScopes, defaultScopes }); } + setSession(session: T | undefined): void { + this.currentSession = session; + this.stateTracker.setIsSignedIn(Boolean(session)); + } + async getSession(options: GetSessionOptions): Promise { if ( this.helper.sessionExistsAndHasScope(this.currentSession, options.scopes) diff --git a/packages/core-api/src/lib/AuthSessionManager/types.ts b/packages/core-api/src/lib/AuthSessionManager/types.ts index 804c7121e1..f57afd6760 100644 --- a/packages/core-api/src/lib/AuthSessionManager/types.ts +++ b/packages/core-api/src/lib/AuthSessionManager/types.ts @@ -36,6 +36,13 @@ export type SessionManager = { sessionState$(): Observable; }; +/** + * An extension of the session manager where the session can also be pushed from the manager. + */ +export interface MutableSessionManager extends SessionManager { + setSession(session: T | undefined): void; +} + /** * A function called to determine the scopes of a session. */ From 33627f3352e2d2e1e7467da647069c2c70ff2a65 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Dec 2020 05:11:53 +0000 Subject: [PATCH 88/98] build(deps): bump graphql from 15.3.0 to 15.4.0 Bumps [graphql](https://github.com/graphql/graphql-js) from 15.3.0 to 15.4.0. - [Release notes](https://github.com/graphql/graphql-js/releases) - [Commits](https://github.com/graphql/graphql-js/compare/v15.3.0...v15.4.0) Signed-off-by: dependabot[bot] --- plugins/graphiql/package.json | 2 +- yarn.lock | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index b6e7ca72ed..af30bc4b12 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -37,7 +37,7 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", "graphiql": "^1.0.0-alpha.10", - "graphql": "15.3.0", + "graphql": "15.4.0", "react": "^16.13.1", "react-dom": "^16.13.1", "react-use": "^15.3.3" diff --git a/yarn.lock b/yarn.lock index 24c06e1d8f..0923d3ed70 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1644,7 +1644,7 @@ to-fast-properties "^2.0.0" "@backstage/catalog-model@^0.2.0": - version "0.5.0" + version "0.6.0" dependencies: "@backstage/config" "^0.1.2" "@types/json-schema" "^7.0.5" @@ -1655,7 +1655,7 @@ yup "^0.29.3" "@backstage/catalog-model@^0.3.0": - version "0.5.0" + version "0.6.0" dependencies: "@backstage/config" "^0.1.2" "@types/json-schema" "^7.0.5" @@ -1666,10 +1666,10 @@ yup "^0.29.3" "@backstage/core@^0.3.0": - version "0.4.0" + version "0.4.1" dependencies: "@backstage/config" "^0.1.2" - "@backstage/core-api" "^0.2.5" + "@backstage/core-api" "^0.2.6" "@backstage/theme" "^0.2.2" "@material-ui/core" "^4.11.0" "@material-ui/icons" "^4.9.1" @@ -13688,10 +13688,10 @@ graphql-upload@^8.0.2: http-errors "^1.7.3" object-path "^0.11.4" -graphql@15.3.0, graphql@^15.3.0: - version "15.3.0" - resolved "https://registry.npmjs.org/graphql/-/graphql-15.3.0.tgz#3ad2b0caab0d110e3be4a5a9b2aa281e362b5278" - integrity sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w== +graphql@15.4.0, graphql@^15.3.0: + version "15.4.0" + resolved "https://registry.npmjs.org/graphql/-/graphql-15.4.0.tgz#e459dea1150da5a106486ba7276518b5295a4347" + integrity sha512-EB3zgGchcabbsU9cFe1j+yxdzKQKAbGUWRb13DsrsMN1yyfmmIq+2+L5MqVWcDCE4V89R5AyUOi7sMOGxdsYtA== graphql@^14.5.3: version "14.7.0" From f742a8bf7b9188ae8fbb2cb9247b2fbc6385e747 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Fri, 18 Dec 2020 10:42:38 +0100 Subject: [PATCH 89/98] Add search plugin to new CLI created apps --- packages/create-app/package.json | 1 + packages/create-app/src/lib/versions.ts | 2 ++ .../templates/default-app/packages/app/package.json.hbs | 1 + .../templates/default-app/packages/app/src/App.tsx | 5 +++++ .../templates/default-app/packages/app/src/sidebar.tsx | 2 ++ 5 files changed, 11 insertions(+) diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 64f7e83ae4..52691fc2ee 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -55,6 +55,7 @@ "@backstage/plugin-register-component": "^0.2.5", "@backstage/plugin-rollbar-backend": "^0.1.5", "@backstage/plugin-scaffolder": "^0.3.4", + "@backstage/plugin-search": "^0.2.4", "@backstage/plugin-scaffolder-backend": "^0.3.5", "@backstage/plugin-tech-radar": "^0.3.1", "@backstage/plugin-techdocs": "^0.5.0", diff --git a/packages/create-app/src/lib/versions.ts b/packages/create-app/src/lib/versions.ts index 84f015509c..df8b9c01ea 100644 --- a/packages/create-app/src/lib/versions.ts +++ b/packages/create-app/src/lib/versions.ts @@ -48,6 +48,7 @@ import { version as pluginRegisterComponent } from '@backstage/plugin-register-c import { version as pluginRollbarBackend } from '@backstage/plugin-rollbar-backend/package.json'; import { version as pluginScaffolder } from '@backstage/plugin-scaffolder/package.json'; import { version as pluginScaffolderBackend } from '@backstage/plugin-scaffolder-backend/package.json'; +import { version as pluginSearch } from '@backstage/plugin-search/package.json'; import { version as pluginTechRadar } from '@backstage/plugin-tech-radar/package.json'; import { version as pluginTechdocs } from '@backstage/plugin-techdocs/package.json'; import { version as pluginTechdocsBackend } from '@backstage/plugin-techdocs-backend/package.json'; @@ -75,6 +76,7 @@ export const packageVersions = { '@backstage/plugin-rollbar-backend': pluginRollbarBackend, '@backstage/plugin-scaffolder': pluginScaffolder, '@backstage/plugin-scaffolder-backend': pluginScaffolderBackend, + '@backstage/plugin-search': pluginSearch, '@backstage/plugin-tech-radar': pluginTechRadar, '@backstage/plugin-techdocs': pluginTechdocs, '@backstage/plugin-techdocs-backend': pluginTechdocsBackend, diff --git a/packages/create-app/templates/default-app/packages/app/package.json.hbs b/packages/create-app/templates/default-app/packages/app/package.json.hbs index f284f2da0f..1746f171c9 100644 --- a/packages/create-app/templates/default-app/packages/app/package.json.hbs +++ b/packages/create-app/templates/default-app/packages/app/package.json.hbs @@ -19,6 +19,7 @@ "@backstage/plugin-tech-radar": "^{{version '@backstage/plugin-tech-radar'}}", "@backstage/plugin-github-actions": "^{{version '@backstage/plugin-github-actions'}}", "@backstage/plugin-user-settings": "^{{version '@backstage/plugin-user-settings'}}", + "@backstage/plugin-search": "^{{version '@backstage/plugin-search'}}", "@backstage/test-utils": "^{{version '@backstage/test-utils'}}", "@backstage/theme": "^{{version '@backstage/theme'}}", "history": "^5.0.0", diff --git a/packages/create-app/templates/default-app/packages/app/src/App.tsx b/packages/create-app/templates/default-app/packages/app/src/App.tsx index 4f5c4edea0..0be751eb83 100644 --- a/packages/create-app/templates/default-app/packages/app/src/App.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/App.tsx @@ -14,6 +14,7 @@ import { Router as CatalogRouter } from '@backstage/plugin-catalog'; import { Router as DocsRouter } from '@backstage/plugin-techdocs'; import { Router as RegisterComponentRouter } from '@backstage/plugin-register-component'; import { Router as TechRadarRouter } from '@backstage/plugin-tech-radar'; +import { SearchPage as SearchRouter } from '@backstage/plugin-search' import { EntityPage } from './components/catalog/EntityPage'; @@ -54,6 +55,10 @@ const App = () => ( path="/register-component" element={} /> + } + /> {deprecatedAppRoutes} diff --git a/packages/create-app/templates/default-app/packages/app/src/sidebar.tsx b/packages/create-app/templates/default-app/packages/app/src/sidebar.tsx index db73e706b1..a5595e2c09 100644 --- a/packages/create-app/templates/default-app/packages/app/src/sidebar.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/sidebar.tsx @@ -20,10 +20,12 @@ import { SidebarContext, SidebarSpace, } from '@backstage/core'; +import { SidebarSearch } from '@backstage/plugin-search'; export const AppSidebar = () => ( + {/* Global nav, not org-specific */} From 0101c7a161157f1bdcadc37a965c2140c586c520 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Fri, 18 Dec 2020 11:31:16 +0100 Subject: [PATCH 90/98] Add changeset and add missing semicolon --- .changeset/orange-dancers-occur.md | 5 +++++ .../templates/default-app/packages/app/src/App.tsx | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/orange-dancers-occur.md diff --git a/.changeset/orange-dancers-occur.md b/.changeset/orange-dancers-occur.md new file mode 100644 index 0000000000..0283ffb634 --- /dev/null +++ b/.changeset/orange-dancers-occur.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': minor +--- + +Add search plugin to default template for CLI created apps diff --git a/packages/create-app/templates/default-app/packages/app/src/App.tsx b/packages/create-app/templates/default-app/packages/app/src/App.tsx index 0be751eb83..2e250a94a1 100644 --- a/packages/create-app/templates/default-app/packages/app/src/App.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/App.tsx @@ -14,7 +14,7 @@ import { Router as CatalogRouter } from '@backstage/plugin-catalog'; import { Router as DocsRouter } from '@backstage/plugin-techdocs'; import { Router as RegisterComponentRouter } from '@backstage/plugin-register-component'; import { Router as TechRadarRouter } from '@backstage/plugin-tech-radar'; -import { SearchPage as SearchRouter } from '@backstage/plugin-search' +import { SearchPage as SearchRouter } from '@backstage/plugin-search'; import { EntityPage } from './components/catalog/EntityPage'; From c35554dc4c42dde7279f3a4fbf09602f72f794ad Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 17 Dec 2020 17:20:24 +0100 Subject: [PATCH 91/98] core-api: add lazy loading of component extensions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: blam --- packages/core-api/src/app/App.test.tsx | 17 +++-- .../src/extensions/extensions.test.tsx | 10 ++- .../core-api/src/extensions/extensions.tsx | 54 ++++++++++---- .../core-api/src/plugin/collectors.test.tsx | 16 ++-- .../core-api/src/routing/collectors.test.tsx | 27 +++++-- packages/core-api/src/routing/hooks.test.tsx | 73 ++++++++++++------- plugins/graphiql/src/plugin.ts | 3 +- 7 files changed, 136 insertions(+), 64 deletions(-) diff --git a/packages/core-api/src/app/App.test.tsx b/packages/core-api/src/app/App.test.tsx index 4050343bbf..8dd40d52b0 100644 --- a/packages/core-api/src/app/App.test.tsx +++ b/packages/core-api/src/app/App.test.tsx @@ -66,23 +66,24 @@ describe('Integration Test', () => { const HiddenComponent = plugin2.provide( createRoutableExtension({ - component: (_: { path?: string }) =>
, + component: () => Promise.resolve((_: { path?: string }) =>
), mountPoint: plugin2RouteRef, }), ); const ExposedComponent = plugin1.provide( createRoutableExtension({ - component: (_: PropsWithChildren<{ path?: string }>) => { - // eslint-disable-next-line react-hooks/rules-of-hooks - const routeRefFunction = useRouteRef(externalRouteRef); - return
Our Route Is: {routeRefFunction({})}
; - }, + component: () => + Promise.resolve((_: PropsWithChildren<{ path?: string }>) => { + // eslint-disable-next-line react-hooks/rules-of-hooks + const routeRefFunction = useRouteRef(externalRouteRef); + return
Our Route Is: {routeRefFunction({})}
; + }), mountPoint: plugin1RouteRef, }), ); - it('runs happy path', () => { + it('runs happy path', async () => { const components = { NotFoundErrorPage: () => null, BootErrorPage: () => null, @@ -112,7 +113,7 @@ describe('Integration Test', () => { const Provider = app.getProvider(); const Router = app.getRouter(); - renderWithEffects( + await renderWithEffects( diff --git a/packages/core-api/src/extensions/extensions.test.tsx b/packages/core-api/src/extensions/extensions.test.tsx index 861045fb3d..26755b3bcf 100644 --- a/packages/core-api/src/extensions/extensions.test.tsx +++ b/packages/core-api/src/extensions/extensions.test.tsx @@ -33,7 +33,9 @@ describe('extensions', () => { const Component = () =>
; const extension = createReactExtension({ - component: Component, + component: { + sync: Component, + }, data: { myData: { foo: 'bar' }, }, @@ -51,11 +53,13 @@ describe('extensions', () => { const routeRef = createRouteRef({ path: '/foo', title: 'Foo' }); const extension1 = createComponentExtension({ - component: Component, + component: { + sync: Component, + }, }); const extension2 = createRoutableExtension({ - component: Component, + component: () => Promise.resolve(Component), mountPoint: routeRef, }); diff --git a/packages/core-api/src/extensions/extensions.tsx b/packages/core-api/src/extensions/extensions.tsx index aca29e87dc..adec690f20 100644 --- a/packages/core-api/src/extensions/extensions.tsx +++ b/packages/core-api/src/extensions/extensions.tsx @@ -14,17 +14,30 @@ * limitations under the License. */ -import React from 'react'; +import React, { lazy, Suspense } from 'react'; import { RouteRef } from '../routing'; import { attachComponentData } from './componentData'; import { Extension, BackstagePlugin } from '../plugin/types'; +type ComponentLoader = + | { + lazy: () => Promise; + } + | { + sync: T; + }; + export function createRoutableExtension< T extends (props: any) => JSX.Element ->(options: { component: T; mountPoint: RouteRef }): Extension { +>(options: { + component: () => Promise; + mountPoint: RouteRef; +}): Extension { const { component, mountPoint } = options; return createReactExtension({ - component, + component: { + lazy: component, + }, data: { 'core.mountPoint': mountPoint, }, @@ -33,32 +46,47 @@ export function createRoutableExtension< export function createComponentExtension< T extends (props: any) => JSX.Element ->(options: { component: T }): Extension { +>(options: { component: ComponentLoader }): Extension { const { component } = options; return createReactExtension({ component }); } export function createReactExtension< T extends (props: any) => JSX.Element ->(options: { component: T; data?: Record }): Extension { +>(options: { + component: ComponentLoader; + data?: Record; +}): Extension { const { data = {} } = options; - const Component = options.component as T & { - displayName?: string; - }; + + let Component: T; + if ('lazy' in options.component) { + const lazyLoader = options.component.lazy; + Component = (lazy(() => + lazyLoader().then(component => ({ default: component })), + ) as unknown) as T; + } else { + Component = options.component.sync; + } + const componentName = + (Component as { displayName?: string }).displayName || + Component.name || + 'Component'; return { expose(plugin: BackstagePlugin) { - const Result: any = (props: any) => ; + const Result: any = (props: any) => ( + + + + ); attachComponentData(Result, 'core.plugin', plugin); for (const [key, value] of Object.entries(data)) { attachComponentData(Result, key, value); } - const name = Component.displayName || Component.name || 'Component'; - if (name) { - Result.displayName = `Extension(${name})`; - } + Result.displayName = `Extension(${componentName})`; return Result; }, }; diff --git a/packages/core-api/src/plugin/collectors.test.tsx b/packages/core-api/src/plugin/collectors.test.tsx index e5f8a123e3..5baf2539ab 100644 --- a/packages/core-api/src/plugin/collectors.test.tsx +++ b/packages/core-api/src/plugin/collectors.test.tsx @@ -42,19 +42,25 @@ const ref1 = createRouteRef(mockConfig()); const ref2 = createRouteRef(mockConfig()); const Extension1 = pluginA.provide( - createRoutableExtension({ component: MockComponent, mountPoint: ref1 }), + createRoutableExtension({ + component: () => Promise.resolve(MockComponent), + mountPoint: ref1, + }), ); const Extension2 = pluginB.provide( - createRoutableExtension({ component: MockComponent, mountPoint: ref2 }), + createRoutableExtension({ + component: () => Promise.resolve(MockComponent), + mountPoint: ref2, + }), ); const Extension3 = pluginA.provide( - createComponentExtension({ component: MockComponent }), + createComponentExtension({ component: { sync: MockComponent } }), ); const Extension4 = pluginB.provide( - createComponentExtension({ component: MockComponent }), + createComponentExtension({ component: { sync: MockComponent } }), ); const Extension5 = pluginC.provide( - createComponentExtension({ component: MockComponent }), + createComponentExtension({ component: { sync: MockComponent } }), ); describe('collection', () => { diff --git a/packages/core-api/src/routing/collectors.test.tsx b/packages/core-api/src/routing/collectors.test.tsx index e44474565c..200846f175 100644 --- a/packages/core-api/src/routing/collectors.test.tsx +++ b/packages/core-api/src/routing/collectors.test.tsx @@ -41,19 +41,34 @@ const ref4 = createRouteRef(mockConfig()); const ref5 = createRouteRef(mockConfig()); const Extension1 = plugin.provide( - createRoutableExtension({ component: MockComponent, mountPoint: ref1 }), + createRoutableExtension({ + component: () => Promise.resolve(MockComponent), + mountPoint: ref1, + }), ); const Extension2 = plugin.provide( - createRoutableExtension({ component: MockComponent, mountPoint: ref2 }), + createRoutableExtension({ + component: () => Promise.resolve(MockComponent), + mountPoint: ref2, + }), ); const Extension3 = plugin.provide( - createRoutableExtension({ component: MockComponent, mountPoint: ref3 }), + createRoutableExtension({ + component: () => Promise.resolve(MockComponent), + mountPoint: ref3, + }), ); const Extension4 = plugin.provide( - createRoutableExtension({ component: MockComponent, mountPoint: ref4 }), + createRoutableExtension({ + component: () => Promise.resolve(MockComponent), + mountPoint: ref4, + }), ); const Extension5 = plugin.provide( - createRoutableExtension({ component: MockComponent, mountPoint: ref5 }), + createRoutableExtension({ + component: () => Promise.resolve(MockComponent), + mountPoint: ref5, + }), ); describe('discovery', () => { @@ -190,6 +205,6 @@ describe('discovery', () => { routeParents: routeParentCollector, }, }), - ).toThrow(`Visited element Extension(MockComponent) twice`); + ).toThrow(`Visited element Extension(Component) twice`); }); }); diff --git a/packages/core-api/src/routing/hooks.test.tsx b/packages/core-api/src/routing/hooks.test.tsx index a29e263e14..3dbeaf8e3e 100644 --- a/packages/core-api/src/routing/hooks.test.tsx +++ b/packages/core-api/src/routing/hooks.test.tsx @@ -85,19 +85,34 @@ const MockRouteSource = (props: { }; const Extension1 = plugin.provide( - createRoutableExtension({ component: MockComponent, mountPoint: ref1 }), + createRoutableExtension({ + component: () => Promise.resolve(MockComponent), + mountPoint: ref1, + }), ); const Extension2 = plugin.provide( - createRoutableExtension({ component: MockRouteSource, mountPoint: ref2 }), + createRoutableExtension({ + component: () => Promise.resolve(MockRouteSource), + mountPoint: ref2, + }), ); const Extension3 = plugin.provide( - createRoutableExtension({ component: MockComponent, mountPoint: ref3 }), + createRoutableExtension({ + component: () => Promise.resolve(MockComponent), + mountPoint: ref3, + }), ); const Extension4 = plugin.provide( - createRoutableExtension({ component: MockRouteSource, mountPoint: ref4 }), + createRoutableExtension({ + component: () => Promise.resolve(MockRouteSource), + mountPoint: ref4, + }), ); const Extension5 = plugin.provide( - createRoutableExtension({ component: MockComponent, mountPoint: ref5 }), + createRoutableExtension({ + component: () => Promise.resolve(MockComponent), + mountPoint: ref5, + }), ); function withRoutingProvider( @@ -127,7 +142,7 @@ function withRoutingProvider( } describe('discovery', () => { - it('should handle simple routeRef path creation for routeRefs used in other parts of the app', () => { + it('should handle simple routeRef path creation for routeRefs used in other parts of the app', async () => { const root = ( @@ -151,7 +166,9 @@ describe('discovery', () => { ]), ); - expect(rendered.getByText('Path at inside: /foo/bar')).toBeInTheDocument(); + await expect( + rendered.findByText('Path at inside: /foo/bar'), + ).resolves.toBeInTheDocument(); expect( rendered.getByText('Path at insideExternal: /baz'), ).toBeInTheDocument(); @@ -164,7 +181,7 @@ describe('discovery', () => { ).toBeInTheDocument(); }); - it('should handle routeRefs with parameters', () => { + it('should handle routeRefs with parameters', async () => { const root = ( @@ -187,37 +204,39 @@ describe('discovery', () => { const rendered = render(withRoutingProvider(root)); - expect( - rendered.getByText('Path at inside: /foo/bar/bleb'), - ).toBeInTheDocument(); + await expect( + rendered.findByText('Path at inside: /foo/bar/bleb'), + ).resolves.toBeInTheDocument(); expect( rendered.getByText('Path at outside: /foo/bar/blob'), ).toBeInTheDocument(); }); - it('should handle relative routing within parameterized routePaths', () => { + it('should handle relative routing within parameterized routePaths', async () => { const root = ( - - - - - - - - + + + + + + + + + + ); const rendered = render(withRoutingProvider(root)); - expect( - rendered.getByText('Path at inside: /foo/blob/baz'), - ).toBeInTheDocument(); + await expect( + rendered.findByText('Path at inside: /foo/blob/baz'), + ).resolves.toBeInTheDocument(); }); it('should throw errors for routing to other routeRefs with unsupported parameters', () => { diff --git a/plugins/graphiql/src/plugin.ts b/plugins/graphiql/src/plugin.ts index fb4c33760d..a0bb79ed29 100644 --- a/plugins/graphiql/src/plugin.ts +++ b/plugins/graphiql/src/plugin.ts @@ -19,7 +19,6 @@ import { createApiFactory, createRoutableExtension, } from '@backstage/core'; -import { GraphiQLPage as Component } from './components'; import { graphQlBrowseApiRef, GraphQLEndpoints } from './lib/api'; import { graphiQLRouteRef } from './route-refs'; @@ -42,7 +41,7 @@ export const plugin = createPlugin({ export const GraphiQLPage = plugin.provide( createRoutableExtension({ - component: Component, + component: () => import('./components').then(m => m.GraphiQLPage), mountPoint: graphiQLRouteRef, }), ); From c47ec51a943f73b69cd63535d3f17bae8e05851c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 17 Dec 2020 17:48:57 +0100 Subject: [PATCH 92/98] core-api: memoize app element traversal and validation --- packages/core-api/src/app/App.tsx | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/packages/core-api/src/app/App.tsx b/packages/core-api/src/app/App.tsx index 08393f3e9e..2aaeba9796 100644 --- a/packages/core-api/src/app/App.tsx +++ b/packages/core-api/src/app/App.tsx @@ -242,18 +242,21 @@ export class PrivateAppImpl implements BackstageApp { [], ); - // Probably want to memo this? - const { routePaths, routeParents, routeObjects } = traverseElementTree({ - root: children, - discoverers: [childDiscoverer, routeElementDiscoverer], - collectors: { - routePaths: routePathCollector, - routeParents: routeParentCollector, - routeObjects: routeObjectCollector, - }, - }); + const { routePaths, routeParents, routeObjects } = useMemo(() => { + const result = traverseElementTree({ + root: children, + discoverers: [childDiscoverer, routeElementDiscoverer], + collectors: { + routePaths: routePathCollector, + routeParents: routeParentCollector, + routeObjects: routeObjectCollector, + }, + }); - validateRoutes(routePaths, routeParents); + validateRoutes(result.routePaths, result.routeParents); + + return result; + }, [children]); const loadedConfig = useConfigLoader( this.configLoader, From f0eda7e0aa0f1adde69e3d796deaff22839b523b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 18 Dec 2020 14:21:40 +0100 Subject: [PATCH 93/98] core-api: ensure that routable extension components are discovered at boot Co-authored-by: blam --- .../core-api/src/extensions/extensions.tsx | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/core-api/src/extensions/extensions.tsx b/packages/core-api/src/extensions/extensions.tsx index adec690f20..e56b6901dd 100644 --- a/packages/core-api/src/extensions/extensions.tsx +++ b/packages/core-api/src/extensions/extensions.tsx @@ -15,7 +15,7 @@ */ import React, { lazy, Suspense } from 'react'; -import { RouteRef } from '../routing'; +import { RouteRef, useRouteRef } from '../routing'; import { attachComponentData } from './componentData'; import { Extension, BackstagePlugin } from '../plugin/types'; @@ -36,7 +36,23 @@ export function createRoutableExtension< const { component, mountPoint } = options; return createReactExtension({ component: { - lazy: component, + lazy: () => + component().then(InnerComponent => { + const RoutableExtensionWrapper = ((props: any) => { + // Validate that the routing is wired up correctly in the App.tsx + try { + useRouteRef(mountPoint); + } catch { + throw new Error( + 'Routable extension component was not discovered in the app element tree. ' + + 'Routable extension components may not be rendered by other components and must be ' + + 'directly available as an element within the App provider component.', + ); + } + return ; + }) as T; + return RoutableExtensionWrapper; + }), }, data: { 'core.mountPoint': mountPoint, From 33a82a713792e11024c3fd1b9ae527b18bab3e75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Fri, 18 Dec 2020 15:56:17 +0100 Subject: [PATCH 94/98] scaffolder-backend: gitlab preparer uses integrations token --- .changeset/little-lemons-hope.md | 5 +++ plugins/scaffolder-backend/package.json | 1 + .../scaffolder/stages/prepare/gitlab.test.ts | 37 +++++++++++++--- .../src/scaffolder/stages/prepare/gitlab.ts | 43 +++++++++++++------ 4 files changed, 66 insertions(+), 20 deletions(-) create mode 100644 .changeset/little-lemons-hope.md diff --git a/.changeset/little-lemons-hope.md b/.changeset/little-lemons-hope.md new file mode 100644 index 0000000000..e2a7f747d6 --- /dev/null +++ b/.changeset/little-lemons-hope.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +GitLab preparer uses the right token (primarily the same one as the publisher, falling back to the integrations token) diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index d5f5a5c56b..46abade7c7 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -32,6 +32,7 @@ "@backstage/backend-common": "^0.4.1", "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", + "@backstage/integration": "^0.1.4", "@gitbeaker/core": "^25.2.0", "@gitbeaker/node": "^25.2.0", "@octokit/rest": "^18.0.0", diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts index 3d8d7faf7a..8712507026 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts @@ -42,7 +42,7 @@ const mockEntityWithProtocol = (protocol: string): TemplateEntityV1alpha1 => ({ name: 'graphql-starter', title: 'GraphQL Service', description: - 'A GraphQL starter template for backstage to get you up and running\nthe best pracices with GraphQL\n', + 'A GraphQL starter template for backstage to get you up and running\nthe best practices with GraphQL\n', uid: '9cf16bad-16e0-4213-b314-c4eec773c50b', etag: 'ZTkxMjUxMjUtYWY3Yi00MjU2LWFkYWMtZTZjNjU5ZjJhOWM2', generation: 1, @@ -89,16 +89,41 @@ describe('GitLabPreparer', () => { ); }); - it(`calls the clone command with the correct arguments if an access token is provided for a repository using the ${protocol} protocol`, async () => { + it(`calls the clone command with the correct arguments if an access token is provided in integrations for a repository using the ${protocol} protocol`, async () => { const preparer = new GitlabPreparer( new ConfigReader({ - catalog: { - processors: { - gitlabApi: { - privateToken: 'fake-token', + integrations: { + gitlab: [ + { + host: 'gitlab.com', + token: 'fake-token', }, + ], + }, + }), + ); + mockEntity = mockEntityWithProtocol(protocol); + await preparer.prepare(mockEntity, { logger: getVoidLogger() }); + expect(mocks.Clone.clone).toHaveBeenNthCalledWith( + 1, + 'https://gitlab.com/benjdlambert/backstage-graphql-template', + expect.any(String), + { + fetchOpts: { + callbacks: { + credentials: expect.anything(), }, }, + }, + ); + }); + + it(`calls the clone command with the correct arguments if an access token is provided in scaffolder for a repository using the ${protocol} protocol`, async () => { + const preparer = new GitlabPreparer( + new ConfigReader({ + scaffolder: { + gitlab: { api: { token: 'fake-token' } }, + }, }), ); mockEntity = mockEntityWithProtocol(protocol); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts index 605c8db2df..c2c2dcd3fd 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts @@ -13,24 +13,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import os from 'os'; -import fs from 'fs-extra'; -import path from 'path'; -import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; -import { parseLocationAnnotation } from '../helpers'; import { InputError } from '@backstage/backend-common'; -import { PreparerBase, PreparerOptions } from './types'; +import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; +import { Config } from '@backstage/config'; +import { + GitLabIntegrationConfig, + readGitLabIntegrationConfigs, +} from '@backstage/integration'; +import fs from 'fs-extra'; import GitUriParser from 'git-url-parse'; import { Clone, Cred } from 'nodegit'; -import { Config } from '@backstage/config'; +import os from 'os'; +import path from 'path'; +import { parseLocationAnnotation } from '../helpers'; +import { PreparerBase, PreparerOptions } from './types'; export class GitlabPreparer implements PreparerBase { - private readonly privateToken: string; + private readonly integrations: GitLabIntegrationConfig[]; + private readonly scaffolderToken: string | undefined; constructor(config: Config) { - this.privateToken = - config.getOptionalString('catalog.processors.gitlabApi.privateToken') ?? - ''; + this.integrations = readGitLabIntegrationConfigs( + config.getOptionalConfigArray('integrations.gitlab') ?? [], + ); + this.scaffolderToken = config.getOptionalString( + 'scaffolder.gitlab.api.token', + ); } async prepare( @@ -58,12 +66,12 @@ export class GitlabPreparer implements PreparerBase { template.spec.path ?? '.', ); - const options = this.privateToken + const token = this.getToken(parsedGitLocation.resource); + const options = token ? { fetchOpts: { callbacks: { - credentials: () => - Cred.userpassPlaintextNew('oauth2', this.privateToken), + credentials: () => Cred.userpassPlaintextNew('oauth2', token), }, }, } @@ -73,4 +81,11 @@ export class GitlabPreparer implements PreparerBase { return path.resolve(tempDir, templateDirectory); } + + private getToken(host: string): string | undefined { + return ( + this.scaffolderToken || + this.integrations.find(c => c.host === host)?.token + ); + } } From aed8f7f12f1d0c691a6c4e80c2e50f253c4fcf06 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 16 Dec 2020 22:27:11 +0100 Subject: [PATCH 95/98] scaffolder-backend: clarify type detection error message --- .changeset/warm-moose-applaud.md | 5 +++++ .../src/scaffolder/stages/prepare/preparers.ts | 12 +++++++++++- .../src/scaffolder/stages/publish/publishers.ts | 12 +++++++++++- 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 .changeset/warm-moose-applaud.md diff --git a/.changeset/warm-moose-applaud.md b/.changeset/warm-moose-applaud.md new file mode 100644 index 0000000000..70ae20711a --- /dev/null +++ b/.changeset/warm-moose-applaud.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Clearer error message when preparer or publisher type can't be determined. diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.ts index 226f7e3836..84be130b79 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.ts @@ -50,7 +50,17 @@ export class Preparers implements PreparerBuilder { if (detected) { return detected; } - throw new Error(`No preparer integration found for url "${location}"`); + if (type) { + throw new Error( + `No preparer configuration available for type '${type}' with url "${location}". ` + + "Make sure you've added appropriate configuration in the 'scaffolder' configuration section", + ); + } else { + throw new Error( + `Failed to detect preparer type. Unable to determine integration type for location "${location}". ` + + "Please add appropriate configuration to the 'integrations' configuration section", + ); + } } throw new Error(`No preparer registered for type: "${protocol}"`); } diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts index 961fc45cae..03a4e884ba 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts @@ -51,7 +51,17 @@ export class Publishers implements PublisherBuilder { if (detected) { return detected; } - throw new Error(`No preparer integration found for url "${location}"`); + if (type) { + throw new Error( + `No publisher configuration available for type '${type}' with url "${location}". ` + + "Make sure you've added appropriate configuration in the 'scaffolder' configuration section", + ); + } else { + throw new Error( + `Failed to detect publisher type. Unable to determine integration type for location "${location}". ` + + "Please add appropriate configuration to the 'integrations' configuration section", + ); + } } throw new Error(`No publisher registered for type: "${protocol}"`); } From 20533789d6ab4502ccf4970ee6167eb7f1195975 Mon Sep 17 00:00:00 2001 From: Erik Larsson Date: Mon, 21 Dec 2020 00:13:22 +0100 Subject: [PATCH 96/98] docs: Update lighthouse docs --- plugins/lighthouse/README.md | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/plugins/lighthouse/README.md b/plugins/lighthouse/README.md index 1f1d32937f..42de0a2591 100644 --- a/plugins/lighthouse/README.md +++ b/plugins/lighthouse/README.md @@ -30,24 +30,17 @@ to enable the plugin: export { plugin as LighthousePlugin } from '@backstage/plugin-lighthouse'; ``` -Then, you need to use the `lighthouseApiRef` exported from the plugin to initialize the Rest API in -your [`apis.ts`](https://github.com/backstage/backstage/blob/master/packages/app/src/apis.ts). +Modify your app routes to include the Router component exported from the plugin, for example: -```js -import { ApiHolder, ApiRegistry } from '@backstage/core'; -import { Config } from '@backstage/config'; -import { - lighthouseApiRef, - LighthouseRestApi, -} from '@backstage/plugin-lighthouse'; +```tsx +import { Router as LighthouseRouter } from '@backstage/plugin-lighthouse'; -export const apis = (config: ConfigApi) => { - const builder = ApiRegistry.builder(); - - builder.add(lighthouseApiRef, LighthouseRestApi.fromConfig(config)); - - return builder.build() as ApiHolder; -} +// Inside App component + + // ... + } /> + // ... +; ``` Then configure the lighthouse service url in your [`app-config.yaml`](https://github.com/backstage/backstage/blob/master/app-config.yaml). @@ -86,7 +79,7 @@ const WebsiteEntityPage = ({ entity }: { entity: Entity }) => ( // ... } /> From 1d2708c6fe497de30078c09aa2f5fff715fdf217 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Dec 2020 04:56:34 +0000 Subject: [PATCH 97/98] build(deps): bump typescript-json-schema from 0.45.0 to 0.45.1 Bumps [typescript-json-schema](https://github.com/YousefED/typescript-json-schema) from 0.45.0 to 0.45.1. - [Release notes](https://github.com/YousefED/typescript-json-schema/releases) - [Commits](https://github.com/YousefED/typescript-json-schema/compare/v0.45.0...v0.45.1) Signed-off-by: dependabot[bot] --- yarn.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/yarn.lock b/yarn.lock index 0923d3ed70..abfd01f0d6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24235,20 +24235,20 @@ typedarray@^0.0.6: integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= typescript-json-schema@^0.45.0: - version "0.45.0" - resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.45.0.tgz#2f244e99518e589a442ee5f9c1d2c85a1ec7dc84" - integrity sha512-4MeX0HIODRd+K1/sIbkPryGXG43PVQ9cvIC8gDYml6yBgcsWLjvPMpTNr9VV+bQwpDLncB8Ie4qSenuKUwNZpg== + version "0.45.1" + resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.45.1.tgz#d3c1feea85b3bfeaf7e42a8c3bab80f2dc121a5d" + integrity sha512-Iz1NKVtJi09iZSzXj3J350GekBrZ1TiNw6Cbf42jLOGyooh9BWoi8XP6XlTIMOI3aMD8XxuL9hEvIEq8FD/WUw== dependencies: "@types/json-schema" "^7.0.6" glob "^7.1.6" json-stable-stringify "^1.0.1" - typescript "^4.1.2" - yargs "^16.1.1" + typescript "^4.1.3" + yargs "^16.2.0" -typescript@^4.0.3, typescript@^4.1.2: - version "4.1.2" - resolved "https://registry.npmjs.org/typescript/-/typescript-4.1.2.tgz#6369ef22516fe5e10304aae5a5c4862db55380e9" - integrity sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ== +typescript@^4.0.3, typescript@^4.1.3: + version "4.1.3" + resolved "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7" + integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== ua-parser-js@^0.7.18: version "0.7.21" @@ -25588,10 +25588,10 @@ yargs@^15.1.0, yargs@^15.3.1, yargs@^15.4.1: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^16.0.3, yargs@^16.1.1: - version "16.1.1" - resolved "https://registry.npmjs.org/yargs/-/yargs-16.1.1.tgz#5a4a095bd1ca806b0a50d0c03611d38034d219a1" - integrity sha512-hAD1RcFP/wfgfxgMVswPE+z3tlPFtxG8/yWUrG2i17sTWGCGqWnxKcLTF4cUKDUK8fzokwsmO9H0TDkRbMHy8w== +yargs@^16.0.3, yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== dependencies: cliui "^7.0.2" escalade "^3.1.1" From 6e65800eb6f9ca64d56995ab7a1afb51da6aeaec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Dec 2020 05:08:20 +0000 Subject: [PATCH 98/98] build(deps): bump archiver from 5.0.2 to 5.1.0 Bumps [archiver](https://github.com/archiverjs/node-archiver) from 5.0.2 to 5.1.0. - [Release notes](https://github.com/archiverjs/node-archiver/releases) - [Changelog](https://github.com/archiverjs/node-archiver/blob/master/CHANGELOG.md) - [Commits](https://github.com/archiverjs/node-archiver/compare/5.0.2...5.1.0) Signed-off-by: dependabot[bot] --- yarn.lock | 84 +++++++++++++++++++++++++------------------------------ 1 file changed, 38 insertions(+), 46 deletions(-) diff --git a/yarn.lock b/yarn.lock index 0923d3ed70..8594739552 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7386,9 +7386,9 @@ archiver-utils@^2.1.0: readable-stream "^2.0.0" archiver@^5.0.2: - version "5.0.2" - resolved "https://registry.npmjs.org/archiver/-/archiver-5.0.2.tgz#b2c435823499b1f46eb07aa18e7bcb332f6ca3fc" - integrity sha512-Tq3yV/T4wxBsD2Wign8W9VQKhaUxzzRmjEiSoOK0SLqPgDP/N1TKdYyBeIEu56T4I9iO4fKTTR0mN9NWkBA0sg== + version "5.1.0" + resolved "https://registry.npmjs.org/archiver/-/archiver-5.1.0.tgz#05b0f6f7836f3e6356a0532763d2bb91017a7e37" + integrity sha512-iKuQUP1nuKzBC2PFlGet5twENzCfyODmvkxwDV0cEFXavwcLrIW5ssTuHi9dyTPvpWr6Faweo2eQaQiLIwyXTA== dependencies: archiver-utils "^2.1.0" async "^3.2.0" @@ -7396,7 +7396,7 @@ archiver@^5.0.2: readable-stream "^3.6.0" readdir-glob "^1.0.0" tar-stream "^2.1.4" - zip-stream "^4.0.0" + zip-stream "^4.0.4" are-we-there-yet@~1.1.2: version "1.1.5" @@ -8288,7 +8288,7 @@ bl@^1.0.0: readable-stream "^2.3.5" safe-buffer "^5.1.1" -bl@^4.0.1, bl@^4.0.3: +bl@^4.0.3: version "4.0.3" resolved "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz#12d6287adc29080e22a705e5764b2a9522cdc489" integrity sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg== @@ -8613,14 +8613,6 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.1.0: - version "5.7.1" - resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - buffer@^5.5.0: version "5.6.0" resolved "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" @@ -9507,13 +9499,13 @@ component-emitter@^1.2.0, component-emitter@^1.2.1: resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== -compress-commons@^4.0.0: - version "4.0.1" - resolved "https://registry.npmjs.org/compress-commons/-/compress-commons-4.0.1.tgz#c5fa908a791a0c71329fba211d73cd2a32005ea8" - integrity sha512-xZm9o6iikekkI0GnXCmAl3LQGZj5TBDj0zLowsqi7tJtEa3FMGSEcHcqrSJIrOAk1UG/NBbDn/F1q+MG/p/EsA== +compress-commons@^4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/compress-commons/-/compress-commons-4.0.2.tgz#d6896be386e52f37610cef9e6fa5defc58c31bd7" + integrity sha512-qhd32a9xgzmpfoga1VQEiLEwdKZ6Plnpx5UCgIsf89FSolyJ7WnifY4Gtjgv5WR6hWAyRaHxC5MiEhU/38U70A== dependencies: buffer-crc32 "^0.2.13" - crc32-stream "^4.0.0" + crc32-stream "^4.0.1" normalize-path "^3.0.0" readable-stream "^3.6.0" @@ -9914,20 +9906,21 @@ cpy@^8.1.1: p-filter "^2.1.0" p-map "^3.0.0" -crc32-stream@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.0.tgz#05b7ca047d831e98c215538666f372b756d91893" - integrity sha512-tyMw2IeUX6t9jhgXI6um0eKfWq4EIDpfv5m7GX4Jzp7eVelQ360xd8EPXJhp2mHwLQIkqlnMLjzqSZI3a+0wRw== +crc-32@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208" + integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA== dependencies: - crc "^3.4.4" - readable-stream "^3.4.0" + exit-on-epipe "~1.0.1" + printj "~1.1.0" -crc@^3.4.4: - version "3.8.0" - resolved "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6" - integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ== +crc32-stream@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.1.tgz#0f047d74041737f8a55e86837a1b826bd8ab0067" + integrity sha512-FN5V+weeO/8JaXsamelVYO1PHyeCsuL3HcG4cqsj0ceARcocxalaShCsohZMSAF+db7UYFwBy1rARK/0oFItUw== dependencies: - buffer "^5.1.0" + crc-32 "^1.2.0" + readable-stream "^3.4.0" create-ecdh@^4.0.0: version "4.0.3" @@ -12126,6 +12119,11 @@ exit-hook@^1.0.0: resolved "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" integrity sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g= +exit-on-epipe@~1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692" + integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw== + exit@^0.1.2: version "0.1.2" resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -20059,6 +20057,11 @@ pretty-hrtime@^1.0.3: resolved "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= +printj@~1.1.0: + version "1.1.2" + resolved "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" + integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ== + prismjs@^1.21.0, prismjs@~1.21.0: version "1.21.0" resolved "https://registry.npmjs.org/prismjs/-/prismjs-1.21.0.tgz#36c086ec36b45319ec4218ee164c110f9fc015a3" @@ -23493,18 +23496,7 @@ tar-stream@^1.1.2: to-buffer "^1.1.1" xtend "^4.0.0" -tar-stream@^2.0.0: - version "2.1.2" - resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.2.tgz#6d5ef1a7e5783a95ff70b69b97455a5968dc1325" - integrity sha512-UaF6FoJ32WqALZGOIAApXx+OdxhekNMChu6axLJR85zMMjXKWFGjbIRe+J6P4UnRGg9rAwWvbTT0oI7hD/Un7Q== - dependencies: - bl "^4.0.1" - end-of-stream "^1.4.1" - fs-constants "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.1.1" - -tar-stream@^2.1.4: +tar-stream@^2.0.0, tar-stream@^2.1.4: version "2.1.4" resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.4.tgz#c4fb1a11eb0da29b893a5b25476397ba2d053bfa" integrity sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw== @@ -25683,13 +25675,13 @@ zenscroll@^4.0.2: resolved "https://registry.npmjs.org/zenscroll/-/zenscroll-4.0.2.tgz#e8d5774d1c0738a47bcfa8729f3712e2deddeb25" integrity sha1-6NV3TRwHOKR7z6hynzcS4t7d6yU= -zip-stream@^4.0.0: - version "4.0.2" - resolved "https://registry.npmjs.org/zip-stream/-/zip-stream-4.0.2.tgz#3a20f1bd7729c2b59fd4efa04df5eb7a5a217d2e" - integrity sha512-TGxB2g+1ur6MHkvM644DuZr8Uzyz0k0OYWtS3YlpfWBEmK4woaC2t3+pozEL3dBfIPmpgmClR5B2QRcMgGt22g== +zip-stream@^4.0.4: + version "4.0.4" + resolved "https://registry.npmjs.org/zip-stream/-/zip-stream-4.0.4.tgz#3a8f100b73afaa7d1ae9338d910b321dec77ff3a" + integrity sha512-a65wQ3h5gcQ/nQGWV1mSZCEzCML6EK/vyVPcrPNynySP1j3VBbQKh3nhC8CbORb+jfl2vXvh56Ul5odP1bAHqw== dependencies: archiver-utils "^2.1.0" - compress-commons "^4.0.0" + compress-commons "^4.0.2" readable-stream "^3.6.0" zombie@^6.1.4:

2tx$*YN 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�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�ObJWyN*zO{ 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� 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⪙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%0D@G9%7Eh|%WR94hYBusIqCc?xn<;q2T{{|?Ko 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%0DJ_eCk6Sq24fePOnw4=A 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