+ +### 1. Open `app-config.yaml` and change it as follows _from:_ @@ -75,23 +83,229 @@ auth: $env: AUTH_GITHUB_CLIENT_ID clientSecret: $env: AUTH_GITHUB_CLIENT_SECRET - ## uncomment the following three lines if using enterprise + ## uncomment the following two lines if using enterprise # enterpriseInstanceUrl: # $env: AUTH_GITHUB_ENTERPRISE_INSTANCE_URL ``` -2. Set environment variables in whatever fashion is easiest for you. I chose to - add mine to my `.zshrc` profile. +### 2. Generate a GitHub client ID and secret + +- Log into http://github.com +- Navigate to (Settings > Developer Settings > OAuth Apps > New OAuth + App)[https://github.com/settings/applications/new] +- Set Homepage URL = `http://localhost:3000` +- Set Callback URL = `http://localhost:7000/api/auth/github` +- Click [Register application] +- On the next page, copy and paste your new Client ID and Client Secret to + environment variables defined in the `app-config.yaml` file, + `AUTH_GITHUB_CLIENT_ID` & `AUTH_GITHUB_CLIENT_SECRET` + +
++ +### 1. Open `app-config.yaml` and change it as follows + +_from:_ + +```yaml +auth: + providers: {} +``` + +_to:_ + +```yaml +auth: + providers: + gitlab: + development: + clientId: + $env: AUTH_GITLAB_CLIENT_ID + clientSecret: + $env: AUTH_GITLAB_CLIENT_SECRET + audience: https://gitlab.com # Or your self-hosted GitLab instance URL +``` + +### 2. Generate a GitLab Application client ID and secret + +- Log into GitLab +- Navigate to (Profile > Settings > + Applications)[https://gitlab.com/-/profile/applications] +- Name your application +- Set Callback URL = `http://localhost:7000/api/auth/gitlab/handler/frame` +- Select the following values: + - `read_user` (Read the authenticated user's personal information) + - `read_repository` (Allows read-only access to the repository) + - `write_repository` (Allows read-write access to the repository) + - `openid` (Authenticate using OpenID Connect) + - `profile` (Allows read-only access to the user's personal information using + OpenID Connect) + - `email` (Allows read-only access to the user's primary email address using + OpenID Connect) +- Click [Save application] +- On the next page, copy and paste your new Application ID and Secret to + environment variables defined in the `app-config.yaml` file, + `AUTH_GITLAB_CLIENT_ID` & `AUTH_GITLAB_CLIENT_SECRET` + +
++ +### 1. Open `app-config.yaml` and change it as follows + +_from:_ + +```yaml +auth: + providers: {} +``` + +_to:_ + +```yaml +auth: + providers: + google: + development: + clientId: + $env: AUTH_GOOGLE_CLIENT_ID + clientSecret: + $env: AUTH_GOOGLE_CLIENT_SECRET +``` + +### 2. Generate Google Credentials in Google Cloud console + +- Log into https://console.cloud.google.com +- Select or create a new project from the dropdown on the top bar +- Navigate to (APIs & Services > + Credentials)[https://console.cloud.google.com/apis/credentials] +- Click Create Credentials and select [OAuth client ID] +- Select Web Application as the application type +- Add new Authorised JavaScript origin = `http://localhost:3000` +- Add new Authorised redirect URI = + `http://localhost:7000/api/auth/google/handler/frame` +- Click [Save application] +- Google should display a modal with your Client ID and Secret. Copy and paste + those to environment variables defined in the `app-config.yaml` file, + `AUTH_GOOGLE_CLIENT_ID` & `AUTH_GOOGLE_CLIENT_SECRET` + +
++ +### 1. Open `app-config.yaml` and change it as follows + +_from:_ + +```yaml +auth: + providers: {} +``` + +_to:_ + +```yaml +auth: + providers: + microsoft: + development: + clientId: + $env: AUTH_MICROSOFT_CLIENT_ID + clientSecret: + $env: AUTH_MICROSOFT_CLIENT_SECRET + tenantId: + $env: AUTH_MICROSOFT_TENANT_ID +``` + +### 2. Create a Microsoft App Registration in Microsoft Portal + +- Log into https://portal.azure.com +- Navigate to (Azure Active Directory > App + Registrations)[https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredApps] +- Create a New Registration +- Add new Redirect URI = `http://localhost:3000` +- Add new Authorised redirect URI = + `http://localhost:7000/api/auth/microsoft/handler/frame` +- Click [Save application] +- Set environment variable `AUTH_MICROSOFT_CLIENT_ID` from + `Application (client) Id` displayed on the directory page +- Set environment variable `AUTH_MICROSOFT_TENANT_ID` from + `Directory (tenant) ID` displayed on the directory page +- Navigate to Certificates & Secrets section and click [Create a new secret] +- Set environment variable `AUTH_MICROSOFT_CLIENT_SECRET` from the `value` field + created. + +
++ +### 1. Open `app-config.yaml` and change it as follows + +_from:_ + +```yaml +auth: + providers: {} +``` + +_to:_ + +```yaml +auth: + providers: + auth0: + development: + clientId: + $env: AUTH_AUTH0_CLIENT_ID + clientSecret: + $env: AUTH_AUTH0_CLIENT_SECRET + domain: + $env: AUTH_AUTH0_DOMAIN_ID +``` + +### 2. Create an Auth0 application in the Auth0 management console + +- Log into https://manage.auth0.com/dashboard/ +- Navigate to Applications +- Create a New Application + - Select Single Page Web Application +- Go to Settings tab +- Add new line to Allowed Callback URLs = + `http://localhost:7000/api/auth/auth0/handler/frame` +- Click [Save Changes] +- Set environment variables displayed on the Basic Information page + - `AUTH_AUTH0_CLIENT_ID` from `Client ID` displayed on Auth0 application page + - `AUTH_AUTH0_CLIENT_SECRET` from `Client Secret` displayed on Auth0 + application page + - `AUTH_AUTH0_DOMAIN_ID` from `Domain` displayed on Auth0 application page + +
+/conversions
- const apiUrl = url.replace(/(?:\/[^\/]+){3}$/, '');
+ ).then(({ data }) => {
resolve({
name: data.name,
slug: data.slug,
appId: data.id,
- apiUrl,
webhookUrl: this.webhookUrl,
clientId: data.client_id,
clientSecret: data.client_secret,
diff --git a/packages/cli/src/commands/create-github-app/index.ts b/packages/cli/src/commands/create-github-app/index.ts
index b8d232674e..cd9e8dbe09 100644
--- a/packages/cli/src/commands/create-github-app/index.ts
+++ b/packages/cli/src/commands/create-github-app/index.ts
@@ -26,9 +26,14 @@ import { GithubCreateAppServer } from './GithubCreateAppServer';
export default async (org: string) => {
const { slug, name, ...config } = await GithubCreateAppServer.run({ org });
- const fileName = `github-app-${slug}.yaml`;
+ const fileName = `github-app-${slug}-credentials.yaml`;
const content = `# Name: ${name}\n${stringifyYaml(config)}`;
await fs.writeFile(paths.resolveTargetRoot(fileName), content);
console.log(`GitHub App configuration written to ${chalk.cyan(fileName)}`);
+ console.log(
+ chalk.yellow(
+ 'This file contains sensitive credentials, it should not be committed to version control and handled with care!',
+ ),
+ );
// TODO: log instructions on how to use the newly created app configuration.
};
diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md
index bb13447f94..b9ea855c83 100644
--- a/packages/core/CHANGELOG.md
+++ b/packages/core/CHANGELOG.md
@@ -1,5 +1,11 @@
# @backstage/core
+## 0.4.4
+
+### Patch Changes
+
+- 265a7ab30: Fix issue where `SidebarItem` with `onClick` and without `to` renders an inaccessible div. It now renders a button.
+
## 0.4.3
### Patch Changes
diff --git a/packages/core/package.json b/packages/core/package.json
index b84eb4ff7b..d86ea3b240 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/core",
"description": "Core API used by Backstage plugins and apps",
- "version": "0.4.3",
+ "version": "0.4.4",
"private": false,
"publishConfig": {
"access": "public",
@@ -65,7 +65,7 @@
"zen-observable": "^0.8.15"
},
"devDependencies": {
- "@backstage/cli": "^0.4.4",
+ "@backstage/cli": "^0.4.6",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^10.4.1",
diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md
index 5c9b44fd07..8dba8d8fc1 100644
--- a/packages/create-app/CHANGELOG.md
+++ b/packages/create-app/CHANGELOG.md
@@ -1,5 +1,17 @@
# @backstage/create-app
+## 0.3.5
+
+### Patch Changes
+
+- 94fdf4955: Get rid of all usages of @octokit/types, and bump the rest of the octokit dependencies to the latest version
+- cc068c0d6: Bump the gitbeaker dependencies to 28.x.
+
+ To update your own installation, go through the `package.json` files of all of
+ your packages, and ensure that all dependencies on `@gitbeaker/node` or
+ `@gitbeaker/core` are at version `^28.0.2`. Then run `yarn install` at the root
+ of your repo.
+
## 0.3.4
### Patch Changes
diff --git a/packages/create-app/package.json b/packages/create-app/package.json
index 9dec615bb7..0c703bcdac 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.4",
+ "version": "0.3.5",
"private": false,
"publishConfig": {
"access": "public"
@@ -37,29 +37,29 @@
"recursive-readdir": "^2.2.2"
},
"devDependencies": {
- "@backstage/backend-common": "^0.4.2",
- "@backstage/catalog-model": "^0.6.0",
- "@backstage/cli": "^0.4.5",
+ "@backstage/backend-common": "^0.4.3",
+ "@backstage/catalog-model": "^0.6.1",
+ "@backstage/cli": "^0.4.6",
"@backstage/config": "^0.1.2",
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/plugin-api-docs": "^0.4.2",
"@backstage/plugin-app-backend": "^0.3.3",
- "@backstage/plugin-auth-backend": "^0.2.9",
- "@backstage/plugin-catalog": "^0.2.10",
- "@backstage/plugin-catalog-backend": "^0.5.2",
- "@backstage/plugin-catalog-import": "^0.3.3",
+ "@backstage/plugin-auth-backend": "^0.2.10",
+ "@backstage/plugin-catalog": "^0.2.11",
+ "@backstage/plugin-catalog-backend": "^0.5.3",
+ "@backstage/plugin-catalog-import": "^0.3.4",
"@backstage/plugin-circleci": "^0.2.5",
"@backstage/plugin-explore": "^0.2.2",
- "@backstage/plugin-github-actions": "^0.2.6",
- "@backstage/plugin-lighthouse": "^0.2.6",
+ "@backstage/plugin-github-actions": "^0.2.7",
+ "@backstage/plugin-lighthouse": "^0.2.7",
"@backstage/plugin-proxy-backend": "^0.2.3",
"@backstage/plugin-rollbar-backend": "^0.1.6",
"@backstage/plugin-scaffolder": "^0.3.6",
"@backstage/plugin-search": "^0.2.5",
- "@backstage/plugin-scaffolder-backend": "^0.4.0",
+ "@backstage/plugin-scaffolder-backend": "^0.4.1",
"@backstage/plugin-tech-radar": "^0.3.2",
- "@backstage/plugin-techdocs": "^0.5.2",
- "@backstage/plugin-techdocs-backend": "^0.5.2",
+ "@backstage/plugin-techdocs": "^0.5.3",
+ "@backstage/plugin-techdocs-backend": "^0.5.3",
"@backstage/plugin-user-settings": "^0.2.3",
"@backstage/test-utils": "^0.1.6",
"@backstage/theme": "^0.2.2",
diff --git a/packages/create-app/templates/default-app/.gitignore.hbs b/packages/create-app/templates/default-app/.gitignore.hbs
index 5f5cc739f4..4adebc5adc 100644
--- a/packages/create-app/templates/default-app/.gitignore.hbs
+++ b/packages/create-app/templates/default-app/.gitignore.hbs
@@ -30,4 +30,7 @@ dist-types
site
# Local configuration files
-*.local.yaml
\ No newline at end of file
+*.local.yaml
+
+# Sensitive credentials
+*-credentials.yaml
diff --git a/packages/create-app/templates/default-app/app-config.yaml.hbs b/packages/create-app/templates/default-app/app-config.yaml.hbs
index 90f272270a..d253102f71 100644
--- a/packages/create-app/templates/default-app/app-config.yaml.hbs
+++ b/packages/create-app/templates/default-app/app-config.yaml.hbs
@@ -88,23 +88,23 @@ catalog:
target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/all-apis.yaml
# Backstage example templates
- - type: github
+ - type: url
target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml
rules:
- allow: [Template]
- - type: github
+ - type: url
target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/springboot-grpc-template/template.yaml
rules:
- allow: [Template]
- - type: github
+ - type: url
target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml
rules:
- allow: [Template]
- - type: github
+ - type: url
target: https://github.com/spotify/cookiecutter-golang/blob/master/template.yaml
rules:
- allow: [Template]
- - type: github
+ - type: url
target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/docs-template/template.yaml
rules:
- allow: [Template]
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 693e66e0c6..13880f9ee3 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
@@ -15,6 +15,7 @@ import { Router as DocsRouter } from '@backstage/plugin-techdocs';
import { Router as ImportComponentRouter } from '@backstage/plugin-catalog-import';
import { Router as TechRadarRouter } from '@backstage/plugin-tech-radar';
import { SearchPage as SearchRouter } from '@backstage/plugin-search';
+import { Router as SettingsRouter } from '@backstage/plugin-user-settings';
import { EntityPage } from './components/catalog/EntityPage';
@@ -59,6 +60,7 @@ const App = () => (
path="/search"
element={ }
/>
+ } />
{deprecatedAppRoutes}
diff --git a/packages/create-app/templates/default-app/packages/app/src/plugins.ts b/packages/create-app/templates/default-app/packages/app/src/plugins.ts
index d3c9d6e2f3..28b42d5be2 100644
--- a/packages/create-app/templates/default-app/packages/app/src/plugins.ts
+++ b/packages/create-app/templates/default-app/packages/app/src/plugins.ts
@@ -6,3 +6,5 @@ export { plugin as GithubActions } from '@backstage/plugin-github-actions';
export { plugin as ScaffolderPlugin } from '@backstage/plugin-scaffolder';
export { plugin as TechDocsPlugin } from '@backstage/plugin-techdocs';
export { plugin as TechRadar } from '@backstage/plugin-tech-radar';
+export { plugin as UserSettings } from '@backstage/plugin-user-settings';
+
diff --git a/packages/create-app/templates/default-app/packages/backend/package.json.hbs b/packages/create-app/templates/default-app/packages/backend/package.json.hbs
index 7b7429d838..3fed72f07b 100644
--- a/packages/create-app/templates/default-app/packages/backend/package.json.hbs
+++ b/packages/create-app/templates/default-app/packages/backend/package.json.hbs
@@ -45,8 +45,7 @@
"@backstage/cli": "^{{version '@backstage/cli'}}",
"@types/dockerode": "^3.2.1",
"@types/express": "^4.17.6",
- "@types/express-serve-static-core": "^4.17.5",
- "@types/helmet": "^0.0.47"
+ "@types/express-serve-static-core": "^4.17.5"
},
"files": [
"dist"
diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/scaffolder.ts b/packages/create-app/templates/default-app/packages/backend/src/plugins/scaffolder.ts
index 2dc69feb45..196d48ec78 100644
--- a/packages/create-app/templates/default-app/packages/backend/src/plugins/scaffolder.ts
+++ b/packages/create-app/templates/default-app/packages/backend/src/plugins/scaffolder.ts
@@ -1,21 +1,13 @@
import {
CookieCutter,
createRouter,
- FilePreparer,
- GithubPreparer,
- GitlabPreparer,
Preparers,
Publishers,
- GithubPublisher,
- GitlabPublisher,
CreateReactAppTemplater,
Templaters,
- RepoVisibilityOptions,
CatalogEntityClient,
} from '@backstage/plugin-scaffolder-backend';
import { SingleHostDiscovery } from '@backstage/backend-common';
-import { Octokit } from '@octokit/rest';
-import { Gitlab } from '@gitbeaker/node';
import type { PluginEnvironment } from '../types';
import Docker from 'dockerode';
@@ -29,74 +21,8 @@ export default async function createPlugin({
templaters.register('cookiecutter', cookiecutterTemplater);
templaters.register('cra', craTemplater);
- const filePreparer = new FilePreparer();
- const githubPreparer = new GithubPreparer();
- const gitlabPreparer = new GitlabPreparer(config);
- const preparers = new Preparers();
-
- preparers.register('file', filePreparer);
- preparers.register('github', githubPreparer);
- preparers.register('gitlab', gitlabPreparer);
- preparers.register('gitlab/api', gitlabPreparer);
-
- const publishers = new Publishers();
-
- const githubConfig = config.getOptionalConfig('scaffolder.github');
-
- if (githubConfig) {
- try {
- const repoVisibility = githubConfig.getString(
- 'visibility',
- ) as RepoVisibilityOptions;
-
- const githubToken = githubConfig.getString('token');
- const githubHost = githubConfig.getOptionalString('host');
- const githubClient = new Octokit({ auth: githubToken, baseUrl: githubHost });
- const githubPublisher = new GithubPublisher({
- client: githubClient,
- token: githubToken,
- repoVisibility,
- });
- publishers.register('file', githubPublisher);
- publishers.register('github', githubPublisher);
- } catch (e) {
- const providerName = 'github';
- if (process.env.NODE_ENV !== 'development') {
- throw new Error(
- `Failed to initialize ${providerName} scaffolding provider, ${e.message}`,
- );
- }
-
- logger.warn(
- `Skipping ${providerName} scaffolding provider, ${e.message}`,
- );
- }
- }
-
- const gitLabConfig = config.getOptionalConfig('scaffolder.gitlab.api');
- if (gitLabConfig) {
- try {
- const gitLabToken = gitLabConfig.getString('token');
- const gitLabClient = new Gitlab({
- host: gitLabConfig.getOptionalString('baseUrl'),
- token: gitLabToken,
- });
- const gitLabPublisher = new GitlabPublisher(gitLabClient, gitLabToken);
- publishers.register('gitlab', gitLabPublisher);
- publishers.register('gitlab/api', gitLabPublisher);
- } catch (e) {
- const providerName = 'gitlab';
- if (process.env.NODE_ENV !== 'development') {
- throw new Error(
- `Failed to initialize ${providerName} scaffolding provider, ${e.message}`,
- );
- }
-
- logger.warn(
- `Skipping ${providerName} scaffolding provider, ${e.message}`,
- );
- }
- }
+ const preparers = await Preparers.fromConfig(config, { logger });
+ const publishers = await Publishers.fromConfig(config, { logger });
const dockerClient = new Docker();
diff --git a/packages/e2e-test/src/lib/helpers.ts b/packages/e2e-test/src/lib/helpers.ts
index 0b05eaf4b4..190ff403d9 100644
--- a/packages/e2e-test/src/lib/helpers.ts
+++ b/packages/e2e-test/src/lib/helpers.ts
@@ -152,7 +152,7 @@ export async function waitForPageWithText(
// The page may not be fully loaded and hence we need to retry.
let findTextAttempts = 0;
- const escapedText = text.replace(/"/g, '\\"');
+ const escapedText = text.replace(/"|\\/g, '\\$&');
for (;;) {
try {
browser.assert.evaluate(
diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md
index 10b30a11ad..2310c7d020 100644
--- a/packages/integration/CHANGELOG.md
+++ b/packages/integration/CHANGELOG.md
@@ -1,5 +1,11 @@
# @backstage/integration
+## 0.2.0
+
+### Minor Changes
+
+- 466354aaa: Build out the `ScmIntegrations` class, as well as the individual `*Integration` classes
+
## 0.1.5
### Patch Changes
diff --git a/packages/integration/config.d.ts b/packages/integration/config.d.ts
index a03a07409b..6a9fd62995 100644
--- a/packages/integration/config.d.ts
+++ b/packages/integration/config.d.ts
@@ -35,6 +35,16 @@ export interface Config {
apiBaseUrl?: string;
/** @visibility frontend */
rawBaseUrl?: string;
+ apps?: Array<{
+ appId: number;
+ /** @visiblity secret */
+ privateKey: string;
+ /** @visiblity secret */
+ webhookSecret: string;
+ clientId: string;
+ /** @visiblity secret */
+ clientSecret: string;
+ }>;
}>;
gitlab?: Array<{
diff --git a/packages/integration/package.json b/packages/integration/package.json
index 258c5c61c6..8a8804c8e5 100644
--- a/packages/integration/package.json
+++ b/packages/integration/package.json
@@ -1,6 +1,6 @@
{
"name": "@backstage/integration",
- "version": "0.1.5",
+ "version": "0.2.0",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -31,12 +31,16 @@
"dependencies": {
"@backstage/config": "^0.1.2",
"cross-fetch": "^3.0.6",
- "git-url-parse": "^11.4.3"
+ "git-url-parse": "^11.4.3",
+ "@octokit/rest": "^18.0.12",
+ "@octokit/auth-app": "^2.10.5",
+ "luxon": "^1.25.0"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/test-utils": "^0.1.5",
"@types/jest": "^26.0.7",
+ "@types/luxon": "^1.25.0",
"msw": "^0.21.2"
},
"files": [
diff --git a/packages/integration/src/github/GithubCredentialsProvider.test.ts b/packages/integration/src/github/GithubCredentialsProvider.test.ts
new file mode 100644
index 0000000000..f708f75184
--- /dev/null
+++ b/packages/integration/src/github/GithubCredentialsProvider.test.ts
@@ -0,0 +1,265 @@
+/*
+ * 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.
+ */
+
+const octokit = {
+ apps: {
+ listInstallations: jest.fn(),
+ createInstallationAccessToken: jest.fn(),
+ },
+};
+
+jest.doMock('@octokit/rest', () => {
+ class Octokit {
+ constructor() {
+ return octokit;
+ }
+ }
+ return { Octokit };
+});
+
+import { GithubCredentialsProvider } from './GithubCredentialsProvider';
+import { RestEndpointMethodTypes } from '@octokit/rest';
+import { DateTime } from 'luxon';
+
+const github = GithubCredentialsProvider.create({
+ host: 'github.com',
+ apps: [
+ {
+ appId: 1,
+ privateKey: 'privateKey',
+ webhookSecret: '123',
+ clientId: 'CLIENT_ID',
+ clientSecret: 'CLIENT_SECRET',
+ },
+ ],
+ token: 'hardcoded_token',
+});
+
+describe('GithubCredentialsProvider tests', () => {
+ beforeEach(() => {
+ jest.resetAllMocks();
+ });
+ it('create repository specific tokens', async () => {
+ octokit.apps.listInstallations.mockResolvedValueOnce({
+ headers: {
+ etag: '123',
+ },
+ data: [
+ {
+ id: 1,
+ repository_selection: 'selected',
+ account: null,
+ },
+ {
+ id: 2,
+ repository_selection: 'selected',
+ account: {
+ login: 'backstage',
+ },
+ },
+ ],
+ } as RestEndpointMethodTypes['apps']['listInstallations']['response']);
+ octokit.apps.listInstallations.mockRejectedValue({ status: 304 });
+
+ octokit.apps.createInstallationAccessToken.mockResolvedValueOnce({
+ data: {
+ expires_at: DateTime.local().plus({ hour: 1 }).toString(),
+ token: 'secret_token',
+ },
+ } as RestEndpointMethodTypes['apps']['createInstallationAccessToken']['response']);
+
+ const { token, headers } = await github.getCredentials({
+ url: 'https://github.com/backstage/foobar',
+ });
+ const { token: accessToken2 } = await github.getCredentials({
+ url: 'https://github.com/backstage/foobar',
+ });
+
+ expect(token).toEqual('secret_token');
+ expect(token).toEqual(accessToken2);
+ expect(headers).toEqual({ Authorization: 'Bearer secret_token' });
+
+ // fallback to the configured token if no application is matching
+ await expect(
+ github.getCredentials({
+ url: 'https://github.com/404/foobar',
+ }),
+ ).resolves.toEqual({
+ headers: {
+ Authorization: 'Bearer hardcoded_token',
+ },
+ token: 'hardcoded_token',
+ });
+ });
+
+ it('creates tokens for an organization', async () => {
+ octokit.apps.listInstallations.mockResolvedValueOnce({
+ headers: {
+ etag: '123',
+ },
+ data: [
+ {
+ id: 1,
+ repository_selection: 'all',
+ account: {
+ login: 'backstage',
+ },
+ },
+ ],
+ } as RestEndpointMethodTypes['apps']['listInstallations']['response']);
+ octokit.apps.listInstallations.mockRejectedValue({ status: 304 });
+
+ octokit.apps.createInstallationAccessToken.mockResolvedValueOnce({
+ data: {
+ expires_at: DateTime.local().plus({ hour: 1 }).toString(),
+ token: 'secret_token',
+ },
+ } as RestEndpointMethodTypes['apps']['createInstallationAccessToken']['response']);
+
+ const { token, headers } = await github.getCredentials({
+ url: 'https://github.com/backstage',
+ });
+ const { token: accessToken2 } = await github.getCredentials({
+ url: 'https://github.com/backstage',
+ });
+
+ expect(headers).toEqual({ Authorization: 'Bearer secret_token' });
+ expect(token).toEqual('secret_token');
+ expect(token).toEqual(accessToken2);
+ });
+
+ it('should fail to issue tokens for an organization when the app is installed for a single repo', async () => {
+ octokit.apps.listInstallations.mockResolvedValueOnce({
+ headers: {
+ etag: '123',
+ },
+ data: [
+ {
+ id: 1,
+ repository_selection: 'selected',
+ account: {
+ login: 'backstage',
+ },
+ },
+ ],
+ } as RestEndpointMethodTypes['apps']['listInstallations']['response']);
+ octokit.apps.listInstallations.mockRejectedValue({ status: 304 });
+
+ octokit.apps.createInstallationAccessToken.mockResolvedValueOnce({
+ data: {
+ expires_at: DateTime.local().plus({ hour: 1 }).toString(),
+ token: 'secret_token',
+ },
+ } as RestEndpointMethodTypes['apps']['createInstallationAccessToken']['response']);
+
+ await expect(
+ github.getCredentials({
+ url: 'https://github.com/backstage',
+ }),
+ ).rejects.toThrow(
+ 'The Backstage GitHub application used in the backstage organization must be installed for the entire organization to be able to issue credentials without a specified repository.',
+ );
+ });
+
+ it('should throw if the app is suspended', async () => {
+ octokit.apps.listInstallations.mockResolvedValueOnce({
+ headers: {
+ etag: '123',
+ },
+ data: [
+ {
+ id: 1,
+ suspended_by: {
+ login: 'admin',
+ },
+ repository_selection: 'all',
+ account: {
+ login: 'backstage',
+ },
+ },
+ ],
+ } as RestEndpointMethodTypes['apps']['listInstallations']['response']);
+ octokit.apps.listInstallations.mockRejectedValue({ status: 304 });
+
+ await expect(
+ github.getCredentials({
+ url: 'https://github.com/backstage',
+ }),
+ ).rejects.toThrow('The GitHub application for backstage is suspended');
+ });
+
+ it('should return the default token when the call to github return a status that is not recognized', async () => {
+ octokit.apps.listInstallations.mockRejectedValue({
+ status: 404,
+ message: 'NotFound',
+ });
+
+ await expect(
+ github.getCredentials({
+ url: 'https://github.com/backstage',
+ }),
+ ).rejects.toEqual({ status: 404, message: 'NotFound' });
+ });
+
+ it('should return the default token if no app is configured', async () => {
+ const github = GithubCredentialsProvider.create({
+ host: 'github.com',
+ apps: [],
+ token: 'fallback_token',
+ });
+
+ await expect(
+ github.getCredentials({
+ url: 'https://github.com/404/foobar',
+ }),
+ ).resolves.toEqual(expect.objectContaining({ token: 'fallback_token' }));
+ });
+
+ it('should return the configured token if listing installations throws', async () => {
+ const github = GithubCredentialsProvider.create({
+ host: 'github.com',
+ apps: [
+ {
+ appId: 1,
+ privateKey: 'privateKey',
+ webhookSecret: '123',
+ clientId: 'CLIENT_ID',
+ clientSecret: 'CLIENT_SECRET',
+ },
+ ],
+ token: 'hardcoded_token',
+ });
+ octokit.apps.listInstallations.mockRejectedValue({ status: 304 });
+
+ await expect(
+ github.getCredentials({
+ url: 'https://github.com/backstage',
+ }),
+ ).resolves.toEqual(expect.objectContaining({ token: 'hardcoded_token' }));
+ });
+
+ it('should return undefined if no token or apps are configured', async () => {
+ const github = GithubCredentialsProvider.create({
+ host: 'github.com',
+ });
+
+ await expect(
+ github.getCredentials({
+ url: 'https://github.com/backstage',
+ }),
+ ).resolves.toEqual({ headers: undefined, token: undefined });
+ });
+});
diff --git a/packages/integration/src/github/GithubCredentialsProvider.ts b/packages/integration/src/github/GithubCredentialsProvider.ts
new file mode 100644
index 0000000000..843ef629ab
--- /dev/null
+++ b/packages/integration/src/github/GithubCredentialsProvider.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 gitUrlParse from 'git-url-parse';
+import { GithubAppConfig, GitHubIntegrationConfig } from './config';
+import { createAppAuth } from '@octokit/auth-app';
+import { Octokit, RestEndpointMethodTypes } from '@octokit/rest';
+import { DateTime } from 'luxon';
+
+type InstallationData = {
+ installationId: number;
+ suspended: boolean;
+ repositorySelection: 'selected' | 'all';
+};
+
+class Cache {
+ private readonly tokenCache = new Map<
+ string,
+ { token: string; expiresAt: DateTime }
+ >();
+
+ async getOrCreateToken(
+ key: string,
+ supplier: () => Promise<{ token: string; expiresAt: DateTime }>,
+ ): Promise<{ accessToken: string }> {
+ const item = this.tokenCache.get(key);
+ if (item && this.isNotExpired(item.expiresAt)) {
+ return { accessToken: item.token };
+ }
+
+ const result = await supplier();
+ this.tokenCache.set(key, result);
+ return { accessToken: result.token };
+ }
+
+ // consider timestamps older than 50 minutes to be expired.
+ private isNotExpired = (date: DateTime) =>
+ date.diff(DateTime.local(), 'minutes').minutes > 50;
+}
+
+/**
+ * This accept header is required when calling App APIs in GitHub Enterprise.
+ * It has no effect on calls to github.com and can probably be removed entierly
+ * once GitHub Apps is out of preview.
+ */
+const HEADERS = {
+ Accept: 'application/vnd.github.machine-man-preview+json',
+};
+
+/**
+ * GithubAppManager issues and caches tokens for a specific GitHub App.
+ */
+class GithubAppManager {
+ private readonly appClient: Octokit;
+ private readonly baseAuthConfig: { appId: number; privateKey: string };
+ private installations?: RestEndpointMethodTypes['apps']['listInstallations']['response'];
+ private readonly cache = new Cache();
+
+ constructor(config: GithubAppConfig, baseUrl?: string) {
+ this.baseAuthConfig = {
+ appId: config.appId,
+ privateKey: config.privateKey,
+ };
+ this.appClient = new Octokit({
+ baseUrl,
+ headers: HEADERS,
+ authStrategy: createAppAuth,
+ auth: this.baseAuthConfig,
+ });
+ }
+
+ async getInstallationCredentials(
+ owner: string,
+ repo?: string,
+ ): Promise<{ accessToken: string }> {
+ const {
+ installationId,
+ suspended,
+ repositorySelection,
+ } = await this.getInstallationData(owner);
+ if (suspended) {
+ throw new Error(
+ `The GitHub application for ${[owner, repo]
+ .filter(Boolean)
+ .join('/')} is suspended`,
+ );
+ }
+ if (repositorySelection !== 'all' && !repo) {
+ throw new Error(
+ `The Backstage GitHub application used in the ${owner} organization must be installed for the entire organization to be able to issue credentials without a specified repository.`,
+ );
+ }
+
+ const cacheKey = !repo ? owner : `${owner}/${repo}`;
+ const repositories = repositorySelection !== 'all' ? [repo!] : undefined;
+
+ // Go and grab an access token for the app scoped to a repository if provided, if not use the organisation installation.
+ return this.cache.getOrCreateToken(cacheKey, async () => {
+ const result = await this.appClient.apps.createInstallationAccessToken({
+ installation_id: installationId,
+ headers: HEADERS,
+ repositories,
+ });
+ return {
+ token: result.data.token,
+ expiresAt: DateTime.fromISO(result.data.expires_at),
+ };
+ });
+ }
+
+ private async getInstallationData(owner: string): Promise {
+ // List all installations using the last used etag.
+ // Return cached InstallationData if error with status 304 is thrown.
+ try {
+ this.installations = await this.appClient.apps.listInstallations({
+ headers: {
+ 'If-None-Match': this.installations?.headers.etag,
+ Accept: HEADERS.Accept,
+ },
+ });
+ } catch (error) {
+ if (error.status !== 304) {
+ throw error;
+ }
+ }
+ const installation = this.installations?.data.find(
+ inst => inst.account?.login === owner,
+ );
+ if (installation) {
+ return {
+ installationId: installation.id,
+ suspended: Boolean(installation.suspended_by),
+ repositorySelection: installation.repository_selection,
+ };
+ }
+ const notFoundError = new Error(
+ `No app installation found for ${owner} in ${this.baseAuthConfig.appId}`,
+ );
+ notFoundError.name = 'NotFoundError';
+ throw notFoundError;
+ }
+}
+
+// GithubAppCredentialsMux corresponds to a Github installation which internally could hold several GitHub Apps.
+export class GithubAppCredentialsMux {
+ private readonly apps: GithubAppManager[];
+
+ constructor(config: GitHubIntegrationConfig) {
+ this.apps =
+ config.apps?.map(ac => new GithubAppManager(ac, config.apiBaseUrl)) ?? [];
+ }
+
+ async getAppToken(owner: string, repo?: string): Promise {
+ if (this.apps.length === 0) {
+ return undefined;
+ }
+
+ const results = await Promise.all(
+ this.apps.map(app =>
+ app.getInstallationCredentials(owner, repo).then(
+ credentials => ({ credentials, error: undefined }),
+ error => ({ credentials: undefined, error }),
+ ),
+ ),
+ );
+
+ const result = results.find(result => result.credentials);
+ if (result) {
+ return result.credentials!.accessToken;
+ }
+
+ const errors = results.map(r => r.error);
+ const notNotFoundError = errors.find(err => err.name !== 'NotFoundError');
+ if (notNotFoundError) {
+ throw notNotFoundError;
+ }
+
+ return undefined;
+ }
+}
+
+export type GithubCredentials = {
+ headers?: { [name: string]: string };
+ token?: string;
+};
+
+// TODO: Possibly move this to a backend only package so that it's not used in the frontend by mistake
+export class GithubCredentialsProvider {
+ static create(config: GitHubIntegrationConfig): GithubCredentialsProvider {
+ return new GithubCredentialsProvider(
+ new GithubAppCredentialsMux(config),
+ config.token,
+ );
+ }
+
+ private constructor(
+ private readonly githubAppCredentialsMux: GithubAppCredentialsMux,
+ private readonly token?: string,
+ ) {}
+
+ /**
+ * Returns GithubCredentials for requested url.
+ * Consecutive calls to this method with the same url will return cached credentials.
+ * The shortest lifetime for a token returned is 10 minutes.
+ * @param opts containing the organization or repository url
+ * @returns {Promise} of @type {GithubCredentials}.
+ * @example
+ * const { token, headers } = await getCredentials({url: 'github.com/backstage/foobar'})
+ */
+ async getCredentials(opts: { url: string }): Promise {
+ const parsed = gitUrlParse(opts.url);
+
+ const owner = parsed.owner || parsed.name;
+ const repo = parsed.owner ? parsed.name : undefined;
+
+ let token = await this.githubAppCredentialsMux.getAppToken(owner, repo);
+ if (!token) {
+ token = this.token;
+ }
+
+ return {
+ headers: token
+ ? {
+ Authorization: `Bearer ${token}`,
+ }
+ : undefined,
+ token,
+ };
+ }
+}
diff --git a/packages/integration/src/github/config.ts b/packages/integration/src/github/config.ts
index 22e8ad57d8..94ed00731e 100644
--- a/packages/integration/src/github/config.ts
+++ b/packages/integration/src/github/config.ts
@@ -58,6 +58,41 @@ export type GitHubIntegrationConfig = {
* If no token is specified, anonymous access is used.
*/
token?: string;
+
+ /**
+ * The GitHub Apps configuration to use for requests to this provider.
+ *
+ * If no apps are specified, token or anonymous is used.
+ */
+ apps?: GithubAppConfig[];
+};
+
+/**
+ * The configuration parameters for authenticating a GitHub Application.
+ * A Github Apps configuration can be generated using the `backstage-cli create-github-app` command.
+ */
+export type GithubAppConfig = {
+ /**
+ * Unique app identifier, found at https://github.com/organizations/$org/settings/apps/$AppName
+ */
+ appId: number;
+ /**
+ * The private key is used by the GitHub App integration to authenticate the app.
+ * A private key can be generated from the app at https://github.com/organizations/$org/settings/apps/$AppName
+ */
+ privateKey: string;
+ /**
+ * Webhook secret can be configured at https://github.com/organizations/$org/settings/apps/$AppName
+ */
+ webhookSecret: string;
+ /**
+ * Found at https://github.com/organizations/$org/settings/apps/$AppName
+ */
+ clientId: string;
+ /**
+ * Client secrets can be generated at https://github.com/organizations/$org/settings/apps/$AppName
+ */
+ clientSecret: string;
};
/**
@@ -72,6 +107,13 @@ export function readGitHubIntegrationConfig(
let apiBaseUrl = config.getOptionalString('apiBaseUrl');
let rawBaseUrl = config.getOptionalString('rawBaseUrl');
const token = config.getOptionalString('token');
+ const apps = config.getOptionalConfigArray('apps')?.map(c => ({
+ appId: c.getNumber('appId'),
+ clientId: c.getString('clientId'),
+ clientSecret: c.getString('clientSecret'),
+ webhookSecret: c.getString('webhookSecret'),
+ privateKey: c.getString('privateKey'),
+ }));
if (!isValidHost(host)) {
throw new Error(
@@ -91,7 +133,7 @@ export function readGitHubIntegrationConfig(
rawBaseUrl = GITHUB_RAW_BASE_URL;
}
- return { host, apiBaseUrl, rawBaseUrl, token };
+ return { host, apiBaseUrl, rawBaseUrl, token, apps };
}
/**
diff --git a/packages/integration/src/github/index.ts b/packages/integration/src/github/index.ts
index 5f97f6980a..6491e8dcc5 100644
--- a/packages/integration/src/github/index.ts
+++ b/packages/integration/src/github/index.ts
@@ -20,3 +20,4 @@ export {
} from './config';
export type { GitHubIntegrationConfig } from './config';
export { getGitHubFileFetchUrl, getGitHubRequestOptions } from './core';
+export { GithubCredentialsProvider } from './GithubCredentialsProvider';
diff --git a/packages/techdocs-common/CHANGELOG.md b/packages/techdocs-common/CHANGELOG.md
index 6a2ec6cf97..c26164bbb6 100644
--- a/packages/techdocs-common/CHANGELOG.md
+++ b/packages/techdocs-common/CHANGELOG.md
@@ -1,5 +1,44 @@
# @backstage/techdocs-common
+## 0.3.4
+
+### Patch Changes
+
+- a594a7257: @backstage/techdocs-common can now be imported in an environment without @backstage/plugin-techdocs-backend being installed.
+
+## 0.3.3
+
+### Patch Changes
+
+- 68ad5af51: Improve techdocs-common Generator API for it to be used by techdocs-cli. TechDocs generator.run function now takes
+ an input AND an output directory. Most probably you use techdocs-common via plugin-techdocs-backend, and so there
+ is no breaking change for you.
+ But if you use techdocs-common separately, you need to create an output directory and pass into the generator.
+- 371f67ecd: fix to-string breakage of binary files
+- f1e74777a: Fix bug where binary files (`png`, etc.) could not load when using AWS or GCS publisher.
+- dbe4450c3: Google Cloud authentication in TechDocs has been improved.
+
+ 1. `techdocs.publisher.googleGcs.credentials` is now optional. If it is missing, `GOOGLE_APPLICATION_CREDENTIALS`
+ environment variable (and some other methods) will be used to authenticate.
+ Read more here https://cloud.google.com/docs/authentication/production
+
+ 2. `techdocs.publisher.googleGcs.projectId` is no longer used. You can remove it from your `app-config.yaml`.
+
+- 5826d0973: AWS SDK version bump for TechDocs.
+- b3b9445df: AWS S3 authentication in TechDocs has been improved.
+
+ 1. `techdocs.publisher.awsS3.bucketName` is now the only required config. `techdocs.publisher.awsS3.credentials` and `techdocs.publisher.awsS3.region` are optional.
+
+ 2. If `techdocs.publisher.awsS3.credentials` and `techdocs.publisher.awsS3.region` are missing, the AWS environment variables `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_REGION` will be used. There are more better ways of setting up AWS authentication. Read the guide at https://backstage.io/docs/features/techdocs/using-cloud-storage
+
+- Updated dependencies [466354aaa]
+- Updated dependencies [f3b064e1c]
+- Updated dependencies [abbee6fff]
+- Updated dependencies [147fadcb9]
+ - @backstage/integration@0.2.0
+ - @backstage/catalog-model@0.6.1
+ - @backstage/backend-common@0.4.3
+
## 0.3.2
### Patch Changes
diff --git a/packages/techdocs-common/package.json b/packages/techdocs-common/package.json
index c95f415ad3..a069326375 100644
--- a/packages/techdocs-common/package.json
+++ b/packages/techdocs-common/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/techdocs-common",
"description": "Common functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli",
- "version": "0.3.2",
+ "version": "0.3.4",
"main": "src/index.ts",
"types": "src/index.ts",
"private": false,
@@ -37,10 +37,10 @@
},
"dependencies": {
"@aws-sdk/client-s3": "^3.1.0",
- "@backstage/backend-common": "^0.4.2",
- "@backstage/catalog-model": "^0.6.0",
+ "@backstage/backend-common": "^0.4.3",
+ "@backstage/catalog-model": "^0.6.1",
"@backstage/config": "^0.1.2",
- "@backstage/integration": "^0.1.5",
+ "@backstage/integration": "^0.2.0",
"@google-cloud/storage": "^5.6.0",
"@types/dockerode": "^3.2.1",
"@types/express": "^4.17.6",
@@ -57,7 +57,7 @@
},
"devDependencies": {
"@aws-sdk/types": "3.1.0",
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@types/fs-extra": "^9.0.5",
"@types/git-url-parse": "^9.0.0",
"@types/js-yaml": "^3.12.5",
diff --git a/packages/techdocs-common/src/stages/publish/awsS3.ts b/packages/techdocs-common/src/stages/publish/awsS3.ts
index 7a21ae6475..3f7a0e3d81 100644
--- a/packages/techdocs-common/src/stages/publish/awsS3.ts
+++ b/packages/techdocs-common/src/stages/publish/awsS3.ts
@@ -24,13 +24,13 @@ import { PublisherBase, PublishRequest } from './types';
import fs from 'fs-extra';
import { Readable } from 'stream';
-const streamToString = (stream: Readable): Promise => {
+const streamToBuffer = (stream: Readable): Promise => {
return new Promise((resolve, reject) => {
try {
const chunks: any[] = [];
stream.on('data', chunk => chunks.push(chunk));
stream.on('error', reject);
- stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
+ stream.on('end', () => resolve(Buffer.concat(chunks)));
} catch (e) {
throw new Error(`Unable to parse the response data, ${e.message}`);
}
@@ -173,7 +173,7 @@ export class AwsS3Publish implements PublisherBase {
Key: `${entityRootDir}/techdocs_metadata.json`,
})
.then(async file => {
- const techdocsMetadataJson = await streamToString(
+ const techdocsMetadataJson = await streamToBuffer(
file.Body as Readable,
);
@@ -183,7 +183,7 @@ export class AwsS3Publish implements PublisherBase {
);
}
- resolve(techdocsMetadataJson);
+ resolve(techdocsMetadataJson.toString('utf-8'));
})
.catch(err => {
this.logger.error(err.message);
@@ -211,7 +211,7 @@ export class AwsS3Publish implements PublisherBase {
this.storageClient
.getObject({ Bucket: this.bucketName, Key: filePath })
.then(async object => {
- const fileContent = await streamToString(object.Body as Readable);
+ const fileContent = await streamToBuffer(object.Body as Readable);
if (!fileContent) {
throw new Error(`Unable to parse the file ${filePath}.`);
}
diff --git a/packages/techdocs-common/src/stages/publish/local.ts b/packages/techdocs-common/src/stages/publish/local.ts
index 2739940530..de670cfba5 100644
--- a/packages/techdocs-common/src/stages/publish/local.ts
+++ b/packages/techdocs-common/src/stages/publish/local.ts
@@ -16,6 +16,8 @@
import fetch from 'cross-fetch';
import express from 'express';
import fs from 'fs-extra';
+import path from 'path';
+import os from 'os';
import { Logger } from 'winston';
import { Entity, EntityName } from '@backstage/catalog-model';
import {
@@ -25,10 +27,20 @@ import {
import { Config } from '@backstage/config';
import { PublisherBase, PublishRequest, PublishResponse } from './types';
-const staticDocsDir = resolvePackagePath(
- '@backstage/plugin-techdocs-backend',
- 'static/docs',
-);
+// TODO: Use a more persistent storage than node_modules or /tmp directory.
+// Make it configurable with techdocs.publisher.local.publishDirectory
+let staticDocsDir = '';
+try {
+ staticDocsDir = resolvePackagePath(
+ '@backstage/plugin-techdocs-backend',
+ 'static/docs',
+ );
+} catch (err) {
+ // This will most probably never be used.
+ // The try/catch is introduced so that techdocs-cli can import @backstage/techdocs-common
+ // on CI/CD without installing techdocs backend plugin.
+ staticDocsDir = os.tmpdir();
+}
/**
* Local publisher which uses the local filesystem to store the generated static files. It uses a directory
@@ -39,6 +51,9 @@ export class LocalPublish implements PublisherBase {
private readonly logger: Logger;
private readonly discovery: PluginEndpointDiscovery;
+ // TODO: Use a static fromConfig method to create a LocalPublish instance, similar to aws/gcs publishers.
+ // Move the logic of setting staticDocsDir based on config over to fromConfig,
+ // and set the value as a class parameter.
constructor(
config: Config,
logger: Logger,
@@ -52,9 +67,8 @@ export class LocalPublish implements PublisherBase {
publish({ entity, directory }: PublishRequest): Promise {
const entityNamespace = entity.metadata.namespace ?? 'default';
- const publishDir = resolvePackagePath(
- '@backstage/plugin-techdocs-backend',
- 'static/docs',
+ const publishDir = path.join(
+ staticDocsDir,
entityNamespace,
entity.kind,
entity.metadata.name,
diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json
index 0bbd96f1a8..39e202eef8 100644
--- a/plugins/api-docs/package.json
+++ b/plugins/api-docs/package.json
@@ -30,7 +30,7 @@
},
"dependencies": {
"@backstage/catalog-model": "^0.6.0",
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/plugin-catalog": "^0.2.9",
"@backstage/theme": "^0.2.2",
"@kyma-project/asyncapi-react": "^0.14.2",
@@ -49,7 +49,7 @@
"swagger-ui-react": "^3.37.2"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md
index ce029cded2..f21224eb65 100644
--- a/plugins/auth-backend/CHANGELOG.md
+++ b/plugins/auth-backend/CHANGELOG.md
@@ -1,5 +1,16 @@
# @backstage/plugin-auth-backend
+## 0.2.10
+
+### Patch Changes
+
+- 468579734: Allow blank certificates and support logout URLs in the SAML provider.
+- Updated dependencies [f3b064e1c]
+- Updated dependencies [abbee6fff]
+- Updated dependencies [147fadcb9]
+ - @backstage/catalog-model@0.6.1
+ - @backstage/backend-common@0.4.3
+
## 0.2.9
### Patch Changes
diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json
index 38d074f7fb..8f88c69487 100644
--- a/plugins/auth-backend/package.json
+++ b/plugins/auth-backend/package.json
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-auth-backend",
- "version": "0.2.9",
+ "version": "0.2.10",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -29,9 +29,9 @@
"clean": "backstage-cli clean"
},
"dependencies": {
- "@backstage/backend-common": "^0.4.2",
+ "@backstage/backend-common": "^0.4.3",
"@backstage/catalog-client": "^0.3.4",
- "@backstage/catalog-model": "^0.6.0",
+ "@backstage/catalog-model": "^0.6.1",
"@backstage/config": "^0.1.2",
"@types/express": "^4.17.6",
"compression": "^1.7.4",
@@ -64,7 +64,7 @@
"yn": "^4.0.0"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@types/body-parser": "^1.19.0",
"@types/cookie-parser": "^1.4.2",
"@types/express-session": "^1.17.2",
diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md
index b60555037c..a3ee4b7eb3 100644
--- a/plugins/catalog-backend/CHANGELOG.md
+++ b/plugins/catalog-backend/CHANGELOG.md
@@ -1,5 +1,19 @@
# @backstage/plugin-catalog-backend
+## 0.5.3
+
+### Patch Changes
+
+- 94fdf4955: Get rid of all usages of @octokit/types, and bump the rest of the octokit dependencies to the latest version
+- ade6b3bdf: AWS SDK version bump for Catalog Backend.
+- abbee6fff: Implement System, Domain and Resource entity kinds.
+- 147fadcb9: Add subcomponentOf to Component kind to represent subsystems of larger components.
+- Updated dependencies [f3b064e1c]
+- Updated dependencies [abbee6fff]
+- Updated dependencies [147fadcb9]
+ - @backstage/catalog-model@0.6.1
+ - @backstage/backend-common@0.4.3
+
## 0.5.2
### Patch Changes
diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json
index 9a782ac1e5..e6b6713e20 100644
--- a/plugins/catalog-backend/package.json
+++ b/plugins/catalog-backend/package.json
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-catalog-backend",
- "version": "0.5.2",
+ "version": "0.5.3",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -30,9 +30,9 @@
},
"dependencies": {
"@aws-sdk/client-organizations": "^3.2.0",
- "@azure/msal-node": "^1.0.0-alpha.8",
- "@backstage/backend-common": "^0.4.2",
- "@backstage/catalog-model": "^0.6.0",
+ "@azure/msal-node": "^1.0.0-beta.3",
+ "@backstage/backend-common": "^0.4.3",
+ "@backstage/catalog-model": "^0.6.1",
"@backstage/config": "^0.1.2",
"@octokit/graphql": "^4.5.8",
"@types/express": "^4.17.6",
@@ -57,7 +57,7 @@
"yup": "^0.29.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/test-utils": "^0.1.6",
"@types/core-js": "^2.5.4",
"@types/git-url-parse": "^9.0.0",
diff --git a/plugins/catalog-backend/src/database/CommonDatabase.test.ts b/plugins/catalog-backend/src/database/CommonDatabase.test.ts
index 130ed41eb1..b319bb832d 100644
--- a/plugins/catalog-backend/src/database/CommonDatabase.test.ts
+++ b/plugins/catalog-backend/src/database/CommonDatabase.test.ts
@@ -137,6 +137,22 @@ describe('CommonDatabase', () => {
await expect(db.location(location.id)).rejects.toThrow(/Found no location/);
});
+ it('refuses to remove the bootstrap location', async () => {
+ const input: Location = {
+ id: 'dd12620d-0436-422f-93bd-929aa0788123',
+ type: 'bootstrap',
+ target: 'bootstrap',
+ };
+
+ const output = await db.transaction(
+ async tx => await db.addLocation(tx, input),
+ );
+
+ await expect(
+ db.transaction(async tx => await db.removeLocation(tx, output.id)),
+ ).rejects.toThrow(ConflictError);
+ });
+
describe('addEntities', () => {
it('happy path: adds entities to empty database', async () => {
const result = await db.transaction(tx =>
diff --git a/plugins/catalog-backend/src/database/CommonDatabase.ts b/plugins/catalog-backend/src/database/CommonDatabase.ts
index d641cbb7b6..2edc0ca5b8 100644
--- a/plugins/catalog-backend/src/database/CommonDatabase.ts
+++ b/plugins/catalog-backend/src/database/CommonDatabase.ts
@@ -330,15 +330,21 @@ export class CommonDatabase implements Database {
async removeLocation(txOpaque: Transaction, id: string): Promise {
const tx = txOpaque as Knex.Transaction;
+ const locations = await tx('locations')
+ .where({ id })
+ .select();
+ if (!locations.length) {
+ throw new NotFoundError(`Found no location with ID ${id}`);
+ }
+
+ if (locations[0].type === 'bootstrap') {
+ throw new ConflictError('You may not delete the bootstrap location.');
+ }
+
await tx('entities')
.where({ location_id: id })
.update({ location_id: null });
-
- const result = await tx('locations').where({ id }).del();
-
- if (!result) {
- throw new NotFoundError(`Found no location with ID ${id}`);
- }
+ await tx('locations').where({ id }).del();
}
async location(id: string): Promise {
diff --git a/plugins/catalog-backend/src/ingestion/HigherOrderOperations.ts b/plugins/catalog-backend/src/ingestion/HigherOrderOperations.ts
index b7e9c48fe5..ba97232810 100644
--- a/plugins/catalog-backend/src/ingestion/HigherOrderOperations.ts
+++ b/plugins/catalog-backend/src/ingestion/HigherOrderOperations.ts
@@ -186,7 +186,7 @@ export class HigherOrderOperations implements HigherOrderOperation {
throw e;
}
- this.logger.info(`Posting update success markers`);
+ this.logger.debug(`Posting update success markers`);
await this.locationsCatalog.logUpdateSuccess(
location.id,
diff --git a/plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts b/plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts
index 97df326fc5..bc81cf14f8 100644
--- a/plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts
+++ b/plugins/catalog-backend/src/ingestion/LocationAnalyzer.ts
@@ -15,7 +15,7 @@
*/
import { Logger } from 'winston';
-import parseGitUri from 'git-url-parse';
+import parseGitUrl from 'git-url-parse';
import {
AnalyzeLocationRequest,
AnalyzeLocationResponse,
@@ -31,7 +31,7 @@ export class RepoLocationAnalyzer implements LocationAnalyzer {
async analyzeLocation(
request: AnalyzeLocationRequest,
): Promise {
- const { owner, name, source } = parseGitUri(request.location.target);
+ const { owner, name, source } = parseGitUrl(request.location.target);
const entity = {
apiVersion: 'backstage.io/v1alpha1',
kind: 'Component',
diff --git a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts
index 1d2562c25b..feb4791477 100644
--- a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts
+++ b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts
@@ -17,7 +17,10 @@
import {
ApiEntity,
ComponentEntity,
+ DomainEntity,
GroupEntity,
+ ResourceEntity,
+ SystemEntity,
UserEntity,
} from '@backstage/catalog-model';
import { BuiltinKindsEntityProcessor } from './BuiltinKindsEntityProcessor';
@@ -42,12 +45,13 @@ describe('BuiltinKindsEntityProcessor', () => {
lifecycle: 'l',
providesApis: ['b'],
consumesApis: ['c'],
+ system: 's',
},
};
await processor.postProcessEntity(entity, location, emit);
- expect(emit).toBeCalledTimes(8);
+ expect(emit).toBeCalledTimes(10);
expect(emit).toBeCalledWith({
type: 'relation',
relation: {
@@ -112,6 +116,22 @@ describe('BuiltinKindsEntityProcessor', () => {
target: { kind: 'Component', namespace: 'default', name: 's' },
},
});
+ expect(emit).toBeCalledWith({
+ type: 'relation',
+ relation: {
+ source: { kind: 'System', namespace: 'default', name: 's' },
+ type: 'hasPart',
+ target: { kind: 'Component', namespace: 'default', name: 'n' },
+ },
+ });
+ expect(emit).toBeCalledWith({
+ type: 'relation',
+ relation: {
+ source: { kind: 'Component', namespace: 'default', name: 'n' },
+ type: 'partOf',
+ target: { kind: 'System', namespace: 'default', name: 's' },
+ },
+ });
});
it('generates relations for api entities', async () => {
@@ -124,12 +144,13 @@ describe('BuiltinKindsEntityProcessor', () => {
owner: 'o',
lifecycle: 'l',
definition: 'd',
+ system: 's',
},
};
await processor.postProcessEntity(entity, location, emit);
- expect(emit).toBeCalledTimes(2);
+ expect(emit).toBeCalledTimes(4);
expect(emit).toBeCalledWith({
type: 'relation',
relation: {
@@ -146,6 +167,150 @@ describe('BuiltinKindsEntityProcessor', () => {
target: { kind: 'Group', namespace: 'default', name: 'o' },
},
});
+ expect(emit).toBeCalledWith({
+ type: 'relation',
+ relation: {
+ source: { kind: 'System', namespace: 'default', name: 's' },
+ type: 'hasPart',
+ target: { kind: 'API', namespace: 'default', name: 'n' },
+ },
+ });
+ expect(emit).toBeCalledWith({
+ type: 'relation',
+ relation: {
+ source: { kind: 'API', namespace: 'default', name: 'n' },
+ type: 'partOf',
+ target: { kind: 'System', namespace: 'default', name: 's' },
+ },
+ });
+ });
+
+ it('generates relations for resource entities', async () => {
+ const entity: ResourceEntity = {
+ apiVersion: 'backstage.io/v1alpha1',
+ kind: 'Resource',
+ metadata: { name: 'n' },
+ spec: {
+ type: 'database',
+ owner: 'o',
+ system: 's',
+ },
+ };
+
+ await processor.postProcessEntity(entity, location, emit);
+
+ expect(emit).toBeCalledTimes(4);
+ expect(emit).toBeCalledWith({
+ type: 'relation',
+ relation: {
+ source: { kind: 'Group', namespace: 'default', name: 'o' },
+ type: 'ownerOf',
+ target: { kind: 'Resource', namespace: 'default', name: 'n' },
+ },
+ });
+ expect(emit).toBeCalledWith({
+ type: 'relation',
+ relation: {
+ source: { kind: 'Resource', namespace: 'default', name: 'n' },
+ type: 'ownedBy',
+ target: { kind: 'Group', namespace: 'default', name: 'o' },
+ },
+ });
+ expect(emit).toBeCalledWith({
+ type: 'relation',
+ relation: {
+ source: { kind: 'System', namespace: 'default', name: 's' },
+ type: 'hasPart',
+ target: { kind: 'Resource', namespace: 'default', name: 'n' },
+ },
+ });
+ expect(emit).toBeCalledWith({
+ type: 'relation',
+ relation: {
+ source: { kind: 'Resource', namespace: 'default', name: 'n' },
+ type: 'partOf',
+ target: { kind: 'System', namespace: 'default', name: 's' },
+ },
+ });
+ });
+
+ it('generates relations for system entities', async () => {
+ const entity: SystemEntity = {
+ apiVersion: 'backstage.io/v1alpha1',
+ kind: 'System',
+ metadata: { name: 'n' },
+ spec: {
+ owner: 'o',
+ domain: 'd',
+ },
+ };
+
+ await processor.postProcessEntity(entity, location, emit);
+
+ expect(emit).toBeCalledTimes(4);
+ expect(emit).toBeCalledWith({
+ type: 'relation',
+ relation: {
+ source: { kind: 'Group', namespace: 'default', name: 'o' },
+ type: 'ownerOf',
+ target: { kind: 'System', namespace: 'default', name: 'n' },
+ },
+ });
+ expect(emit).toBeCalledWith({
+ type: 'relation',
+ relation: {
+ source: { kind: 'System', namespace: 'default', name: 'n' },
+ type: 'ownedBy',
+ target: { kind: 'Group', namespace: 'default', name: 'o' },
+ },
+ });
+ expect(emit).toBeCalledWith({
+ type: 'relation',
+ relation: {
+ source: { kind: 'Domain', namespace: 'default', name: 'd' },
+ type: 'hasPart',
+ target: { kind: 'System', namespace: 'default', name: 'n' },
+ },
+ });
+ expect(emit).toBeCalledWith({
+ type: 'relation',
+ relation: {
+ source: { kind: 'System', namespace: 'default', name: 'n' },
+ type: 'partOf',
+ target: { kind: 'Domain', namespace: 'default', name: 'd' },
+ },
+ });
+ });
+
+ it('generates relations for domain entities', async () => {
+ const entity: DomainEntity = {
+ apiVersion: 'backstage.io/v1alpha1',
+ kind: 'Domain',
+ metadata: { name: 'n' },
+ spec: {
+ owner: 'o',
+ },
+ };
+
+ await processor.postProcessEntity(entity, location, emit);
+
+ expect(emit).toBeCalledTimes(2);
+ expect(emit).toBeCalledWith({
+ type: 'relation',
+ relation: {
+ source: { kind: 'Group', namespace: 'default', name: 'o' },
+ type: 'ownerOf',
+ target: { kind: 'Domain', namespace: 'default', name: 'n' },
+ },
+ });
+ expect(emit).toBeCalledWith({
+ type: 'relation',
+ relation: {
+ source: { kind: 'Domain', namespace: 'default', name: 'n' },
+ type: 'ownedBy',
+ target: { kind: 'Group', namespace: 'default', name: 'o' },
+ },
+ });
});
it('generates relations for user entities', async () => {
diff --git a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts
index 67e89ac52c..c75a46874d 100644
--- a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts
+++ b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts
@@ -19,6 +19,8 @@ import {
apiEntityV1alpha1Validator,
ComponentEntity,
componentEntityV1alpha1Validator,
+ DomainEntity,
+ domainEntityV1alpha1Validator,
Entity,
getEntityName,
GroupEntity,
@@ -31,13 +33,17 @@ import {
RELATION_CHILD_OF,
RELATION_CONSUMES_API,
RELATION_HAS_MEMBER,
- RELATION_MEMBER_OF,
RELATION_HAS_PART,
- RELATION_PART_OF,
+ RELATION_MEMBER_OF,
RELATION_OWNED_BY,
RELATION_OWNER_OF,
RELATION_PARENT_OF,
+ RELATION_PART_OF,
RELATION_PROVIDES_API,
+ ResourceEntity,
+ resourceEntityV1alpha1Validator,
+ SystemEntity,
+ systemEntityV1alpha1Validator,
templateEntityV1alpha1Validator,
UserEntity,
userEntityV1alpha1Validator,
@@ -49,10 +55,13 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor {
private readonly validators = [
apiEntityV1alpha1Validator,
componentEntityV1alpha1Validator,
+ resourceEntityV1alpha1Validator,
groupEntityV1alpha1Validator,
locationEntityV1alpha1Validator,
templateEntityV1alpha1Validator,
userEntityV1alpha1Validator,
+ systemEntityV1alpha1Validator,
+ domainEntityV1alpha1Validator,
];
async validateEntityKind(entity: Entity): Promise {
@@ -135,6 +144,12 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor {
RELATION_CONSUMES_API,
RELATION_API_CONSUMED_BY,
);
+ doEmit(
+ component.spec.system,
+ { defaultKind: 'System', defaultNamespace: selfRef.namespace },
+ RELATION_PART_OF,
+ RELATION_HAS_PART,
+ );
}
/*
@@ -149,6 +164,32 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor {
RELATION_OWNED_BY,
RELATION_OWNER_OF,
);
+ doEmit(
+ api.spec.system,
+ { defaultKind: 'System', defaultNamespace: selfRef.namespace },
+ RELATION_PART_OF,
+ RELATION_HAS_PART,
+ );
+ }
+
+ /*
+ * Emit relations for the Resource kind
+ */
+
+ if (entity.kind === 'Resource') {
+ const resource = entity as ResourceEntity;
+ doEmit(
+ resource.spec.owner,
+ { defaultKind: 'Group', defaultNamespace: selfRef.namespace },
+ RELATION_OWNED_BY,
+ RELATION_OWNER_OF,
+ );
+ doEmit(
+ resource.spec.system,
+ { defaultKind: 'System', defaultNamespace: selfRef.namespace },
+ RELATION_PART_OF,
+ RELATION_HAS_PART,
+ );
}
/*
@@ -185,6 +226,40 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor {
);
}
+ /*
+ * Emit relations for the System kind
+ */
+
+ if (entity.kind === 'System') {
+ const system = entity as SystemEntity;
+ doEmit(
+ system.spec.owner,
+ { defaultKind: 'Group', defaultNamespace: selfRef.namespace },
+ RELATION_OWNED_BY,
+ RELATION_OWNER_OF,
+ );
+ doEmit(
+ system.spec.domain,
+ { defaultKind: 'Domain', defaultNamespace: selfRef.namespace },
+ RELATION_PART_OF,
+ RELATION_HAS_PART,
+ );
+ }
+
+ /*
+ * Emit relations for the Domain kind
+ */
+
+ if (entity.kind === 'Domain') {
+ const domain = entity as DomainEntity;
+ doEmit(
+ domain.spec.owner,
+ { defaultKind: 'Group', defaultNamespace: selfRef.namespace },
+ RELATION_OWNED_BY,
+ RELATION_OWNER_OF,
+ );
+ }
+
return entity;
}
}
diff --git a/plugins/catalog-backend/src/ingestion/processors/CodeOwnersProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/CodeOwnersProcessor.ts
index e2b8a8b62c..e1d7e22ccf 100644
--- a/plugins/catalog-backend/src/ingestion/processors/CodeOwnersProcessor.ts
+++ b/plugins/catalog-backend/src/ingestion/processors/CodeOwnersProcessor.ts
@@ -20,7 +20,7 @@ import * as codeowners from 'codeowners-utils';
import { CodeOwnersEntry } from 'codeowners-utils';
// NOTE: This can be removed when ES2021 is implemented
import 'core-js/features/promise';
-import parseGitUri from 'git-url-parse';
+import parseGitUrl from 'git-url-parse';
import { filter, get, head, pipe, reverse } from 'lodash/fp';
import { Logger } from 'winston';
import { CatalogProcessor } from './types';
@@ -123,7 +123,7 @@ export function buildCodeOwnerUrl(
basePath: string,
codeOwnersPath: string,
): string {
- return buildUrl({ ...parseGitUri(basePath), codeOwnersPath });
+ return buildUrl({ ...parseGitUrl(basePath), codeOwnersPath });
}
export function parseCodeOwners(ownersText: string) {
diff --git a/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.test.ts
index 9bf72d620b..aac4235e3a 100644
--- a/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.test.ts
+++ b/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.test.ts
@@ -27,13 +27,18 @@ import {
} from './types';
describe('UrlReaderProcessor', () => {
- const mockApiOrigin = 'http://localhost:23000';
+ const mockApiOrigin = 'http://localhost';
const server = setupServer();
msw.setupDefaultHandlers(server);
it('should load from url', async () => {
const logger = getVoidLogger();
- const reader = UrlReaders.default({ logger, config: new ConfigReader({}) });
+ const reader = UrlReaders.default({
+ logger,
+ config: new ConfigReader({
+ backend: { reading: { allow: [{ host: 'localhost' }] } },
+ }),
+ });
const processor = new UrlReaderProcessor({ reader, logger });
const spec = {
type: 'url',
@@ -57,7 +62,12 @@ describe('UrlReaderProcessor', () => {
it('should fail load from url with error', async () => {
const logger = getVoidLogger();
- const reader = UrlReaders.default({ logger, config: new ConfigReader({}) });
+ const reader = UrlReaders.default({
+ logger,
+ config: new ConfigReader({
+ backend: { reading: { allow: [{ host: 'localhost' }] } },
+ }),
+ });
const processor = new UrlReaderProcessor({ reader, logger });
const spec = {
type: 'url',
diff --git a/plugins/catalog-backend/src/ingestion/processors/microsoftGraph/client.ts b/plugins/catalog-backend/src/ingestion/processors/microsoftGraph/client.ts
index bdb5918b2f..3dfc58e773 100644
--- a/plugins/catalog-backend/src/ingestion/processors/microsoftGraph/client.ts
+++ b/plugins/catalog-backend/src/ingestion/processors/microsoftGraph/client.ts
@@ -96,6 +96,10 @@ export class MicrosoftGraphClient {
scopes: ['https://graph.microsoft.com/.default'],
});
+ if (!token) {
+ throw new Error('Error while requesting token for Microsoft Graph');
+ }
+
return await fetch(url, {
headers: {
Authorization: `Bearer ${token.accessToken}`,
diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md
index f494949aab..a307095014 100644
--- a/plugins/catalog-import/CHANGELOG.md
+++ b/plugins/catalog-import/CHANGELOG.md
@@ -1,5 +1,24 @@
# @backstage/plugin-catalog-import
+## 0.3.4
+
+### Patch Changes
+
+- 34a01a171: Improve how URLs are analyzed for add/import
+- bc40ccecf: Add more generic descriptions for the catalog-import form.
+- 94fdf4955: Get rid of all usages of @octokit/types, and bump the rest of the octokit dependencies to the latest version
+- be5ac7fde: Remove dependency to `@backstage/plugin-catalog-backend`.
+- Updated dependencies [466354aaa]
+- Updated dependencies [f3b064e1c]
+- Updated dependencies [c00488983]
+- Updated dependencies [265a7ab30]
+- Updated dependencies [abbee6fff]
+- Updated dependencies [147fadcb9]
+ - @backstage/integration@0.2.0
+ - @backstage/catalog-model@0.6.1
+ - @backstage/plugin-catalog@0.2.11
+ - @backstage/core@0.4.4
+
## 0.3.3
### Patch Changes
diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json
index 1a7d22d551..5e601ad896 100644
--- a/plugins/catalog-import/package.json
+++ b/plugins/catalog-import/package.json
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-catalog-import",
- "version": "0.3.3",
+ "version": "0.3.4",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -30,10 +30,10 @@
"clean": "backstage-cli clean"
},
"dependencies": {
- "@backstage/catalog-model": "^0.6.0",
- "@backstage/core": "^0.4.3",
- "@backstage/plugin-catalog": "^0.2.10",
- "@backstage/integration": "^0.1.5",
+ "@backstage/catalog-model": "^0.6.1",
+ "@backstage/core": "^0.4.4",
+ "@backstage/plugin-catalog": "^0.2.11",
+ "@backstage/integration": "^0.2.0",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -49,7 +49,7 @@
"yaml": "^1.10.0"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/catalog-import/src/util/urls.ts b/plugins/catalog-import/src/util/urls.ts
index d142263734..c51dc0a999 100644
--- a/plugins/catalog-import/src/util/urls.ts
+++ b/plugins/catalog-import/src/util/urls.ts
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-import parseGitUri from 'git-url-parse';
+import parseGitUrl from 'git-url-parse';
export type UrlType = 'file' | 'tree';
export function urlType(url: string): UrlType {
- const { filepathtype, filepath } = parseGitUri(url);
+ const { filepathtype, filepath } = parseGitUrl(url);
if (filepathtype === 'tree' || filepathtype === 'file') {
return filepathtype;
diff --git a/plugins/catalog-import/src/util/useGithubRepos.ts b/plugins/catalog-import/src/util/useGithubRepos.ts
index 6c11ca1e8b..a2d299b9f4 100644
--- a/plugins/catalog-import/src/util/useGithubRepos.ts
+++ b/plugins/catalog-import/src/util/useGithubRepos.ts
@@ -18,7 +18,7 @@ import * as YAML from 'yaml';
import { useApi, configApiRef } from '@backstage/core';
import { catalogImportApiRef } from '../api/CatalogImportApi';
import { ConfigSpec } from '../components/ImportComponentPage';
-import parseGitUri from 'git-url-parse';
+import parseGitUrl from 'git-url-parse';
// TODO: (O5ten) Refactor into a core API instead of direct usage like this
// https://github.com/backstage/backstage/pull/3613#issuecomment-7408929430
@@ -36,7 +36,7 @@ export function useGithubRepos() {
name: repoName,
owner: ownerName,
resource: hostname,
- } = parseGitUri(location);
+ } = parseGitUrl(location);
const configs = readGitHubIntegrationConfigs(
config.getOptionalConfigArray('integrations.github') ?? [],
diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md
index 57a8a9d205..b826346b39 100644
--- a/plugins/catalog/CHANGELOG.md
+++ b/plugins/catalog/CHANGELOG.md
@@ -1,5 +1,22 @@
# @backstage/plugin-catalog
+## 0.2.11
+
+### Patch Changes
+
+- c00488983: Enable catalog table actions for all location types.
+
+ The edit button has had support for other providers for a while and there is
+ no specific reason the View in GitHub cannot work for all locations. This
+ change also replaces the GitHub icon with the OpenInNew icon.
+
+- Updated dependencies [f3b064e1c]
+- Updated dependencies [265a7ab30]
+- Updated dependencies [abbee6fff]
+- Updated dependencies [147fadcb9]
+ - @backstage/catalog-model@0.6.1
+ - @backstage/core@0.4.4
+
## 0.2.10
### Patch Changes
diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json
index a5fa16ed6f..fa6d757f0a 100644
--- a/plugins/catalog/package.json
+++ b/plugins/catalog/package.json
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-catalog",
- "version": "0.2.10",
+ "version": "0.2.11",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -31,8 +31,8 @@
},
"dependencies": {
"@backstage/catalog-client": "^0.3.4",
- "@backstage/catalog-model": "^0.6.0",
- "@backstage/core": "^0.4.3",
+ "@backstage/catalog-model": "^0.6.1",
+ "@backstage/core": "^0.4.4",
"@backstage/plugin-scaffolder": "^0.3.6",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
@@ -51,7 +51,7 @@
"swr": "^0.3.0"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@microsoft/microsoft-graph-types": "^1.25.0",
diff --git a/plugins/catalog/src/components/AboutCard/AboutContent.tsx b/plugins/catalog/src/components/AboutCard/AboutContent.tsx
index b8d5d84316..178debb42a 100644
--- a/plugins/catalog/src/components/AboutCard/AboutContent.tsx
+++ b/plugins/catalog/src/components/AboutCard/AboutContent.tsx
@@ -14,15 +14,16 @@
* limitations under the License.
*/
-import React from 'react';
-import { Grid, Typography, Chip, makeStyles } from '@material-ui/core';
-import { AboutField } from './AboutField';
import {
Entity,
- ENTITY_DEFAULT_NAMESPACE,
RELATION_OWNED_BY,
- serializeEntityRef,
+ RELATION_PART_OF,
} from '@backstage/catalog-model';
+import { Chip, Grid, makeStyles, Typography } from '@material-ui/core';
+import React from 'react';
+import { EntityRefLink } from '../EntityRefLink';
+import { getEntityRelations } from '../getEntityRelations';
+import { AboutField } from './AboutField';
const useStyles = makeStyles({
description: {
@@ -36,6 +37,17 @@ type Props = {
export const AboutContent = ({ entity }: Props) => {
const classes = useStyles();
+ const isSystem = entity.kind.toLowerCase() === 'system';
+ const isDomain = entity.kind.toLowerCase() === 'domain';
+ const isResource = entity.kind.toLowerCase() === 'resource';
+ const [partOfSystemRelation] = getEntityRelations(entity, RELATION_PART_OF, {
+ kind: 'system',
+ });
+ const [partOfDomainRelation] = getEntityRelations(entity, RELATION_PART_OF, {
+ kind: 'domain',
+ });
+ const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY);
+
return (
@@ -43,32 +55,56 @@ export const AboutContent = ({ entity }: Props) => {
{entity?.metadata?.description || 'No description'}
- r.type === RELATION_OWNED_BY)
- .map(({ target: { kind, name, namespace } }) =>
- // TODO(Rugvip): we want to provide some utils for this
- serializeEntityRef({
- kind,
- name,
- namespace:
- namespace === ENTITY_DEFAULT_NAMESPACE ? undefined : namespace,
- }),
- )
- .join(', ')}
- gridSizes={{ xs: 12, sm: 6, lg: 4 }}
- />
-
-
+
+ {ownedByRelations.map((t, i) => (
+
+ {i > 0 && ', '}
+
+
+ ))}
+
+ {isSystem && (
+
+ {partOfDomainRelation && (
+
+ )}
+
+ )}
+ {!isSystem && !isDomain && (
+
+ {partOfSystemRelation && (
+
+ )}
+
+ )}
+ {!isSystem && !isDomain && (
+
+ )}
+ {!isSystem && !isDomain && !isResource && (
+
+ )}
', () => {
+ it('renders link for entity in default namespace', () => {
+ const entity = {
+ apiVersion: 'v1',
+ kind: 'Component',
+ metadata: {
+ name: 'software',
+ },
+ spec: {
+ owner: 'guest',
+ type: 'service',
+ lifecycle: 'production',
+ },
+ };
+ const { getByText } = render( , {
+ wrapper: MemoryRouter,
+ });
+
+ expect(getByText('component:software')).toBeInTheDocument();
+ });
+
+ it('renders link for entity in other namespace', () => {
+ const entity = {
+ apiVersion: 'v1',
+ kind: 'Component',
+ metadata: {
+ name: 'software',
+ namespace: 'test',
+ },
+ spec: {
+ owner: 'guest',
+ type: 'service',
+ lifecycle: 'production',
+ },
+ };
+ const { getByText } = render( , {
+ wrapper: MemoryRouter,
+ });
+ expect(getByText('component:test/software')).toBeInTheDocument();
+ });
+
+ it('renders link for entity and hides default kind', () => {
+ const entity = {
+ apiVersion: 'v1',
+ kind: 'Component',
+ metadata: {
+ name: 'software',
+ namespace: 'test',
+ },
+ spec: {
+ owner: 'guest',
+ type: 'service',
+ lifecycle: 'production',
+ },
+ };
+ const { getByText } = render(
+ ,
+ {
+ wrapper: MemoryRouter,
+ },
+ );
+ expect(getByText('test/software')).toBeInTheDocument();
+ });
+
+ it('renders link for entity name in default namespace', () => {
+ const entityName = {
+ kind: 'Component',
+ namespace: 'default',
+ name: 'software',
+ };
+ const { getByText } = render( , {
+ wrapper: MemoryRouter,
+ });
+ expect(getByText('component:software')).toBeInTheDocument();
+ });
+
+ it('renders link for entity name in other namespace', () => {
+ const entityName = {
+ kind: 'Component',
+ namespace: 'test',
+ name: 'software',
+ };
+ const { getByText } = render( , {
+ wrapper: MemoryRouter,
+ });
+ expect(getByText('component:test/software')).toBeInTheDocument();
+ });
+
+ it('renders link for entity name and hides default kind', () => {
+ const entityName = {
+ kind: 'Component',
+ namespace: 'test',
+ name: 'software',
+ };
+ const { getByText } = render(
+ ,
+ {
+ wrapper: MemoryRouter,
+ },
+ );
+ expect(getByText('test/software')).toBeInTheDocument();
+ });
+});
diff --git a/plugins/catalog/src/components/EntityRefLink/EntityRefLink.tsx b/plugins/catalog/src/components/EntityRefLink/EntityRefLink.tsx
new file mode 100644
index 0000000000..a06ba69fbe
--- /dev/null
+++ b/plugins/catalog/src/components/EntityRefLink/EntityRefLink.tsx
@@ -0,0 +1,80 @@
+/*
+ * 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 {
+ Entity,
+ EntityName,
+ ENTITY_DEFAULT_NAMESPACE,
+ serializeEntityRef,
+} from '@backstage/catalog-model';
+import { Link } from '@material-ui/core';
+import React from 'react';
+import { generatePath } from 'react-router';
+import { Link as RouterLink } from 'react-router-dom';
+import { entityRoute } from '../../routes';
+
+type EntityRefLinkProps = {
+ entityRef: Entity | EntityName;
+ defaultKind?: string;
+};
+
+// TODO: This component is private for now, as it should probably belong into
+// some kind of helper module for the catalog plugin to avoid a dependency on
+// the catalog plugin itself.
+export const EntityRefLink = ({
+ entityRef,
+ defaultKind,
+}: EntityRefLinkProps) => {
+ let kind;
+ let namespace;
+ let name;
+
+ if ('metadata' in entityRef) {
+ kind = entityRef.kind;
+ namespace = entityRef.metadata.namespace;
+ name = entityRef.metadata.name;
+ } else {
+ kind = entityRef.kind;
+ namespace = entityRef.namespace;
+ name = entityRef.name;
+ }
+
+ if (namespace === ENTITY_DEFAULT_NAMESPACE) {
+ namespace = undefined;
+ }
+
+ kind = kind.toLowerCase();
+
+ const title = `${serializeEntityRef({
+ kind: defaultKind && defaultKind.toLowerCase() === kind ? undefined : kind,
+ name,
+ namespace,
+ })}`;
+ const routeParams = {
+ kind,
+ namespace: namespace?.toLowerCase() ?? ENTITY_DEFAULT_NAMESPACE,
+ name,
+ };
+
+ // TODO: Use useRouteRef here to generate the path
+ return (
+
+ {title}
+
+ );
+};
diff --git a/plugins/catalog/src/components/EntityRefLink/index.ts b/plugins/catalog/src/components/EntityRefLink/index.ts
new file mode 100644
index 0000000000..aa2c6641ef
--- /dev/null
+++ b/plugins/catalog/src/components/EntityRefLink/index.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export { EntityRefLink } from './EntityRefLink';
diff --git a/plugins/catalog/src/components/createEditLink.ts b/plugins/catalog/src/components/createEditLink.ts
index cc04d605f1..57fc876704 100644
--- a/plugins/catalog/src/components/createEditLink.ts
+++ b/plugins/catalog/src/components/createEditLink.ts
@@ -15,7 +15,7 @@
*/
import { LocationSpec } from '@backstage/catalog-model';
-import gitUrlParse from 'git-url-parse';
+import parseGitUrl from 'git-url-parse';
/**
* Creates the edit link for components yaml file
@@ -26,7 +26,7 @@ import gitUrlParse from 'git-url-parse';
export const createEditLink = (location: LocationSpec): string | undefined => {
try {
- const urlData = gitUrlParse(location.target);
+ const urlData = parseGitUrl(location.target);
const url = new URL(location.target);
switch (location.type) {
case 'github':
@@ -64,7 +64,7 @@ export const createEditLink = (location: LocationSpec): string | undefined => {
* @returns string representing type of icon to be used
*/
export const determineUrlType = (url: string): string => {
- const urlData = gitUrlParse(url);
+ const urlData = parseGitUrl(url);
if (urlData.source === 'github.com') {
return 'github';
diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json
index 8e0b4743a0..7e3124375a 100644
--- a/plugins/circleci/package.json
+++ b/plugins/circleci/package.json
@@ -32,7 +32,7 @@
},
"dependencies": {
"@backstage/catalog-model": "^0.6.0",
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/plugin-catalog": "^0.2.7",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
@@ -50,7 +50,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md
index 64e1fe2937..95eaf4a391 100644
--- a/plugins/cloudbuild/CHANGELOG.md
+++ b/plugins/cloudbuild/CHANGELOG.md
@@ -1,5 +1,19 @@
# @backstage/plugin-cloudbuild
+## 0.2.6
+
+### Patch Changes
+
+- 94fdf4955: Get rid of all usages of @octokit/types, and bump the rest of the octokit dependencies to the latest version
+- Updated dependencies [f3b064e1c]
+- Updated dependencies [c00488983]
+- Updated dependencies [265a7ab30]
+- Updated dependencies [abbee6fff]
+- Updated dependencies [147fadcb9]
+ - @backstage/catalog-model@0.6.1
+ - @backstage/plugin-catalog@0.2.11
+ - @backstage/core@0.4.4
+
## 0.2.5
### Patch Changes
diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json
index 9434ec70c8..5b55f1df5a 100644
--- a/plugins/cloudbuild/package.json
+++ b/plugins/cloudbuild/package.json
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-cloudbuild",
- "version": "0.2.5",
+ "version": "0.2.6",
"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.6.0",
- "@backstage/core": "^0.4.3",
- "@backstage/plugin-catalog": "^0.2.7",
+ "@backstage/catalog-model": "^0.6.1",
+ "@backstage/core": "^0.4.4",
+ "@backstage/plugin-catalog": "^0.2.11",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -47,7 +47,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json
index fd0b0e8e7d..f0538720ab 100644
--- a/plugins/cost-insights/package.json
+++ b/plugins/cost-insights/package.json
@@ -31,7 +31,7 @@
},
"dependencies": {
"@backstage/config": "^0.1.2",
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -55,7 +55,7 @@
"yup": "^0.29.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/explore/package.json b/plugins/explore/package.json
index 5c109d6a9e..613c0cb098 100644
--- a/plugins/explore/package.json
+++ b/plugins/explore/package.json
@@ -30,7 +30,7 @@
"start": "backstage-cli plugin:serve"
},
"dependencies": {
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -42,7 +42,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json
index 3036554fad..81e047e7ab 100644
--- a/plugins/fossa/package.json
+++ b/plugins/fossa/package.json
@@ -32,7 +32,7 @@
},
"dependencies": {
"@backstage/catalog-model": "^0.6.0",
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -43,7 +43,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json
index f2202054db..797b63bda9 100644
--- a/plugins/gcp-projects/package.json
+++ b/plugins/gcp-projects/package.json
@@ -30,7 +30,7 @@
"clean": "backstage-cli clean"
},
"dependencies": {
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -41,7 +41,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md
index f2537742f4..7aead61ed2 100644
--- a/plugins/github-actions/CHANGELOG.md
+++ b/plugins/github-actions/CHANGELOG.md
@@ -1,5 +1,20 @@
# @backstage/plugin-github-actions
+## 0.2.7
+
+### Patch Changes
+
+- 94fdf4955: Get rid of all usages of @octokit/types, and bump the rest of the octokit dependencies to the latest version
+- a6f9dca0d: Remove dependency on `@backstage/core-api`. No plugin should ever depend on that package; it's an internal concern whose important bits are re-exported by `@backstage/core` which is the public facing dependency to use.
+- Updated dependencies [f3b064e1c]
+- Updated dependencies [c00488983]
+- Updated dependencies [265a7ab30]
+- Updated dependencies [abbee6fff]
+- Updated dependencies [147fadcb9]
+ - @backstage/catalog-model@0.6.1
+ - @backstage/plugin-catalog@0.2.11
+ - @backstage/core@0.4.4
+
## 0.2.6
### Patch Changes
diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json
index f876eb9e7c..9b2d199b1f 100644
--- a/plugins/github-actions/package.json
+++ b/plugins/github-actions/package.json
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-github-actions",
- "version": "0.2.6",
+ "version": "0.2.7",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -32,10 +32,9 @@
"clean": "backstage-cli clean"
},
"dependencies": {
- "@backstage/catalog-model": "^0.6.0",
- "@backstage/core": "^0.4.3",
- "@backstage/core-api": "^0.2.7",
- "@backstage/plugin-catalog": "^0.2.8",
+ "@backstage/catalog-model": "^0.6.1",
+ "@backstage/core": "^0.4.4",
+ "@backstage/plugin-catalog": "^0.2.11",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -50,7 +49,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx
index 1d6001e038..0fd77c0443 100644
--- a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx
+++ b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-import type { Props as RecentWorkflowRunsCardProps } from './RecentWorkflowRunsCard';
-import React from 'react';
-import { render } from '@testing-library/react';
-import { RecentWorkflowRunsCard } from './RecentWorkflowRunsCard';
-import { ApiProvider, ApiRegistry, errorApiRef } from '@backstage/core-api';
-import { useWorkflowRuns } from '../useWorkflowRuns';
-import { ThemeProvider } from '@material-ui/core';
+import { ApiProvider, ApiRegistry, errorApiRef } from '@backstage/core';
import { lightTheme } from '@backstage/theme';
+import { ThemeProvider } from '@material-ui/core';
+import { render } from '@testing-library/react';
+import React from 'react';
import { MemoryRouter } from 'react-router';
+import { useWorkflowRuns } from '../useWorkflowRuns';
+import type { Props as RecentWorkflowRunsCardProps } from './RecentWorkflowRunsCard';
+import { RecentWorkflowRunsCard } from './RecentWorkflowRunsCard';
jest.mock('../useWorkflowRuns', () => ({
useWorkflowRuns: jest.fn(),
diff --git a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx
index 70348ece0a..9bb52b9ab1 100644
--- a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx
+++ b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx
@@ -14,14 +14,19 @@
* limitations under the License.
*/
import { Entity } from '@backstage/catalog-model';
-import { errorApiRef, useApi } from '@backstage/core-api';
+import {
+ EmptyState,
+ errorApiRef,
+ InfoCard,
+ Table,
+ useApi,
+} from '@backstage/core';
+import { Button, Link } from '@material-ui/core';
+import React, { useEffect } from 'react';
+import { generatePath, Link as RouterLink } from 'react-router-dom';
import { GITHUB_ACTIONS_ANNOTATION } from '../useProjectName';
import { useWorkflowRuns } from '../useWorkflowRuns';
-import React, { useEffect } from 'react';
-import { EmptyState, InfoCard, Table } from '@backstage/core';
import { WorkflowRunStatus } from '../WorkflowRunStatus';
-import { Button, Link } from '@material-ui/core';
-import { generatePath, Link as RouterLink } from 'react-router-dom';
const firstLine = (message: string): string => message.split('\n')[0];
diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json
index 28fead7796..61adfe5d67 100644
--- a/plugins/gitops-profiles/package.json
+++ b/plugins/gitops-profiles/package.json
@@ -31,7 +31,7 @@
"clean": "backstage-cli clean"
},
"dependencies": {
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -42,7 +42,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/graphiql/CHANGELOG.md b/plugins/graphiql/CHANGELOG.md
index 9c1289febc..fa33128f45 100644
--- a/plugins/graphiql/CHANGELOG.md
+++ b/plugins/graphiql/CHANGELOG.md
@@ -1,5 +1,13 @@
# @backstage/plugin-graphiql
+## 0.2.5
+
+### Patch Changes
+
+- 5a1368ba1: Updated README
+- Updated dependencies [265a7ab30]
+ - @backstage/core@0.4.4
+
## 0.2.4
### Patch Changes
diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json
index 341c4c14f7..f995dc4ebc 100644
--- a/plugins/graphiql/package.json
+++ b/plugins/graphiql/package.json
@@ -1,7 +1,7 @@
{
"name": "@backstage/plugin-graphiql",
"description": "Backstage plugin for browsing GraphQL APIs",
- "version": "0.2.4",
+ "version": "0.2.5",
"private": false,
"publishConfig": {
"access": "public",
@@ -31,7 +31,7 @@
"clean": "backstage-cli clean"
},
"dependencies": {
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -43,7 +43,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/jenkins/CHANGELOG.md b/plugins/jenkins/CHANGELOG.md
index 78792789cf..bcddeedf29 100644
--- a/plugins/jenkins/CHANGELOG.md
+++ b/plugins/jenkins/CHANGELOG.md
@@ -1,5 +1,19 @@
# @backstage/plugin-jenkins
+## 0.3.5
+
+### Patch Changes
+
+- feabc7f0c: Handle missing ObjectMetadataAction in Jenkins API
+- Updated dependencies [f3b064e1c]
+- Updated dependencies [c00488983]
+- Updated dependencies [265a7ab30]
+- Updated dependencies [abbee6fff]
+- Updated dependencies [147fadcb9]
+ - @backstage/catalog-model@0.6.1
+ - @backstage/plugin-catalog@0.2.11
+ - @backstage/core@0.4.4
+
## 0.3.4
### Patch Changes
diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json
index 99d69cf50e..f8c0b3fd76 100644
--- a/plugins/jenkins/package.json
+++ b/plugins/jenkins/package.json
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-jenkins",
- "version": "0.3.4",
+ "version": "0.3.5",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -31,9 +31,9 @@
"clean": "backstage-cli clean"
},
"dependencies": {
- "@backstage/catalog-model": "^0.6.0",
- "@backstage/core": "^0.4.3",
- "@backstage/plugin-catalog": "^0.2.7",
+ "@backstage/catalog-model": "^0.6.1",
+ "@backstage/core": "^0.4.4",
+ "@backstage/plugin-catalog": "^0.2.11",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -46,7 +46,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md
index 9b247c174f..eeb710fce4 100644
--- a/plugins/kubernetes-backend/CHANGELOG.md
+++ b/plugins/kubernetes-backend/CHANGELOG.md
@@ -1,5 +1,16 @@
# @backstage/plugin-kubernetes-backend
+## 0.2.4
+
+### Patch Changes
+
+- 5a9a7e7c2: Revamped Kubernetes UI and added error reporting/detection
+- Updated dependencies [f3b064e1c]
+- Updated dependencies [abbee6fff]
+- Updated dependencies [147fadcb9]
+ - @backstage/catalog-model@0.6.1
+ - @backstage/backend-common@0.4.3
+
## 0.2.3
### Patch Changes
diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json
index 66a36f8395..56c6707427 100644
--- a/plugins/kubernetes-backend/package.json
+++ b/plugins/kubernetes-backend/package.json
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-kubernetes-backend",
- "version": "0.2.3",
+ "version": "0.2.4",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -31,10 +31,10 @@
"clean": "backstage-cli clean"
},
"dependencies": {
- "@backstage/backend-common": "^0.4.1",
- "@backstage/catalog-model": "^0.6.0",
+ "@backstage/backend-common": "^0.4.3",
+ "@backstage/catalog-model": "^0.6.1",
"@backstage/config": "^0.1.2",
- "@kubernetes/client-node": "^0.12.1",
+ "@kubernetes/client-node": "^0.13.2",
"@types/express": "^4.17.6",
"compression": "^1.7.4",
"cors": "^2.8.5",
@@ -49,7 +49,7 @@
"yn": "^4.0.0"
},
"devDependencies": {
- "@backstage/cli": "^0.4.2",
+ "@backstage/cli": "^0.4.6",
"supertest": "^4.0.2"
},
"files": [
diff --git a/plugins/kubernetes-backend/src/service/KubernetesFetcher.test.ts b/plugins/kubernetes-backend/src/service/KubernetesFetcher.test.ts
index 29233cf7fd..8d29439539 100644
--- a/plugins/kubernetes-backend/src/service/KubernetesFetcher.test.ts
+++ b/plugins/kubernetes-backend/src/service/KubernetesFetcher.test.ts
@@ -197,6 +197,27 @@ describe('KubernetesClientProvider', () => {
});
// they're in testErrorResponse
// eslint-disable-next-line jest/expect-expect
+ it('should return pods, bad request error', async () => {
+ await testErrorResponse(
+ {
+ response: {
+ statusCode: 400,
+ request: {
+ uri: {
+ pathname: '/some/path',
+ },
+ },
+ },
+ },
+ {
+ errorType: 'BAD_REQUEST',
+ resourcePath: '/some/path',
+ statusCode: 400,
+ },
+ );
+ });
+ // they're in testErrorResponse
+ // eslint-disable-next-line jest/expect-expect
it('should return pods, unauthorized error', async () => {
await testErrorResponse(
{
diff --git a/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts b/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts
index d9c6ee6d1a..991174e78a 100644
--- a/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts
+++ b/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts
@@ -74,6 +74,8 @@ function fetchResultsToResponseWrapper(
const statusCodeToErrorType = (statusCode: number): KubernetesErrorTypes => {
switch (statusCode) {
+ case 400:
+ return 'BAD_REQUEST';
case 401:
return 'UNAUTHORIZED_ERROR';
case 500:
diff --git a/plugins/kubernetes-backend/src/types/types.ts b/plugins/kubernetes-backend/src/types/types.ts
index 9f0b90c032..cf6576153b 100644
--- a/plugins/kubernetes-backend/src/types/types.ts
+++ b/plugins/kubernetes-backend/src/types/types.ts
@@ -135,6 +135,7 @@ export interface KubernetesClustersSupplier {
}
export type KubernetesErrorTypes =
+ | 'BAD_REQUEST'
| 'UNAUTHORIZED_ERROR'
| 'SYSTEM_ERROR'
| 'UNKNOWN_ERROR';
diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md
index ef5b51cfb9..997676bef7 100644
--- a/plugins/kubernetes/CHANGELOG.md
+++ b/plugins/kubernetes/CHANGELOG.md
@@ -1,5 +1,26 @@
# @backstage/plugin-kubernetes
+## 0.3.5
+
+### Patch Changes
+
+- 1fea88fd0: Fixed an issue where assets weren't properly bundled in the published package.
+
+## 0.3.4
+
+### Patch Changes
+
+- 5a9a7e7c2: Revamped Kubernetes UI and added error reporting/detection
+- 3e7c09c84: Minor updates to display of errors
+- Updated dependencies [5a9a7e7c2]
+- Updated dependencies [f3b064e1c]
+- Updated dependencies [265a7ab30]
+- Updated dependencies [abbee6fff]
+- Updated dependencies [147fadcb9]
+ - @backstage/plugin-kubernetes-backend@0.2.4
+ - @backstage/catalog-model@0.6.1
+ - @backstage/core@0.4.4
+
## 0.3.3
### Patch Changes
diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json
index f00c846163..554bfe69ab 100644
--- a/plugins/kubernetes/package.json
+++ b/plugins/kubernetes/package.json
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-kubernetes",
- "version": "0.3.3",
+ "version": "0.3.5",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -31,12 +31,12 @@
"clean": "backstage-cli clean"
},
"dependencies": {
- "@backstage/catalog-model": "^0.6.0",
+ "@backstage/catalog-model": "^0.6.1",
"@backstage/config": "^0.1.2",
- "@backstage/core": "^0.4.3",
- "@backstage/plugin-kubernetes-backend": "^0.2.3",
+ "@backstage/core": "^0.4.4",
+ "@backstage/plugin-kubernetes-backend": "^0.2.4",
"@backstage/theme": "^0.2.2",
- "@kubernetes/client-node": "^0.12.1",
+ "@kubernetes/client-node": "^0.13.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.45",
@@ -47,7 +47,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/kubernetes/assets/emptystate.svg b/plugins/kubernetes/src/assets/emptystate.svg
similarity index 98%
rename from plugins/kubernetes/assets/emptystate.svg
rename to plugins/kubernetes/src/assets/emptystate.svg
index fa7f19123e..f01a74f374 100644
--- a/plugins/kubernetes/assets/emptystate.svg
+++ b/plugins/kubernetes/src/assets/emptystate.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/plugins/kubernetes/src/components/ErrorReporting/ErrorReporting.tsx b/plugins/kubernetes/src/components/ErrorReporting/ErrorReporting.tsx
index c986c0158d..21f66f28c0 100644
--- a/plugins/kubernetes/src/components/ErrorReporting/ErrorReporting.tsx
+++ b/plugins/kubernetes/src/components/ErrorReporting/ErrorReporting.tsx
@@ -17,7 +17,7 @@ import * as React from 'react';
import { Table, TableColumn, InfoCard } from '@backstage/core';
import { DetectedError, DetectedErrorsByCluster } from '../../error-detection';
import { Chip, Typography, Grid } from '@material-ui/core';
-import EmptyStateImage from '../../../assets/emptystate.svg';
+import EmptyStateImage from '../../assets/emptystate.svg';
type ErrorReportingProps = {
detectedErrors: DetectedErrorsByCluster;
@@ -113,17 +113,17 @@ export const ErrorEmptyState = () => {
return (
-
+
Nice! There are no errors to report!
-
+
{
// title
expect(
getByText(
- 'There was an error retrieving some Kubernetes resources for the entity: THIS_ENTITY',
+ 'There was a problem retrieving some Kubernetes resources for the entity: THIS_ENTITY. This could mean that the Error Reporting card is not completely accurate.',
),
).toBeInTheDocument();
@@ -67,7 +67,7 @@ describe('ErrorPanel', () => {
// title
expect(
getByText(
- 'There was an error retrieving some Kubernetes resources for the entity: THIS_ENTITY',
+ 'There was a problem retrieving some Kubernetes resources for the entity: THIS_ENTITY. This could mean that the Error Reporting card is not completely accurate.',
),
).toBeInTheDocument();
diff --git a/plugins/kubernetes/src/components/KubernetesContent/ErrorPanel.tsx b/plugins/kubernetes/src/components/KubernetesContent/ErrorPanel.tsx
index 85060fc11b..650e6ddff1 100644
--- a/plugins/kubernetes/src/components/KubernetesContent/ErrorPanel.tsx
+++ b/plugins/kubernetes/src/components/KubernetesContent/ErrorPanel.tsx
@@ -52,8 +52,8 @@ export const ErrorPanel = ({
clustersWithErrors,
}: ErrorPanelProps) => (
{clustersWithErrors && (
Errors: {clustersWithErrorsToErrorMessage(clustersWithErrors)}
diff --git a/plugins/kubernetes/src/components/KubernetesContent/KubernetesContent.tsx b/plugins/kubernetes/src/components/KubernetesContent/KubernetesContent.tsx
index 293e7a4833..39e73782f1 100644
--- a/plugins/kubernetes/src/components/KubernetesContent/KubernetesContent.tsx
+++ b/plugins/kubernetes/src/components/KubernetesContent/KubernetesContent.tsx
@@ -106,51 +106,55 @@ export const KubernetesContent = ({ entity }: KubernetesContentProps) => {
return (
-
- {kubernetesObjects === undefined && error === undefined && (
-
- )}
+ {kubernetesObjects === undefined && error === undefined && }
- {/* errors retrieved from the kubernetes clusters */}
- {clustersWithErrors.length > 0 && (
-
- )}
+ {/* errors retrieved from the kubernetes clusters */}
+ {clustersWithErrors.length > 0 && (
+
+
+
+
+
+ )}
- {/* other errors */}
- {error !== undefined && (
-
- )}
+ {/* other errors */}
+ {error !== undefined && (
+
+
+
+
+
+ )}
- {kubernetesObjects && (
- <>
-
-
-
-
-
-
-
- Your Clusters
-
-
- {kubernetesObjects?.items.map((item, i) => (
-
-
-
- ))}
-
- >
- )}
-
+ {kubernetesObjects && (
+
+
+
+
+
+
+
+
+ Your Clusters
+
+
+ {kubernetesObjects?.items.map((item, i) => (
+
+
+
+ ))}
+
+
+ )}
);
diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md
index 42035d1209..b70539f6fa 100644
--- a/plugins/lighthouse/CHANGELOG.md
+++ b/plugins/lighthouse/CHANGELOG.md
@@ -1,5 +1,20 @@
# @backstage/plugin-lighthouse
+## 0.2.7
+
+### Patch Changes
+
+- cf7df3b1f: Strip trailing slash from url when creating a new audit. This change prevents duplicate audits from being displayed in the audit list.
+- a6f9dca0d: Remove dependency on `@backstage/core-api`. No plugin should ever depend on that package; it's an internal concern whose important bits are re-exported by `@backstage/core` which is the public facing dependency to use.
+- Updated dependencies [f3b064e1c]
+- Updated dependencies [c00488983]
+- Updated dependencies [265a7ab30]
+- Updated dependencies [abbee6fff]
+- Updated dependencies [147fadcb9]
+ - @backstage/catalog-model@0.6.1
+ - @backstage/plugin-catalog@0.2.11
+ - @backstage/core@0.4.4
+
## 0.2.6
### Patch Changes
diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json
index f688f9c1db..6f4892da6c 100644
--- a/plugins/lighthouse/package.json
+++ b/plugins/lighthouse/package.json
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-lighthouse",
- "version": "0.2.6",
+ "version": "0.2.7",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -31,11 +31,10 @@
"start": "backstage-cli plugin:serve"
},
"dependencies": {
- "@backstage/catalog-model": "^0.6.0",
+ "@backstage/catalog-model": "^0.6.1",
"@backstage/config": "^0.1.2",
- "@backstage/core": "^0.4.3",
- "@backstage/core-api": "^0.2.6",
- "@backstage/plugin-catalog": "^0.2.7",
+ "@backstage/core": "^0.4.4",
+ "@backstage/plugin-catalog": "^0.2.11",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -47,7 +46,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx b/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx
index 7f5925abf8..c1773921cf 100644
--- a/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx
+++ b/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx
@@ -15,7 +15,7 @@
*/
import React, { PropsWithChildren } from 'react';
import { renderHook } from '@testing-library/react-hooks';
-import { ApiProvider, ApiRegistry, errorApiRef } from '@backstage/core-api';
+import { ApiProvider, ApiRegistry, errorApiRef } from '@backstage/core';
import { lighthouseApiRef, WebsiteListResponse } from '../api';
import { useWebsiteForEntity } from './useWebsiteForEntity';
import { EntityContext } from '@backstage/plugin-catalog';
diff --git a/plugins/lighthouse/src/hooks/useWebsiteForEntity.ts b/plugins/lighthouse/src/hooks/useWebsiteForEntity.ts
index c52e38f473..08d9925b7a 100644
--- a/plugins/lighthouse/src/hooks/useWebsiteForEntity.ts
+++ b/plugins/lighthouse/src/hooks/useWebsiteForEntity.ts
@@ -15,7 +15,7 @@
*/
import { useEntity } from '@backstage/plugin-catalog';
import { LIGHTHOUSE_WEBSITE_URL_ANNOTATION } from '../../constants';
-import { errorApiRef, useApi } from '@backstage/core-api';
+import { errorApiRef, useApi } from '@backstage/core';
import { lighthouseApiRef } from '../api';
import { useAsync } from 'react-use';
diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json
index 629dec635b..6d6eb4ac5c 100644
--- a/plugins/newrelic/package.json
+++ b/plugins/newrelic/package.json
@@ -31,7 +31,7 @@
"clean": "backstage-cli clean"
},
"dependencies": {
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -41,7 +41,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md
index 13025d8e83..e1bcf20114 100644
--- a/plugins/org/CHANGELOG.md
+++ b/plugins/org/CHANGELOG.md
@@ -1,5 +1,19 @@
# @backstage/plugin-org
+## 0.3.3
+
+### Patch Changes
+
+- f573cf368: Fixed - normalizing strings for comparison when ignoring when one is in low case.
+- Updated dependencies [f3b064e1c]
+- Updated dependencies [c00488983]
+- Updated dependencies [265a7ab30]
+- Updated dependencies [abbee6fff]
+- Updated dependencies [147fadcb9]
+ - @backstage/catalog-model@0.6.1
+ - @backstage/plugin-catalog@0.2.11
+ - @backstage/core@0.4.4
+
## 0.3.2
### Patch Changes
diff --git a/plugins/org/package.json b/plugins/org/package.json
index 9db6fff348..90cbf2aa57 100644
--- a/plugins/org/package.json
+++ b/plugins/org/package.json
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-org",
- "version": "0.3.2",
+ "version": "0.3.3",
"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.6.0",
- "@backstage/core": "^0.4.3",
- "@backstage/plugin-catalog": "^0.2.7",
+ "@backstage/catalog-model": "^0.6.1",
+ "@backstage/core": "^0.4.4",
+ "@backstage/plugin-catalog": "^0.2.11",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -33,7 +33,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json
index 1db99822a2..6bfcf86a89 100644
--- a/plugins/pagerduty/package.json
+++ b/plugins/pagerduty/package.json
@@ -31,7 +31,7 @@
},
"dependencies": {
"@backstage/catalog-model": "^0.6.0",
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -44,7 +44,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/register-component/package.json b/plugins/register-component/package.json
index 56451b7958..955092c2ee 100644
--- a/plugins/register-component/package.json
+++ b/plugins/register-component/package.json
@@ -31,7 +31,7 @@
},
"dependencies": {
"@backstage/catalog-model": "^0.6.0",
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/plugin-catalog": "^0.2.9",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
@@ -45,7 +45,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json
index 37c9cec4c0..e7bfd4f379 100644
--- a/plugins/rollbar/package.json
+++ b/plugins/rollbar/package.json
@@ -32,7 +32,7 @@
},
"dependencies": {
"@backstage/catalog-model": "^0.6.0",
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/plugin-catalog": "^0.2.7",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
@@ -47,7 +47,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md
index ee54a5c794..80330bbce3 100644
--- a/plugins/scaffolder-backend/CHANGELOG.md
+++ b/plugins/scaffolder-backend/CHANGELOG.md
@@ -1,5 +1,26 @@
# @backstage/plugin-scaffolder-backend
+## 0.4.1
+
+### Patch Changes
+
+- 94fdf4955: Get rid of all usages of @octokit/types, and bump the rest of the octokit dependencies to the latest version
+- cc068c0d6: Bump the gitbeaker dependencies to 28.x.
+
+ To update your own installation, go through the `package.json` files of all of
+ your packages, and ensure that all dependencies on `@gitbeaker/node` or
+ `@gitbeaker/core` are at version `^28.0.2`. Then run `yarn install` at the root
+ of your repo.
+
+- 711ba55a2: Export all preparers and publishers properly
+- Updated dependencies [466354aaa]
+- Updated dependencies [f3b064e1c]
+- Updated dependencies [abbee6fff]
+- Updated dependencies [147fadcb9]
+ - @backstage/integration@0.2.0
+ - @backstage/catalog-model@0.6.1
+ - @backstage/backend-common@0.4.3
+
## 0.4.0
### Minor Changes
diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json
index 7855dcd349..134f63f96a 100644
--- a/plugins/scaffolder-backend/package.json
+++ b/plugins/scaffolder-backend/package.json
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-scaffolder-backend",
- "version": "0.4.0",
+ "version": "0.4.1",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -29,10 +29,10 @@
"clean": "backstage-cli clean"
},
"dependencies": {
- "@backstage/backend-common": "^0.4.2",
- "@backstage/catalog-model": "^0.6.0",
+ "@backstage/backend-common": "^0.4.3",
+ "@backstage/catalog-model": "^0.6.1",
"@backstage/config": "^0.1.2",
- "@backstage/integration": "^0.1.5",
+ "@backstage/integration": "^0.2.0",
"@gitbeaker/core": "^28.0.2",
"@gitbeaker/node": "^28.0.2",
"@octokit/rest": "^18.0.12",
@@ -58,7 +58,7 @@
"yaml": "^1.10.0"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/test-utils": "^0.1.5",
"@types/fs-extra": "^9.0.1",
"@types/git-url-parse": "^9.0.0",
diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts
index a38c5f4fdc..51763c6291 100644
--- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts
+++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts
@@ -20,7 +20,7 @@ import { TemplateEntityV1alpha1 } from '@backstage/catalog-model';
import { parseLocationAnnotation } from '../helpers';
import { InputError, Git } from '@backstage/backend-common';
import { PreparerBase, PreparerOptions } from './types';
-import GitUriParser from 'git-url-parse';
+import parseGitUrl from 'git-url-parse';
import { Config } from '@backstage/config';
export class AzurePreparer implements PreparerBase {
@@ -46,7 +46,7 @@ export class AzurePreparer implements PreparerBase {
}
const templateId = template.metadata.name;
- const parsedGitLocation = GitUriParser(location);
+ const parsedGitLocation = parseGitUrl(location);
const repositoryCheckoutUrl = parsedGitLocation.toString('https');
const tempDir = await fs.promises.mkdtemp(
path.join(workingDirectory, templateId),
diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/bitbucket.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/bitbucket.ts
index 5b244d24ce..278b481da2 100644
--- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/bitbucket.ts
+++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/bitbucket.ts
@@ -20,7 +20,7 @@ import { TemplateEntityV1alpha1 } from '@backstage/catalog-model';
import { parseLocationAnnotation } from '../helpers';
import { InputError, Git } from '@backstage/backend-common';
import { PreparerBase, PreparerOptions } from './types';
-import GitUriParser from 'git-url-parse';
+import parseGitUrl from 'git-url-parse';
import { Config } from '@backstage/config';
export class BitbucketPreparer implements PreparerBase {
@@ -49,7 +49,7 @@ export class BitbucketPreparer implements PreparerBase {
}
const templateId = template.metadata.name;
- const repo = GitUriParser(location);
+ const repo = parseGitUrl(location);
const repositoryCheckoutUrl = repo.toString('https');
const tempDir = await fs.promises.mkdtemp(
diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts
index e7fa0c9b72..c157263894 100644
--- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts
+++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts
@@ -20,7 +20,7 @@ import { TemplateEntityV1alpha1 } from '@backstage/catalog-model';
import { parseLocationAnnotation } from '../helpers';
import { InputError, Git } from '@backstage/backend-common';
import { PreparerBase, PreparerOptions } from './types';
-import GitUriParser from 'git-url-parse';
+import parseGitUrl from 'git-url-parse';
export class GithubPreparer implements PreparerBase {
token?: string;
@@ -44,7 +44,7 @@ export class GithubPreparer implements PreparerBase {
}
const templateId = template.metadata.name;
- const parsedGitLocation = GitUriParser(location);
+ const parsedGitLocation = parseGitUrl(location);
const repositoryCheckoutUrl = parsedGitLocation.toString('https');
const tempDir = await fs.promises.mkdtemp(
path.join(workingDirectory, templateId),
diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts
index 6e169baa98..9b0d468431 100644
--- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts
+++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts
@@ -21,7 +21,7 @@ import {
readGitLabIntegrationConfigs,
} from '@backstage/integration';
import fs from 'fs-extra';
-import GitUriParser from 'git-url-parse';
+import parseGitUrl from 'git-url-parse';
import os from 'os';
import path from 'path';
import { parseLocationAnnotation } from '../helpers';
@@ -55,7 +55,7 @@ export class GitlabPreparer implements PreparerBase {
}
const templateId = template.metadata.name;
- const parsedGitLocation = GitUriParser(location);
+ const parsedGitLocation = parseGitUrl(location);
const repositoryCheckoutUrl = parsedGitLocation.toString('https');
const tempDir = await fs.promises.mkdtemp(
path.join(workingDirectory, templateId),
diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json
index 0d6c1bdb37..655b7f324c 100644
--- a/plugins/scaffolder/package.json
+++ b/plugins/scaffolder/package.json
@@ -31,7 +31,7 @@
},
"dependencies": {
"@backstage/catalog-model": "^0.6.0",
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/plugin-catalog": "^0.2.10",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
@@ -50,7 +50,7 @@
"swr": "^0.3.0"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/search/package.json b/plugins/search/package.json
index aae095dafe..eb9512e52c 100644
--- a/plugins/search/package.json
+++ b/plugins/search/package.json
@@ -29,7 +29,7 @@
"clean": "backstage-cli clean"
},
"dependencies": {
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/plugin-catalog": "^0.2.10",
"@backstage/catalog-model": "^0.6.0",
"@backstage/theme": "^0.2.2",
@@ -43,7 +43,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json
index 6a1ef07436..5bf8fe1045 100644
--- a/plugins/sentry/package.json
+++ b/plugins/sentry/package.json
@@ -32,7 +32,7 @@
},
"dependencies": {
"@backstage/catalog-model": "^0.6.0",
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/plugin-catalog": "^0.2.10",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
@@ -46,7 +46,7 @@
"timeago.js": "^4.0.2"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json
index 8ca178f9fe..78c6343685 100644
--- a/plugins/sonarqube/package.json
+++ b/plugins/sonarqube/package.json
@@ -33,7 +33,7 @@
},
"dependencies": {
"@backstage/catalog-model": "^0.6.0",
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -46,7 +46,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json
index 326b0fe732..6e0663e159 100644
--- a/plugins/tech-radar/package.json
+++ b/plugins/tech-radar/package.json
@@ -30,7 +30,7 @@
"start": "backstage-cli plugin:serve"
},
"dependencies": {
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -43,7 +43,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md
index d83ff92fd4..9993456436 100644
--- a/plugins/techdocs-backend/CHANGELOG.md
+++ b/plugins/techdocs-backend/CHANGELOG.md
@@ -1,5 +1,27 @@
# @backstage/plugin-techdocs-backend
+## 0.5.3
+
+### Patch Changes
+
+- 68ad5af51: Improve techdocs-common Generator API for it to be used by techdocs-cli. TechDocs generator.run function now takes
+ an input AND an output directory. Most probably you use techdocs-common via plugin-techdocs-backend, and so there
+ is no breaking change for you.
+ But if you use techdocs-common separately, you need to create an output directory and pass into the generator.
+- cb7af51e7: If using Url Reader, cache downloaded source files for 30 minutes.
+- Updated dependencies [68ad5af51]
+- Updated dependencies [f3b064e1c]
+- Updated dependencies [371f67ecd]
+- Updated dependencies [f1e74777a]
+- Updated dependencies [dbe4450c3]
+- Updated dependencies [5826d0973]
+- Updated dependencies [b3b9445df]
+- Updated dependencies [abbee6fff]
+- Updated dependencies [147fadcb9]
+ - @backstage/techdocs-common@0.3.3
+ - @backstage/catalog-model@0.6.1
+ - @backstage/backend-common@0.4.3
+
## 0.5.2
### Patch Changes
diff --git a/plugins/techdocs-backend/examples/documented-component/documented-component.yaml b/plugins/techdocs-backend/examples/documented-component/catalog-info.yaml
similarity index 61%
rename from plugins/techdocs-backend/examples/documented-component/documented-component.yaml
rename to plugins/techdocs-backend/examples/documented-component/catalog-info.yaml
index 800116344f..d609866f9b 100644
--- a/plugins/techdocs-backend/examples/documented-component/documented-component.yaml
+++ b/plugins/techdocs-backend/examples/documented-component/catalog-info.yaml
@@ -4,7 +4,7 @@ metadata:
name: documented-component
description: A Service with TechDocs documentation
annotations:
- backstage.io/techdocs-ref: 'github:https://github.com/backstage/backstage/blob/master/plugins/techdocs-backend/examples/documented-component'
+ backstage.io/techdocs-ref: 'url:https://github.com/backstage/backstage/tree/master/plugins/techdocs-backend/examples/documented-component'
spec:
type: service
lifecycle: experimental
diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json
index 6b0aeec177..7c756641e2 100644
--- a/plugins/techdocs-backend/package.json
+++ b/plugins/techdocs-backend/package.json
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-techdocs-backend",
- "version": "0.5.2",
+ "version": "0.5.3",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -30,10 +30,10 @@
"clean": "backstage-cli clean"
},
"dependencies": {
- "@backstage/backend-common": "^0.4.2",
- "@backstage/catalog-model": "^0.6.0",
+ "@backstage/backend-common": "^0.4.3",
+ "@backstage/catalog-model": "^0.6.1",
"@backstage/config": "^0.1.2",
- "@backstage/techdocs-common": "^0.3.2",
+ "@backstage/techdocs-common": "^0.3.3",
"@types/dockerode": "^3.2.1",
"@types/express": "^4.17.6",
"cross-fetch": "^3.0.6",
@@ -45,7 +45,7 @@
"winston": "^3.2.1"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"supertest": "^4.0.2"
},
"files": [
diff --git a/plugins/techdocs-backend/src/DocsBuilder/builder.ts b/plugins/techdocs-backend/src/DocsBuilder/builder.ts
index 3d40f0a870..33d3120c47 100644
--- a/plugins/techdocs-backend/src/DocsBuilder/builder.ts
+++ b/plugins/techdocs-backend/src/DocsBuilder/builder.ts
@@ -144,6 +144,18 @@ export class DocsBuilder {
}
}
+ // Cache downloaded source files for 30 minutes.
+ // TODO: When urlReader/readTree supports some way to get latest commit timestamp,
+ // it should be used to invalidate cache.
+ if (type === 'url') {
+ const builtAt = buildMetadataStorage.getTimestamp();
+ const now = Date.now();
+
+ if (builtAt > now - 1800000) {
+ return true;
+ }
+ }
+
this.logger.debug(
`Docs for entity ${getEntityId(this.entity)} was outdated.`,
);
diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md
index 8bd79e4139..ee8860da46 100644
--- a/plugins/techdocs/CHANGELOG.md
+++ b/plugins/techdocs/CHANGELOG.md
@@ -1,5 +1,41 @@
# @backstage/plugin-techdocs
+## 0.5.3
+
+### Patch Changes
+
+- dbe4450c3: Google Cloud authentication in TechDocs has been improved.
+
+ 1. `techdocs.publisher.googleGcs.credentials` is now optional. If it is missing, `GOOGLE_APPLICATION_CREDENTIALS`
+ environment variable (and some other methods) will be used to authenticate.
+ Read more here https://cloud.google.com/docs/authentication/production
+
+ 2. `techdocs.publisher.googleGcs.projectId` is no longer used. You can remove it from your `app-config.yaml`.
+
+- a6f9dca0d: Remove dependency on `@backstage/core-api`. No plugin should ever depend on that package; it's an internal concern whose important bits are re-exported by `@backstage/core` which is the public facing dependency to use.
+- b3b9445df: AWS S3 authentication in TechDocs has been improved.
+
+ 1. `techdocs.publisher.awsS3.bucketName` is now the only required config. `techdocs.publisher.awsS3.credentials` and `techdocs.publisher.awsS3.region` are optional.
+
+ 2. If `techdocs.publisher.awsS3.credentials` and `techdocs.publisher.awsS3.region` are missing, the AWS environment variables `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_REGION` will be used. There are more better ways of setting up AWS authentication. Read the guide at https://backstage.io/docs/features/techdocs/using-cloud-storage
+
+- e5d12f705: Use `history.pushState` for hash link navigation.
+- Updated dependencies [68ad5af51]
+- Updated dependencies [f3b064e1c]
+- Updated dependencies [371f67ecd]
+- Updated dependencies [f1e74777a]
+- Updated dependencies [dbe4450c3]
+- Updated dependencies [c00488983]
+- Updated dependencies [265a7ab30]
+- Updated dependencies [5826d0973]
+- Updated dependencies [b3b9445df]
+- Updated dependencies [abbee6fff]
+- Updated dependencies [147fadcb9]
+ - @backstage/techdocs-common@0.3.3
+ - @backstage/catalog-model@0.6.1
+ - @backstage/plugin-catalog@0.2.11
+ - @backstage/core@0.4.4
+
## 0.5.2
### Patch Changes
diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json
index 955b0f798c..fb26087790 100644
--- a/plugins/techdocs/package.json
+++ b/plugins/techdocs/package.json
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-techdocs",
- "version": "0.5.2",
+ "version": "0.5.3",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -31,13 +31,12 @@
"clean": "backstage-cli clean"
},
"dependencies": {
- "@backstage/catalog-model": "^0.6.0",
- "@backstage/core": "^0.4.3",
- "@backstage/core-api": "^0.2.8",
- "@backstage/plugin-catalog": "^0.2.9",
+ "@backstage/catalog-model": "^0.6.1",
+ "@backstage/core": "^0.4.4",
+ "@backstage/plugin-catalog": "^0.2.11",
"@backstage/test-utils": "^0.1.6",
"@backstage/theme": "^0.2.2",
- "@backstage/techdocs-common": "^0.3.1",
+ "@backstage/techdocs-common": "^0.3.3",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.45",
@@ -50,7 +49,7 @@
"sanitize-html": "^1.27.0"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/techdocs/src/reader/components/TechDocsHome.test.tsx b/plugins/techdocs/src/reader/components/TechDocsHome.test.tsx
index 0924b90fc1..4979f027a6 100644
--- a/plugins/techdocs/src/reader/components/TechDocsHome.test.tsx
+++ b/plugins/techdocs/src/reader/components/TechDocsHome.test.tsx
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { ApiProvider, ApiRegistry } from '@backstage/core-api';
+import { ApiProvider, ApiRegistry } from '@backstage/core';
import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog';
import { wrapInTestApp } from '@backstage/test-utils';
import { render } from '@testing-library/react';
diff --git a/plugins/techdocs/src/reader/components/TechDocsPage.test.tsx b/plugins/techdocs/src/reader/components/TechDocsPage.test.tsx
index c05c0488ff..bc84f792a7 100644
--- a/plugins/techdocs/src/reader/components/TechDocsPage.test.tsx
+++ b/plugins/techdocs/src/reader/components/TechDocsPage.test.tsx
@@ -17,7 +17,7 @@ import React from 'react';
import { TechDocsPage } from './TechDocsPage';
import { render, act } from '@testing-library/react';
import { wrapInTestApp } from '@backstage/test-utils';
-import { ApiRegistry, ApiProvider } from '@backstage/core-api';
+import { ApiRegistry, ApiProvider } from '@backstage/core';
import {
techdocsApiRef,
TechDocsApi,
diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json
index 38b26dd94c..33b1d1aa46 100644
--- a/plugins/user-settings/package.json
+++ b/plugins/user-settings/package.json
@@ -30,7 +30,7 @@
"clean": "backstage-cli clean"
},
"dependencies": {
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -41,7 +41,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/plugins/welcome/package.json b/plugins/welcome/package.json
index d215028960..7ac7dd43b8 100644
--- a/plugins/welcome/package.json
+++ b/plugins/welcome/package.json
@@ -30,7 +30,7 @@
"start": "backstage-cli plugin:serve"
},
"dependencies": {
- "@backstage/core": "^0.4.3",
+ "@backstage/core": "^0.4.4",
"@backstage/theme": "^0.2.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
@@ -41,7 +41,7 @@
"react-use": "^15.3.3"
},
"devDependencies": {
- "@backstage/cli": "^0.4.5",
+ "@backstage/cli": "^0.4.6",
"@backstage/dev-utils": "^0.1.7",
"@backstage/test-utils": "^0.1.6",
"@testing-library/jest-dom": "^5.10.1",
diff --git a/scripts/check-if-release.js b/scripts/check-if-release.js
new file mode 100755
index 0000000000..57a0ad792c
--- /dev/null
+++ b/scripts/check-if-release.js
@@ -0,0 +1,101 @@
+#!/usr/bin/env node
+/* eslint-disable import/no-extraneous-dependencies */
+/*
+ * 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.
+ */
+
+// This script is used to determine whether a particular commit has changes
+// that should lead to a release. It is run as part of the main master build
+// to determine whether the release flow should be run as well.
+//
+// It has the following output which can be used later in GitHub actions:
+//
+// needs_release = 'true' | 'false'
+
+const { execFile: execFileCb } = require('child_process');
+const { resolve: resolvePath } = require('path');
+const { promises: fs } = require('fs');
+const { promisify } = require('util');
+
+const parentRef = process.env.COMMIT_SHA_BEFORE || 'HEAD^';
+
+const execFile = promisify(execFileCb);
+
+async function runPlain(cmd, ...args) {
+ try {
+ const { stdout } = await execFile(cmd, args, { shell: true });
+ return stdout.trim();
+ } catch (error) {
+ if (error.stderr) {
+ process.stderr.write(error.stderr);
+ }
+ if (!error.code) {
+ throw error;
+ }
+ throw new Error(
+ `Command '${[cmd, ...args].join(' ')}' failed with code ${error.code}`,
+ );
+ }
+}
+
+async function main() {
+ process.cwd(resolvePath(__dirname, '..'));
+
+ const diff = await runPlain(
+ 'git',
+ 'diff',
+ '--name-only',
+ parentRef,
+ 'packages/*/package.json',
+ 'plugins/*/package.json',
+ );
+ const packageList = diff.split(/^(.*)$/gm).filter(s => s.trim());
+
+ const packageVersions = await Promise.all(
+ packageList.map(async path => {
+ const { name, version: newVersion } = JSON.parse(
+ await fs.readFile(path, 'utf8'),
+ );
+ const { version: oldVersion } = JSON.parse(
+ await runPlain('git', 'show', `${parentRef}:${path}`),
+ );
+ return { name, oldVersion, newVersion };
+ }),
+ );
+
+ const newVersions = packageVersions.filter(
+ ({ oldVersion, newVersion }) => oldVersion !== newVersion,
+ );
+
+ if (newVersions.length === 0) {
+ console.log('No package version bumps detected, no release needed');
+ console.log(`::set-output name=needs_release::false`);
+ return;
+ }
+
+ console.log('Package version bumps detected, a new release is needed');
+ const maxLength = Math.max(...newVersions.map(_ => _.name.length));
+ for (const { name, oldVersion, newVersion } of newVersions) {
+ console.log(
+ ` ${name.padEnd(maxLength, ' ')} ${oldVersion} -> ${newVersion}`,
+ );
+ }
+ console.log(`::set-output name=needs_release::true`);
+}
+
+main().catch(error => {
+ console.error(error.stack);
+ process.exit(1);
+});
diff --git a/scripts/create-github-release.js b/scripts/create-github-release.js
index a9bfb9f5b3..1d6a493db3 100755
--- a/scripts/create-github-release.js
+++ b/scripts/create-github-release.js
@@ -53,7 +53,8 @@ if (!BOOL_CREATE_RELEASE) {
const GH_OWNER = 'backstage';
const GH_REPO = 'backstage';
-const EXPECTED_COMMIT_MESSAGE = /^Merge pull request #(?[0-9]+) from backstage\/changeset-release\/master\n\nVersion Packages$/;
+const EXPECTED_COMMIT_MESSAGE = /^Merge pull request #(?[0-9]+) from/;
+const CHANGESET_RELEASE_BRANCH = 'backstage/changeset-release/master';
// Initialize a GitHub client
const octokit = new Octokit({
@@ -116,7 +117,7 @@ async function getCommitMessageUsingTagName(tagName) {
}
// There is a PR number in our expected commit message. Get the description of that PR.
-async function getPrDescriptionFromCommitMessage(commitMessage) {
+async function getReleaseDescriptionFromCommitMessage(commitMessage) {
// It should exactly match the pattern of changeset commit message, or else will abort.
const expectedMessage = RegExp(EXPECTED_COMMIT_MESSAGE);
if (!expectedMessage.test(commitMessage)) {
@@ -131,20 +132,19 @@ async function getPrDescriptionFromCommitMessage(commitMessage) {
`Identified the changeset Pull request - https://github.com/backstage/backstage/pull/${prNumber}`,
);
- const prData = await octokit.pulls.get({
+ const { data } = await octokit.pulls.get({
owner: GH_OWNER,
repo: GH_REPO,
pull_number: prNumber,
});
- return prData.data.body;
-}
+ // Use the PR description to prepare for the release description
+ const isChangesetRelease = commitMessage.includes(CHANGESET_RELEASE_BRANCH);
+ if (isChangesetRelease) {
+ return data.body.split('\n').slice(3).join('\n');
+ }
-// Use the PR description to prepare for the release description
-async function prepareReleaseDescription(prDescription) {
- // TODO: Refine prDescription to remove the lines containing "Update Dependencies"
- // Remove everything in the beginning until changelogs.
- return prDescription.split('\n').slice(3).join('\n');
+ return data.body;
}
// Create Release on GitHub.
@@ -178,8 +178,9 @@ async function createRelease(releaseDescription) {
async function main() {
const commitMessage = await getCommitMessageUsingTagName(TAG_NAME);
- const prDescription = await getPrDescriptionFromCommitMessage(commitMessage);
- const releaseDescription = await prepareReleaseDescription(prDescription);
+ const releaseDescription = await getReleaseDescriptionFromCommitMessage(
+ commitMessage,
+ );
await createRelease(releaseDescription);
}
diff --git a/scripts/verify-links.js b/scripts/verify-links.js
index 75e7a8c1d0..5ad14ead4d 100755
--- a/scripts/verify-links.js
+++ b/scripts/verify-links.js
@@ -18,8 +18,27 @@
/* eslint-disable import/no-extraneous-dependencies */
const { resolve: resolvePath, join: joinPath, dirname } = require('path');
-const fs = require('fs-extra');
-const recursive = require('recursive-readdir');
+const fs = require('fs').promises;
+const { existsSync } = require('fs');
+
+const IGNORED_DIRS = ['node_modules', 'dist', 'bin', '.git'];
+
+async function listFiles(dir) {
+ const files = await fs.readdir(dir);
+ const paths = await Promise.all(
+ files
+ .filter(file => !IGNORED_DIRS.includes(file))
+ .map(async file => {
+ const path = joinPath(dir, file);
+
+ if ((await fs.stat(path)).isDirectory()) {
+ return listFiles(path);
+ }
+ return path;
+ }),
+ );
+ return paths.flat();
+}
const projectRoot = resolvePath(__dirname, '..');
@@ -65,7 +84,7 @@ async function verifyUrl(basePath, absUrl, docPages) {
}
const staticPath = resolvePath(projectRoot, 'microsite/static', `.${url}`);
- if (await fs.pathExists(staticPath)) {
+ if (existsSync(staticPath)) {
return undefined;
}
@@ -82,8 +101,7 @@ async function verifyUrl(basePath, absUrl, docPages) {
return { url, basePath, problem: 'out-of-docs' };
}
- const exists = await fs.pathExists(path);
- if (!exists) {
+ if (!existsSync(path)) {
return { url, basePath, problem: 'missing' };
}
@@ -110,7 +128,7 @@ async function verifyFile(filePath, docPages) {
// It is used to validate microsite links from outside /docs/, as those
// are not transformed from the markdown file representation by docusaurus.
async function findExternalDocsLinks(dir) {
- const allFiles = await recursive(dir);
+ const allFiles = await listFiles(dir);
const mdFiles = allFiles.filter(p => p.endsWith('.md'));
const paths = new Map();
@@ -138,14 +156,15 @@ async function findExternalDocsLinks(dir) {
async function main() {
process.chdir(projectRoot);
- const files = await recursive('.', ['node_modules', 'dist', 'bin']);
+ const files = await listFiles('.');
const mdFiles = files.filter(f => f.endsWith('.md'));
const badUrls = [];
const docPages = await findExternalDocsLinks('docs');
+ const docPageSet = new Set(docPages.values());
for (const mdFile of mdFiles) {
- const badFileUrls = await verifyFile(mdFile, new Set(docPages.values()));
+ const badFileUrls = await verifyFile(mdFile, docPageSet);
badUrls.push(...badFileUrls);
}
diff --git a/yarn.lock b/yarn.lock
index b10819d4f2..6710c7e8e7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -879,21 +879,20 @@
dependencies:
tslib "^1.8.0"
-"@azure/msal-common@^1.6.2":
- version "1.6.2"
- resolved "https://registry.npmjs.org/@azure/msal-common/-/msal-common-1.6.2.tgz#91f3732866d727e20f1e142e6e88a981268fbff2"
- integrity sha512-GShzp1q7Ld8SwYiDEjQZ9PmFOY4x+2stE86maiguylE9/d/c2muqKjc8aepmEqyjbV7o/omDvEf2Sr9QcIqkSA==
+"@azure/msal-common@^2.1.0":
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/@azure/msal-common/-/msal-common-2.1.0.tgz#a4bc17e254d6ec524016f13267947dd4ff4a624d"
+ integrity sha512-Y1Id+jG59S3eY2ZQQtUA/lxwbRcgjcWaiib9YX+SwV3zeRauKfEiZT7l3z+lwV+T+Sst20F6l1mJsfQcfE7CEQ==
dependencies:
debug "^4.1.1"
-"@azure/msal-node@^1.0.0-alpha.8":
- version "1.0.0-alpha.12"
- resolved "https://registry.npmjs.org/@azure/msal-node/-/msal-node-1.0.0-alpha.12.tgz#09d8d52f5cea90b133c3d48fe4ec477693040c91"
- integrity sha512-uGLOJRWiEhfJIrTv/lwdm4RxQFm++00h83zNgDn0O3NkXlzAoCCq9QFYW84PjMR/Q2PUvVy7uW+6yKL/Nq3gBA==
+"@azure/msal-node@^1.0.0-beta.3":
+ version "1.0.0-beta.3"
+ resolved "https://registry.npmjs.org/@azure/msal-node/-/msal-node-1.0.0-beta.3.tgz#c84c7948028b39e48b901f5fac35bdedcbc8772e"
+ integrity sha512-/KfYRfrsOIrZONvo/0Vi5umuqbPBtCWNtmRvkse64uI0C4CP/W4WXwRD42VMws/8LtKvr1I5rYlYgFzt5zDz/A==
dependencies:
- "@azure/msal-common" "^1.6.2"
- axios "^0.19.2"
- debug "^4.1.1"
+ "@azure/msal-common" "^2.1.0"
+ axios "^0.21.1"
jsonwebtoken "^8.5.1"
uuid "^8.3.0"
@@ -1990,20 +1989,6 @@
"@babel/helper-plugin-utils" "^7.10.4"
"@babel/plugin-syntax-jsx" "^7.12.1"
-"@babel/plugin-transform-react-jsx-self@^7.12.1":
- version "7.12.1"
- resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.12.1.tgz#ef43cbca2a14f1bd17807dbe4376ff89d714cf28"
- integrity sha512-FbpL0ieNWiiBB5tCldX17EtXgmzeEZjFrix72rQYeq9X6nUK38HCaxexzVQrZWXanxKJPKVVIU37gFjEQYkPkA==
- dependencies:
- "@babel/helper-plugin-utils" "^7.10.4"
-
-"@babel/plugin-transform-react-jsx-source@^7.12.1":
- version "7.12.1"
- resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.12.1.tgz#d07de6863f468da0809edcf79a1aa8ce2a82a26b"
- integrity sha512-keQ5kBfjJNRc6zZN1/nVHCd6LLIHq4aUKcVnvE/2l+ZZROSbqoiGFRtT5t3Is89XJxBQaP7NLZX2jgGHdZvvFQ==
- dependencies:
- "@babel/helper-plugin-utils" "^7.10.4"
-
"@babel/plugin-transform-react-jsx@^7.0.0":
version "7.10.4"
resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.4.tgz#673c9f913948764a4421683b2bef2936968fddf2"
@@ -2024,16 +2009,6 @@
"@babel/helper-plugin-utils" "^7.10.4"
"@babel/plugin-syntax-jsx" "^7.12.1"
-"@babel/plugin-transform-react-jsx@^7.12.7":
- version "7.12.7"
- resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.7.tgz#8b14d45f6eccd41b7f924bcb65c021e9f0a06f7f"
- integrity sha512-YFlTi6MEsclFAPIDNZYiCRbneg1MFGao9pPG9uD5htwE0vDbPaMUMeYd6itWjw7K4kro4UbdQf3ljmFl9y48dQ==
- dependencies:
- "@babel/helper-builder-react-jsx" "^7.10.4"
- "@babel/helper-builder-react-jsx-experimental" "^7.12.4"
- "@babel/helper-plugin-utils" "^7.10.4"
- "@babel/plugin-syntax-jsx" "^7.12.1"
-
"@babel/plugin-transform-react-pure-annotations@^7.12.1":
version "7.12.1"
resolved "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz#05d46f0ab4d1339ac59adf20a1462c91b37a1a42"
@@ -2230,7 +2205,7 @@
"@babel/types" "^7.4.4"
esutils "^2.0.2"
-"@babel/preset-react@^7.12.1":
+"@babel/preset-react@^7.12.1", "@babel/preset-react@^7.12.5", "@babel/preset-react@^7.9.4":
version "7.12.10"
resolved "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.12.10.tgz#4fed65f296cbb0f5fb09de6be8cddc85cc909be9"
integrity sha512-vtQNjaHRl4DUpp+t+g4wvTHsLQuye+n0H/wsXIZRn69oz/fvNC7gQ4IK73zGJBaxvHoxElDvnYCthMcT7uzFoQ==
@@ -2241,19 +2216,6 @@
"@babel/plugin-transform-react-jsx-development" "^7.12.7"
"@babel/plugin-transform-react-pure-annotations" "^7.12.1"
-"@babel/preset-react@^7.12.5", "@babel/preset-react@^7.9.4":
- version "7.12.7"
- resolved "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.12.7.tgz#36d61d83223b07b6ac4ec55cf016abb0f70be83b"
- integrity sha512-wKeTdnGUP5AEYCYQIMeXMMwU7j+2opxrG0WzuZfxuuW9nhKvvALBjl67653CWamZJVefuJGI219G591RSldrqQ==
- dependencies:
- "@babel/helper-plugin-utils" "^7.10.4"
- "@babel/plugin-transform-react-display-name" "^7.12.1"
- "@babel/plugin-transform-react-jsx" "^7.12.7"
- "@babel/plugin-transform-react-jsx-development" "^7.12.7"
- "@babel/plugin-transform-react-jsx-self" "^7.12.1"
- "@babel/plugin-transform-react-jsx-source" "^7.12.1"
- "@babel/plugin-transform-react-pure-annotations" "^7.12.1"
-
"@babel/preset-typescript@^7.12.1":
version "7.12.7"
resolved "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.12.7.tgz#fc7df8199d6aae747896f1e6c61fc872056632a3"
@@ -2436,7 +2398,7 @@
to-fast-properties "^2.0.0"
"@backstage/catalog-model@^0.2.0":
- version "0.6.0"
+ version "0.6.1"
dependencies:
"@backstage/config" "^0.1.2"
"@types/json-schema" "^7.0.5"
@@ -2447,7 +2409,7 @@
yup "^0.29.3"
"@backstage/catalog-model@^0.3.0":
- version "0.6.0"
+ version "0.6.1"
dependencies:
"@backstage/config" "^0.1.2"
"@types/json-schema" "^7.0.5"
@@ -2458,7 +2420,7 @@
yup "^0.29.3"
"@backstage/core@^0.3.0":
- version "0.4.3"
+ version "0.4.4"
dependencies:
"@backstage/config" "^0.1.2"
"@backstage/core-api" "^0.2.8"
@@ -3732,10 +3694,10 @@
resolved "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796"
integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==
-"@kubernetes/client-node@^0.12.1":
- version "0.12.2"
- resolved "https://registry.npmjs.org/@kubernetes/client-node/-/client-node-0.12.2.tgz#8728684bd57d1cbcbe14fe742e79be7021403eea"
- integrity sha512-J0UwyFl1Iv/IZ6WMP7LaizBEoKPnqwtc8tIO2q/X+EuDT7eGpPPAMHXSEOC/EI9JGIf0FaJEcDHhB/Dio/mKhw==
+"@kubernetes/client-node@^0.13.2":
+ version "0.13.2"
+ resolved "https://registry.npmjs.org/@kubernetes/client-node/-/client-node-0.13.2.tgz#881eb407afbd5b499e5daf898ffcc40f839709e7"
+ integrity sha512-ufvGfjBXuy5LbZTJZ8bd1eRVgWUd9rRDCryMWNfxb4372Q60R1oG8qy7svUB9NqBmwFgKHuaXkrfq3rFFbGrew==
dependencies:
"@types/js-yaml" "^3.12.1"
"@types/node" "^10.12.0"
@@ -4661,32 +4623,27 @@
dependencies:
mkdirp "^1.0.4"
-"@octokit/auth-token@^2.4.0":
- version "2.4.0"
- resolved "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.0.tgz#b64178975218b99e4dfe948253f0673cbbb59d9f"
- integrity sha512-eoOVMjILna7FVQf96iWc3+ZtE/ZT6y8ob8ZzcqKY1ibSQCnu4O/B7pJvzMx5cyZ/RjAff6DAdEb0O0Cjcxidkg==
+"@octokit/auth-app@^2.10.5":
+ version "2.10.5"
+ resolved "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-2.10.5.tgz#85d69cb96818f5da34bf0b81bb637d3675ad4e9a"
+ integrity sha512-6yXyjtcBWpuPYSdZN8z8IIjGSqkPmiJzdmCdod8at41ANB1FtaKbUIDL5+IkG+svv68NIYs+XORbhBRFXYB3bw==
dependencies:
- "@octokit/types" "^2.0.0"
+ "@octokit/request" "^5.4.11"
+ "@octokit/request-error" "^2.0.0"
+ "@octokit/types" "^6.0.3"
+ "@types/lru-cache" "^5.1.0"
+ deprecation "^2.3.1"
+ lru-cache "^6.0.0"
+ universal-github-app-jwt "^1.0.1"
+ universal-user-agent "^6.0.0"
-"@octokit/auth-token@^2.4.4":
+"@octokit/auth-token@^2.4.0", "@octokit/auth-token@^2.4.4":
version "2.4.4"
resolved "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.4.tgz#ee31c69b01d0378c12fd3ffe406030f3d94d3b56"
integrity sha512-LNfGu3Ro9uFAYh10MUZVaT7X2CnNm2C8IDQmabx+3DygYIQjs9FwzFAHN/0t6mu5HEPhxcb1XOuxdpY82vCg2Q==
dependencies:
"@octokit/types" "^6.0.0"
-"@octokit/core@^3.0.0":
- version "3.1.0"
- resolved "https://registry.npmjs.org/@octokit/core/-/core-3.1.0.tgz#9c3c9b23f7504668cfa057f143ccbf0c645a0ac9"
- integrity sha512-yPyQSmxIXLieEIRikk2w8AEtWkFdfG/LXcw1KvEtK3iP0ENZLW/WYQmdzOKqfSaLhooz4CJ9D+WY79C8ZliACw==
- dependencies:
- "@octokit/auth-token" "^2.4.0"
- "@octokit/graphql" "^4.3.1"
- "@octokit/request" "^5.4.0"
- "@octokit/types" "^5.0.0"
- before-after-hook "^2.1.0"
- universal-user-agent "^5.0.0"
-
"@octokit/core@^3.2.3":
version "3.2.4"
resolved "https://registry.npmjs.org/@octokit/core/-/core-3.2.4.tgz#5791256057a962eca972e31818f02454897fd106"
@@ -4708,15 +4665,6 @@
is-plain-object "^3.0.0"
universal-user-agent "^5.0.0"
-"@octokit/graphql@^4.3.1":
- version "4.5.1"
- resolved "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.5.1.tgz#162aed1490320b88ce34775b3f6b8de945529fa9"
- integrity sha512-qgMsROG9K2KxDs12CO3bySJaYoUu2aic90qpFrv7A8sEBzZ7UFGvdgPKiLw5gOPYEYbS0Xf8Tvf84tJutHPulQ==
- dependencies:
- "@octokit/request" "^5.3.0"
- "@octokit/types" "^5.0.0"
- universal-user-agent "^5.0.0"
-
"@octokit/graphql@^4.5.8":
version "4.5.8"
resolved "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.5.8.tgz#d42373633c3015d0eafce64a8ce196be167fdd9b"
@@ -4743,13 +4691,6 @@
dependencies:
"@octokit/types" "^2.0.1"
-"@octokit/plugin-paginate-rest@^2.2.0":
- version "2.2.3"
- resolved "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.2.3.tgz#a6ad4377e7e7832fb4bdd9d421e600cb7640ac27"
- integrity sha512-eKTs91wXnJH8Yicwa30jz6DF50kAh7vkcqCQ9D7/tvBAP5KKkg6I2nNof8Mp/65G0Arjsb4QcOJcIEQY+rK1Rg==
- dependencies:
- "@octokit/types" "^5.0.0"
-
"@octokit/plugin-paginate-rest@^2.6.2":
version "2.7.0"
resolved "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.7.0.tgz#6bb7b043c246e0654119a6ec4e72a172c9e2c7f3"
@@ -4757,12 +4698,7 @@
dependencies:
"@octokit/types" "^6.0.1"
-"@octokit/plugin-request-log@^1.0.0":
- version "1.0.0"
- resolved "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.0.tgz#eef87a431300f6148c39a7f75f8cfeb218b2547e"
- integrity sha512-ywoxP68aOT3zHCLgWZgwUJatiENeHE7xJzYjfz8WI0goynp96wETBF+d95b8g/uL4QmS6owPVlaxiz3wyMAzcw==
-
-"@octokit/plugin-request-log@^1.0.2":
+"@octokit/plugin-request-log@^1.0.0", "@octokit/plugin-request-log@^1.0.2":
version "1.0.2"
resolved "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.2.tgz#394d59ec734cd2f122431fbaf05099861ece3c44"
integrity sha512-oTJSNAmBqyDR41uSMunLQKMX0jmEXbwD1fpz8FG27lScV3RhtGfBa1/BBLym+PxcC16IBlF7KH9vP1BUYxA+Eg==
@@ -4775,14 +4711,6 @@
"@octokit/types" "^2.0.1"
deprecation "^2.3.1"
-"@octokit/plugin-rest-endpoint-methods@4.1.4":
- version "4.1.4"
- resolved "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.1.4.tgz#ca60736d761b304fec02a2608caaec2d822e9835"
- integrity sha512-Y2tVpSa7HjV3DGIQrQOJcReJ2JtcN9FaGr9jDa332Flro923/h3/Iu9e7Y4GilnzfLclHEh5iCQoCkHm7tWOcg==
- dependencies:
- "@octokit/types" "^5.4.1"
- deprecation "^2.3.1"
-
"@octokit/plugin-rest-endpoint-methods@4.4.1":
version "4.4.1"
resolved "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.4.1.tgz#105cf93255432155de078c9efc33bd4e14d1cd63"
@@ -4809,21 +4737,7 @@
deprecation "^2.0.0"
once "^1.4.0"
-"@octokit/request@^5.2.0", "@octokit/request@^5.3.0", "@octokit/request@^5.4.0":
- version "5.4.5"
- resolved "https://registry.npmjs.org/@octokit/request/-/request-5.4.5.tgz#8df65bd812047521f7e9db6ff118c06ba84ac10b"
- integrity sha512-atAs5GAGbZedvJXXdjtKljin+e2SltEs48B3naJjqWupYl2IUBbB/CJisyjbNHcKpHzb3E+OYEZ46G8eakXgQg==
- dependencies:
- "@octokit/endpoint" "^6.0.1"
- "@octokit/request-error" "^2.0.0"
- "@octokit/types" "^5.0.0"
- deprecation "^2.0.0"
- is-plain-object "^3.0.0"
- node-fetch "^2.3.0"
- once "^1.4.0"
- universal-user-agent "^5.0.0"
-
-"@octokit/request@^5.4.12":
+"@octokit/request@^5.2.0", "@octokit/request@^5.3.0", "@octokit/request@^5.4.11", "@octokit/request@^5.4.12":
version "5.4.12"
resolved "https://registry.npmjs.org/@octokit/request/-/request-5.4.12.tgz#b04826fa934670c56b135a81447be2c1723a2ffc"
integrity sha512-MvWYdxengUWTGFpfpefBBpVmmEYfkwMoxonIB3sUGp5rhdgwjXL1ejo6JbgzG/QD9B/NYt/9cJX1pxXeSIUCkg==
@@ -4859,17 +4773,7 @@
once "^1.4.0"
universal-user-agent "^4.0.0"
-"@octokit/rest@^18.0.0":
- version "18.0.5"
- resolved "https://registry.npmjs.org/@octokit/rest/-/rest-18.0.5.tgz#1f1498dcdc2d85d0f86b8168e4ff5779842b2742"
- integrity sha512-SPKI24tQXrr1XsnaIjv2x0rl4M5eF1+hj8+vMe3d/exZ7NnL5sTe1BuFyCyJyrc+j1HkXankvgGN9zT0rwBwtg==
- dependencies:
- "@octokit/core" "^3.0.0"
- "@octokit/plugin-paginate-rest" "^2.2.0"
- "@octokit/plugin-request-log" "^1.0.0"
- "@octokit/plugin-rest-endpoint-methods" "4.1.4"
-
-"@octokit/rest@^18.0.12":
+"@octokit/rest@^18.0.0", "@octokit/rest@^18.0.12":
version "18.0.12"
resolved "https://registry.npmjs.org/@octokit/rest/-/rest-18.0.12.tgz#278bd41358c56d87c201e787e8adc0cac132503a"
integrity sha512-hNRCZfKPpeaIjOVuNJzkEL6zacfZlBPV8vw8ReNeyUkVvbuCvvrrx8K8Gw2eyHHsmd4dPlAxIXIZ9oHhJfkJpw==
@@ -4887,16 +4791,9 @@
"@types/node" ">= 8"
"@octokit/types@^5.0.0", "@octokit/types@^5.0.1":
- version "5.0.1"
- resolved "https://registry.npmjs.org/@octokit/types/-/types-5.0.1.tgz#5459e9a5e9df8565dcc62c17a34491904d71971e"
- integrity sha512-GorvORVwp244fGKEt3cgt/P+M0MGy4xEDbckw+K5ojEezxyMDgCaYPKVct+/eWQfZXOT7uq0xRpmrl/+hliabA==
- dependencies:
- "@types/node" ">= 8"
-
-"@octokit/types@^5.4.1":
- version "5.4.1"
- resolved "https://registry.npmjs.org/@octokit/types/-/types-5.4.1.tgz#d5d5f2b70ffc0e3f89467c3db749fa87fc3b7031"
- integrity sha512-OlMlSySBJoJ6uozkr/i03nO5dlYQyE05vmQNZhAh9MyO4DPBP88QlwsDVLmVjIMFssvIZB6WO0ctIGMRG+xsJQ==
+ version "5.5.0"
+ resolved "https://registry.npmjs.org/@octokit/types/-/types-5.5.0.tgz#e5f06e8db21246ca102aa28444cdb13ae17a139b"
+ integrity sha512-UZ1pErDue6bZNjYOotCNveTXArOMZQFG6hKJfOnGnulVCMcVVi7YIIuuR4WfBhjo7zgpmzn/BkPDnUXtNx+PcQ==
dependencies:
"@types/node" ">= 8"
@@ -5024,9 +4921,9 @@
shortid "^2.2.14"
"@rjsf/material-ui@^2.4.0":
- version "2.4.0"
- resolved "https://registry.npmjs.org/@rjsf/material-ui/-/material-ui-2.4.0.tgz#1b5859298bf3f61137d7b05084f058a775d6fd73"
- integrity sha512-U8F/suzg4MuV+8mK1/ufs0Y6c3O8hc1wnuD2IKoOVJvegGfz5JCafyoyGAW6iyuT1DZBMPzVWEqfiuYPmoE7pw==
+ version "2.4.1"
+ 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"
@@ -5293,7 +5190,7 @@
react-syntax-highlighter "^13.5.0"
regenerator-runtime "^0.13.7"
-"@storybook/addons@6.1.11", "@storybook/addons@^6.1.11":
+"@storybook/addons@6.1.11":
version "6.1.11"
resolved "https://registry.npmjs.org/@storybook/addons/-/addons-6.1.11.tgz#cb4578411ca00ccb206b484df5a171ccaca34719"
integrity sha512-OZXsdmn60dVe482l9zWxzOqqJApD2jggk/8QJKn3/Ub9posmqdqg712bW6v71BBe0UXXG/QfkZA7gcyiyEENbw==
@@ -5308,6 +5205,21 @@
global "^4.3.2"
regenerator-runtime "^0.13.7"
+"@storybook/addons@6.1.14", "@storybook/addons@^6.1.11":
+ version "6.1.14"
+ resolved "https://registry.npmjs.org/@storybook/addons/-/addons-6.1.14.tgz#2b81304bbe696923df95cdcf85cfc592d10f4065"
+ integrity sha512-HlpmV7aejp/MeW8bo/WKME3i71gi0men9qcwoovjDjnSF6jXoNLT336a5udKXdHqYSZgzdyURlgLtilCWkWaJQ==
+ dependencies:
+ "@storybook/api" "6.1.14"
+ "@storybook/channels" "6.1.14"
+ "@storybook/client-logger" "6.1.14"
+ "@storybook/core-events" "6.1.14"
+ "@storybook/router" "6.1.14"
+ "@storybook/theming" "6.1.14"
+ core-js "^3.0.1"
+ global "^4.3.2"
+ regenerator-runtime "^0.13.7"
+
"@storybook/api@6.1.11":
version "6.1.11"
resolved "https://registry.npmjs.org/@storybook/api/-/api-6.1.11.tgz#1e0b798203df823ac21184386258cf8b5f17f440"
@@ -5333,6 +5245,31 @@
ts-dedent "^2.0.0"
util-deprecate "^1.0.2"
+"@storybook/api@6.1.14":
+ version "6.1.14"
+ resolved "https://registry.npmjs.org/@storybook/api/-/api-6.1.14.tgz#20035dd336aba1c5a0f8c83c8c14a2edaf4db891"
+ integrity sha512-gWcC/xEW8HL5DsocLujHBUdoNsl4YW1Zx1Y4SBbLCyrhj8v4JudJpylwJpOUBDe/GESXq1zqvNKvUPtI8DQNyw==
+ dependencies:
+ "@reach/router" "^1.3.3"
+ "@storybook/channels" "6.1.14"
+ "@storybook/client-logger" "6.1.14"
+ "@storybook/core-events" "6.1.14"
+ "@storybook/csf" "0.0.1"
+ "@storybook/router" "6.1.14"
+ "@storybook/semver" "^7.3.2"
+ "@storybook/theming" "6.1.14"
+ "@types/reach__router" "^1.3.5"
+ core-js "^3.0.1"
+ fast-deep-equal "^3.1.1"
+ global "^4.3.2"
+ lodash "^4.17.15"
+ memoizerific "^1.11.3"
+ regenerator-runtime "^0.13.7"
+ store2 "^2.7.1"
+ telejson "^5.0.2"
+ ts-dedent "^2.0.0"
+ util-deprecate "^1.0.2"
+
"@storybook/channel-postmessage@6.1.11":
version "6.1.11"
resolved "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.1.11.tgz#62c1079f04870dd27925bd538a2020e7380daa2e"
@@ -5346,6 +5283,19 @@
qs "^6.6.0"
telejson "^5.0.2"
+"@storybook/channel-postmessage@6.1.14":
+ version "6.1.14"
+ resolved "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.1.14.tgz#41f3115895010dad9fb30f4ac381e4f904b1e50c"
+ integrity sha512-If83dXXW9mKIRuvuWhWa/zkEw/F0FDgikp33x8436J3rWCh3recp27kffFRrKG0YDMpFSk/Ci5G47E9zn9SCjw==
+ dependencies:
+ "@storybook/channels" "6.1.14"
+ "@storybook/client-logger" "6.1.14"
+ "@storybook/core-events" "6.1.14"
+ core-js "^3.0.1"
+ global "^4.3.2"
+ qs "^6.6.0"
+ telejson "^5.0.2"
+
"@storybook/channels@6.1.11":
version "6.1.11"
resolved "https://registry.npmjs.org/@storybook/channels/-/channels-6.1.11.tgz#a93a83746ad78dd40e1c056029f6d93b17bb66bc"
@@ -5355,6 +5305,15 @@
ts-dedent "^2.0.0"
util-deprecate "^1.0.2"
+"@storybook/channels@6.1.14":
+ version "6.1.14"
+ resolved "https://registry.npmjs.org/@storybook/channels/-/channels-6.1.14.tgz#c479190ebb853a603f3ed90fc470534a02eb46eb"
+ integrity sha512-vP19IB2FXj8SiFbQ9ETljEBienL+KRMLgMzz3Ta3nZj/OfjJJbIuj42ZfexQGV4mS0Bo+OW+qT7VMIY6fulnFw==
+ dependencies:
+ core-js "^3.0.1"
+ ts-dedent "^2.0.0"
+ util-deprecate "^1.0.2"
+
"@storybook/client-api@6.1.11":
version "6.1.11"
resolved "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.1.11.tgz#d25aac484ca84a1acb01d450e756a62408f00c1a"
@@ -5379,6 +5338,30 @@
ts-dedent "^2.0.0"
util-deprecate "^1.0.2"
+"@storybook/client-api@6.1.14":
+ version "6.1.14"
+ resolved "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.1.14.tgz#6daf56743cc72e13f05fff3d2ac554897cc9f9fd"
+ integrity sha512-pIDSlS48bhJdtgNg7sXV1NmLJtB0ebRHJI9htIiqtL7EGQenb4+Bbwflhj1j51OEkuM+bQsAAZxq5deiUQEGVw==
+ dependencies:
+ "@storybook/addons" "6.1.14"
+ "@storybook/channel-postmessage" "6.1.14"
+ "@storybook/channels" "6.1.14"
+ "@storybook/client-logger" "6.1.14"
+ "@storybook/core-events" "6.1.14"
+ "@storybook/csf" "0.0.1"
+ "@types/qs" "^6.9.0"
+ "@types/webpack-env" "^1.15.3"
+ core-js "^3.0.1"
+ global "^4.3.2"
+ lodash "^4.17.15"
+ memoizerific "^1.11.3"
+ qs "^6.6.0"
+ regenerator-runtime "^0.13.7"
+ stable "^0.1.8"
+ store2 "^2.7.1"
+ ts-dedent "^2.0.0"
+ util-deprecate "^1.0.2"
+
"@storybook/client-logger@6.1.11":
version "6.1.11"
resolved "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.1.11.tgz#5dd092e4293e5f58f7e89ddbc6eb2511b7d60954"
@@ -5387,6 +5370,14 @@
core-js "^3.0.1"
global "^4.3.2"
+"@storybook/client-logger@6.1.14":
+ version "6.1.14"
+ resolved "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.1.14.tgz#216b9c1332ffa3a3473dad837780a3b14f686bae"
+ integrity sha512-NSO8nVsp6o0eoQ1Drlu66KXpl6DPuq02Kj8AhttGzvqSYB50SV4CV+wceBcg77tIVu5QmQ+71hAEVXhx7sjRHA==
+ dependencies:
+ core-js "^3.0.1"
+ global "^4.3.2"
+
"@storybook/components@6.1.11":
version "6.1.11"
resolved "https://registry.npmjs.org/@storybook/components/-/components-6.1.11.tgz#edd5db7fe43f47b5a7ab515840795a89d931512e"
@@ -5413,6 +5404,32 @@
react-textarea-autosize "^8.1.1"
ts-dedent "^2.0.0"
+"@storybook/components@6.1.14":
+ version "6.1.14"
+ resolved "https://registry.npmjs.org/@storybook/components/-/components-6.1.14.tgz#4ea47edfa0a3e4a26882aa5a1eb90c1ec86e6f71"
+ integrity sha512-Nxsp/9o1tqfY8s6RBWNHyM03A5D9k56Kr/4VNa++CbDrz1+TIxpYlDgS4sllUlXyvICLfk3sUtg3KS5CPl2iZA==
+ dependencies:
+ "@popperjs/core" "^2.5.4"
+ "@storybook/client-logger" "6.1.14"
+ "@storybook/csf" "0.0.1"
+ "@storybook/theming" "6.1.14"
+ "@types/overlayscrollbars" "^1.9.0"
+ "@types/react-color" "^3.0.1"
+ "@types/react-syntax-highlighter" "11.0.4"
+ core-js "^3.0.1"
+ fast-deep-equal "^3.1.1"
+ global "^4.3.2"
+ lodash "^4.17.15"
+ markdown-to-jsx "^6.11.4"
+ memoizerific "^1.11.3"
+ overlayscrollbars "^1.10.2"
+ polished "^3.4.4"
+ react-color "^2.17.0"
+ react-popper-tooltip "^3.1.1"
+ react-syntax-highlighter "^13.5.0"
+ react-textarea-autosize "^8.1.1"
+ ts-dedent "^2.0.0"
+
"@storybook/core-events@6.1.11":
version "6.1.11"
resolved "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.1.11.tgz#d50e8ec90490f9a7180a8c8a83afb6dcfe47ed66"
@@ -5420,10 +5437,17 @@
dependencies:
core-js "^3.0.1"
-"@storybook/core@6.1.11":
- version "6.1.11"
- resolved "https://registry.npmjs.org/@storybook/core/-/core-6.1.11.tgz#ed9d3b513794c604ab11180f6a014924b871179e"
- integrity sha512-pYOOQwiNJ5myLRn6p6nnLUjjjISHK/N55vS4HFnETYSaRLA++h1coN1jk7Zwt89dOQTdF0EsTJn+6snYOC+lxQ==
+"@storybook/core-events@6.1.14":
+ version "6.1.14"
+ resolved "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.1.14.tgz#a3165e32cefd6be7326bbad4b8140653bdfa0426"
+ integrity sha512-tpM3VDvzqgRY7S17CRglgt1625rxNoyEwrLQiNcZkUPyO0rpaacPqVEbPCtcTmUeboI1bLdnSQIjT9B0/Y2Pww==
+ dependencies:
+ core-js "^3.0.1"
+
+"@storybook/core@6.1.14":
+ version "6.1.14"
+ resolved "https://registry.npmjs.org/@storybook/core/-/core-6.1.14.tgz#17e724a5b94d6e1bb557e213b8176660d2d14762"
+ integrity sha512-lHKZmfLAo2VGtF/yrZkkWMYgmFRNKbzIDxYJGp8USyUQyTfEpz2qqJlBdoD6rxr1hFPM2954tIKwh8iPhT2PFQ==
dependencies:
"@babel/core" "^7.12.3"
"@babel/plugin-proposal-class-properties" "^7.12.1"
@@ -5447,20 +5471,20 @@
"@babel/preset-react" "^7.12.1"
"@babel/preset-typescript" "^7.12.1"
"@babel/register" "^7.12.1"
- "@storybook/addons" "6.1.11"
- "@storybook/api" "6.1.11"
- "@storybook/channel-postmessage" "6.1.11"
- "@storybook/channels" "6.1.11"
- "@storybook/client-api" "6.1.11"
- "@storybook/client-logger" "6.1.11"
- "@storybook/components" "6.1.11"
- "@storybook/core-events" "6.1.11"
+ "@storybook/addons" "6.1.14"
+ "@storybook/api" "6.1.14"
+ "@storybook/channel-postmessage" "6.1.14"
+ "@storybook/channels" "6.1.14"
+ "@storybook/client-api" "6.1.14"
+ "@storybook/client-logger" "6.1.14"
+ "@storybook/components" "6.1.14"
+ "@storybook/core-events" "6.1.14"
"@storybook/csf" "0.0.1"
- "@storybook/node-logger" "6.1.11"
- "@storybook/router" "6.1.11"
+ "@storybook/node-logger" "6.1.14"
+ "@storybook/router" "6.1.14"
"@storybook/semver" "^7.3.2"
- "@storybook/theming" "6.1.11"
- "@storybook/ui" "6.1.11"
+ "@storybook/theming" "6.1.14"
+ "@storybook/ui" "6.1.14"
"@types/glob-base" "^0.3.0"
"@types/micromatch" "^4.0.1"
"@types/node-fetch" "^2.5.4"
@@ -5534,10 +5558,10 @@
dependencies:
lodash "^4.17.15"
-"@storybook/node-logger@6.1.11":
- version "6.1.11"
- resolved "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.1.11.tgz#8e0d058b4804f2fea03c9d7d331b8e2d02f3b7ff"
- integrity sha512-MASonXDWpSMU9HF9mqbGOR1Ps/DTJ8AVmYD50+OnB9kXl4M42Dliobeq7JwKFMnZ42RelUCCSXdWW80hGrUKKA==
+"@storybook/node-logger@6.1.14":
+ version "6.1.14"
+ resolved "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.1.14.tgz#e5294f986e3ec5c67b2738895b9d16c9a2b667fa"
+ integrity sha512-3jrw7coAwFXZu4qK1vm54bCPhNRvxjG+7jISbhhocDoNIv0nLWL3+tJyrC5/k/XHQiUlLkhEzpMaASADmkttNw==
dependencies:
"@types/npmlog" "^4.1.2"
chalk "^4.0.0"
@@ -5546,16 +5570,16 @@
pretty-hrtime "^1.0.3"
"@storybook/react@^6.1.11":
- version "6.1.11"
- resolved "https://registry.npmjs.org/@storybook/react/-/react-6.1.11.tgz#e94403cd878c66b445df993bad9bec9023db3ebe"
- integrity sha512-EmR7yvVW6z6AYhfzAgJMGR/5+igeBGa1EePaEIibn51r5uboSB72N12NaADyF2OaycIdV+0sW6vP9Zvlvexa/w==
+ version "6.1.14"
+ resolved "https://registry.npmjs.org/@storybook/react/-/react-6.1.14.tgz#436e9b90096b1d7c83f7f073b5baf47212b2e425"
+ integrity sha512-M99wHjc/5z+Wz1FdFaScVs6dyAi/6PdcIx5Fyip6Qd8aKwm1XyYoOMql5Vu3Cf560feDYCKS4phzyEZ7EJy+EQ==
dependencies:
"@babel/preset-flow" "^7.12.1"
"@babel/preset-react" "^7.12.1"
"@pmmmwh/react-refresh-webpack-plugin" "^0.4.2"
- "@storybook/addons" "6.1.11"
- "@storybook/core" "6.1.11"
- "@storybook/node-logger" "6.1.11"
+ "@storybook/addons" "6.1.14"
+ "@storybook/core" "6.1.14"
+ "@storybook/node-logger" "6.1.14"
"@storybook/semver" "^7.3.2"
"@types/webpack-env" "^1.15.3"
babel-plugin-add-react-displayname "^0.0.5"
@@ -5584,6 +5608,18 @@
memoizerific "^1.11.3"
qs "^6.6.0"
+"@storybook/router@6.1.14":
+ version "6.1.14"
+ resolved "https://registry.npmjs.org/@storybook/router/-/router-6.1.14.tgz#f6aef8c9dabf19bf06dddd80907e66369261fdde"
+ integrity sha512-rMaUCYzgfVLwFWo3A1Q/weSv8FBqCLmHY+3+t6ao7OV6NYjR0XgLKRzHrXq1uYdbMxWeIKhN2tIt/LR43bmDjQ==
+ dependencies:
+ "@reach/router" "^1.3.3"
+ "@types/reach__router" "^1.3.5"
+ core-js "^3.0.1"
+ global "^4.3.2"
+ memoizerific "^1.11.3"
+ qs "^6.6.0"
+
"@storybook/semver@^7.3.2":
version "7.3.2"
resolved "https://registry.npmjs.org/@storybook/semver/-/semver-7.3.2.tgz#f3b9c44a1c9a0b933c04e66d0048fcf2fa10dac0"
@@ -5627,21 +5663,39 @@
resolve-from "^5.0.0"
ts-dedent "^2.0.0"
-"@storybook/ui@6.1.11":
- version "6.1.11"
- resolved "https://registry.npmjs.org/@storybook/ui/-/ui-6.1.11.tgz#2e5a5df010f2bb75a09a0fd0439fc8e62f8c89e5"
- integrity sha512-Qth2dxS5+VbKHcqgkiKpeD+xr/hRUuUIDUA/2Ierh/BaA8Up/krlso/mCLaQOa5E8Og9WJAdDFO0cUbt939c2Q==
+"@storybook/theming@6.1.14":
+ version "6.1.14"
+ resolved "https://registry.npmjs.org/@storybook/theming/-/theming-6.1.14.tgz#fecb66cab22d3b3218b4a98a9c210eb8a7be91e8"
+ integrity sha512-S+t30y4FqBTXWoVr+dtxVJ/ywiQGHBclBd9aUunbdCV4mMFra5InNo2CWn+RJlNEauLZ93gRIEzSFchIbzLk1A==
dependencies:
"@emotion/core" "^10.1.1"
- "@storybook/addons" "6.1.11"
- "@storybook/api" "6.1.11"
- "@storybook/channels" "6.1.11"
- "@storybook/client-logger" "6.1.11"
- "@storybook/components" "6.1.11"
- "@storybook/core-events" "6.1.11"
- "@storybook/router" "6.1.11"
+ "@emotion/is-prop-valid" "^0.8.6"
+ "@emotion/styled" "^10.0.23"
+ "@storybook/client-logger" "6.1.14"
+ core-js "^3.0.1"
+ deep-object-diff "^1.1.0"
+ emotion-theming "^10.0.19"
+ global "^4.3.2"
+ memoizerific "^1.11.3"
+ polished "^3.4.4"
+ resolve-from "^5.0.0"
+ ts-dedent "^2.0.0"
+
+"@storybook/ui@6.1.14":
+ version "6.1.14"
+ resolved "https://registry.npmjs.org/@storybook/ui/-/ui-6.1.14.tgz#766d696480ee6f6a5a0454ccb2f101c38a0eb9d2"
+ integrity sha512-DTW2TM05jTMKxh8LzUGk3g5a528PgJxrtgODFU6zzwSg2+LwdmSDtd1HAxopt2vpfTyQyX+6WN2H+lMNwfQTAQ==
+ dependencies:
+ "@emotion/core" "^10.1.1"
+ "@storybook/addons" "6.1.14"
+ "@storybook/api" "6.1.14"
+ "@storybook/channels" "6.1.14"
+ "@storybook/client-logger" "6.1.14"
+ "@storybook/components" "6.1.14"
+ "@storybook/core-events" "6.1.14"
+ "@storybook/router" "6.1.14"
"@storybook/semver" "^7.3.2"
- "@storybook/theming" "6.1.11"
+ "@storybook/theming" "6.1.14"
"@types/markdown-to-jsx" "^6.11.0"
copy-to-clipboard "^3.0.8"
core-js "^3.0.1"
@@ -6479,13 +6533,6 @@
dependencies:
"@types/unist" "*"
-"@types/helmet@^0.0.48":
- version "0.0.48"
- resolved "https://registry.npmjs.org/@types/helmet/-/helmet-0.0.48.tgz#e754399d2f4672ba63962e8490efd3edd31d9799"
- integrity sha512-C7MpnvSDrunS1q2Oy1VWCY7CDWHozqSnM8P4tFeRTuzwqni+PYOjEredwcqWG+kLpYcgLsgcY3orHB54gbx2Jw==
- dependencies:
- "@types/express" "*"
-
"@types/history@*":
version "4.7.5"
resolved "https://registry.npmjs.org/@types/history/-/history-4.7.5.tgz#527d20ef68571a4af02ed74350164e7a67544860"
@@ -6631,7 +6678,7 @@
resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
-"@types/jsonwebtoken@^8.5.0":
+"@types/jsonwebtoken@^8.3.3", "@types/jsonwebtoken@^8.5.0":
version "8.5.0"
resolved "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.0.tgz#2531d5e300803aa63279b232c014acf780c981c5"
integrity sha512-9bVao7LvyorRGZCw0VmH/dr7Og+NdjYSsKAxB43OQoComFbBgsEpoR9JW6+qSq/ogwVBg8GI2MfAlk4SYI4OLg==
@@ -6694,6 +6741,16 @@
resolved "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==
+"@types/lru-cache@^5.1.0":
+ version "5.1.0"
+ resolved "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.0.tgz#57f228f2b80c046b4a1bd5cac031f81f207f4f03"
+ integrity sha512-RaE0B+14ToE4l6UqdarKPnXwVDuigfFv+5j9Dze/Nqr23yyuqdNvzcZi3xB+3Agvi5R4EOgAksfv3lXX4vBt9w==
+
+"@types/luxon@^1.25.0":
+ version "1.25.0"
+ resolved "https://registry.npmjs.org/@types/luxon/-/luxon-1.25.0.tgz#3d6fe591fac874f48dd225cb5660b2b785a21a05"
+ integrity sha512-iIJp2CP6C32gVqI08HIYnzqj55tlLnodIBMCcMf28q9ckqMfMzocCmIzd9JWI/ALLPMUiTkCu1JGv3FFtu6t3g==
+
"@types/markdown-to-jsx@^6.11.0":
version "6.11.2"
resolved "https://registry.npmjs.org/@types/markdown-to-jsx/-/markdown-to-jsx-6.11.2.tgz#05d1aaffbf15be7be12c70535fa4fed65cc7c64f"
@@ -7265,12 +7322,7 @@
"@types/serve-static" "*"
"@types/webpack" "*"
-"@types/webpack-env@^1.15.2":
- version "1.15.3"
- resolved "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.15.3.tgz#fb602cd4c2f0b7c0fb857e922075fdf677d25d84"
- integrity sha512-5oiXqR7kwDGZ6+gmzIO2lTC+QsriNuQXZDWNYRV3l2XRN/zmPgnC21DLSx2D05zvD8vnXW6qUg7JnXZ4I6qLVQ==
-
-"@types/webpack-env@^1.15.3":
+"@types/webpack-env@^1.15.2", "@types/webpack-env@^1.15.3":
version "1.16.0"
resolved "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.16.0.tgz#8c0a9435dfa7b3b1be76562f3070efb3f92637b4"
integrity sha512-Fx+NpfOO0CpeYX2g9bkvX8O5qh9wrU1sOF4g8sft4Mu7z+qfe387YlyY8w8daDyDsKY5vUxM0yxkAYnbkRbZEw==
@@ -8560,12 +8612,12 @@ axobject-query@^2.0.2:
integrity sha512-ICt34ZmrVt8UQnvPl6TVyDTkmhXmAyAT4Jh5ugfGUX4MOrZ+U/ZY6/sdylRw3qGNr9Ub5AJsaHeDMzNLehRdOQ==
azure-devops-node-api@^10.1.1:
- version "10.1.1"
- resolved "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-10.1.1.tgz#9016d8935316fff260f5f8fafd81d0caff90a19e"
- integrity sha512-P4Hyrh/+Nzc2KXQk73z72/GsenSWIH5o8uiyELqykJYs9TWTVCxVwghoR7lPeiY6QVoXkq2S2KtvAgi5fyjl9w==
+ version "10.2.1"
+ resolved "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-10.2.1.tgz#835080164f8c30cec6506c47198b044c053f1f36"
+ integrity sha512-XuSiUaYpk0tQpd9fD8qfRa5y1IdavupKNVmwxy0w/RhmxG2Wl8uAYnNJchUoWd3Rn9On0mYTCCZSn+UlYdYFSg==
dependencies:
tunnel "0.0.6"
- typed-rest-client "^1.7.3"
+ typed-rest-client "^1.8.0"
underscore "1.8.3"
babel-code-frame@^6.22.0:
@@ -14257,23 +14309,6 @@ got@^11.5.2:
p-cancelable "^2.0.0"
responselike "^2.0.0"
-got@^11.6.2:
- version "11.7.0"
- resolved "https://registry.npmjs.org/got/-/got-11.7.0.tgz#a386360305571a74548872e674932b4ef70d3b24"
- integrity sha512-7en2XwH2MEqOsrK0xaKhbWibBoZqy+f1RSUoIeF1BLcnf+pyQdDsljWMfmOh+QKJwuvDIiKx38GtPh5wFdGGjg==
- dependencies:
- "@sindresorhus/is" "^3.1.1"
- "@szmarczak/http-timer" "^4.0.5"
- "@types/cacheable-request" "^6.0.1"
- "@types/responselike" "^1.0.0"
- cacheable-lookup "^5.0.3"
- cacheable-request "^7.0.1"
- decompress-response "^6.0.0"
- http2-wrapper "^1.0.0-beta.5.2"
- lowercase-keys "^2.0.0"
- p-cancelable "^2.0.0"
- responselike "^2.0.0"
-
got@^11.7.0, got@^11.8.0:
version "11.8.0"
resolved "https://registry.npmjs.org/got/-/got-11.8.0.tgz#be0920c3586b07fd94add3b5b27cb28f49e6545f"
@@ -17739,6 +17774,11 @@ lru-queue@0.1:
dependencies:
es5-ext "~0.10.2"
+luxon@^1.25.0:
+ version "1.25.0"
+ resolved "https://registry.npmjs.org/luxon/-/luxon-1.25.0.tgz#d86219e90bc0102c0eb299d65b2f5e95efe1fe72"
+ integrity sha512-hEgLurSH8kQRjY6i4YLey+mcKVAWXbDNlZRmM6AgWDJ1cY3atl8Ztf5wEY7VBReFbmGnwQPz7KYJblL8B2k0jQ==
+
macos-release@^2.2.0:
version "2.3.0"
resolved "https://registry.npmjs.org/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f"
@@ -19355,21 +19395,7 @@ opencollective-postinstall@^2.0.2:
resolved "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz#5657f1bede69b6e33a45939b061eb53d3c6c3a89"
integrity sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw==
-openid-client@^4.1.1:
- version "4.1.1"
- resolved "https://registry.npmjs.org/openid-client/-/openid-client-4.1.1.tgz#3e8a25584c4292e9b9b03e60358f5549fb85197a"
- integrity sha512-/qch3I3v8UtO0A7wVgyXJJjGX/knR8bv06DQpLuKQqLG5u4AHcgusGuVKPKAcneLZvHKbKovF2+3e2ngXyuudA==
- dependencies:
- base64url "^3.0.1"
- got "^11.6.2"
- jose "^2.0.2"
- lru-cache "^6.0.0"
- make-error "^1.3.6"
- object-hash "^2.0.1"
- oidc-token-hash "^5.0.0"
- p-any "^3.0.0"
-
-openid-client@^4.2.1:
+openid-client@^4.1.1, openid-client@^4.2.1:
version "4.2.1"
resolved "https://registry.npmjs.org/openid-client/-/openid-client-4.2.1.tgz#8200c0ab6a3b8e954727dfa790847dc5cb8999c2"
integrity sha512-07eOcJeMH3ZHNvx5DVMZQmy3vZSTQqKSSunbtM1pXb+k5LBPi5hMum1vJCFReXlo4wuLEqZ/OgbsZvXPhbGRtA==
@@ -22160,12 +22186,7 @@ regenerator-runtime@^0.11.0:
resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
-regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.5:
- version "0.13.5"
- resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697"
- integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==
-
-regenerator-runtime@^0.13.7:
+regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.5, regenerator-runtime@^0.13.7:
version "0.13.7"
resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55"
integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==
@@ -24854,22 +24875,17 @@ tslib@2.0.0:
resolved "https://registry.npmjs.org/tslib/-/tslib-2.0.0.tgz#18d13fc2dce04051e20f074cc8387fd8089ce4f3"
integrity sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g==
-tslib@2.0.1, tslib@^2.0.0, tslib@~2.0.0, tslib@~2.0.1:
+tslib@2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e"
integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==
-tslib@^1.10.0, tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
- version "1.13.0"
- resolved "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
- integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==
-
-tslib@^1.8.0:
+tslib@^1.10.0, tslib@^1.11.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
version "1.14.1"
resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
-tslib@^2.0.1:
+tslib@^2.0.0, tslib@^2.0.1, tslib@~2.0.0, tslib@~2.0.1:
version "2.0.3"
resolved "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c"
integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==
@@ -24977,10 +24993,10 @@ type@^2.0.0:
resolved "https://registry.npmjs.org/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3"
integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==
-typed-rest-client@^1.7.3:
- version "1.7.3"
- resolved "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.7.3.tgz#1beb263b86b14d34596f6127c6172dd5fd652e7b"
- integrity sha512-CwTpx/TkRHGZoHkJhBcp4X8K3/WtlzSHVQR0OIFnt10j4tgy4ypgq/SrrgVpA1s6tAL49Q6J3R5C0Cgfh2ddqA==
+typed-rest-client@^1.8.0:
+ version "1.8.0"
+ resolved "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.0.tgz#3b6c22a7cc31b665ec1e4bedb3482ebe12e2fbe6"
+ integrity sha512-Nu1MrdH6ECrRW5gHoRAdubgCs4oH6q5/J76jsEC8bVDfvVoVPkigukPalhMHPwb7ZvpsZqPptd5zpt/QdtrdBw==
dependencies:
qs "^6.9.1"
tunnel "0.0.6"
@@ -25191,6 +25207,14 @@ unist-util-visit@^2.0.0:
unist-util-is "^4.0.0"
unist-util-visit-parents "^3.0.0"
+universal-github-app-jwt@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-1.1.0.tgz#0abaa876101cdf1d3e4c546be2768841c0c1b514"
+ integrity sha512-3b+ocAjjz4JTyqaOT+NNBd5BtTuvJTxWElIoeHSVelUV9J3Jp7avmQTdLKCaoqi/5Ox2o/q+VK19TJ233rVXVQ==
+ dependencies:
+ "@types/jsonwebtoken" "^8.3.3"
+ jsonwebtoken "^8.5.1"
+
universal-user-agent@^4.0.0:
version "4.0.1"
resolved "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-4.0.1.tgz#fd8d6cb773a679a709e967ef8288a31fcc03e557"
@@ -26112,12 +26136,7 @@ ws@^6.0.0, ws@^6.1.2, ws@^6.2.1:
dependencies:
async-limiter "~1.0.0"
-ws@^7.2.3:
- version "7.3.0"
- resolved "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz#4b2f7f219b3d3737bc1a2fbf145d825b94d38ffd"
- integrity sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==
-
-ws@^7.3.1:
+ws@^7.2.3, ws@^7.3.1:
version "7.3.1"
resolved "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8"
integrity sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==