diff --git a/.changeset/bright-lions-camp.md b/.changeset/bright-lions-camp.md deleted file mode 100644 index fee5d5b5fc..0000000000 --- a/.changeset/bright-lions-camp.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Allow custom directory to be specified for GitHub publish action diff --git a/.changeset/chatty-ghosts-lay.md b/.changeset/chatty-ghosts-lay.md new file mode 100644 index 0000000000..7d8ef3edbd --- /dev/null +++ b/.changeset/chatty-ghosts-lay.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-sonarqube': patch +--- + +Export isSonarQubeAvailable. diff --git a/.changeset/clever-walls-bow.md b/.changeset/clever-walls-bow.md new file mode 100644 index 0000000000..36e56f6e37 --- /dev/null +++ b/.changeset/clever-walls-bow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Add built-in publish action for creating GitHub pull requests. diff --git a/.changeset/eight-files-rhyme.md b/.changeset/eight-files-rhyme.md deleted file mode 100644 index c45556366d..0000000000 --- a/.changeset/eight-files-rhyme.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-badges': minor -'@backstage/plugin-badges-backend': patch ---- - -Support auth in badge plugin diff --git a/.changeset/fair-geese-yell.md b/.changeset/fair-geese-yell.md deleted file mode 100644 index 00c5b16854..0000000000 --- a/.changeset/fair-geese-yell.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -'@backstage/config-loader': minor ---- - -Fix bug where `$${...}` was not being escaped to `${...}` - -Add support for environment variable substitution in `$include`, `$file` and -`$env` transform values. - -- This change allows for including dynamic paths, such as environment specific - secrets by using the same environment variable substitution (`${..}`) already - supported outside of the various include transforms. -- If you are currently using the syntax `${...}` in your include transform values, - you will need to escape the substitution by using `$${...}` instead to maintain - the same behavior. diff --git a/.changeset/fluffy-rice-push.md b/.changeset/fluffy-rice-push.md new file mode 100644 index 0000000000..032d580c6b --- /dev/null +++ b/.changeset/fluffy-rice-push.md @@ -0,0 +1,30 @@ +--- +'@backstage/create-app': patch +--- + +Fixing dependency resolution for problematic library `graphql-language-service-interface`. + +This change might not have to be applied to your local installation, however if you run into this error: + +``` +Error: Failed to compile. +/tmp/backstage-e2e-uMeycm/test-app/node_modules/graphql-language-service-interface/esm/GraphQLLanguageService.js 100:23 +Module parse failed: Unexpected token (100:23) +You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders +| } +| let customRules = null; +> if (extensions?.customValidationRules && +| typeof extensions.customValidationRules === 'function') { +| customRules = extensions.customValidationRules(this._graphQLConfig); +``` + +You can fix it by adding the following to the root `package.json`. + +```json +... +"resolutions": { + "graphql-language-service-interface": "2.8.2", + "graphql-language-service-parser": "1.9.0" + }, +... +``` diff --git a/.changeset/forty-ladybugs-move.md b/.changeset/forty-ladybugs-move.md deleted file mode 100644 index 254efea584..0000000000 --- a/.changeset/forty-ladybugs-move.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-backend': patch ---- - -When using OAuth2 authentication the name is now taken from the name property of the JWT instead of the email property diff --git a/.changeset/forty-paws-drum.md b/.changeset/forty-paws-drum.md new file mode 100644 index 0000000000..1f3b587b8a --- /dev/null +++ b/.changeset/forty-paws-drum.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Fix for the `file://` protocol check in the `FilePreparer` being too strict, breaking Windows. diff --git a/.changeset/forty-queens-hear.md b/.changeset/forty-queens-hear.md deleted file mode 100644 index 5e0b35162a..0000000000 --- a/.changeset/forty-queens-hear.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/core': patch -'@backstage/core-api': patch ---- - -Introduce a `load-chunk` step in the `BootErrorPage` to show make chunk loading -errors visible to the user. diff --git a/.changeset/funny-donkeys-jam.md b/.changeset/funny-donkeys-jam.md deleted file mode 100644 index 0c45d4b5ff..0000000000 --- a/.changeset/funny-donkeys-jam.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/core-api': patch -'@backstage/core': patch ---- - -Improved error messaging for routable extension errors, making it easier to identify the component and mount point that caused the error. diff --git a/.changeset/green-otters-grin.md b/.changeset/green-otters-grin.md new file mode 100644 index 0000000000..abfd332a2b --- /dev/null +++ b/.changeset/green-otters-grin.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Add support for configure an LDAP query filter on multiple lines. diff --git a/.changeset/little-starfishes-whisper.md b/.changeset/little-starfishes-whisper.md deleted file mode 100644 index ea00753b4f..0000000000 --- a/.changeset/little-starfishes-whisper.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/catalog-model': patch ---- - -Added `stringifyEntityRef`, which always creates a string representation of an entity reference. Also deprecated `serializeEntityRef`, as `stringifyEntityRef` should be used instead. diff --git a/.changeset/loud-apricots-fix.md b/.changeset/loud-apricots-fix.md new file mode 100644 index 0000000000..3763ebf0e3 --- /dev/null +++ b/.changeset/loud-apricots-fix.md @@ -0,0 +1,31 @@ +--- +'@backstage/create-app': patch +'@backstage/plugin-scaffolder': minor +--- + +Expose the catalog-import route as an external route from the scaffolder. + +This will make it possible to hide the "Register Existing Component" button +when you for example are running backstage with `catalog.readonly=true`. + +As a consequence of this change you need add a new binding to your createApp call to +keep the button visible. However, if you instead want to hide the button you can safely +ignore the following example. + +To bind the external route from the catalog-import plugin to the scaffolder template +index page, make sure you have the appropriate imports and add the following +to the createApp call: + +```typescript +import { catalogImportPlugin } from '@backstage/plugin-catalog-import'; + +const app = createApp({ + // ... + bindRoutes({ bind }) { + // ... + bind(scaffolderPlugin.externalRoutes, { + registerComponent: catalogImportPlugin.routes.importPage, + }); + }, +}); +``` diff --git a/.changeset/neat-lions-peel.md b/.changeset/neat-lions-peel.md deleted file mode 100644 index 1cd50641ec..0000000000 --- a/.changeset/neat-lions-peel.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/core-api': patch -'@backstage/core': patch ---- - -Fixed a bug with `useRouteRef` where navigating from routes beneath a mount point would often fail. diff --git a/.changeset/odd-toys-kiss.md b/.changeset/odd-toys-kiss.md new file mode 100644 index 0000000000..888ba5f752 --- /dev/null +++ b/.changeset/odd-toys-kiss.md @@ -0,0 +1,14 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Bitbucket server needs username to be set as well as the token or appPassword for the publishing process to work. + +```yaml +integrations: + bitbucket: + - host: bitbucket.mycompany.com + apiBaseUrl: https://bitbucket.mycompany.com/rest/api/1.0 + token: token + username: username +``` diff --git a/.changeset/old-spies-love.md b/.changeset/old-spies-love.md deleted file mode 100644 index 722d9d937e..0000000000 --- a/.changeset/old-spies-love.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-import': patch ---- - -When importing components you will now have the ability to use non Unicode characters in the entity owner field diff --git a/.changeset/polite-cameras-sin.md b/.changeset/polite-cameras-sin.md deleted file mode 100644 index b7989be2c6..0000000000 --- a/.changeset/polite-cameras-sin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/test-utils': patch ---- - -Remove unnecessary wrapping of elements rendered by `wrapInTestApp` and `renderInTestApp`, which was breaking mount discovery. diff --git a/.changeset/red-planets-hammer.md b/.changeset/red-planets-hammer.md new file mode 100644 index 0000000000..eb72314556 --- /dev/null +++ b/.changeset/red-planets-hammer.md @@ -0,0 +1,13 @@ +--- +'@backstage/catalog-model': patch +'@backstage/plugin-catalog-backend': patch +'@backstage/plugin-catalog': patch +--- + +Implemented missing support for the dependsOn/dependencyOf relationships +between `Component` and `Resource` catalog model objects. + +Added support for generating the relevant relationships to the +`BuiltinKindsEntityProcessor`, and added simple support for fetching +relationships between `Components` and `Resources` for rendering in the +system diagram. All catalog-model changes backwards compatible. diff --git a/.changeset/sharp-rings-march.md b/.changeset/sharp-rings-march.md deleted file mode 100644 index 81ea9aa9df..0000000000 --- a/.changeset/sharp-rings-march.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/catalog-model': patch -'@backstage/core': patch -'@backstage/plugin-catalog': patch -'@backstage/plugin-scaffolder': patch ---- - -Add support for multiple links to post-scaffold task summary page diff --git a/.changeset/stale-geese-rule.md b/.changeset/stale-geese-rule.md deleted file mode 100644 index f22ca2983d..0000000000 --- a/.changeset/stale-geese-rule.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-org': patch ---- - -Optimize data fetched for the `OwnershipCard`. diff --git a/.changeset/stale-jobs-tease.md b/.changeset/stale-jobs-tease.md new file mode 100644 index 0000000000..e62f87afe7 --- /dev/null +++ b/.changeset/stale-jobs-tease.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-techdocs-backend': patch +--- + +Change the response status of metadata endpoints in case a documentation is not +available to `404 NOT FOUND`. This also introduces the JSON based error messages +used by other backends. diff --git a/.changeset/tasty-apples-sell.md b/.changeset/tasty-apples-sell.md new file mode 100644 index 0000000000..d24cd61e37 --- /dev/null +++ b/.changeset/tasty-apples-sell.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Adds a collaborator field to GitHub publish action for multiple users and access levels diff --git a/.changeset/techdocs-dry-starfishes-carry.md b/.changeset/techdocs-dry-starfishes-carry.md new file mode 100644 index 0000000000..f5841c6994 --- /dev/null +++ b/.changeset/techdocs-dry-starfishes-carry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Add borders to TechDocs tables and increase font size. Fixes #5264 and #5276. diff --git a/.changeset/tender-turtles-smash.md b/.changeset/tender-turtles-smash.md new file mode 100644 index 0000000000..645ed688db --- /dev/null +++ b/.changeset/tender-turtles-smash.md @@ -0,0 +1,6 @@ +--- +'@backstage/core': patch +'@backstage/plugin-api-docs': patch +--- + +add debounce time attribute for apis-docs for search, giving more time to the users when they are typing. diff --git a/.changeset/thirty-owls-lay.md b/.changeset/thirty-owls-lay.md new file mode 100644 index 0000000000..3f3ce64606 --- /dev/null +++ b/.changeset/thirty-owls-lay.md @@ -0,0 +1,5 @@ +--- +'@backstage/core': patch +--- + +exposes undocumented `PageTheme` diff --git a/.changeset/thirty-panthers-learn.md b/.changeset/thirty-panthers-learn.md deleted file mode 100644 index f0e2c05e81..0000000000 --- a/.changeset/thirty-panthers-learn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-github-deployments': patch ---- - -Add a button to reload the GitHub Deployments card diff --git a/.changeset/wicked-mirrors-scream.md b/.changeset/wicked-mirrors-scream.md new file mode 100644 index 0000000000..204d3b7eac --- /dev/null +++ b/.changeset/wicked-mirrors-scream.md @@ -0,0 +1,5 @@ +--- +'@backstage/core': patch +--- + +Don't use a drag & drop cursor when clicking on disabled `IconLinkVertical`. diff --git a/.changeset/witty-rats-bake.md b/.changeset/witty-rats-bake.md new file mode 100644 index 0000000000..2189961899 --- /dev/null +++ b/.changeset/witty-rats-bake.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Fix bug in pull request sample template. diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index b0bcf9c9f7..8c385e1bbb 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -13,6 +13,7 @@ Cloudformation Codecov Codehilite Config +Debounce Discoverability Dockerfile Dockerize @@ -111,6 +112,7 @@ cookiecutter css dataflow deadnaming +debounce declaratively destructured dev diff --git a/ADOPTERS.md b/ADOPTERS.md index 218a4edeba..45842b1833 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -24,3 +24,4 @@ | [Trendyol](https://trendyol.com) | [Erdogan Oksuz](https://github.com/erdoganoksuz) | The Developer Portal has been called `Pandora`. Provides an overview of Trendyol tech ecosystem. TechDocs, Catalog, Custom Plugins and Theme. | | [Peloton](https://www.onepeloton.com/) | [Jim Haughwout](https://github.com/JimHaughwout) | Creating our first developer portal and tech-docs. Exploring Service Catalog, Tech Insights and Cost Insights as well. | | [TELUS](https://telus.com) | [Seb Barre](https://github.com/sbarre) | The Go-to place to find answers about development and delivery at TELUS. | +| [Brex](https://www.brex.com/) | [Vamsi Chitters](https://github.com/vamsikc) | A centralized UI to understand how a service fits in the whole Brex architecture and manage a team’s engineering dependencies. | diff --git a/app-config.yaml b/app-config.yaml index 465c7b0049..309fa28234 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -150,6 +150,10 @@ integrations: - host: dev.azure.com token: $env: AZURE_TOKEN +# googleGcs: +# clientEmail: 'example@example.com' +# privateKey: +# $env: GCS_PRIVATE_KEY catalog: rules: diff --git a/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md new file mode 100644 index 0000000000..ba0aef89ea --- /dev/null +++ b/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md @@ -0,0 +1,170 @@ +# Using AWS Application Load Balancer with Azure Active Directory to authenticate requests + +Backstage allows offloading the responsibility of authenticating users to an AWS Application Load Balancer (**ALB**), leveraging the authentication support on ALB. +This tutorial shows how to use authentication on an ALB sitting in front of Backstage. +Azure Active Directory (**AAD**) is used as identity provider but any identity provider supporting OpenID Connect (OIDC) can be used. + +It is assumed an ALB is already serving traffic in front of a Backstage instance configured to serve the frontend app from the backend. + +## Infrastructure setup + +### AAD App + +The AAD App is used to execute the authentication flow, serve and refresh the identity token. + +Create the AAD App following the steps outlined in `Create a Microsoft App Registration in Microsoft Portal` section from the tutorial [Monorepo App Setup With Authentication][monorepo-app-setup-with-auth]. + +Instead of `localhost` addresses, use the following values. + +- Identifier URI: `https://backstage.yourdomain.com` +- Redirect URI: `https://backstage.yourdomain.com/oauth2/idpresponse` + +`Application (client) Id`, `Directory (tenant) ID` and `client secret`values will be used while configuring the ALB. + +### ALB + +In the AWS console, configure ALB Authentication: + +- Edit the ALB rule used to forward the traffic to Backstage and add a new `Authenticate` action. The action will have higher priority compared to the existing `Forward to`. +- Select `OIDC` under `Authenticate` +- Set `Issuer` to `https://login.microsoftonline.com/{TENANT_ID}/v2.0`, replacing `{TENANT_ID}` with the value of `Directory (tenant) ID` of the AAD App. +- Set `Authorization endpoint` to `https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/authorize`, replacing `{TENANT_ID}` with the value of `Directory (tenant) ID` of the AAD App. +- Set `Token endpoint` to `https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/authorize`, replacing `{TENANT_ID}` with the value of `Directory (tenant) ID` of the AAD App. +- Set `User info endpoint` to `https://graph.microsoft.com/oidc/userinfo` +- Set `Client ID` to the AAD App `Application (client) Id` +- Set `Client secret` to the AAD APP `client secret` + +Use the following advanced settings: + +- `Session cookie name` = `AWSELBAuthSessionCookie` +- `Session timeout` = `604800` seconds +- `Scope` = `openid profile offline_access` +- `Action on unauthenticated request` = `Autenticate (client reattempt)` + +Once you've saved the action, you should see an authentication flow be triggered against AAD when visiting Backstage address at `https://backstage.yourdomain.com`. The flow will not complete successfully as the Backstage app isn't yet configured properly. + +## Backstage changes + +### Frontend + +The Backstage App needs a SignInPage when authentication is required. +When using ALB authentication Backstage will only be loaded once the user has successfully authenticated; we won't need to display a SignIn page, however we will need to create a dummy SignIn component that can refresh the token. + +- edit `packages/app/src/App.tsx` +- import the following two additional definitions from `@backstage/core`: `useApi`, `configApiRef`; these will be used to check whether Backstage is running locally or behind an ALB +- add the following definition just before the app is created (`const app = createApp`): + +```ts +const DummySignInComponent: any = (props: any) => { + try { + const config = useApi(configApiRef); + const shouldAuth = !!config.getOptionalConfig('auth.providers.awsalb'); + if (shouldAuth) { + fetch(`${window.location.origin}/api/auth/awsalb/refresh`) + .then(data => data.json()) + .then(data => { + props.onResult({ + userId: data.backstageIdentity.id, + profile: data.profile, + }); + }); + } else { + props.onResult({ + userId: 'guest', + profile: { + email: 'guest@example.com', + displayName: 'Guest', + picture: '', + }, + }); + } + return
; + } catch (err) { + return
{err.message}
; + } +}; +``` + +- add `DummySignInComponent` as `SignInPage`: + +```ts +const app = createApp({ + ... + components: { + SignInPage: DummySignInComponent, + ... + }, + ... +}); +``` + +### Backend + +When using ALB auth it is not possible to leverage the built-in auth config discovery mechanism implemented in the app created by default; bespoke logic needs to be implemented. + +- replace the content of `packages/backend/plugin/auth.ts` with the below + +```ts +import { + createRouter, + AuthResponse, + AuthProviderFactoryOptions, + defaultAuthProviderFactories, +} from '@backstage/plugin-auth-backend'; +import { PluginEnvironment } from '../types'; + +export default async function createPlugin({ + logger, + database, + config, + discovery, +}: PluginEnvironment) { + const identityResolver = (payload: any): Promise> => { + return Promise.resolve({ + providerInfo: {}, + profile: { + email: payload.email, + displayName: payload.name, + picture: payload.picture, + }, + backstageIdentity: { + id: payload.email, + }, + }); + }; + const providerFactories = { + awsalb: (options: AuthProviderFactoryOptions) => + defaultAuthProviderFactories.awsalb({ ...options, identityResolver }), + }; + return await createRouter({ + logger, + config, + database, + discovery, + providerFactories, + }); +} +``` + +### Configuration + +Use the following `auth` configuration when running Backstage on AWS: + +```yaml +auth: + providers: + awsalb: + issuer: + issuer: https://login.microsoftonline.com/{TENANT_ID}/v2.0 + region: { AWS_REGION } +``` + +Replace `{TENANT_ID}` with the value of `Directory (tenant) ID` of the AAD App and `{AWS_REGION}` with the AWS region identifier where the ALB is deployed (for example: `eu-central-1`). + +## Conclusion + +Once it's deployed, after going through the AAD authentication flow, Backstage should display the AAD user details. + + + +[monorepo-app-setup-with-auth-ms]: https://backstage.io/docs/tutorials/quickstart-app-auth#the-auth-configuration diff --git a/docs/auth/index.md b/docs/auth/index.md index 6e3747dd25..fc6ce33e2b 100644 --- a/docs/auth/index.md +++ b/docs/auth/index.md @@ -22,7 +22,7 @@ Backstage comes with many common authentication providers in the core library: - [GitLab](gitlab/provider.md) - [Google](google/provider.md) - [Okta](okta/provider.md) -- OneLogin +- [OneLogin](onelogin/provider.md) These built-in providers handle the authentication flow for a particular service including required scopes, callbacks, etc. These providers are each added to a diff --git a/docs/auth/onelogin/provider.md b/docs/auth/onelogin/provider.md new file mode 100644 index 0000000000..62c1657fea --- /dev/null +++ b/docs/auth/onelogin/provider.md @@ -0,0 +1,54 @@ +--- +id: provider +title: OneLogin Authentication Provider +sidebar_label: OneLogin +description: Adding OneLogin OIDC as an authentication provider in Backstage +--- + +The Backstage `core-api` package comes with a OneLogin authentication provider +that can authenticate users using OpenID Connect. + +## Create an Application on OneLogin + +To support OneLogin authentication, you must create an Application: + +1. From the OneLogin Admin portal, choose Applications +2. Click `Add App` and select `OpenID Connect` + - Display Name: Backstage (or your custom app name) +3. Click Save +4. Go to the Configuration tab for the Application and set: + - `Login Url`: `http://localhost:3000` + - `Redirect URIs`: `http://localhost:7000/api/auth/onelogin/handler/frame` +5. Click Save +6. Go to the SSO tab for the Application and set: + - `Token Endpoint` > `Authentication Method`: `POST` +7. Click Save + +## Configuration + +The provider configuration can then be added to your `app-config.yaml` under the +root `auth` configuration: + +```yaml +auth: + environment: development + providers: + onelogin: + development: + clientId: ${AUTH_ONELOGIN_CLIENT_ID} + clientSecret: ${AUTH_ONELOGIN_CLIENT_SECRET} + issuer: https://.onelogin.com/oidc/2 +``` + +The OneLogin provider is a structure with three configuration keys; **these are +found on the SSO tab** for the OneLogin Application: + +- `clientId`: The client ID +- `clientSecret`: The client secret +- `issuer`: The issuer URL + +## Adding the provider to the Backstage frontend + +To add the provider to the frontend, add the `oneloginAuthApi` reference and +`SignInPage` component as shown in +[Adding the provider to the sign-in page](../index.md#adding-the-provider-to-the-sign-in-page). diff --git a/docs/cli/commands.md b/docs/cli/commands.md index ca89a43a6a..33693b010f 100644 --- a/docs/cli/commands.md +++ b/docs/cli/commands.md @@ -54,6 +54,8 @@ versions:check Check Backstage package versioning prepack Prepares a package for packaging before publishing postpack Restores the changes made by the prepack command +create-github-app Create new GitHub App in your organization (experimental) + help [command] display help for command ``` @@ -190,10 +192,13 @@ output of `backstage-cli backend:bundle` into an image: FROM node:14-buster-slim WORKDIR /app -ADD yarn.lock package.json packages/backend/dist/skeleton.tar.gz ./ +COPY yarn.lock package.json packages/backend/dist/skeleton.tar.gz ./ +RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz + RUN yarn install --frozen-lockfile --production --network-timeout 300000 && rm -rf "$(yarn cache dir)" -ADD packages/backend/dist/bundle.tar.gz app-config.yaml ./ +COPY packages/backend/dist/bundle.tar.gz app-config.yaml ./ +RUN tar xzf bundle.tar.gz && rm bundle.tar.gz CMD ["node", "packages/backend"] ``` @@ -606,3 +611,18 @@ the resulting archive in the target `workspace-dir`. ```text Usage: backstage-cli build-workspace [options] <workspace-dir> ``` + +## create-github-app + +Scope: `root` + +Creates a GitHub App in your GitHub organization. This is an alternative to +token-based [GitHub integration](../integrations/github/locations.md). See +[GitHub Apps for Backstage Authentication](../plugins/github-apps.md). + +Launches a browser to create the App through GitHub and saves the result as a +YAML file that can be referenced in the GitHub integration configuration. + +```text +Usage: backstage-cli create-github-app <github-org> +``` diff --git a/docs/features/software-catalog/descriptor-format.md b/docs/features/software-catalog/descriptor-format.md index 7397ce7d23..f4e1f86dd8 100644 --- a/docs/features/software-catalog/descriptor-format.md +++ b/docs/features/software-catalog/descriptor-format.md @@ -519,6 +519,17 @@ consumed by the component, e.g. `artist-api`. This field is optional. | --------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------------- | | [`API`](#kind-api) (default) | Same as this entity, typically `default` | [`consumesApi`, and reverse `apiConsumedBy`](well-known-relations.md#consumesapi-and-apiconsumedby) | +### `spec.dependsOn` [optional] + +An array of [entity references](#string-references) to the components and +resources that the component depends on, e.g. `artists-db`. This field is +optional. + +| [`kind`](#apiversion-and-kind-required) | Default [`namespace`](#namespace-optional) | Generated [relation](well-known-relations.md) type | +| --------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------- | +| [`Component`](#kind-component) | Same as this entity, typically `default` | [`dependsOn`, and reverse `dependencyOf`](well-known-relations.md#dependson-and-dependencyof) | +| [`Resource`](#kind-resource) | Same as this entity, typically `default` | [`dependsOn`, and reverse `dependencyOf`](well-known-relations.md#dependson-and-dependencyof) | + ## Kind: Template The following describes the following entity kind: @@ -1014,6 +1025,17 @@ belongs to, e.g. `artist-engagement-portal`. This field is optional. | --------------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------- | | [`System`](#kind-system) (default) | Same as this entity, typically `default` | [`partOf`, and reverse `hasPart`](well-known-relations.md#partof-and-haspart) | +### `spec.dependsOn` [optional] + +An array of [entity references](#string-references) to the components and +resources that the resource depends on, e.g. `artist-lookup`. This field is +optional. + +| [`kind`](#apiversion-and-kind-required) | Default [`namespace`](#namespace-optional) | Generated [relation](well-known-relations.md) type | +| --------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------- | +| [`Component`](#kind-component) | Same as this entity, typically `default` | [`dependsOn`, and reverse `dependencyOf`](well-known-relations.md#dependson-and-dependencyof) | +| [`Resource`](#kind-resource) | Same as this entity, typically `default` | [`dependsOn`, and reverse `dependencyOf`](well-known-relations.md#dependson-and-dependencyof) | + ## Kind: System Describes the following entity kind: diff --git a/docs/features/software-templates/installation.md b/docs/features/software-templates/installation.md index e145567666..b3c9f878d7 100644 --- a/docs/features/software-templates/installation.md +++ b/docs/features/software-templates/installation.md @@ -265,3 +265,15 @@ GITHUB_TOKEN= yarn start If you've also set up the frontend plugin, so you should be ready to go browse the templates at [localhost:3000/create](http://localhost:3000/create) now! + +### Disabling Docker in Docker situation (Optional) + +Software Templates use +[Cookiecutter](https://github.com/cookiecutter/cookiecutter) as templating +library. By default it will use the +[spotify/backstage-cookiecutter](<[spotify/backstage-cookiecutter](https://github.com/backstage/backstage/blob/37e35b910afc7d1270855aed0ec4718aba366c91/plugins/scaffolder-backend/scripts/Cookiecutter.dockerfile)>) +docker image. + +If you are running backstage from a Docker container and you want to avoid +calling a container inside a container, you can set up Cookiecutter in your own +image, this will use the local installation instead. diff --git a/docs/getting-started/app-custom-theme.md b/docs/getting-started/app-custom-theme.md index 345b7ad969..181f541929 100644 --- a/docs/getting-started/app-custom-theme.md +++ b/docs/getting-started/app-custom-theme.md @@ -74,3 +74,64 @@ Note that your list of custom themes overrides the default themes. If you still want to use the default themes, they are exported as `lightTheme` and `darkTheme` from [@backstage/theme](https://www.npmjs.com/package/@backstage/theme). + +## Example of a custom theme + +```ts +const themeOptions = createThemeOptions({ + palette: { + ...lightTheme.palette, + primary: { + main: '#123456', + }, + secondary: { + main: '#123456', + }, + error: { + main: '#123456' + }, + warning: { + main: '#123456', + }, + info: { + main: '#123456', + }, + success: { + main: '#123456', + }, + background: { + default: '#123456', + paper: '#123456', + }, + banner: { + info: '#123456', + error: '#123456' + text: '#123456' + link: '#123456', + }, + errorBackground: '#123456' + warningBackground: '#123456' + infoBackground: '#123456' + navigation: { + background: '#123456', + indicator: '#123456' + color: '#123456' + selectedColor: '#123456', + }, + }, + defaultPageTheme: 'home', + fontFamily: 'Comic Sans', + /* below drives the header colors */ + pageTheme: { + home: genPageTheme(['#123456','#123456'], shapes.wave), + documentation: genPageTheme(['#123456','#123456'], shapes.wave2), + tool: genPageTheme(['#123456','#123456'], shapes.round), + service: genPageTheme(['#123456','#123456'], shapes.wave), + website: genPageTheme(['#123456','#123456'], shapes.wave), + library: genPageTheme(['#123456','#123456'] shapes.wave), + other: genPageTheme(['#123456','#123456'], shapes.wave), + app: genPageTheme(['#123456','#123456'], shapes.wave), + apis: genPageTheme(['#123456','#123456'], shapes.wave), + }, +}); +``` diff --git a/docs/getting-started/configure-app-with-plugins.md b/docs/getting-started/configure-app-with-plugins.md index 964987c4a7..e5b4d08a3f 100644 --- a/docs/getting-started/configure-app-with-plugins.md +++ b/docs/getting-started/configure-app-with-plugins.md @@ -68,9 +68,9 @@ proxy: In a standard Backstage app created with [@backstage/create-app](./create-an-app.md), the sidebar is managed inside -`packages/app/src/components/Root.tsx`. The file exports the entire `Sidebar` -element of your app, which you can extend with additional entries by adding new -`SidebarItem` elements. +`packages/app/src/components/Root/Root.tsx`. The file exports the entire +`Sidebar` element of your app, which you can extend with additional entries by +adding new `SidebarItem` elements. For example, if you install the `api-docs` plugin, a matching `SidebarItem` could be something like this: diff --git a/docs/getting-started/create-an-app.md b/docs/getting-started/create-an-app.md index 837a27e592..fefb20b095 100644 --- a/docs/getting-started/create-an-app.md +++ b/docs/getting-started/create-an-app.md @@ -106,6 +106,12 @@ The install process may also fail if no Python installation is available. Python is commonly available in most systems already, but if it isn't you can head for example [here](https://www.python.org/downloads/) to install it. +#### Could not execute command yarn install + +Install yarn on your system with `npm install --global yarn` or for more details +refer to the +[prerequisites](https://backstage.io/docs/getting-started/running-backstage-locally#prerequisites) + ## Run the app When the installation is complete you can open the app folder and start the app. diff --git a/docs/integrations/bitbucket/locations.md b/docs/integrations/bitbucket/locations.md index 992a240290..d318eef874 100644 --- a/docs/integrations/bitbucket/locations.md +++ b/docs/integrations/bitbucket/locations.md @@ -38,3 +38,6 @@ a structure with up to four elements: - `apiBaseUrl` (optional): The URL of the Bitbucket API. For self-hosted installations, it is commonly at `https:///rest/api/1.0`. For bitbucket.org, this configuration is not needed as it can be inferred. + +> Note: If you are using Bitbucket server you MUST set the username as well as +> the token or appPassword. diff --git a/docs/integrations/google-cloud-storage/locations.md b/docs/integrations/google-cloud-storage/locations.md new file mode 100644 index 0000000000..e3f6b72847 --- /dev/null +++ b/docs/integrations/google-cloud-storage/locations.md @@ -0,0 +1,57 @@ +--- +id: locations +sidebar_label: Locations +title: Google Cloud Storage Locations +# prettier-ignore +description: Setting up an integration with Google Cloud Storage +--- + +The Backstage catalog can import entities from a yaml file stored in a GCS +(Google Cloud Storage) bucket. To enable the ingestion of said entities the +`GoogleGcs` integration must be enabled first. + +## Configuration + +To configure the integration add the appropriate credentials to the Backstage +backend. There are two main ways to do this: by explicitly setting a +`clientEmail` and a `privateKey` or by letting the Google Storage SDK discover +the credentials automatically. + +### Explicit credentials + +Explicit credentials can be set in the following format: + +```yaml +integrations: + googleGcs: + clientEmail: + $env: GCS_CLIENT_EMAIL + privateKey: + $env: GCS_PRIVATE_KEY +``` + +Then make sure the environment variables `GCS_CLIENT_EMAIL` and +`GCS_PRIVATE_KEY` are set when you run Backstage. + +### Automatic discovery of Google credentials + +Since this integration uses the Google Storage SDK, you can also choose to not +provide any explicit credentials and let the SDK discover them automatically. + +One of these discovery methods is to provide an environment variable called +`GOOGLE_APPLICATION_CREDENTIALS` and set it to the file path of your JSON +service account key. + +For more details and methods to provide credentials to the Google Storage SDK +you can check [this documentation page][google gcs docs]. + +## Usage + +To use this integration to import entities from a GCS bucket go to the Google +console and browse the file you would like to import. Then copy the +`Authenticated URL` and paste it into the text box in the `register component` +form. This url should look like +`https://storage.cloud.google.com///catalog-info.yaml`. + +[google gcs docs]: + https://cloud.google.com/docs/authentication/production#auth-cloud-implicit-nodejs diff --git a/microsite/pages/en/index.js b/microsite/pages/en/index.js index 47f9568d9b..a761d6b6e2 100644 --- a/microsite/pages/en/index.js +++ b/microsite/pages/en/index.js @@ -292,7 +292,7 @@ class Index extends React.Component { Build your own software templates Contribute diff --git a/microsite/sidebars.json b/microsite/sidebars.json index 0a438b7653..64ff108a78 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -142,6 +142,11 @@ "type": "subcategory", "label": "LDAP", "ids": ["integrations/ldap/org"] + }, + { + "type": "subcategory", + "label": "Google GCS", + "ids": ["integrations/google-cloud-storage/locations"] } ], "Plugins": [ @@ -195,7 +200,8 @@ "auth/github/provider", "auth/gitlab/provider", "auth/google/provider", - "auth/okta/provider" + "auth/okta/provider", + "auth/onelogin/provider" ] }, "auth/add-auth-provider", diff --git a/package.json b/package.json index fcabe5b3e5..d87b98fbdb 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,9 @@ "resolutions": { "**/@roadiehq/**/@backstage/core": "*", "**/@roadiehq/**/@backstage/plugin-catalog": "*", - "**/@roadiehq/**/@backstage/catalog-model": "*" + "**/@roadiehq/**/@backstage/catalog-model": "*", + "graphql-language-service-interface": "2.8.2", + "graphql-language-service-parser": "1.9.0" }, "version": "1.0.0", "devDependencies": { diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 00cf81a903..5b96841e65 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,29 @@ # example-app +## 0.2.23 + +### Patch Changes + +- Updated dependencies [d0b4ebf22] +- Updated dependencies [1279a3325] +- Updated dependencies [4a4681b1b] +- Updated dependencies [97b60de98] +- Updated dependencies [3f96a9d5a] +- Updated dependencies [b051e770c] +- Updated dependencies [f9c75f7a9] +- Updated dependencies [98dd5da71] +- Updated dependencies [97d53f686] +- Updated dependencies [64d2ce700] + - @backstage/plugin-badges@0.2.0 + - @backstage/core@0.7.4 + - @backstage/catalog-model@0.7.6 + - @backstage/plugin-scaffolder@0.8.2 + - @backstage/plugin-catalog-import@0.5.2 + - @backstage/plugin-catalog@0.5.3 + - @backstage/plugin-org@0.3.12 + - @backstage/plugin-github-deployments@0.1.2 + - @backstage/cli@0.6.7 + ## 0.2.21 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 4c734b85f3..304bd8d8b3 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,17 +1,17 @@ { "name": "example-app", - "version": "0.2.21", + "version": "0.2.23", "private": true, "bundled": true, "dependencies": { - "@backstage/catalog-model": "^0.7.4", - "@backstage/cli": "^0.6.6", - "@backstage/core": "^0.7.3", + "@backstage/catalog-model": "^0.7.6", + "@backstage/cli": "^0.6.7", + "@backstage/core": "^0.7.4", "@backstage/integration-react": "^0.1.1", "@backstage/plugin-api-docs": "^0.4.9", - "@backstage/plugin-badges": "^0.1.2", - "@backstage/plugin-catalog": "^0.5.1", - "@backstage/plugin-catalog-import": "^0.5.0", + "@backstage/plugin-badges": "^0.2.0", + "@backstage/plugin-catalog": "^0.5.3", + "@backstage/plugin-catalog-import": "^0.5.2", "@backstage/plugin-catalog-react": "^0.1.3", "@backstage/plugin-circleci": "^0.2.12", "@backstage/plugin-cloudbuild": "^0.2.13", @@ -19,7 +19,7 @@ "@backstage/plugin-explore": "^0.3.2", "@backstage/plugin-gcp-projects": "^0.2.5", "@backstage/plugin-github-actions": "^0.4.2", - "@backstage/plugin-github-deployments": "^0.1.1", + "@backstage/plugin-github-deployments": "^0.1.2", "@backstage/plugin-gitops-profiles": "^0.2.6", "@backstage/plugin-graphiql": "^0.2.9", "@backstage/plugin-jenkins": "^0.4.1", @@ -27,12 +27,12 @@ "@backstage/plugin-kubernetes": "^0.4.2", "@backstage/plugin-lighthouse": "^0.2.14", "@backstage/plugin-newrelic": "^0.2.6", - "@backstage/plugin-org": "^0.3.10", + "@backstage/plugin-org": "^0.3.12", "@backstage/plugin-pagerduty": "0.3.2", "@backstage/plugin-register-component": "^0.2.12", "@backstage/plugin-github-release-manager": "^0.1.1", "@backstage/plugin-rollbar": "^0.3.3", - "@backstage/plugin-scaffolder": "^0.8.0", + "@backstage/plugin-scaffolder": "^0.8.2", "@backstage/plugin-search": "^0.3.4", "@backstage/plugin-sentry": "^0.3.8", "@backstage/plugin-tech-radar": "^0.3.8", @@ -43,10 +43,10 @@ "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@octokit/rest": "^18.0.12", - "@roadiehq/backstage-plugin-buildkite": "^0.1.3", - "@roadiehq/backstage-plugin-github-insights": "^0.3.2", - "@roadiehq/backstage-plugin-github-pull-requests": "^0.7.6", - "@roadiehq/backstage-plugin-travis-ci": "^0.4.5", + "@roadiehq/backstage-plugin-buildkite": "^1.0.0", + "@roadiehq/backstage-plugin-github-insights": "^1.0.0", + "@roadiehq/backstage-plugin-github-pull-requests": "^1.0.0", + "@roadiehq/backstage-plugin-travis-ci": "^1.0.0", "history": "^5.0.0", "prop-types": "^15.7.2", "react": "^16.12.0", @@ -58,7 +58,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/cypress": "^7.0.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index defa70dbb7..c5e5033973 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -27,7 +27,11 @@ import { CatalogIndexPage, catalogPlugin, } from '@backstage/plugin-catalog'; -import { CatalogImportPage } from '@backstage/plugin-catalog-import'; + +import { + CatalogImportPage, + catalogImportPlugin, +} from '@backstage/plugin-catalog-import'; import { CostInsightsLabelDataflowInstructionsPage, CostInsightsPage, @@ -48,8 +52,8 @@ import React from 'react'; import { hot } from 'react-hot-loader/root'; import { Navigate, Route } from 'react-router'; import { apis } from './apis'; -import { EntityPage } from './components/catalog/EntityPage'; import { Root } from './components/Root'; +import { entityPage } from './components/catalog/EntityPage'; import { providers } from './identityProviders'; import * as plugins from './plugins'; @@ -82,6 +86,9 @@ const app = createApp({ bind(explorePlugin.externalRoutes, { catalogEntity: catalogPlugin.routes.catalogEntity, }); + bind(scaffolderPlugin.externalRoutes, { + registerComponent: catalogImportPlugin.routes.importPage, + }); }, }); @@ -96,7 +103,7 @@ const routes = ( path="/catalog/:namespace/:kind/:name" element={} > - + {entityPage} } /> } /> diff --git a/packages/app/src/components/catalog/EntityPage.test.tsx b/packages/app/src/components/catalog/EntityPage.test.tsx index 1392f77a6d..9860792ea0 100644 --- a/packages/app/src/components/catalog/EntityPage.test.tsx +++ b/packages/app/src/components/catalog/EntityPage.test.tsx @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import React from 'react'; -import { CICDSwitcher } from './EntityPage'; -import { UrlPatternDiscovery, ApiProvider, ApiRegistry } from '@backstage/core'; -import { - buildKiteApiRef, - BuildkiteApi, -} from '@roadiehq/backstage-plugin-buildkite'; -import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils'; +import { ApiProvider, ApiRegistry } from '@backstage/core'; +import { EntityLayout } from '@backstage/plugin-catalog'; +import { EntityProvider } from '@backstage/plugin-catalog-react'; +import { renderInTestApp } from '@backstage/test-utils'; +import { cicdContent } from './EntityPage'; +import { githubActionsApiRef } from '@backstage/plugin-github-actions'; describe('EntityPage Test', () => { const entity = { @@ -29,7 +29,7 @@ describe('EntityPage Test', () => { metadata: { name: 'ExampleComponent', annotations: { - 'buildkite.com/project-slug': 'exampleProject/examplePipeline', + 'github.com/project-slug': 'example/project', }, }, spec: { @@ -39,24 +39,36 @@ describe('EntityPage Test', () => { }, }; - const discoveryApi = UrlPatternDiscovery.compile('http://exampleapi.com'); + const mockedApi = { + listWorkflowRuns: jest.fn().mockResolvedValue([]), + getWorkflow: jest.fn(), + getWorkflowRun: jest.fn(), + reRunWorkflow: jest.fn(), + downloadJobLogsForWorkflowRun: jest.fn(), + } as jest.Mocked; - const apis = ApiRegistry.from([ - [buildKiteApiRef, new BuildkiteApi({ discoveryApi })], - ]); + const apis = ApiRegistry.with(githubActionsApiRef, mockedApi); - describe('CICDSwitcher Test', () => { - it('Should render Buildkite View', async () => { - const renderedComponent = await renderWithEffects( - wrapInTestApp( - - - , - ), + describe('cicdContent', () => { + it('Should render GitHub Actions View', async () => { + const rendered = await renderInTestApp( + + + + + {cicdContent} + + + + , ); - expect( - renderedComponent.getByText(/exampleProject\/examplePipeline/), - ).toBeInTheDocument(); + + expect(rendered.getByText('ExampleComponent')).toBeInTheDocument(); + + await expect( + rendered.findByText('No Workflow Data'), + ).resolves.toBeInTheDocument(); + expect(rendered.getByText('Create new Workflow')).toBeInTheDocument(); }); }); }); diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 5dc4f4c570..d6f91957a9 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -14,174 +14,96 @@ * limitations under the License. */ -import { - ApiEntity, - DomainEntity, - Entity, - GroupEntity, - SystemEntity, - UserEntity, -} from '@backstage/catalog-model'; +import React, { ReactNode, useMemo, useState } from 'react'; +import BadgeIcon from '@material-ui/icons/CallToAction'; import { EmptyState } from '@backstage/core'; import { - ApiDefinitionCard, - ConsumedApisCard, - ConsumingComponentsCard, + EntityApiDefinitionCard, + EntityConsumingComponentsCard, EntityHasApisCard, - ProvidedApisCard, - ProvidingComponentsCard, + EntityProvidingComponentsCard, + EntityProvidedApisCard, + EntityConsumedApisCard, } from '@backstage/plugin-api-docs'; import { EntityBadgesDialog } from '@backstage/plugin-badges'; import { - AboutCard, + EntityAboutCard, EntityHasComponentsCard, EntityHasSubcomponentsCard, EntityHasSystemsCard, + EntityLayout, EntityLinksCard, - EntityPageLayout, EntitySystemDiagramCard, + EntitySwitch, + isComponentType, + isKind, } from '@backstage/plugin-catalog'; -import { EntityProvider, useEntity } from '@backstage/plugin-catalog-react'; import { - isPluginApplicableToEntity as isCircleCIAvailable, - Router as CircleCIRouter, + EntityCircleCIContent, + isCircleCIAvailable, } from '@backstage/plugin-circleci'; import { - isPluginApplicableToEntity as isCloudbuildAvailable, - Router as CloudbuildRouter, + EntityCloudbuildContent, + isCloudbuildAvailable, } from '@backstage/plugin-cloudbuild'; import { - isPluginApplicableToEntity as isGitHubActionsAvailable, - RecentWorkflowRunsCard, - Router as GitHubActionsRouter, + EntityGithubActionsContent, + EntityRecentGithubActionsRunsCard, + isGithubActionsAvailable, } from '@backstage/plugin-github-actions'; import { - isPluginApplicableToEntity as isJenkinsAvailable, - LatestRunCard as JenkinsLatestRunCard, - Router as JenkinsRouter, + EntityJenkinsContent, + EntityLatestJenkinsRunCard, + isJenkinsAvailable, } from '@backstage/plugin-jenkins'; -import { Router as KafkaRouter } from '@backstage/plugin-kafka'; -import { Router as KubernetesRouter } from '@backstage/plugin-kubernetes'; +import { EntityKafkaContent } from '@backstage/plugin-kafka'; +import { EntityKubernetesContent } from '@backstage/plugin-kubernetes'; import { - EmbeddedRouter as LighthouseRouter, - isPluginApplicableToEntity as isLighthouseAvailable, - LastLighthouseAuditCard, + EntityLastLighthouseAuditCard, + EntityLighthouseContent, + isLighthouseAvailable, } from '@backstage/plugin-lighthouse'; import { - GroupProfileCard, - MembersListCard, - OwnershipCard, - UserProfileCard, + EntityGroupProfileCard, + EntityMembersListCard, + EntityOwnershipCard, + EntityUserProfileCard, } from '@backstage/plugin-org'; import { - isPluginApplicableToEntity as isPagerDutyAvailable, - PagerDutyCard, + EntityPagerDutyCard, + isPagerDutyAvailable, } from '@backstage/plugin-pagerduty'; import { + EntityRollbarContent, isRollbarAvailable, - Router as RollbarRouter, } from '@backstage/plugin-rollbar'; -import { Router as SentryRouter } from '@backstage/plugin-sentry'; -import { EmbeddedDocsRouter as DocsRouter } from '@backstage/plugin-techdocs'; +import { EntitySentryContent } from '@backstage/plugin-sentry'; +import { EntityTechdocsContent } from '@backstage/plugin-techdocs'; import { EntityTodoContent } from '@backstage/plugin-todo'; import { Button, Grid } from '@material-ui/core'; import { - isPluginApplicableToEntity as isBuildkiteAvailable, - Router as BuildkiteRouter, + EntityBuildkiteContent, + isBuildkiteAvailable, } from '@roadiehq/backstage-plugin-buildkite'; import { - isPluginApplicableToEntity as isGitHubAvailable, - LanguagesCard, - ReadMeCard, - ReleasesCard, - Router as GitHubInsightsRouter, + EntityGithubInsightsContent, + EntityGithubInsightsLanguagesCard, + EntityGithubInsightsReadmeCard, + EntityGithubInsightsReleasesCard, + isGithubInsightsAvailable, } from '@roadiehq/backstage-plugin-github-insights'; import { - isPluginApplicableToEntity as isPullRequestsAvailable, - PullRequestsStatsCard, - Router as PullRequestsRouter, + EntityGithubPullRequestsContent, + EntityGithubPullRequestsOverviewCard, + isGithubPullRequestsAvailable, } from '@roadiehq/backstage-plugin-github-pull-requests'; import { - isPluginApplicableToEntity as isTravisCIAvailable, - RecentTravisCIBuildsWidget, - Router as TravisCIRouter, + EntityTravisCIContent, + EntityTravisCIOverviewCard, + isTravisciAvailable, } from '@roadiehq/backstage-plugin-travis-ci'; -import React, { ReactNode, useMemo, useState } from 'react'; -import BadgeIcon from '@material-ui/icons/CallToAction'; -export const CICDSwitcher = ({ entity }: { entity: Entity }) => { - // This component is just an example of how you can implement your company's logic in entity page. - // You can for example enforce that all components of type 'service' should use GitHubActions - switch (true) { - case isJenkinsAvailable(entity): - return ; - case isBuildkiteAvailable(entity): - return ; - case isCircleCIAvailable(entity): - return ; - case isCloudbuildAvailable(entity): - return ; - case isTravisCIAvailable(entity): - return ; - case isGitHubActionsAvailable(entity): - return ; - default: - return ( - - Read more - - } - /> - ); - } -}; - -const RecentCICDRunsSwitcher = ({ entity }: { entity: Entity }) => { - let content: ReactNode; - switch (true) { - case isJenkinsAvailable(entity): - content = ; - break; - case isTravisCIAvailable(entity): - content = ; - break; - case isGitHubActionsAvailable(entity): - content = ( - - ); - break; - default: - content = null; - } - if (!content) { - return null; - } - return ( - - {content} - - ); -}; - -export const ErrorsSwitcher = ({ entity }: { entity: Entity }) => { - switch (true) { - case isRollbarAvailable(entity): - return ; - default: - return ; - } -}; - -const EntityPageLayoutWrapper = (props: { children?: React.ReactNode }) => { +const EntityLayoutWrapper = (props: { children?: ReactNode }) => { const [badgesDialogOpen, setBadgesDialogOpen] = useState(false); const extraMenuItems = useMemo(() => { @@ -196,9 +118,9 @@ const EntityPageLayoutWrapper = (props: { children?: React.ReactNode }) => { return ( <> - + {props.children} - + setBadgesDialogOpen(false)} @@ -207,350 +129,367 @@ const EntityPageLayoutWrapper = (props: { children?: React.ReactNode }) => { ); }; -const ComponentOverviewContent = ({ entity }: { entity: Entity }) => ( +export const cicdContent = ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + Read more + + } + /> + + +); + +const cicdCard = ( + + + + + + + + + + + + + + + + + + + +); + +const errorsContent = ( + + + + + + + + + +); + +const overviewContent = ( - - + + - {isPagerDutyAvailable(entity) && ( - - - - - - )} - - + + + + + + + + + + + - - {isGitHubAvailable(entity) && ( - <> - - - + + {cicdCard} + + + Boolean(isGithubInsightsAvailable(e))}> + + + - - + + - - )} - {isLighthouseAvailable(entity) && ( - - - - )} - {isPullRequestsAvailable(entity) && ( - - - - )} - + + + + + + + + + + + + + Boolean(isGithubPullRequestsAvailable(e))}> + + + + + + + ); -const ComponentApisContent = ({ entity }: { entity: Entity }) => ( - - - - - - - - -); +const serviceEntityPage = ( + + + {overviewContent} + -const ServiceEntityPage = ({ entity }: { entity: Entity }) => ( - - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - -); + + {cicdContent} + -const WebsiteEntityPage = ({ entity }: { entity: Entity }) => ( - - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - -); + + {errorsContent} + -const DefaultEntityPage = ({ entity }: { entity: Entity }) => ( - - } - /> - } - /> - } - /> - -); - -export const ComponentEntityPage = ({ entity }: { entity: Entity }) => { - switch (entity?.spec?.type) { - case 'service': - return ; - case 'website': - return ; - default: - return ; - } -}; - -const ApiOverviewContent = ({ entity }: { entity: Entity }) => ( - - - - - - - + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + +); + +const websiteEntityPage = ( + + + {overviewContent} + + + + {cicdContent} + + + + + + + + {errorsContent} + + + + + + + + + + + + + + + + + + + + + + +); + +const defaultEntityPage = ( + + + {overviewContent} + + + + + + + + + + +); + +const componentPage = ( + + + {serviceEntityPage} + + + + {websiteEntityPage} + + + {defaultEntityPage} + +); + +const apiPage = ( + + + + + + + + + + + + + + - - + + + + + + + + + + ); -const ApiDefinitionContent = ({ entity }: { entity: ApiEntity }) => ( - - - - - +const userPage = ( + + + + + + + + + + + + ); -const ApiEntityPage = ({ entity }: { entity: Entity }) => ( - - } - /> - } - /> - +const groupPage = ( + + + + + + + + + + + + + + + + + + + ); -const UserOverviewContent = ({ entity }: { entity: UserEntity }) => ( - - - - - - - - +const systemPage = ( + + + + + + + + + + + + + + + ); -const UserEntityPage = ({ entity }: { entity: Entity }) => ( - - } - /> - +const domainPage = ( + + + + + + + + + + + + ); -const GroupOverviewContent = ({ entity }: { entity: GroupEntity }) => ( - - - - - - - - - - - +export const entityPage = ( + + + + + + + + + {defaultEntityPage} + ); - -const GroupEntityPage = ({ entity }: { entity: Entity }) => ( - - } - /> - -); - -const SystemOverviewContent = ({ entity }: { entity: SystemEntity }) => ( - - - - - - - - - - - -); - -const SystemEntityPage = ({ entity }: { entity: Entity }) => ( - - } - /> - } - /> - -); - -const DomainOverviewContent = ({ entity }: { entity: DomainEntity }) => ( - - - - - - - - -); - -const DomainEntityPage = ({ entity }: { entity: Entity }) => ( - - } - /> - -); - -export const EntityPage = () => { - const { entity } = useEntity(); - - switch (entity?.kind?.toLocaleLowerCase('en-US')) { - case 'component': - return ; - case 'api': - return ; - case 'group': - return ; - case 'user': - return ; - case 'system': - return ; - case 'domain': - return ; - case 'location': - case 'resource': - case 'template': - default: - return ; - } -}; diff --git a/packages/app/src/plugins.ts b/packages/app/src/plugins.ts index 4099061428..eff6093314 100644 --- a/packages/app/src/plugins.ts +++ b/packages/app/src/plugins.ts @@ -27,19 +27,19 @@ export { plugin as GraphiQL } from '@backstage/plugin-graphiql'; export { plugin as GithubActions } from '@backstage/plugin-github-actions'; export { plugin as Rollbar } from '@backstage/plugin-rollbar'; export { plugin as Newrelic } from '@backstage/plugin-newrelic'; -export { plugin as TravisCI } from '@roadiehq/backstage-plugin-travis-ci'; +export { travisciPlugin } from '@roadiehq/backstage-plugin-travis-ci'; export { plugin as Jenkins } from '@backstage/plugin-jenkins'; export { plugin as ApiDocs } from '@backstage/plugin-api-docs'; -export { plugin as GithubPullRequests } from '@roadiehq/backstage-plugin-github-pull-requests'; +export { githubPullRequestsPlugin } from '@roadiehq/backstage-plugin-github-pull-requests'; export { plugin as GcpProjects } from '@backstage/plugin-gcp-projects'; export { plugin as Kubernetes } from '@backstage/plugin-kubernetes'; export { plugin as Cloudbuild } from '@backstage/plugin-cloudbuild'; export { plugin as CostInsights } from '@backstage/plugin-cost-insights'; -export { plugin as GitHubInsights } from '@roadiehq/backstage-plugin-github-insights'; +export { githubInsightsPlugin } from '@roadiehq/backstage-plugin-github-insights'; export { plugin as CatalogImport } from '@backstage/plugin-catalog-import'; export { plugin as UserSettings } from '@backstage/plugin-user-settings'; export { plugin as PagerDuty } from '@backstage/plugin-pagerduty'; -export { plugin as Buildkite } from '@roadiehq/backstage-plugin-buildkite'; +export { buildkitePlugin } from '@roadiehq/backstage-plugin-buildkite'; export { plugin as Search } from '@backstage/plugin-search'; export { plugin as Org } from '@backstage/plugin-org'; export { plugin as Kafka } from '@backstage/plugin-kafka'; diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index dfe057da53..c194f7e666 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/backend-common +## 0.6.2 + +### Patch Changes + +- b779b5fee: Add UrlReader for Google Cloud Storage +- Updated dependencies [82c66b8cd] + - @backstage/config-loader@0.6.0 + ## 0.6.1 ### Patch Changes diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index b860336d31..41fa657818 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.6.1", + "version": "0.6.2", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -31,9 +31,10 @@ "dependencies": { "@backstage/cli-common": "^0.1.1", "@backstage/config": "^0.1.4", - "@backstage/config-loader": "^0.5.1", + "@backstage/config-loader": "^0.6.0", "@backstage/errors": "^0.1.1", "@backstage/integration": "^0.5.1", + "@google-cloud/storage": "^5.8.0", "@octokit/rest": "^18.0.12", "@types/cors": "^2.8.6", "@types/dockerode": "^3.2.1", @@ -56,6 +57,7 @@ "minimatch": "^3.0.4", "minimist": "^1.2.5", "morgan": "^1.10.0", + "raw-body": "^2.4.1", "selfsigned": "^1.10.7", "stoppable": "^1.1.0", "tar": "^6.0.5", @@ -71,8 +73,8 @@ } }, "devDependencies": { - "@backstage/cli": "^0.6.5", - "@backstage/test-utils": "^0.1.9", + "@backstage/cli": "^0.6.7", + "@backstage/test-utils": "^0.1.10", "@types/archiver": "^5.1.0", "@types/compression": "^1.7.0", "@types/concat-stream": "^1.6.0", diff --git a/packages/backend-common/src/reading/GoogleGcsUrlReader.test.ts b/packages/backend-common/src/reading/GoogleGcsUrlReader.test.ts new file mode 100644 index 0000000000..e201361a91 --- /dev/null +++ b/packages/backend-common/src/reading/GoogleGcsUrlReader.test.ts @@ -0,0 +1,94 @@ +/* + * 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, JsonObject } from '@backstage/config'; +import { getVoidLogger } from '../logging'; +import { ReadTreeResponseFactory } from './tree'; +import { GoogleGcsUrlReader } from './GoogleGcsUrlReader'; +import { UrlReaderPredicateTuple } from './types'; + +describe('GcsUrlReader', () => { + const createReader = (config: JsonObject): UrlReaderPredicateTuple[] => { + return GoogleGcsUrlReader.factory({ + config: new ConfigReader(config), + logger: getVoidLogger(), + treeResponseFactory: ReadTreeResponseFactory.create({ + config: new ConfigReader({}), + }), + }); + }; + + it('does not create a reader without the googleGcs field', () => { + const entries = createReader({ + integrations: {}, + }); + expect(entries).toHaveLength(0); + }); + + it('creates a reader with credentials correctly configured', () => { + const entries = createReader({ + integrations: { + googleGcs: { + privateKey: '--- BEGIN KEY ---- fakekey --- END KEY ---', + clientEmail: 'someone@example.com', + }, + }, + }); + expect(entries).toHaveLength(1); + }); + + it('creates a reader with default credentials provider', () => { + const entries = createReader({ + integrations: { + googleGcs: {}, + }, + }); + expect(entries).toHaveLength(1); + }); + + describe('predicates', () => { + const readers = createReader({ + integrations: { + googleGcs: {}, + }, + }); + const predicate = readers[0].predicate; + + it('returns true for the correct google cloud storage host', () => { + expect(predicate(new URL('https://storage.cloud.google.com'))).toBe(true); + }); + it('returns true for a url with the full path and the correct host', () => { + expect( + predicate( + new URL( + 'https://storage.cloud.google.com/team1/service1/catalog-info.yaml', + ), + ), + ).toBe(true); + }); + it('returns false for the wrong hostname under cloud.google.com', () => { + expect(predicate(new URL('https://storage2.cloud.google.com'))).toBe( + false, + ); + }); + it('returns false for a partially correct host', () => { + expect(predicate(new URL('https://cloud.google.com'))).toBe(false); + }); + it('returns false for a completely different host', () => { + expect(predicate(new URL('https://a.example.com/test'))).toBe(false); + }); + }); +}); diff --git a/packages/backend-common/src/reading/GoogleGcsUrlReader.ts b/packages/backend-common/src/reading/GoogleGcsUrlReader.ts new file mode 100644 index 0000000000..4ea24fa22f --- /dev/null +++ b/packages/backend-common/src/reading/GoogleGcsUrlReader.ts @@ -0,0 +1,105 @@ +/* + * 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 { Storage } from '@google-cloud/storage'; +import { + ReaderFactory, + ReadTreeResponse, + SearchResponse, + UrlReader, +} from './types'; +import getRawBody from 'raw-body'; +import { + GoogleGcsIntegrationConfig, + readGoogleGcsIntegrationConfig, +} from '@backstage/integration'; + +const GOOGLE_GCS_HOST = 'storage.cloud.google.com'; + +const parseURL = ( + url: string, +): { host: string; bucket: string; key: string } => { + const { host, pathname } = new URL(url); + + if (host !== GOOGLE_GCS_HOST) { + throw new Error(`not a valid GCS URL: ${url}`); + } + + const [, bucket, ...key] = pathname.split('/'); + return { + host: host, + bucket, + key: key.join('/'), + }; +}; + +export class GoogleGcsUrlReader implements UrlReader { + static factory: ReaderFactory = ({ config, logger }) => { + if (!config.has('integrations.googleGcs')) { + return []; + } + const gcsConfig = readGoogleGcsIntegrationConfig( + config.getConfig('integrations.googleGcs'), + ); + let storage: Storage; + if (!gcsConfig.clientEmail || !gcsConfig.privateKey) { + logger.info( + 'googleGcs credentials not found in config. Using default credentials provider.', + ); + storage = new Storage(); + } else { + storage = new Storage({ + credentials: { + client_email: gcsConfig.clientEmail || undefined, + private_key: gcsConfig.privateKey || undefined, + }, + }); + } + const reader = new GoogleGcsUrlReader(gcsConfig, storage); + const predicate = (url: URL) => url.host === GOOGLE_GCS_HOST; + return [{ reader, predicate }]; + }; + + constructor( + private readonly integration: GoogleGcsIntegrationConfig, + private readonly storage: Storage, + ) {} + + async read(url: string): Promise { + try { + const { bucket, key } = parseURL(url); + + return await getRawBody( + this.storage.bucket(bucket).file(key).createReadStream(), + ); + } catch (error) { + throw new Error(`unable to read gcs file from ${url}, ${error}`); + } + } + + async readTree(): Promise { + throw new Error('GcsUrlReader does not implement readTree'); + } + + async search(): Promise { + throw new Error('GcsUrlReader does not implement search'); + } + + toString() { + const key = this.integration.privateKey; + return `googleGcs{host=${GOOGLE_GCS_HOST},authed=${Boolean(key)}}`; + } +} diff --git a/packages/backend-common/src/reading/UrlReaders.ts b/packages/backend-common/src/reading/UrlReaders.ts index 2f233463bb..06c6fdcdcf 100644 --- a/packages/backend-common/src/reading/UrlReaders.ts +++ b/packages/backend-common/src/reading/UrlReaders.ts @@ -24,6 +24,7 @@ import { GithubUrlReader } from './GithubUrlReader'; import { GitlabUrlReader } from './GitlabUrlReader'; import { ReadTreeResponseFactory } from './tree'; import { FetchUrlReader } from './FetchUrlReader'; +import { GoogleGcsUrlReader } from './GoogleGcsUrlReader'; type CreateOptions = { /** Root config object */ @@ -70,6 +71,7 @@ export class UrlReaders { BitbucketUrlReader.factory, GithubUrlReader.factory, GitlabUrlReader.factory, + GoogleGcsUrlReader.factory, FetchUrlReader.factory, ]), }); diff --git a/packages/backend/Dockerfile b/packages/backend/Dockerfile index acef405c8a..02aab45609 100644 --- a/packages/backend/Dockerfile +++ b/packages/backend/Dockerfile @@ -16,11 +16,13 @@ WORKDIR /app # Copy repo skeleton first, to avoid unnecessary docker cache invalidation. # The skeleton contains the package.json of each package in the monorepo, # and along with yarn.lock and the root package.json, that's enough to run yarn install. -ADD yarn.lock package.json packages/backend/dist/skeleton.tar.gz ./ +COPY yarn.lock package.json packages/backend/dist/skeleton.tar.gz ./ +RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz RUN yarn install --frozen-lockfile --production --network-timeout 300000 && rm -rf "$(yarn cache dir)" # Then copy the rest of the backend bundle, along with any other files we might want. ADD packages/backend/dist/bundle.tar.gz app-config.yaml ./ +RUN tar xzf bundle.tar.gz && rm bundle.tar.gz CMD ["node", "packages/backend", "--config", "app-config.yaml"] diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md index 0ad5d6993f..71a0ba6676 100644 --- a/packages/catalog-model/CHANGELOG.md +++ b/packages/catalog-model/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/catalog-model +## 0.7.6 + +### Patch Changes + +- 97b60de98: Added `stringifyEntityRef`, which always creates a string representation of an entity reference. Also deprecated `serializeEntityRef`, as `stringifyEntityRef` should be used instead. +- 98dd5da71: Add support for multiple links to post-scaffold task summary page + ## 0.7.5 ### Patch Changes diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index 1e5239cc23..680c73e905 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/catalog-model", - "version": "0.7.5", + "version": "0.7.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -39,7 +39,7 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.6.4", + "@backstage/cli": "^0.6.7", "@types/express": "^4.17.6", "@types/jest": "^26.0.7", "@types/lodash": "^4.14.151", diff --git a/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts b/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts index 9284a5d5b1..358e7b6526 100644 --- a/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts +++ b/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts @@ -36,6 +36,7 @@ describe('ComponentV1alpha1Validator', () => { subcomponentOf: 'monolith', providesApis: ['api-0'], consumesApis: ['api-0'], + dependsOn: ['resource:resource-0', 'component:component-0'], system: 'system', }, }; @@ -160,6 +161,26 @@ describe('ComponentV1alpha1Validator', () => { await expect(validator.check(entity)).resolves.toBe(true); }); + it('accepts missing dependsOn', async () => { + delete (entity as any).spec.dependsOn; + await expect(validator.check(entity)).resolves.toBe(true); + }); + + it('rejects empty dependsOn', async () => { + (entity as any).spec.dependsOn = ['']; + await expect(validator.check(entity)).rejects.toThrow(/dependsOn/); + }); + + it('rejects undefined dependsOn', async () => { + (entity as any).spec.dependsOn = [undefined]; + await expect(validator.check(entity)).rejects.toThrow(/dependsOn/); + }); + + it('accepts no dependsOn', async () => { + (entity as any).spec.dependsOn = []; + await expect(validator.check(entity)).resolves.toBe(true); + }); + it('accepts missing system', async () => { delete (entity as any).spec.system; 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 3006a4288c..489aa8b1bd 100644 --- a/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.ts +++ b/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.ts @@ -34,6 +34,7 @@ export interface ComponentEntityV1alpha1 extends Entity { subcomponentOf?: string; providesApis?: string[]; consumesApis?: string[]; + dependsOn?: string[]; system?: string; }; } diff --git a/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.test.ts b/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.test.ts index ad8ea5cdf3..953ec5889a 100644 --- a/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.test.ts +++ b/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.test.ts @@ -32,6 +32,7 @@ describe('ResourceV1alpha1Validator', () => { spec: { type: 'database', owner: 'me', + dependsOn: ['component:component-0', 'resource:resource-0'], system: 'system', }, }; @@ -86,6 +87,26 @@ describe('ResourceV1alpha1Validator', () => { await expect(validator.check(entity)).rejects.toThrow(/owner/); }); + it('accepts missing dependsOn', async () => { + delete (entity as any).spec.dependsOn; + await expect(validator.check(entity)).resolves.toBe(true); + }); + + it('rejects empty dependsOn', async () => { + (entity as any).spec.dependsOn = ['']; + await expect(validator.check(entity)).rejects.toThrow(/dependsOn/); + }); + + it('rejects undefined dependsOn', async () => { + (entity as any).spec.dependsOn = [undefined]; + await expect(validator.check(entity)).rejects.toThrow(/dependsOn/); + }); + + it('accepts no dependsOn', async () => { + (entity as any).spec.dependsOn = []; + await expect(validator.check(entity)).resolves.toBe(true); + }); + it('accepts missing system', async () => { delete (entity as any).spec.system; await expect(validator.check(entity)).resolves.toBe(true); diff --git a/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.ts b/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.ts index 520a39f02c..fd71500f40 100644 --- a/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.ts +++ b/packages/catalog-model/src/kinds/ResourceEntityV1alpha1.ts @@ -30,6 +30,7 @@ export interface ResourceEntityV1alpha1 extends Entity { spec: { type: string; owner: string; + dependsOn?: string[]; system?: string; }; } diff --git a/packages/catalog-model/src/schema/kinds/Component.v1alpha1.schema.json b/packages/catalog-model/src/schema/kinds/Component.v1alpha1.schema.json index 822059a0ea..34fc48d285 100644 --- a/packages/catalog-model/src/schema/kinds/Component.v1alpha1.schema.json +++ b/packages/catalog-model/src/schema/kinds/Component.v1alpha1.schema.json @@ -84,6 +84,14 @@ "type": "string", "minLength": 1 } + }, + "dependsOn": { + "type": "array", + "description": "An array of references to other entities that the component depends on to function.", + "items": { + "type": "string", + "minLength": 1 + } } } } diff --git a/packages/catalog-model/src/schema/kinds/Resource.v1alpha1.schema.json b/packages/catalog-model/src/schema/kinds/Resource.v1alpha1.schema.json index b426dd7f94..4958afc18c 100644 --- a/packages/catalog-model/src/schema/kinds/Resource.v1alpha1.schema.json +++ b/packages/catalog-model/src/schema/kinds/Resource.v1alpha1.schema.json @@ -47,6 +47,14 @@ "examples": ["artist-relations-team", "user:john.johnson"], "minLength": 1 }, + "dependsOn": { + "type": "array", + "description": "An array of references to other entities that the resource depends on to function.", + "items": { + "type": "string", + "minLength": 1 + } + }, "system": { "type": "string", "description": "An entity reference to the system that the resource belongs to.", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index c29669f31c..f9dc749009 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/cli +## 0.6.7 + +### Patch Changes + +- Updated dependencies [82c66b8cd] + - @backstage/config-loader@0.6.0 + ## 0.6.6 ### Patch Changes diff --git a/packages/cli/config/tsconfig.json b/packages/cli/config/tsconfig.json index a55b215f74..f6b4f65edd 100644 --- a/packages/cli/config/tsconfig.json +++ b/packages/cli/config/tsconfig.json @@ -11,7 +11,7 @@ "incremental": true, "isolatedModules": true, "jsx": "react", - "lib": ["DOM", "DOM.Iterable", "ScriptHost", "ES2020", "ESNext.Promise"], + "lib": ["DOM", "DOM.Iterable", "ScriptHost", "ES2020"], "module": "ESNext", "moduleResolution": "node", "noEmit": false, diff --git a/packages/cli/package.json b/packages/cli/package.json index 01306eba2a..22b116e87c 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.6.6", + "version": "0.6.7", "private": false, "publishConfig": { "access": "public" @@ -32,7 +32,7 @@ "@babel/plugin-transform-modules-commonjs": "^7.4.4", "@backstage/cli-common": "^0.1.1", "@backstage/config": "^0.1.4", - "@backstage/config-loader": "^0.5.1", + "@backstage/config-loader": "^0.6.0", "@hot-loader/react-dom": "^16.13.0", "@lerna/package-graph": "^4.0.0", "@lerna/project": "^4.0.0", @@ -116,11 +116,11 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-common": "^0.6.0", + "@backstage/backend-common": "^0.6.2", "@backstage/config": "^0.1.4", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@backstage/theme": "^0.2.5", "@types/diff": "^5.0.0", "@types/express": "^4.17.6", diff --git a/packages/cli/src/lib/bundler/transforms.ts b/packages/cli/src/lib/bundler/transforms.ts index 4f097343c2..6107485d78 100644 --- a/packages/cli/src/lib/bundler/transforms.ts +++ b/packages/cli/src/lib/bundler/transforms.ts @@ -74,7 +74,7 @@ export const transforms = (options: TransformOptions): Transforms => { /\.jpe?g$/, /\.png$/, /\.frag/, - { test: /\.svg/, not: [/\.icon\.svg/] }, + { and: [/\.svg/, { not: [/\.icon\.svg/] }] }, /\.xml/, ], loader: require.resolve('url-loader'), diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md index cbc6473286..cb8ef123ce 100644 --- a/packages/config-loader/CHANGELOG.md +++ b/packages/config-loader/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/config-loader +## 0.6.0 + +### Minor Changes + +- 82c66b8cd: Fix bug where `${...}` was not being escaped to `${...}` + + Add support for environment variable substitution in `$include`, `$file` and + `$env` transform values. + + - This change allows for including dynamic paths, such as environment specific + secrets by using the same environment variable substitution (`${..}`) already + supported outside of the various include transforms. + - If you are currently using the syntax `${...}` in your include transform values, + you will need to escape the substitution by using `${...}` instead to maintain + the same behavior. + ## 0.5.1 ### Patch Changes diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index a54975c6ff..0a0a76c2d6 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config-loader", "description": "Config loading functionality used by Backstage backend, and CLI", - "version": "0.5.1", + "version": "0.6.0", "private": false, "publishConfig": { "access": "public", diff --git a/packages/core-api/CHANGELOG.md b/packages/core-api/CHANGELOG.md index f8f38cbf59..609940b8db 100644 --- a/packages/core-api/CHANGELOG.md +++ b/packages/core-api/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/core-api +## 0.2.16 + +### Patch Changes + +- 1279a3325: Introduce a `load-chunk` step in the `BootErrorPage` to show make chunk loading + errors visible to the user. +- 4a4681b1b: Improved error messaging for routable extension errors, making it easier to identify the component and mount point that caused the error. +- b051e770c: Fixed a bug with `useRouteRef` where navigating from routes beneath a mount point would often fail. + ## 0.2.15 ### Patch Changes diff --git a/packages/core-api/package.json b/packages/core-api/package.json index 411fa44c0d..33e5ac146d 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.15", + "version": "0.2.16", "private": false, "publishConfig": { "access": "public", @@ -42,8 +42,8 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.6.6", - "@backstage/test-utils": "^0.1.9", + "@backstage/cli": "^0.6.7", + "@backstage/test-utils": "^0.1.10", "@backstage/test-utils-core": "^0.1.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 45f26804a5..519a43788d 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/core +## 0.7.4 + +### Patch Changes + +- 1279a3325: Introduce a `load-chunk` step in the `BootErrorPage` to show make chunk loading + errors visible to the user. +- 4a4681b1b: Improved error messaging for routable extension errors, making it easier to identify the component and mount point that caused the error. +- b051e770c: Fixed a bug with `useRouteRef` where navigating from routes beneath a mount point would often fail. +- 98dd5da71: Add support for multiple links to post-scaffold task summary page +- Updated dependencies [1279a3325] +- Updated dependencies [4a4681b1b] +- Updated dependencies [b051e770c] + - @backstage/core-api@0.2.16 + ## 0.7.3 ### Patch Changes diff --git a/packages/core/package.json b/packages/core/package.json index 051bacc4c2..d5f9042d0e 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.7.3", + "version": "0.7.4", "private": false, "publishConfig": { "access": "public", @@ -30,7 +30,7 @@ }, "dependencies": { "@backstage/config": "^0.1.4", - "@backstage/core-api": "^0.2.15", + "@backstage/core-api": "^0.2.16", "@backstage/errors": "^0.1.1", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", @@ -69,8 +69,8 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.6.6", - "@backstage/test-utils": "^0.1.9", + "@backstage/cli": "^0.6.7", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/packages/core/src/components/Dialog/Dialog.stories.tsx b/packages/core/src/components/Dialog/Dialog.stories.tsx new file mode 100644 index 0000000000..c9388dcbec --- /dev/null +++ b/packages/core/src/components/Dialog/Dialog.stories.tsx @@ -0,0 +1,127 @@ +/* + * Copyright 2021 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 { + Button, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + IconButton, + Typography, +} from '@material-ui/core'; +import { makeStyles, createStyles, Theme } from '@material-ui/core/styles'; +import CloseIcon from '@material-ui/icons/Close'; +import React, { useState } from 'react'; + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + closeButton: { + position: 'absolute', + right: theme.spacing(1), + top: theme.spacing(1), + color: theme.palette.grey[500], + }, + }), +); + +export default { + title: 'Layout/Dialog', + component: Dialog, +}; + +export const Default = () => { + const [open, setOpen] = useState(false); + const classes = useStyles(); + + const openDialog = () => { + setOpen(true); + }; + + const closeDialog = () => { + setOpen(false); + }; + + const dialogContent = () => { + return ( + <> + + This is an example of how to use the Dialog component. + + + This component is used whenever confirmation of some sort is needed, + such as: + +
    +
  • + + Consent to sensitive matters like GDPR, access, etc; + +
  • +
  • + + Save, submit, cancel after a form is completed; + +
  • +
  • + Alert message; +
  • +
  • + Buttons are optional. +
  • +
+ + The color for the secondary button is the same as the primary. + +
color="primary"
+ + ); + }; + + return ( + <> + + + + Dialog Box Title + + + + + {dialogContent()} + + + + + + + ); +}; diff --git a/packages/core/src/components/HeaderIconLinkRow/IconLinkVertical.tsx b/packages/core/src/components/HeaderIconLinkRow/IconLinkVertical.tsx index b3e665820a..425bed3490 100644 --- a/packages/core/src/components/HeaderIconLinkRow/IconLinkVertical.tsx +++ b/packages/core/src/components/HeaderIconLinkRow/IconLinkVertical.tsx @@ -35,12 +35,10 @@ const useIconStyles = makeStyles(theme => ({ justifyItems: 'center', gridGap: 4, textAlign: 'center', - '&:active': { - cursor: 'grabbing', - }, }, disabled: { color: 'gray', + cursor: 'default', }, primary: { color: theme.palette.primary.main, diff --git a/packages/core/src/hooks/useQueryParamState.ts b/packages/core/src/hooks/useQueryParamState.ts index dc2279cb53..da303234f5 100644 --- a/packages/core/src/hooks/useQueryParamState.ts +++ b/packages/core/src/hooks/useQueryParamState.ts @@ -58,6 +58,7 @@ type SetQueryParams = (params: T) => void; export function useQueryParamState( stateName: string, + debounceTime: number = 100, ): [T | undefined, SetQueryParams] { const navigate = useNavigate(); const location = useLocation(); @@ -85,7 +86,7 @@ export function useQueryParamState( navigate({ ...location, search: `?${queryString}` }, { replace: true }); } }, - 100, + debounceTime, [queryParamState], ); diff --git a/packages/core/src/layout/Header/Header.stories.tsx b/packages/core/src/layout/Header/Header.stories.tsx index badd63a5ad..3deb980dfd 100644 --- a/packages/core/src/layout/Header/Header.stories.tsx +++ b/packages/core/src/layout/Header/Header.stories.tsx @@ -45,6 +45,46 @@ export const HomeWithSubtitle = () => ( ); +export const Apis = () => ( + +
+ {labels} +
+
+); + +export const Grpc = () => ( + +
+ {labels} +
+
+); + +export const AsyncApi = () => ( + +
+ {labels} +
+
+); + +export const Graphql = () => ( + +
+ {labels} +
+
+); + +export const OpenApi = () => ( + +
+ {labels} +
+
+); + export const Tool = () => (
diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 762cfbc0d5..9855790e00 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,216 @@ # @backstage/create-app +## 0.3.17 + +### Patch Changes + +- 3e7de08af: **Fully migrated the template to the new composability API** + + The `create-app` template is now fully migrated to the new composability API, see [Composability System Migration Documentation](https://backstage.io/docs/plugins/composability) for explanations and more details. The final change which is now done was to migrate the `EntityPage` from being a component built on top of the `EntityPageLayout` and several more custom components, to an element tree built with `EntitySwitch` and `EntityLayout`. + + To apply this change to an existing plugin, it is important that all plugins that you are using have already been migrated. In this case the most crucial piece is that no entity page cards of contents may require the `entity` prop, and they must instead consume the entity from context using `useEntity`. + + Since this change is large with a lot of repeated changes, we'll describe a couple of common cases rather than the entire change. If your entity pages are unchanged from the `create-app` template, you can also just bring in the latest version directly from the [template itself](https://github.com/backstage/backstage/blob/master/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx). + + The first step of the change is to change the `packages/app/src/components/catalog/EntityPage.tsx` export to `entityPage` rather than `EntityPage`. This will require an update to `App.tsx`, which is the only change we need to do outside of `EntityPage.tsx`: + + ```diff + -import { EntityPage } from './components/catalog/EntityPage'; + +import { entityPage } from './components/catalog/EntityPage'; + + } + > + - + + {entityPage} + + ``` + + The rest of the changes happen within `EntityPage.tsx`, and can be split into two broad categories, updating page components, and updating switch components. + + #### Migrating Page Components + + Let's start with an example of migrating a user page component. The following is the old code in the template: + + ```tsx + const UserOverviewContent = ({ entity }: { entity: UserEntity }) => ( + + + + + + + + + ); + + const UserEntityPage = ({ entity }: { entity: Entity }) => ( + + } + /> + + ); + ``` + + There's the main `UserEntityPage` component, and the `UserOverviewContent` component. Let's start with migrating the page contents, which we do by rendering an element rather than creating a component, as well as replace the cards with their new composability compatible variants. The new cards and content components can be identified by the `Entity` prefix. + + ```tsx + const userOverviewContent = ( + + + + + + + + + ); + ``` + + Now let's migrate the page component, again by converting it into a rendered element instead of a component, as well as replacing the use of `EntityPageLayout` with `EntityLayout`. + + ```tsx + const userPage = ( + + + {userOverviewContent} + + + ); + ``` + + At this point the `userPage` is quite small, so throughout this migration we have inlined the page contents for all pages. This is an optional step, but may help reduce noise. The final page now looks like this: + + ```tsx + const userPage = ( + + + + + + + + + + + + + ); + ``` + + #### Migrating Switch Components + + Switch components were used to select what entity page components or cards to render, based on for example the kind of entity. For this example we'll focus on the root `EntityPage` switch component, but the process is the same for example for the CI/CD switcher. + + The old `EntityPage` looked like this: + + ```tsx + export const EntityPage = () => { + const { entity } = useEntity(); + + switch (entity?.kind?.toLocaleLowerCase('en-US')) { + case 'component': + return ; + case 'api': + return ; + case 'group': + return ; + case 'user': + return ; + case 'system': + return ; + case 'domain': + return ; + case 'location': + case 'resource': + case 'template': + default: + return ; + } + }; + ``` + + In order to migrate to the composability API, we need to make this an element instead of a component, which means we're unable to keep the switch statement as is. To help with this, the catalog plugin provides an `EntitySwitch` component, which functions similar to a regular `switch` statement, which the first match being the one that is rendered. The catalog plugin also provides a number of built-in filter functions to use, such as `isKind` and `isComponentType`. + + To migrate the `EntityPage`, we convert the `switch` statement into an `EntitySwitch` element, and each `case` statement into an `EntitySwitch.Case` element. We also move over to use our new element version of the page components, with the result looking like this: + + ```tsx + export const entityPage = ( + + + + + + + + + {defaultEntityPage} + + ); + ``` + + Another example is the `ComponentEntityPage`, which is migrated from this: + + ```tsx + export const ComponentEntityPage = ({ entity }: { entity: Entity }) => { + switch (entity?.spec?.type) { + case 'service': + return ; + case 'website': + return ; + default: + return ; + } + }; + ``` + + To this: + + ```tsx + const componentPage = ( + + + {serviceEntityPage} + + + + {websiteEntityPage} + + + {defaultEntityPage} + + ); + ``` + + Note that if you want to conditionally render some piece of content, you can omit the default `EntitySwitch.Case`. If no case is matched in an `EntitySwitch`, nothing will be rendered. + +- Updated dependencies [802b41b65] +- Updated dependencies [2b2b31186] +- Updated dependencies [1279a3325] +- Updated dependencies [4a4681b1b] +- Updated dependencies [97b60de98] +- Updated dependencies [3f96a9d5a] +- Updated dependencies [b051e770c] +- Updated dependencies [f9c75f7a9] +- Updated dependencies [ae6250ce3] +- Updated dependencies [98dd5da71] +- Updated dependencies [b779b5fee] + - @backstage/plugin-scaffolder-backend@0.9.5 + - @backstage/plugin-auth-backend@0.3.8 + - @backstage/core@0.7.4 + - @backstage/catalog-model@0.7.6 + - @backstage/plugin-scaffolder@0.8.2 + - @backstage/plugin-catalog-import@0.5.2 + - @backstage/test-utils@0.1.10 + - @backstage/plugin-catalog@0.5.3 + - @backstage/backend-common@0.6.2 + - @backstage/cli@0.6.7 + - @backstage/plugin-app-backend@0.3.11 + ## 0.3.16 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index e62a544ba1..35ce1b5180 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.3.16", + "version": "0.3.17", "private": false, "publishConfig": { "access": "public" diff --git a/packages/create-app/templates/default-app/package.json.hbs b/packages/create-app/templates/default-app/package.json.hbs index d7f7fbafaf..7ae86c0fbc 100644 --- a/packages/create-app/templates/default-app/package.json.hbs +++ b/packages/create-app/templates/default-app/package.json.hbs @@ -22,6 +22,10 @@ "create-plugin": "backstage-cli create-plugin --scope internal --no-private", "remove-plugin": "backstage-cli remove-plugin" }, + "resolutions": { + "graphql-language-service-interface": "2.8.2", + "graphql-language-service-parser": "1.9.0" + }, "workspaces": { "packages": [ "packages/*", 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 1cd7b77965..1ed7aa030a 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 @@ -12,14 +12,14 @@ import { CatalogIndexPage, catalogPlugin, } from '@backstage/plugin-catalog'; -import { CatalogImportPage } from '@backstage/plugin-catalog-import'; +import {CatalogImportPage, catalogImportPlugin} from '@backstage/plugin-catalog-import'; import { ScaffolderPage, scaffolderPlugin } from '@backstage/plugin-scaffolder'; import { SearchPage } from '@backstage/plugin-search'; import { TechRadarPage } from '@backstage/plugin-tech-radar'; import { TechdocsPage } from '@backstage/plugin-techdocs'; import { UserSettingsPage } from '@backstage/plugin-user-settings'; import { apis } from './apis'; -import { EntityPage } from './components/catalog/EntityPage'; +import { entityPage } from './components/catalog/EntityPage'; import { Root } from './components/Root'; import * as plugins from './plugins'; @@ -33,6 +33,9 @@ const app = createApp({ bind(apiDocsPlugin.externalRoutes, { createComponent: scaffolderPlugin.routes.root, }); + bind(scaffolderPlugin.externalRoutes, { + registerComponent: catalogImportPlugin.routes.importPage, + }); }, }); @@ -47,7 +50,7 @@ const routes = ( path="/catalog/:namespace/:kind/:name" element={} > - + {entityPage} } /> } /> diff --git a/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx b/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx index d05f6bfa8d..f1aba46c52 100644 --- a/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx @@ -15,308 +15,248 @@ */ import React from 'react'; import { Button, Grid } from '@material-ui/core'; -import { - ApiEntity, - DomainEntity, - Entity, - GroupEntity, - SystemEntity, - UserEntity, -} from '@backstage/catalog-model'; import { EmptyState } from '@backstage/core'; import { - ApiDefinitionCard, - ConsumedApisCard, - ConsumingComponentsCard, + EntityApiDefinitionCard, + EntityConsumedApisCard, + EntityConsumingComponentsCard, EntityHasApisCard, - ProvidedApisCard, - ProvidingComponentsCard, + EntityProvidedApisCard, + EntityProvidingComponentsCard, } from '@backstage/plugin-api-docs'; import { - AboutCard, + EntityAboutCard, + EntitySystemDiagramCard, EntityHasComponentsCard, EntityHasSystemsCard, - EntityPageLayout, + EntityLayout, + EntitySwitch, + isComponentType, + isKind, } from '@backstage/plugin-catalog'; -import { useEntity } from '@backstage/plugin-catalog-react'; import { - isPluginApplicableToEntity as isGitHubActionsAvailable, - Router as GitHubActionsRouter, + isGithubActionsAvailable, + EntityGithubActionsContent, } from '@backstage/plugin-github-actions'; import { - GroupProfileCard, - MembersListCard, - OwnershipCard, - UserProfileCard, + EntityUserProfileCard, + EntityGroupProfileCard, + EntityMembersListCard, + EntityOwnershipCard, } from '@backstage/plugin-org'; -import { EmbeddedDocsRouter as DocsRouter } from '@backstage/plugin-techdocs'; +import { EntityTechdocsContent } from '@backstage/plugin-techdocs'; - -const CICDSwitcher = ({ entity }: { entity: Entity }) => { - // This component is just an example of how you can implement your company's logic in entity page. +const cicdContent = ( + // This is an example of how you can implement your company's logic in entity page. // You can for example enforce that all components of type 'service' should use GitHubActions - switch (true) { - case isGitHubActionsAvailable(entity): - return ; - default: - return ( - - Read more - - } - /> - ); - } -}; + + + + -const OverviewContent = ({ entity }: { entity: Entity }) => ( + + + Read more + + } + /> + + +); + +const overviewContent = ( - + ); -const ComponentApisContent = ({ entity }: { entity: Entity }) => ( - - - - - - - - -); +const serviceEntityPage = ( + + + {overviewContent} + -const ServiceEntityPage = ({ entity }: { entity: Entity }) => ( - - } - /> - } - /> - } - /> - } - /> - -); + + {cicdContent} + -const WebsiteEntityPage = ({ entity }: { entity: Entity }) => ( - - } - /> - } - /> - } - /> - -); - -const DefaultEntityPage = ({ entity }: { entity: Entity }) => ( - - } - /> - } - /> - -); - -export const ComponentEntityPage = ({ entity }: { entity: Entity }) => { - switch (entity?.spec?.type) { - case 'service': - return ; - case 'website': - return ; - default: - return ; - } -}; - -const ApiOverviewContent = ({ entity }: { entity: Entity }) => ( - - - - - - - + + + + + + + + - - + + + + + + +); + +const websiteEntityPage = ( + + + {overviewContent} + + + + {cicdContent} + + + + + + +); + +const defaultEntityPage = ( + + + {overviewContent} + + + + + + +); + +const componentPage = ( + + + {serviceEntityPage} + + + + {websiteEntityPage} + + + {defaultEntityPage} + +); + +const apiPage = ( + + + + + + + + + + + + + + - - + + + + + + + + + + ); -const ApiDefinitionContent = ({ entity }: { entity: ApiEntity }) => ( - - - - - +const userPage = ( + + + + + + + + + + + + ); -const ApiEntityPage = ({ entity }: { entity: Entity }) => ( - - } - /> - } - /> - +const groupPage = ( + + + + + + + + + + + + + + + + + + + ); -const UserOverviewContent = ({ entity }: { entity: UserEntity }) => ( - - - - - - - - +const systemPage = ( + + + + + + + + + + + + + + + ); -const UserEntityPage = ({ entity }: { entity: Entity }) => ( - - } - /> - +const domainPage = ( + + + + + + + + + + + + ); -const GroupOverviewContent = ({ entity }: { entity: GroupEntity }) => ( - - - - - - - - - - - +export const entityPage = ( + + + + + + + + + {defaultEntityPage} + ); - -const GroupEntityPage = ({ entity }: { entity: Entity }) => ( - - } - /> - -); - -const SystemOverviewContent = ({ entity }: { entity: SystemEntity }) => ( - - - - - - - - - - - -); - -const SystemEntityPage = ({ entity }: { entity: Entity }) => ( - - } - /> - -); - -const DomainOverviewContent = ({ entity }: { entity: DomainEntity }) => ( - - - - - - - - -); - -const DomainEntityPage = ({ entity }: { entity: Entity }) => ( - - } - /> - -); - -export const EntityPage = () => { - const { entity } = useEntity(); - - switch (entity?.kind?.toLocaleLowerCase('en-US')) { - case 'component': - return ; - case 'api': - return ; - case 'group': - return ; - case 'user': - return ; - case 'system': - return ; - case 'domain': - return ; - case 'location': - case 'resource': - case 'template': - default: - return ; - } -}; diff --git a/packages/create-app/templates/default-app/packages/backend/Dockerfile b/packages/create-app/templates/default-app/packages/backend/Dockerfile index acef405c8a..31231a3a4a 100644 --- a/packages/create-app/templates/default-app/packages/backend/Dockerfile +++ b/packages/create-app/templates/default-app/packages/backend/Dockerfile @@ -16,11 +16,13 @@ WORKDIR /app # Copy repo skeleton first, to avoid unnecessary docker cache invalidation. # The skeleton contains the package.json of each package in the monorepo, # and along with yarn.lock and the root package.json, that's enough to run yarn install. -ADD yarn.lock package.json packages/backend/dist/skeleton.tar.gz ./ +COPY yarn.lock package.json packages/backend/dist/skeleton.tar.gz ./ +RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz RUN yarn install --frozen-lockfile --production --network-timeout 300000 && rm -rf "$(yarn cache dir)" # Then copy the rest of the backend bundle, along with any other files we might want. -ADD packages/backend/dist/bundle.tar.gz app-config.yaml ./ +COPY packages/backend/dist/bundle.tar.gz app-config.yaml ./ +RUN tar xzf bundle.tar.gz && rm bundle.tar.gz CMD ["node", "packages/backend", "--config", "app-config.yaml"] diff --git a/packages/integration/config.d.ts b/packages/integration/config.d.ts index f0d72b7ceb..ddc84ae011 100644 --- a/packages/integration/config.d.ts +++ b/packages/integration/config.d.ts @@ -149,5 +149,19 @@ export interface Config { */ baseUrl?: string; }>; + + /** Integration configuration for Google Cloud Storage */ + googleGcs?: { + /** + * Service account email used to authenticate requests. + * @visibility backend + */ + clientEmail?: string; + /** + * Service account private key used to authenticate requests. + * @visibility secret + */ + privateKey?: string; + }; }; } diff --git a/packages/integration/package.json b/packages/integration/package.json index c57c0e78cd..dcfae4ea05 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -37,9 +37,9 @@ "luxon": "^1.25.0" }, "devDependencies": { - "@backstage/cli": "^0.6.4", - "@backstage/config-loader": "^0.5.1", - "@backstage/test-utils": "^0.1.7", + "@backstage/cli": "^0.6.7", + "@backstage/config-loader": "^0.6.0", + "@backstage/test-utils": "^0.1.10", "@types/jest": "^26.0.7", "@types/luxon": "^1.25.0", "msw": "^0.21.2" diff --git a/packages/integration/src/googleGcs/config.test.ts b/packages/integration/src/googleGcs/config.test.ts new file mode 100644 index 0000000000..a924e953b9 --- /dev/null +++ b/packages/integration/src/googleGcs/config.test.ts @@ -0,0 +1,45 @@ +/* + * 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, ConfigReader } from '@backstage/config'; +import { + GoogleGcsIntegrationConfig, + readGoogleGcsIntegrationConfig, +} from './config'; + +describe('readGoogleGcsIntegrationConfig', () => { + function buildConfig(data: Partial): Config { + return new ConfigReader(data); + } + + it('reads all values', () => { + const output = readGoogleGcsIntegrationConfig( + buildConfig({ + privateKey: 'fake-key', + clientEmail: 'someone@example.com', + }), + ); + expect(output).toEqual({ + privateKey: 'fake-key', + clientEmail: 'someone@example.com', + }); + }); + + it('does not fail when config is not set', () => { + const output = readGoogleGcsIntegrationConfig(buildConfig({})); + expect(output).toEqual({}); + }); +}); diff --git a/packages/integration/src/googleGcs/config.ts b/packages/integration/src/googleGcs/config.ts new file mode 100644 index 0000000000..7924138b5a --- /dev/null +++ b/packages/integration/src/googleGcs/config.ts @@ -0,0 +1,53 @@ +/* + * 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 Google Cloud Storage provider. + */ +export type GoogleGcsIntegrationConfig = { + /** + * Service account email used to authenticate requests. + */ + clientEmail?: string; + /** + * Service account private key used to authenticate requests. + */ + privateKey?: string; +}; + +/** + * Reads a single Google GCS integration config. + * + * @param config The config object of a single integration + */ +export function readGoogleGcsIntegrationConfig( + config: Config, +): GoogleGcsIntegrationConfig { + if (!config) { + return {}; + } + + if (!config.has('clientEmail') && !config.has('privateKey')) { + return {}; + } + + const privateKey = config.getString('privateKey').split('\\n').join('\n'); + + const clientEmail = config.getString('clientEmail'); + return { clientEmail: clientEmail, privateKey: privateKey }; +} diff --git a/plugins/techdocs-backend/src/service/helpers.ts b/packages/integration/src/googleGcs/index.ts similarity index 57% rename from plugins/techdocs-backend/src/service/helpers.ts rename to packages/integration/src/googleGcs/index.ts index fc80ab717d..d9355fd299 100644 --- a/plugins/techdocs-backend/src/service/helpers.ts +++ b/packages/integration/src/googleGcs/index.ts @@ -13,18 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { EntityName } from '@backstage/catalog-model'; -/** - * Using the path of the TechDocs page URL, return a structured EntityName type object with namespace, - * kind and name of the Entity. - * @param {string} path Example: default/Component/documented-component - */ -export const getEntityNameFromUrlPath = (path: string): EntityName => { - const [namespace, kind, name] = path.split('/'); - return { - namespace, - kind, - name, - }; -}; +export { readGoogleGcsIntegrationConfig } from './config'; +export type { GoogleGcsIntegrationConfig } from './config'; diff --git a/packages/integration/src/index.ts b/packages/integration/src/index.ts index e89cf6ef92..d15eea0832 100644 --- a/packages/integration/src/index.ts +++ b/packages/integration/src/index.ts @@ -18,6 +18,7 @@ export * from './azure'; export * from './bitbucket'; export * from './github'; export * from './gitlab'; +export * from './googleGcs'; export { defaultScmResolveUrl } from './helpers'; export { ScmIntegrations } from './ScmIntegrations'; export type { diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index bcdc94abbb..d2c2748449 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/test-utils +## 0.1.10 + +### Patch Changes + +- ae6250ce3: Remove unnecessary wrapping of elements rendered by `wrapInTestApp` and `renderInTestApp`, which was breaking mount discovery. +- Updated dependencies [1279a3325] +- Updated dependencies [4a4681b1b] +- Updated dependencies [b051e770c] + - @backstage/core-api@0.2.16 + ## 0.1.9 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index f3a979fc72..a81455df01 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/test-utils", "description": "Utilities to test Backstage plugins and apps.", - "version": "0.1.9", + "version": "0.1.10", "private": false, "publishConfig": { "access": "public", @@ -29,7 +29,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-api": "^0.2.14", + "@backstage/core-api": "^0.2.16", "@backstage/test-utils-core": "^0.1.1", "@backstage/theme": "^0.2.3", "@material-ui/core": "^4.11.0", @@ -45,7 +45,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.6.5", + "@backstage/cli": "^0.6.7", "@types/jest": "^26.0.7", "@types/node": "^14.14.32" }, diff --git a/packages/theme/src/pageTheme.ts b/packages/theme/src/pageTheme.ts index f86f3a6449..c9a61bd95b 100644 --- a/packages/theme/src/pageTheme.ts +++ b/packages/theme/src/pageTheme.ts @@ -63,4 +63,5 @@ export const pageTheme: Record = { library: genPageTheme(colorVariants.rubyRed, shapes.wave), other: genPageTheme(colorVariants.darkGrey, shapes.wave), app: genPageTheme(colorVariants.toastyOrange, shapes.wave), + apis: genPageTheme(colorVariants.eveningSea, shapes.wave2), }; diff --git a/plugins/api-docs/README.md b/plugins/api-docs/README.md index 0b8d658f89..4e71e87275 100644 --- a/plugins/api-docs/README.md +++ b/plugins/api-docs/README.md @@ -1,7 +1,5 @@ # API Documentation -WORK IN PROGRESS - This is an extension for the catalog plugin that provides components to discover and display API entities. APIs define the interface between components, see the [system model](https://backstage.io/docs/features/software-catalog/system-model) for details. They are defined in machine readable formats and provide a human readable documentation. @@ -23,9 +21,145 @@ Other formats are displayed as plain text, but this can easily be extended. To fill the catalog with APIs, [provide entities of kind API](https://backstage.io/docs/features/software-catalog/descriptor-format#kind-api). To link that a component provides or consumes an API, see the [`providesApis`](https://backstage.io/docs/features/software-catalog/descriptor-format#specprovidesapis-optional) and [`consumesApis`](https://backstage.io/docs/features/software-catalog/descriptor-format#specconsumesapis-optional) properties on the Component kind. -## Implementing OAuth 2 Authorization Code flow with Swagger UI +## Getting Started -### Adding `oauth2-redirect.html` to support OAuth2 `redirect_uri` route +> The plugin is already added when using `npx @backstage/create-app` so you can skip these steps. + +1. Install the API docs plugin + +```bash +# packages/app + +yarn add @backstage/plugin-api-docs +``` + +2. Add the plugin to the app: + +```ts +// packages/app/src/plugins.ts + +export { apiDocsPlugin } from '@backstage/plugin-api-docs'; +``` + +} /> + +3. Register the `ApiExplorerPage` at the `/api-docs` path: + +```tsx +// packages/app/src/App.tsx + +import { ApiExplorerPage } from '@backstage/plugin-api-docs'; + +} />; +``` + +4. Add one of the provided widgets to the EntityPage: + +```tsx +// packages/app/src/components/catalog/EntityPage.tsx + +import { + EntityAboutCard, + EntityApiDefinitionCard, + EntityConsumingComponentsCard, + EntityProvidingComponentsCard, +} from '@backstage/plugin-api-docs'; + +const apiPage = ( + + + + + + + + + + + + + + + + + + + + + + + + + +); + +// ... + +export const entityPage = ( + + // ... + + // ... + +); +``` + +There are other components to discover in [`./src/components`](./src/components) that are also added by the default app. + +## Customizations + +### Custom API Renderings + +You can add support for additional API types by providing a custom implementation for the `apiDocsConfigRef`. +You can also use this to override the rendering of one of the already supported types. + +This is an example with a made-up renderer for SQL schemas: + +```tsx +// packages/app/src/apis.tsx + +import { ApiEntity } from '@backstage/catalog-model'; +import { + ApiDefinitionWidget, + apiDocsConfigRef, + defaultDefinitionWidgets, +} from '@backstage/plugin-api-docs'; +import { SqlRenderer } from '...'; + +// ... + +export const apis: AnyApiFactory[] = [ + // ... + + createApiFactory({ + api: apiDocsConfigRef, + deps: {}, + factory: () => { + // load the default widgets + const definitionWidgets = defaultDefinitionWidgets(); + return { + getApiDefinitionWidget: (apiEntity: ApiEntity) => { + // custom rendering for sql + if (apiEntity.spec.type === 'sql') { + return { + type: 'sql', + title: 'SQL', + component: definition => , + } as ApiDefinitionWidget; + } + + // fallback to the defaults + return definitionWidgets.find(d => d.type === apiEntity.spec.type); + }, + }; + }, + }), +]; +``` + +### Implementing OAuth 2 Authorization Code flow with Swagger UI + +#### Adding `oauth2-redirect.html` to support OAuth2 `redirect_uri` route The Swagger UI package by expects to have a route to `/oauth2-redirect.html` which processes the redirect callback for the OAuth2 Authorization Code flow, however, this file is not installed @@ -34,7 +168,7 @@ by this plugin. Grab a copy of [oauth2-redirect.html](https://github.com/swagger-api/swagger-ui/blob/master/dist/oauth2-redirect.html) and put it in the `app/public/` directory in order to enable Swagger UI to complete this redirection. -### Configuring your OAuth2 Client +#### Configuring your OAuth2 Client You'll need to make sure your OAuth2 client has been registered in your OAuth2 Authentication Server (AS) with the appropriate `redirect_uris`, `scopes` and `grant_types`. For example, if your AS supports @@ -62,7 +196,7 @@ The above `redirect_uris` are: - Local Backstage app development: `http://localhost:3000/oauth2-redirect.html` - Backstage app production: `https:///oauth2-redirect.html` -### Configuring OAuth2 in your OpenAPI 3.0 schema +#### Configuring OAuth2 in your OpenAPI 3.0 schema To configure [OAuth 2 Authorization Code](https://swagger.io/docs/specification/authentication/oauth2/) flow in your OpenAPI 3.0 schema you'll need something like this snippet: diff --git a/plugins/api-docs/docs/api_list.png b/plugins/api-docs/docs/api_list.png index 4ca2f09542..97d38e25a6 100644 Binary files a/plugins/api-docs/docs/api_list.png and b/plugins/api-docs/docs/api_list.png differ diff --git a/plugins/api-docs/docs/entity_tab_api.png b/plugins/api-docs/docs/entity_tab_api.png index 439fac73fa..213f6eb04a 100644 Binary files a/plugins/api-docs/docs/entity_tab_api.png and b/plugins/api-docs/docs/entity_tab_api.png differ diff --git a/plugins/api-docs/docs/openapi_definition.png b/plugins/api-docs/docs/openapi_definition.png index 49d12a08e8..c6a0350914 100644 Binary files a/plugins/api-docs/docs/openapi_definition.png and b/plugins/api-docs/docs/openapi_definition.png differ diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 7f34627f6b..d7f5f3754b 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -31,7 +31,7 @@ "dependencies": { "@asyncapi/react-component": "^0.19.2", "@backstage/catalog-model": "^0.7.5", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/plugin-catalog-react": "^0.1.4", "@backstage/theme": "^0.2.5", "@material-icons/font": "^1.0.2", @@ -49,9 +49,9 @@ "swagger-ui-react": "^3.37.2" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerLayout.tsx b/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerLayout.tsx index add886fead..fb94df8528 100644 --- a/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerLayout.tsx +++ b/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerLayout.tsx @@ -26,7 +26,7 @@ export const ApiExplorerLayout = ({ children }: Props) => { configApi.getOptionalString('organization.name') ?? 'Backstage' } API Explorer`; return ( - +
{ const [queryParamState, setQueryParamState] = useQueryParamState( 'apiTable', + 500, ); if (error) { diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index e8c4510d54..85fab4455d 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-app-backend +## 0.3.11 + +### Patch Changes + +- Updated dependencies [82c66b8cd] +- Updated dependencies [b779b5fee] + - @backstage/config-loader@0.6.0 + - @backstage/backend-common@0.6.2 + ## 0.3.10 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index 9346c6366d..c6a1dd5a6b 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-app-backend", - "version": "0.3.10", + "version": "0.3.11", "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.6.0", - "@backstage/config-loader": "^0.5.1", + "@backstage/backend-common": "^0.6.2", + "@backstage/config-loader": "^0.6.0", "@backstage/config": "^0.1.4", "@types/express": "^4.17.6", "express": "^4.17.1", @@ -40,7 +40,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.6.5", + "@backstage/cli": "^0.6.7", "@types/supertest": "^2.0.8", "msw": "^0.20.5", "supertest": "^6.1.3" diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index bb2c44f7ff..47616b68c7 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-auth-backend +## 0.3.8 + +### Patch Changes + +- 2b2b31186: When using OAuth2 authentication the name is now taken from the name property of the JWT instead of the email property +- Updated dependencies [97b60de98] +- Updated dependencies [ae6250ce3] +- Updated dependencies [98dd5da71] +- Updated dependencies [b779b5fee] + - @backstage/catalog-model@0.7.6 + - @backstage/test-utils@0.1.10 + - @backstage/backend-common@0.6.2 + ## 0.3.7 ### Patch Changes diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 183798c9e1..4af8a1736d 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend", - "version": "0.3.7", + "version": "0.3.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,12 +29,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.6.1", + "@backstage/backend-common": "^0.6.2", "@backstage/catalog-client": "^0.3.9", - "@backstage/catalog-model": "^0.7.5", + "@backstage/catalog-model": "^0.7.6", "@backstage/config": "^0.1.4", "@backstage/errors": "^0.1.1", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@types/express": "^4.17.6", "@types/passport": "^1.0.3", "compression": "^1.7.4", @@ -68,7 +68,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@types/body-parser": "^1.19.0", "@types/cookie-parser": "^1.4.2", "@types/express-session": "^1.17.2", diff --git a/plugins/badges-backend/CHANGELOG.md b/plugins/badges-backend/CHANGELOG.md new file mode 100644 index 0000000000..69785a645f --- /dev/null +++ b/plugins/badges-backend/CHANGELOG.md @@ -0,0 +1,12 @@ +# @backstage/plugin-badges-backend + +## 0.1.2 + +### Patch Changes + +- d0b4ebf22: Support auth in badge plugin +- Updated dependencies [97b60de98] +- Updated dependencies [98dd5da71] +- Updated dependencies [b779b5fee] + - @backstage/catalog-model@0.7.6 + - @backstage/backend-common@0.6.2 diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index 6ff83ecac9..eb2a93fe67 100644 --- a/plugins/badges-backend/package.json +++ b/plugins/badges-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-badges-backend", - "version": "0.1.1", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,9 +30,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.6.0", + "@backstage/backend-common": "^0.6.2", "@backstage/catalog-client": "^0.3.6", - "@backstage/catalog-model": "^0.7.3", + "@backstage/catalog-model": "^0.7.6", "@backstage/config": "^0.1.3", "@backstage/errors": "^0.1.1", "@types/express": "^4.17.6", @@ -45,7 +45,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.6.3", + "@backstage/cli": "^0.6.7", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/badges/CHANGELOG.md b/plugins/badges/CHANGELOG.md index bc3e64113a..a0efd43ccc 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-badges +## 0.2.0 + +### Minor Changes + +- d0b4ebf22: Support auth in badge plugin + +### Patch Changes + +- Updated dependencies [1279a3325] +- Updated dependencies [4a4681b1b] +- Updated dependencies [97b60de98] +- Updated dependencies [b051e770c] +- Updated dependencies [98dd5da71] + - @backstage/core@0.7.4 + - @backstage/catalog-model@0.7.6 + ## 0.1.2 ### Patch Changes diff --git a/plugins/badges/package.json b/plugins/badges/package.json index e438a6807b..1ab7315278 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-badges", - "version": "0.1.2", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,8 +20,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.3", + "@backstage/catalog-model": "^0.7.6", + "@backstage/core": "^0.7.4", "@backstage/errors": "^0.1.1", "@backstage/plugin-catalog-react": "^0.1.3", "@backstage/theme": "^0.2.5", @@ -34,9 +34,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index f7f58d99cf..8a3b519fcb 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -21,7 +21,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.2", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/plugin-catalog-react": "^0.1.2", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", @@ -37,9 +37,9 @@ "recharts": "^1.8.5" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts index 2162272390..cb60c119b6 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts @@ -45,13 +45,14 @@ describe('BuiltinKindsEntityProcessor', () => { lifecycle: 'l', providesApis: ['b'], consumesApis: ['c'], + dependsOn: ['Resource:r', 'Component:d'], system: 's', }, }; await processor.postProcessEntity(entity, location, emit); - expect(emit).toBeCalledTimes(10); + expect(emit).toBeCalledTimes(14); expect(emit).toBeCalledWith({ type: 'relation', relation: { @@ -100,6 +101,38 @@ describe('BuiltinKindsEntityProcessor', () => { target: { kind: 'API', namespace: 'default', name: 'c' }, }, }); + expect(emit).toBeCalledWith({ + type: 'relation', + relation: { + source: { kind: 'Component', namespace: 'default', name: 'n' }, + type: 'dependsOn', + target: { kind: 'Resource', namespace: 'default', name: 'r' }, + }, + }); + expect(emit).toBeCalledWith({ + type: 'relation', + relation: { + source: { kind: 'Resource', namespace: 'default', name: 'r' }, + type: 'dependencyOf', + target: { kind: 'Component', namespace: 'default', name: 'n' }, + }, + }); + expect(emit).toBeCalledWith({ + type: 'relation', + relation: { + source: { kind: 'Component', namespace: 'default', name: 'n' }, + type: 'dependsOn', + target: { kind: 'Component', namespace: 'default', name: 'd' }, + }, + }); + expect(emit).toBeCalledWith({ + type: 'relation', + relation: { + source: { kind: 'Component', namespace: 'default', name: 'd' }, + type: 'dependencyOf', + target: { kind: 'Component', namespace: 'default', name: 'n' }, + }, + }); expect(emit).toBeCalledWith({ type: 'relation', relation: { @@ -134,6 +167,29 @@ describe('BuiltinKindsEntityProcessor', () => { }); }); + it('generates an error for component entities with unspecified dependsOn entity reference kinds', async () => { + const entity: ComponentEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { name: 'n' }, + spec: { + type: 'service', + owner: 'o', + subcomponentOf: 's', + lifecycle: 'l', + providesApis: ['b'], + consumesApis: ['c'], + dependsOn: ['r'], + system: 's', + }, + }; + await expect( + processor.postProcessEntity(entity, location, emit), + ).rejects.toThrowError( + 'Entity reference "r" did not specify a kind (e.g. starting with "Component:"), and has no default', + ); + }); + it('generates relations for api entities', async () => { const entity: ApiEntity = { apiVersion: 'backstage.io/v1alpha1', @@ -193,13 +249,14 @@ describe('BuiltinKindsEntityProcessor', () => { spec: { type: 'database', owner: 'o', + dependsOn: ['Component:c', 'Resource:r'], system: 's', }, }; await processor.postProcessEntity(entity, location, emit); - expect(emit).toBeCalledTimes(4); + expect(emit).toBeCalledTimes(8); expect(emit).toBeCalledWith({ type: 'relation', relation: { @@ -216,6 +273,41 @@ describe('BuiltinKindsEntityProcessor', () => { target: { kind: 'Group', namespace: 'default', name: 'o' }, }, }); + + expect(emit).toBeCalledWith({ + type: 'relation', + relation: { + source: { kind: 'Resource', namespace: 'default', name: 'n' }, + type: 'dependsOn', + target: { kind: 'Component', namespace: 'default', name: 'c' }, + }, + }); + expect(emit).toBeCalledWith({ + type: 'relation', + relation: { + source: { kind: 'Component', namespace: 'default', name: 'c' }, + type: 'dependencyOf', + target: { kind: 'Resource', namespace: 'default', name: 'n' }, + }, + }); + + expect(emit).toBeCalledWith({ + type: 'relation', + relation: { + source: { kind: 'Resource', namespace: 'default', name: 'n' }, + type: 'dependsOn', + target: { kind: 'Resource', namespace: 'default', name: 'r' }, + }, + }); + expect(emit).toBeCalledWith({ + type: 'relation', + relation: { + source: { kind: 'Resource', namespace: 'default', name: 'r' }, + type: 'dependencyOf', + target: { kind: 'Resource', namespace: 'default', name: 'n' }, + }, + }); + expect(emit).toBeCalledWith({ type: 'relation', relation: { @@ -234,6 +326,25 @@ describe('BuiltinKindsEntityProcessor', () => { }); }); + it('generates an error for resource entities with unspecified dependsOn entity reference kinds', async () => { + const entity: ResourceEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Resource', + metadata: { name: 'n' }, + spec: { + type: 'database', + owner: 'o', + dependsOn: ['c'], + system: 's', + }, + }; + await expect( + processor.postProcessEntity(entity, location, emit), + ).rejects.toThrowError( + 'Entity reference "c" did not specify a kind (e.g. starting with "Component:"), and has no default', + ); + }); + it('generates relations for system entities', async () => { const entity: SystemEntity = { apiVersion: 'backstage.io/v1alpha1', diff --git a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts index 64a47127f9..404d7fd30d 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts @@ -32,6 +32,8 @@ import { RELATION_API_PROVIDED_BY, RELATION_CHILD_OF, RELATION_CONSUMES_API, + RELATION_DEPENDENCY_OF, + RELATION_DEPENDS_ON, RELATION_HAS_MEMBER, RELATION_HAS_PART, RELATION_MEMBER_OF, @@ -90,7 +92,7 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor { function doEmit( targets: string | string[] | undefined, - context: { defaultKind: string; defaultNamespace: string }, + context: { defaultKind?: string; defaultNamespace: string }, outgoingRelation: string, incomingRelation: string, ): void { @@ -99,16 +101,29 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor { } for (const target of [targets].flat()) { const targetRef = parseEntityRef(target, context); + if (targetRef.kind === undefined) { + throw new Error( + `Entity reference "${target}" did not specify a kind (e.g. starting with "Component:"), and has no default`, + ); + } emit( result.relation({ source: selfRef, type: outgoingRelation, - target: targetRef, + target: { + kind: targetRef.kind, + namespace: targetRef.namespace, + name: targetRef.name, + }, }), ); emit( result.relation({ - source: targetRef, + source: { + kind: targetRef.kind, + namespace: targetRef.namespace, + name: targetRef.name, + }, type: incomingRelation, target: selfRef, }), @@ -146,6 +161,12 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor { RELATION_CONSUMES_API, RELATION_API_CONSUMED_BY, ); + doEmit( + component.spec.dependsOn, + { defaultNamespace: selfRef.namespace }, + RELATION_DEPENDS_ON, + RELATION_DEPENDENCY_OF, + ); doEmit( component.spec.system, { defaultKind: 'System', defaultNamespace: selfRef.namespace }, @@ -186,6 +207,12 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor { RELATION_OWNED_BY, RELATION_OWNER_OF, ); + doEmit( + resource.spec.dependsOn, + { defaultNamespace: selfRef.namespace }, + RELATION_DEPENDS_ON, + RELATION_DEPENDENCY_OF, + ); doEmit( resource.spec.system, { defaultKind: 'System', defaultNamespace: selfRef.namespace }, 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 5e293766aa..aac9a091b8 100644 --- a/plugins/catalog-backend/src/ingestion/processors/ldap/config.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/ldap/config.test.ts @@ -172,4 +172,35 @@ describe('readLdapConfig', () => { ]; expect(actual).toEqual(expected); }); + + it('supports multiline ldap query filter', () => { + const config = { + providers: [ + { + target: 'target', + users: { + dn: 'udn', + options: { + filter: ` + (| + (cn=foo bar) + (cn=bar) + ) + `, + }, + }, + groups: { + dn: 'gdn', + options: { + filter: 'f', + }, + }, + }, + ], + }; + const actual = readLdapConfig(new ConfigReader(config)); + + const expected = '(|(cn=foo bar)(cn=bar))'; + expect(actual[0].users.options.filter).toEqual(expected); + }); }); diff --git a/plugins/catalog-backend/src/ingestion/processors/ldap/config.ts b/plugins/catalog-backend/src/ingestion/processors/ldap/config.ts index 7608f247d4..625282ca05 100644 --- a/plugins/catalog-backend/src/ingestion/processors/ldap/config.ts +++ b/plugins/catalog-backend/src/ingestion/processors/ldap/config.ts @@ -182,7 +182,7 @@ export function readLdapConfig(config: Config): LdapProviderConfig[] { } return { scope: c.getOptionalString('scope') as SearchOptions['scope'], - filter: c.getOptionalString('filter'), + filter: formatFilter(c.getOptionalString('filter')), attributes: c.getOptionalStringArray('attributes'), paged: c.getOptionalBoolean('paged'), }; @@ -260,6 +260,11 @@ export function readLdapConfig(config: Config): LdapProviderConfig[] { }; } + function formatFilter(filter?: string): string | undefined { + // Remove extra whitespaces between blocks to support multiline filters from the configuration + return filter?.replace(/\s*(\(|\))/g, '$1')?.trim(); + } + const providerConfigs = config.getOptionalConfigArray('providers') ?? []; return providerConfigs.map(c => { const newConfig = { diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index 1e2124f3df..3ab6d64dc8 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -44,7 +44,7 @@ "devDependencies": { "@backstage/cli": "^0.6.5", "@backstage/test-utils": "^0.1.9", - "@graphql-codegen/cli": "^1.17.7", + "@graphql-codegen/cli": "^1.21.3", "@graphql-codegen/typescript": "^1.17.7", "@graphql-codegen/typescript-resolvers": "^1.17.7", "@types/express": "^4.17.7", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 7b5cee247f..5fd93562d6 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-import +## 0.5.2 + +### Patch Changes + +- f9c75f7a9: When importing components you will now have the ability to use non Unicode characters in the entity owner field +- Updated dependencies [1279a3325] +- Updated dependencies [4a4681b1b] +- Updated dependencies [97b60de98] +- Updated dependencies [b051e770c] +- Updated dependencies [98dd5da71] + - @backstage/core@0.7.4 + - @backstage/catalog-model@0.7.6 + ## 0.5.1 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index d3e8d45b4e..a168f089c8 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-import", - "version": "0.5.1", + "version": "0.5.2", "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.7.5", + "@backstage/catalog-model": "^0.7.6", "@backstage/catalog-client": "^0.3.9", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/integration": "^0.5.0", "@backstage/integration-react": "^0.1.1", "@backstage/plugin-catalog-react": "^0.1.4", @@ -53,9 +53,9 @@ "yaml": "^1.10.0" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^3.3.0", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index 31f511fdbf..7a79c39af1 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog +## 0.5.3 + +### Patch Changes + +- 98dd5da71: Add support for multiple links to post-scaffold task summary page +- Updated dependencies [1279a3325] +- Updated dependencies [4a4681b1b] +- Updated dependencies [97b60de98] +- Updated dependencies [b051e770c] +- Updated dependencies [98dd5da71] + - @backstage/core@0.7.4 + - @backstage/catalog-model@0.7.6 + ## 0.5.2 ### Patch Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index f86c43430a..4e3d364b78 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog", - "version": "0.5.2", + "version": "0.5.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,8 +31,8 @@ }, "dependencies": { "@backstage/catalog-client": "^0.3.9", - "@backstage/catalog-model": "^0.7.5", - "@backstage/core": "^0.7.3", + "@backstage/catalog-model": "^0.7.6", + "@backstage/core": "^0.7.4", "@backstage/errors": "^0.1.1", "@backstage/integration": "^0.5.1", "@backstage/integration-react": "^0.1.1", @@ -53,9 +53,9 @@ "swr": "^0.3.0" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@microsoft/microsoft-graph-types": "^1.25.0", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", diff --git a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx index df20e910aa..78288c46e9 100644 --- a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx +++ b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx @@ -16,6 +16,7 @@ import { Entity, + RELATION_DEPENDS_ON, RELATION_PROVIDES_API, RELATION_PART_OF, serializeEntityRef, @@ -124,7 +125,6 @@ export function SystemDiagramCard() { catalogItem, RELATION_PROVIDES_API, ); - catalogItemRelations_providesApi.forEach(foundRelation => systemEdges.push({ from: simplifiedEntityName(catalogItem), @@ -132,6 +132,18 @@ export function SystemDiagramCard() { label: 'provides API', }), ); + + const catalogItemRelations_dependsOn = getEntityRelations( + catalogItem, + RELATION_DEPENDS_ON, + ); + catalogItemRelations_dependsOn.forEach(foundRelation => + systemEdges.push({ + from: simplifiedEntityName(catalogItem), + to: simplifiedEntityName(foundRelation), + label: 'depends on', + }), + ); } } diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 3a3b847e97..1d9fa11b3c 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -32,7 +32,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/plugin-catalog-react": "^0.1.2", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", @@ -50,9 +50,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 8718a50a5f..a713d57883 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -32,7 +32,7 @@ "dependencies": { "@backstage/catalog-model": "^0.7.3", "@backstage/plugin-catalog-react": "^0.1.2", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -47,9 +47,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 7aece742fc..a983e4ed3e 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -31,7 +31,7 @@ }, "dependencies": { "@backstage/config": "^0.1.3", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -55,9 +55,9 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/explore/package.json b/plugins/explore/package.json index c640be6f23..ea6c41fcd4 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -31,7 +31,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.5", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/plugin-catalog-react": "^0.1.4", "@backstage/plugin-explore-react": "^0.0.4", "@backstage/theme": "^0.2.5", @@ -45,9 +45,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index d503f76928..209f7512aa 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -32,7 +32,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/plugin-catalog-react": "^0.1.1", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", @@ -44,9 +44,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 0f05e9d05b..a381d785a0 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.7.3", + "@backstage/core": "^0.7.4", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -41,9 +41,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 8cc9471613..a744fcdc6e 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -34,7 +34,7 @@ "dependencies": { "@backstage/catalog-model": "^0.7.5", "@backstage/plugin-catalog-react": "^0.1.4", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/integration": "^0.5.1", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", @@ -50,9 +50,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md new file mode 100644 index 0000000000..9369ef87f9 --- /dev/null +++ b/plugins/github-deployments/CHANGELOG.md @@ -0,0 +1,14 @@ +# @backstage/plugin-github-deployments + +## 0.1.2 + +### Patch Changes + +- 64d2ce700: Add a button to reload the GitHub Deployments card +- Updated dependencies [1279a3325] +- Updated dependencies [4a4681b1b] +- Updated dependencies [97b60de98] +- Updated dependencies [b051e770c] +- Updated dependencies [98dd5da71] + - @backstage/core@0.7.4 + - @backstage/catalog-model@0.7.6 diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index b8761c1385..b625316ed8 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-deployments", - "version": "0.1.1", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,8 +20,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.7.4", - "@backstage/core": "^0.7.3", + "@backstage/catalog-model": "^0.7.6", + "@backstage/core": "^0.7.4", "@backstage/plugin-catalog-react": "^0.1.3", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", @@ -34,9 +34,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index a82a2c26ed..2d12272e22 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.7.3", + "@backstage/core": "^0.7.4", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -42,9 +42,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index b9e61b02da..e9d1353112 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -43,9 +43,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index f580dc2d15..3e00ae9373 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -32,7 +32,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/plugin-catalog-react": "^0.1.3", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", @@ -47,9 +47,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index fb4ec0db41..52cd84b790 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -21,7 +21,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.4", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/plugin-catalog-react": "^0.1.1", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", @@ -33,9 +33,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^3.4.2", diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 71f11e7a68..9d01997c13 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -33,7 +33,7 @@ "dependencies": { "@backstage/catalog-model": "^0.7.4", "@backstage/config": "^0.1.4", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/plugin-catalog-react": "^0.1.3", "@backstage/plugin-kubernetes-backend": "^0.3.2", "@backstage/theme": "^0.2.5", @@ -50,9 +50,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^3.4.2", diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index 7f5b678afd..2fd25a9add 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -33,7 +33,7 @@ "dependencies": { "@backstage/catalog-model": "^0.7.3", "@backstage/config": "^0.1.4", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/plugin-catalog-react": "^0.1.2", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", @@ -46,9 +46,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index b62fd82d20..83a46bb8b1 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -41,9 +41,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index 9239eabd9b..c62c618ff4 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-org +## 0.3.12 + +### Patch Changes + +- 97d53f686: Optimize data fetched for the `OwnershipCard`. +- Updated dependencies [1279a3325] +- Updated dependencies [4a4681b1b] +- Updated dependencies [97b60de98] +- Updated dependencies [b051e770c] +- Updated dependencies [98dd5da71] + - @backstage/core@0.7.4 + - @backstage/core-api@0.2.16 + - @backstage/catalog-model@0.7.6 + ## 0.3.11 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index d8de1469ee..9fa79e27c6 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-org", - "version": "0.3.11", + "version": "0.3.12", "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.7.5", - "@backstage/core": "^0.7.3", - "@backstage/core-api": "^0.2.14", + "@backstage/catalog-model": "^0.7.6", + "@backstage/core": "^0.7.4", + "@backstage/core-api": "^0.2.16", "@backstage/plugin-catalog-react": "^0.1.4", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", @@ -35,9 +35,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index df1078eedd..342d375863 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -31,7 +31,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/plugin-catalog-react": "^0.1.1", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", @@ -46,9 +46,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/register-component/package.json b/plugins/register-component/package.json index 73d343a205..d63800db5c 100644 --- a/plugins/register-component/package.json +++ b/plugins/register-component/package.json @@ -31,7 +31,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.5", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/plugin-catalog-react": "^0.1.4", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", @@ -45,9 +45,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 1421ee5051..084dcbad32 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -32,7 +32,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/plugin-catalog-react": "^0.1.1", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", @@ -47,9 +47,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^3.3.0", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index a54ec4430d..e2c1717a71 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-scaffolder-backend +## 0.9.5 + +### Patch Changes + +- 802b41b65: Allow custom directory to be specified for GitHub publish action +- Updated dependencies [97b60de98] +- Updated dependencies [98dd5da71] +- Updated dependencies [b779b5fee] + - @backstage/catalog-model@0.7.6 + - @backstage/backend-common@0.6.2 + ## 0.9.4 ### Patch Changes diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 69aced77b5..c86004d7a4 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend", - "version": "0.9.4", + "version": "0.9.5", "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.6.1", + "@backstage/backend-common": "^0.6.2", "@backstage/catalog-client": "^0.3.9", - "@backstage/catalog-model": "^0.7.5", + "@backstage/catalog-model": "^0.7.6", "@backstage/config": "^0.1.4", "@backstage/errors": "^0.1.1", "@backstage/integration": "^0.5.1", @@ -55,17 +55,20 @@ "handlebars": "^4.7.6", "helmet": "^4.0.0", "isomorphic-git": "^1.8.0", + "jest-when": "^3.1.0", "jsonschema": "^1.2.6", "knex": "^0.95.1", + "lodash": "^4.17.21", "luxon": "^1.26.0", "morgan": "^1.10.0", + "octokit-plugin-create-pull-request": "^3.9.3", "uuid": "^8.2.0", "winston": "^3.2.1", "yaml": "^1.10.0" }, "devDependencies": { - "@backstage/cli": "^0.6.6", - "@backstage/test-utils": "^0.1.9", + "@backstage/cli": "^0.6.7", + "@backstage/test-utils": "^0.1.10", "@types/fs-extra": "^9.0.1", "@types/mock-fs": "^4.13.0", "@types/supertest": "^2.0.8", diff --git a/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml b/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml index 91f887ed0a..82fde335c5 100644 --- a/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml +++ b/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml @@ -19,6 +19,7 @@ spec: - component_id - use_typescript - description + - collaborators properties: component_id: title: Name @@ -39,4 +40,28 @@ spec: type: boolean description: Use Github Actions default: true - + collaborators: + title: Collaborators + description: Provide users with permissions + type: array + ui:options: + orderable: false + items: + type: object + required: + - username + - access + properties: + access: + type: string + description: The type of access for the user + default: pull + enum: + - push + - pull + - admin + - maintain + - triage + username: + type: string + description: The username or group diff --git a/plugins/scaffolder-backend/sample-templates/local-templates.yaml b/plugins/scaffolder-backend/sample-templates/local-templates.yaml index b0e16f9dea..76c76bc97a 100644 --- a/plugins/scaffolder-backend/sample-templates/local-templates.yaml +++ b/plugins/scaffolder-backend/sample-templates/local-templates.yaml @@ -10,3 +10,4 @@ spec: - ./react-ssr-template/template.yaml - ./springboot-grpc-template/template.yaml - ./v1beta2-demo/template.yaml + - ./pull-request/template.yaml diff --git a/plugins/scaffolder-backend/sample-templates/pull-request/template.yaml b/plugins/scaffolder-backend/sample-templates/pull-request/template.yaml new file mode 100644 index 0000000000..b6de1c29ca --- /dev/null +++ b/plugins/scaffolder-backend/sample-templates/pull-request/template.yaml @@ -0,0 +1,77 @@ +apiVersion: backstage.io/v1beta2 +kind: Template +metadata: + name: pull-request + title: Pull Request Action template + description: scaffolder v1beta2 template demo publishing to PR on existing git repository +spec: + owner: backstage/techdocs-core + type: service + + parameters: + - title: Fill in some steps + required: + - name + properties: + name: + title: Name + type: string + description: Unique name of the component + ui:autofocus: true + ui:options: + rows: 5 + description: + title: Description + type: string + description: Description of the component + targetPath: + title: Target Path in repo + type: string + description: Name of the directory to create in the repository + - title: Choose a location + required: + - repoUrl + properties: + repoUrl: + title: Repository Location + type: string + ui:field: RepoUrlPicker + ui:options: + allowedHosts: + - github.com + + steps: + - id: fetch-base + name: Fetch Base + action: fetch:cookiecutter + input: + url: ./template + values: + name: '{{parameters.name}}' + + - id: fetch-docs + name: Fetch Docs + action: fetch:plain + input: + targetPath: ./community + url: https://github.com/backstage/community/tree/main/backstage-community-sessions + + - id: publish + name: Publish + action: publish:github:pull-request + input: + repoUrl: '{{ parameters.repoUrl }}' + title: 'Create new project: {{parameters.name}}' + branchName: 'create-{{parameters.name}}' + description: | + # New project: {{parameters.name}} + + {{#if parameters.description}} + {{parameters.description}} + {{/if}} + targetPath: '{{#if parameters.targetPath}}{{parameters.targetPath}}{{else}}{{parameters.name}}{{/if}}' + + output: + links: + - url: '{{steps.publish.output.remoteUrl}}' + text: 'Go to PR' diff --git a/plugins/scaffolder-backend/sample-templates/pull-request/template/catalog-info.yaml b/plugins/scaffolder-backend/sample-templates/pull-request/template/catalog-info.yaml new file mode 100644 index 0000000000..dd1e0ebd09 --- /dev/null +++ b/plugins/scaffolder-backend/sample-templates/pull-request/template/catalog-info.yaml @@ -0,0 +1,8 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: {{cookiecutter.name | jsonify}} +spec: + type: website + lifecycle: experimental + owner: guest diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts index 0829a101f2..2d4b8fb4c5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts @@ -23,6 +23,7 @@ import { createPublishAzureAction, createPublishBitbucketAction, createPublishGithubAction, + createPublishGithubPullRequestAction, createPublishGitlabAction, } from './publish'; import Docker from 'dockerode'; @@ -57,6 +58,9 @@ export const createBuiltinActions = (options: { createPublishGithubAction({ integrations, }), + createPublishGithubPullRequestAction({ + integrations, + }), createPublishGitlabAction({ integrations, }), diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts index 9880dda621..dc2f602778 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts @@ -22,6 +22,7 @@ import { ConfigReader } from '@backstage/config'; import { getVoidLogger } from '@backstage/backend-common'; import { PassThrough } from 'stream'; import { initRepoAndPush } from '../../../stages/publish/helpers'; +import { when } from 'jest-when'; describe('publish:github', () => { const integrations = ScmIntegrations.fromConfig( @@ -232,6 +233,114 @@ describe('publish:github', () => { }); }); + it('should add multiple collaborators when provided', async () => { + mockGithubClient.users.getByUsername.mockResolvedValue({ + data: { type: 'User' }, + }); + + mockGithubClient.repos.createForAuthenticatedUser.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + collaborators: [ + { + access: 'pull', + username: 'robot-1', + }, + { + access: 'push', + username: 'robot-2', + }, + ], + }, + }); + + const commonProperties = { + org: 'owner', + owner: 'owner', + repo: 'repo', + }; + + expect( + mockGithubClient.teams.addOrUpdateRepoPermissionsInOrg.mock.calls[1], + ).toEqual([ + { + ...commonProperties, + team_slug: 'robot-1', + permission: 'pull', + }, + ]); + + expect( + mockGithubClient.teams.addOrUpdateRepoPermissionsInOrg.mock.calls[2], + ).toEqual([ + { + ...commonProperties, + team_slug: 'robot-2', + permission: 'push', + }, + ]); + }); + + it('should ignore failures when adding multiple collaborators', async () => { + mockGithubClient.users.getByUsername.mockResolvedValue({ + data: { type: 'User' }, + }); + + mockGithubClient.repos.createForAuthenticatedUser.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + when(mockGithubClient.teams.addOrUpdateRepoPermissionsInOrg) + .calledWith({ + org: 'owner', + owner: 'owner', + repo: 'repo', + team_slug: 'robot-1', + permission: 'pull', + }) + .mockRejectedValueOnce(new Error('Something bad happened') as never); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + collaborators: [ + { + access: 'pull', + username: 'robot-1', + }, + { + access: 'push', + username: 'robot-2', + }, + ], + }, + }); + + expect( + mockGithubClient.teams.addOrUpdateRepoPermissionsInOrg.mock.calls[2], + ).toEqual([ + { + org: 'owner', + owner: 'owner', + repo: 'repo', + team_slug: 'robot-2', + permission: 'push', + }, + ]); + }); + it('should call output with the remoteUrl and the repoContentsUrl', async () => { mockGithubClient.users.getByUsername.mockResolvedValue({ data: { type: 'User' }, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts index 70394b0039..e58f2c68aa 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts @@ -23,6 +23,9 @@ import { initRepoAndPush } from '../../../stages/publish/helpers'; import { getRepoSourceDirectory, parseRepoUrl } from './util'; import { createTemplateAction } from '../../createTemplateAction'; +type Permission = 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; +type Collaborator = { access: Permission; username: string }; + export function createPublishGithubAction(options: { integrations: ScmIntegrationRegistry; }) { @@ -41,6 +44,7 @@ export function createPublishGithubAction(options: { access?: string; sourcePath?: string; repoVisibility: 'private' | 'internal' | 'public'; + collaborators: Collaborator[]; }>({ id: 'publish:github', description: @@ -72,6 +76,26 @@ export function createPublishGithubAction(options: { 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the respository.', type: 'string', }, + collaborators: { + title: 'Collaborators', + description: 'Provide users with permissions', + type: 'array', + items: { + type: 'object', + required: ['username', 'access'], + properties: { + access: { + type: 'string', + description: 'The type of access for the user', + enum: ['push', 'pull', 'admin', 'maintain', 'triage'], + }, + username: { + type: 'string', + description: 'The username or group', + }, + }, + }, + }, }, }, output: { @@ -94,6 +118,7 @@ export function createPublishGithubAction(options: { description, access, repoVisibility = 'private', + collaborators, } = ctx.input; const { owner, repo, host } = parseRepoUrl(repoUrl); @@ -165,6 +190,27 @@ export function createPublishGithubAction(options: { }); } + if (collaborators) { + for (const { + access: permission, + username: team_slug, + } of collaborators) { + try { + await client.teams.addOrUpdateRepoPermissionsInOrg({ + org: owner, + team_slug, + owner, + repo, + permission, + }); + } catch (e) { + ctx.logger.warn( + `Skipping ${permission} access for ${team_slug}, ${e.message}`, + ); + } + } + } + const remoteUrl = data.clone_url; const repoContentsUrl = `${data.html_url}/blob/master`; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts new file mode 100644 index 0000000000..fb9d3aeaa6 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts @@ -0,0 +1,236 @@ +/* + * Copyright 2021 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 mockFs from 'mock-fs'; +import { Writable } from 'stream'; +import { + PullRequestCreator, + GithubPullRequestActionInput, + createPublishGithubPullRequestAction, + ClientFactoryInput, +} from './githubPullRequest'; +import { ActionContext, TemplateAction } from '../../types'; +import { getRootLogger } from '@backstage/backend-common'; + +import { ScmIntegrations } from '@backstage/integration'; +import { ConfigReader } from '@backstage/config'; + +const id = 'createPublishGithubPullRequestAction'; + +describe('createPublishGithubPullRequestAction', () => { + let instance: TemplateAction; + let fakeClient: PullRequestCreator; + + let clientFactory: (input: ClientFactoryInput) => Promise; + + beforeEach(() => { + const integrations = ScmIntegrations.fromConfig(new ConfigReader({})); + fakeClient = { + createPullRequest: jest.fn(async (_: any) => { + return { + url: 'https://api.github.com/myorg/myrepo/pull/123', + headers: {}, + status: 201, + data: { + html_url: 'https://github.com/myorg/myrepo/pull/123', + }, + }; + }), + }; + clientFactory = jest.fn(async () => fakeClient); + + instance = createPublishGithubPullRequestAction({ + integrations, + clientFactory, + }); + }); + + describe('with no sourcePath', () => { + let input: GithubPullRequestActionInput; + let ctx: ActionContext; + + beforeEach(() => { + input = { + owner: 'myorg', + repo: 'myrepo', + title: 'Create my new app', + branchName: 'new-app', + description: 'This PR is really good', + }; + + mockFs({ + [id]: { 'file.txt': 'Hello there!' }, + }); + + ctx = { + createTemporaryDirectory: jest.fn(), + output: jest.fn(), + logger: getRootLogger(), + logStream: new Writable(), + input, + workspacePath: id, + }; + }); + it('creates a pull request', async () => { + await instance.handler(ctx); + + expect(fakeClient.createPullRequest).toHaveBeenCalledWith({ + owner: 'myorg', + repo: 'myrepo', + title: 'Create my new app', + head: 'new-app', + body: 'This PR is really good', + changes: [ + { + commit: 'Create my new app', + files: { + 'file.txt': 'Hello there!', + }, + }, + ], + }); + }); + + it('creates outputs for the url', async () => { + await instance.handler(ctx); + + expect(ctx.output).toHaveBeenCalledWith( + 'remoteUrl', + 'https://github.com/myorg/myrepo/pull/123', + ); + }); + afterEach(() => { + mockFs.restore(); + jest.resetAllMocks(); + }); + }); + + describe('with sourcePath', () => { + let input: GithubPullRequestActionInput; + let ctx: ActionContext; + + beforeEach(() => { + input = { + owner: 'myorg', + repo: 'myrepo', + title: 'Create my new app', + branchName: 'new-app', + description: 'This PR is really good', + sourcePath: 'source', + }; + + mockFs({ + [id]: { + source: { 'foo.txt': 'Hello there!' }, + irrelevant: { 'bar.txt': 'Nothing to see here' }, + }, + }); + + ctx = { + createTemporaryDirectory: jest.fn(), + output: jest.fn(), + logger: getRootLogger(), + logStream: new Writable(), + input, + workspacePath: id, + }; + }); + + afterEach(() => { + mockFs.restore(); + jest.resetAllMocks(); + }); + + it('creates a pull request with only relevant files', async () => { + await instance.handler(ctx); + + expect(fakeClient.createPullRequest).toHaveBeenCalledWith({ + owner: 'myorg', + repo: 'myrepo', + title: 'Create my new app', + head: 'new-app', + body: 'This PR is really good', + changes: [ + { + commit: 'Create my new app', + files: { + 'foo.txt': 'Hello there!', + }, + }, + ], + }); + }); + }); + + describe('with repoUrl', () => { + let input: GithubPullRequestActionInput; + let ctx: ActionContext; + + beforeEach(() => { + input = { + repoUrl: 'github.com?owner=myorg&repo=myrepo', + title: 'Create my new app', + branchName: 'new-app', + description: 'This PR is really good', + }; + + mockFs({ + [id]: { 'file.txt': 'Hello there!' }, + }); + + ctx = { + createTemporaryDirectory: jest.fn(), + output: jest.fn(), + logger: getRootLogger(), + logStream: new Writable(), + input, + workspacePath: id, + }; + }); + it('creates a pull request', async () => { + await instance.handler(ctx); + + expect(fakeClient.createPullRequest).toHaveBeenCalledWith({ + owner: 'myorg', + repo: 'myrepo', + title: 'Create my new app', + head: 'new-app', + body: 'This PR is really good', + changes: [ + { + commit: 'Create my new app', + files: { + 'file.txt': 'Hello there!', + }, + }, + ], + }); + }); + + it('creates outputs for the url', async () => { + await instance.handler(ctx); + + expect(ctx.output).toHaveBeenCalledWith( + 'remoteUrl', + 'https://github.com/myorg/myrepo/pull/123', + ); + }); + afterEach(() => { + mockFs.restore(); + jest.resetAllMocks(); + }); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts new file mode 100644 index 0000000000..3a00610a92 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts @@ -0,0 +1,243 @@ +/* + * Copyright 2021 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 { readFile } from 'fs-extra'; +import path from 'path'; +import { parseRepoUrl } from './util'; + +import { + GithubCredentialsProvider, + ScmIntegrationRegistry, +} from '@backstage/integration'; +import { zipObject } from 'lodash'; +import { createTemplateAction } from '../../createTemplateAction'; +import { Octokit } from '@octokit/rest'; +import { InputError, CustomErrorBase } from '@backstage/errors'; +import { createPullRequest } from 'octokit-plugin-create-pull-request'; +import globby from 'globby'; + +class GithubResponseError extends CustomErrorBase {} + +type CreatePullRequestResponse = { + data: { html_url: string }; +}; + +export interface PullRequestCreator { + createPullRequest( + options: createPullRequest.Options, + ): Promise; +} + +export type PullRequestCreatorConstructor = ( + octokit: Octokit, +) => PullRequestCreator; + +export type GithubPullRequestActionInput = { + title: string; + branchName: string; + description: string; + owner?: string; + repo?: string; + repoUrl?: string; + host?: string; + targetPath?: string; + sourcePath?: string; +}; + +export type ClientFactoryInput = { + integrations: ScmIntegrationRegistry; + host: string; + owner: string; + repo: string; +}; + +export const defaultClientFactory = async ({ + integrations, + owner, + repo, + host = 'github.com', +}: ClientFactoryInput): Promise => { + const integrationConfig = integrations.github.byHost(host)?.config; + + if (!integrationConfig) { + throw new InputError(`No integration for host ${host}`); + } + + const credentialsProvider = GithubCredentialsProvider.create( + integrationConfig, + ); + + if (!credentialsProvider) { + throw new InputError( + `No matching credentials for host ${host}, please check your integrations config`, + ); + } + + const { token } = await credentialsProvider.getCredentials({ + url: `${host}/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`, + }); + + if (!token) { + throw new InputError( + `No token available for host: ${host}, with owner ${owner}, and repo ${repo}`, + ); + } + + const OctokitPR = Octokit.plugin(createPullRequest); + + return new OctokitPR({ + auth: token, + baseUrl: integrationConfig.apiBaseUrl, + }); +}; + +interface CreateGithubPullRequestActionOptions { + integrations: ScmIntegrationRegistry; + clientFactory?: (input: ClientFactoryInput) => Promise; +} + +export const createPublishGithubPullRequestAction = ({ + integrations, + clientFactory = defaultClientFactory, +}: CreateGithubPullRequestActionOptions) => { + return createTemplateAction({ + id: 'publish:github:pull-request', + schema: { + input: { + required: ['owner', 'repo', 'title', 'description', 'branchName'], + type: 'object', + properties: { + owner: { + type: 'string', + title: 'Repository owner', + description: 'The owner of the target repository', + }, + repo: { + type: 'string', + title: 'Repository', + description: 'The github repository to create the file in', + }, + branchName: { + type: 'string', + title: 'Branch Name', + description: 'The name for the branch', + }, + title: { + type: 'string', + title: 'Pull Request Name', + description: 'The name for the pull request', + }, + description: { + type: 'string', + title: 'Pull Request Description', + description: 'The description of the pull request', + }, + sourcePath: { + type: 'string', + title: 'Working Subdirectory', + description: + 'Subdirectory of working directory to copy changes from', + }, + targetPath: { + type: 'string', + title: 'Repository Subdirectory', + description: 'Subdirectory of repository to apply changes to', + }, + }, + }, + output: { + required: ['remoteUrl'], + type: 'object', + properties: { + remoteUrl: { + type: 'string', + title: 'Pull Request URL', + description: 'Link to the pull request in Github', + }, + }, + }, + }, + async handler(ctx) { + let { owner, repo } = ctx.input; + let host = 'github.com'; + const { + repoUrl, + branchName, + title, + description, + targetPath, + sourcePath, + } = ctx.input; + + if (repoUrl) { + const parsed = parseRepoUrl(repoUrl); + host = parsed.host; + owner = parsed.owner; + repo = parsed.repo; + } + + if (!host || !owner || !repo) { + throw new InputError( + 'must provide either valid repo URL or owner and repo as parameters', + ); + } + + const client = await clientFactory({ integrations, host, owner, repo }); + const fileRoot = sourcePath + ? path.join(ctx.workspacePath, sourcePath) + : ctx.workspacePath; + const localFilePaths = await globby(`${fileRoot}/**/*.*`); + + const fileContents = await Promise.all( + localFilePaths.map(p => readFile(p)), + ); + + const repoFilePaths = localFilePaths.map(p => { + const relativePath = path.relative(fileRoot, p); + return targetPath ? `${targetPath}/${relativePath}` : relativePath; + }); + + const changes = [ + { + files: zipObject( + repoFilePaths, + fileContents.map(buf => buf.toString()), + ), + commit: title, + }, + ]; + + try { + const response = await client.createPullRequest({ + owner, + repo, + title, + changes, + body: description, + head: branchName, + }); + + if (!response) { + throw new GithubResponseError('null response from Github'); + } + + ctx.output('remoteUrl', response.data.html_url); + } catch (e) { + throw new GithubResponseError('Pull request creation failed', e); + } + }, + }); +}; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/index.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/index.ts index 419922704d..537a2b882d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/index.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/index.ts @@ -15,6 +15,7 @@ */ export { createPublishGithubAction } from './github'; +export { createPublishGithubPullRequestAction } from './githubPullRequest'; export { createPublishAzureAction } from './azure'; export { createPublishGitlabAction } from './gitlab'; export { createPublishBitbucketAction } from './bitbucket'; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.test.ts index f6e5600a83..24a3ef4112 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.test.ts @@ -31,7 +31,7 @@ describe('File preparer', () => { const targetPath = path.resolve(workspacePath, 'template'); await preparer.prepare({ - url: `file:///${root}path/to/template`, + url: `file://${root}path/to/template`, logger, workspacePath, }); @@ -46,12 +46,34 @@ describe('File preparer', () => { await expect( preparer.prepare({ - url: 'file://not/full/path', + url: 'http://not/file/path', logger, workspacePath, }), ).rejects.toThrow( - "Wrong location protocol, should be 'file', file://not/full/path", + "Wrong location protocol, should be 'file', http://not/file/path", ); + + if (os.platform() === 'win32') { + // eslint-disable-next-line jest/no-conditional-expect + await expect( + preparer.prepare({ + url: 'file:///unix/file/path', + logger, + workspacePath, + }), + ).rejects.toThrow('File URL path must be absolute'); + } else { + // eslint-disable-next-line jest/no-conditional-expect + await expect( + preparer.prepare({ + url: 'file://not/full/path', + logger, + workspacePath, + }), + ).rejects.toThrow( + `File URL host must be "localhost" or empty on ${os.platform()}`, + ); + } }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts index 9eb380be13..b02c496ff5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts @@ -21,15 +21,15 @@ import { PreparerBase, PreparerOptions } from './types'; export class FilePreparer implements PreparerBase { async prepare({ url, workspacePath }: PreparerOptions) { - if (!url.startsWith('file:///')) { + if (!url.startsWith('file://')) { throw new InputError(`Wrong location protocol, should be 'file', ${url}`); } + const templatePath = fileURLToPath(url); + const targetDir = path.join(workspacePath, 'template'); await fs.ensureDir(targetDir); - const templatePath = fileURLToPath(url); - await fs.copy(templatePath, targetDir, { recursive: true, }); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.test.ts index 4cf5e83ba3..33fa51af1b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.test.ts @@ -97,6 +97,19 @@ describe('Bitbucket Publisher', () => { }); describe('publish: createRemoteInBitbucketServer', () => { + it('should throw an error if no username present', async () => { + await expect( + BitbucketPublisher.fromConfig( + { + host: 'bitbucket.mycompany.com', + token: 'fake-token', + }, + { repoVisibility: 'private' }, + ), + ).rejects.toThrow( + 'Bitbucket server requires the username to be set in your config', + ); + }); it('should create repo in bitbucket server', async () => { server.use( rest.post( @@ -128,6 +141,7 @@ describe('Bitbucket Publisher', () => { const publisher = await BitbucketPublisher.fromConfig( { host: 'bitbucket.mycompany.com', + username: 'foo', token: 'fake-token', }, { repoVisibility: 'private' }, @@ -151,7 +165,7 @@ describe('Bitbucket Publisher', () => { expect(initRepoAndPush).toHaveBeenCalledWith({ dir: resultPath, remoteUrl: 'https://bitbucket.mycompany.com/scm/project/repo', - auth: { username: 'x-token-auth', password: 'fake-token' }, + auth: { username: 'foo', password: 'fake-token' }, logger: logger, }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.ts index 102a3a7d02..aef0625c79 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.ts @@ -32,6 +32,11 @@ export class BitbucketPublisher implements PublisherBase { config: BitbucketIntegrationConfig, { repoVisibility }: { repoVisibility: RepoVisibilityOptions }, ) { + if (config.host !== 'bitbucket.org' && !config.username) + throw new Error( + 'Bitbucket server requires the username to be set in your config', + ); + return new BitbucketPublisher({ host: config.host, token: config.token, diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.test.ts index 87bcd1d003..95eb4891dc 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.test.ts @@ -76,7 +76,9 @@ describe('Publishers', () => { const publishers = await Publishers.fromConfig( new ConfigReader({ integrations: { - bitbucket: [{ host: 'bitbucket.com', token: 'blob' }], + bitbucket: [ + { host: 'bitbucket.com', username: 'foo', token: 'blob' }, + ], }, }), { diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index 4823c19816..6a43bccab3 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-scaffolder +## 0.8.2 + +### Patch Changes + +- 3f96a9d5a: Support auth by sending cookies in event stream request +- 98dd5da71: Add support for multiple links to post-scaffold task summary page +- Updated dependencies [1279a3325] +- Updated dependencies [4a4681b1b] +- Updated dependencies [97b60de98] +- Updated dependencies [b051e770c] +- Updated dependencies [98dd5da71] + - @backstage/core@0.7.4 + - @backstage/catalog-model@0.7.6 + ## 0.8.1 ### Patch Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 410e12a97d..0de3b5ee53 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder", - "version": "0.8.1", + "version": "0.8.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,9 +31,9 @@ }, "dependencies": { "@backstage/catalog-client": "^0.3.9", - "@backstage/catalog-model": "^0.7.5", + "@backstage/catalog-model": "^0.7.6", "@backstage/config": "^0.1.4", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/integration": "^0.5.1", "@backstage/integration-react": "^0.1.1", "@backstage/plugin-catalog-react": "^0.1.4", @@ -60,9 +60,9 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/scaffolder/src/api.ts b/plugins/scaffolder/src/api.ts index e266d06a91..6caa2a4446 100644 --- a/plugins/scaffolder/src/api.ts +++ b/plugins/scaffolder/src/api.ts @@ -196,7 +196,7 @@ export class ScaffolderClient implements ScaffolderApi { const url = `${baseUrl}/v2/tasks/${encodeURIComponent( taskId, )}/eventstream`; - const eventSource = new EventSource(url); + const eventSource = new EventSource(url, { withCredentials: true }); eventSource.addEventListener('log', (event: any) => { if (event.data) { try { diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx index 0353dff798..68bf588d01 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx +++ b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx @@ -26,6 +26,7 @@ import { Progress, SupportButton, useApi, + useRouteRef, WarningPanel, } from '@backstage/core'; import { useStarredEntities } from '@backstage/plugin-catalog-react'; @@ -39,6 +40,7 @@ import { ScaffolderFilter } from '../ScaffolderFilter'; import { ButtonGroup } from '../ScaffolderFilter/ScaffolderFilter'; import SearchToolbar from '../SearchToolbar/SearchToolbar'; import { TemplateCard, TemplateCardProps } from '../TemplateCard'; +import { registerComponentRouteRef } from '../../routes'; const useStyles = makeStyles(theme => ({ contentWrapper: { @@ -108,6 +110,8 @@ export const ScaffolderPageContents = () => { `${metadata.title}`.toLocaleUpperCase('en-US').includes(query) || metadata.tags?.join('').toLocaleUpperCase('en-US').indexOf(query) !== -1; + const registerComponentLink = useRouteRef(registerComponentRouteRef); + useEffect(() => { if (search.length === 0) { return setMatchingEntities(filteredEntities); @@ -132,14 +136,16 @@ export const ScaffolderPageContents = () => { /> - + {registerComponentLink && ( + + )} Create new software components using standard templates. Different templates create different kinds of components (services, websites, diff --git a/plugins/scaffolder/src/plugin.ts b/plugins/scaffolder/src/plugin.ts index 1aa25d8e18..be47daec46 100644 --- a/plugins/scaffolder/src/plugin.ts +++ b/plugins/scaffolder/src/plugin.ts @@ -23,7 +23,7 @@ import { } from '@backstage/core'; import { scmIntegrationsApiRef } from '@backstage/integration-react'; import { scaffolderApiRef, ScaffolderClient } from './api'; -import { rootRouteRef } from './routes'; +import { rootRouteRef, registerComponentRouteRef } from './routes'; export const scaffolderPlugin = createPlugin({ id: 'scaffolder', @@ -42,6 +42,9 @@ export const scaffolderPlugin = createPlugin({ routes: { root: rootRouteRef, }, + externalRoutes: { + registerComponent: registerComponentRouteRef, + }, }); export const ScaffolderPage = scaffolderPlugin.provide( diff --git a/plugins/scaffolder/src/routes.ts b/plugins/scaffolder/src/routes.ts index 413e8f4194..3cca269b84 100644 --- a/plugins/scaffolder/src/routes.ts +++ b/plugins/scaffolder/src/routes.ts @@ -13,7 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createRouteRef } from '@backstage/core'; +import { createExternalRouteRef, createRouteRef } from '@backstage/core'; + +export const registerComponentRouteRef = createExternalRouteRef({ + id: 'register-component', + optional: true, +}); export const rootRouteRef = createRouteRef({ title: 'Create new entity', diff --git a/plugins/search/package.json b/plugins/search/package.json index d0eab8f808..942035159c 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -29,7 +29,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/catalog-model": "^0.7.3", "@backstage/plugin-catalog-react": "^0.1.2", "@backstage/search-common": "^0.1.1", @@ -44,9 +44,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index 4b086c8e5e..cfed11acb8 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -32,7 +32,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/plugin-catalog-react": "^0.1.1", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", @@ -46,9 +46,9 @@ "timeago.js": "^4.0.2" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index 412d2fd905..14f3dcfe10 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -34,7 +34,7 @@ "dependencies": { "@backstage/catalog-model": "^0.7.3", "@backstage/plugin-catalog-react": "^0.1.3", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -47,9 +47,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/sonarqube/src/components/index.ts b/plugins/sonarqube/src/components/index.ts index 8f0786bb8e..56b9d05885 100644 --- a/plugins/sonarqube/src/components/index.ts +++ b/plugins/sonarqube/src/components/index.ts @@ -15,3 +15,4 @@ */ export * from './SonarQubeCard'; +export { isSonarQubeAvailable } from './useProjectKey'; diff --git a/plugins/sonarqube/src/components/useProjectKey.ts b/plugins/sonarqube/src/components/useProjectKey.ts index dcff79d972..c0f488b00c 100644 --- a/plugins/sonarqube/src/components/useProjectKey.ts +++ b/plugins/sonarqube/src/components/useProjectKey.ts @@ -18,6 +18,9 @@ import { Entity } from '@backstage/catalog-model'; export const SONARQUBE_PROJECT_KEY_ANNOTATION = 'sonarqube.org/project-key'; +export const isSonarQubeAvailable = (entity: Entity) => + Boolean(entity.metadata.annotations?.[SONARQUBE_PROJECT_KEY_ANNOTATION]); + export const useProjectKey = (entity: Entity) => { return entity?.metadata.annotations?.[SONARQUBE_PROJECT_KEY_ANNOTATION] ?? ''; }; diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index 6ef9fe22af..4e06c68e3a 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -31,7 +31,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.4", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/plugin-catalog-react": "^0.1.1", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", @@ -45,9 +45,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 5d8da62ca9..e172fae350 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.7.3", + "@backstage/core": "^0.7.4", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -43,9 +43,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/techdocs-backend/src/service/helpers.test.ts b/plugins/techdocs-backend/src/service/helpers.test.ts deleted file mode 100644 index 507373107d..0000000000 --- a/plugins/techdocs-backend/src/service/helpers.test.ts +++ /dev/null @@ -1,26 +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 { getEntityNameFromUrlPath } from './helpers'; - -describe('getEntityNameFromUrlPath', () => { - it('should parse correctly', () => { - const path = 'default/Component/documented-component'; - const parsedEntity = getEntityNameFromUrlPath(path); - expect(parsedEntity).toHaveProperty('namespace', 'default'); - expect(parsedEntity).toHaveProperty('kind', 'Component'); - expect(parsedEntity).toHaveProperty('name', 'documented-component'); - }); -}); diff --git a/plugins/techdocs-backend/src/service/router.ts b/plugins/techdocs-backend/src/service/router.ts index 9456e8a277..121ddddef5 100644 --- a/plugins/techdocs-backend/src/service/router.ts +++ b/plugins/techdocs-backend/src/service/router.ts @@ -14,8 +14,9 @@ * limitations under the License. */ import { PluginEndpointDiscovery } from '@backstage/backend-common'; -import { Entity } from '@backstage/catalog-model'; +import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; +import { NotFoundError } from '@backstage/errors'; import { GeneratorBuilder, getLocationForEntity, @@ -30,8 +31,6 @@ import { Knex } from 'knex'; import { Logger } from 'winston'; import { DocsBuilder } from '../DocsBuilder'; import { shouldCheckForUpdate } from '../DocsBuilder/BuildMetadataStorage'; -import { getEntityNameFromUrlPath } from './helpers'; -import { NotFoundError } from '@backstage/errors'; type RouterOptions = { preparers: PreparerBuilder; @@ -55,10 +54,9 @@ export async function createRouter({ }: RouterOptions): Promise { const router = Router(); - router.get('/metadata/techdocs/*', async (req, res) => { - // path is `:namespace/:kind:/:name` - const { '0': path } = req.params; - const entityName = getEntityNameFromUrlPath(path); + router.get('/metadata/techdocs/:namespace/:kind/:name', async (req, res) => { + const { kind, namespace, name } = req.params; + const entityName = { kind, namespace, name }; try { const techdocsMetadata = await publisher.fetchTechDocsMetadata( @@ -67,14 +65,15 @@ export async function createRouter({ res.json(techdocsMetadata); } catch (err) { - logger.error( - `Unable to get metadata for ${entityName.namespace}/${entityName.name} with error ${err}`, + logger.info( + `Unable to get metadata for '${stringifyEntityRef( + entityName, + )}' with error ${err}`, + ); + throw new NotFoundError( + `Unable to get metadata for '${stringifyEntityRef(entityName)}'`, + err, ); - res - .status(500) - .send( - `Unable to get metadata for $${entityName.namespace}/${entityName.name}, reason: ${err}`, - ); } }); @@ -82,9 +81,11 @@ export async function createRouter({ const catalogUrl = await discovery.getBaseUrl('catalog'); const { kind, namespace, name } = req.params; + const entityName = { kind, namespace, name }; try { const token = getBearerToken(req.headers.authorization); + // TODO: Consider using the catalog client here const entity = (await ( await fetch( `${catalogUrl}/entities/by-name/${kind}/${namespace}/${name}`, @@ -98,10 +99,13 @@ export async function createRouter({ res.json({ ...entity, locationMetadata }); } catch (err) { logger.info( - `Unable to get metadata for ${kind}/${namespace}/${name} with error ${err}`, + `Unable to get metadata for '${stringifyEntityRef( + entityName, + )}' with error ${err}`, ); - throw new Error( - `Unable to get metadata for ${kind}/${namespace}/${name} with error ${err}`, + throw new NotFoundError( + `Unable to get metadata for '${stringifyEntityRef(entityName)}'`, + err, ); } }); diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index f8e7a184fd..4342b32a3a 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -33,7 +33,7 @@ "dependencies": { "@backstage/config": "^0.1.4", "@backstage/catalog-model": "^0.7.5", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/plugin-catalog-react": "^0.1.4", "@backstage/test-utils": "^0.1.9", "@backstage/theme": "^0.2.5", @@ -49,9 +49,9 @@ "sanitize-html": "^2.3.2" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/techdocs/src/reader/components/Reader.tsx b/plugins/techdocs/src/reader/components/Reader.tsx index 67b39d0ef7..874ca5e018 100644 --- a/plugins/techdocs/src/reader/components/Reader.tsx +++ b/plugins/techdocs/src/reader/components/Reader.tsx @@ -162,6 +162,16 @@ export const Reader = ({ entityId, onReady }: Props) => { .md-typeset { font-size: 1rem; } .md-nav { font-size: 1rem; } .md-grid { max-width: 90vw; margin: 0 } + .md-typeset table:not([class]) { + font-size: 1rem; + border: 1px solid ${theme.palette.text.primary}; + border-bottom: none; + border-collapse: collapse; + } + .md-typeset table:not([class]) td, .md-typeset table:not([class]) th { + border-bottom: 1px solid ${theme.palette.text.primary}; + } + .md-typeset table:not([class]) th { font-weight: bold; } @media screen and (max-width: 76.1875em) { .md-nav { background-color: ${theme.palette.background.default}; @@ -221,6 +231,7 @@ export const Reader = ({ entityId, onReady }: Props) => { :host { --md-tasklist-icon: url('data:image/svg+xml;charset=utf-8,'); --md-tasklist-icon--checked: url('data:image/svg+xml;charset=utf-8,'); + } `, }), ]); diff --git a/plugins/todo/package.json b/plugins/todo/package.json index 5a92e4a256..d253f18fa6 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -27,7 +27,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.7.3", - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/errors": "^0.1.1", "@backstage/plugin-catalog-react": "^0.1.1", "@backstage/theme": "^0.2.5", @@ -39,9 +39,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 674e8ee57c..fde05caee8 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.7.3", + "@backstage/core": "^0.7.4", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -41,9 +41,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/welcome/package.json b/plugins/welcome/package.json index 85bda39a65..d100bd85b8 100644 --- a/plugins/welcome/package.json +++ b/plugins/welcome/package.json @@ -30,7 +30,7 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core": "^0.7.3", + "@backstage/core": "^0.7.4", "@backstage/theme": "^0.2.5", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -41,9 +41,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.6.6", + "@backstage/cli": "^0.6.7", "@backstage/dev-utils": "^0.1.13", - "@backstage/test-utils": "^0.1.9", + "@backstage/test-utils": "^0.1.10", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^12.0.7", diff --git a/yarn.lock b/yarn.lock index d341a67170..4dee004e65 100644 --- a/yarn.lock +++ b/yarn.lock @@ -249,7 +249,7 @@ dependencies: "@babel/highlight" "^7.0.0" -"@babel/code-frame@7.10.4", "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.5.5", "@babel/code-frame@^7.8.3": +"@babel/code-frame@7.10.4": version "7.10.4" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== @@ -263,77 +263,45 @@ dependencies: "@babel/highlight" "^7.8.3" -"@babel/code-frame@^7.12.13": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.5.5": version "7.12.13" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g== dependencies: "@babel/highlight" "^7.12.13" -"@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7": +"@babel/compat-data@^7.12.7": version "7.12.7" resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41" integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw== +"@babel/compat-data@^7.13.12": + version "7.13.15" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.13.15.tgz#7e8eea42d0b64fda2b375b22d06c605222e848f4" + integrity sha512-ltnibHKR1VnrU4ymHyQ/CXtNXI6yZC0oJThyW78Hft8XndANwi+9H+UIklBDraIjFEJzw8wmcM427oDd9KS5wA== + "@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.4.4", "@babel/core@^7.7.5": - version "7.12.9" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz#fd450c4ec10cdbb980e2928b7aa7a28484593fc8" - integrity sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ== + version "7.13.15" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.13.15.tgz#a6d40917df027487b54312202a06812c4f7792d0" + integrity sha512-6GXmNYeNjS2Uz+uls5jalOemgIhnTMeaXo+yBUA72kC2uX/8VW6XyhVIo2L8/q0goKQA3EVKx0KOQpVKSeWadQ== dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.12.5" - "@babel/helper-module-transforms" "^7.12.1" - "@babel/helpers" "^7.12.5" - "@babel/parser" "^7.12.7" - "@babel/template" "^7.12.7" - "@babel/traverse" "^7.12.9" - "@babel/types" "^7.12.7" + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.13.9" + "@babel/helper-compilation-targets" "^7.13.13" + "@babel/helper-module-transforms" "^7.13.14" + "@babel/helpers" "^7.13.10" + "@babel/parser" "^7.13.15" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.13.15" + "@babel/types" "^7.13.14" convert-source-map "^1.7.0" debug "^4.1.0" - gensync "^1.0.0-beta.1" + gensync "^1.0.0-beta.2" json5 "^2.1.2" - lodash "^4.17.19" - resolve "^1.3.2" - semver "^5.4.1" + semver "^6.3.0" source-map "^0.5.0" -"@babel/generator@^7.10.5": - version "7.10.5" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.10.5.tgz#1b903554bc8c583ee8d25f1e8969732e6b829a69" - integrity sha512-3vXxr3FEW7E7lJZiWQ3bM4+v/Vyr9C+hpolQ8BGFr9Y8Ri2tFLWTixmwKBafDujO1WVah4fhZBeU1bieKdghig== - dependencies: - "@babel/types" "^7.10.5" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.11.0", "@babel/generator@^7.5.0": - version "7.11.0" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.11.0.tgz#4b90c78d8c12825024568cbe83ee6c9af193585c" - integrity sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ== - dependencies: - "@babel/types" "^7.11.0" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.11.5", "@babel/generator@^7.9.6": - version "7.11.6" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz#b868900f81b163b4d464ea24545c61cbac4dc620" - integrity sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA== - dependencies: - "@babel/types" "^7.11.5" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.12.5": - version "7.12.5" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.12.5.tgz#a2c50de5c8b6d708ab95be5e6053936c1884a4de" - integrity sha512-m16TQQJ8hPt7E+OS/XVQg/7U184MLXtvuGbCdA7na61vha+ImkyyNM/9DDA0unYCVZn3ZOhng+qz48/KBOT96A== - dependencies: - "@babel/types" "^7.12.5" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.13.0": +"@babel/generator@^7.11.5", "@babel/generator@^7.13.9", "@babel/generator@^7.5.0": version "7.13.9" resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz#3a7aa96f9efb8e2be42d38d80e2ceb4c64d8de39" integrity sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw== @@ -399,15 +367,15 @@ "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-compilation-targets@^7.12.5": - version "7.12.5" - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" - integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw== +"@babel/helper-compilation-targets@^7.12.5", "@babel/helper-compilation-targets@^7.13.13": + version "7.13.13" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.13.tgz#2b2972a0926474853f41e4adbc69338f520600e5" + integrity sha512-q1kcdHNZehBwD9jYPh3WyXcsFERi39X4I59I3NadciWtNDyZ6x+GboOxncFK0kXlKIv6BJm5acncehXWUjWQMQ== dependencies: - "@babel/compat-data" "^7.12.5" - "@babel/helper-validator-option" "^7.12.1" + "@babel/compat-data" "^7.13.12" + "@babel/helper-validator-option" "^7.12.17" browserslist "^4.14.5" - semver "^5.5.0" + semver "^6.3.0" "@babel/helper-create-class-features-plugin@^7.10.4": version "7.10.5" @@ -466,7 +434,7 @@ "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-function-name@^7.10.4", "@babel/helper-function-name@^7.9.5": +"@babel/helper-function-name@^7.10.4": version "7.10.4" resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== @@ -519,12 +487,12 @@ dependencies: "@babel/types" "^7.12.7" -"@babel/helper-member-expression-to-functions@^7.13.0": - version "7.13.0" - resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.0.tgz#6aa4bb678e0f8c22f58cdb79451d30494461b091" - integrity sha512-yvRf8Ivk62JwisqV1rFRMxiSMDGnN6KH1/mDMmIrij4jztpQNRoHqqMG3U6apYbGRPJpgPalhva9Yd06HlUxJQ== +"@babel/helper-member-expression-to-functions@^7.13.12": + version "7.13.12" + resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz#dfe368f26d426a07299d8d6513821768216e6d72" + integrity sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw== dependencies: - "@babel/types" "^7.13.0" + "@babel/types" "^7.13.12" "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.10.4": version "7.10.4" @@ -540,27 +508,26 @@ dependencies: "@babel/types" "^7.12.5" -"@babel/helper-module-imports@^7.12.13": - version "7.12.13" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.13.tgz#ec67e4404f41750463e455cc3203f6a32e93fcb0" - integrity sha512-NGmfvRp9Rqxy0uHSSVP+SRIW1q31a7Ji10cLBcqSDUngGentY4FRiHOFZFE1CLU5eiL0oE8reH7Tg1y99TDM/g== +"@babel/helper-module-imports@^7.13.12": + version "7.13.12" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz#c6a369a6f3621cb25da014078684da9196b61977" + integrity sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA== dependencies: - "@babel/types" "^7.12.13" + "@babel/types" "^7.13.12" -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.13.0": - version "7.13.0" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.13.0.tgz#42eb4bd8eea68bab46751212c357bfed8b40f6f1" - integrity sha512-Ls8/VBwH577+pw7Ku1QkUWIyRRNHpYlts7+qSqBBFCW3I8QteB9DxfcZ5YJpOwH6Ihe/wn8ch7fMGOP1OhEIvw== +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.13.0", "@babel/helper-module-transforms@^7.13.14": + version "7.13.14" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.13.14.tgz#e600652ba48ccb1641775413cb32cfa4e8b495ef" + integrity sha512-QuU/OJ0iAOSIatyVZmfqB0lbkVP0kDRiKj34xy+QNsnVZi/PA6BoSoreeqnxxa9EHFAIL0R9XOaAR/G9WlIy5g== dependencies: - "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-replace-supers" "^7.13.0" - "@babel/helper-simple-access" "^7.12.13" + "@babel/helper-module-imports" "^7.13.12" + "@babel/helper-replace-supers" "^7.13.12" + "@babel/helper-simple-access" "^7.13.12" "@babel/helper-split-export-declaration" "^7.12.13" "@babel/helper-validator-identifier" "^7.12.11" "@babel/template" "^7.12.13" - "@babel/traverse" "^7.13.0" - "@babel/types" "^7.13.0" - lodash "^4.17.19" + "@babel/traverse" "^7.13.13" + "@babel/types" "^7.13.14" "@babel/helper-optimise-call-expression@^7.10.4": version "7.10.4" @@ -617,15 +584,15 @@ "@babel/traverse" "^7.12.5" "@babel/types" "^7.12.5" -"@babel/helper-replace-supers@^7.13.0": - version "7.13.0" - resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.0.tgz#6034b7b51943094cb41627848cb219cb02be1d24" - integrity sha512-Segd5me1+Pz+rmN/NFBOplMbZG3SqRJOBlY+mA0SxAv6rjj7zJqr1AVr3SfzUVTLCv7ZLU5FycOM/SBGuLPbZw== +"@babel/helper-replace-supers@^7.13.12": + version "7.13.12" + resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz#6442f4c1ad912502481a564a7386de0c77ff3804" + integrity sha512-Gz1eiX+4yDO8mT+heB94aLVNCL+rbuT2xy4YfyNqu8F+OI6vMvJK891qGBTqL9Uc8wxEvRW92Id6G7sDen3fFw== dependencies: - "@babel/helper-member-expression-to-functions" "^7.13.0" + "@babel/helper-member-expression-to-functions" "^7.13.12" "@babel/helper-optimise-call-expression" "^7.12.13" "@babel/traverse" "^7.13.0" - "@babel/types" "^7.13.0" + "@babel/types" "^7.13.12" "@babel/helper-simple-access@^7.12.13": version "7.12.13" @@ -634,6 +601,13 @@ dependencies: "@babel/types" "^7.12.13" +"@babel/helper-simple-access@^7.13.12": + version "7.13.12" + resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz#dd6c538afb61819d205a012c31792a39c7a5eaf6" + integrity sha512-7FEjbrx5SL9cWvXioDbnlYTppcZGuCY6ow3/D5vMggb2Ywgu4dMrpTJX0JdQAIcRRUElOIxF3yEooa9gUb9ZbA== + dependencies: + "@babel/types" "^7.13.12" + "@babel/helper-skip-transparent-expression-wrappers@^7.11.0": version "7.11.0" resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz#eec162f112c2f58d3af0af125e3bb57665146729" @@ -648,7 +622,7 @@ dependencies: "@babel/types" "^7.12.1" -"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.8.3": +"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0": version "7.11.0" resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== @@ -677,6 +651,11 @@ resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz#175567380c3e77d60ff98a54bb015fe78f2178d9" integrity sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A== +"@babel/helper-validator-option@^7.12.17": + version "7.12.17" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz#d1fbf012e1a79b7eebbfdc6d270baaf8d9eb9831" + integrity sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw== + "@babel/helper-wrap-function@^7.10.4": version "7.10.4" resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" @@ -687,14 +666,14 @@ "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helpers@^7.12.5": - version "7.12.5" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" - integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA== +"@babel/helpers@^7.13.10": + version "7.13.10" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.13.10.tgz#fd8e2ba7488533cdeac45cc158e9ebca5e3c7df8" + integrity sha512-4VO883+MWPDUVRF3PhiLBUFHoX/bsLTGFpFK/HqvvfBZz2D57u9XzPVNFVBTc0PW/CWR9BXTOKt8NF4DInUHcQ== dependencies: - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.12.5" - "@babel/types" "^7.12.5" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" "@babel/highlight@^7.0.0", "@babel/highlight@^7.10.4", "@babel/highlight@^7.8.3": version "7.10.4" @@ -714,35 +693,15 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@7.11.5", "@babel/parser@^7.11.5": +"@babel/parser@7.11.5": version "7.11.5" resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037" integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q== -"@babel/parser@^7.0.0", "@babel/parser@^7.11.0": - version "7.11.3" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.11.3.tgz#9e1eae46738bcd08e23e867bab43e7b95299a8f9" - integrity sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA== - -"@babel/parser@^7.1.0", "@babel/parser@^7.8.6", "@babel/parser@^7.9.6": - version "7.9.6" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz#3b1bbb30dabe600cd72db58720998376ff653bc7" - integrity sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q== - -"@babel/parser@^7.10.4", "@babel/parser@^7.10.5": - version "7.10.5" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.10.5.tgz#e7c6bf5a7deff957cec9f04b551e2762909d826b" - integrity sha512-wfryxy4bE1UivvQKSQDU4/X6dr+i8bctjUjj8Zyt3DQy7NtPizJXT8M52nqpNKL+nq2PW8lxk4ZqLj0fD4B4hQ== - -"@babel/parser@^7.12.13", "@babel/parser@^7.13.0": - version "7.13.11" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.13.11.tgz#f93ebfc99d21c1772afbbaa153f47e7ce2f50b88" - integrity sha512-PhuoqeHoO9fc4ffMEVk4qb/w/s2iOSWohvbHxLtxui0eBg3Lg5gN1U8wp1V1u61hOWkPQJJyJzGH6Y+grwkq8Q== - -"@babel/parser@^7.12.7": - version "7.12.7" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.12.7.tgz#fee7b39fe809d0e73e5b25eecaf5780ef3d73056" - integrity sha512-oWR02Ubp4xTLCAqPRiNIuMVgNO5Aif/xpXtabhzW2HWUD47XJsAB4Zd/Rg30+XeQA3juXigV7hlquOTmwqLiwg== +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.11.5", "@babel/parser@^7.12.13", "@babel/parser@^7.13.15": + version "7.13.15" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.13.15.tgz#8e66775fb523599acb6a289e12929fa5ab0954d8" + integrity sha512-b9COtcAlVEQljy/9fbcMHpG+UIW9ReF+gpaxDHTlZd0c6/UU9ng8zdySAW9sRTzpvcdCHn6bUcbuYUgGzLAWVQ== "@babel/plugin-proposal-async-generator-functions@^7.12.1": version "7.12.1" @@ -1663,16 +1622,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.10.4": - version "7.10.4" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" - integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/parser" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/template@^7.12.13": +"@babel/template@^7.10.4", "@babel/template@^7.12.13", "@babel/template@^7.3.3": version "7.12.13" resolved "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327" integrity sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA== @@ -1681,24 +1631,6 @@ "@babel/parser" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/template@^7.12.7": - version "7.12.7" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc" - integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/parser" "^7.12.7" - "@babel/types" "^7.12.7" - -"@babel/template@^7.3.3": - version "7.8.6" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" - integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/parser" "^7.8.6" - "@babel/types" "^7.8.6" - "@babel/traverse@7.11.5": version "7.11.5" resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz#be777b93b518eb6d76ee2e1ea1d143daa11e61c3" @@ -1714,82 +1646,21 @@ globals "^11.1.0" lodash "^4.17.19" -"@babel/traverse@^7.0.0": - version "7.11.0" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24" - integrity sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.11.0" - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/parser" "^7.11.0" - "@babel/types" "^7.11.0" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.19" - -"@babel/traverse@^7.1.0": - version "7.9.6" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz#5540d7577697bf619cc57b92aa0f1c231a94f442" - integrity sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.6" - "@babel/helper-function-name" "^7.9.5" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/parser" "^7.9.6" - "@babel/types" "^7.9.6" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/traverse@^7.10.4": - version "7.10.5" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.5.tgz#77ce464f5b258be265af618d8fddf0536f20b564" - integrity sha512-yc/fyv2gUjPqzTz0WHeRJH2pv7jA9kA7mBX2tXl/x5iOE81uaVPuGPtaYk7wmkx4b67mQ7NqI8rmT2pF47KYKQ== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.10.5" - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.10.4" - "@babel/parser" "^7.10.5" - "@babel/types" "^7.10.5" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.19" - -"@babel/traverse@^7.12.5", "@babel/traverse@^7.12.9": - version "7.12.9" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.9.tgz#fad26c972eabbc11350e0b695978de6cc8e8596f" - integrity sha512-iX9ajqnLdoU1s1nHt36JDI9KG4k+vmI8WgjK5d+aDTwQbL2fUnzedNedssA645Ede3PM2ma1n8Q4h2ohwXgMXw== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.12.5" - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/parser" "^7.12.7" - "@babel/types" "^7.12.7" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.19" - -"@babel/traverse@^7.13.0": - version "7.13.0" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.0.tgz#6d95752475f86ee7ded06536de309a65fc8966cc" - integrity sha512-xys5xi5JEhzC3RzEmSGrs/b3pJW/o87SypZ+G/PhaE7uqVQNv/jlmVIBXuoh5atqQ434LfXV+sf23Oxj0bchJQ== +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.5", "@babel/traverse@^7.13.0", "@babel/traverse@^7.13.13", "@babel/traverse@^7.13.15": + version "7.13.15" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.15.tgz#c38bf7679334ddd4028e8e1f7b3aa5019f0dada7" + integrity sha512-/mpZMNvj6bce59Qzl09fHEs8Bt8NnpEDQYleHUPZQ3wXUMvXi+HJPLars68oAbmp839fGoOkv2pSL2z9ajCIaQ== dependencies: "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.13.0" + "@babel/generator" "^7.13.9" "@babel/helper-function-name" "^7.12.13" "@babel/helper-split-export-declaration" "^7.12.13" - "@babel/parser" "^7.13.0" - "@babel/types" "^7.13.0" + "@babel/parser" "^7.13.15" + "@babel/types" "^7.13.14" debug "^4.1.0" globals "^11.1.0" - lodash "^4.17.19" -"@babel/types@7.11.5", "@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.5", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.8.6", "@babel/types@^7.9.6": +"@babel/types@7.11.5": version "7.11.5" resolved "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d" integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q== @@ -1798,230 +1669,15 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" -"@babel/types@^7.11.0": - version "7.11.0" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d" - integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA== - dependencies: - "@babel/helper-validator-identifier" "^7.10.4" - lodash "^4.17.19" - to-fast-properties "^2.0.0" - -"@babel/types@^7.12.1", "@babel/types@^7.12.5", "@babel/types@^7.12.6", "@babel/types@^7.12.7": - version "7.12.7" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.12.7.tgz#6039ff1e242640a29452c9ae572162ec9a8f5d13" - integrity sha512-MNyI92qZq6jrQkXvtIiykvl4WtoRrVV9MPn+ZfsoEENjiWcBQ3ZSHrkxnJWgWtLX3XXqX5hrSQ+X69wkmesXuQ== - dependencies: - "@babel/helper-validator-identifier" "^7.10.4" - 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" - -"@babel/types@^7.12.13", "@babel/types@^7.13.0": - version "7.13.0" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.13.0.tgz#74424d2816f0171b4100f0ab34e9a374efdf7f80" - integrity sha512-hE+HE8rnG1Z6Wzo+MhaKE5lM5eMx71T4EHJgku2E3xIfaULhDcxiiRxUYgwX8qwP1BBSlag+TdGOt6JAidIZTA== +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.11.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.13", "@babel/types@^7.12.5", "@babel/types@^7.12.6", "@babel/types@^7.12.7", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.13.14", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.13.14" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz#c35a4abb15c7cd45a2746d78ab328e362cbace0d" + integrity sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ== dependencies: "@babel/helper-validator-identifier" "^7.12.11" lodash "^4.17.19" to-fast-properties "^2.0.0" -"@backstage/catalog-model@^0.2.0": - version "0.7.5" - dependencies: - "@backstage/config" "^0.1.3" - "@types/json-schema" "^7.0.5" - "@types/yup" "^0.29.8" - ajv "^7.0.3" - json-schema "^0.2.5" - lodash "^4.17.15" - uuid "^8.0.0" - yup "^0.29.3" - -"@backstage/core@^0.3.0": - version "0.7.3" - dependencies: - "@backstage/config" "^0.1.4" - "@backstage/core-api" "^0.2.15" - "@backstage/errors" "^0.1.1" - "@backstage/theme" "^0.2.5" - "@material-ui/core" "^4.11.0" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "4.0.0-alpha.45" - "@testing-library/react-hooks" "^3.4.2" - "@types/dagre" "^0.7.44" - "@types/prop-types" "^15.7.3" - "@types/react" "^16.9" - "@types/react-sparklines" "^1.7.0" - "@types/react-text-truncate" "^0.14.0" - classnames "^2.2.6" - clsx "^1.1.0" - d3-selection "^2.0.0" - d3-shape "^2.0.0" - d3-zoom "^2.0.0" - dagre "^0.8.5" - immer "^9.0.1" - lodash "^4.17.15" - material-table "^1.69.1" - prop-types "^15.7.2" - qs "^6.9.4" - rc-progress "^3.0.0" - react "^16.12.0" - react-dom "^16.12.0" - react-helmet "6.1.0" - react-hook-form "^6.6.0" - react-markdown "^5.0.2" - react-router "6.0.0-beta.0" - react-router-dom "6.0.0-beta.0" - react-sparklines "^1.7.0" - react-syntax-highlighter "^15.4.3" - react-text-truncate "^0.16.0" - react-use "^15.3.3" - remark-gfm "^1.0.0" - zen-observable "^0.8.15" - -"@backstage/core@^0.6.0": - version "0.7.3" - dependencies: - "@backstage/config" "^0.1.4" - "@backstage/core-api" "^0.2.15" - "@backstage/errors" "^0.1.1" - "@backstage/theme" "^0.2.5" - "@material-ui/core" "^4.11.0" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "4.0.0-alpha.45" - "@testing-library/react-hooks" "^3.4.2" - "@types/dagre" "^0.7.44" - "@types/prop-types" "^15.7.3" - "@types/react" "^16.9" - "@types/react-sparklines" "^1.7.0" - "@types/react-text-truncate" "^0.14.0" - classnames "^2.2.6" - clsx "^1.1.0" - d3-selection "^2.0.0" - d3-shape "^2.0.0" - d3-zoom "^2.0.0" - dagre "^0.8.5" - immer "^9.0.1" - lodash "^4.17.15" - material-table "^1.69.1" - prop-types "^15.7.2" - qs "^6.9.4" - rc-progress "^3.0.0" - react "^16.12.0" - react-dom "^16.12.0" - react-helmet "6.1.0" - react-hook-form "^6.6.0" - react-markdown "^5.0.2" - react-router "6.0.0-beta.0" - react-router-dom "6.0.0-beta.0" - react-sparklines "^1.7.0" - react-syntax-highlighter "^15.4.3" - react-text-truncate "^0.16.0" - react-use "^15.3.3" - remark-gfm "^1.0.0" - zen-observable "^0.8.15" - -"@backstage/core@^0.6.1": - version "0.7.3" - dependencies: - "@backstage/config" "^0.1.4" - "@backstage/core-api" "^0.2.15" - "@backstage/errors" "^0.1.1" - "@backstage/theme" "^0.2.5" - "@material-ui/core" "^4.11.0" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "4.0.0-alpha.45" - "@testing-library/react-hooks" "^3.4.2" - "@types/dagre" "^0.7.44" - "@types/prop-types" "^15.7.3" - "@types/react" "^16.9" - "@types/react-sparklines" "^1.7.0" - "@types/react-text-truncate" "^0.14.0" - classnames "^2.2.6" - clsx "^1.1.0" - d3-selection "^2.0.0" - d3-shape "^2.0.0" - d3-zoom "^2.0.0" - dagre "^0.8.5" - immer "^9.0.1" - lodash "^4.17.15" - material-table "^1.69.1" - prop-types "^15.7.2" - qs "^6.9.4" - rc-progress "^3.0.0" - react "^16.12.0" - react-dom "^16.12.0" - react-helmet "6.1.0" - react-hook-form "^6.6.0" - react-markdown "^5.0.2" - react-router "6.0.0-beta.0" - react-router-dom "6.0.0-beta.0" - react-sparklines "^1.7.0" - react-syntax-highlighter "^15.4.3" - react-text-truncate "^0.16.0" - react-use "^15.3.3" - remark-gfm "^1.0.0" - zen-observable "^0.8.15" - -"@backstage/plugin-catalog@^0.2.1": - version "0.5.2" - dependencies: - "@backstage/catalog-client" "^0.3.9" - "@backstage/catalog-model" "^0.7.5" - "@backstage/core" "^0.7.3" - "@backstage/errors" "^0.1.1" - "@backstage/integration" "^0.5.1" - "@backstage/integration-react" "^0.1.1" - "@backstage/plugin-catalog-react" "^0.1.4" - "@backstage/theme" "^0.2.5" - "@material-ui/core" "^4.11.0" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "4.0.0-alpha.45" - "@types/react" "^16.9" - classnames "^2.2.6" - git-url-parse "^11.4.4" - react "^16.13.1" - react-dom "^16.13.1" - react-helmet "6.1.0" - react-router "6.0.0-beta.0" - react-router-dom "6.0.0-beta.0" - react-use "^15.3.3" - swr "^0.3.0" - -"@backstage/plugin-catalog@^0.3.1": - version "0.5.2" - dependencies: - "@backstage/catalog-client" "^0.3.9" - "@backstage/catalog-model" "^0.7.5" - "@backstage/core" "^0.7.3" - "@backstage/errors" "^0.1.1" - "@backstage/integration" "^0.5.1" - "@backstage/integration-react" "^0.1.1" - "@backstage/plugin-catalog-react" "^0.1.4" - "@backstage/theme" "^0.2.5" - "@material-ui/core" "^4.11.0" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "4.0.0-alpha.45" - "@types/react" "^16.9" - classnames "^2.2.6" - git-url-parse "^11.4.4" - react "^16.13.1" - react-dom "^16.13.1" - react-helmet "6.1.0" - react-router "6.0.0-beta.0" - react-router-dom "6.0.0-beta.0" - react-use "^15.3.3" - swr "^0.3.0" - "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -2387,6 +2043,16 @@ resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== +"@endemolshinegroup/cosmiconfig-typescript-loader@3.0.2": + version "3.0.2" + resolved "https://registry.npmjs.org/@endemolshinegroup/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-3.0.2.tgz#eea4635828dde372838b0909693ebd9aafeec22d" + integrity sha512-QRVtqJuS1mcT56oHpVegkKBlgtWjXw/gHNWO3eL9oyB5Sc7HBoc2OLG/nYpVfT/Jejvo3NUrD0Udk7XgoyDKkA== + dependencies: + lodash.get "^4" + make-error "^1" + ts-node "^9" + tslib "^2" + "@eslint/eslintrc@^0.2.1": version "0.2.1" resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.1.tgz#f72069c330461a06684d119384435e12a5d76e3c" @@ -2570,6 +2236,33 @@ stream-events "^1.0.1" xdg-basedir "^4.0.0" +"@google-cloud/storage@^5.8.0": + version "5.8.0" + resolved "https://registry.npmjs.org/@google-cloud/storage/-/storage-5.8.0.tgz#1f580e276f1d453790b382156421d1bcc4bd3f4b" + integrity sha512-WOShvBPOfkDXUzXMO+3j8Bzus+PFI9r1Ey9dLG2Zf458/PVuFTtaRWntd9ZiDG8g90zl2LmnA1JkDCreGUKr5g== + dependencies: + "@google-cloud/common" "^3.6.0" + "@google-cloud/paginator" "^3.0.0" + "@google-cloud/promisify" "^2.0.0" + arrify "^2.0.0" + async-retry "^1.3.1" + compressible "^2.0.12" + date-and-time "^0.14.2" + duplexify "^4.0.0" + extend "^3.0.2" + gaxios "^4.0.0" + gcs-resumable-upload "^3.1.3" + get-stream "^6.0.0" + hash-stream-validation "^0.2.2" + mime "^2.2.0" + mime-types "^2.0.8" + onetime "^5.1.0" + p-limit "^3.0.1" + pumpify "^2.0.0" + snakeize "^0.1.0" + stream-events "^1.0.1" + xdg-basedir "^4.0.0" + "@graphiql/toolkit@^0.1.0": version "0.1.1" resolved "https://registry.npmjs.org/@graphiql/toolkit/-/toolkit-0.1.1.tgz#a7da3ba460ceae27bcdc8f03831ca4f88f90f3d7" @@ -2580,13 +2273,13 @@ meros "^1.1.2" subscriptions-transport-ws "^0.9.18" -"@graphql-codegen/cli@^1.17.7": - version "1.17.10" - resolved "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-1.17.10.tgz#efebf9b887fdb94dd26dbf3eb1950e832efcda0e" - integrity sha512-nQYbabB3aS3XArETJc/NrpUtlj/Dzh2KeDgvVRsc3zxopcudZTKj1dcTCOA/QZPSpbzALbZZ/1loBVVrMIe+Iw== +"@graphql-codegen/cli@^1.21.3": + version "1.21.3" + resolved "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-1.21.3.tgz#3506c5d019c6995be1927bd4d9c67a739fafe5e6" + integrity sha512-jwg0mKhseg0QI4/T4IQcttTBCZgnahiTWqnYWIK+E8nrbXCE9o2hxvaYin/Kq9+5oFtxDePED56cjVs/ESRw6g== dependencies: - "@graphql-codegen/core" "1.17.8" - "@graphql-codegen/plugin-helpers" "^1.17.9" + "@graphql-codegen/core" "1.17.9" + "@graphql-codegen/plugin-helpers" "^1.18.4" "@graphql-tools/apollo-engine-loader" "^6" "@graphql-tools/code-file-loader" "^6" "@graphql-tools/git-loader" "^6" @@ -2596,19 +2289,18 @@ "@graphql-tools/load" "^6" "@graphql-tools/prisma-loader" "^6" "@graphql-tools/url-loader" "^6" - "@graphql-tools/utils" "^6" + "@graphql-tools/utils" "^7.0.0" ansi-escapes "^4.3.1" - camel-case "^4.1.1" chalk "^4.1.0" - chokidar "^3.4.2" + change-case-all "1.0.12" + chokidar "^3.4.3" common-tags "^1.8.0" - constant-case "^3.0.3" cosmiconfig "^7.0.0" debounce "^1.2.0" - dependency-graph "^0.9.0" + dependency-graph "^0.11.0" detect-indent "^6.0.0" glob "^7.1.6" - graphql-config "^3.0.2" + graphql-config "^3.2.0" indent-string "^4.0.0" inquirer "^7.3.3" is-glob "^4.0.1" @@ -2617,30 +2309,27 @@ listr "^0.14.3" listr-update-renderer "^0.5.0" log-symbols "^4.0.0" - lower-case "^2.0.1" minimatch "^3.0.4" mkdirp "^1.0.4" - pascal-case "^3.1.1" - request "^2.88.2" string-env-interpolation "^1.0.1" ts-log "^2.2.3" - tslib "~2.0.1" - upper-case "^2.0.1" + tslib "~2.1.0" valid-url "^1.0.9" wrap-ansi "^7.0.0" - yargs "^16.0.3" + yaml "^1.10.0" + yargs "^16.1.1" -"@graphql-codegen/core@1.17.8": - version "1.17.8" - resolved "https://registry.npmjs.org/@graphql-codegen/core/-/core-1.17.8.tgz#d70281bcf9f4b7b560ab5b16f7fc7a2853c49a8a" - integrity sha512-HUntoeLhLZf6wroD1HYLsniz51N3zW7cjgwojGKgbUsI6Oa8pGsh+kKaN9xtvlb/hIpsRJ00q9LbPVIM/kXQtQ== +"@graphql-codegen/core@1.17.9": + version "1.17.9" + resolved "https://registry.npmjs.org/@graphql-codegen/core/-/core-1.17.9.tgz#c03e71018ff04d26f5139a2d90a32b31d3bb2b43" + integrity sha512-7nwy+bMWqb0iYJ2DKxA9UiE16meeJ2Ch2XWS/N/ZnA0snTR+GZ20USI8z6YqP1Fuist7LvGO1MbitO2qBT8raA== dependencies: - "@graphql-codegen/plugin-helpers" "^1.17.8" - "@graphql-tools/merge" "^6.0.18" - "@graphql-tools/utils" "^6.0.18" - tslib "~2.0.0" + "@graphql-codegen/plugin-helpers" "^1.18.2" + "@graphql-tools/merge" "^6" + "@graphql-tools/utils" "^6" + tslib "~2.0.1" -"@graphql-codegen/plugin-helpers@^1.17.8", "@graphql-codegen/plugin-helpers@^1.17.9", "@graphql-codegen/plugin-helpers@^1.18.2", "@graphql-codegen/plugin-helpers@^1.18.3": +"@graphql-codegen/plugin-helpers@^1.18.2", "@graphql-codegen/plugin-helpers@^1.18.3": version "1.18.3" resolved "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-1.18.3.tgz#607a8bc16d80b30d59cd07d70de2ba803b57bc4a" integrity sha512-+LVxWFlcZW+FB32CyvkdaMN/tIMajO42pCg0Cy8Z8ZZtGutXW1w6UggrvrEUzMZc9GHZQe49q+w7QQxeooaIlA== @@ -2651,6 +2340,17 @@ lodash "~4.17.20" tslib "~2.1.0" +"@graphql-codegen/plugin-helpers@^1.18.4": + version "1.18.4" + resolved "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-1.18.4.tgz#0adc4c0f88386a50b7a69d358080b6ee54fc3b16" + integrity sha512-dpfhUmn9GOS8ByoOPIN3V4Nn9HX7sl9NR7Hf26TgN6Clg7cQvkT6XjHdS2e56Q3kWrxZT1zJ1sEa67D3tj9ZtQ== + dependencies: + "@graphql-tools/utils" "^7.0.0" + common-tags "1.8.0" + import-from "3.0.0" + lodash "~4.17.20" + tslib "~2.1.0" + "@graphql-codegen/typescript-resolvers@^1.17.7": version "1.18.2" resolved "https://registry.npmjs.org/@graphql-codegen/typescript-resolvers/-/typescript-resolvers-1.18.2.tgz#7513b92df7c5a0d3c27342c591ada7340696cf8f" @@ -2836,6 +2536,15 @@ unixify "1.0.0" valid-url "1.0.9" +"@graphql-tools/merge@^6": + version "6.2.11" + resolved "https://registry.npmjs.org/@graphql-tools/merge/-/merge-6.2.11.tgz#398f6c5fb6498fe0b5f062c65cf648c0e4a57e9c" + integrity sha512-temQABWkDTZb/qJwcIdrEbyJ5WkhaWZQeYxiuxGqZWlIOoFkYfqzfAP2qKl2Ry+ZkN+Q/Yozr1/ap//xjpwAlA== + dependencies: + "@graphql-tools/schema" "^7.0.0" + "@graphql-tools/utils" "^7.7.0" + tslib "~2.1.0" + "@graphql-tools/merge@^6.0.0": version "6.0.15" resolved "https://registry.npmjs.org/@graphql-tools/merge/-/merge-6.0.15.tgz#09c84bd08971edfb3e1035d71432b47687820bdc" @@ -2845,15 +2554,6 @@ "@graphql-tools/utils" "6.0.15" tslib "~2.0.0" -"@graphql-tools/merge@^6.0.18": - version "6.0.18" - resolved "https://registry.npmjs.org/@graphql-tools/merge/-/merge-6.0.18.tgz#d105e16c6f5f874ddfdba3f3f4a2f676a6d2d04a" - integrity sha512-XAFbqMyXsExnuzgr5+JQC8mxsYp0aGIR0m+GbleQDZSlqDOL2maF5xM3dGOOkguz0Paa7ei/5UfnMXyRU3cW/w== - dependencies: - "@graphql-tools/schema" "6.0.18" - "@graphql-tools/utils" "6.0.18" - tslib "~2.0.0" - "@graphql-tools/merge@^6.2.4": version "6.2.4" resolved "https://registry.npmjs.org/@graphql-tools/merge/-/merge-6.2.4.tgz#5b3b68083d55a38a7f3caac6e0adc46f428c2a3b" @@ -2917,14 +2617,6 @@ "@graphql-tools/utils" "6.0.15" tslib "~2.0.0" -"@graphql-tools/schema@6.0.18": - version "6.0.18" - resolved "https://registry.npmjs.org/@graphql-tools/schema/-/schema-6.0.18.tgz#243eb370e4cded00767202bbabf0893f65c3f5b9" - integrity sha512-xrScjRX9pTSVxqiSkx7Hn/9rzxLweysINa5Pkirdkv5lJY4e0Db53osur0nG/+SJyUmIN70tUtuhEZq4Ezr/PA== - dependencies: - "@graphql-tools/utils" "6.0.18" - tslib "~2.0.0" - "@graphql-tools/schema@^6.2.4": version "6.2.4" resolved "https://registry.npmjs.org/@graphql-tools/schema/-/schema-6.2.4.tgz#cc4e9f5cab0f4ec48500e666719d99fc5042481d" @@ -2933,6 +2625,14 @@ "@graphql-tools/utils" "^6.2.4" tslib "~2.0.1" +"@graphql-tools/schema@^7.0.0": + version "7.1.3" + resolved "https://registry.npmjs.org/@graphql-tools/schema/-/schema-7.1.3.tgz#d816400da51fbac1f0086e35540ab63b5e30e858" + integrity sha512-ZY76hmcJlF1iyg3Im0sQ3ASRkiShjgv102vLTVcH22lEGJeCaCyyS/GF1eUHom418S60bS8Th6+autRUxfBiBg== + dependencies: + "@graphql-tools/utils" "^7.1.2" + tslib "~2.1.0" + "@graphql-tools/url-loader@^6", "@graphql-tools/url-loader@^6.0.0", "@graphql-tools/url-loader@^6.2.4": version "6.3.0" resolved "https://registry.npmjs.org/@graphql-tools/url-loader/-/url-loader-6.3.0.tgz#75b82bdf0983d3e389c75948a7abff20fa45a630" @@ -2956,15 +2656,7 @@ "@ardatan/aggregate-error" "0.0.1" camel-case "4.1.1" -"@graphql-tools/utils@6.0.18": - version "6.0.18" - resolved "https://registry.npmjs.org/@graphql-tools/utils/-/utils-6.0.18.tgz#bba960f0ab327c8304089d41da0b7a3e00fe430f" - integrity sha512-8ntYuXJucBtjViOYljeKBzScfpVTnv7BfqIPU/WJ65h6nXD+qf8fMUR1C4MpCUeFvSjMiDSB5Z4enJmau/9D3A== - dependencies: - "@ardatan/aggregate-error" "0.0.1" - camel-case "4.1.1" - -"@graphql-tools/utils@^6", "@graphql-tools/utils@^6.0.0", "@graphql-tools/utils@^6.0.18", "@graphql-tools/utils@^6.2.4": +"@graphql-tools/utils@^6", "@graphql-tools/utils@^6.0.0", "@graphql-tools/utils@^6.2.4": version "6.2.4" resolved "https://registry.npmjs.org/@graphql-tools/utils/-/utils-6.2.4.tgz#38a2314d2e5e229ad4f78cca44e1199e18d55856" integrity sha512-ybgZ9EIJE3JMOtTrTd2VcIpTXtDrn2q6eiYkeYMKRVh3K41+LZa6YnR2zKERTXqTWqhobROwLt4BZbw2O3Aeeg== @@ -2982,6 +2674,15 @@ camel-case "4.1.2" tslib "~2.1.0" +"@graphql-tools/utils@^7.1.2", "@graphql-tools/utils@^7.7.0": + version "7.7.1" + resolved "https://registry.npmjs.org/@graphql-tools/utils/-/utils-7.7.1.tgz#81f32cb4819b34b3a378d51ab2cd60935977f0b4" + integrity sha512-SFT4/dTfrwWer1wSOLU+jqgv3oa/xTR8q+MiNbE9nCH2FXyMsqIOaXKm9wHfKIWFWHozqBdcnwFkQZrdD7H2TQ== + dependencies: + "@ardatan/aggregate-error" "0.0.6" + camel-case "4.1.2" + tslib "~2.1.0" + "@graphql-tools/wrap@^6.2.4": version "6.2.4" resolved "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-6.2.4.tgz#2709817da6e469753735a9fe038c9e99736b2c57" @@ -3032,6 +2733,11 @@ prop-types "^15.6.2" scheduler "^0.19.0" +"@iarna/toml@^2.2.5": + version "2.2.5" + resolved "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz#b32366c89b43c6f8cefbdefac778b9c828e3ba8c" + integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg== + "@icons/material@^0.2.4": version "0.2.4" resolved "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8" @@ -3107,11 +2813,6 @@ slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/create-cache-key-function@^26.5.0": - version "26.5.0" - resolved "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-26.5.0.tgz#1d07947adc51ea17766d9f0ccf5a8d6ea94c47dc" - integrity sha512-DJ+pEBUIqarrbv1W/C39f9YH0rJ4wsXZ/VC6JafJPlHW2HOucKceeaqTOQj9MEDQZjySxMLkOq5mfXZXNZcmWw== - "@jest/environment@^26.6.2": version "26.6.2" resolved "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz#ba364cc72e221e79cc8f0a99555bf5d7577cf92c" @@ -4302,6 +4003,11 @@ resolved "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-5.3.2.tgz#b8ac43c5c3d00aef61a34cf744e315110c78deb4" integrity sha512-NxF1yfYOUO92rCx3dwvA2onF30Vdlg7YUkMVXkeptqpzA3tRLplThhFleV/UKWFgh7rpKu1yYRbvNDUtzSopKA== +"@octokit/openapi-types@^6.0.0": + version "6.0.0" + resolved "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-6.0.0.tgz#7da8d7d5a72d3282c1a3ff9f951c8133a707480d" + integrity sha512-CnDdK7ivHkBtJYzWzZm7gEkanA7gKH6a09Eguz7flHw//GacPJLmkHA3f3N++MJmlxD1Fl+mB7B32EEpSCwztQ== + "@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" @@ -4327,6 +4033,14 @@ "@octokit/types" "^6.12.2" deprecation "^2.3.1" +"@octokit/plugin-rest-endpoint-methods@5.0.0": + version "5.0.0" + resolved "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.0.0.tgz#cf2cdeb24ea829c31688216a5b165010b61f9a98" + integrity sha512-Jc7CLNUueIshXT+HWt6T+M0sySPjF32mSFQAK7UfAg8qGeRI6OM1GSBxDLwbXjkqy2NVdnqCedJcP1nC785JYg== + dependencies: + "@octokit/types" "^6.13.0" + deprecation "^2.3.1" + "@octokit/request-error@^2.0.0": version "2.0.2" resolved "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.2.tgz#0e76b83f5d8fdda1db99027ea5f617c2e6ba9ed0" @@ -4350,7 +4064,7 @@ once "^1.4.0" universal-user-agent "^6.0.0" -"@octokit/rest@^18.0.0", "@octokit/rest@^18.0.12", "@octokit/rest@^18.1.0": +"@octokit/rest@^18.0.12", "@octokit/rest@^18.1.0": version "18.3.5" resolved "https://registry.npmjs.org/@octokit/rest/-/rest-18.3.5.tgz#a89903d46e0b4273bd3234674ec2777a651d68ab" integrity sha512-ZPeRms3WhWxQBEvoIh0zzf8xdU2FX0Capa7+lTca8YHmRsO3QNJzf1H3PcuKKsfgp91/xVDRtX91sTe1kexlbw== @@ -4360,6 +4074,16 @@ "@octokit/plugin-request-log" "^1.0.2" "@octokit/plugin-rest-endpoint-methods" "4.13.5" +"@octokit/rest@^18.1.1": + version "18.5.2" + resolved "https://registry.npmjs.org/@octokit/rest/-/rest-18.5.2.tgz#0369e554b7076e3749005147be94c661c7a5a74b" + integrity sha512-Kz03XYfKS0yYdi61BkL9/aJ0pP2A/WK5vF/syhu9/kY30J8He3P68hv9GRpn8bULFx2K0A9MEErn4v3QEdbZcw== + dependencies: + "@octokit/core" "^3.2.3" + "@octokit/plugin-paginate-rest" "^2.6.2" + "@octokit/plugin-request-log" "^1.0.2" + "@octokit/plugin-rest-endpoint-methods" "5.0.0" + "@octokit/types@^5.0.0", "@octokit/types@^5.0.1": version "5.5.0" resolved "https://registry.npmjs.org/@octokit/types/-/types-5.5.0.tgz#e5f06e8db21246ca102aa28444cdb13ae17a139b" @@ -4367,13 +4091,20 @@ dependencies: "@types/node" ">= 8" -"@octokit/types@^6.0.0", "@octokit/types@^6.0.1", "@octokit/types@^6.0.3", "@octokit/types@^6.12.2", "@octokit/types@^6.8.2": +"@octokit/types@^6.0.0", "@octokit/types@^6.0.1", "@octokit/types@^6.0.3", "@octokit/types@^6.12.2": version "6.12.2" resolved "https://registry.npmjs.org/@octokit/types/-/types-6.12.2.tgz#5b44add079a478b8eb27d78cf384cc47e4411362" integrity sha512-kCkiN8scbCmSq+gwdJV0iLgHc0O/GTPY1/cffo9kECu1MvatLPh9E+qFhfRIktKfHEA6ZYvv6S1B4Wnv3bi3pA== dependencies: "@octokit/openapi-types" "^5.3.2" +"@octokit/types@^6.13.0", "@octokit/types@^6.8.2": + version "6.13.0" + resolved "https://registry.npmjs.org/@octokit/types/-/types-6.13.0.tgz#779e5b7566c8dde68f2f6273861dd2f0409480d0" + integrity sha512-W2J9qlVIU11jMwKHUp5/rbVUeErqelCsO5vW5PKNb7wAXQVUz87Rc+imjlEvpvbH8yUb+KHmv8NEjVZdsdpyxA== + dependencies: + "@octokit/openapi-types" "^6.0.0" + "@open-draft/until@^1.0.3": version "1.0.3" resolved "https://registry.npmjs.org/@open-draft/until/-/until-1.0.3.tgz#db9cc719191a62e7d9200f6e7bab21c5b848adca" @@ -4511,55 +4242,60 @@ resolved "https://registry.npmjs.org/@rjsf/material-ui/-/material-ui-2.4.1.tgz#b0dedff8877b114147e298966ca3faba895a7a62" integrity sha512-pZaWL5Dw+km8S0hFLIK1lRHaeNtheMxTF2mZrWhf6HlGWCTGkQJnXta2UgshJN/nKtZPgO1L4FKz42Eun9nnhg== -"@roadiehq/backstage-plugin-buildkite@^0.1.3": - version "0.1.3" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-buildkite/-/backstage-plugin-buildkite-0.1.3.tgz#5a116bf677dfad22088212dde398cf3e9b48d6e4" - integrity sha512-q+cnAvZmjLu0DcqRKJZJhWTVcKaA9j7cM44tx6JcshEyb3UgzrlECLvx4ethnYyrmhM1/FSpMLa+t3N5A1Xz4g== +"@roadiehq/backstage-plugin-buildkite@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-buildkite/-/backstage-plugin-buildkite-1.0.0.tgz#0c00352eb7a204ac45f55bc5dd4c17c9c1cfdf9e" + integrity sha512-R6pxMSOeTK+4OBBhSktEEEIkaVTcOWTsgnpB5FEZ748YZ3Ul4dp4H2S3bup2OnMIL79xY2oAxYt1iRmAe69Bng== dependencies: - "@backstage/catalog-model" "^0.2.0" - "@backstage/core" "^0.3.0" - "@backstage/plugin-catalog" "^0.2.1" + "@backstage/catalog-model" "^0.7.4" + "@backstage/core" "^0.7.3" + "@backstage/plugin-catalog" "^0.5.1" + "@backstage/plugin-catalog-react" "^0.1.4" + "@backstage/theme" "^0.2.5" "@material-ui/core" "^4.11.0" "@material-ui/icons" "^4.9.1" "@material-ui/lab" "4.0.0-alpha.45" + history "^5.0.0" moment "^2.27.0" react "^16.13.1" react-dom "^16.13.1" react-lazylog "^4.5.2" react-router "6.0.0-beta.0" react-router-dom "6.0.0-beta.0" - react-use "^15.3.3" + react-use "^15.3.6" -"@roadiehq/backstage-plugin-github-insights@^0.3.2": - version "0.3.2" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-insights/-/backstage-plugin-github-insights-0.3.2.tgz#2db83e172ae34738677bd47c3b754c31bb2b5987" - integrity sha512-eIhqQS0jTRcdTCu+GxrRCH1tq+kDrTb6mMJpD/6sGnE9QXgj5nKHIm6KHmFYEfIiukQrGxXY4lABNWstvi7hgA== +"@roadiehq/backstage-plugin-github-insights@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-insights/-/backstage-plugin-github-insights-1.0.0.tgz#8b30bd3c4979aab8cd145c4c0b28488badd8e662" + integrity sha512-KynUXVGb+lpMoDoGrolOtsY9roFuPaMre92g1/DZBoLU2BXFpdmnhJXf1YaDHVuBIITP0AhtQfZpu8KNXm/Cmg== dependencies: - "@backstage/catalog-model" "^0.7.1" - "@backstage/core" "^0.6.0" - "@backstage/theme" "^0.2.3" + "@backstage/catalog-model" "^0.7.4" + "@backstage/core" "^0.7.3" + "@backstage/plugin-catalog-react" "^0.1.4" + "@backstage/theme" "^0.2.5" "@date-io/core" "2.10.7" "@material-ui/core" "^4.11.0" "@material-ui/icons" "^4.9.1" "@material-ui/lab" "4.0.0-alpha.57" - "@octokit/rest" "^18.0.0" - "@octokit/types" "^6.8.2" + "@octokit/rest" "^18.1.1" + "@octokit/types" "^6.13.0" history "^5.0.0" react "^16.13.1" react-dom "^16.13.1" react-router "^6.0.0-beta.0" - react-use "^17.1.0" + react-use "^17.2.1" -"@roadiehq/backstage-plugin-github-pull-requests@^0.7.6": - version "0.7.8" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-pull-requests/-/backstage-plugin-github-pull-requests-0.7.8.tgz#14a8e512b83de6cb5304b2a8e62c447b2bd6e311" - integrity sha512-sgBzIYC4GfZGbFpRixQBinf62laVqefRLHPLaoF2LuTMStXGcjUIGlqySmWNOXvpmGjCv3QIxh1NaxZBp6Z1Vw== +"@roadiehq/backstage-plugin-github-pull-requests@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-pull-requests/-/backstage-plugin-github-pull-requests-1.0.0.tgz#5103d9ff65ed38a752ceb8ac1c7369fd0724388f" + integrity sha512-HAi3X0kto/xMNaMzy9f4t142MGvxwuxDfiLN+bZUsWwta4iI3CgK/9fZAd5kU9+E04EFxkRXmg72FXxG64H6Zg== dependencies: - "@backstage/catalog-model" "^0.7.1" - "@backstage/core" "^0.6.1" + "@backstage/catalog-model" "^0.7.4" + "@backstage/core" "^0.7.3" + "@backstage/plugin-catalog-react" "^0.1.4" "@material-ui/core" "^4.11.0" "@material-ui/icons" "^4.9.1" - "@octokit/rest" "^18.0.0" + "@octokit/rest" "^18.1.1" "@octokit/types" "^5.0.1" "@types/node-fetch" "^2.5.7" history "^5.0.0" @@ -4570,20 +4306,21 @@ react-router "6.0.0-beta.0" react-use "^15.3.6" -"@roadiehq/backstage-plugin-travis-ci@^0.4.5": - version "0.4.5" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-travis-ci/-/backstage-plugin-travis-ci-0.4.5.tgz#c80eb972951badd110173f5521aae65b8a5cfc53" - integrity sha512-+y5kFtVaPjXgf6naGVU2E3C33nvoXuaBbfYEmCeByg2t0b5jHMHzsTv2tV5/8zeAcus/5+yIkRCq+F1Tcbwutw== +"@roadiehq/backstage-plugin-travis-ci@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-travis-ci/-/backstage-plugin-travis-ci-1.0.0.tgz#5aa29f4ba2086b6341a903a22c843d898808f503" + integrity sha512-JjMDwbou1iY0sSoit8ttpzXEP6lhmLmxf/Pj6Am/1rcia5KLdeMUqpilkzQ33LeHiMXXxu95gp4r6aJ5vC9wGg== dependencies: - "@backstage/catalog-model" "^0.7.0" - "@backstage/core" "^0.6.0" - "@backstage/plugin-catalog" "^0.3.1" - "@backstage/theme" "^0.2.1" + "@backstage/catalog-model" "^0.7.4" + "@backstage/core" "^0.7.3" + "@backstage/plugin-catalog" "^0.5.1" + "@backstage/plugin-catalog-react" "^0.1.4" + "@backstage/theme" "^0.2.5" "@material-ui/core" "^4.9.1" "@material-ui/icons" "^4.9.1" "@material-ui/lab" "4.0.0-alpha.45" cross-fetch "^3.0.6" - date-fns "^2.16.1" + date-fns "^2.18.0" history "^5.0.0" moment "^2.29.1" react "^16.13.1" @@ -6259,13 +5996,13 @@ "@types/uglify-js" "*" "@types/html-webpack-plugin@*", "@types/html-webpack-plugin@^3.2.2": - version "3.2.4" - resolved "https://registry.npmjs.org/@types/html-webpack-plugin/-/html-webpack-plugin-3.2.4.tgz#ed770ddfec53ed2aa6b5f4523acca291192235c6" - integrity sha512-WM0s78bfCIXnTlICf+8nWP0IvP+fn4YfiI3uxAX1K1PSRpzs0iysp03j4zR0xTgxSqF67TbOsHs49YXonRAkeQ== + version "3.2.5" + resolved "https://registry.npmjs.org/@types/html-webpack-plugin/-/html-webpack-plugin-3.2.5.tgz#58e94c0d57801903b2b77674d2b9ef6c4a65a6db" + integrity sha512-DhC7NTte+Ikw/zxp2w9qjcWtHqpShbUx7ASPUZ00trn1EOftoRtMmy8nS7F/mW8ASTA2JGMFX2bbuqqxiqs6mQ== dependencies: "@types/html-minifier" "*" - "@types/tapable" "*" - "@types/webpack" "*" + "@types/tapable" "^1" + "@types/webpack" "^4" "@types/http-assert@*": version "1.5.1" @@ -6357,7 +6094,7 @@ dependencies: "@types/jest" "*" -"@types/jest@*", "@types/jest@26.x", "@types/jest@^26.0.7": +"@types/jest@*", "@types/jest@^26.0.7": version "26.0.15" resolved "https://registry.npmjs.org/@types/jest/-/jest-26.0.15.tgz#12e02c0372ad0548e07b9f4e19132b834cb1effe" integrity sha512-s2VMReFXRg9XXxV+CW9e5Nz8fH2K1aEhwgjUqPPbQd7g95T0laAcvLv032EhFHIa5GHsZ8W7iJEQVaJq6k3Gog== @@ -7002,10 +6739,10 @@ dependencies: "@types/react" "*" -"@types/tapable@*", "@types/tapable@^1.0.5": - version "1.0.5" - resolved "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.5.tgz#9adbc12950582aa65ead76bffdf39fe0c27a3c02" - integrity sha512-/gG2M/Imw7cQFp8PGvz/SwocNrmKFjFsm5Pb8HdbHkZ1K8pmuPzOX4VeVoiEecFCVf4CsN1r3/BRvx+6sNqwtQ== +"@types/tapable@^1", "@types/tapable@^1.0.5": + version "1.0.7" + resolved "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.7.tgz#545158342f949e8fd3bfd813224971ecddc3fac4" + integrity sha512-0VBprVqfgFD7Ehb2vd8Lh9TG3jP98gvr8rgehQqzztZNI7o8zS8Ad4jyZneKELphpuE212D8J70LnSNQSyO6bQ== "@types/tar@^4.0.3": version "4.0.4" @@ -7134,14 +6871,14 @@ "@types/source-list-map" "*" source-map "^0.6.1" -"@types/webpack@*", "@types/webpack@^4.41.7", "@types/webpack@^4.41.8": - version "4.41.26" - resolved "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.26.tgz#27a30d7d531e16489f9c7607c747be6bc1a459ef" - integrity sha512-7ZyTfxjCRwexh+EJFwRUM+CDB2XvgHl4vfuqf1ZKrgGvcS5BrNvPQqJh3tsZ0P6h6Aa1qClVHaJZszLPzpqHeA== +"@types/webpack@*", "@types/webpack@^4", "@types/webpack@^4.41.7", "@types/webpack@^4.41.8": + version "4.41.27" + resolved "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.27.tgz#f47da488c8037e7f1b2dbf2714fbbacb61ec0ffc" + integrity sha512-wK/oi5gcHi72VMTbOaQ70VcDxSQ1uX8S2tukBK9ARuGXrYM/+u4ou73roc7trXDNmCxCoerE8zruQqX/wuHszA== dependencies: "@types/anymatch" "*" "@types/node" "*" - "@types/tapable" "*" + "@types/tapable" "^1" "@types/uglify-js" "*" "@types/webpack-sources" "*" source-map "^0.6.0" @@ -8962,10 +8699,10 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" -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== +bl@^4.0.3, bl@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== dependencies: buffer "^5.5.0" inherits "^2.0.4" @@ -9662,7 +9399,7 @@ chalk@^4.0.0, chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -change-case-all@^1.0.12: +change-case-all@1.0.12, change-case-all@^1.0.12: version "1.0.12" resolved "https://registry.npmjs.org/change-case-all/-/change-case-all-1.0.12.tgz#ae3e0faf5e610e8e25c5d5eaa4a6d5c2f1d68797" integrity sha512-zdQus7R0lkprF99lrWUC5bFj6Nog4Xt4YCEjQ/vM4vbc6b5JHFBQMxRPAjfx+HJH8WxMzH0E+lQ8yQJLgmPCBg== @@ -9772,6 +9509,21 @@ chokidar@^3.2.2, chokidar@^3.3.0, chokidar@^3.3.1, chokidar@^3.4.1, chokidar@^3. optionalDependencies: fsevents "~2.1.2" +chokidar@^3.4.3: + version "3.5.1" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" + integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" + optionalDependencies: + fsevents "~2.3.1" + chownr@^1.1.1: version "1.1.4" resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" @@ -10399,15 +10151,6 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= -constant-case@^3.0.3: - version "3.0.3" - resolved "https://registry.npmjs.org/constant-case/-/constant-case-3.0.3.tgz#ac910a99caf3926ac5112f352e3af599d8c5fc0a" - integrity sha512-FXtsSnnrFYpzDmvwDGQW+l8XK3GV1coLyBN0eBz16ZUzGaZcT2ANVCJmLeuw2GQgxKHQIe9e0w2dzkSfaRlUmA== - dependencies: - no-case "^3.0.3" - tslib "^1.10.0" - upper-case "^2.0.1" - constant-case@^3.0.4: version "3.0.4" resolved "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz#3b84a9aeaf4cf31ec45e6bf5de91bdfb0589faf1" @@ -10624,6 +10367,13 @@ cors@^2.8.4, cors@^2.8.5: object-assign "^4" vary "^1" +cosmiconfig-toml-loader@1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/cosmiconfig-toml-loader/-/cosmiconfig-toml-loader-1.0.0.tgz#0681383651cceff918177debe9084c0d3769509b" + integrity sha512-H/2gurFWVi7xXvCyvsWRLCMekl4tITJcX0QEsDMpzxtuxDyM59xLatYNg4s/k9AA/HdtCYfj2su8mgA0GSDLDA== + dependencies: + "@iarna/toml" "^2.2.5" + cosmiconfig@6.0.0, cosmiconfig@^6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" @@ -11408,6 +11158,11 @@ date-fns@^2.0.0-alpha.27, date-fns@^2.16.1: resolved "https://registry.npmjs.org/date-fns/-/date-fns-2.18.0.tgz#08e50aee300ad0d2c5e054e3f0d10d8f9cdfe09e" integrity sha512-NYyAg4wRmGVU4miKq5ivRACOODdZRY3q5WLmOJSq8djyzftYphU7dTHLcEtLqEvfqMKQ0jVv91P4BAwIjsXIcw== +date-fns@^2.18.0: + version "2.19.0" + resolved "https://registry.npmjs.org/date-fns/-/date-fns-2.19.0.tgz#65193348635a28d5d916c43ec7ce6fbd145059e1" + integrity sha512-X3bf2iTPgCAQp9wvjOQytnf5vO5rESYRXlPIVcgSbtT5OTScPcsf9eZU+B/YIkKAtYr5WeCii58BgATrNitlWg== + dateformat@^3.0.0: version "3.0.3" resolved "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" @@ -11658,11 +11413,6 @@ dependency-graph@^0.11.0: resolved "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz#ac0ce7ed68a54da22165a85e97a01d53f5eb2e27" integrity sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg== -dependency-graph@^0.9.0: - version "0.9.0" - resolved "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.9.0.tgz#11aed7e203bc8b00f48356d92db27b265c445318" - integrity sha512-9YLIBURXj4DJMFALxXw9K3Y3rwb5Fk0X5/8ipCzaN84+gKxoHK43tVKRNakCQbiEx07E8Uwhuq21BpUagFhZ8w== - deprecated-decorator@^0.1.6: version "0.1.6" resolved "https://registry.npmjs.org/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz#00966317b7a12fe92f3cc831f7583af329b86c37" @@ -13864,6 +13614,11 @@ fsevents@^2.1.2, fsevents@~2.1.2: resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== +fsevents@~2.3.1: + version "2.3.2" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + fstream@^1.0.0, fstream@^1.0.12: version "1.0.12" resolved "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" @@ -13991,10 +13746,10 @@ generic-pool@2.4.3: resolved "https://registry.npmjs.org/generic-pool/-/generic-pool-2.4.3.tgz#780c36f69dfad05a5a045dd37be7adca11a4f6ff" integrity sha1-eAw29p360FpaBF3Te+etyhGk9v8= -gensync@^1.0.0-beta.1: - version "1.0.0-beta.1" - resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" - integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-caller-file@^1.0.1: version "1.0.3" @@ -14558,6 +14313,24 @@ graphql-config@^3.0.2: string-env-interpolation "1.0.1" tslib "^2.0.0" +graphql-config@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/graphql-config/-/graphql-config-3.2.0.tgz#3ec3a7e319792086b80e54db4b37372ad4a79a32" + integrity sha512-ygEKDeQNZKpm4137560n2oY3bGM0D5zyRsQVaJntKkufWdgPg6sb9/4J1zJW2y/yC1ortAbhNho09qmeJeLa9g== + dependencies: + "@endemolshinegroup/cosmiconfig-typescript-loader" "3.0.2" + "@graphql-tools/graphql-file-loader" "^6.0.0" + "@graphql-tools/json-file-loader" "^6.0.0" + "@graphql-tools/load" "^6.0.0" + "@graphql-tools/merge" "^6.0.0" + "@graphql-tools/url-loader" "^6.0.0" + "@graphql-tools/utils" "^6.0.0" + cosmiconfig "6.0.0" + cosmiconfig-toml-loader "1.0.0" + minimatch "3.0.4" + string-env-interpolation "1.0.1" + tslib "^2.0.0" + graphql-extensions@^0.12.8: version "0.12.8" resolved "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.12.8.tgz#9cdc2c43d8fe5e0f6c3177a004ac011da2a8aa0f" @@ -14567,7 +14340,7 @@ graphql-extensions@^0.12.8: apollo-server-env "^3.0.0" apollo-server-types "^0.6.3" -graphql-language-service-interface@^2.8.2: +graphql-language-service-interface@2.8.2, graphql-language-service-interface@^2.8.2: version "2.8.2" resolved "https://registry.npmjs.org/graphql-language-service-interface/-/graphql-language-service-interface-2.8.2.tgz#b3bb2aef7eaf0dff0b4ea419fa412c5f66fa268b" integrity sha512-otbOQmhgkAJU1QJgQkMztNku6SbJLu/uodoFOYOOtJsizTjrMs93vkYaHCcYnLA3oi1Goj27XcHjMnRCYQOZXQ== @@ -14577,7 +14350,7 @@ graphql-language-service-interface@^2.8.2: graphql-language-service-utils "^2.5.1" vscode-languageserver-types "^3.15.1" -graphql-language-service-parser@^1.9.0: +graphql-language-service-parser@1.9.0, graphql-language-service-parser@^1.9.0: version "1.9.0" resolved "https://registry.npmjs.org/graphql-language-service-parser/-/graphql-language-service-parser-1.9.0.tgz#79af21294119a0a7e81b6b994a1af36833bab724" integrity sha512-B5xPZLbBmIp0kHvpY1Z35I5DtPoDK9wGxQVRDIzcBaiIvAmlTrDvjo3bu7vKREdjFbYKvWNgrEWENuprMbF17Q== @@ -15099,6 +14872,17 @@ http-errors@1.7.2: statuses ">= 1.5.0 < 2" toidentifier "1.0.0" +http-errors@1.7.3, http-errors@~1.7.2: + version "1.7.3" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + http-errors@^1.7.3: version "1.8.0" resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz#75d1bbe497e1044f51e4ee9e704a62f28d336507" @@ -15120,17 +14904,6 @@ http-errors@~1.6.2: setprototypeof "1.1.0" statuses ">= 1.4.0 < 2" -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - "http-parser-js@>=0.4.0 <0.4.11": version "0.4.10" resolved "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4" @@ -16166,6 +15939,11 @@ is-unc-path@^1.0.0: dependencies: unc-path-regex "^0.1.2" +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + is-upper-case@^2.0.1: version "2.0.2" resolved "https://registry.npmjs.org/is-upper-case/-/is-upper-case-2.0.2.tgz#f1105ced1fe4de906a5f39553e7d3803fd804649" @@ -16742,19 +16520,7 @@ jest-snapshot@^26.6.2: pretty-format "^26.6.2" semver "^7.3.2" -jest-util@^26.1.0: - version "26.6.1" - resolved "https://registry.npmjs.org/jest-util/-/jest-util-26.6.1.tgz#4cc0d09ec57f28d12d053887eec5dc976a352e9b" - integrity sha512-xCLZUqVoqhquyPLuDXmH7ogceGctbW8SMyQVjD9o+1+NPWI7t0vO08udcFLVPLgKWcvc+zotaUv/RuaR6l8HIA== - dependencies: - "@jest/types" "^26.6.1" - "@types/node" "*" - chalk "^4.0.0" - graceful-fs "^4.2.4" - is-ci "^2.0.0" - micromatch "^4.0.2" - -jest-util@^26.6.2: +jest-util@^26.1.0, jest-util@^26.6.2: version "26.6.2" resolved "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz#907535dbe4d5a6cb4c47ac9b926f6af29576cbc1" integrity sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q== @@ -17894,6 +17660,11 @@ lodash.flattendeep@^4.0.0: resolved "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= +lodash.get@^4: + version "4.4.2" + resolved "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= + lodash.includes@^4.3.0: version "4.3.0" resolved "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" @@ -17929,7 +17700,7 @@ lodash.isstring@^4.0.1: resolved "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= -lodash.memoize@4.x, lodash.memoize@^4.1.2: +lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= @@ -17989,7 +17760,7 @@ lodash@4.17.15: resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -lodash@^4.0.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@~4.17.20, lodash@~4.17.4: +lodash@4.x, lodash@^4.0.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@~4.17.20, lodash@~4.17.4: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -18008,12 +17779,13 @@ log-symbols@^3.0.0: dependencies: chalk "^2.4.2" -log-symbols@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" - integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== +log-symbols@^4.0.0, log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== dependencies: - chalk "^4.0.0" + chalk "^4.1.0" + is-unicode-supported "^0.1.0" log-update@^2.3.0: version "2.3.0" @@ -18197,7 +17969,7 @@ make-dir@^3.0.0, make-dir@^3.0.2: dependencies: semver "^6.0.0" -make-error@1.x, make-error@^1.1.1, make-error@^1.3.6: +make-error@1.x, make-error@^1, make-error@^1.1.1, make-error@^1.3.6: version "1.3.6" resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -19882,6 +19654,13 @@ obuf@^1.0.0, obuf@^1.1.2: resolved "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== +octokit-plugin-create-pull-request@^3.9.3: + version "3.9.3" + resolved "https://registry.npmjs.org/octokit-plugin-create-pull-request/-/octokit-plugin-create-pull-request-3.9.3.tgz#f99f53907ac322a3494cc970514a023d7b659e2b" + integrity sha512-lTyNnCRoT4IvCQx2Cb4eFMqg8aIpsaDd59MNwf4OPnWAJM7hT6g7RW/icImvAzZLR4t5ENSLNzWarv2XqLL+Lg== + dependencies: + "@octokit/types" "^6.8.2" + oidc-token-hash@^5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.0.tgz#acdfb1f4310f58e64d5d74a4e8671a426986e888" @@ -19996,16 +19775,17 @@ optionator@^0.9.1: word-wrap "^1.2.3" ora@^5.3.0: - version "5.3.0" - resolved "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz#fb832899d3a1372fe71c8b2c534bbfe74961bb6f" - integrity sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g== + version "5.4.0" + resolved "https://registry.npmjs.org/ora/-/ora-5.4.0.tgz#42eda4855835b9cd14d33864c97a3c95a3f56bf4" + integrity sha512-1StwyXQGoU6gdjYkyVcqOLnVlbKj+6yPNNOxJVgpt9t4eksKjiriiHuxktLYkgllwk+D6MbC4ihH84L1udRXPg== dependencies: - bl "^4.0.3" + bl "^4.1.0" chalk "^4.1.0" cli-cursor "^3.1.0" cli-spinners "^2.5.0" is-interactive "^1.0.0" - log-symbols "^4.0.0" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" strip-ansi "^6.0.0" wcwidth "^1.0.1" @@ -20755,10 +20535,10 @@ pg-pool@^3.2.2: resolved "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.2.tgz#a560e433443ed4ad946b84d774b3f22452694dff" integrity sha512-ORJoFxAlmmros8igi608iVEbQNNZlp89diFVx6yV5v+ehmpMY9sK6QgpmgoXbmkNaBAx8cOOZh9g80kJv1ooyA== -pg-protocol@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.3.0.tgz#3c8fb7ca34dbbfcc42776ce34ac5f537d6e34770" - integrity sha512-64/bYByMrhWULUaCd+6/72c9PMWhiVFs3EVxl9Ct6a3v/U8+rKgqP2w+kKg/BIGgMJyB+Bk/eNivT32Al+Jghw== +pg-protocol@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.4.0.tgz#43a71a92f6fe3ac559952555aa3335c8cb4908be" + integrity sha512-El+aXWcwG/8wuFICMQjM5ZSAm6OWiJicFdNYo+VY3QP+8vI4SvLIWVe51PppTzMhikUJR+PsyIFKqfdXPz/yxA== pg-types@1.*: version "1.13.0" @@ -20797,15 +20577,15 @@ pg@^6.1.0: semver "4.3.2" pg@^8.3.0: - version "8.4.2" - resolved "https://registry.npmjs.org/pg/-/pg-8.4.2.tgz#2aa58166a23391e91d56a7ea57c6d99931c0642a" - integrity sha512-E9FlUrrc7w3+sbRmL1CSw99vifACzB2TjhMM9J5w9D1LIg+6un0jKkpHS1EQf2CWhKhec2bhrBLVMmUBDbjPRQ== + version "8.5.1" + resolved "https://registry.npmjs.org/pg/-/pg-8.5.1.tgz#34dcb15f6db4a29c702bf5031ef2e1e25a06a120" + integrity sha512-9wm3yX9lCfjvA98ybCyw2pADUivyNWT/yIP4ZcDVpMN0og70BUWYEGXPCTAQdGTAqnytfRADb7NERrY1qxhIqw== dependencies: buffer-writer "2.0.0" packet-reader "1.0.0" pg-connection-string "^2.4.0" pg-pool "^3.2.2" - pg-protocol "^1.3.0" + pg-protocol "^1.4.0" pg-types "^2.1.0" pgpass "1.x" @@ -21921,6 +21701,16 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" +raw-body@^2.4.1: + version "2.4.1" + resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c" + integrity sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA== + dependencies: + bytes "3.1.0" + http-errors "1.7.3" + iconv-lite "0.4.24" + unpipe "1.0.0" + raw-loader@^4.0.1: version "4.0.2" resolved "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz#1aac6b7d1ad1501e66efdac1522c73e59a584eb6" @@ -22481,7 +22271,7 @@ react-use@^15.3.3, react-use@^15.3.6: ts-easing "^0.2.0" tslib "^2.0.0" -react-use@^17.1.0: +react-use@^17.2.1: version "17.2.1" resolved "https://registry.npmjs.org/react-use/-/react-use-17.2.1.tgz#c81e12544115ed049c7deba1e3bb3d977dfee9b8" integrity sha512-9r51/at7/Nr/nEP4CsHz+pl800EAqhIY9R6O68m68kaWc8slDAfx1UrIedQqpsb4ImddFYb+6hF1i5Vj4u4Cnw== @@ -23185,7 +22975,7 @@ resolve-url@^0.2.1: resolved "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.19.0, resolve@^1.3.2, resolve@^1.9.0: +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.19.0, resolve@^1.9.0: version "1.20.0" resolved "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -25576,18 +25366,16 @@ ts-invariant@^0.4.0: tslib "^1.9.3" ts-jest@^26.4.3: - version "26.4.3" - resolved "https://registry.npmjs.org/ts-jest/-/ts-jest-26.4.3.tgz#d153a616033e7ec8544b97ddbe2638cbe38d53db" - integrity sha512-pFDkOKFGY+nL9v5pkhm+BIFpoAuno96ff7GMnIYr/3L6slFOS365SI0fGEVYx2RKGji5M2elxhWjDMPVcOCdSw== + version "26.5.4" + resolved "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.4.tgz#207f4c114812a9c6d5746dd4d1cdf899eafc9686" + integrity sha512-I5Qsddo+VTm94SukBJ4cPimOoFZsYTeElR2xy6H2TOVs+NsvgYglW8KuQgKoApOKuaU/Ix/vrF9ebFZlb5D2Pg== dependencies: - "@jest/create-cache-key-function" "^26.5.0" - "@types/jest" "26.x" bs-logger "0.x" buffer-from "1.x" fast-json-stable-stringify "2.x" jest-util "^26.1.0" json5 "2.x" - lodash.memoize "4.x" + lodash "4.x" make-error "1.x" mkdirp "1.x" semver "7.x" @@ -25620,7 +25408,7 @@ ts-node@^8.10.2, ts-node@^8.6.2: source-map-support "^0.5.17" yn "3.1.1" -ts-node@^9.1.1: +ts-node@^9, ts-node@^9.1.1: version "9.1.1" resolved "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d" integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg== @@ -25662,7 +25450,7 @@ 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.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@~2.1.0: +tslib@^2, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@~2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== @@ -27159,16 +26947,11 @@ yaml@^1.10.0, yaml@^1.7.2, yaml@^1.9.2: resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== -yargs-parser@20.2.4, yargs-parser@^20.2.2, yargs-parser@^20.2.3: +yargs-parser@20.2.4, yargs-parser@20.x, yargs-parser@^20.2.2, yargs-parser@^20.2.3: version "20.2.4" resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== -yargs-parser@20.x: - version "20.2.3" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.3.tgz#92419ba867b858c868acf8bae9bf74af0dd0ce26" - integrity sha512-emOFRT9WVHw03QSvN5qor9QQT9+sw5vwxfYweivSMHTcAXPefwVae2FjO7JJjj8hCE4CzPOPeFM83VwT29HCww== - yargs-parser@^13.1.2: version "13.1.2" resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" @@ -27226,7 +27009,7 @@ 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.2.0: +yargs@^16.0.3, yargs@^16.1.1, 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==