From 722c8a9e8af503e1a0952cbc3c393265628d834a Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Sun, 25 Oct 2020 20:50:43 +0100 Subject: [PATCH 01/45] Cleanup after refactoring of plugins --- packages/app/src/apis.ts | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/packages/app/src/apis.ts b/packages/app/src/apis.ts index c129bebfa2..567ac13c78 100644 --- a/packages/app/src/apis.ts +++ b/packages/app/src/apis.ts @@ -25,16 +25,6 @@ import { GraphQLEndpoints, } from '@backstage/plugin-graphiql'; -import { - TravisCIApi, - travisCIApiRef, -} from '@roadiehq/backstage-plugin-travis-ci'; - -import { - GithubPullRequestsClient, - githubPullRequestsApiRef, -} from '@roadiehq/backstage-plugin-github-pull-requests'; - import { costInsightsApiRef } from '@backstage/plugin-cost-insights'; import { ExampleCostInsightsClient } from './plugins/cost-insights'; @@ -59,8 +49,4 @@ export const apis = [ }), createApiFactory(costInsightsApiRef, new ExampleCostInsightsClient()), - - // TODO: move to plugins - createApiFactory(travisCIApiRef, new TravisCIApi()), - createApiFactory(githubPullRequestsApiRef, new GithubPullRequestsClient()), ]; From e7f5471fde971b8381a9963e7a8d86fe6107262b Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Sun, 25 Oct 2020 20:55:43 +0100 Subject: [PATCH 02/45] Add changeset --- .changeset/sweet-bikes-battle.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/sweet-bikes-battle.md diff --git a/.changeset/sweet-bikes-battle.md b/.changeset/sweet-bikes-battle.md new file mode 100644 index 0000000000..68ed8caeeb --- /dev/null +++ b/.changeset/sweet-bikes-battle.md @@ -0,0 +1,5 @@ +--- +'example-app': patch +--- + +cleaning up because external plugins have already implemented new api for creating From fd910e9560e40f98e7791cd5e2bc12b563d354bb Mon Sep 17 00:00:00 2001 From: Marek Calus Date: Sun, 25 Oct 2020 23:50:37 +0100 Subject: [PATCH 03/45] Bump travis-ci package version --- packages/app/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/app/package.json b/packages/app/package.json index dc452e0803..e047e0e4a9 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -36,7 +36,7 @@ "@octokit/rest": "^18.0.0", "@roadiehq/backstage-plugin-github-insights": "^0.2.7", "@roadiehq/backstage-plugin-github-pull-requests": "^0.5.2", - "@roadiehq/backstage-plugin-travis-ci": "^0.2.3", + "@roadiehq/backstage-plugin-travis-ci": "^0.2.5", "dayjs": "^1.9.1", "history": "^5.0.0", "prop-types": "^15.7.2", From f09e6eb4ce308431cb2668e96412b292630aaba1 Mon Sep 17 00:00:00 2001 From: Fabian Chong Date: Mon, 26 Oct 2020 13:35:25 +0800 Subject: [PATCH 04/45] Add tsconfig to non monorepo plugin. --- packages/cli/src/commands/plugin/diff.ts | 6 +----- packages/cli/src/lib/tasks.ts | 6 ++++++ packages/cli/templates/default-plugin/tsconfig.json | 13 +++++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 packages/cli/templates/default-plugin/tsconfig.json diff --git a/packages/cli/src/commands/plugin/diff.ts b/packages/cli/src/commands/plugin/diff.ts index f5dfa670b7..012c061f74 100644 --- a/packages/cli/src/commands/plugin/diff.ts +++ b/packages/cli/src/commands/plugin/diff.ts @@ -40,17 +40,13 @@ const fileHandlers = [ patterns: ['package.json'], handler: handlers.packageJson, }, - { - patterns: ['tsconfig.json'], - handler: handlers.exactMatch, - }, { // make sure files in 1st level of src/ and dev/ exist patterns: ['.eslintrc.js', /^(src|dev)\/[^/]+$/], handler: handlers.exists, }, { - patterns: ['README.md', /^src\//], + patterns: ['README.md', 'tsconfig.json', /^src\//], handler: handlers.skip, }, ]; diff --git a/packages/cli/src/lib/tasks.ts b/packages/cli/src/lib/tasks.ts index 0753301b78..80dc1a5ed7 100644 --- a/packages/cli/src/lib/tasks.ts +++ b/packages/cli/src/lib/tasks.ts @@ -20,6 +20,7 @@ import handlebars from 'handlebars'; import ora from 'ora'; import { basename, dirname } from 'path'; import recursive from 'recursive-readdir'; +import { paths } from './paths'; const TASK_NAME_MAX_LENGTH = 14; @@ -72,6 +73,7 @@ export async function templatingTask( const files = await recursive(templateDir).catch(error => { throw new Error(`Failed to read template directory: ${error.message}`); }); + const isMonoRepo = await fs.pathExists(paths.resolveTargetRoot('lerna.json')); for (const file of files) { const destinationFile = file.replace(templateDir, destinationDir); @@ -92,6 +94,10 @@ export async function templatingTask( }); }); } else { + if (isMonoRepo && file.match('tsconfig.json')) { + continue; + } + await Task.forItem('copying', basename(file), async () => { await fs.copyFile(file, destinationFile).catch(error => { const destination = destinationFile; diff --git a/packages/cli/templates/default-plugin/tsconfig.json b/packages/cli/templates/default-plugin/tsconfig.json new file mode 100644 index 0000000000..d77f0fe3b4 --- /dev/null +++ b/packages/cli/templates/default-plugin/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@backstage/cli/config/tsconfig.json", + "include": [ + "src", + "dev", + "migrations" + ], + "exclude": ["node_modules"], + "compilerOptions": { + "outDir": "dist-types", + "rootDir": "." + } +} From 36a71d2780b2d355936542409eec1bc3a4a2a558 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 26 Oct 2020 15:46:22 +0100 Subject: [PATCH 05/45] catalog-backend: removed deprecated location processors --- .changeset/polite-laws-think.md | 5 + .../templates/default-app/app-config.yaml.hbs | 22 +- .../processors/AzureApiReaderProcessor.ts | 146 ---------- .../processors/BitbucketApiReaderProcessor.ts | 138 --------- .../processors/GithubReaderProcessor.ts | 274 ------------------ .../processors/GitlabApiReaderProcessor.ts | 141 --------- .../processors/GitlabReaderProcessor.ts | 94 ------ .../src/ingestion/processors/index.ts | 5 - .../src/service/CatalogBuilder.ts | 38 +-- 9 files changed, 26 insertions(+), 837 deletions(-) create mode 100644 .changeset/polite-laws-think.md delete mode 100644 plugins/catalog-backend/src/ingestion/processors/AzureApiReaderProcessor.ts delete mode 100644 plugins/catalog-backend/src/ingestion/processors/BitbucketApiReaderProcessor.ts delete mode 100644 plugins/catalog-backend/src/ingestion/processors/GithubReaderProcessor.ts delete mode 100644 plugins/catalog-backend/src/ingestion/processors/GitlabApiReaderProcessor.ts delete mode 100644 plugins/catalog-backend/src/ingestion/processors/GitlabReaderProcessor.ts diff --git a/.changeset/polite-laws-think.md b/.changeset/polite-laws-think.md new file mode 100644 index 0000000000..a5eb7f9883 --- /dev/null +++ b/.changeset/polite-laws-think.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': minor +--- + +Removed support for deprecated `catalog.providers` config that have been moved to `integrations` 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 a0b9f156ed..1f265d7e7d 100644 --- a/packages/create-app/templates/default-app/app-config.yaml.hbs +++ b/packages/create-app/templates/default-app/app-config.yaml.hbs @@ -39,6 +39,17 @@ backend: # $file: /ca/server.crt {{/if}} +integrations: + github: + - host: github.com + token: + $env: GITHUB_TOKEN + ### Example for how to add your GitHub Enterprise instance using the API: + # - host: ghe.example.net + # apiBaseUrl: https://ghe.example.net/api/v3 + # token: + # $env: GHE_TOKEN + proxy: '/test': target: 'https://example.com' @@ -66,17 +77,6 @@ scaffolder: catalog: rules: - allow: [Component, API, Group, User, Template, Location] - processors: - github: - providers: - - target: https://github.com - token: - $env: GITHUB_TOKEN - # Example for how to add your GitHub Enterprise instance: - # - target: https://ghe.example.net - # apiBaseUrl: https://ghe.example.net/api/v3 - # token: - # $env: GHE_TOKEN locations: # Backstage example components - type: url diff --git a/plugins/catalog-backend/src/ingestion/processors/AzureApiReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/AzureApiReaderProcessor.ts deleted file mode 100644 index 9b9ba586ef..0000000000 --- a/plugins/catalog-backend/src/ingestion/processors/AzureApiReaderProcessor.ts +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { LocationSpec } from '@backstage/catalog-model'; - -import { Config } from '@backstage/config'; -import fetch from 'cross-fetch'; -import * as result from './results'; -import { CatalogProcessor, CatalogProcessorEmit } from './types'; - -// *********************************************************************** -// * NOTE: This has been replaced by packages/backend-common/src/reading * -// * Don't implement new functionality here as this file will be removed * -// *********************************************************************** - -export class AzureApiReaderProcessor implements CatalogProcessor { - private privateToken: string; - - constructor(config: Config) { - this.privateToken = - config.getOptionalString('catalog.processors.azureApi.privateToken') ?? - ''; - } - - getRequestOptions(): RequestInit { - const headers: HeadersInit = {}; - - if (this.privateToken !== '') { - headers.Authorization = `Basic ${Buffer.from( - `:${this.privateToken}`, - 'utf8', - ).toString('base64')}`; - } - - return { - headers, - }; - } - - async readLocation( - location: LocationSpec, - optional: boolean, - emit: CatalogProcessorEmit, - ): Promise { - if (location.type !== 'azure/api') { - return false; - } - - try { - const url = this.buildRawUrl(location.target); - - const response = await fetch(url.toString(), this.getRequestOptions()); - - // for private repos when PAT is not valid, Azure API returns a http status code 203 with sign in page html - if (response.ok && response.status !== 203) { - const data = Buffer.from(await response.text()); - emit(result.data(location, data)); - } else { - const message = `${location.target} could not be read as ${url}, ${response.status} ${response.statusText}`; - if (response.status === 404) { - if (!optional) { - emit(result.notFoundError(location, message)); - } - } else { - emit(result.generalError(location, message)); - } - } - } catch (e) { - const message = `Unable to read ${location.type} ${location.target}, ${e}`; - emit(result.generalError(location, message)); - } - return true; - } - - // Converts - // from: https://dev.azure.com/{organization}/{project}/_git/reponame?path={path}&version=GB{commitOrBranch}&_a=contents - // to: https://dev.azure.com/{organization}/{project}/_apis/git/repositories/reponame/items?path={path}&version={commitOrBranch} - buildRawUrl(target: string): URL { - try { - const url = new URL(target); - - const [ - empty, - userOrOrg, - project, - srcKeyword, - repoName, - ] = url.pathname.split('/'); - - const path = url.searchParams.get('path') || ''; - const ref = url.searchParams.get('version')?.substr(2); - - if ( - url.hostname !== 'dev.azure.com' || - empty !== '' || - userOrOrg === '' || - project === '' || - srcKeyword !== '_git' || - repoName === '' || - path === '' || - ref === '' - ) { - throw new Error('Wrong Azure Devops URL or Invalid file path'); - } - - // transform to api - url.pathname = [ - empty, - userOrOrg, - project, - '_apis', - 'git', - 'repositories', - repoName, - 'items', - ].join('/'); - - const queryParams = [`path=${path}`]; - - if (ref) { - queryParams.push(`version=${ref}`); - } - - url.search = queryParams.join('&'); - - url.protocol = 'https'; - - return url; - } catch (e) { - throw new Error(`Incorrect url: ${target}, ${e}`); - } - } -} diff --git a/plugins/catalog-backend/src/ingestion/processors/BitbucketApiReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/BitbucketApiReaderProcessor.ts deleted file mode 100644 index 337053965f..0000000000 --- a/plugins/catalog-backend/src/ingestion/processors/BitbucketApiReaderProcessor.ts +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { LocationSpec } from '@backstage/catalog-model'; -import fetch from 'cross-fetch'; -import * as result from './results'; -import { Config } from '@backstage/config'; -import { CatalogProcessor, CatalogProcessorEmit } from './types'; - -// *********************************************************************** -// * NOTE: This has been replaced by packages/backend-common/src/reading * -// * Don't implement new functionality here as this file will be removed * -// *********************************************************************** - -export class BitbucketApiReaderProcessor implements CatalogProcessor { - private username: string; - private password: string; - - constructor(config: Config) { - this.username = - config.getOptionalString('catalog.processors.bitbucketApi.username') ?? - ''; - this.password = - config.getOptionalString('catalog.processors.bitbucketApi.appPassword') ?? - ''; - } - - getRequestOptions(): RequestInit { - const headers: HeadersInit = {}; - - if (this.username !== '' && this.password !== '') { - headers.Authorization = `Basic ${Buffer.from( - `${this.username}:${this.password}`, - 'utf8', - ).toString('base64')}`; - } - - const requestOptions: RequestInit = { - headers, - }; - - return requestOptions; - } - - async readLocation( - location: LocationSpec, - optional: boolean, - emit: CatalogProcessorEmit, - ): Promise { - if (location.type !== 'bitbucket/api') { - return false; - } - - try { - const url = this.buildRawUrl(location.target); - - const response = await fetch(url.toString(), this.getRequestOptions()); - - if (response.ok) { - const data = await response.text(); - emit(result.data(location, Buffer.from(data))); - } else { - const message = `${location.target} could not be read as ${url}, ${response.status} ${response.statusText}`; - if (response.status === 404) { - if (!optional) { - emit(result.notFoundError(location, message)); - } - } else { - emit(result.generalError(location, message)); - } - } - } catch (e) { - const message = `Unable to read ${location.type} ${location.target}, ${e}`; - emit(result.generalError(location, message)); - } - return true; - } - - // Converts - // from: https://bitbucket.org/orgname/reponame/src/master/file.yaml - // to: https://api.bitbucket.org/2.0/repositories/orgname/reponame/src/master/file.yaml - - buildRawUrl(target: string): URL { - try { - const url = new URL(target); - - const [ - empty, - userOrOrg, - repoName, - srcKeyword, - ref, - ...restOfPath - ] = url.pathname.split('/'); - - if ( - url.hostname !== 'bitbucket.org' || - empty !== '' || - userOrOrg === '' || - repoName === '' || - srcKeyword !== 'src' - ) { - throw new Error('Wrong Bitbucket URL or Invalid file path'); - } - - // transform to api - url.pathname = [ - empty, - '2.0', - 'repositories', - userOrOrg, - repoName, - 'src', - ref, - ...restOfPath, - ].join('/'); - url.hostname = 'api.bitbucket.org'; - url.protocol = 'https'; - - return url; - } catch (e) { - throw new Error(`Incorrect url: ${target}, ${e}`); - } - } -} diff --git a/plugins/catalog-backend/src/ingestion/processors/GithubReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/GithubReaderProcessor.ts deleted file mode 100644 index fed7f2a5c2..0000000000 --- a/plugins/catalog-backend/src/ingestion/processors/GithubReaderProcessor.ts +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { LocationSpec } from '@backstage/catalog-model'; -import { Config } from '@backstage/config'; -import parseGitUri from 'git-url-parse'; -import fetch from 'cross-fetch'; -import { Logger } from 'winston'; -import * as result from './results'; -import { CatalogProcessor, CatalogProcessorEmit } from './types'; - -// *********************************************************************** -// * NOTE: This has been replaced by packages/backend-common/src/reading * -// * Don't implement new functionality here as this file will be removed * -// *********************************************************************** - -/** - * The configuration parameters for a single GitHub API provider. - */ -export type ProviderConfig = { - /** - * The prefix of the target that this matches on, e.g. "https://github.com", - * with no trailing slash. - */ - target: string; - - /** - * The base URL of the API of this provider, e.g. "https://api.github.com", - * with no trailing slash. - * - * May be omitted specifically for GitHub; then it will be deduced. - * - * The API will always be preferred if both its base URL and a token are - * present. - */ - apiBaseUrl?: string; - - /** - * The base URL of the raw fetch endpoint of this provider, e.g. - * "https://raw.githubusercontent.com", with no trailing slash. - * - * May be omitted specifically for GitHub; then it will be deduced. - * - * The API will always be preferred if both its base URL and a token are - * present. - */ - rawBaseUrl?: string; - - /** - * The authorization token to use for requests to this provider. - * - * If no token is specified, anonymous access is used. - */ - token?: string; -}; - -export function getApiRequestOptions(provider: ProviderConfig): RequestInit { - const headers: HeadersInit = { - Accept: 'application/vnd.github.v3.raw', - }; - - if (provider.token) { - headers.Authorization = `token ${provider.token}`; - } - - return { - headers, - }; -} - -export function getRawRequestOptions(provider: ProviderConfig): RequestInit { - const headers: HeadersInit = {}; - - if (provider.token) { - headers.Authorization = `token ${provider.token}`; - } - - return { - headers, - }; -} - -// Converts for example -// from: https://github.com/a/b/blob/branchname/path/to/c.yaml -// to: https://api.github.com/repos/a/b/contents/path/to/c.yaml?ref=branchname -export function getApiUrl(target: string, provider: ProviderConfig): URL { - try { - const { owner, name, ref, filepathtype, filepath } = parseGitUri(target); - - if ( - !owner || - !name || - !ref || - (filepathtype !== 'blob' && filepathtype !== 'raw') - ) { - throw new Error('Wrong URL or invalid file path'); - } - - const pathWithoutSlash = filepath.replace(/^\//, ''); - return new URL( - `${provider.apiBaseUrl}/repos/${owner}/${name}/contents/${pathWithoutSlash}?ref=${ref}`, - ); - } catch (e) { - throw new Error(`Incorrect URL: ${target}, ${e}`); - } -} - -// Converts for example -// from: https://github.com/a/b/blob/branchname/c.yaml -// to: https://raw.githubusercontent.com/a/b/branchname/c.yaml -export function getRawUrl(target: string, provider: ProviderConfig): URL { - try { - const { owner, name, ref, filepathtype, filepath } = parseGitUri(target); - - if ( - !owner || - !name || - !ref || - (filepathtype !== 'blob' && filepathtype !== 'raw') - ) { - throw new Error('Wrong URL or invalid file path'); - } - - const pathWithoutSlash = filepath.replace(/^\//, ''); - return new URL( - `${provider.rawBaseUrl}/${owner}/${name}/${ref}/${pathWithoutSlash}`, - ); - } catch (e) { - throw new Error(`Incorrect URL: ${target}, ${e}`); - } -} - -export function readConfig(config: Config, logger: Logger): ProviderConfig[] { - const providers: ProviderConfig[] = []; - - // TODO(freben): Deprecate the old config root entirely in a later release - if (config.has('catalog.processors.githubApi')) { - logger.warn( - 'The catalog.processors.githubApi configuration key has been deprecated, please use catalog.processors.github instead', - ); - } - - // In a previous version of the configuration, we only supported github, - // and the "privateToken" key held the token to use for it. The new - // configuration method is to use the "providers" key instead. - const providerConfigs = - config.getOptionalConfigArray('catalog.processors.github.providers') ?? - config.getOptionalConfigArray('catalog.processors.githubApi.providers') ?? - []; - const legacyToken = - config.getOptionalString('catalog.processors.github.privateToken') ?? - config.getOptionalString('catalog.processors.githubApi.privateToken'); - - // First read all the explicit providers - for (const providerConfig of providerConfigs) { - const target = providerConfig.getString('target').replace(/\/+$/, ''); - let apiBaseUrl = providerConfig.getOptionalString('apiBaseUrl'); - let rawBaseUrl = providerConfig.getOptionalString('rawBaseUrl'); - const token = providerConfig.getOptionalString('token'); - - if (apiBaseUrl) { - apiBaseUrl = apiBaseUrl.replace(/\/+$/, ''); - } else if (target === 'https://github.com') { - apiBaseUrl = 'https://api.github.com'; - } - - if (rawBaseUrl) { - rawBaseUrl = rawBaseUrl.replace(/\/+$/, ''); - } else if (target === 'https://github.com') { - rawBaseUrl = 'https://raw.githubusercontent.com'; - } - - if (!apiBaseUrl && !rawBaseUrl) { - throw new Error( - `Provider at ${target} must configure an explicit apiBaseUrl or rawBaseUrl`, - ); - } - - providers.push({ target, apiBaseUrl, rawBaseUrl, token }); - } - - // If no explicit github.com provider was added, put one in the list as - // a convenience - if (!providers.some(p => p.target === 'https://github.com')) { - providers.push({ - target: 'https://github.com', - apiBaseUrl: 'https://api.github.com', - rawBaseUrl: 'https://raw.githubusercontent.com', - token: legacyToken, - }); - } - - return providers; -} - -/** - * A processor that adds the ability to read files from GitHub v3 APIs, such as - * the one exposed by GitHub itself. - */ -export class GithubReaderProcessor implements CatalogProcessor { - private providers: ProviderConfig[]; - - static fromConfig(config: Config, logger: Logger) { - return new GithubReaderProcessor(readConfig(config, logger)); - } - - constructor(providers: ProviderConfig[]) { - this.providers = providers; - } - - async readLocation( - location: LocationSpec, - optional: boolean, - emit: CatalogProcessorEmit, - ): Promise { - // The github/api type is for backward compatibility - if (location.type !== 'github' && location.type !== 'github/api') { - return false; - } - - const provider = this.providers.find(p => - location.target.startsWith(`${p.target}/`), - ); - if (!provider) { - throw new Error( - `There is no GitHub provider that matches ${location.target}. Please add a configuration entry for it under catalog.processors.github.providers.`, - ); - } - - try { - const useApi = - provider.apiBaseUrl && (provider.token || !provider.rawBaseUrl); - const url = useApi - ? getApiUrl(location.target, provider) - : getRawUrl(location.target, provider); - const options = useApi - ? getApiRequestOptions(provider) - : getRawRequestOptions(provider); - const response = await fetch(url.toString(), options); - - if (response.ok) { - const data = await response.text(); - emit(result.data(location, Buffer.from(data))); - } else { - const message = `${location.target} could not be read as ${url}, ${response.status} ${response.statusText}`; - if (response.status === 404) { - if (!optional) { - emit(result.notFoundError(location, message)); - } - } else { - emit(result.generalError(location, message)); - } - } - } catch (e) { - const message = `Unable to read ${location.type} ${location.target}, ${e}`; - emit(result.generalError(location, message)); - } - - return true; - } -} diff --git a/plugins/catalog-backend/src/ingestion/processors/GitlabApiReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/GitlabApiReaderProcessor.ts deleted file mode 100644 index 51a286c7ea..0000000000 --- a/plugins/catalog-backend/src/ingestion/processors/GitlabApiReaderProcessor.ts +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { LocationSpec } from '@backstage/catalog-model'; -import fetch from 'cross-fetch'; -import { Config } from '@backstage/config'; -import * as result from './results'; -import { CatalogProcessor, CatalogProcessorEmit } from './types'; - -// *********************************************************************** -// * NOTE: This has been replaced by packages/backend-common/src/reading * -// * Don't implement new functionality here as this file will be removed * -// *********************************************************************** - -export class GitlabApiReaderProcessor implements CatalogProcessor { - private privateToken: string; - - constructor(config: Config) { - this.privateToken = - config.getOptionalString('catalog.processors.gitlabApi.privateToken') ?? - ''; - } - - getRequestOptions(): RequestInit { - const headers: HeadersInit = { 'PRIVATE-TOKEN': '' }; - if (this.privateToken !== '') { - headers['PRIVATE-TOKEN'] = this.privateToken; - } - - const requestOptions: RequestInit = { - headers, - }; - - return requestOptions; - } - - async readLocation( - location: LocationSpec, - optional: boolean, - emit: CatalogProcessorEmit, - ): Promise { - if (location.type !== 'gitlab/api') { - return false; - } - - try { - const projectID = await this.getProjectID(location.target); - const url = this.buildRawUrl(location.target, projectID); - const response = await fetch(url.toString(), this.getRequestOptions()); - if (response.ok) { - const data = await response.text(); - emit(result.data(location, Buffer.from(data))); - } else { - const message = `${location.target} could not be read as ${url}, ${response.status} ${response.statusText}`; - if (response.status === 404) { - if (!optional) { - emit(result.notFoundError(location, message)); - } - } else { - emit(result.generalError(location, message)); - } - } - } catch (e) { - const message = `Unable to read ${location.type} ${location.target}, ${e}`; - emit(result.generalError(location, message)); - } - return true; - } - - // convert https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/filepath - // to https://gitlab.com/api/v4/projects//repository/files/filepath?ref=branch - buildRawUrl(target: string, projectID: Number): URL { - try { - const url = new URL(target); - - const branchAndfilePath = url.pathname.split('/-/blob/')[1]; - - const [branch, ...filePath] = branchAndfilePath.split('/'); - - url.pathname = [ - '/api/v4/projects', - projectID, - 'repository/files', - encodeURIComponent(filePath.join('/')), - 'raw', - ].join('/'); - url.search = `?ref=${branch}`; - - return url; - } catch (e) { - throw new Error(`Incorrect url: ${target}, ${e}`); - } - } - - async getProjectID(target: string): Promise { - const url = new URL(target); - - if ( - // absPaths to gitlab files should contain /-/blob - // ex: https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/filepath - !url.pathname.match(/\/\-\/blob\//) - ) { - throw new Error('Please provide full path to yaml file from Gitlab'); - } - try { - const repo = url.pathname.split('/-/blob/')[0]; - - // Find ProjectID from url - // convert 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/filepath' - // to 'https://gitlab.com/api/v4/projects/groupA%2Fteams%2FsubgroupA%2FteamA%2Frepo' - const repoIDLookup = new URL( - `${url.protocol + url.hostname}/api/v4/projects/${encodeURIComponent( - repo.replace(/^\//, ''), - )}`, - ); - const response = await fetch( - repoIDLookup.toString(), - this.getRequestOptions(), - ); - const projectIDJson = await response.json(); - const projectID: Number = projectIDJson.id; - - return projectID; - } catch (e) { - throw new Error(`Could not get GitLab ProjectID for: ${target}, ${e}`); - } - } -} diff --git a/plugins/catalog-backend/src/ingestion/processors/GitlabReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/GitlabReaderProcessor.ts deleted file mode 100644 index 38498b44fa..0000000000 --- a/plugins/catalog-backend/src/ingestion/processors/GitlabReaderProcessor.ts +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { LocationSpec } from '@backstage/catalog-model'; -import fetch from 'cross-fetch'; -import * as result from './results'; -import { CatalogProcessor, CatalogProcessorEmit } from './types'; - -// *********************************************************************** -// * NOTE: This has been replaced by packages/backend-common/src/reading * -// * Don't implement new functionality here as this file will be removed * -// *********************************************************************** - -export class GitlabReaderProcessor implements CatalogProcessor { - async readLocation( - location: LocationSpec, - optional: boolean, - emit: CatalogProcessorEmit, - ): Promise { - if (location.type !== 'gitlab') { - return false; - } - - try { - const url = this.buildRawUrl(location.target); - - const response = await fetch(url.toString()); - - if (response.ok) { - const data = await response.text(); - emit(result.data(location, Buffer.from(data))); - } else { - const message = `${location.target} could not be read as ${url}, ${response.status} ${response.statusText}`; - if (response.status === 404) { - if (!optional) { - throw result.notFoundError(location, message); - } - } else { - throw result.generalError(location, message); - } - } - } catch (e) { - const message = `Unable to read ${location.type} ${location.target}, ${e}`; - emit(result.generalError(location, message)); - } - - return true; - } - - // Converts - // from: https://gitlab.example.com/a/b/blob/master/c.yaml - // to: https://gitlab.example.com/a/b/raw/master/c.yaml - private buildRawUrl(target: string): URL { - try { - const url = new URL(target); - - const [empty, userOrOrg, repoName, , ...restOfPath] = url.pathname - .split('/') - // for the common case https://gitlab.example.com/a/b/-/blob/master/c.yaml - .filter(path => path !== '-'); - - if ( - empty !== '' || - userOrOrg === '' || - repoName === '' || - !restOfPath.join('/').match(/\.yaml$/) - ) { - throw new Error('Wrong GitLab URL'); - } - - // Replace 'blob' with 'raw' - url.pathname = [empty, userOrOrg, repoName, 'raw', ...restOfPath].join( - '/', - ); - - return url; - } catch (e) { - throw new Error(`Incorrect url: ${target}, ${e}`); - } - } -} diff --git a/plugins/catalog-backend/src/ingestion/processors/index.ts b/plugins/catalog-backend/src/ingestion/processors/index.ts index 92303f04a3..8344678e5f 100644 --- a/plugins/catalog-backend/src/ingestion/processors/index.ts +++ b/plugins/catalog-backend/src/ingestion/processors/index.ts @@ -20,14 +20,9 @@ export { results }; export * from './types'; export { AnnotateLocationEntityProcessor } from './AnnotateLocationEntityProcessor'; -export { AzureApiReaderProcessor } from './AzureApiReaderProcessor'; -export { BitbucketApiReaderProcessor } from './BitbucketApiReaderProcessor'; export { CodeOwnersProcessor } from './CodeOwnersProcessor'; export { FileReaderProcessor } from './FileReaderProcessor'; export { GithubOrgReaderProcessor } from './GithubOrgReaderProcessor'; -export { GithubReaderProcessor } from './GithubReaderProcessor'; -export { GitlabApiReaderProcessor } from './GitlabApiReaderProcessor'; -export { GitlabReaderProcessor } from './GitlabReaderProcessor'; export { OwnerRelationProcessor } from './OwnerRelationProcessor'; export { LocationRefProcessor } from './LocationEntityProcessor'; export { PlaceholderProcessor } from './PlaceholderProcessor'; diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.ts b/plugins/catalog-backend/src/service/CatalogBuilder.ts index 4ec2a0834d..e795310915 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.ts @@ -43,15 +43,10 @@ import { import { DatabaseManager } from '../database'; import { AnnotateLocationEntityProcessor, - AzureApiReaderProcessor, - BitbucketApiReaderProcessor, CatalogProcessor, CodeOwnersProcessor, FileReaderProcessor, GithubOrgReaderProcessor, - GithubReaderProcessor, - GitlabApiReaderProcessor, - GitlabReaderProcessor, OwnerRelationProcessor, HigherOrderOperation, HigherOrderOperations, @@ -318,6 +313,8 @@ export class CatalogBuilder { private buildProcessors(): CatalogProcessor[] { const { config, logger, reader } = this.env; + this.checkDeprecatedReaderProcessors(); + const placeholderResolvers: Record = { json: jsonPlaceholderResolver, yaml: yamlPlaceholderResolver, @@ -342,48 +339,33 @@ export class CatalogBuilder { return [ StaticLocationProcessor.fromConfig(config), new PlaceholderProcessor({ resolvers: placeholderResolvers, reader }), - ...this.buildDeprecatedReaderProcessors(), ...processors, ]; } - // TODO(Rugvip): These are added for backwards compatibility if config exists - // The idea is to have everyone migrate from using the old processors to - // the new integration config driven UrlReaders. In an upcoming release we - // can then completely remove support for the old processors, but still - // keep handling the deprecated location types for a while, but with a - // warning. - private buildDeprecatedReaderProcessors(): CatalogProcessor[] { - const { config, logger } = this.env; - - const result = []; - const pc = config.getOptionalConfig('catalog.processors'); + // TODO(Rugvip): These old processors are removed, for a while we'll be throwing + // errors here to make sure people know where to move the config + private checkDeprecatedReaderProcessors() { + const pc = this.env.config.getOptionalConfig('catalog.processors'); if (pc?.has('github')) { - logger.warn( + throw new Error( `Using deprecated configuration for catalog.processors.github, move to using integrations.github instead`, ); - result.push(GithubReaderProcessor.fromConfig(config, logger)); } if (pc?.has('gitlabApi')) { - logger.warn( + throw new Error( `Using deprecated configuration for catalog.processors.gitlabApi, move to using integrations.gitlab instead`, ); - result.push(new GitlabApiReaderProcessor(config)); - result.push(new GitlabReaderProcessor()); } if (pc?.has('bitbucketApi')) { - logger.warn( + throw new Error( `Using deprecated configuration for catalog.processors.bitbucketApi, move to using integrations.bitbucket instead`, ); - result.push(new BitbucketApiReaderProcessor(config)); } if (pc?.has('azureApi')) { - logger.warn( + throw new Error( `Using deprecated configuration for catalog.processors.azureApi, move to using integrations.azure instead`, ); - result.push(new AzureApiReaderProcessor(config)); } - - return result; } } From 0eac8f037d41ef83f4c5cccdc38101e718832d35 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Mon, 26 Oct 2020 15:00:46 -0400 Subject: [PATCH 06/45] move cost insights example client to plugin --- packages/app/package.json | 3 --- packages/app/src/apis.ts | 3 +-- .../app/src/plugins/cost-insights/index.ts | 17 ----------------- plugins/cost-insights/dev/index.tsx | 19 ++++++++++++++++--- plugins/cost-insights/package.json | 9 ++++++--- .../src/api}/ExampleCostInsightsClient.ts | 4 ++-- plugins/cost-insights/src/api/index.ts | 1 + plugins/cost-insights/src/plugin.ts | 8 +++++--- yarn.lock | 8 ++++---- 9 files changed, 35 insertions(+), 37 deletions(-) delete mode 100644 packages/app/src/plugins/cost-insights/index.ts rename {packages/app/src/plugins/cost-insights => plugins/cost-insights/src/api}/ExampleCostInsightsClient.ts (99%) diff --git a/packages/app/package.json b/packages/app/package.json index dc452e0803..7ac3c8e5fc 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -37,7 +37,6 @@ "@roadiehq/backstage-plugin-github-insights": "^0.2.7", "@roadiehq/backstage-plugin-github-pull-requests": "^0.5.2", "@roadiehq/backstage-plugin-travis-ci": "^0.2.3", - "dayjs": "^1.9.1", "history": "^5.0.0", "prop-types": "^15.7.2", "react": "^16.12.0", @@ -46,7 +45,6 @@ "react-router": "6.0.0-beta.0", "react-router-dom": "6.0.0-beta.0", "react-use": "^15.3.3", - "regression": "^2.0.1", "zen-observable": "^0.8.15" }, "devDependencies": { @@ -58,7 +56,6 @@ "@types/jquery": "^3.3.34", "@types/node": "^12.0.0", "@types/react-dom": "^16.9.8", - "@types/regression": "^2.0.0", "@types/zen-observable": "^0.8.0", "cross-env": "^7.0.0", "cypress": "^4.2.0", diff --git a/packages/app/src/apis.ts b/packages/app/src/apis.ts index c129bebfa2..9fdc6ce804 100644 --- a/packages/app/src/apis.ts +++ b/packages/app/src/apis.ts @@ -35,8 +35,7 @@ import { githubPullRequestsApiRef, } from '@roadiehq/backstage-plugin-github-pull-requests'; -import { costInsightsApiRef } from '@backstage/plugin-cost-insights'; -import { ExampleCostInsightsClient } from './plugins/cost-insights'; +import { costInsightsApiRef, ExampleCostInsightsClient } from '@backstage/plugin-cost-insights'; export const apis = [ createApiFactory({ diff --git a/packages/app/src/plugins/cost-insights/index.ts b/packages/app/src/plugins/cost-insights/index.ts deleted file mode 100644 index 47d540049f..0000000000 --- a/packages/app/src/plugins/cost-insights/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { ExampleCostInsightsClient } from './ExampleCostInsightsClient'; diff --git a/plugins/cost-insights/dev/index.tsx b/plugins/cost-insights/dev/index.tsx index 812a5585d4..515a9b6d80 100644 --- a/plugins/cost-insights/dev/index.tsx +++ b/plugins/cost-insights/dev/index.tsx @@ -13,8 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - import { createDevApp } from '@backstage/dev-utils'; -import { plugin } from '../src/plugin'; +import { createPlugin, createApiFactory } from '@backstage/core'; +import { ExampleCostInsightsClient } from '../src/api'; +import { costInsightsApiRef } from '../src'; +import { pluginConfig } from '../src/plugin'; -createDevApp().registerPlugin(plugin).render(); +const devPlugin = createPlugin({ + ...pluginConfig, + apis: [ + createApiFactory({ + api: costInsightsApiRef, + deps: {}, + factory: () => new ExampleCostInsightsClient() + }) + ] +}); + +createDevApp().registerPlugin(devPlugin).render(); diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index e79c4ab962..0a258299b3 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -33,6 +33,7 @@ "@types/recharts": "^1.8.14", "canvas": "^2.6.1", "classnames": "^2.2.6", + "dayjs": "^1.9.4", "history": "^5.0.0", "moment": "^2.27.0", "qs": "^6.9.4", @@ -41,21 +42,23 @@ "react-router-dom": "6.0.0-beta.0", "react-use": "^15.3.3", "recharts": "^1.8.5", + "regression": "^2.0.1", "yup": "^0.29.3" }, "devDependencies": { "@backstage/cli": "^0.1.1-alpha.25", "@backstage/dev-utils": "^0.1.1-alpha.25", + "@backstage/test-utils": "^0.1.1-alpha.25", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", - "@types/yup": "^0.29.8", "@types/recharts": "^1.8.14", - "msw": "^0.21.2", + "@types/regression": "^2.0.0", + "@types/yup": "^0.29.8", "cross-fetch": "^3.0.6", - "@backstage/test-utils": "^0.1.1-alpha.25" + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/packages/app/src/plugins/cost-insights/ExampleCostInsightsClient.ts b/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts similarity index 99% rename from packages/app/src/plugins/cost-insights/ExampleCostInsightsClient.ts rename to plugins/cost-insights/src/api/ExampleCostInsightsClient.ts index 799b9e1975..35bff86f7f 100644 --- a/packages/app/src/plugins/cost-insights/ExampleCostInsightsClient.ts +++ b/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts @@ -17,11 +17,11 @@ import dayjs from 'dayjs'; import regression, { DataPoint } from 'regression'; +import { CostInsightsApi } from './CostInsightsApi'; import { Alert, ChangeStatistic, Cost, - CostInsightsApi, DateAggregation, DEFAULT_DATE_FORMAT, Duration, @@ -37,7 +37,7 @@ import { Trendline, UnlabeledDataflowAlert, UnlabeledDataflowData, -} from '@backstage/plugin-cost-insights'; +} from '../types'; type IntervalFields = { duration: Duration; diff --git a/plugins/cost-insights/src/api/index.ts b/plugins/cost-insights/src/api/index.ts index d231570e9b..a367df9487 100644 --- a/plugins/cost-insights/src/api/index.ts +++ b/plugins/cost-insights/src/api/index.ts @@ -15,3 +15,4 @@ */ export * from './CostInsightsApi'; +export * from './ExampleCostInsightsClient'; diff --git a/plugins/cost-insights/src/plugin.ts b/plugins/cost-insights/src/plugin.ts index d8d54ae71b..3c50707374 100644 --- a/plugins/cost-insights/src/plugin.ts +++ b/plugins/cost-insights/src/plugin.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { createPlugin, createRouteRef } from '@backstage/core'; +import { createPlugin, createRouteRef, PluginConfig } from '@backstage/core'; import CostInsightsPage from './components/CostInsightsPage'; import ProjectGrowthInstructionsPage from './components/ProjectGrowthInstructionsPage'; import LabelDataflowInstructionsPage from './components/LabelDataflowInstructionsPage'; @@ -34,7 +34,7 @@ export const unlabeledDataflowAlertRef = createRouteRef({ title: 'Labeling Dataflow Jobs', }); -export const plugin = createPlugin({ +export const pluginConfig: PluginConfig = { id: 'cost-insights', register({ router, featureFlags }) { router.addRoute(rootRouteRef, CostInsightsPage); @@ -42,4 +42,6 @@ export const plugin = createPlugin({ router.addRoute(unlabeledDataflowAlertRef, LabelDataflowInstructionsPage); featureFlags.register('cost-insights-currencies'); }, -}); +} + +export const plugin = createPlugin(pluginConfig); diff --git a/yarn.lock b/yarn.lock index 3d3300493a..92bac86b17 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9797,10 +9797,10 @@ dateformat@^3.0.0: resolved "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -dayjs@^1.9.1: - version "1.9.3" - resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.9.3.tgz#b7f94b22ad2a136a4ca02a01ab68ae893fe1a268" - integrity sha512-V+1SyIvkS+HmNbN1G7A9+ERbFTV9KTXu6Oor98v2xHmzzpp52OIJhQuJSTywWuBY5pyAEmlwbCi1Me87n/SLOw== +dayjs@^1.9.4: + version "1.9.4" + resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.9.4.tgz#fcde984e227f4296f04e7b05720adad2e1071f1b" + integrity sha512-ABSF3alrldf7nM9sQ2U+Ln67NRwmzlLOqG7kK03kck0mw3wlSSEKv/XhKGGxUjQcS57QeiCyNdrFgtj9nWlrng== de-indent@^1.0.2: version "1.0.2" From fe741950a0901de5baa42931f76d1571ea4fbefd Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Mon, 26 Oct 2020 15:02:19 -0400 Subject: [PATCH 07/45] make PluginConfig and dependent types public --- packages/core-api/src/plugin/Plugin.tsx | 40 ++----------------------- packages/core-api/src/plugin/types.ts | 32 ++++++++++++++++++++ 2 files changed, 34 insertions(+), 38 deletions(-) diff --git a/packages/core-api/src/plugin/Plugin.tsx b/packages/core-api/src/plugin/Plugin.tsx index 1835ec03ad..dd6d2b8247 100644 --- a/packages/core-api/src/plugin/Plugin.tsx +++ b/packages/core-api/src/plugin/Plugin.tsx @@ -14,54 +14,18 @@ * limitations under the License. */ -import { ComponentType } from 'react'; import { + PluginConfig, PluginOutput, - RoutePath, - RouteOptions, - FeatureFlagName, BackstagePlugin, } from './types'; import { validateBrowserCompat, validateFlagName } from '../app/FeatureFlags'; -import { RouteRef } from '../routing'; import { AnyApiFactory } from '../apis'; -export type PluginConfig = { - id: string; - apis?: Iterable; - register?(hooks: PluginHooks): void; -}; - -export type PluginHooks = { - router: RouterHooks; - featureFlags: FeatureFlagsHooks; -}; - -export type RouterHooks = { - addRoute( - target: RouteRef, - Component: ComponentType, - options?: RouteOptions, - ): void; - - /** - * @deprecated See the `addRoute` method - */ - registerRoute( - path: RoutePath, - Component: ComponentType, - options?: RouteOptions, - ): void; -}; - -export type FeatureFlagsHooks = { - register(name: FeatureFlagName): void; -}; - export class PluginImpl { private storedOutput?: PluginOutput[]; - constructor(private readonly config: PluginConfig) {} + constructor(private readonly config: PluginConfig) { } getId(): string { return this.config.id; diff --git a/packages/core-api/src/plugin/types.ts b/packages/core-api/src/plugin/types.ts index dacb3668bc..76c05f7b04 100644 --- a/packages/core-api/src/plugin/types.ts +++ b/packages/core-api/src/plugin/types.ts @@ -73,3 +73,35 @@ export type BackstagePlugin = { output(): PluginOutput[]; getApis(): Iterable; }; + +export type PluginConfig = { + id: string; + apis?: Iterable; + register?(hooks: PluginHooks): void; +}; + +export type PluginHooks = { + router: RouterHooks; + featureFlags: FeatureFlagsHooks; +}; + +export type RouterHooks = { + addRoute( + target: RouteRef, + Component: ComponentType, + options?: RouteOptions, + ): void; + + /** + * @deprecated See the `addRoute` method + */ + registerRoute( + path: RoutePath, + Component: ComponentType, + options?: RouteOptions, + ): void; +}; + +export type FeatureFlagsHooks = { + register(name: FeatureFlagName): void; +}; From 26e69ab1a244ebb9de98cf642310fe015f6474ca Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Mon, 26 Oct 2020 15:29:13 -0400 Subject: [PATCH 08/45] changeset --- .changeset/seven-humans-check.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .changeset/seven-humans-check.md diff --git a/.changeset/seven-humans-check.md b/.changeset/seven-humans-check.md new file mode 100644 index 0000000000..f2fb784cc0 --- /dev/null +++ b/.changeset/seven-humans-check.md @@ -0,0 +1,9 @@ +--- +'example-app': patch +'@backstage/core-api': patch +'@backstage/plugin-cost-insights': patch +--- + +Remove cost insights example client from demo app and export from plugin +Create cost insights dev plugin using example client +Make PluginConfig and dependent types public From 75336fbbd71622130ba783bd94016440b5ccf524 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Mon, 26 Oct 2020 15:41:13 -0400 Subject: [PATCH 09/45] formatting --- packages/app/src/apis.ts | 5 ++++- packages/core-api/src/plugin/Plugin.tsx | 8 ++------ plugins/cost-insights/dev/index.tsx | 6 +++--- plugins/cost-insights/src/plugin.ts | 2 +- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/app/src/apis.ts b/packages/app/src/apis.ts index 9fdc6ce804..fe24ac228d 100644 --- a/packages/app/src/apis.ts +++ b/packages/app/src/apis.ts @@ -35,7 +35,10 @@ import { githubPullRequestsApiRef, } from '@roadiehq/backstage-plugin-github-pull-requests'; -import { costInsightsApiRef, ExampleCostInsightsClient } from '@backstage/plugin-cost-insights'; +import { + costInsightsApiRef, + ExampleCostInsightsClient, +} from '@backstage/plugin-cost-insights'; export const apis = [ createApiFactory({ diff --git a/packages/core-api/src/plugin/Plugin.tsx b/packages/core-api/src/plugin/Plugin.tsx index dd6d2b8247..866d430070 100644 --- a/packages/core-api/src/plugin/Plugin.tsx +++ b/packages/core-api/src/plugin/Plugin.tsx @@ -14,18 +14,14 @@ * limitations under the License. */ -import { - PluginConfig, - PluginOutput, - BackstagePlugin, -} from './types'; +import { PluginConfig, PluginOutput, BackstagePlugin } from './types'; import { validateBrowserCompat, validateFlagName } from '../app/FeatureFlags'; import { AnyApiFactory } from '../apis'; export class PluginImpl { private storedOutput?: PluginOutput[]; - constructor(private readonly config: PluginConfig) { } + constructor(private readonly config: PluginConfig) {} getId(): string { return this.config.id; diff --git a/plugins/cost-insights/dev/index.tsx b/plugins/cost-insights/dev/index.tsx index 515a9b6d80..836aea0edb 100644 --- a/plugins/cost-insights/dev/index.tsx +++ b/plugins/cost-insights/dev/index.tsx @@ -25,9 +25,9 @@ const devPlugin = createPlugin({ createApiFactory({ api: costInsightsApiRef, deps: {}, - factory: () => new ExampleCostInsightsClient() - }) - ] + factory: () => new ExampleCostInsightsClient(), + }), + ], }); createDevApp().registerPlugin(devPlugin).render(); diff --git a/plugins/cost-insights/src/plugin.ts b/plugins/cost-insights/src/plugin.ts index 3c50707374..0fc9cc623e 100644 --- a/plugins/cost-insights/src/plugin.ts +++ b/plugins/cost-insights/src/plugin.ts @@ -42,6 +42,6 @@ export const pluginConfig: PluginConfig = { router.addRoute(unlabeledDataflowAlertRef, LabelDataflowInstructionsPage); featureFlags.register('cost-insights-currencies'); }, -} +}; export const plugin = createPlugin(pluginConfig); From 1f862ecf020ca8dbdc8cf531b6cf23fb5d1ccb17 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Mon, 26 Oct 2020 17:18:26 -0400 Subject: [PATCH 10/45] prefer named exports --- .../AlertActionCard.test.tsx | 2 +- .../AlertActionCardList/AlertActionCard.tsx | 4 +- .../AlertActionCardList.tsx | 6 +-- .../components/AlertActionCardList/index.ts | 2 +- .../AlertInsights/AlertInsights.tsx | 8 ++-- .../AlertInsights/AlertInsightsHeader.tsx | 4 +- .../AlertInsights/AlertInsightsSection.tsx | 6 +-- .../AlertInsightsSectionHeader.tsx | 4 +- .../src/components/AlertInsights/index.ts | 2 +- .../AlertInstructionsLayout.tsx | 4 +- .../AlertInstructionsLayout/index.ts | 2 +- .../src/components/BarChart/BarChart.test.tsx | 2 +- .../src/components/BarChart/BarChart.tsx | 8 ++-- .../src/components/BarChart/BarChartLabel.tsx | 4 +- .../components/BarChart/BarChartStepper.tsx | 8 ++-- .../BarChart/BarChartStepperButton.tsx | 4 +- .../src/components/BarChart/BarChartSteps.tsx | 9 ++-- .../src/components/BarChart/BarChartTick.tsx | 4 +- .../src/components/BarChart/index.ts | 2 +- .../CopyUrlToClipboard/CopyUrlToClipboard.tsx | 4 +- .../components/CopyUrlToClipboard/index.ts | 2 +- .../components/CostGrowth/CostGrowth.test.tsx | 10 ++--- .../src/components/CostGrowth/CostGrowth.tsx | 4 +- .../src/components/CostGrowth/index.ts | 2 +- .../CostInsightsHeader.test.tsx | 2 +- .../CostInsightsHeader/CostInsightsHeader.tsx | 4 +- .../components/CostInsightsHeader/index.ts | 2 +- .../CostInsightsLayout/CostInsightsLayout.tsx | 6 +-- .../components/CostInsightsLayout/index.ts | 2 +- .../CostInsightsNavigation.test.tsx | 2 +- .../CostInsightsNavigation.tsx | 12 +++-- .../CostInsightsNavigation/index.ts | 2 +- .../CostInsightsPage/CostInsightsPage.tsx | 29 ++++++------ .../CostInsightsPage/CostInsightsPageRoot.tsx | 6 +-- .../src/components/CostInsightsPage/index.ts | 3 +- .../CostInsightsSupportButton.tsx | 4 +- .../CostInsightsSupportButton/index.ts | 2 +- .../CostInsightsTabs.test.tsx | 2 +- .../CostInsightsTabs/CostInsightsTabs.tsx | 4 +- .../src/components/CostInsightsTabs/index.ts | 2 +- .../CostOverviewCard/CostOverviewCard.tsx | 16 +++---- .../CostOverviewCard/CostOverviewChart.tsx | 6 +-- .../CostOverviewCard/CostOverviewHeader.tsx | 44 +++++++++---------- .../CostOverviewCard/CostOverviewTooltip.tsx | 4 +- .../src/components/CostOverviewCard/index.ts | 2 +- .../CurrencySelect/CurrencySelect.tsx | 4 +- .../src/components/CurrencySelect/index.ts | 2 +- .../LabelDataflowInstructionsPage.tsx | 6 +-- .../LabelDataflowInstructionsPage/index.ts | 2 +- .../src/components/LegendItem/LegendItem.tsx | 4 +- .../src/components/LegendItem/index.ts | 2 +- .../MetricSelect/MetricSelect.test.tsx | 2 +- .../components/MetricSelect/MetricSelect.tsx | 4 +- .../src/components/MetricSelect/index.ts | 2 +- .../PeriodSelect/PeriodSelect.test.tsx | 2 +- .../components/PeriodSelect/PeriodSelect.tsx | 4 +- .../src/components/PeriodSelect/index.ts | 2 +- .../ProductInsights/ProductInsights.tsx | 11 ++--- .../src/components/ProductInsights/index.ts | 2 +- .../ProductInsightsCard.test.tsx | 2 +- .../ProductInsightsCard.tsx | 10 ++--- .../components/ProductInsightsCard/index.ts | 2 +- .../ProjectGrowthAlertCard.test.tsx | 2 +- .../ProjectGrowthAlertCard.tsx | 13 +++--- .../ProjectGrowthAlertCard/index.ts | 2 +- .../ProjectGrowthInstructionsPage.tsx | 10 ++--- .../ProjectGrowthInstructionsPage/index.ts | 2 +- .../ProjectSelect/ProjectSelect.test.tsx | 2 +- .../ProjectSelect/ProjectSelect.tsx | 4 +- .../src/components/ProjectSelect/index.ts | 2 +- .../ResourceGrowthBarChart.test.tsx | 2 +- .../ResourceGrowthBarChart.tsx | 6 +-- .../ResourceGrowthBarChart/index.ts | 2 +- .../ResourceGrowthBarChartLegend.test.tsx | 2 +- .../ResourceGrowthBarChartLegend.tsx | 8 ++-- .../ResourceGrowthBarChartLegend/index.ts | 2 +- .../src/components/Tooltip/Tooltip.test.tsx | 2 +- .../src/components/Tooltip/Tooltip.tsx | 6 +-- .../src/components/Tooltip/TooltipItem.tsx | 4 +- .../src/components/Tooltip/index.ts | 4 +- .../UnlabeledDataflowAlertCard.test.tsx | 4 +- .../UnlabeledDataflowAlertCard.tsx | 8 ++-- .../UnlabeledDataflowBarChart.tsx | 4 +- .../UnlabeledDataflowBarChartLegend.test.tsx | 2 +- .../UnlabeledDataflowBarChartLegend.tsx | 6 +-- .../UnlabeledDataflowAlertCard/index.ts | 2 +- .../UnlabeledDataflowBarChart/index.ts | 17 ------- .../UnlabeledDataflowBarChartLegend/index.ts | 17 ------- .../WhyCostsMatter/WhyCostsMatter.tsx | 4 +- .../src/components/WhyCostsMatter/index.ts | 2 +- plugins/cost-insights/src/components/index.ts | 6 +-- plugins/cost-insights/src/plugin.ts | 6 +-- plugins/cost-insights/src/types/Alert.tsx | 4 +- 93 files changed, 180 insertions(+), 303 deletions(-) rename plugins/cost-insights/src/components/{UnlabeledDataflowBarChart => UnlabeledDataflowAlertCard}/UnlabeledDataflowBarChart.tsx (96%) rename plugins/cost-insights/src/components/{UnlabeledDataflowBarChartLegend => UnlabeledDataflowAlertCard}/UnlabeledDataflowBarChartLegend.test.tsx (93%) rename plugins/cost-insights/src/components/{UnlabeledDataflowBarChartLegend => UnlabeledDataflowAlertCard}/UnlabeledDataflowBarChartLegend.tsx (92%) delete mode 100644 plugins/cost-insights/src/components/UnlabeledDataflowBarChart/index.ts delete mode 100644 plugins/cost-insights/src/components/UnlabeledDataflowBarChartLegend/index.ts diff --git a/plugins/cost-insights/src/components/AlertActionCardList/AlertActionCard.test.tsx b/plugins/cost-insights/src/components/AlertActionCardList/AlertActionCard.test.tsx index 0600f89c60..3e2ca4f8c8 100644 --- a/plugins/cost-insights/src/components/AlertActionCardList/AlertActionCard.test.tsx +++ b/plugins/cost-insights/src/components/AlertActionCardList/AlertActionCard.test.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { renderInTestApp } from '@backstage/test-utils'; -import AlertActionCard from './AlertActionCard'; +import { AlertActionCard } from './AlertActionCard'; import { ProjectGrowthAlert, ProjectGrowthData } from '../../types'; import { MockScrollProvider } from '../../utils/tests'; diff --git a/plugins/cost-insights/src/components/AlertActionCardList/AlertActionCard.tsx b/plugins/cost-insights/src/components/AlertActionCardList/AlertActionCard.tsx index a83c7bc7ce..78feade952 100644 --- a/plugins/cost-insights/src/components/AlertActionCardList/AlertActionCard.tsx +++ b/plugins/cost-insights/src/components/AlertActionCardList/AlertActionCard.tsx @@ -27,7 +27,7 @@ type AlertActionCardProps = { number: number; }; -const AlertActionCard = ({ alert, number }: AlertActionCardProps) => { +export const AlertActionCard = ({ alert, number }: AlertActionCardProps) => { const { scrollIntoView } = useScroll(`alert-${number}`); const headerClasses = useHeaderStyles(); const classes = useStyles(); @@ -43,5 +43,3 @@ const AlertActionCard = ({ alert, number }: AlertActionCardProps) => { ); }; - -export default AlertActionCard; diff --git a/plugins/cost-insights/src/components/AlertActionCardList/AlertActionCardList.tsx b/plugins/cost-insights/src/components/AlertActionCardList/AlertActionCardList.tsx index 1ea1fb6a96..f28989d745 100644 --- a/plugins/cost-insights/src/components/AlertActionCardList/AlertActionCardList.tsx +++ b/plugins/cost-insights/src/components/AlertActionCardList/AlertActionCardList.tsx @@ -15,14 +15,14 @@ */ import React, { FC, Fragment } from 'react'; import { Paper, Divider } from '@material-ui/core'; -import AlertActionCard from './AlertActionCard'; +import { AlertActionCard } from './AlertActionCard'; import { Alert } from '../../types'; type AlertActionCardList = { alerts: Array; }; -const AlertActionCardList: FC = ({ alerts }) => ( +export const AlertActionCardList: FC = ({ alerts }) => ( {alerts.map((alert, index) => ( @@ -32,5 +32,3 @@ const AlertActionCardList: FC = ({ alerts }) => ( ))} ); - -export default AlertActionCardList; diff --git a/plugins/cost-insights/src/components/AlertActionCardList/index.ts b/plugins/cost-insights/src/components/AlertActionCardList/index.ts index cccffd2985..a0ce118482 100644 --- a/plugins/cost-insights/src/components/AlertActionCardList/index.ts +++ b/plugins/cost-insights/src/components/AlertActionCardList/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './AlertActionCardList'; +export { AlertActionCardList } from './AlertActionCardList'; diff --git a/plugins/cost-insights/src/components/AlertInsights/AlertInsights.tsx b/plugins/cost-insights/src/components/AlertInsights/AlertInsights.tsx index e0aa0f02d9..4606906f04 100644 --- a/plugins/cost-insights/src/components/AlertInsights/AlertInsights.tsx +++ b/plugins/cost-insights/src/components/AlertInsights/AlertInsights.tsx @@ -16,8 +16,8 @@ import React from 'react'; import { Grid } from '@material-ui/core'; -import AlertInsightsSection from './AlertInsightsSection'; -import AlertInsightsHeader from './AlertInsightsHeader'; +import { AlertInsightsSection } from './AlertInsightsSection'; +import { AlertInsightsHeader } from './AlertInsightsHeader'; import { Alert } from '../../types'; const title = "Your team's action items"; @@ -28,7 +28,7 @@ type AlertInsightsProps = { alerts: Array; }; -const AlertInsights = ({ alerts }: AlertInsightsProps) => ( +export const AlertInsights = ({ alerts }: AlertInsightsProps) => ( @@ -42,5 +42,3 @@ const AlertInsights = ({ alerts }: AlertInsightsProps) => ( ); - -export default AlertInsights; diff --git a/plugins/cost-insights/src/components/AlertInsights/AlertInsightsHeader.tsx b/plugins/cost-insights/src/components/AlertInsights/AlertInsightsHeader.tsx index b08ea01730..7a65010abf 100644 --- a/plugins/cost-insights/src/components/AlertInsights/AlertInsightsHeader.tsx +++ b/plugins/cost-insights/src/components/AlertInsights/AlertInsightsHeader.tsx @@ -25,7 +25,7 @@ type AlertInsightsHeaderProps = { subtitle: string; }; -const AlertInsightsHeader = ({ title, subtitle }: AlertInsightsHeaderProps) => { +export const AlertInsightsHeader = ({ title, subtitle }: AlertInsightsHeaderProps) => { const classes = useStyles(); const { ScrollAnchor } = useScroll(DefaultNavigation.AlertInsightsHeader); return ( @@ -43,5 +43,3 @@ const AlertInsightsHeader = ({ title, subtitle }: AlertInsightsHeaderProps) => { ); }; - -export default AlertInsightsHeader; diff --git a/plugins/cost-insights/src/components/AlertInsights/AlertInsightsSection.tsx b/plugins/cost-insights/src/components/AlertInsights/AlertInsightsSection.tsx index d2305e390d..fe5425a937 100644 --- a/plugins/cost-insights/src/components/AlertInsights/AlertInsightsSection.tsx +++ b/plugins/cost-insights/src/components/AlertInsights/AlertInsightsSection.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; import { Box, Button } from '@material-ui/core'; -import AlertInsightsSectionHeader from './AlertInsightsSectionHeader'; +import { AlertInsightsSectionHeader } from './AlertInsightsSectionHeader'; import { Alert } from '../../types'; type AlertInsightsSectionProps = { @@ -23,7 +23,7 @@ type AlertInsightsSectionProps = { number: number; }; -const AlertInsightsSection = ({ alert, number }: AlertInsightsSectionProps) => { +export const AlertInsightsSection = ({ alert, number }: AlertInsightsSectionProps) => { return ( { ); }; - -export default AlertInsightsSection; diff --git a/plugins/cost-insights/src/components/AlertInsights/AlertInsightsSectionHeader.tsx b/plugins/cost-insights/src/components/AlertInsights/AlertInsightsSectionHeader.tsx index a561735d58..3613e3adc8 100644 --- a/plugins/cost-insights/src/components/AlertInsights/AlertInsightsSectionHeader.tsx +++ b/plugins/cost-insights/src/components/AlertInsights/AlertInsightsSectionHeader.tsx @@ -25,7 +25,7 @@ type AlertInsightsSectionHeaderProps = { subtitle: string; }; -const AlertInsightsSectionHeader = ({ +export const AlertInsightsSectionHeader = ({ number, title, subtitle, @@ -47,5 +47,3 @@ const AlertInsightsSectionHeader = ({ ); }; - -export default AlertInsightsSectionHeader; diff --git a/plugins/cost-insights/src/components/AlertInsights/index.ts b/plugins/cost-insights/src/components/AlertInsights/index.ts index 5ed33f4e39..a0684fdf26 100644 --- a/plugins/cost-insights/src/components/AlertInsights/index.ts +++ b/plugins/cost-insights/src/components/AlertInsights/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './AlertInsights'; +export { AlertInsights } from './AlertInsights'; diff --git a/plugins/cost-insights/src/components/AlertInstructionsLayout/AlertInstructionsLayout.tsx b/plugins/cost-insights/src/components/AlertInstructionsLayout/AlertInstructionsLayout.tsx index e230e94130..e46b718060 100644 --- a/plugins/cost-insights/src/components/AlertInstructionsLayout/AlertInstructionsLayout.tsx +++ b/plugins/cost-insights/src/components/AlertInstructionsLayout/AlertInstructionsLayout.tsx @@ -32,7 +32,7 @@ type AlertInstructionsLayoutProps = { title: string; }; -const AlertInstructionsLayout = ({ +export const AlertInstructionsLayout = ({ title, children, }: PropsWithChildren) => { @@ -65,5 +65,3 @@ const AlertInstructionsLayout = ({ ); }; - -export default AlertInstructionsLayout; diff --git a/plugins/cost-insights/src/components/AlertInstructionsLayout/index.ts b/plugins/cost-insights/src/components/AlertInstructionsLayout/index.ts index 4063fe06d9..22165e74c3 100644 --- a/plugins/cost-insights/src/components/AlertInstructionsLayout/index.ts +++ b/plugins/cost-insights/src/components/AlertInstructionsLayout/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './AlertInstructionsLayout'; +export { AlertInstructionsLayout } from './AlertInstructionsLayout'; diff --git a/plugins/cost-insights/src/components/BarChart/BarChart.test.tsx b/plugins/cost-insights/src/components/BarChart/BarChart.test.tsx index 737b86018c..a095324e6e 100644 --- a/plugins/cost-insights/src/components/BarChart/BarChart.test.tsx +++ b/plugins/cost-insights/src/components/BarChart/BarChart.test.tsx @@ -17,7 +17,7 @@ import React from 'react'; import { TooltipPayload } from 'recharts'; import { fireEvent } from '@testing-library/react'; -import BarChart, { BarChartProps } from './BarChart'; +import { BarChart, BarChartProps } from './BarChart'; import { BarChartData, ResourceData } from '../../types'; import { createMockEntity } from '../../utils/mockData'; import { resourceSort } from '../../utils/sort'; diff --git a/plugins/cost-insights/src/components/BarChart/BarChart.tsx b/plugins/cost-insights/src/components/BarChart/BarChart.tsx index 6b2bbc1490..65e7e39c64 100644 --- a/plugins/cost-insights/src/components/BarChart/BarChart.tsx +++ b/plugins/cost-insights/src/components/BarChart/BarChart.tsx @@ -28,8 +28,8 @@ import { TooltipPayload, } from 'recharts'; import { Box, useTheme } from '@material-ui/core'; -import BarChartTick from './BarChartTick'; -import BarChartStepper from './BarChartStepper'; +import { BarChartTick } from './BarChartTick'; +import { BarChartStepper } from './BarChartStepper'; import { Tooltip, TooltipItemProps } from '../Tooltip'; import { currencyFormatter } from '../../utils/formatters'; @@ -52,7 +52,7 @@ export type BarChartProps = { resources: ResourceData[]; }; -const BarChart = ({ +export const BarChart = ({ responsive = true, displayAmount = 6, barChartData, @@ -171,5 +171,3 @@ const BarChart = ({ ); }; - -export default BarChart; diff --git a/plugins/cost-insights/src/components/BarChart/BarChartLabel.tsx b/plugins/cost-insights/src/components/BarChart/BarChartLabel.tsx index 9e49cb14dd..0a21f1ed46 100644 --- a/plugins/cost-insights/src/components/BarChart/BarChartLabel.tsx +++ b/plugins/cost-insights/src/components/BarChart/BarChartLabel.tsx @@ -25,7 +25,7 @@ type BarChartLabel = { width: number; }; -const BarChartLabel = ({ +export const BarChartLabel = ({ x, y, height, @@ -52,5 +52,3 @@ const BarChartLabel = ({ ); }; - -export default BarChartLabel; diff --git a/plugins/cost-insights/src/components/BarChart/BarChartStepper.tsx b/plugins/cost-insights/src/components/BarChart/BarChartStepper.tsx index 27f7a589f3..e2e432fe04 100644 --- a/plugins/cost-insights/src/components/BarChart/BarChartStepper.tsx +++ b/plugins/cost-insights/src/components/BarChart/BarChartStepper.tsx @@ -18,8 +18,8 @@ import React, { useEffect, useState } from 'react'; import { Paper, Slide } from '@material-ui/core'; import ChevronLeftIcon from '@material-ui/icons/ChevronLeft'; import ChevronRightIcon from '@material-ui/icons/ChevronRight'; -import BarChartStepperButton from './BarChartStepperButton'; -import BarChartSteps from './BarChartSteps'; +import { BarChartStepperButton } from './BarChartStepperButton'; +import { BarChartSteps } from './BarChartSteps'; import { useBarChartStepperStyles } from '../../utils/styles'; type BarChartStepperProps = { @@ -28,7 +28,7 @@ type BarChartStepperProps = { onChange: (activeStep: number) => void; }; -const BarChartStepper = ({ +export const BarChartStepper = ({ steps, disableScroll, onChange, @@ -111,5 +111,3 @@ const BarChartStepper = ({ ); }; - -export default BarChartStepper; diff --git a/plugins/cost-insights/src/components/BarChart/BarChartStepperButton.tsx b/plugins/cost-insights/src/components/BarChart/BarChartStepperButton.tsx index 66d1424576..0f36cfac77 100644 --- a/plugins/cost-insights/src/components/BarChart/BarChartStepperButton.tsx +++ b/plugins/cost-insights/src/components/BarChart/BarChartStepperButton.tsx @@ -22,7 +22,7 @@ interface BarChartStepperButtonProps extends ButtonBaseProps { name: string; } -const BarChartStepperButton = forwardRef( +export const BarChartStepperButton = forwardRef( ( { name, @@ -45,5 +45,3 @@ const BarChartStepperButton = forwardRef( ); }, ); - -export default BarChartStepperButton; diff --git a/plugins/cost-insights/src/components/BarChart/BarChartSteps.tsx b/plugins/cost-insights/src/components/BarChart/BarChartSteps.tsx index 1ca0c7082a..7e3d40b476 100644 --- a/plugins/cost-insights/src/components/BarChart/BarChartSteps.tsx +++ b/plugins/cost-insights/src/components/BarChart/BarChartSteps.tsx @@ -24,7 +24,7 @@ export type BarChartSteps = { onClick: (index: number) => void; }; -const BarChartSteps = ({ steps, activeStep, onClick }: BarChartSteps) => { +export const BarChartSteps = ({ steps, activeStep, onClick }: BarChartSteps) => { const classes = useStyles(); const handleOnClick = (index: number) => ( event: React.MouseEvent, @@ -39,14 +39,11 @@ const BarChartSteps = ({ steps, activeStep, onClick }: BarChartSteps) => {
))}
); }; - -export default BarChartSteps; diff --git a/plugins/cost-insights/src/components/BarChart/BarChartTick.tsx b/plugins/cost-insights/src/components/BarChart/BarChartTick.tsx index 99158c4573..005753fce6 100644 --- a/plugins/cost-insights/src/components/BarChart/BarChartTick.tsx +++ b/plugins/cost-insights/src/components/BarChart/BarChartTick.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import BarChartLabel from './BarChartLabel'; +import { BarChartLabel } from './BarChartLabel'; type BarChartTickProps = { x: number; @@ -44,5 +44,3 @@ export const BarChartTick = ({ ); }; - -export default BarChartTick; diff --git a/plugins/cost-insights/src/components/BarChart/index.ts b/plugins/cost-insights/src/components/BarChart/index.ts index 255bd2b3d8..b2c6390388 100644 --- a/plugins/cost-insights/src/components/BarChart/index.ts +++ b/plugins/cost-insights/src/components/BarChart/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './BarChart'; +export { BarChart } from './BarChart'; diff --git a/plugins/cost-insights/src/components/CopyUrlToClipboard/CopyUrlToClipboard.tsx b/plugins/cost-insights/src/components/CopyUrlToClipboard/CopyUrlToClipboard.tsx index c801eb86a5..0b5e7f9613 100644 --- a/plugins/cost-insights/src/components/CopyUrlToClipboard/CopyUrlToClipboard.tsx +++ b/plugins/cost-insights/src/components/CopyUrlToClipboard/CopyUrlToClipboard.tsx @@ -28,7 +28,7 @@ const ClipboardMessage = { error: "Couldn't copy to clipboard", }; -const CopyUrlToClipboard = () => { +export const CopyUrlToClipboard = () => { const location = useLocation(); const [state, copyToClipboard] = useCopyToClipboard(); const [copied, setCopied] = useState(false); @@ -66,5 +66,3 @@ const CopyUrlToClipboard = () => { ); }; - -export default CopyUrlToClipboard; diff --git a/plugins/cost-insights/src/components/CopyUrlToClipboard/index.ts b/plugins/cost-insights/src/components/CopyUrlToClipboard/index.ts index 15e2318c56..c7d6d4bf1f 100644 --- a/plugins/cost-insights/src/components/CopyUrlToClipboard/index.ts +++ b/plugins/cost-insights/src/components/CopyUrlToClipboard/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './CopyUrlToClipboard'; +export { CopyUrlToClipboard } from './CopyUrlToClipboard'; diff --git a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx index 026b16c74a..3a49ba4626 100644 --- a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx +++ b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx @@ -16,7 +16,7 @@ import React, { PropsWithChildren } from 'react'; import { renderInTestApp } from '@backstage/test-utils'; -import CostGrowth from './CostGrowth'; +import { CostGrowth } from './CostGrowth'; import { defaultCurrencies, Currency, @@ -41,10 +41,10 @@ const MockContext = ({ currency: Currency; engineerCost: number; }>) => ( - - {children} - -); + + {children} + + ); describe.each` engineerCost | ratio | amount | expected diff --git a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx index 0c0db2d62c..a43cae9720 100644 --- a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx +++ b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx @@ -35,7 +35,7 @@ export type CostGrowthProps = { duration: Duration; }; -const CostGrowth = ({ change, duration }: CostGrowthProps) => { +export const CostGrowth = ({ change, duration }: CostGrowthProps) => { const styles = useStyles(); const { engineerCost } = useConfig(); const [currency] = useCurrency(); @@ -70,5 +70,3 @@ const CostGrowth = ({ change, duration }: CostGrowthProps) => { return {cost}; }; - -export default CostGrowth; diff --git a/plugins/cost-insights/src/components/CostGrowth/index.ts b/plugins/cost-insights/src/components/CostGrowth/index.ts index 3cd809ee49..d4b1396586 100644 --- a/plugins/cost-insights/src/components/CostGrowth/index.ts +++ b/plugins/cost-insights/src/components/CostGrowth/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './CostGrowth'; +export { CostGrowth } from './CostGrowth'; diff --git a/plugins/cost-insights/src/components/CostInsightsHeader/CostInsightsHeader.test.tsx b/plugins/cost-insights/src/components/CostInsightsHeader/CostInsightsHeader.test.tsx index 8af5091188..8f299b0a3b 100644 --- a/plugins/cost-insights/src/components/CostInsightsHeader/CostInsightsHeader.test.tsx +++ b/plugins/cost-insights/src/components/CostInsightsHeader/CostInsightsHeader.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import CostInsightsHeader from './CostInsightsHeader'; +import { CostInsightsHeader } from './CostInsightsHeader'; import { renderInTestApp } from '@backstage/test-utils'; import { ApiProvider, diff --git a/plugins/cost-insights/src/components/CostInsightsHeader/CostInsightsHeader.tsx b/plugins/cost-insights/src/components/CostInsightsHeader/CostInsightsHeader.tsx index 57fa26b5fc..5e6de017d1 100644 --- a/plugins/cost-insights/src/components/CostInsightsHeader/CostInsightsHeader.tsx +++ b/plugins/cost-insights/src/components/CostInsightsHeader/CostInsightsHeader.tsx @@ -31,7 +31,7 @@ type CostInsightsHeaderProps = { alerts: number; }; -const CostInsightsHeader = (props: CostInsightsHeaderProps) => { +export const CostInsightsHeader = (props: CostInsightsHeaderProps) => { if (!props.hasCostData) { return ; } @@ -132,5 +132,3 @@ export const CostInsightsHeaderNoGroups = () => { ); }; - -export default CostInsightsHeader; diff --git a/plugins/cost-insights/src/components/CostInsightsHeader/index.ts b/plugins/cost-insights/src/components/CostInsightsHeader/index.ts index 8e7ddcc9c8..f5099aa19d 100644 --- a/plugins/cost-insights/src/components/CostInsightsHeader/index.ts +++ b/plugins/cost-insights/src/components/CostInsightsHeader/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default, CostInsightsHeaderNoGroups } from './CostInsightsHeader'; +export { CostInsightsHeader, CostInsightsHeaderNoGroups } from './CostInsightsHeader'; diff --git a/plugins/cost-insights/src/components/CostInsightsLayout/CostInsightsLayout.tsx b/plugins/cost-insights/src/components/CostInsightsLayout/CostInsightsLayout.tsx index 1e5a56f1ff..2fc43957df 100644 --- a/plugins/cost-insights/src/components/CostInsightsLayout/CostInsightsLayout.tsx +++ b/plugins/cost-insights/src/components/CostInsightsLayout/CostInsightsLayout.tsx @@ -17,7 +17,7 @@ import React, { PropsWithChildren } from 'react'; import { makeStyles } from '@material-ui/core'; import { Header, Page } from '@backstage/core'; import { Group } from '../../types'; -import CostInsightsTabs from '../CostInsightsTabs'; +import { CostInsightsTabs } from '../CostInsightsTabs'; const useStyles = makeStyles(theme => ({ root: { @@ -36,7 +36,7 @@ type CostInsightsLayoutProps = { groups: Group[]; }; -const CostInsightsLayout = ({ +export const CostInsightsLayout = ({ groups, children, }: PropsWithChildren) => { @@ -56,5 +56,3 @@ const CostInsightsLayout = ({ ); }; - -export default CostInsightsLayout; diff --git a/plugins/cost-insights/src/components/CostInsightsLayout/index.ts b/plugins/cost-insights/src/components/CostInsightsLayout/index.ts index dd35eb2855..aa1c27bc93 100644 --- a/plugins/cost-insights/src/components/CostInsightsLayout/index.ts +++ b/plugins/cost-insights/src/components/CostInsightsLayout/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './CostInsightsLayout'; +export { CostInsightsLayout } from './CostInsightsLayout'; diff --git a/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.test.tsx b/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.test.tsx index ac8561aa91..e2a0dd08b1 100644 --- a/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.test.tsx +++ b/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.test.tsx @@ -17,7 +17,7 @@ import React from 'react'; import { default as HappyFace } from '@material-ui/icons/SentimentSatisfiedAlt'; import { renderInTestApp } from '@backstage/test-utils'; -import CostInsightsNavigation from './CostInsightsNavigation'; +import { CostInsightsNavigation } from './CostInsightsNavigation'; import { Product, Icon } from '../../types'; import { MockConfigProvider, MockScrollProvider } from '../../utils/tests'; import { getDefaultNavigationItems } from '../../utils/navigation'; diff --git a/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx b/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx index fdbabe0402..62482c3323 100644 --- a/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx +++ b/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx @@ -36,7 +36,7 @@ type CostInsightsNavigationProps = { alerts: number; }; -const CostInsightsNavigation = ({ alerts }: CostInsightsNavigationProps) => { +export const CostInsightsNavigation = ({ alerts }: CostInsightsNavigationProps) => { const classes = useNavigationStyles(); const { products, icons } = useConfig(); @@ -64,10 +64,10 @@ const CostInsightsNavigation = ({ alerts }: CostInsightsNavigationProps) => { })} ) : ( - React.cloneElement(item.icon, { - className: classes.navigationIcon, - }) - ) + React.cloneElement(item.icon, { + className: classes.navigationIcon, + }) + ) } title={item.title} /> @@ -93,5 +93,3 @@ const NavigationMenuItem = ({ navigation, icon, title }: NavigationItem) => { ); }; - -export default CostInsightsNavigation; diff --git a/plugins/cost-insights/src/components/CostInsightsNavigation/index.ts b/plugins/cost-insights/src/components/CostInsightsNavigation/index.ts index 6c32ba7677..946ad157bb 100644 --- a/plugins/cost-insights/src/components/CostInsightsNavigation/index.ts +++ b/plugins/cost-insights/src/components/CostInsightsNavigation/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './CostInsightsNavigation'; +export { CostInsightsNavigation } from './CostInsightsNavigation'; diff --git a/plugins/cost-insights/src/components/CostInsightsPage/CostInsightsPage.tsx b/plugins/cost-insights/src/components/CostInsightsPage/CostInsightsPage.tsx index 8e96a6f5a4..638f6fef00 100644 --- a/plugins/cost-insights/src/components/CostInsightsPage/CostInsightsPage.tsx +++ b/plugins/cost-insights/src/components/CostInsightsPage/CostInsightsPage.tsx @@ -19,19 +19,20 @@ import { Box, Container, Divider, Grid, Typography } from '@material-ui/core'; import { featureFlagsApiRef, Progress, useApi } from '@backstage/core'; import { default as MaterialAlert } from '@material-ui/lab/Alert'; import { costInsightsApiRef } from '../../api'; -import AlertActionCardList from '../AlertActionCardList'; -import AlertInsights from '../AlertInsights'; -import CostInsightsLayout from '../CostInsightsLayout'; -import CopyUrlToClipboard from '../CopyUrlToClipboard'; -import CurrencySelect from '../CurrencySelect'; -import WhyCostsMatter from '../WhyCostsMatter'; -import CostInsightsHeader, { +import { AlertActionCardList } from '../AlertActionCardList'; +import { AlertInsights } from '../AlertInsights'; +import { CostInsightsLayout } from '../CostInsightsLayout'; +import { CopyUrlToClipboard } from '../CopyUrlToClipboard'; +import { CurrencySelect } from '../CurrencySelect'; +import { WhyCostsMatter } from '../WhyCostsMatter'; +import { + CostInsightsHeader, CostInsightsHeaderNoGroups, } from '../CostInsightsHeader'; -import CostInsightsNavigation from '../CostInsightsNavigation'; -import CostOverviewCard from '../CostOverviewCard'; -import ProductInsights from '../ProductInsights'; -import CostInsightsSupportButton from '../CostInsightsSupportButton'; +import { CostInsightsNavigation } from '../CostInsightsNavigation'; +import { CostOverviewCard } from '../CostOverviewCard'; +import { ProductInsights } from '../ProductInsights'; +import { CostInsightsSupportButton } from '../CostInsightsSupportButton'; import { useConfig, useCurrency, @@ -49,10 +50,10 @@ import { Project, } from '../../types'; import { mapLoadingToProps } from './selector'; -import ProjectSelect from '../ProjectSelect'; +import { ProjectSelect } from '../ProjectSelect'; import { useSubtleTypographyStyles } from '../../utils/styles'; -const CostInsightsPage = () => { +export const CostInsightsPage = () => { const classes = useSubtleTypographyStyles(); const flags = useApi(featureFlagsApiRef).getFlags(); // There is not currently a UI to set feature flags @@ -300,5 +301,3 @@ const CostInsightsPage = () => { ); }; - -export default CostInsightsPage; diff --git a/plugins/cost-insights/src/components/CostInsightsPage/CostInsightsPageRoot.tsx b/plugins/cost-insights/src/components/CostInsightsPage/CostInsightsPageRoot.tsx index 6dca7982db..4f506b4076 100644 --- a/plugins/cost-insights/src/components/CostInsightsPage/CostInsightsPageRoot.tsx +++ b/plugins/cost-insights/src/components/CostInsightsPage/CostInsightsPageRoot.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import CostInsightsPage from './CostInsightsPage'; +import { CostInsightsPage } from './CostInsightsPage'; import { FilterProvider } from '../../hooks/useFilters'; import { LoadingProvider } from '../../hooks/useLoading'; import { GroupsProvider } from '../../hooks/useGroups'; @@ -25,7 +25,7 @@ import { ConfigProvider } from '../../hooks/useConfig'; import { BillingDateProvider } from '../../hooks/useLastCompleteBillingDate'; import { CostInsightsThemeProvider } from './CostInsightsThemeProvider'; -const CostInsightsPageRoot = () => ( +export const CostInsightsPageRoot = () => ( @@ -44,5 +44,3 @@ const CostInsightsPageRoot = () => ( ); - -export default CostInsightsPageRoot; diff --git a/plugins/cost-insights/src/components/CostInsightsPage/index.ts b/plugins/cost-insights/src/components/CostInsightsPage/index.ts index 67d5eb5daa..07d7b76233 100644 --- a/plugins/cost-insights/src/components/CostInsightsPage/index.ts +++ b/plugins/cost-insights/src/components/CostInsightsPage/index.ts @@ -14,4 +14,5 @@ * limitations under the License. */ -export { default } from './CostInsightsPageRoot'; +export { CostInsightsPage } from './CostInsightsPage'; +export { CostInsightsPageRoot } from './CostInsightsPageRoot'; diff --git a/plugins/cost-insights/src/components/CostInsightsSupportButton/CostInsightsSupportButton.tsx b/plugins/cost-insights/src/components/CostInsightsSupportButton/CostInsightsSupportButton.tsx index c8e7fdac97..4dde49b3ef 100644 --- a/plugins/cost-insights/src/components/CostInsightsSupportButton/CostInsightsSupportButton.tsx +++ b/plugins/cost-insights/src/components/CostInsightsSupportButton/CostInsightsSupportButton.tsx @@ -17,12 +17,10 @@ import React from 'react'; import { SupportButton } from '@backstage/core'; -const CostInsightsSupportButton = () => { +export const CostInsightsSupportButton = () => { return ( Insights into cloud costs for your organization ); }; - -export default CostInsightsSupportButton; diff --git a/plugins/cost-insights/src/components/CostInsightsSupportButton/index.ts b/plugins/cost-insights/src/components/CostInsightsSupportButton/index.ts index eab947c1be..2049bd11e5 100644 --- a/plugins/cost-insights/src/components/CostInsightsSupportButton/index.ts +++ b/plugins/cost-insights/src/components/CostInsightsSupportButton/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './CostInsightsSupportButton'; +export { CostInsightsSupportButton } from './CostInsightsSupportButton'; diff --git a/plugins/cost-insights/src/components/CostInsightsTabs/CostInsightsTabs.test.tsx b/plugins/cost-insights/src/components/CostInsightsTabs/CostInsightsTabs.test.tsx index b75e0ab0d9..a910d43c22 100644 --- a/plugins/cost-insights/src/components/CostInsightsTabs/CostInsightsTabs.test.tsx +++ b/plugins/cost-insights/src/components/CostInsightsTabs/CostInsightsTabs.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import CostInsightsTabs from './CostInsightsTabs'; +import { CostInsightsTabs } from './CostInsightsTabs'; import UserEvent from '@testing-library/user-event'; import { Group } from '../../types'; import { MockFilterProvider, MockLoadingProvider } from '../../utils/tests'; diff --git a/plugins/cost-insights/src/components/CostInsightsTabs/CostInsightsTabs.tsx b/plugins/cost-insights/src/components/CostInsightsTabs/CostInsightsTabs.tsx index 3b86aa79ef..9e2f9598dc 100644 --- a/plugins/cost-insights/src/components/CostInsightsTabs/CostInsightsTabs.tsx +++ b/plugins/cost-insights/src/components/CostInsightsTabs/CostInsightsTabs.tsx @@ -26,7 +26,7 @@ export type CostInsightsTabsProps = { groups: Group[]; }; -const CostInsightsTabs = ({ groups }: CostInsightsTabsProps) => { +export const CostInsightsTabs = ({ groups }: CostInsightsTabsProps) => { const classes = useStyles(); const [index] = useState(0); // index is fixed for now until other tabs are added const [groupMenuEl, setGroupMenuEl] = useState(null); @@ -107,5 +107,3 @@ const CostInsightsTabs = ({ groups }: CostInsightsTabsProps) => { ); }; - -export default CostInsightsTabs; diff --git a/plugins/cost-insights/src/components/CostInsightsTabs/index.ts b/plugins/cost-insights/src/components/CostInsightsTabs/index.ts index 7055334c2d..76472bb631 100644 --- a/plugins/cost-insights/src/components/CostInsightsTabs/index.ts +++ b/plugins/cost-insights/src/components/CostInsightsTabs/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './CostInsightsTabs'; +export { CostInsightsTabs } from './CostInsightsTabs'; diff --git a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewCard.tsx b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewCard.tsx index a08e7fc789..c6269f7dc6 100644 --- a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewCard.tsx +++ b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewCard.tsx @@ -16,12 +16,12 @@ import React from 'react'; import { Box, Card, CardContent, Divider, useTheme } from '@material-ui/core'; -import CostGrowth from '../CostGrowth'; -import CostOverviewChart from './CostOverviewChart'; -import CostOverviewHeader from './CostOverviewHeader'; -import LegendItem from '../LegendItem'; -import MetricSelect from '../MetricSelect'; -import PeriodSelect from '../PeriodSelect'; +import { CostGrowth } from '../CostGrowth'; +import { CostOverviewChart } from './CostOverviewChart'; +import { CostOverviewHeader } from './CostOverviewHeader'; +import { LegendItem } from '../LegendItem'; +import { MetricSelect } from '../MetricSelect'; +import { PeriodSelect } from '../PeriodSelect'; import { useScroll, useFilters, useConfig } from '../../hooks'; import { mapFiltersToProps } from './selector'; import { DefaultNavigation } from '../../utils/navigation'; @@ -39,7 +39,7 @@ export type CostOverviewCardProps = { metricData: MetricData | null; }; -const CostOverviewCard = ({ +export const CostOverviewCard = ({ dailyCostData, metricData, }: CostOverviewCardProps) => { @@ -114,5 +114,3 @@ const CostOverviewCard = ({ ); }; - -export default CostOverviewCard; diff --git a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewChart.tsx b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewChart.tsx index 9612589542..e442b9a64a 100644 --- a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewChart.tsx +++ b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewChart.tsx @@ -38,7 +38,7 @@ import { overviewGraphTickFormatter, formatGraphValue, } from '../../utils/graphs'; -import CostOverviewTooltip from './CostOverviewTooltip'; +import { CostOverviewTooltip } from './CostOverviewTooltip'; import { TooltipItemProps } from '../Tooltip'; import { useCostOverviewStyles as useStyles } from '../../utils/styles'; import { groupByDate, toDataMax, trendFrom } from '../../utils/charts'; @@ -51,7 +51,7 @@ type CostOverviewChartProps = { responsive?: boolean; }; -const CostOverviewChart = ({ +export const CostOverviewChart = ({ dailyCostData, metric, metricData, @@ -181,5 +181,3 @@ const CostOverviewChart = ({ ); }; - -export default CostOverviewChart; diff --git a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewHeader.tsx b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewHeader.tsx index 76a0d944de..c01eabfa53 100644 --- a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewHeader.tsx +++ b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewHeader.tsx @@ -21,32 +21,30 @@ type CostOverviewHeaderProps = { subtitle?: string; }; -const CostOverviewHeader = ({ +export const CostOverviewHeader = ({ title, subtitle, children, }: PropsWithChildren) => ( - - - - {title} - - {!!subtitle && ( - - {subtitle} + + + + {title} - )} + {!!subtitle && ( + + {subtitle} + + )} + + + {children} + - - {children} - - -); - -export default CostOverviewHeader; + ); diff --git a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewTooltip.tsx b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewTooltip.tsx index c8a7b8533c..e0a9b9a9ea 100644 --- a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewTooltip.tsx +++ b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewTooltip.tsx @@ -24,7 +24,7 @@ export type CostOverviewTooltipProps = TooltipProps & { format: (payload: TooltipPayload) => TooltipItemProps; }; -const CostOverviewTooltip = ({ +export const CostOverviewTooltip = ({ label, payload, dataKeys, @@ -36,5 +36,3 @@ const CostOverviewTooltip = ({ .map(p => format(p)); return ; }; - -export default CostOverviewTooltip; diff --git a/plugins/cost-insights/src/components/CostOverviewCard/index.ts b/plugins/cost-insights/src/components/CostOverviewCard/index.ts index c59fb5cc5b..370dab8d01 100644 --- a/plugins/cost-insights/src/components/CostOverviewCard/index.ts +++ b/plugins/cost-insights/src/components/CostOverviewCard/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './CostOverviewCard'; +export { CostOverviewCard } from './CostOverviewCard'; diff --git a/plugins/cost-insights/src/components/CurrencySelect/CurrencySelect.tsx b/plugins/cost-insights/src/components/CurrencySelect/CurrencySelect.tsx index 24063a664e..413426e9af 100644 --- a/plugins/cost-insights/src/components/CurrencySelect/CurrencySelect.tsx +++ b/plugins/cost-insights/src/components/CurrencySelect/CurrencySelect.tsx @@ -27,7 +27,7 @@ type CurrencySelectProps = { onSelect: (currency: Currency) => void; }; -const CurrencySelect = ({ +export const CurrencySelect = ({ currency, currencies, onSelect, @@ -71,5 +71,3 @@ const CurrencySelect = ({ ); }; - -export default CurrencySelect; diff --git a/plugins/cost-insights/src/components/CurrencySelect/index.ts b/plugins/cost-insights/src/components/CurrencySelect/index.ts index 322b67d4ce..5e42217fe1 100644 --- a/plugins/cost-insights/src/components/CurrencySelect/index.ts +++ b/plugins/cost-insights/src/components/CurrencySelect/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './CurrencySelect'; +export { CurrencySelect } from './CurrencySelect'; diff --git a/plugins/cost-insights/src/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.tsx b/plugins/cost-insights/src/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.tsx index 9783fadcb2..3442de49fc 100644 --- a/plugins/cost-insights/src/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.tsx +++ b/plugins/cost-insights/src/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.tsx @@ -17,9 +17,9 @@ import React from 'react'; import { Box, Typography } from '@material-ui/core'; import { CodeSnippet } from '@backstage/core'; -import AlertInstructionsLayout from '../AlertInstructionsLayout'; +import { AlertInstructionsLayout } from '../AlertInstructionsLayout'; -const LabelDataflowInstructionsPage = () => { +export const LabelDataflowInstructionsPage = () => { return ( Labeling Dataflow Jobs @@ -92,5 +92,3 @@ sc.optionsAs[DataflowPipelineOptions].setLabels(Map("job-id" -> "my-dataflow-job ); }; - -export default LabelDataflowInstructionsPage; diff --git a/plugins/cost-insights/src/components/LabelDataflowInstructionsPage/index.ts b/plugins/cost-insights/src/components/LabelDataflowInstructionsPage/index.ts index 052ed379ec..de2136f033 100644 --- a/plugins/cost-insights/src/components/LabelDataflowInstructionsPage/index.ts +++ b/plugins/cost-insights/src/components/LabelDataflowInstructionsPage/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './LabelDataflowInstructionsPage'; +export { LabelDataflowInstructionsPage } from './LabelDataflowInstructionsPage'; diff --git a/plugins/cost-insights/src/components/LegendItem/LegendItem.tsx b/plugins/cost-insights/src/components/LegendItem/LegendItem.tsx index ffde830312..cabc5f9c59 100644 --- a/plugins/cost-insights/src/components/LegendItem/LegendItem.tsx +++ b/plugins/cost-insights/src/components/LegendItem/LegendItem.tsx @@ -26,7 +26,7 @@ type LegendItemProps = { markerColor?: string; }; -const LegendItem = ({ +export const LegendItem = ({ title, tooltipText, markerColor, @@ -73,5 +73,3 @@ const LegendItem = ({ ); }; - -export default LegendItem; diff --git a/plugins/cost-insights/src/components/LegendItem/index.ts b/plugins/cost-insights/src/components/LegendItem/index.ts index 763b8fc4f4..e97af0c97f 100644 --- a/plugins/cost-insights/src/components/LegendItem/index.ts +++ b/plugins/cost-insights/src/components/LegendItem/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './LegendItem'; +export { LegendItem } from './LegendItem'; diff --git a/plugins/cost-insights/src/components/MetricSelect/MetricSelect.test.tsx b/plugins/cost-insights/src/components/MetricSelect/MetricSelect.test.tsx index e78fd77b1a..bfb6daedd6 100644 --- a/plugins/cost-insights/src/components/MetricSelect/MetricSelect.test.tsx +++ b/plugins/cost-insights/src/components/MetricSelect/MetricSelect.test.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { waitFor } from '@testing-library/react'; import UserEvent from '@testing-library/user-event'; -import MetricSelect, { MetricSelectProps } from './MetricSelect'; +import { MetricSelect, MetricSelectProps } from './MetricSelect'; import { renderInTestApp } from '@backstage/test-utils'; describe('', () => { diff --git a/plugins/cost-insights/src/components/MetricSelect/MetricSelect.tsx b/plugins/cost-insights/src/components/MetricSelect/MetricSelect.tsx index 474d8622ea..f91070271f 100644 --- a/plugins/cost-insights/src/components/MetricSelect/MetricSelect.tsx +++ b/plugins/cost-insights/src/components/MetricSelect/MetricSelect.tsx @@ -25,7 +25,7 @@ export type MetricSelectProps = { onSelect: (metric: Maybe) => void; }; -const MetricSelect = ({ metric, metrics, onSelect }: MetricSelectProps) => { +export const MetricSelect = ({ metric, metrics, onSelect }: MetricSelectProps) => { const classes = useStyles(); function onChange(e: React.ChangeEvent<{ value: unknown }>) { @@ -61,5 +61,3 @@ const MetricSelect = ({ metric, metrics, onSelect }: MetricSelectProps) => { ); }; - -export default MetricSelect; diff --git a/plugins/cost-insights/src/components/MetricSelect/index.ts b/plugins/cost-insights/src/components/MetricSelect/index.ts index f68e5031c1..4be7e97e90 100644 --- a/plugins/cost-insights/src/components/MetricSelect/index.ts +++ b/plugins/cost-insights/src/components/MetricSelect/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './MetricSelect'; +export { MetricSelect } from './MetricSelect'; diff --git a/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.test.tsx b/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.test.tsx index 3c55285908..e2cf1b7480 100644 --- a/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.test.tsx +++ b/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.test.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { getByRole, waitFor } from '@testing-library/react'; import { renderInTestApp } from '@backstage/test-utils'; import UserEvent from '@testing-library/user-event'; -import PeriodSelect, { getDefaultOptions } from './PeriodSelect'; +import { PeriodSelect, getDefaultOptions } from './PeriodSelect'; import { Duration, getDefaultPageFilters, Group } from '../../types'; import { MockBillingDateProvider } from '../../utils/tests'; diff --git a/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx b/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx index 08cf8a73f9..0088830471 100644 --- a/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx +++ b/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx @@ -58,7 +58,7 @@ type PeriodSelectProps = { options?: PeriodOption[]; }; -const PeriodSelect = ({ duration, onSelect, options }: PeriodSelectProps) => { +export const PeriodSelect = ({ duration, onSelect, options }: PeriodSelectProps) => { const classes = useStyles(); const lastCompleteBillingDate = useLastCompleteBillingDate(); const optionsOrDefault = @@ -95,5 +95,3 @@ const PeriodSelect = ({ duration, onSelect, options }: PeriodSelectProps) => { ); }; - -export default PeriodSelect; diff --git a/plugins/cost-insights/src/components/PeriodSelect/index.ts b/plugins/cost-insights/src/components/PeriodSelect/index.ts index 7bd70b3358..31ca2a649c 100644 --- a/plugins/cost-insights/src/components/PeriodSelect/index.ts +++ b/plugins/cost-insights/src/components/PeriodSelect/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './PeriodSelect'; +export { PeriodSelect } from './PeriodSelect'; diff --git a/plugins/cost-insights/src/components/ProductInsights/ProductInsights.tsx b/plugins/cost-insights/src/components/ProductInsights/ProductInsights.tsx index cc52012543..7420c8d82c 100644 --- a/plugins/cost-insights/src/components/ProductInsights/ProductInsights.tsx +++ b/plugins/cost-insights/src/components/ProductInsights/ProductInsights.tsx @@ -16,12 +16,11 @@ import React from 'react'; import { Box, Typography, Grid } from '@material-ui/core'; -import ProductInsightsCard from '../ProductInsightsCard'; +import { ProductInsightsCard } from '../ProductInsightsCard'; import { useConfig } from '../../hooks'; -const ProductInsights = ({}) => { - const { products } = useConfig(); - +export const ProductInsights = ({ }) => { + const config = useConfig(); return ( <> @@ -30,7 +29,7 @@ const ProductInsights = ({}) => { - {products.map(product => ( + {config.products.map(product => ( @@ -39,5 +38,3 @@ const ProductInsights = ({}) => { ); }; - -export default ProductInsights; diff --git a/plugins/cost-insights/src/components/ProductInsights/index.ts b/plugins/cost-insights/src/components/ProductInsights/index.ts index 0a20d3c322..84c2d410b0 100644 --- a/plugins/cost-insights/src/components/ProductInsights/index.ts +++ b/plugins/cost-insights/src/components/ProductInsights/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './ProductInsights'; +export { ProductInsights } from './ProductInsights'; diff --git a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.test.tsx b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.test.tsx index bae4eef591..9d1610e298 100644 --- a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.test.tsx +++ b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.test.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { renderInTestApp } from '@backstage/test-utils'; -import ProductInsightsCard from './ProductInsightsCard'; +import { ProductInsightsCard } from './ProductInsightsCard'; import { CostInsightsApi } from '../../api'; import { createMockEntity, diff --git a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.tsx b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.tsx index bf56eb23e8..840c99522a 100644 --- a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.tsx +++ b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.tsx @@ -19,9 +19,9 @@ import { InfoCard, useApi } from '@backstage/core'; import { Box } from '@material-ui/core'; import Alert from '@material-ui/lab/Alert'; import { costInsightsApiRef } from '../../api'; -import PeriodSelect from '../PeriodSelect'; -import ResourceGrowthBarChart from '../ResourceGrowthBarChart'; -import ResourceGrowthBarChartLegend from '../ResourceGrowthBarChartLegend'; +import { PeriodSelect } from '../PeriodSelect'; +import { ResourceGrowthBarChart } from '../ResourceGrowthBarChart'; +import { ResourceGrowthBarChartLegend } from '../ResourceGrowthBarChartLegend'; import { useFilters, useLastCompleteBillingDate, @@ -38,7 +38,7 @@ type ProductInsightsCardProps = { product: Product; }; -const ProductInsightsCard = ({ product }: ProductInsightsCardProps) => { +export const ProductInsightsCard = ({ product }: ProductInsightsCardProps) => { const client = useApi(costInsightsApiRef); const classes = useStyles(); const { ScrollAnchor } = useScroll(product.kind); @@ -166,5 +166,3 @@ const ProductInsightsCard = ({ product }: ProductInsightsCardProps) => { ); }; - -export default ProductInsightsCard; diff --git a/plugins/cost-insights/src/components/ProductInsightsCard/index.ts b/plugins/cost-insights/src/components/ProductInsightsCard/index.ts index ef378004f0..61222f9466 100644 --- a/plugins/cost-insights/src/components/ProductInsightsCard/index.ts +++ b/plugins/cost-insights/src/components/ProductInsightsCard/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './ProductInsightsCard'; +export { ProductInsightsCard } from './ProductInsightsCard'; diff --git a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.test.tsx b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.test.tsx index 97775258c9..4b5da409a4 100644 --- a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.test.tsx +++ b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.test.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { renderInTestApp } from '@backstage/test-utils'; -import ProjectGrowthAlertCard from './ProjectGrowthAlertCard'; +import { ProjectGrowthAlertCard } from './ProjectGrowthAlertCard'; import { createMockProjectGrowthData } from '../../utils/mockData'; import { MockCurrencyProvider, diff --git a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx index 1b37a5a131..18f7fa151d 100644 --- a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx +++ b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx @@ -18,8 +18,8 @@ import React from 'react'; import moment from 'moment'; import { Box } from '@material-ui/core'; import { InfoCard } from '@backstage/core'; -import ResourceGrowthBarChart from '../ResourceGrowthBarChart'; -import ResourceGrowthBarChartLegend from '../ResourceGrowthBarChartLegend'; +import { ResourceGrowthBarChart } from '../ResourceGrowthBarChart'; +import { ResourceGrowthBarChartLegend } from '../ResourceGrowthBarChartLegend'; import { Duration, ProjectGrowthData } from '../../types'; import { pluralOf } from '../../utils/grammar'; @@ -27,13 +27,12 @@ type ProjectGrowthAlertProps = { alert: ProjectGrowthData; }; -const ProjectGrowthAlertCard = ({ alert }: ProjectGrowthAlertProps) => { +export const ProjectGrowthAlertCard = ({ alert }: ProjectGrowthAlertProps) => { const [costStart, costEnd] = alert.aggregation; const subheader = ` - ${alert.products.length} ${pluralOf(alert.products.length, 'product')}${ - alert.products.length > 1 ? ', sorted by cost' : '' - }`; + ${alert.products.length} ${pluralOf(alert.products.length, 'product')}${alert.products.length > 1 ? ', sorted by cost' : '' + }`; const previousName = moment(alert.periodStart, 'YYYY-[Q]Q').format( '[Q]Q YYYY', ); @@ -64,5 +63,3 @@ const ProjectGrowthAlertCard = ({ alert }: ProjectGrowthAlertProps) => { ); }; - -export default ProjectGrowthAlertCard; diff --git a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/index.ts b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/index.ts index ab608f5f4c..75656f105c 100644 --- a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/index.ts +++ b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './ProjectGrowthAlertCard'; +export { ProjectGrowthAlertCard } from './ProjectGrowthAlertCard'; diff --git a/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx b/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx index 634514c1df..3c2d241222 100644 --- a/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx +++ b/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx @@ -17,7 +17,7 @@ import React from 'react'; import { Box, Typography } from '@material-ui/core'; import { InfoCard } from '@backstage/core'; -import AlertInstructionsLayout from '../AlertInstructionsLayout'; +import { AlertInstructionsLayout } from '../AlertInstructionsLayout'; import { Alert, Duration, @@ -26,10 +26,10 @@ import { ProjectGrowthAlert, ProjectGrowthData, } from '../../types'; -import ResourceGrowthBarChartLegend from '../ResourceGrowthBarChartLegend'; -import ResourceGrowthBarChart from '../ResourceGrowthBarChart'; +import { ResourceGrowthBarChartLegend } from '../ResourceGrowthBarChartLegend'; +import { ResourceGrowthBarChart } from '../ResourceGrowthBarChart'; -const ProjectGrowthInstructionsPage = () => { +export const ProjectGrowthInstructionsPage = () => { const alertData: ProjectGrowthData = { project: 'example-project', periodStart: 'Q1 2020', @@ -211,5 +211,3 @@ const ProjectGrowthInstructionsPage = () => { ); }; - -export default ProjectGrowthInstructionsPage; diff --git a/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/index.ts b/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/index.ts index c75240405c..053289b2e2 100644 --- a/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/index.ts +++ b/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './ProjectGrowthInstructionsPage'; +export { ProjectGrowthInstructionsPage } from './ProjectGrowthInstructionsPage'; diff --git a/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.test.tsx b/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.test.tsx index 848fd9ea7c..16270429e8 100644 --- a/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.test.tsx +++ b/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.test.tsx @@ -17,7 +17,7 @@ import React from 'react'; import { getByRole, waitFor } from '@testing-library/react'; import UserEvent from '@testing-library/user-event'; -import ProjectSelect from './ProjectSelect'; +import { ProjectSelect } from './ProjectSelect'; import { MockFilterProvider } from '../../utils/tests'; import { renderInTestApp } from '@backstage/test-utils'; diff --git a/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.tsx b/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.tsx index 934ad99f63..29169d1f5f 100644 --- a/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.tsx +++ b/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.tsx @@ -24,7 +24,7 @@ type ProjectSelectProps = { onSelect: (project: Maybe) => void; }; -const ProjectSelect = ({ project, projects, onSelect }: ProjectSelectProps) => { +export const ProjectSelect = ({ project, projects, onSelect }: ProjectSelectProps) => { const classes = useStyles(); const projectOptions = [{ id: 'all' } as Project, ...projects] @@ -66,5 +66,3 @@ const ProjectSelect = ({ project, projects, onSelect }: ProjectSelectProps) => { ); }; - -export default ProjectSelect; diff --git a/plugins/cost-insights/src/components/ProjectSelect/index.ts b/plugins/cost-insights/src/components/ProjectSelect/index.ts index 47a2b9e22c..06a553444d 100644 --- a/plugins/cost-insights/src/components/ProjectSelect/index.ts +++ b/plugins/cost-insights/src/components/ProjectSelect/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './ProjectSelect'; +export { ProjectSelect } from './ProjectSelect'; diff --git a/plugins/cost-insights/src/components/ResourceGrowthBarChart/ResourceGrowthBarChart.test.tsx b/plugins/cost-insights/src/components/ResourceGrowthBarChart/ResourceGrowthBarChart.test.tsx index 9a3899f2ff..e3d9d61d1b 100644 --- a/plugins/cost-insights/src/components/ResourceGrowthBarChart/ResourceGrowthBarChart.test.tsx +++ b/plugins/cost-insights/src/components/ResourceGrowthBarChart/ResourceGrowthBarChart.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import ResourceGrowthBarChart from './ResourceGrowthBarChart'; +import { ResourceGrowthBarChart } from './ResourceGrowthBarChart'; import { renderInTestApp } from '@backstage/test-utils'; import { createMockEntity } from '../../utils/mockData'; diff --git a/plugins/cost-insights/src/components/ResourceGrowthBarChart/ResourceGrowthBarChart.tsx b/plugins/cost-insights/src/components/ResourceGrowthBarChart/ResourceGrowthBarChart.tsx index daa6d88683..b4014bf00f 100644 --- a/plugins/cost-insights/src/components/ResourceGrowthBarChart/ResourceGrowthBarChart.tsx +++ b/plugins/cost-insights/src/components/ResourceGrowthBarChart/ResourceGrowthBarChart.tsx @@ -26,7 +26,7 @@ import { Maybe, ResourceData, } from '../../types'; -import BarChart from '../BarChart'; +import { BarChart } from '../BarChart'; import { TooltipItemProps } from '../Tooltip'; import { useTheme } from '@material-ui/core'; @@ -36,7 +36,7 @@ export type ResourceGrowthBarChartProps = { currentName: string; }; -const ResourceGrowthBarChart = ({ +export const ResourceGrowthBarChart = ({ resources, previousName, currentName, @@ -85,5 +85,3 @@ const ResourceGrowthBarChart = ({ /> ); }; - -export default ResourceGrowthBarChart; diff --git a/plugins/cost-insights/src/components/ResourceGrowthBarChart/index.ts b/plugins/cost-insights/src/components/ResourceGrowthBarChart/index.ts index b1388143e4..ef649a17af 100644 --- a/plugins/cost-insights/src/components/ResourceGrowthBarChart/index.ts +++ b/plugins/cost-insights/src/components/ResourceGrowthBarChart/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './ResourceGrowthBarChart'; +export { ResourceGrowthBarChart } from './ResourceGrowthBarChart'; diff --git a/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.test.tsx b/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.test.tsx index e3c2506296..2bc998d9df 100644 --- a/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.test.tsx +++ b/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.test.tsx @@ -16,7 +16,7 @@ import React, { PropsWithChildren } from 'react'; import { renderInTestApp } from '@backstage/test-utils'; -import ResourceGrowthBarChartLegend from './ResourceGrowthBarChartLegend'; +import { ResourceGrowthBarChartLegend } from './ResourceGrowthBarChartLegend'; import { defaultCurrencies, Duration, findAlways } from '../../types'; import { MockConfigProvider, MockCurrencyProvider } from '../../utils/tests'; diff --git a/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.tsx b/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.tsx index 9b0f77ceda..6b5ce17c95 100644 --- a/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.tsx +++ b/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.tsx @@ -16,8 +16,8 @@ import React from 'react'; import { Box, useTheme } from '@material-ui/core'; -import LegendItem from '../LegendItem'; -import CostGrowth from '../CostGrowth'; +import { LegendItem } from '../LegendItem'; +import { CostGrowth } from '../CostGrowth'; import { currencyFormatter } from '../../utils/formatters'; import { ChangeStatistic, CostInsightsTheme, Duration } from '../../types'; @@ -30,7 +30,7 @@ export type ResourceGrowthBarChartLegendProps = { costEnd: number; }; -const ResourceGrowthBarChartLegend = ({ +export const ResourceGrowthBarChartLegend = ({ change, duration, previousName, @@ -58,5 +58,3 @@ const ResourceGrowthBarChartLegend = ({ ); }; - -export default ResourceGrowthBarChartLegend; diff --git a/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/index.ts b/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/index.ts index 7071799805..ee77a483e6 100644 --- a/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/index.ts +++ b/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './ResourceGrowthBarChartLegend'; +export { ResourceGrowthBarChartLegend } from './ResourceGrowthBarChartLegend'; diff --git a/plugins/cost-insights/src/components/Tooltip/Tooltip.test.tsx b/plugins/cost-insights/src/components/Tooltip/Tooltip.test.tsx index 8c12b34ffb..2f1f8fe7e1 100644 --- a/plugins/cost-insights/src/components/Tooltip/Tooltip.test.tsx +++ b/plugins/cost-insights/src/components/Tooltip/Tooltip.test.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { renderInTestApp } from '@backstage/test-utils'; -import Tooltip from './Tooltip'; +import { Tooltip } from './Tooltip'; import { CostInsightsThemeProvider } from '../CostInsightsPage/CostInsightsThemeProvider'; const mockTooltipItems = [ diff --git a/plugins/cost-insights/src/components/Tooltip/Tooltip.tsx b/plugins/cost-insights/src/components/Tooltip/Tooltip.tsx index 727b2476c8..e0ee93c669 100644 --- a/plugins/cost-insights/src/components/Tooltip/Tooltip.tsx +++ b/plugins/cost-insights/src/components/Tooltip/Tooltip.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { Box, Typography } from '@material-ui/core'; -import TooltipItem, { TooltipItemProps } from './TooltipItem'; +import { TooltipItem, TooltipItemProps } from './TooltipItem'; import { useTooltipStyles } from '../../utils/styles'; export type TooltipProps = { @@ -24,7 +24,7 @@ export type TooltipProps = { items?: Array; }; -const Tooltip = ({ label, items }: TooltipProps) => { +export const Tooltip = ({ label, items }: TooltipProps) => { const classes = useTooltipStyles(); return ( { ); }; - -export default Tooltip; diff --git a/plugins/cost-insights/src/components/Tooltip/TooltipItem.tsx b/plugins/cost-insights/src/components/Tooltip/TooltipItem.tsx index 67d4eac15f..a084a0fd1d 100644 --- a/plugins/cost-insights/src/components/Tooltip/TooltipItem.tsx +++ b/plugins/cost-insights/src/components/Tooltip/TooltipItem.tsx @@ -25,7 +25,7 @@ export type TooltipItemProps = { fill: string; }; -const TooltipItem = ({ fill, label, value }: TooltipItemProps) => { +export const TooltipItem = ({ fill, label, value }: TooltipItemProps) => { const classes = useStyles(); const style = { fill: fill }; return ( @@ -45,5 +45,3 @@ const TooltipItem = ({ fill, label, value }: TooltipItemProps) => { ); }; - -export default TooltipItem; diff --git a/plugins/cost-insights/src/components/Tooltip/index.ts b/plugins/cost-insights/src/components/Tooltip/index.ts index d56352d324..b26409480e 100644 --- a/plugins/cost-insights/src/components/Tooltip/index.ts +++ b/plugins/cost-insights/src/components/Tooltip/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -export { default as Tooltip } from './Tooltip'; +export { Tooltip } from './Tooltip'; export type { TooltipProps } from './Tooltip'; -export { default as TooltipItem } from './TooltipItem'; +export { TooltipItem } from './TooltipItem'; export type { TooltipItemProps } from './TooltipItem'; diff --git a/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.test.tsx b/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.test.tsx index edc4152e3c..6edd4ed637 100644 --- a/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.test.tsx +++ b/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import UnlabeledDataflowAlertCard from './UnlabeledDataflowAlertCard'; +import { UnlabeledDataflowAlertCard } from './UnlabeledDataflowAlertCard'; import { createMockUnlabeledDataflowData, createMockUnlabeledDataflowAlertProject, @@ -44,7 +44,7 @@ describe('', () => { it('renders the correct subheader for multiple projects', async () => { const subheader = new RegExp( `Showing costs from ${MockUnlabeledDataflowAlertMultipleProjects.projects.length} ` + - 'projects with unlabeled Dataflow jobs in the last 30 days.', + 'projects with unlabeled Dataflow jobs in the last 30 days.', ); const rendered = await renderInTestApp( { +export const UnlabeledDataflowAlertCard = ({ alert }: UnlabeledDataflowAlertProps) => { const projects = pluralOf(alert.projects.length, 'project'); const subheader = ` Showing costs from ${alert.projects.length} ${projects} with unlabeled Dataflow jobs in the last 30 days. @@ -47,5 +47,3 @@ const UnlabeledDataflowAlertCard = ({ alert }: UnlabeledDataflowAlertProps) => { ); }; - -export default UnlabeledDataflowAlertCard; diff --git a/plugins/cost-insights/src/components/UnlabeledDataflowBarChart/UnlabeledDataflowBarChart.tsx b/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowBarChart.tsx similarity index 96% rename from plugins/cost-insights/src/components/UnlabeledDataflowBarChart/UnlabeledDataflowBarChart.tsx rename to plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowBarChart.tsx index 7b1f4e31ec..faf27ba04f 100644 --- a/plugins/cost-insights/src/components/UnlabeledDataflowBarChart/UnlabeledDataflowBarChart.tsx +++ b/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowBarChart.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { TooltipPayload } from 'recharts'; -import BarChart from '../BarChart'; +import { BarChart } from '../BarChart'; import { TooltipItemProps } from '../Tooltip'; import { BarChartData, @@ -69,5 +69,3 @@ export const UnlabeledDataflowBarChart = ({ /> ); }; - -export default UnlabeledDataflowBarChart; diff --git a/plugins/cost-insights/src/components/UnlabeledDataflowBarChartLegend/UnlabeledDataflowBarChartLegend.test.tsx b/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowBarChartLegend.test.tsx similarity index 93% rename from plugins/cost-insights/src/components/UnlabeledDataflowBarChartLegend/UnlabeledDataflowBarChartLegend.test.tsx rename to plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowBarChartLegend.test.tsx index 9ab4e90001..ab38ba8d44 100644 --- a/plugins/cost-insights/src/components/UnlabeledDataflowBarChartLegend/UnlabeledDataflowBarChartLegend.test.tsx +++ b/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowBarChartLegend.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import UnlabeledDataflowBarChartLegend from './UnlabeledDataflowBarChartLegend'; +import { UnlabeledDataflowBarChartLegend } from './UnlabeledDataflowBarChartLegend'; import { renderInTestApp } from '@backstage/test-utils'; describe('', () => { diff --git a/plugins/cost-insights/src/components/UnlabeledDataflowBarChartLegend/UnlabeledDataflowBarChartLegend.tsx b/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowBarChartLegend.tsx similarity index 92% rename from plugins/cost-insights/src/components/UnlabeledDataflowBarChartLegend/UnlabeledDataflowBarChartLegend.tsx rename to plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowBarChartLegend.tsx index 68caaed6d0..aac37c799d 100644 --- a/plugins/cost-insights/src/components/UnlabeledDataflowBarChartLegend/UnlabeledDataflowBarChartLegend.tsx +++ b/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowBarChartLegend.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { Box, useTheme } from '@material-ui/core'; -import LegendItem from '../LegendItem'; +import { LegendItem } from '../LegendItem'; import { currencyFormatter } from '../../utils/formatters'; import { CostInsightsTheme } from '../../types'; @@ -25,7 +25,7 @@ type UnlabeledDataflowBarChartLegendProps = { unlabeledCost: number; }; -const UnlabeledDataflowBarChartLegend = ({ +export const UnlabeledDataflowBarChartLegend = ({ unlabeledCost, labeledCost, }: UnlabeledDataflowBarChartLegendProps) => { @@ -55,5 +55,3 @@ const UnlabeledDataflowBarChartLegend = ({ ); }; - -export default UnlabeledDataflowBarChartLegend; diff --git a/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/index.ts b/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/index.ts index 6f22abc062..11f7a6b6dd 100644 --- a/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/index.ts +++ b/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './UnlabeledDataflowAlertCard'; +export { UnlabeledDataflowAlertCard } from './UnlabeledDataflowAlertCard'; diff --git a/plugins/cost-insights/src/components/UnlabeledDataflowBarChart/index.ts b/plugins/cost-insights/src/components/UnlabeledDataflowBarChart/index.ts deleted file mode 100644 index 6f475d5a80..0000000000 --- a/plugins/cost-insights/src/components/UnlabeledDataflowBarChart/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { default } from './UnlabeledDataflowBarChart'; diff --git a/plugins/cost-insights/src/components/UnlabeledDataflowBarChartLegend/index.ts b/plugins/cost-insights/src/components/UnlabeledDataflowBarChartLegend/index.ts deleted file mode 100644 index 470722e60a..0000000000 --- a/plugins/cost-insights/src/components/UnlabeledDataflowBarChartLegend/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { default } from './UnlabeledDataflowBarChartLegend'; diff --git a/plugins/cost-insights/src/components/WhyCostsMatter/WhyCostsMatter.tsx b/plugins/cost-insights/src/components/WhyCostsMatter/WhyCostsMatter.tsx index 69de854b00..18b5307d86 100644 --- a/plugins/cost-insights/src/components/WhyCostsMatter/WhyCostsMatter.tsx +++ b/plugins/cost-insights/src/components/WhyCostsMatter/WhyCostsMatter.tsx @@ -17,7 +17,7 @@ import React from 'react'; import { Typography, Box, Grid, Container, Divider } from '@material-ui/core'; -const WhyCostsMatter = () => { +export const WhyCostsMatter = () => { return ( @@ -73,5 +73,3 @@ const WhyCostsMatter = () => { ); }; - -export default WhyCostsMatter; diff --git a/plugins/cost-insights/src/components/WhyCostsMatter/index.ts b/plugins/cost-insights/src/components/WhyCostsMatter/index.ts index ed60207fde..ef847d20aa 100644 --- a/plugins/cost-insights/src/components/WhyCostsMatter/index.ts +++ b/plugins/cost-insights/src/components/WhyCostsMatter/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { default } from './WhyCostsMatter'; +export { WhyCostsMatter } from './WhyCostsMatter'; diff --git a/plugins/cost-insights/src/components/index.ts b/plugins/cost-insights/src/components/index.ts index ba04830218..d28c256a0b 100644 --- a/plugins/cost-insights/src/components/index.ts +++ b/plugins/cost-insights/src/components/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -export { default as BarChart } from './BarChart'; -export { default as CostGrowth } from './CostGrowth'; -export { default as LegendItem } from './LegendItem'; +export { BarChart } from './BarChart'; +export { CostGrowth } from './CostGrowth'; +export { LegendItem } from './LegendItem'; export * from './Tooltip'; diff --git a/plugins/cost-insights/src/plugin.ts b/plugins/cost-insights/src/plugin.ts index d8d54ae71b..7006d5bf5d 100644 --- a/plugins/cost-insights/src/plugin.ts +++ b/plugins/cost-insights/src/plugin.ts @@ -15,9 +15,9 @@ */ import { createPlugin, createRouteRef } from '@backstage/core'; -import CostInsightsPage from './components/CostInsightsPage'; -import ProjectGrowthInstructionsPage from './components/ProjectGrowthInstructionsPage'; -import LabelDataflowInstructionsPage from './components/LabelDataflowInstructionsPage'; +import { CostInsightsPage } from './components/CostInsightsPage'; +import { ProjectGrowthInstructionsPage } from './components/ProjectGrowthInstructionsPage'; +import { LabelDataflowInstructionsPage } from './components/LabelDataflowInstructionsPage'; export const rootRouteRef = createRouteRef({ path: '/cost-insights', diff --git a/plugins/cost-insights/src/types/Alert.tsx b/plugins/cost-insights/src/types/Alert.tsx index 98214bed8f..4ed55a844c 100644 --- a/plugins/cost-insights/src/types/Alert.tsx +++ b/plugins/cost-insights/src/types/Alert.tsx @@ -17,8 +17,8 @@ import React from 'react'; import { ChangeStatistic } from './ChangeStatistic'; import { Maybe } from './Maybe'; -import UnlabeledDataflowAlertCard from '../components/UnlabeledDataflowAlertCard'; -import ProjectGrowthAlertCard from '../components/ProjectGrowthAlertCard'; +import { UnlabeledDataflowAlertCard } from '../components/UnlabeledDataflowAlertCard'; +import { ProjectGrowthAlertCard } from '../components/ProjectGrowthAlertCard'; /** * Generic alert type with required fields for display. The `element` field will be rendered in From 12c1fbfeb9e5422a144486cc4d1245ce569602d5 Mon Sep 17 00:00:00 2001 From: Eric Nilsson Date: Mon, 26 Oct 2020 22:38:48 +0100 Subject: [PATCH 11/45] added validation for CRA and stage-failure fix --- .../sample-templates/create-react-app/template.yaml | 1 + .../src/scaffolder/jobs/processor.ts | 2 +- .../MultistepJsonForm/MultistepJsonForm.tsx | 12 +++++++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml b/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml index 2c8b3b3d6d..10109dee3d 100644 --- a/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml +++ b/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml @@ -22,6 +22,7 @@ spec: component_id: title: Name type: string + pattern: ^[a-z0-9]+(-[a-z0-9]+)*$ description: Unique name of the component. Lowercase, URL-safe characters only. description: title: Description diff --git a/plugins/scaffolder-backend/src/scaffolder/jobs/processor.ts b/plugins/scaffolder-backend/src/scaffolder/jobs/processor.ts index c39677232d..f1dbb24dd7 100644 --- a/plugins/scaffolder-backend/src/scaffolder/jobs/processor.ts +++ b/plugins/scaffolder-backend/src/scaffolder/jobs/processor.ts @@ -118,8 +118,8 @@ export class JobProcessor implements Processor { stage.status = 'COMPLETED'; } catch (error) { // Log to the current stage the error that occured and fail the stage. - logger.error(`Stage failed with error: ${error.message}`); stage.status = 'FAILED'; + logger.error(`Stage failed with error: ${error.message}`); // Throw the error so the job can be failed too. throw error; diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx index f0ba720b39..9e7a405731 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx @@ -25,7 +25,7 @@ import { Stepper, Typography, } from '@material-ui/core'; -import { FormProps, IChangeEvent, withTheme } from '@rjsf/core'; +import { AjvError, FormProps, IChangeEvent, withTheme } from '@rjsf/core'; import { Theme as MuiTheme } from '@rjsf/material-ui'; import React, { useState } from 'react'; @@ -63,6 +63,15 @@ export const MultistepJsonForm = ({ setActiveStep(Math.min(activeStep + 1, steps.length)); const handleBack = () => setActiveStep(Math.max(activeStep - 1, 0)); + const transformErrors = (errors: AjvError[]) => + errors.map(error => { + if (error.name === 'pattern') { + error.message = 'does not match the required pattern'; + error.stack = `${error.property} ${error.message}, see its description`; + } + return error; + }); + return ( <> @@ -75,6 +84,7 @@ export const MultistepJsonForm = ({ formData={formData} onChange={onChange} schema={schema as FormProps['schema']} + transformErrors={transformErrors} onSubmit={e => { if (e.errors.length === 0) handleNext(); }} From ff0dc1be98984e642b49b4255764c25c09f1cd0d Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Mon, 26 Oct 2020 17:46:18 -0400 Subject: [PATCH 12/45] export root as page --- plugins/cost-insights/src/components/CostInsightsPage/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/cost-insights/src/components/CostInsightsPage/index.ts b/plugins/cost-insights/src/components/CostInsightsPage/index.ts index 07d7b76233..bf34a7dbe7 100644 --- a/plugins/cost-insights/src/components/CostInsightsPage/index.ts +++ b/plugins/cost-insights/src/components/CostInsightsPage/index.ts @@ -14,5 +14,4 @@ * limitations under the License. */ -export { CostInsightsPage } from './CostInsightsPage'; -export { CostInsightsPageRoot } from './CostInsightsPageRoot'; +export { CostInsightsPageRoot as CostInsightsPage } from './CostInsightsPageRoot'; From 157063409b24d9fa44c78ee66ce9e35236e3f76a Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Mon, 26 Oct 2020 17:58:42 -0400 Subject: [PATCH 13/45] use wildcard form for re-exports --- plugins/cost-insights/src/components/BarChart/index.ts | 1 + plugins/cost-insights/src/components/CostGrowth/index.ts | 1 + .../cost-insights/src/components/LegendItem/LegendItem.tsx | 2 +- plugins/cost-insights/src/components/index.ts | 6 +++--- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/cost-insights/src/components/BarChart/index.ts b/plugins/cost-insights/src/components/BarChart/index.ts index b2c6390388..4525bd24f3 100644 --- a/plugins/cost-insights/src/components/BarChart/index.ts +++ b/plugins/cost-insights/src/components/BarChart/index.ts @@ -15,3 +15,4 @@ */ export { BarChart } from './BarChart'; +export type { BarChartProps } from './BarChart'; diff --git a/plugins/cost-insights/src/components/CostGrowth/index.ts b/plugins/cost-insights/src/components/CostGrowth/index.ts index d4b1396586..da17ae8709 100644 --- a/plugins/cost-insights/src/components/CostGrowth/index.ts +++ b/plugins/cost-insights/src/components/CostGrowth/index.ts @@ -15,3 +15,4 @@ */ export { CostGrowth } from './CostGrowth'; +export type { CostGrowthProps } from './CostGrowth'; diff --git a/plugins/cost-insights/src/components/LegendItem/LegendItem.tsx b/plugins/cost-insights/src/components/LegendItem/LegendItem.tsx index cabc5f9c59..9424c50bf7 100644 --- a/plugins/cost-insights/src/components/LegendItem/LegendItem.tsx +++ b/plugins/cost-insights/src/components/LegendItem/LegendItem.tsx @@ -20,7 +20,7 @@ import LensIcon from '@material-ui/icons/Lens'; import HelpOutlineOutlinedIcon from '@material-ui/icons/HelpOutlineOutlined'; import { useCostGrowthLegendStyles } from '../../utils/styles'; -type LegendItemProps = { +export type LegendItemProps = { title: string; tooltipText?: string; markerColor?: string; diff --git a/plugins/cost-insights/src/components/index.ts b/plugins/cost-insights/src/components/index.ts index d28c256a0b..5b918144d9 100644 --- a/plugins/cost-insights/src/components/index.ts +++ b/plugins/cost-insights/src/components/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -export { BarChart } from './BarChart'; -export { CostGrowth } from './CostGrowth'; -export { LegendItem } from './LegendItem'; +export * from './BarChart'; +export * from './CostGrowth'; +export * from './LegendItem'; export * from './Tooltip'; From 023d514206b00c163746b321c1d019db0ffda707 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Mon, 26 Oct 2020 18:04:11 -0400 Subject: [PATCH 14/45] changeset --- .changeset/swift-carrots-bake.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/swift-carrots-bake.md diff --git a/.changeset/swift-carrots-bake.md b/.changeset/swift-carrots-bake.md new file mode 100644 index 0000000000..bc378ad247 --- /dev/null +++ b/.changeset/swift-carrots-bake.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-cost-insights': patch +--- + +prefer named exports From 60693368306d182536cf17e1d16d3364b8df3cb4 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Mon, 26 Oct 2020 18:10:47 -0400 Subject: [PATCH 15/45] formatting --- .../AlertInsights/AlertInsightsHeader.tsx | 5 ++- .../AlertInsights/AlertInsightsSection.tsx | 5 ++- .../src/components/BarChart/BarChartSteps.tsx | 11 +++-- .../components/CostGrowth/CostGrowth.test.tsx | 8 ++-- .../components/CostInsightsHeader/index.ts | 5 ++- .../CostInsightsNavigation.tsx | 12 +++--- .../CostOverviewCard/CostOverviewHeader.tsx | 40 +++++++++---------- .../components/MetricSelect/MetricSelect.tsx | 6 ++- .../components/PeriodSelect/PeriodSelect.tsx | 6 ++- .../ProductInsights/ProductInsights.tsx | 2 +- .../ProjectGrowthAlertCard.tsx | 5 ++- .../ProjectSelect/ProjectSelect.tsx | 6 ++- .../UnlabeledDataflowAlertCard.test.tsx | 2 +- .../UnlabeledDataflowAlertCard.tsx | 4 +- 14 files changed, 74 insertions(+), 43 deletions(-) diff --git a/plugins/cost-insights/src/components/AlertInsights/AlertInsightsHeader.tsx b/plugins/cost-insights/src/components/AlertInsights/AlertInsightsHeader.tsx index 7a65010abf..b58f6973ae 100644 --- a/plugins/cost-insights/src/components/AlertInsights/AlertInsightsHeader.tsx +++ b/plugins/cost-insights/src/components/AlertInsights/AlertInsightsHeader.tsx @@ -25,7 +25,10 @@ type AlertInsightsHeaderProps = { subtitle: string; }; -export const AlertInsightsHeader = ({ title, subtitle }: AlertInsightsHeaderProps) => { +export const AlertInsightsHeader = ({ + title, + subtitle, +}: AlertInsightsHeaderProps) => { const classes = useStyles(); const { ScrollAnchor } = useScroll(DefaultNavigation.AlertInsightsHeader); return ( diff --git a/plugins/cost-insights/src/components/AlertInsights/AlertInsightsSection.tsx b/plugins/cost-insights/src/components/AlertInsights/AlertInsightsSection.tsx index fe5425a937..426e943092 100644 --- a/plugins/cost-insights/src/components/AlertInsights/AlertInsightsSection.tsx +++ b/plugins/cost-insights/src/components/AlertInsights/AlertInsightsSection.tsx @@ -23,7 +23,10 @@ type AlertInsightsSectionProps = { number: number; }; -export const AlertInsightsSection = ({ alert, number }: AlertInsightsSectionProps) => { +export const AlertInsightsSection = ({ + alert, + number, +}: AlertInsightsSectionProps) => { return ( void; }; -export const BarChartSteps = ({ steps, activeStep, onClick }: BarChartSteps) => { +export const BarChartSteps = ({ + steps, + activeStep, + onClick, +}: BarChartSteps) => { const classes = useStyles(); const handleOnClick = (index: number) => ( event: React.MouseEvent, @@ -39,8 +43,9 @@ export const BarChartSteps = ({ steps, activeStep, onClick }: BarChartSteps) =>
))} diff --git a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx index 3a49ba4626..ed81f657c5 100644 --- a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx +++ b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx @@ -41,10 +41,10 @@ const MockContext = ({ currency: Currency; engineerCost: number; }>) => ( - - {children} - - ); + + {children} + +); describe.each` engineerCost | ratio | amount | expected diff --git a/plugins/cost-insights/src/components/CostInsightsHeader/index.ts b/plugins/cost-insights/src/components/CostInsightsHeader/index.ts index f5099aa19d..f6eebef604 100644 --- a/plugins/cost-insights/src/components/CostInsightsHeader/index.ts +++ b/plugins/cost-insights/src/components/CostInsightsHeader/index.ts @@ -14,4 +14,7 @@ * limitations under the License. */ -export { CostInsightsHeader, CostInsightsHeaderNoGroups } from './CostInsightsHeader'; +export { + CostInsightsHeader, + CostInsightsHeaderNoGroups, +} from './CostInsightsHeader'; diff --git a/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx b/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx index 62482c3323..f190fa88bb 100644 --- a/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx +++ b/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx @@ -36,7 +36,9 @@ type CostInsightsNavigationProps = { alerts: number; }; -export const CostInsightsNavigation = ({ alerts }: CostInsightsNavigationProps) => { +export const CostInsightsNavigation = ({ + alerts, +}: CostInsightsNavigationProps) => { const classes = useNavigationStyles(); const { products, icons } = useConfig(); @@ -64,10 +66,10 @@ export const CostInsightsNavigation = ({ alerts }: CostInsightsNavigationProps) })} ) : ( - React.cloneElement(item.icon, { - className: classes.navigationIcon, - }) - ) + React.cloneElement(item.icon, { + className: classes.navigationIcon, + }) + ) } title={item.title} /> diff --git a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewHeader.tsx b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewHeader.tsx index c01eabfa53..e46b0c3a78 100644 --- a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewHeader.tsx +++ b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewHeader.tsx @@ -26,25 +26,25 @@ export const CostOverviewHeader = ({ subtitle, children, }: PropsWithChildren) => ( - - - - {title} + + + + {title} + + {!!subtitle && ( + + {subtitle} - {!!subtitle && ( - - {subtitle} - - )} - - - {children} - + )} - ); + + {children} + + +); diff --git a/plugins/cost-insights/src/components/MetricSelect/MetricSelect.tsx b/plugins/cost-insights/src/components/MetricSelect/MetricSelect.tsx index f91070271f..a8197fd7e9 100644 --- a/plugins/cost-insights/src/components/MetricSelect/MetricSelect.tsx +++ b/plugins/cost-insights/src/components/MetricSelect/MetricSelect.tsx @@ -25,7 +25,11 @@ export type MetricSelectProps = { onSelect: (metric: Maybe) => void; }; -export const MetricSelect = ({ metric, metrics, onSelect }: MetricSelectProps) => { +export const MetricSelect = ({ + metric, + metrics, + onSelect, +}: MetricSelectProps) => { const classes = useStyles(); function onChange(e: React.ChangeEvent<{ value: unknown }>) { diff --git a/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx b/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx index 0088830471..07365c32eb 100644 --- a/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx +++ b/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx @@ -58,7 +58,11 @@ type PeriodSelectProps = { options?: PeriodOption[]; }; -export const PeriodSelect = ({ duration, onSelect, options }: PeriodSelectProps) => { +export const PeriodSelect = ({ + duration, + onSelect, + options, +}: PeriodSelectProps) => { const classes = useStyles(); const lastCompleteBillingDate = useLastCompleteBillingDate(); const optionsOrDefault = diff --git a/plugins/cost-insights/src/components/ProductInsights/ProductInsights.tsx b/plugins/cost-insights/src/components/ProductInsights/ProductInsights.tsx index 7420c8d82c..16146cb045 100644 --- a/plugins/cost-insights/src/components/ProductInsights/ProductInsights.tsx +++ b/plugins/cost-insights/src/components/ProductInsights/ProductInsights.tsx @@ -19,7 +19,7 @@ import { Box, Typography, Grid } from '@material-ui/core'; import { ProductInsightsCard } from '../ProductInsightsCard'; import { useConfig } from '../../hooks'; -export const ProductInsights = ({ }) => { +export const ProductInsights = ({}) => { const config = useConfig(); return ( <> diff --git a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx index 18f7fa151d..4311bcc1bf 100644 --- a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx +++ b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx @@ -31,8 +31,9 @@ export const ProjectGrowthAlertCard = ({ alert }: ProjectGrowthAlertProps) => { const [costStart, costEnd] = alert.aggregation; const subheader = ` - ${alert.products.length} ${pluralOf(alert.products.length, 'product')}${alert.products.length > 1 ? ', sorted by cost' : '' - }`; + ${alert.products.length} ${pluralOf(alert.products.length, 'product')}${ + alert.products.length > 1 ? ', sorted by cost' : '' + }`; const previousName = moment(alert.periodStart, 'YYYY-[Q]Q').format( '[Q]Q YYYY', ); diff --git a/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.tsx b/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.tsx index 29169d1f5f..ee4641a4eb 100644 --- a/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.tsx +++ b/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.tsx @@ -24,7 +24,11 @@ type ProjectSelectProps = { onSelect: (project: Maybe) => void; }; -export const ProjectSelect = ({ project, projects, onSelect }: ProjectSelectProps) => { +export const ProjectSelect = ({ + project, + projects, + onSelect, +}: ProjectSelectProps) => { const classes = useStyles(); const projectOptions = [{ id: 'all' } as Project, ...projects] diff --git a/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.test.tsx b/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.test.tsx index 6edd4ed637..df38c78a03 100644 --- a/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.test.tsx +++ b/plugins/cost-insights/src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.test.tsx @@ -44,7 +44,7 @@ describe('', () => { it('renders the correct subheader for multiple projects', async () => { const subheader = new RegExp( `Showing costs from ${MockUnlabeledDataflowAlertMultipleProjects.projects.length} ` + - 'projects with unlabeled Dataflow jobs in the last 30 days.', + 'projects with unlabeled Dataflow jobs in the last 30 days.', ); const rendered = await renderInTestApp( { +export const UnlabeledDataflowAlertCard = ({ + alert, +}: UnlabeledDataflowAlertProps) => { const projects = pluralOf(alert.projects.length, 'project'); const subheader = ` Showing costs from ${alert.projects.length} ${projects} with unlabeled Dataflow jobs in the last 30 days. From 75763dadd97f74860c0b5d823ea4f4b940e0f540 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 26 Oct 2020 19:31:42 +0100 Subject: [PATCH 16/45] scaffolder-backend: add Preparers.fromConfig + integration type detection --- packages/backend/src/plugins/scaffolder.ts | 18 +----- .../src/scaffolder/stages/helpers.test.ts | 31 ++++++++- .../src/scaffolder/stages/helpers.ts | 37 +++++++++++ .../src/scaffolder/stages/prepare/azure.ts | 4 +- .../src/scaffolder/stages/prepare/github.ts | 4 +- .../src/scaffolder/stages/prepare/gitlab.ts | 4 +- .../scaffolder/stages/prepare/preparers.ts | 63 ++++++++++++++++++- 7 files changed, 135 insertions(+), 26 deletions(-) diff --git a/packages/backend/src/plugins/scaffolder.ts b/packages/backend/src/plugins/scaffolder.ts index 24bd4e942f..ef00198430 100644 --- a/packages/backend/src/plugins/scaffolder.ts +++ b/packages/backend/src/plugins/scaffolder.ts @@ -17,10 +17,6 @@ import { CookieCutter, createRouter, - FilePreparer, - GithubPreparer, - GitlabPreparer, - AzurePreparer, Preparers, Publishers, GithubPublisher, @@ -46,16 +42,7 @@ export default async function createPlugin({ templaters.register('cookiecutter', cookiecutterTemplater); templaters.register('cra', craTemplater); - const filePreparer = new FilePreparer(); - - const gitlabPreparer = new GitlabPreparer(config); - const azurePreparer = new AzurePreparer(config); - const preparers = new Preparers(); - - preparers.register('file', filePreparer); - preparers.register('gitlab', gitlabPreparer); - preparers.register('gitlab/api', gitlabPreparer); - preparers.register('azure/api', azurePreparer); + const preparers = await Preparers.fromConfig(config, { logger }); const publishers = new Publishers(); @@ -80,9 +67,6 @@ export default async function createPlugin({ repoVisibility, }); - const githubPreparer = new GithubPreparer({ token: githubToken }); - - preparers.register('github', githubPreparer); publishers.register('file', githubPublisher); publishers.register('github', githubPublisher); } catch (e) { diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/helpers.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/helpers.test.ts index 8b174a1edf..09bd6b7885 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/helpers.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/helpers.test.ts @@ -13,11 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { parseLocationAnnotation } from './helpers'; +import { + makeDeprecatedLocationTypeDetector, + parseLocationAnnotation, +} from './helpers'; import { TemplateEntityV1alpha1, LOCATION_ANNOTATION, } from '@backstage/catalog-model'; +import { ConfigReader } from '@backstage/config'; describe('Helpers', () => { describe('parseLocationAnnotation', () => { @@ -253,4 +257,29 @@ describe('Helpers', () => { }); }); }); + + describe('makeDeprecatedLocationTypeDetector', () => { + it('detects deprecated location types', () => { + const detector = makeDeprecatedLocationTypeDetector( + new ConfigReader({ + integrations: { + github: [{ host: 'derp.com' }, { host: 'foo.com' }], + gitlab: [{ host: 'derp.org' }, { host: 'foo.org' }], + azure: [{ host: 'derp.net' }, { host: 'foo.net' }], + }, + }), + ); + + expect(detector('http://lol:wut@derp.com/wat')).toBe('github'); + expect(detector('https://foo.com/wat')).toBe('github'); + expect(detector('http://derp.org:80/wat')).toBe('gitlab'); + expect(detector('https://foo.org/wat')).toBe('gitlab'); + expect(detector('http://not.derp.net')).toBe(undefined); + expect(detector('http://derp.net')).toBe('azure/api'); + expect(detector('http://derp.net:8080/wat')).toBe('azure/api'); + expect(detector('http://github.com')).toBe('github'); + expect(detector('http://gitlab.com')).toBe('gitlab'); + expect(detector('http://dev.azure.com')).toBe('azure/api'); + }); + }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/helpers.ts index 3f31f19d59..e54e796b3b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/helpers.ts @@ -17,6 +17,7 @@ import { TemplateEntityV1alpha1, LOCATION_ANNOTATION, } from '@backstage/catalog-model'; +import { Config } from '@backstage/config'; import { InputError } from '@backstage/backend-common'; import { RemoteProtocol } from './types'; @@ -54,3 +55,39 @@ export const parseLocationAnnotation = ( location, }; }; + +export type DeprecatedLocationTypeDetector = ( + url: string, +) => string | undefined; + +// The reason for the existence of this is to help in migration to using mostly locations +// of type 'url'. This allows us to detect the deprecated location type based on the host, +// which we in turn can use to select out preparer or publisher. +// +// TODO(Rugvip): This should be removed in the future once we fully migrate to using +// integrations configuration for the scaffolder. +export function makeDeprecatedLocationTypeDetector( + config: Config, +): DeprecatedLocationTypeDetector { + const hostMap = new Map(); + + // These are installed by default by the integrations + hostMap.set('github.com', 'github'); + hostMap.set('gitlab.com', 'gitlab'); + hostMap.set('dev.azure.com', 'azure/api'); + + config.getOptionalConfigArray('integrations.github')?.forEach(sub => { + hostMap.set(sub.getString('host'), 'github'); + }); + config.getOptionalConfigArray('integrations.gitlab')?.forEach(sub => { + hostMap.set(sub.getString('host'), 'gitlab'); + }); + config.getOptionalConfigArray('integrations.azure')?.forEach(sub => { + hostMap.set(sub.getString('host'), 'azure/api'); + }); + + return (url: string): string | undefined => { + const parsed = new URL(url); + return hostMap.get(parsed.hostname); + }; +} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts index c2cb97e505..dc74ec0f75 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts @@ -35,9 +35,9 @@ export class AzurePreparer implements PreparerBase { async prepare(template: TemplateEntityV1alpha1): Promise { const { protocol, location } = parseLocationAnnotation(template); - if (protocol !== 'azure/api') { + if (!['azure/api', 'url'].includes(protocol)) { throw new InputError( - `Wrong location protocol: ${protocol}, should be 'azure/api'`, + `Wrong location protocol: ${protocol}, should be 'url'`, ); } const templateId = template.metadata.name; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts index 6eee00f9cb..0f064d22fa 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts @@ -34,9 +34,9 @@ export class GithubPreparer implements PreparerBase { const { protocol, location } = parseLocationAnnotation(template); const { token } = this; - if (protocol !== 'github') { + if (!['github', 'url'].includes(protocol)) { throw new InputError( - `Wrong location protocol: ${protocol}, should be 'github'`, + `Wrong location protocol: ${protocol}, should be 'url'`, ); } const templateId = template.metadata.name; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts index 8efc158a96..8ccde0b626 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts @@ -36,9 +36,9 @@ export class GitlabPreparer implements PreparerBase { async prepare(template: TemplateEntityV1alpha1): Promise { const { protocol, location } = parseLocationAnnotation(template); - if (['gitlab', 'gitlab/api'].indexOf(protocol) < 0) { + if (!['gitlab', 'gitlab/api', 'url'].includes(protocol)) { throw new InputError( - `Wrong location protocol: ${protocol}, should be 'gitlab' or 'gitlab/api'`, + `Wrong location protocol: ${protocol}, should be 'url'`, ); } const templateId = template.metadata.name; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.ts index 5efb3ad60d..59537e73f4 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.ts @@ -14,26 +14,85 @@ * limitations under the License. */ +import { Config } from '@backstage/config'; +import { Logger } from 'winston'; import { PreparerBase, PreparerBuilder } from './types'; import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; -import { parseLocationAnnotation } from '../helpers'; +import { + DeprecatedLocationTypeDetector, + makeDeprecatedLocationTypeDetector, + parseLocationAnnotation, +} from '../helpers'; import { RemoteProtocol } from '../types'; +import { FilePreparer } from './file'; +import { GitlabPreparer } from './gitlab'; +import { AzurePreparer } from './azure'; +import { GithubPreparer } from './github'; export class Preparers implements PreparerBuilder { private preparerMap = new Map(); + constructor(private readonly typeDetector?: DeprecatedLocationTypeDetector) {} + register(protocol: RemoteProtocol, preparer: PreparerBase) { this.preparerMap.set(protocol, preparer); } get(template: TemplateEntityV1alpha1): PreparerBase { - const { protocol } = parseLocationAnnotation(template); + const { protocol, location } = parseLocationAnnotation(template); + const preparer = this.preparerMap.get(protocol); if (!preparer) { + if ((protocol as string) === 'url') { + const type = this.typeDetector?.(location); + const preparer2 = type && this.preparerMap.get(type as RemoteProtocol); + if (preparer2) { + return preparer2; + } + throw new Error(`No preparer integration found for url "${location}"`); + } throw new Error(`No preparer registered for type: "${protocol}"`); } return preparer; } + + static async fromConfig( + config: Config, + { logger }: { logger: Logger }, + ): Promise { + const typeDetector = makeDeprecatedLocationTypeDetector(config); + + const preparers = new Preparers(typeDetector); + + const filePreparer = new FilePreparer(); + const gitlabPreparer = new GitlabPreparer(config); + const azurePreparer = new AzurePreparer(config); + + preparers.register('file', filePreparer); + preparers.register('gitlab', gitlabPreparer); + preparers.register('gitlab/api', gitlabPreparer); + preparers.register('azure/api', azurePreparer); + + const githubConfig = config.getOptionalConfig('scaffolder.github'); + if (githubConfig) { + try { + const githubToken = githubConfig.getString('token'); + const githubPreparer = new GithubPreparer({ token: githubToken }); + + preparers.register('github', githubPreparer); + } catch (e) { + if (process.env.NODE_ENV !== 'development') { + throw new Error( + `Failed to initialize github scaffolding provider, ${e.message}`, + ); + } + + logger.warn(`Skipping github scaffolding provider, ${e.message}`); + } + } + + return preparers; + } } From f8064794ccb4b8dae7ec91895576de001aa17d03 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 26 Oct 2020 23:28:09 +0100 Subject: [PATCH 17/45] scaffolder-backend: add Publishers.fromConfig --- packages/backend/src/plugins/scaffolder.ts | 99 +------------- .../scaffolder/stages/publish/publishers.ts | 124 +++++++++++++++++- 2 files changed, 124 insertions(+), 99 deletions(-) diff --git a/packages/backend/src/plugins/scaffolder.ts b/packages/backend/src/plugins/scaffolder.ts index ef00198430..c84928ea68 100644 --- a/packages/backend/src/plugins/scaffolder.ts +++ b/packages/backend/src/plugins/scaffolder.ts @@ -19,16 +19,9 @@ import { createRouter, Preparers, Publishers, - GithubPublisher, - GitlabPublisher, - AzurePublisher, CreateReactAppTemplater, Templaters, - RepoVisibilityOptions, } from '@backstage/plugin-scaffolder-backend'; -import { Octokit } from '@octokit/rest'; -import { Gitlab } from '@gitbeaker/node'; -import { getPersonalAccessTokenHandler, WebApi } from 'azure-devops-node-api'; import type { PluginEnvironment } from '../types'; import Docker from 'dockerode'; @@ -43,98 +36,10 @@ export default async function createPlugin({ templaters.register('cra', craTemplater); const preparers = await Preparers.fromConfig(config, { logger }); - - 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') ?? 'https://github.com'; - 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 azureConfig = config.getOptionalConfig('scaffolder.azure'); - if (azureConfig) { - try { - const baseUrl = azureConfig.getString('baseUrl'); - const azureToken = azureConfig.getConfig('api').getString('token'); - - const authHandler = getPersonalAccessTokenHandler(azureToken); - const webApi = new WebApi(baseUrl, authHandler); - const azureClient = await webApi.getGitApi(); - - const azurePublisher = new AzurePublisher(azureClient, azureToken); - publishers.register('azure/api', azurePublisher); - } catch (e) { - const providerName = 'azure'; - 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 publishers = await Publishers.fromConfig(config, { logger }); const dockerClient = new Docker(); + return await createRouter({ preparers, templaters, diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts index a88acc518d..80203e3b54 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts @@ -14,26 +14,146 @@ * limitations under the License. */ +import { Logger } from 'winston'; +import { Octokit } from '@octokit/rest'; +import { Gitlab } from '@gitbeaker/node'; +import { getPersonalAccessTokenHandler, WebApi } from 'azure-devops-node-api'; +import { Config } from '@backstage/config'; import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; -import { parseLocationAnnotation } from '../helpers'; +import { + DeprecatedLocationTypeDetector, + makeDeprecatedLocationTypeDetector, + parseLocationAnnotation, +} from '../helpers'; import { PublisherBase, PublisherBuilder } from './types'; import { RemoteProtocol } from '../types'; +import { GithubPublisher, RepoVisibilityOptions } from './github'; +import { GitlabPublisher } from './gitlab'; +import { AzurePublisher } from './azure'; export class Publishers implements PublisherBuilder { private publisherMap = new Map(); + constructor(private readonly typeDetector?: DeprecatedLocationTypeDetector) {} + register(protocol: RemoteProtocol, publisher: PublisherBase) { this.publisherMap.set(protocol, publisher); } get(template: TemplateEntityV1alpha1): PublisherBase { - const { protocol } = parseLocationAnnotation(template); + const { protocol, location } = parseLocationAnnotation(template); const publisher = this.publisherMap.get(protocol); if (!publisher) { + if ((protocol as string) === 'url') { + const type = this.typeDetector?.(location); + const publisher2 = + type && this.publisherMap.get(type as RemoteProtocol); + if (publisher2) { + return publisher2; + } + throw new Error(`No preparer integration found for url "${location}"`); + } throw new Error(`No publisher registered for type: "${protocol}"`); } return publisher; } + + static async fromConfig( + config: Config, + { logger }: { logger: Logger }, + ): Promise { + const typeDetector = makeDeprecatedLocationTypeDetector(config); + const publishers = new Publishers(typeDetector); + + 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') ?? 'https://github.com'; + 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 azureConfig = config.getOptionalConfig('scaffolder.azure'); + if (azureConfig) { + try { + const baseUrl = azureConfig.getString('baseUrl'); + const azureToken = azureConfig.getConfig('api').getString('token'); + + const authHandler = getPersonalAccessTokenHandler(azureToken); + const webApi = new WebApi(baseUrl, authHandler); + const azureClient = await webApi.getGitApi(); + + const azurePublisher = new AzurePublisher(azureClient, azureToken); + publishers.register('azure/api', azurePublisher); + } catch (e) { + const providerName = 'azure'; + 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}`, + ); + } + } + + return publishers; + } } From c633158fdad87e8d0608e7967b672c4cc7c38db3 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 26 Oct 2020 23:28:29 +0100 Subject: [PATCH 18/45] scaffolder-backend: default github api url to api.github.com --- app-config.yaml | 1 - .../src/scaffolder/stages/publish/publishers.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app-config.yaml b/app-config.yaml index 05bf39b5b3..6e3a68a229 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -156,7 +156,6 @@ catalog: scaffolder: github: - host: https://github.com token: $env: GITHUB_TOKEN visibility: public # or 'internal' or 'private' diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts index 80203e3b54..23f15745ba 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts @@ -76,7 +76,7 @@ export class Publishers implements PublisherBuilder { const githubToken = githubConfig.getString('token'); const githubHost = - githubConfig.getOptionalString('host') ?? 'https://github.com'; + githubConfig.getOptionalString('host') ?? 'https://api.github.com'; const githubClient = new Octokit({ auth: githubToken, baseUrl: githubHost, From 991a950e047e7523e3aeb1ecd62a98a01cc7515e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 26 Oct 2020 23:33:03 +0100 Subject: [PATCH 19/45] changesets: added changeset for scaffolder-backend updates --- .changeset/chilly-emus-fetch.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/chilly-emus-fetch.md diff --git a/.changeset/chilly-emus-fetch.md b/.changeset/chilly-emus-fetch.md new file mode 100644 index 0000000000..ad77c90f4e --- /dev/null +++ b/.changeset/chilly-emus-fetch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Added .fromConfig static factories for Preparers and Publishers + read integrations config to support url location types From 7c28026ae02d90fb7398aa726a22f72fcf871a78 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 26 Oct 2020 23:34:25 +0100 Subject: [PATCH 20/45] docs: update scaffolder-backend installation docs --- .../software-templates/installation.md | 40 +------------------ 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/docs/features/software-templates/installation.md b/docs/features/software-templates/installation.md index 842c59e289..bac5f60789 100644 --- a/docs/features/software-templates/installation.md +++ b/docs/features/software-templates/installation.md @@ -111,44 +111,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 githubToken = config.getString('scaffolder.github.token'); - const repoVisibility = config.getString( - 'scaffolder.github.visibility', - ) as RepoVisibilityOptions; - - const githubClient = new Octokit({ auth: githubToken }); - const githubPublisher = new GithubPublisher({ - client: githubClient, - token: githubToken, - repoVisibility, - }); - publishers.register('file', githubPublisher); - publishers.register('github', githubPublisher); - - const gitLabConfig = config.getOptionalConfig('scaffolder.gitlab.api'); - - if (gitLabConfig) { - 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); - } + const preparers = await Preparers.fromConfig(config, { logger }); + const publishers = await Publishers.fromConfig(config, { logger }); const dockerClient = new Docker(); return await createRouter({ From 99133b930121a800affd8aa4b50e0391013adae8 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 27 Oct 2020 01:17:33 +0100 Subject: [PATCH 21/45] chore(proxy): added some contrib doxs for corporate proxy config --- .../help-im-behind-a-corporate-proxy.md | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 contrib/docs/tutorials/help-im-behind-a-corporate-proxy.md diff --git a/contrib/docs/tutorials/help-im-behind-a-corporate-proxy.md b/contrib/docs/tutorials/help-im-behind-a-corporate-proxy.md new file mode 100644 index 0000000000..75b1b6ff7f --- /dev/null +++ b/contrib/docs/tutorials/help-im-behind-a-corporate-proxy.md @@ -0,0 +1,51 @@ +# Running the backend behind a Corporate Proxy + +Let's admit it, we've all been there. Sometimes you've gotta run stuff with no way out to the public internet, only the smallest of corporate proxy tunnels. + +Whilst this isn't supported natively by Backstage, this might help you get your installation up and running making calls through the said proxy tunnel. + +Unfortunately, `nodejs` does not respect `HTTP(S)_PROXY` environment variables by default, and the library that we use to provide `fetch` functionality `node-fetch` (provided by `cross-fetch`) does not also respect these environment variables. + +There are however some ways to get this to work without too much effort. It's most likely that you're going to run into these issues from the `backend` part of `backstage` as that's the part that isn't helped by your browser or OS's settings for the corporate proxy. + +**Note:** You're gonna want to be in your backend working directory for these solutions as that's where the requests come from that don't go through this proxy. + +### Using `global-agent` + +1. Install `global-agent` using `yarn install global-agent` +2. Go to the entry file for the backend (`src/index.ts`) +3. At the top of the file paste the following: + +```ts +import 'global-agent/bootstrap'; +``` + +4. Start the backend with the `global-agent` variables + +```sh +export GLOBAL_AGENT_HTTP_PROXY=$HTTP_PROXY +yarn start +``` + +More information and more options for configuring `global-agent` including just using the default environment variables can be found here: https://github.com/gajus/global-agent + +### Using `proxy-agent` + +`proxy-agent` is a library that you can use to override the `globalAgents` of `node` land with a tunnel to use for each request. + +1. Install `global-agent` using `yarn install proxy-agent` +2. Go to the entry file for the backend (`src/index.ts`) +3. At the top of the file paste the following: + +```ts +import ProxyAgent from 'proxy-agent'; +import http from 'http'; +import https from 'https'; + +if (process.env.HTTP_PROXY) { + http.globalAgent = new ProxyAgent(process.env.HTTP_PROXY); + https.globalAgent = new ProxyAgent(process.env.HTTP_PROXY); +} +``` + +4. Start the backend with `yarn start` From 4727dc98f9d11e3a7fd6901af1007cec89b9aa74 Mon Sep 17 00:00:00 2001 From: Fabian Chong Date: Tue, 27 Oct 2020 12:05:08 +0800 Subject: [PATCH 22/45] adding tsconfig.json to default-backend-plugin --- .../templates/default-backend-plugin/tsconfig.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 packages/cli/templates/default-backend-plugin/tsconfig.json diff --git a/packages/cli/templates/default-backend-plugin/tsconfig.json b/packages/cli/templates/default-backend-plugin/tsconfig.json new file mode 100644 index 0000000000..d77f0fe3b4 --- /dev/null +++ b/packages/cli/templates/default-backend-plugin/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@backstage/cli/config/tsconfig.json", + "include": [ + "src", + "dev", + "migrations" + ], + "exclude": ["node_modules"], + "compilerOptions": { + "outDir": "dist-types", + "rootDir": "." + } +} From 51394c24bd0727f1eea00ed70ae83f508c2a2a6c Mon Sep 17 00:00:00 2001 From: Fabian Chong Date: Tue, 27 Oct 2020 12:06:30 +0800 Subject: [PATCH 23/45] removing migration from frontend plugin --- packages/cli/templates/default-plugin/tsconfig.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/cli/templates/default-plugin/tsconfig.json b/packages/cli/templates/default-plugin/tsconfig.json index d77f0fe3b4..b61e496175 100644 --- a/packages/cli/templates/default-plugin/tsconfig.json +++ b/packages/cli/templates/default-plugin/tsconfig.json @@ -2,8 +2,7 @@ "extends": "@backstage/cli/config/tsconfig.json", "include": [ "src", - "dev", - "migrations" + "dev" ], "exclude": ["node_modules"], "compilerOptions": { From 2a662cda68ad62142d214e1d303459f1a84779c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Oct 2020 04:25:17 +0000 Subject: [PATCH 24/45] chore(deps-dev): bump @spotify/prettier-config in /microsite Bumps [@spotify/prettier-config](https://github.com/spotify/web-scripts) from 8.0.0 to 9.0.0. - [Release notes](https://github.com/spotify/web-scripts/releases) - [Changelog](https://github.com/spotify/web-scripts/blob/master/CHANGELOG.md) - [Commits](https://github.com/spotify/web-scripts/compare/v8.0.0...v9.0.0) Signed-off-by: dependabot[bot] --- microsite/package.json | 2 +- microsite/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/microsite/package.json b/microsite/package.json index ecf7752b05..a84364c214 100644 --- a/microsite/package.json +++ b/microsite/package.json @@ -14,7 +14,7 @@ "rename-version": "docusaurus-rename-version" }, "devDependencies": { - "@spotify/prettier-config": "^8.0.0", + "@spotify/prettier-config": "^9.0.0", "docusaurus": "^2.0.0-alpha.66", "js-yaml": "^3.14.0", "prettier": "^2.0.5" diff --git a/microsite/yarn.lock b/microsite/yarn.lock index 6707532f9c..b120cb2d47 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -959,10 +959,10 @@ resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== -"@spotify/prettier-config@^8.0.0": - version "8.0.0" - resolved "https://registry.npmjs.org/@spotify/prettier-config/-/prettier-config-8.0.0.tgz#8b6c2bd579ddc54887155a0721fe04e96c89f7f2" - integrity sha512-so8w32ZV42CHWxOEXcBtbNO/hLXFrQNXVmhfzhUI6dVB9cq2xjRaiqu8GjFj8LvKbWpPj+S+KwTIS4aDVWqrFQ== +"@spotify/prettier-config@^9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@spotify/prettier-config/-/prettier-config-9.0.0.tgz#7b562d56573c6fc0094446fbc92b22bc318945dc" + integrity sha512-In1q0tIiqTYKAGe3KOHDcFDdZRFISyQeSeipeTHGfki23ebHRZcjxvqj5SSdBkw65D4VpSREMi0s9i5iJiMcTw== "@types/cheerio@^0.22.8": version "0.22.21" From b863687d7f763c88350832dd6bb25aa1f5ff775a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Oct 2020 04:39:49 +0000 Subject: [PATCH 25/45] chore(deps): bump @rollup/plugin-commonjs from 13.0.0 to 16.0.0 Bumps [@rollup/plugin-commonjs](https://github.com/rollup/plugins) from 13.0.0 to 16.0.0. - [Release notes](https://github.com/rollup/plugins/releases) - [Commits](https://github.com/rollup/plugins/compare/commonjs-v13.0.0...commonjs-v16.0.0) Signed-off-by: dependabot[bot] --- packages/cli/package.json | 2 +- yarn.lock | 39 ++++++++++++++++++++++----------------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index d6e73b41fa..3024c2eeaf 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -34,7 +34,7 @@ "@hot-loader/react-dom": "^16.13.0", "@lerna/package-graph": "^3.18.5", "@lerna/project": "^3.18.0", - "@rollup/plugin-commonjs": "^13.0.0", + "@rollup/plugin-commonjs": "^16.0.0", "@rollup/plugin-json": "^4.0.2", "@rollup/plugin-node-resolve": "^9.0.0", "@rollup/plugin-yaml": "^2.1.1", diff --git a/yarn.lock b/yarn.lock index 3d3300493a..1c655081ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3715,18 +3715,18 @@ react-router-dom "6.0.0-beta.0" react-use "^15.3.3" -"@rollup/plugin-commonjs@^13.0.0": - version "13.0.0" - resolved "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-13.0.0.tgz#8a1d684ba6848afe8b9e3d85649d4b2f6f7217ec" - integrity sha512-Anxc3qgkAi7peAyesTqGYidG5GRim9jtg8xhmykNaZkImtvjA7Wsqep08D2mYsqw1IF7rA3lYfciLgzUSgRoqw== +"@rollup/plugin-commonjs@^16.0.0": + version "16.0.0" + resolved "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-16.0.0.tgz#169004d56cd0f0a1d0f35915d31a036b0efe281f" + integrity sha512-LuNyypCP3msCGVQJ7ki8PqYdpjfEkE/xtFa5DqlF+7IBD0JsfMZ87C58heSwIMint58sAUZbt3ITqOmdQv/dXw== dependencies: - "@rollup/pluginutils" "^3.0.8" + "@rollup/pluginutils" "^3.1.0" commondir "^1.0.1" - estree-walker "^1.0.1" - glob "^7.1.2" - is-reference "^1.1.2" - magic-string "^0.25.2" - resolve "^1.11.0" + estree-walker "^2.0.1" + glob "^7.1.6" + is-reference "^1.2.1" + magic-string "^0.25.7" + resolve "^1.17.0" "@rollup/plugin-json@^4.0.2": version "4.1.0" @@ -11085,6 +11085,11 @@ estree-walker@^1.0.1: resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== +estree-walker@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.1.tgz#f8e030fb21cefa183b44b7ad516b747434e7a3e0" + integrity sha512-tF0hv+Yi2Ot1cwj9eYHtxC0jB9bmjacjQs6ZBTj82H8JwUywFuc+7E83NWfNMwHXZc11mjfFcVXPe9gEP4B8dg== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -13968,12 +13973,12 @@ is-promise@^2.1, is-promise@^2.1.0: resolved "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== -is-reference@^1.1.2: - version "1.1.4" - resolved "https://registry.npmjs.org/is-reference/-/is-reference-1.1.4.tgz#3f95849886ddb70256a3e6d062b1a68c13c51427" - integrity sha512-uJA/CDPO3Tao3GTrxYn6AwkM4nUPJiGGYu5+cB8qbC7WGFlrKZbiRo7SFKxUAEpFUfiHofWCXBUNhvYJMh+6zw== +is-reference@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" + integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== dependencies: - "@types/estree" "0.0.39" + "@types/estree" "*" is-regex@^1.0.4, is-regex@^1.0.5, is-regex@^1.1.1: version "1.1.1" @@ -15845,7 +15850,7 @@ macos-release@^2.2.0: resolved "https://registry.npmjs.org/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f" integrity sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA== -magic-string@^0.25.2: +magic-string@^0.25.7: version "0.25.7" resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== @@ -20442,7 +20447,7 @@ resolve-url@^0.2.1: resolved "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@1.17.0, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.11.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.1, resolve@^1.16.1, resolve@^1.17.0, resolve@^1.3.2: +resolve@1.17.0, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.1, resolve@^1.16.1, resolve@^1.17.0, resolve@^1.3.2: version "1.17.0" resolved "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== From 7c7cc0b1dd57d46f1c3f11e55a888280d5480224 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 27 Oct 2020 09:45:24 +0100 Subject: [PATCH 26/45] docs: fix copy and paste error --- contrib/docs/tutorials/help-im-behind-a-corporate-proxy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/docs/tutorials/help-im-behind-a-corporate-proxy.md b/contrib/docs/tutorials/help-im-behind-a-corporate-proxy.md index 75b1b6ff7f..d02fa4b510 100644 --- a/contrib/docs/tutorials/help-im-behind-a-corporate-proxy.md +++ b/contrib/docs/tutorials/help-im-behind-a-corporate-proxy.md @@ -33,7 +33,7 @@ More information and more options for configuring `global-agent` including just `proxy-agent` is a library that you can use to override the `globalAgents` of `node` land with a tunnel to use for each request. -1. Install `global-agent` using `yarn install proxy-agent` +1. Install `proxy-agent` using `yarn install proxy-agent` 2. Go to the entry file for the backend (`src/index.ts`) 3. At the top of the file paste the following: From c46cdf34e326c1ac9191591bd2cb35875a7b94e3 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 27 Oct 2020 10:00:40 +0100 Subject: [PATCH 27/45] scaffolder-backend: fix review nit --- .../src/scaffolder/stages/prepare/preparers.ts | 6 +++--- .../src/scaffolder/stages/publish/publishers.ts | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.ts index 59537e73f4..226f7e3836 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.ts @@ -46,9 +46,9 @@ export class Preparers implements PreparerBuilder { if (!preparer) { if ((protocol as string) === 'url') { const type = this.typeDetector?.(location); - const preparer2 = type && this.preparerMap.get(type as RemoteProtocol); - if (preparer2) { - return preparer2; + const detected = type && this.preparerMap.get(type as RemoteProtocol); + if (detected) { + return detected; } throw new Error(`No preparer integration found for url "${location}"`); } diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts index 23f15745ba..db383aaf7f 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts @@ -47,10 +47,9 @@ export class Publishers implements PublisherBuilder { if (!publisher) { if ((protocol as string) === 'url') { const type = this.typeDetector?.(location); - const publisher2 = - type && this.publisherMap.get(type as RemoteProtocol); - if (publisher2) { - return publisher2; + const detected = type && this.publisherMap.get(type as RemoteProtocol); + if (detected) { + return detected; } throw new Error(`No preparer integration found for url "${location}"`); } From 2f62e180419573f786b331d7246680f2c1622615 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 26 Oct 2020 17:05:07 +0100 Subject: [PATCH 28/45] catalog-backend: remove data parsing processing step --- .changeset/mighty-starfishes-taste.md | 5 + .../src/ingestion/LocationReaders.ts | 37 ---- .../processors/FileReaderProcessor.ts | 6 +- .../processors/UrlReaderProcessor.test.ts | 10 +- .../processors/UrlReaderProcessor.ts | 6 +- .../processors/YamlProcessor.test.ts | 151 --------------- .../src/ingestion/processors/YamlProcessor.ts | 63 ------ .../src/ingestion/processors/index.ts | 1 - .../src/ingestion/processors/results.ts | 7 - .../src/ingestion/processors/types.ts | 21 -- .../ingestion/processors/util/parse.test.ts | 180 ++++++++++++++++++ .../src/ingestion/processors/util/parse.ts | 49 +++++ .../src/service/CatalogBuilder.test.ts | 11 +- .../src/service/CatalogBuilder.ts | 2 - 14 files changed, 250 insertions(+), 299 deletions(-) create mode 100644 .changeset/mighty-starfishes-taste.md delete mode 100644 plugins/catalog-backend/src/ingestion/processors/YamlProcessor.test.ts delete mode 100644 plugins/catalog-backend/src/ingestion/processors/YamlProcessor.ts create mode 100644 plugins/catalog-backend/src/ingestion/processors/util/parse.test.ts create mode 100644 plugins/catalog-backend/src/ingestion/processors/util/parse.ts diff --git a/.changeset/mighty-starfishes-taste.md b/.changeset/mighty-starfishes-taste.md new file mode 100644 index 0000000000..eb43ce69b8 --- /dev/null +++ b/.changeset/mighty-starfishes-taste.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': minor +--- + +Removed the parseData step from catalog processors. Locations readers should emit full entities instead. diff --git a/plugins/catalog-backend/src/ingestion/LocationReaders.ts b/plugins/catalog-backend/src/ingestion/LocationReaders.ts index 11ae45cae9..45bf2e8ae0 100644 --- a/plugins/catalog-backend/src/ingestion/LocationReaders.ts +++ b/plugins/catalog-backend/src/ingestion/LocationReaders.ts @@ -28,7 +28,6 @@ import { CatalogRulesEnforcer } from './CatalogRules'; import * as result from './processors/results'; import { CatalogProcessor, - CatalogProcessorDataResult, CatalogProcessorEmit, CatalogProcessorEntityResult, CatalogProcessorErrorResult, @@ -75,8 +74,6 @@ export class LocationReaders implements LocationReader { for (const item of items) { if (item.type === 'location') { await this.handleLocation(item, emit); - } else if (item.type === 'data') { - await this.handleData(item, emit); } else if (item.type === 'entity') { if (rulesEnforcer.isAllowed(item.entity, item.location)) { const relations = Array(); @@ -165,40 +162,6 @@ export class LocationReaders implements LocationReader { logger.warn(message); } - private async handleData( - item: CatalogProcessorDataResult, - emit: CatalogProcessorEmit, - ) { - const { processors, logger } = this.options; - - const validatedEmit: CatalogProcessorEmit = emitResult => { - if (emitResult.type === 'relation') { - throw new Error('parseData may not emit entity relations'); - } - - emit(emitResult); - }; - - for (const processor of processors) { - if (processor.parseData) { - try { - if ( - await processor.parseData(item.data, item.location, validatedEmit) - ) { - return; - } - } catch (e) { - const message = `Processor ${processor.constructor.name} threw an error while parsing ${item.location.type} ${item.location.target}, ${e}`; - emit(result.generalError(item.location, message)); - logger.warn(message); - } - } - } - - const message = `No processor was able to parse location ${item.location.type} ${item.location.target}`; - emit(result.inputError(item.location, message)); - } - private async handleEntity( item: CatalogProcessorEntityResult, emit: CatalogProcessorEmit, diff --git a/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.ts index 83fc01185b..2328ec3c7a 100644 --- a/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.ts @@ -18,6 +18,7 @@ import { LocationSpec } from '@backstage/catalog-model'; import fs from 'fs-extra'; import * as result from './results'; import { CatalogProcessor, CatalogProcessorEmit } from './types'; +import { parseEntityYaml } from './util/parse'; export class FileReaderProcessor implements CatalogProcessor { async readLocation( @@ -33,7 +34,10 @@ export class FileReaderProcessor implements CatalogProcessor { const exists = await fs.pathExists(location.target); if (exists) { const data = await fs.readFile(location.target); - emit(result.data(location, data)); + + for (const parseResult of parseEntityYaml(data, location)) { + emit(parseResult); + } } else if (!optional) { const message = `${location.type} ${location.target} does not exist`; emit(result.notFoundError(location, message)); diff --git a/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.test.ts index 73046f0ed1..9bf72d620b 100644 --- a/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.test.ts @@ -21,7 +21,7 @@ import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { msw } from '@backstage/test-utils'; import { - CatalogProcessorDataResult, + CatalogProcessorEntityResult, CatalogProcessorErrorResult, CatalogProcessorResult, } from './types'; @@ -42,17 +42,17 @@ describe('UrlReaderProcessor', () => { server.use( rest.get(`${mockApiOrigin}/component.yaml`, (_, res, ctx) => - res(ctx.body('Hello')), + res(ctx.json({ mock: 'entity' })), ), ); const generated = (await new Promise(emit => processor.readLocation(spec, false, emit), - )) as CatalogProcessorDataResult; + )) as CatalogProcessorEntityResult; - expect(generated.type).toBe('data'); + expect(generated.type).toBe('entity'); expect(generated.location).toBe(spec); - expect(generated.data.toString('utf8')).toBe('Hello'); + expect(generated.entity).toEqual({ mock: 'entity' }); }); it('should fail load from url with error', async () => { diff --git a/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.ts index 0169abbbe3..d31f053c80 100644 --- a/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.ts @@ -19,6 +19,7 @@ import { LocationSpec } from '@backstage/catalog-model'; import { Logger } from 'winston'; import * as result from './results'; import { CatalogProcessor, CatalogProcessorEmit } from './types'; +import { parseEntityYaml } from './util/parse'; // TODO(Rugvip): Added for backwards compatibility when moving to UrlReader, this // can be removed in a bit @@ -55,7 +56,10 @@ export class UrlReaderProcessor implements CatalogProcessor { try { const data = await this.options.reader.read(location.target); - emit(result.data(location, data)); + + for (const parseResult of parseEntityYaml(data, location)) { + emit(parseResult); + } } catch (error) { const message = `Unable to read ${location.type}, ${error}`; diff --git a/plugins/catalog-backend/src/ingestion/processors/YamlProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/YamlProcessor.test.ts deleted file mode 100644 index f5d2dfea38..0000000000 --- a/plugins/catalog-backend/src/ingestion/processors/YamlProcessor.test.ts +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Entity } from '@backstage/catalog-model'; -import { TextEncoder } from 'util'; -import yaml from 'yaml'; -import { - CatalogProcessorEntityResult, - CatalogProcessorErrorResult, -} from './types'; -import { YamlProcessor } from './YamlProcessor'; - -describe('YamlProcessor', () => { - const processor = new YamlProcessor(); - const locationSpec = { - type: 'url', - target: 'http://example.com/component.yaml', - }; - - function encodeEntity(entity: string): Buffer { - const data = new TextEncoder().encode(entity); - return Buffer.from(data); - } - - it('should only process files with yaml', async () => { - const wrongLocationSpec = { - type: 'url', - target: 'http://example.com/component.json', - }; - - const buffer = Buffer.from([]); - const never = jest.fn(); - - expect(await processor.parseData(buffer, wrongLocationSpec, never)).toBe( - false, - ); - - expect(never).not.toBeCalled(); - }); - - it('should process url that contains yaml', async () => { - const containsYamlLocationSpec = { - type: 'url', - target: 'http://example.com/component?path=test.yaml&c=1&d=2', - }; - - const buffer = Buffer.from([]); - const emit = jest.fn(); - - expect( - await processor.parseData(buffer, containsYamlLocationSpec, emit), - ).toBe(true); - - expect(emit).toBeCalled(); - }); - - it('should process entity with yaml', async () => { - const entity = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Component', - metadata: { - name: 'my-component', - }, - spec: {}, - } as Entity; - - const buffer = encodeEntity(yaml.stringify(entity)); - const emit = jest.fn(); - - expect(await processor.parseData(buffer, locationSpec, emit)).toBe(true); - - const e = emit.mock.calls[0][0] as CatalogProcessorEntityResult; - expect(e.type).toBe('entity'); - expect(e.location).toBe(locationSpec); - expect(e.entity).toEqual(entity); - }); - - it('should process multiple entities with yaml', async () => { - const entityComponent = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Component', - metadata: { - name: 'my-component', - }, - spec: {}, - } as Entity; - - const entityApi = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'API', - metadata: { - name: 'my-api', - }, - spec: {}, - } as Entity; - - const buffer = encodeEntity( - `${yaml.stringify(entityComponent)}---\n${yaml.stringify(entityApi)}`, - ); - const emit = jest.fn(); - - expect(await processor.parseData(buffer, locationSpec, emit)).toBe(true); - - const eComponent = emit.mock.calls[0][0] as CatalogProcessorEntityResult; - expect(eComponent.type).toBe('entity'); - expect(eComponent.location).toBe(locationSpec); - expect(eComponent.entity).toEqual(entityComponent); - - const eApi = emit.mock.calls[1][0] as CatalogProcessorEntityResult; - expect(eApi.type).toBe('entity'); - expect(eApi.location).toBe(locationSpec); - expect(eApi.entity).toEqual(entityApi); - }); - - it('should fail process entity on invalid yaml', async () => { - const buffer = encodeEntity('{'); - const emit = jest.fn(); - - expect(await processor.parseData(buffer, locationSpec, emit)).toBe(true); - - const e = emit.mock.calls[0][0] as CatalogProcessorErrorResult; - expect(e.error.message).toMatch(/^YAML error, /); - expect(e.type).toBe('error'); - expect(e.location).toBe(locationSpec); - }); - - it('should fail process entity if not object at root', async () => { - const buffer = encodeEntity('[]'); - const emit = jest.fn(); - - expect(await processor.parseData(buffer, locationSpec, emit)).toBe(true); - - const e = emit.mock.calls[0][0] as CatalogProcessorErrorResult; - expect(e.error.message).toMatch(/^Expected object at root, got /); - expect(e.type).toBe('error'); - expect(e.location).toBe(locationSpec); - }); -}); diff --git a/plugins/catalog-backend/src/ingestion/processors/YamlProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/YamlProcessor.ts deleted file mode 100644 index 46df4e6a2b..0000000000 --- a/plugins/catalog-backend/src/ingestion/processors/YamlProcessor.ts +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Entity, LocationSpec } from '@backstage/catalog-model'; -import lodash from 'lodash'; -import yaml from 'yaml'; -import * as result from './results'; -import { CatalogProcessor, CatalogProcessorEmit } from './types'; - -/** - * Handles incoming raw data buffers, and if they have a yaml extension, - * attempts to parse them into structured data and emitting them as un- - * validated entities. - */ -export class YamlProcessor implements CatalogProcessor { - async parseData( - data: Buffer, - location: LocationSpec, - emit: CatalogProcessorEmit, - ): Promise { - if (!location.target.match(/\.ya?ml/)) { - return false; - } - - let documents: yaml.Document.Parsed[]; - try { - documents = yaml.parseAllDocuments(data.toString('utf8')).filter(d => d); - } catch (e) { - emit(result.generalError(location, `Failed to parse YAML, ${e}`)); - return true; - } - - for (const document of documents) { - if (document.errors?.length) { - const message = `YAML error, ${document.errors[0]}`; - emit(result.generalError(location, message)); - } else { - const json = document.toJSON(); - if (lodash.isPlainObject(json)) { - emit(result.entity(location, json as Entity)); - } else { - const message = `Expected object at root, got ${typeof json}`; - emit(result.generalError(location, message)); - } - } - } - - return true; - } -} diff --git a/plugins/catalog-backend/src/ingestion/processors/index.ts b/plugins/catalog-backend/src/ingestion/processors/index.ts index 8344678e5f..d654f37dc7 100644 --- a/plugins/catalog-backend/src/ingestion/processors/index.ts +++ b/plugins/catalog-backend/src/ingestion/processors/index.ts @@ -29,4 +29,3 @@ export { PlaceholderProcessor } from './PlaceholderProcessor'; export type { PlaceholderResolver } from './PlaceholderProcessor'; export { StaticLocationProcessor } from './StaticLocationProcessor'; export { UrlReaderProcessor } from './UrlReaderProcessor'; -export { YamlProcessor } from './YamlProcessor'; diff --git a/plugins/catalog-backend/src/ingestion/processors/results.ts b/plugins/catalog-backend/src/ingestion/processors/results.ts index 158bc3d950..5f92087cec 100644 --- a/plugins/catalog-backend/src/ingestion/processors/results.ts +++ b/plugins/catalog-backend/src/ingestion/processors/results.ts @@ -51,13 +51,6 @@ export function generalError( return { type: 'error', location: atLocation, error: new Error(message) }; } -export function data( - atLocation: LocationSpec, - newData: Buffer, -): CatalogProcessorResult { - return { type: 'data', location: atLocation, data: newData }; -} - export function location( newLocation: LocationSpec, optional: boolean, diff --git a/plugins/catalog-backend/src/ingestion/processors/types.ts b/plugins/catalog-backend/src/ingestion/processors/types.ts index 7821a61437..5d353d5af0 100644 --- a/plugins/catalog-backend/src/ingestion/processors/types.ts +++ b/plugins/catalog-backend/src/ingestion/processors/types.ts @@ -35,20 +35,6 @@ export type CatalogProcessor = { emit: CatalogProcessorEmit, ): Promise; - /** - * Parses a raw data buffer that was read from a location. - * - * @param data The data to parse - * @param location The location that the data came from - * @param emit A sink for items resulting from the parsing - * @returns True if handled by this processor, false otherwise - */ - parseData?( - data: Buffer, - location: LocationSpec, - emit: CatalogProcessorEmit, - ): Promise; - /** * Pre-processes an emitted entity, after it has been emitted but before it * has been validated. @@ -105,12 +91,6 @@ export type CatalogProcessorLocationResult = { optional: boolean; }; -export type CatalogProcessorDataResult = { - type: 'data'; - data: Buffer; - location: LocationSpec; -}; - export type CatalogProcessorEntityResult = { type: 'entity'; entity: Entity; @@ -131,7 +111,6 @@ export type CatalogProcessorErrorResult = { export type CatalogProcessorResult = | CatalogProcessorLocationResult - | CatalogProcessorDataResult | CatalogProcessorEntityResult | CatalogProcessorRelationResult | CatalogProcessorErrorResult; diff --git a/plugins/catalog-backend/src/ingestion/processors/util/parse.test.ts b/plugins/catalog-backend/src/ingestion/processors/util/parse.test.ts new file mode 100644 index 0000000000..1400a066cd --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/processors/util/parse.test.ts @@ -0,0 +1,180 @@ +/* + * 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 { parseEntityYaml } from './parse'; +import * as result from '../results'; + +const testLoc = { + target: 'my-loc-target', + type: 'my-loc-type', +}; + +describe('parseEntityYaml', () => { + it('should parse a yaml', () => { + const results = Array.from( + parseEntityYaml( + Buffer.from( + ` + apiVersion: backstage.io/v1alpha1 + kind: Component + metadata: + name: backstage + description: backstage.io + annotations: + github.com/project-slug: 'spotify/backstage' + spec: + type: website + lifecycle: production + owner: guest + `, + 'utf8', + ), + testLoc, + ), + ); + + expect(results).toEqual([ + result.entity(testLoc, { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'backstage', + description: 'backstage.io', + annotations: { + 'github.com/project-slug': 'spotify/backstage', + }, + }, + spec: { + type: 'website', + lifecycle: 'production', + owner: 'guest', + }, + }), + ]); + }); + + it('should parse multiple docs', () => { + const results = Array.from( + parseEntityYaml( + Buffer.from( + ` + apiVersion: backstage.io/v1alpha1 + kind: Component + metadata: + name: web + spec: + type: website +--- + apiVersion: backstage.io/v1alpha1 + kind: Component + metadata: + name: srv + spec: + type: service + `, + 'utf8', + ), + testLoc, + ), + ); + + expect(results).toEqual([ + result.entity(testLoc, { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'web', + }, + spec: { + type: 'website', + }, + }), + result.entity(testLoc, { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'srv', + }, + spec: { + type: 'service', + }, + }), + ]); + }); + + it('should emit parsing errors', () => { + const results = Array.from( + parseEntityYaml(Buffer.from('`', 'utf8'), testLoc), + ); + + // Parse errors are always per document + expect(results).toEqual([ + result.generalError( + testLoc, + 'YAML error, YAMLSemanticError: Plain value cannot start with reserved character `', + ), + ]); + }); + + it('should emit parsing errors for individual documents', () => { + const results = Array.from( + parseEntityYaml( + Buffer.from( + ` + apiVersion: backstage.io/v1alpha1 + kind: Component + metadata: + name: web + spec: + type: website +--- + apiVersion: backstage.io/v1alpha1 + this: - is - not [valid] yaml + `, + 'utf8', + ), + testLoc, + ), + ); + + expect(results).toEqual([ + result.entity(testLoc, { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'web', + }, + spec: { + type: 'website', + }, + }), + result.generalError( + testLoc, + 'YAML error, YAMLSemanticError: Nested mappings are not allowed in compact mappings', + ), + ]); + }); + + it('must be an object at root', () => { + const results = Array.from( + parseEntityYaml(Buffer.from('imma-string', 'utf8'), testLoc), + ); + + expect(results).toEqual([ + result.generalError(testLoc, 'Expected object at root, got string'), + ]); + }); +}); diff --git a/plugins/catalog-backend/src/ingestion/processors/util/parse.ts b/plugins/catalog-backend/src/ingestion/processors/util/parse.ts new file mode 100644 index 0000000000..3f07a815b0 --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/processors/util/parse.ts @@ -0,0 +1,49 @@ +/* + * 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, LocationSpec } from '@backstage/catalog-model'; +import lodash from 'lodash'; +import yaml from 'yaml'; +import * as result from '../results'; +import { CatalogProcessorResult } from '../types'; + +export function* parseEntityYaml( + data: Buffer, + location: LocationSpec, +): Iterable { + let documents: yaml.Document.Parsed[]; + try { + documents = yaml.parseAllDocuments(data.toString('utf8')).filter(d => d); + } catch (e) { + yield result.generalError(location, `Failed to parse YAML, ${e}`); + return; + } + + for (const document of documents) { + if (document.errors?.length) { + const message = `YAML error, ${document.errors[0]}`; + yield result.generalError(location, message); + } else { + const json = document.toJSON(); + if (lodash.isPlainObject(json)) { + yield result.entity(location, json as Entity); + } else { + const message = `Expected object at root, got ${typeof json}`; + yield result.generalError(location, message); + } + } + } +} diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.test.ts b/plugins/catalog-backend/src/service/CatalogBuilder.test.ts index bc71934488..4e474c287a 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.test.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.test.ts @@ -83,15 +83,6 @@ describe('CatalogBuilder', () => { emit: CatalogProcessorEmit, ) { expect(location.type).toBe('test'); - emit(result.data(location, await reader.read('ignored'))); - return true; - }, - async parseData( - data: Buffer, - location: LocationSpec, - emit: CatalogProcessorEmit, - ) { - expect(data.toString()).toEqual('junk'); emit( result.entity(location, { apiVersion: 'av', @@ -123,7 +114,7 @@ describe('CatalogBuilder', () => { type: 'test', target: '', }); - expect.assertions(8); + expect.assertions(7); expect(added.entities).toEqual([ { apiVersion: 'av', diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.ts b/plugins/catalog-backend/src/service/CatalogBuilder.ts index e795310915..485e66acbb 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.ts @@ -56,7 +56,6 @@ import { PlaceholderResolver, StaticLocationProcessor, UrlReaderProcessor, - YamlProcessor, } from '../ingestion'; import { CatalogRulesEnforcer } from '../ingestion/CatalogRules'; import { LdapOrgReaderProcessor } from '../ingestion/processors/LdapOrgReaderProcessor'; @@ -329,7 +328,6 @@ export class CatalogBuilder { GithubOrgReaderProcessor.fromConfig(config, { logger }), LdapOrgReaderProcessor.fromConfig(config, { logger }), new UrlReaderProcessor({ reader, logger }), - new YamlProcessor(), new CodeOwnersProcessor({ reader }), new LocationRefProcessor(), new OwnerRelationProcessor(), From 24e5730200befee2965f788696f9234edd554652 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 27 Oct 2020 10:07:25 +0100 Subject: [PATCH 29/45] techdocs-backend: remove duplicate log tagging --- .../techdocs-backend/src/service/helpers.ts | 18 +++++------------- plugins/techdocs-backend/src/service/router.ts | 6 ++---- .../src/techdocs/stages/generate/techdocs.ts | 8 ++++---- .../src/techdocs/stages/prepare/dir.ts | 2 +- 4 files changed, 12 insertions(+), 22 deletions(-) diff --git a/plugins/techdocs-backend/src/service/helpers.ts b/plugins/techdocs-backend/src/service/helpers.ts index 1b8e130ec0..b308dc28af 100644 --- a/plugins/techdocs-backend/src/service/helpers.ts +++ b/plugins/techdocs-backend/src/service/helpers.ts @@ -66,22 +66,16 @@ export class DocsBuilder { } public async build() { - this.logger.info( - `[TechDocs] Running preparer on entity ${getEntityId(this.entity)}`, - ); + this.logger.info(`Running preparer on entity ${getEntityId(this.entity)}`); const preparedDir = await this.preparer.prepare(this.entity); - this.logger.info( - `[TechDocs] Running generator on entity ${getEntityId(this.entity)}`, - ); + this.logger.info(`Running generator on entity ${getEntityId(this.entity)}`); const { resultDir } = await this.generator.run({ directory: preparedDir, dockerClient: this.dockerClient, }); - this.logger.info( - `[TechDocs] Running publisher on entity ${getEntityId(this.entity)}`, - ); + this.logger.info(`Running publisher on entity ${getEntityId(this.entity)}`); await this.publisher.publish({ entity: this.entity, directory: resultDir, @@ -117,16 +111,14 @@ export class DocsBuilder { // Check if documentation source is newer than what we have if (storageTimeStamp && storageTimeStamp >= lastCommit) { this.logger.debug( - `[TechDocs] Docs for entity ${getEntityId( - this.entity, - )} is up to date.`, + `Docs for entity ${getEntityId(this.entity)} is up to date.`, ); return true; } } this.logger.debug( - `[TechDocs] Docs for entity ${getEntityId(this.entity)} was outdated.`, + `Docs for entity ${getEntityId(this.entity)} was outdated.`, ); return false; } diff --git a/plugins/techdocs-backend/src/service/router.ts b/plugins/techdocs-backend/src/service/router.ts index b6f8865a57..2254e721bd 100644 --- a/plugins/techdocs-backend/src/service/router.ts +++ b/plugins/techdocs-backend/src/service/router.ts @@ -71,9 +71,7 @@ export async function createRouter({ const mkDocsMetadata = await (await fetch(metadataURL)).json(); res.send(mkDocsMetadata); } catch (err) { - logger.info( - `[TechDocs] Unable to get metadata for ${path} with error ${err}`, - ); + logger.info(`Unable to get metadata for ${path} with error ${err}`); throw new Error(`Unable to get metadata for ${path} with error ${err}`); } }); @@ -93,7 +91,7 @@ export async function createRouter({ res.send({ ...entity, locationMetadata }); } catch (err) { logger.info( - `[TechDocs] Unable to get metadata for ${kind}/${namespace}/${name} with error ${err}`, + `Unable to get metadata for ${kind}/${namespace}/${name} with error ${err}`, ); throw new Error( `Unable to get metadata for ${kind}/${namespace}/${name} with error ${err}`, diff --git a/plugins/techdocs-backend/src/techdocs/stages/generate/techdocs.ts b/plugins/techdocs-backend/src/techdocs/stages/generate/techdocs.ts index ac73963f9a..1160ff1ade 100644 --- a/plugins/techdocs-backend/src/techdocs/stages/generate/techdocs.ts +++ b/plugins/techdocs-backend/src/techdocs/stages/generate/techdocs.ts @@ -83,7 +83,7 @@ export class TechdocsGenerator implements GeneratorBase { logStream, }); this.logger.info( - `[TechDocs]: Successfully generated docs from ${directory} into ${resultDir} using local mkdocs`, + `Successfully generated docs from ${directory} into ${resultDir} using local mkdocs`, ); break; case 'docker': @@ -96,7 +96,7 @@ export class TechdocsGenerator implements GeneratorBase { dockerClient, }); this.logger.info( - `[TechDocs]: Successfully generated docs from ${directory} into ${resultDir} using techdocs-container`, + `Successfully generated docs from ${directory} into ${resultDir} using techdocs-container`, ); break; default: @@ -106,9 +106,9 @@ export class TechdocsGenerator implements GeneratorBase { } } catch (error) { this.logger.debug( - `[TechDocs]: Failed to generate docs from ${directory} into ${resultDir}`, + `Failed to generate docs from ${directory} into ${resultDir}`, ); - this.logger.debug(`[TechDocs]: Build failed with error: ${log}`); + this.logger.debug(`Build failed with error: ${log}`); throw new Error( `Failed to generate docs from ${directory} into ${resultDir} with error ${error.message}`, ); diff --git a/plugins/techdocs-backend/src/techdocs/stages/prepare/dir.ts b/plugins/techdocs-backend/src/techdocs/stages/prepare/dir.ts index d76aee25bd..1effcf61b5 100644 --- a/plugins/techdocs-backend/src/techdocs/stages/prepare/dir.ts +++ b/plugins/techdocs-backend/src/techdocs/stages/prepare/dir.ts @@ -38,7 +38,7 @@ export class DirectoryPreparer implements PreparerBase { ); this.logger.debug( - `[TechDocs] Building docs for entity with type 'dir' and managed-by-location '${type}'`, + `Building docs for entity with type 'dir' and managed-by-location '${type}'`, ); switch (type) { case 'github': From 796b844cb3492cf6ed0615ea99d02fcc18789eab Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 27 Oct 2020 11:05:42 +0100 Subject: [PATCH 30/45] chore(docs): more docs around proxy setup --- .../docs/tutorials/help-im-behind-a-corporate-proxy.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/contrib/docs/tutorials/help-im-behind-a-corporate-proxy.md b/contrib/docs/tutorials/help-im-behind-a-corporate-proxy.md index d02fa4b510..4f8351ac15 100644 --- a/contrib/docs/tutorials/help-im-behind-a-corporate-proxy.md +++ b/contrib/docs/tutorials/help-im-behind-a-corporate-proxy.md @@ -42,9 +42,16 @@ import ProxyAgent from 'proxy-agent'; import http from 'http'; import https from 'https'; +/* + Something to note here, this might need different configuration depending on your own setup. + If you only have an http_proxy then you'll need to set that as both the http and https globalAgent instead. +*/ if (process.env.HTTP_PROXY) { http.globalAgent = new ProxyAgent(process.env.HTTP_PROXY); - https.globalAgent = new ProxyAgent(process.env.HTTP_PROXY); +} + +if (process.env.HTTPS_PROXY) { + https.globalAgent = new ProxyAgent(process.env.HTTPS_PROXY); } ``` From 754109ee6153d209766898e72dc2841c81749d06 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 27 Oct 2020 12:00:01 +0100 Subject: [PATCH 31/45] v0.1.1-alpha.26 --- lerna.json | 2 +- packages/app/package.json | 56 ++++++++++++------------- packages/backend-common/package.json | 12 +++--- packages/backend/package.json | 32 +++++++------- packages/catalog-model/package.json | 6 +-- packages/cli-common/package.json | 2 +- packages/cli/package.json | 8 ++-- packages/config-loader/package.json | 4 +- packages/config/package.json | 2 +- packages/core-api/package.json | 12 +++--- packages/core/package.json | 12 +++--- packages/create-app/package.json | 4 +- packages/dev-utils/package.json | 10 ++--- packages/docgen/package.json | 2 +- packages/e2e-test/package.json | 6 +-- packages/storybook/package.json | 4 +- packages/techdocs-cli/package.json | 4 +- packages/test-utils-core/package.json | 2 +- packages/test-utils/package.json | 10 ++--- packages/theme/package.json | 4 +- plugins/api-docs/package.json | 20 ++++----- plugins/app-backend/package.json | 8 ++-- plugins/auth-backend/package.json | 12 +++--- plugins/catalog-backend/package.json | 12 +++--- plugins/catalog-graphql/package.json | 16 +++---- plugins/catalog/package.json | 22 +++++----- plugins/circleci/package.json | 18 ++++---- plugins/cloudbuild/package.json | 18 ++++---- plugins/cost-insights/package.json | 20 ++++----- plugins/explore/package.json | 16 +++---- plugins/gcp-projects/package.json | 14 +++---- plugins/github-actions/package.json | 20 ++++----- plugins/gitops-profiles/package.json | 14 +++---- plugins/graphiql/package.json | 16 +++---- plugins/graphql/package.json | 10 ++--- plugins/jenkins/package.json | 18 ++++---- plugins/kubernetes-backend/package.json | 8 ++-- plugins/kubernetes/package.json | 22 +++++----- plugins/lighthouse/package.json | 24 +++++------ plugins/newrelic/package.json | 14 +++---- plugins/proxy-backend/package.json | 8 ++-- plugins/register-component/package.json | 18 ++++---- plugins/rollbar-backend/package.json | 8 ++-- plugins/rollbar/package.json | 20 ++++----- plugins/scaffolder-backend/package.json | 10 ++--- plugins/scaffolder/package.json | 20 ++++----- plugins/sentry-backend/package.json | 6 +-- plugins/sentry/package.json | 14 +++---- plugins/tech-radar/package.json | 16 +++---- plugins/techdocs-backend/package.json | 12 +++--- plugins/techdocs/package.json | 22 +++++----- plugins/user-settings/package.json | 16 +++---- plugins/welcome/package.json | 16 +++---- 53 files changed, 351 insertions(+), 351 deletions(-) diff --git a/lerna.json b/lerna.json index f804c800de..5871423f78 100644 --- a/lerna.json +++ b/lerna.json @@ -2,5 +2,5 @@ "packages": ["packages/*", "plugins/*"], "npmClient": "yarn", "useWorkspaces": true, - "version": "0.1.1-alpha.25" + "version": "0.1.1-alpha.26" } diff --git a/packages/app/package.json b/packages/app/package.json index dc452e0803..bb446a3458 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,36 +1,36 @@ { "name": "example-app", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "private": true, "bundled": true, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/plugin-api-docs": "^0.1.1-alpha.25", - "@backstage/plugin-catalog": "^0.1.1-alpha.25", - "@backstage/plugin-circleci": "^0.1.1-alpha.25", - "@backstage/plugin-cloudbuild": "^0.1.1-alpha.25", - "@backstage/plugin-cost-insights": "^0.1.1-alpha.25", - "@backstage/plugin-explore": "^0.1.1-alpha.25", - "@backstage/plugin-gcp-projects": "^0.1.1-alpha.25", - "@backstage/plugin-github-actions": "^0.1.1-alpha.25", - "@backstage/plugin-gitops-profiles": "^0.1.1-alpha.25", - "@backstage/plugin-graphiql": "^0.1.1-alpha.25", - "@backstage/plugin-jenkins": "^0.1.1-alpha.25", - "@backstage/plugin-kubernetes": "^0.1.1-alpha.25", - "@backstage/plugin-lighthouse": "^0.1.1-alpha.25", - "@backstage/plugin-newrelic": "^0.1.1-alpha.25", - "@backstage/plugin-register-component": "^0.1.1-alpha.25", - "@backstage/plugin-rollbar": "^0.1.1-alpha.25", - "@backstage/plugin-scaffolder": "^0.1.1-alpha.25", - "@backstage/plugin-sentry": "^0.1.1-alpha.25", - "@backstage/plugin-tech-radar": "^0.1.1-alpha.25", - "@backstage/plugin-techdocs": "^0.1.1-alpha.25", - "@backstage/plugin-user-settings": "^0.1.1-alpha.25", - "@backstage/plugin-welcome": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/plugin-api-docs": "^0.1.1-alpha.26", + "@backstage/plugin-catalog": "^0.1.1-alpha.26", + "@backstage/plugin-circleci": "^0.1.1-alpha.26", + "@backstage/plugin-cloudbuild": "^0.1.1-alpha.26", + "@backstage/plugin-cost-insights": "^0.1.1-alpha.26", + "@backstage/plugin-explore": "^0.1.1-alpha.26", + "@backstage/plugin-gcp-projects": "^0.1.1-alpha.26", + "@backstage/plugin-github-actions": "^0.1.1-alpha.26", + "@backstage/plugin-gitops-profiles": "^0.1.1-alpha.26", + "@backstage/plugin-graphiql": "^0.1.1-alpha.26", + "@backstage/plugin-jenkins": "^0.1.1-alpha.26", + "@backstage/plugin-kubernetes": "^0.1.1-alpha.26", + "@backstage/plugin-lighthouse": "^0.1.1-alpha.26", + "@backstage/plugin-newrelic": "^0.1.1-alpha.26", + "@backstage/plugin-register-component": "^0.1.1-alpha.26", + "@backstage/plugin-rollbar": "^0.1.1-alpha.26", + "@backstage/plugin-scaffolder": "^0.1.1-alpha.26", + "@backstage/plugin-sentry": "^0.1.1-alpha.26", + "@backstage/plugin-tech-radar": "^0.1.1-alpha.26", + "@backstage/plugin-techdocs": "^0.1.1-alpha.26", + "@backstage/plugin-user-settings": "^0.1.1-alpha.26", + "@backstage/plugin-welcome": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@octokit/rest": "^18.0.0", diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 875163dd96..dea2f16bae 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-common", "description": "Common functionality library for Backstage backends", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -29,10 +29,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/cli-common": "^0.1.1-alpha.25", - "@backstage/config": "^0.1.1-alpha.25", - "@backstage/config-loader": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", + "@backstage/cli-common": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1-alpha.26", + "@backstage/config-loader": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@types/cors": "^2.8.6", "@types/express": "^4.17.6", "compression": "^1.7.4", @@ -62,7 +62,7 @@ } }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", "@types/compression": "^1.7.0", "@types/http-errors": "^1.6.3", "@types/minimist": "^1.2.0", diff --git a/packages/backend/package.json b/packages/backend/package.json index ef55b007a7..9f8e66bc61 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "dist/index.cjs.js", "types": "src/index.ts", "private": true, @@ -18,24 +18,24 @@ "migrate:create": "knex migrate:make -x ts" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.25", - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/config": "^0.1.1-alpha.25", - "@backstage/plugin-app-backend": "^0.1.1-alpha.25", - "@backstage/plugin-auth-backend": "^0.1.1-alpha.25", - "@backstage/plugin-catalog-backend": "^0.1.1-alpha.25", - "@backstage/plugin-graphql-backend": "^0.1.1-alpha.25", - "@backstage/plugin-kubernetes-backend": "^0.1.1-alpha.25", - "@backstage/plugin-proxy-backend": "^0.1.1-alpha.25", - "@backstage/plugin-rollbar-backend": "^0.1.1-alpha.25", - "@backstage/plugin-scaffolder-backend": "^0.1.1-alpha.25", - "@backstage/plugin-sentry-backend": "^0.1.1-alpha.25", - "@backstage/plugin-techdocs-backend": "^0.1.1-alpha.25", + "@backstage/backend-common": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1-alpha.26", + "@backstage/plugin-app-backend": "^0.1.1-alpha.26", + "@backstage/plugin-auth-backend": "^0.1.1-alpha.26", + "@backstage/plugin-catalog-backend": "^0.1.1-alpha.26", + "@backstage/plugin-graphql-backend": "^0.1.1-alpha.26", + "@backstage/plugin-kubernetes-backend": "^0.1.1-alpha.26", + "@backstage/plugin-proxy-backend": "^0.1.1-alpha.26", + "@backstage/plugin-rollbar-backend": "^0.1.1-alpha.26", + "@backstage/plugin-scaffolder-backend": "^0.1.1-alpha.26", + "@backstage/plugin-sentry-backend": "^0.1.1-alpha.26", + "@backstage/plugin-techdocs-backend": "^0.1.1-alpha.26", "@gitbeaker/node": "^23.5.0", "@octokit/rest": "^18.0.0", "azure-devops-node-api": "^10.1.1", "dockerode": "^3.2.0", - "example-app": "^0.1.1-alpha.25", + "example-app": "^0.1.1-alpha.26", "express": "^4.17.1", "express-promise-router": "^3.0.3", "knex": "^0.21.1", @@ -45,7 +45,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", "@types/dockerode": "^2.5.32", "@types/express": "^4.17.6", "@types/express-serve-static-core": "^4.17.5", diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index 5ba2b6efdf..c97aea9572 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/catalog-model", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,7 +20,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/config": "^0.1.1-alpha.25", + "@backstage/config": "^0.1.1-alpha.26", "@types/json-schema": "^7.0.5", "@types/yup": "^0.29.8", "json-schema": "^0.2.5", @@ -29,7 +29,7 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", "@types/express": "^4.17.6", "@types/jest": "^26.0.7", "@types/lodash": "^4.14.151", diff --git a/packages/cli-common/package.json b/packages/cli-common/package.json index d9492ef127..56fb0d3417 100644 --- a/packages/cli-common/package.json +++ b/packages/cli-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli-common", "description": "Common functionality used by cli, backend, and create-app", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "private": false, "main": "src/index.ts", "types": "src/index.ts", diff --git a/packages/cli/package.json b/packages/cli/package.json index 3024c2eeaf..8a330d861b 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli", "description": "CLI for developing Backstage plugins and apps", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "private": false, "publishConfig": { "access": "public" @@ -28,9 +28,9 @@ "backstage-cli": "bin/backstage-cli" }, "dependencies": { - "@backstage/cli-common": "^0.1.1-alpha.25", - "@backstage/config": "^0.1.1-alpha.25", - "@backstage/config-loader": "^0.1.1-alpha.25", + "@backstage/cli-common": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1-alpha.26", + "@backstage/config-loader": "^0.1.1-alpha.26", "@hot-loader/react-dom": "^16.13.0", "@lerna/package-graph": "^3.18.5", "@lerna/project": "^3.18.0", diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index eead016c8f..2eef7db027 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config-loader", "description": "Config loading functionality used by Backstage backend, and CLI", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "private": false, "publishConfig": { "access": "public", @@ -30,7 +30,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/config": "^0.1.1-alpha.25", + "@backstage/config": "^0.1.1-alpha.26", "fs-extra": "^9.0.0", "yaml": "^1.9.2", "yup": "^0.29.3" diff --git a/packages/config/package.json b/packages/config/package.json index 589c87c15c..d8ee50e97c 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config", "description": "Config API used by Backstage core, backend, and CLI", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "private": false, "publishConfig": { "access": "public", diff --git a/packages/core-api/package.json b/packages/core-api/package.json index 5b1456d1ba..34949e4315 100644 --- a/packages/core-api/package.json +++ b/packages/core-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-api", "description": "Internal Core API used by Backstage plugins and apps", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "private": false, "publishConfig": { "access": "public", @@ -29,9 +29,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/config": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/config": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@types/react": "^16.9", @@ -42,8 +42,8 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/test-utils-core": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/test-utils-core": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/packages/core/package.json b/packages/core/package.json index 2b0fa58266..ec4411b390 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.1.1-alpha.25", + "version": "0.1.1-alpha.26", "private": false, "publishConfig": { "access": "public", @@ -29,9 +29,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/config": "^0.1.1-alpha.25", - "@backstage/core-api": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/config": "^0.1.1-alpha.26", + "@backstage/core-api": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -55,8 +55,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 44745a7a81..ff9e1fa636 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.1.1-alpha.25", + "version": "0.1.1-alpha.26", "private": false, "publishConfig": { "access": "public" @@ -27,7 +27,7 @@ "start": "nodemon --" }, "dependencies": { - "@backstage/cli-common": "^0.1.1-alpha.25", + "@backstage/cli-common": "^0.1.1-alpha.26", "chalk": "^4.0.0", "commander": "^6.1.0", "fs-extra": "^9.0.0", diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 21793bda81..d61336465f 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/dev-utils", "description": "Utilities for developing Backstage plugins.", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "private": false, "publishConfig": { "access": "public", @@ -29,10 +29,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@testing-library/jest-dom": "^5.10.1", diff --git a/packages/docgen/package.json b/packages/docgen/package.json index 7c0bf846bd..18f26d6941 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -1,7 +1,7 @@ { "name": "docgen", "description": "Tool for generating API Documentation for itself", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "private": true, "homepage": "https://backstage.io", "repository": { diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index 764e3c415a..9098b3cd07 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -1,7 +1,7 @@ { "name": "e2e-test", "description": "E2E test for verifying Backstage packages", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "private": true, "homepage": "https://backstage.io", "repository": { @@ -24,14 +24,14 @@ "e2e-test": "bin/e2e-test" }, "devDependencies": { - "@backstage/cli-common": "^0.1.1-alpha.25", + "@backstage/cli-common": "^0.1.1-alpha.26", "@types/fs-extra": "^9.0.1", "@types/node": "^13.7.2", "chalk": "^4.0.0", "commander": "^6.1.0", + "cross-fetch": "^3.0.6", "fs-extra": "^9.0.0", "handlebars": "^4.7.3", - "cross-fetch": "^3.0.6", "pgtools": "^0.3.0", "tree-kill": "^1.2.2", "ts-node": "^8.6.2", diff --git a/packages/storybook/package.json b/packages/storybook/package.json index b1e45a26b6..9eefd85128 100644 --- a/packages/storybook/package.json +++ b/packages/storybook/package.json @@ -1,6 +1,6 @@ { "name": "storybook", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "description": "Storybook build for core package", "private": true, "scripts": { @@ -14,7 +14,7 @@ ] }, "dependencies": { - "@backstage/theme": "^0.1.1-alpha.25" + "@backstage/theme": "^0.1.1-alpha.26" }, "devDependencies": { "@storybook/addon-actions": "^6.0.21", diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index 30ca6e4538..c111a2973a 100644 --- a/packages/techdocs-cli/package.json +++ b/packages/techdocs-cli/package.json @@ -1,7 +1,7 @@ { "name": "@techdocs/cli", "description": "CLI for running TechDocs locally.", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "private": false, "publishConfig": { "access": "public" @@ -40,7 +40,7 @@ "ext": "ts" }, "dependencies": { - "@backstage/cli": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", "commander": "^6.1.0", "fs-extra": "^9.0.1", "http-proxy": "^1.18.1", diff --git a/packages/test-utils-core/package.json b/packages/test-utils-core/package.json index 96d153d397..1db8f6f023 100644 --- a/packages/test-utils-core/package.json +++ b/packages/test-utils-core/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/test-utils-core", "description": "Utilities to test Backstage core", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "private": false, "publishConfig": { "access": "public", diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 2a290802d3..74e0c8dcf7 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/test-utils", "description": "Utilities to test Backstage plugins and apps.", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "private": false, "publishConfig": { "access": "public", @@ -29,10 +29,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/core-api": "^0.1.1-alpha.25", - "@backstage/test-utils-core": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/core-api": "^0.1.1-alpha.26", + "@backstage/test-utils-core": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/packages/theme/package.json b/packages/theme/package.json index 95d0ee150b..ddec0e7981 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/theme", "description": "material-ui theme for use with Backstage.", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "private": false, "publishConfig": { "access": "public", @@ -31,7 +31,7 @@ "@material-ui/core": "^4.11.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25" + "@backstage/cli": "^0.1.1-alpha.26" }, "files": [ "dist" diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 6820027c6e..baf574d5b5 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-api-docs", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,10 +20,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/plugin-catalog": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/plugin-catalog": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@kyma-project/asyncapi-react": "^0.13.1", "@material-icons/font": "^1.0.2", "@material-ui/core": "^4.11.0", @@ -39,9 +39,9 @@ "swagger-ui-react": "^3.31.1" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", @@ -49,8 +49,8 @@ "@types/node": "^12.0.0", "@types/react": "^16.9", "@types/swagger-ui-react": "^3.23.3", - "msw": "^0.21.2", - "cross-fetch": "^3.0.6" + "cross-fetch": "^3.0.6", + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index b402d9fa5b..8297b466af 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-app-backend", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,8 +20,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.25", - "@backstage/config-loader": "^0.1.1-alpha.25", + "@backstage/backend-common": "^0.1.1-alpha.26", + "@backstage/config-loader": "^0.1.1-alpha.26", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^3.0.3", @@ -30,7 +30,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", "@types/supertest": "^2.0.8", "msw": "^0.20.5", "supertest": "^4.0.2" diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 25129f33f7..6489c8547d 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,13 +20,14 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.25", - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/config": "^0.1.1-alpha.25", + "@backstage/backend-common": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1-alpha.26", "@types/express": "^4.17.6", "compression": "^1.7.4", "cookie-parser": "^1.4.5", "cors": "^2.8.5", + "cross-fetch": "^3.0.6", "express": "^4.17.1", "express-promise-router": "^3.0.3", "fs-extra": "^9.0.0", @@ -47,11 +48,10 @@ "passport-saml": "^1.3.3", "uuid": "^8.0.0", "winston": "^3.2.1", - "cross-fetch": "^3.0.6", "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", "@types/body-parser": "^1.19.0", "@types/cookie-parser": "^1.4.2", "@types/jwt-decode": "2.2.1", diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 7d41da2888..cd8e363901 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,9 +20,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.25", - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/config": "^0.1.1-alpha.25", + "@backstage/backend-common": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1-alpha.26", "@octokit/graphql": "^4.5.6", "@types/express": "^4.17.6", "codeowners-utils": "^1.0.2", @@ -45,8 +45,8 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@types/core-js": "^2.5.4", "@types/git-url-parse": "^9.0.0", "@types/ldapjs": "^1.0.9", diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index 3c8c45d246..f74aaf7b57 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graphql", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,28 +20,28 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.25", - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/config": "^0.1.1-alpha.25", + "@backstage/backend-common": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1-alpha.26", "@graphql-modules/core": "^0.7.17", "apollo-server": "^2.16.1", + "cross-fetch": "^3.0.6", "graphql": "^15.3.0", "graphql-tag": "^2.11.0", "graphql-type-json": "^0.3.2", - "cross-fetch": "^3.0.6", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@graphql-codegen/cli": "^1.17.7", "@graphql-codegen/typescript": "^1.17.7", "@graphql-codegen/typescript-resolvers": "^1.17.7", "@types/express": "^4.17.7", "@types/supertest": "^2.0.8", "eslint-plugin-graphql": "^4.0.0", - "supertest": "^4.0.2", "msw": "^0.21.2", + "supertest": "^4.0.2", "ts-node": "^8.10.2" }, "files": [ diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 3d0c932cdd..663ac7554b 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,11 +21,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/plugin-scaffolder": "^0.1.1-alpha.25", - "@backstage/plugin-techdocs": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/plugin-scaffolder": "^0.1.1-alpha.26", + "@backstage/plugin-techdocs": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -41,18 +41,18 @@ "swr": "^0.3.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/react-hooks": "^3.3.0", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", + "cross-fetch": "^3.0.6", "msw": "^0.21.2", - "react-test-renderer": "^16.13.1", - "cross-fetch": "^3.0.6" + "react-test-renderer": "^16.13.1" }, "files": [ "dist" diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 464bb41441..7733d713ab 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-circleci", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,10 +21,10 @@ "postpack": "backstage-cli postpack" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/plugin-catalog": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/plugin-catalog": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -38,17 +38,17 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", "@types/react-lazylog": "^4.5.0", - "msw": "^0.21.2", "cross-fetch": "^3.0.6", - "@backstage/test-utils": "^0.1.1-alpha.25" + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index f8bf338dd1..29bfd1b261 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-cloudbuild", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,10 +20,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/plugin-catalog": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/plugin-catalog": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -39,16 +39,16 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", - "msw": "^0.21.2", "cross-fetch": "^3.0.6", - "@backstage/test-utils": "^0.1.1-alpha.25" + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index e79c4ab962..eae19fecb1 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-cost-insights", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,10 +21,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/config": "^0.1.1-alpha.25", - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/config": "^0.1.1-alpha.26", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -44,18 +44,18 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.25", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", - "@types/yup": "^0.29.8", "@types/recharts": "^1.8.14", - "msw": "^0.21.2", + "@types/yup": "^0.29.8", "cross-fetch": "^3.0.6", - "@backstage/test-utils": "^0.1.1-alpha.25" + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/plugins/explore/package.json b/plugins/explore/package.json index c3e08dc9fe..4db68909b9 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-explore", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,8 +21,8 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -33,16 +33,16 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", - "msw": "^0.21.2", - "cross-fetch": "^3.0.6" + "cross-fetch": "^3.0.6", + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 783504a2cf..4c6375ebf6 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gcp-projects", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,8 +20,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -31,16 +31,16 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", - "msw": "^0.21.2", "cross-fetch": "^3.0.6", - "@backstage/test-utils": "^0.1.1-alpha.25" + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 63390fdcc0..75fed63465 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-actions", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,11 +21,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/core-api": "^0.1.1-alpha.25", - "@backstage/plugin-catalog": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/core-api": "^0.1.1-alpha.26", + "@backstage/plugin-catalog": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -40,16 +40,16 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", - "msw": "^0.21.2", "cross-fetch": "^3.0.6", - "@backstage/test-utils": "^0.1.1-alpha.25" + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index 2daa8b103e..18486bc2b7 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gitops-profiles", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,8 +21,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -32,16 +32,16 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", - "msw": "^0.21.2", "cross-fetch": "^3.0.6", - "@backstage/test-utils": "^0.1.1-alpha.25" + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index bda33bb43e..9e1ffd5ef1 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.1.1-alpha.25", + "version": "0.1.1-alpha.26", "private": false, "publishConfig": { "access": "public", @@ -31,8 +31,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -43,18 +43,18 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/codemirror": "^0.0.97", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", + "cross-fetch": "^3.0.6", "msw": "^0.21.2", - "react-router-dom": "6.0.0-beta.0", - "cross-fetch": "^3.0.6" + "react-router-dom": "6.0.0-beta.0" }, "files": [ "dist" diff --git a/plugins/graphql/package.json b/plugins/graphql/package.json index 63fb2c88db..58b6c763c6 100644 --- a/plugins/graphql/package.json +++ b/plugins/graphql/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-graphql-backend", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -19,9 +19,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.25", - "@backstage/config": "^0.1.1-alpha.25", - "@backstage/plugin-catalog-graphql": "^0.1.1-alpha.25", + "@backstage/backend-common": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1-alpha.26", + "@backstage/plugin-catalog-graphql": "^0.1.1-alpha.26", "@graphql-modules/core": "^0.7.17", "@types/express": "^4.17.6", "apollo-server": "^2.16.1", @@ -35,7 +35,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", "@types/supertest": "^2.0.8", "eslint-plugin-graphql": "^4.0.0", "msw": "^0.20.5", diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index b3f19b2b16..194ae71429 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-jenkins", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,10 +21,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/plugin-catalog": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/plugin-catalog": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -36,17 +36,17 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", "@types/testing-library__jest-dom": "^5.9.1", - "msw": "^0.21.2", "cross-fetch": "^3.0.6", - "@backstage/test-utils": "^0.1.1-alpha.25" + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index fc068621ee..26cc842db9 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-backend", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,8 +20,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.25", - "@backstage/config": "^0.1.1-alpha.25", + "@backstage/backend-common": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1-alpha.26", "@kubernetes/client-node": "^0.12.1", "@types/express": "^4.17.6", "compression": "^1.7.4", @@ -37,7 +37,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", "supertest": "^4.0.2" }, "files": [ diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 1ab4e4a2fb..6544d751e1 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,11 +20,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/config": "^0.1.1-alpha.25", - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/plugin-kubernetes-backend": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1-alpha.26", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/plugin-kubernetes-backend": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@kubernetes/client-node": "^0.12.1", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -35,16 +35,16 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", - "msw": "^0.21.2", - "cross-fetch": "^3.0.6" + "cross-fetch": "^3.0.6", + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index eb2fdde5bc..8285d29635 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-lighthouse", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,12 +21,12 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/config": "^0.1.1-alpha.25", - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/core-api": "^0.1.1-alpha.25", - "@backstage/plugin-catalog": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1-alpha.26", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/core-api": "^0.1.1-alpha.26", + "@backstage/plugin-catalog": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -39,16 +39,16 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", - "msw": "^0.21.2", - "cross-fetch": "^3.0.6" + "cross-fetch": "^3.0.6", + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 3372562ca2..b9a12cc648 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-newrelic", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,8 +21,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -31,16 +31,16 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", - "msw": "^0.21.2", "cross-fetch": "^3.0.6", - "@backstage/test-utils": "^0.1.1-alpha.25" + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 0d7cf00509..fcb68dcd78 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-proxy-backend", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -19,8 +19,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.25", - "@backstage/config": "^0.1.1-alpha.25", + "@backstage/backend-common": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1-alpha.26", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^3.0.3", @@ -33,7 +33,7 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", "@types/http-proxy-middleware": "^0.19.3", "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", diff --git a/plugins/register-component/package.json b/plugins/register-component/package.json index 9729a78d80..5c3f985b4d 100644 --- a/plugins/register-component/package.json +++ b/plugins/register-component/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-register-component", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,10 +21,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/plugin-catalog": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/plugin-catalog": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -36,16 +36,16 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", - "msw": "^0.21.2", "cross-fetch": "^3.0.6", - "@backstage/test-utils": "^0.1.1-alpha.25" + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index e00f046901..cb553d859b 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-rollbar-backend", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,8 +20,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.25", - "@backstage/config": "^0.1.1-alpha.25", + "@backstage/backend-common": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1-alpha.26", "@types/express": "^4.17.6", "axios": "^0.20.0", "camelcase-keys": "^6.2.2", @@ -37,7 +37,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", "@types/supertest": "^2.0.8", "supertest": "^4.0.2" }, diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 4b44d17c62..27421cfd4d 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-rollbar", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,10 +21,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/plugin-catalog": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/plugin-catalog": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -37,9 +37,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/react-hooks": "^3.3.0", @@ -47,8 +47,8 @@ "@types/jest": "^26.0.7", "@types/node": "^12.0.0", "@types/react": "^16.9", - "msw": "^0.21.2", - "cross-fetch": "^3.0.6" + "cross-fetch": "^3.0.6", + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index ec197dbc55..1c85adc23a 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,9 +20,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.25", - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/config": "^0.1.1-alpha.25", + "@backstage/backend-common": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1-alpha.26", "@gitbeaker/core": "^23.5.0", "@gitbeaker/node": "^23.5.0", "@octokit/rest": "^18.0.0", @@ -47,7 +47,7 @@ "yaml": "^1.10.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", "@octokit/types": "^5.4.1", "@types/fs-extra": "^9.0.1", "@types/git-url-parse": "^9.0.0", diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index bda3ff52aa..751f4075b2 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,10 +21,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/plugin-catalog": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/plugin-catalog": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -41,16 +41,16 @@ "swr": "^0.3.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", - "msw": "^0.21.2", - "cross-fetch": "^3.0.6" + "cross-fetch": "^3.0.6", + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/plugins/sentry-backend/package.json b/plugins/sentry-backend/package.json index 4702242b2c..b51eb1509a 100644 --- a/plugins/sentry-backend/package.json +++ b/plugins/sentry-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sentry-backend", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,7 +20,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.25", + "@backstage/backend-common": "^0.1.1-alpha.26", "@types/express": "^4.17.6", "axios": "^0.20.0", "compression": "^1.7.4", @@ -34,7 +34,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25" + "@backstage/cli": "^0.1.1-alpha.26" }, "files": [ "dist" diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index 0060777491..4d9cd59bc3 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sentry", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,9 +21,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -36,9 +36,9 @@ "timeago.js": "^4.0.2" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 19ac41fa8d..3e05fa85d2 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-radar", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,9 +21,9 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -35,8 +35,9 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.25", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", @@ -45,9 +46,8 @@ "@types/jest": "^26.0.7", "@types/node": "^12.0.0", "@types/react": "^16.9", - "msw": "^0.21.2", "cross-fetch": "^3.0.6", - "@backstage/test-utils": "^0.1.1-alpha.25" + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index e3878e95b5..5bdc7ba282 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-backend", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,12 +20,13 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.1.1-alpha.25", - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/config": "^0.1.1-alpha.25", + "@backstage/backend-common": "^0.1.1-alpha.26", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/config": "^0.1.1-alpha.26", "@types/dockerode": "^2.5.34", "@types/express": "^4.17.6", "command-exists-promise": "^2.0.2", + "cross-fetch": "^3.0.6", "dockerode": "^3.2.1", "express": "^4.17.1", "express-promise-router": "^3.0.3", @@ -33,11 +34,10 @@ "git-url-parse": "^11.4.0", "knex": "^0.21.1", "nodegit": "^0.27.0", - "cross-fetch": "^3.0.6", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", "supertest": "^4.0.2" }, "files": [ diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index eb6bb597d9..9f5a099ad6 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,12 +22,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.1.1-alpha.25", - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/core-api": "^0.1.1-alpha.25", - "@backstage/plugin-catalog": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/catalog-model": "^0.1.1-alpha.26", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/core-api": "^0.1.1-alpha.26", + "@backstage/plugin-catalog": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -40,17 +40,17 @@ "sanitize-html": "^1.27.0" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.25", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", "canvas": "^2.6.1", - "msw": "^0.21.2", "cross-fetch": "^3.0.6", - "@backstage/test-utils": "^0.1.1-alpha.25" + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 9748bb1a9e..6f96d7b2fd 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-user-settings", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,8 +21,8 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -32,16 +32,16 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", - "@backstage/test-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", - "msw": "^0.21.2", - "cross-fetch": "^3.0.6" + "cross-fetch": "^3.0.6", + "msw": "^0.21.2" }, "files": [ "dist" diff --git a/plugins/welcome/package.json b/plugins/welcome/package.json index 653678f1f3..380a4b0a46 100644 --- a/plugins/welcome/package.json +++ b/plugins/welcome/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-welcome", - "version": "0.1.1-alpha.25", + "version": "0.1.1-alpha.26", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -21,8 +21,8 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core": "^0.1.1-alpha.25", - "@backstage/theme": "^0.1.1-alpha.25", + "@backstage/core": "^0.1.1-alpha.26", + "@backstage/theme": "^0.1.1-alpha.26", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -32,16 +32,16 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.1.1-alpha.25", - "@backstage/dev-utils": "^0.1.1-alpha.25", + "@backstage/cli": "^0.1.1-alpha.26", + "@backstage/dev-utils": "^0.1.1-alpha.26", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", - "msw": "^0.21.2", + "@types/node": "^12.0.0", "cross-fetch": "^3.0.6", - "@backstage/test-utils": "^0.1.1-alpha.25", - "@types/node": "^12.0.0" + "msw": "^0.21.2" }, "files": [ "dist" From ab44512727601b7aeeae33a253d3f14f3855525d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 27 Oct 2020 12:02:49 +0100 Subject: [PATCH 32/45] fix unbumped packages and bump changelog --- CHANGELOG.md | 6 ++++-- plugins/cost-insights/package.json | 2 +- plugins/tech-radar/package.json | 2 +- plugins/techdocs/package.json | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f445c189f4..0ab3459628 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ If you encounter issues while upgrading to a newer version, don't hesitate to re ## Next Release +> Collect changes for the next release below + +## v0.1.1-alpha.26 + ### @backstage/cli - Configuration files are no longer selected through `APP_ENV` or `NODE_ENV`. The default configuration files are `app-config.yaml` and, fix it exists, `app-config.local.yaml` in the repo root. To load a different set of files, use `--config ` arguments. @@ -16,8 +20,6 @@ If you encounter issues while upgrading to a newer version, don't hesitate to re ## v0.1.1-alpha.25 -> Collect changes for the next release below - ### @backstage/cli - The recommended way to set the configuration environment is now to use `APP_ENV` instead of `NODE_ENV`. diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index eae19fecb1..7e3aec3412 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -46,7 +46,7 @@ "devDependencies": { "@backstage/cli": "^0.1.1-alpha.26", "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.25", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 3e05fa85d2..f27f4c1784 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -37,7 +37,7 @@ "devDependencies": { "@backstage/cli": "^0.1.1-alpha.26", "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.25", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 9f5a099ad6..9d14f0a919 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -42,7 +42,7 @@ "devDependencies": { "@backstage/cli": "^0.1.1-alpha.26", "@backstage/dev-utils": "^0.1.1-alpha.26", - "@backstage/test-utils": "^0.1.1-alpha.25", + "@backstage/test-utils": "^0.1.1-alpha.26", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", "@testing-library/user-event": "^12.0.7", From 4e9453d6ed0c5099b28fcc3a81f192de8b123628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Frinnstr=C3=B6m?= Date: Fri, 23 Oct 2020 14:42:59 +0200 Subject: [PATCH 33/45] Add workdir config support to scaffolder --- app-config.yaml | 1 + packages/backend/src/plugins/scaffolder.ts | 1 + .../templates/default-app/app-config.yaml.hbs | 1 + .../scaffolder/stages/prepare/azure.test.ts | 19 +++++++++----- .../src/scaffolder/stages/prepare/azure.ts | 15 ++++++----- .../scaffolder/stages/prepare/file.test.ts | 5 +++- .../src/scaffolder/stages/prepare/file.ts | 9 ++++--- .../scaffolder/stages/prepare/github.test.ts | 20 ++++++++++----- .../src/scaffolder/stages/prepare/github.ts | 9 ++++--- .../scaffolder/stages/prepare/gitlab.test.ts | 19 +++++++++----- .../src/scaffolder/stages/prepare/gitlab.ts | 10 +++++--- .../src/scaffolder/stages/prepare/types.ts | 2 +- .../src/service/router.test.ts | 2 ++ .../scaffolder-backend/src/service/router.ts | 25 ++++++++++++++++++- 14 files changed, 99 insertions(+), 39 deletions(-) diff --git a/app-config.yaml b/app-config.yaml index 6e3a68a229..009876a64b 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -155,6 +155,7 @@ catalog: target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/acme-corp.yaml scaffolder: + # workingDirectory: /tmp # Use this to configure a working direcotry for the scaffolder, defaults to the OS temp-dir github: token: $env: GITHUB_TOKEN diff --git a/packages/backend/src/plugins/scaffolder.ts b/packages/backend/src/plugins/scaffolder.ts index c84928ea68..6eacd143c1 100644 --- a/packages/backend/src/plugins/scaffolder.ts +++ b/packages/backend/src/plugins/scaffolder.ts @@ -45,6 +45,7 @@ export default async function createPlugin({ templaters, publishers, logger, + config, dockerClient, }); } 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 1f265d7e7d..9f66e7db0a 100644 --- a/packages/create-app/templates/default-app/app-config.yaml.hbs +++ b/packages/create-app/templates/default-app/app-config.yaml.hbs @@ -69,6 +69,7 @@ auth: providers: {} scaffolder: + # workingDirectory: /tmp # Use this to configure a working direcotry for the scaffolder, defaults to the OS temp-dir github: token: $env: GITHUB_TOKEN diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts index 7a7973e981..065ebaefa5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts @@ -19,6 +19,11 @@ const mocks = { CheckoutOptions: jest.fn(() => {}), }; jest.doMock('nodegit', () => mocks); +jest.doMock('fs-extra', () => ({ + promises: { + mkdtemp: jest.fn(dir => `${dir}-static`), + }, +})); import { AzurePreparer } from './azure'; import { @@ -73,7 +78,7 @@ describe('AzurePreparer', () => { it('calls the clone command with the correct arguments for a repository', async () => { const preparer = new AzurePreparer(ConfigReader.fromConfigs([])); - await preparer.prepare(mockEntity); + await preparer.prepare(mockEntity, { workingDirectory: '/workDir' }); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, 'https://dev.azure.com/backstage-org/backstage-project/_git/template-repo', @@ -99,7 +104,7 @@ describe('AzurePreparer', () => { }, ]), ); - await preparer.prepare(mockEntity); + await preparer.prepare(mockEntity, { workingDirectory: '/workDir' }); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, 'https://dev.azure.com/backstage-org/backstage-project/_git/template-repo', @@ -117,7 +122,7 @@ describe('AzurePreparer', () => { it('calls the clone command with the correct arguments for a repository when no path is provided', async () => { const preparer = new AzurePreparer(ConfigReader.fromConfigs([])); delete mockEntity.spec.path; - await preparer.prepare(mockEntity); + await preparer.prepare(mockEntity, { workingDirectory: '/workDir' }); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, 'https://dev.azure.com/backstage-org/backstage-project/_git/template-repo', @@ -129,10 +134,12 @@ describe('AzurePreparer', () => { it('return the temp directory with the path to the folder if it is specified', async () => { const preparer = new AzurePreparer(ConfigReader.fromConfigs([])); mockEntity.spec.path = './template/test/1/2/3'; - const response = await preparer.prepare(mockEntity); + const response = await preparer.prepare(mockEntity, { + workingDirectory: '/workDir', + }); - expect(response.split('\\').join('/')).toMatch( - /\/template\/test\/1\/2\/3$/, + expect(response).toBe( + `/workDir/graphql-starter-static/template/test/1/2/3`, ); }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts index dc74ec0f75..aaf8508c8e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts @@ -15,7 +15,6 @@ */ import fs from 'fs-extra'; import path from 'path'; -import os from 'os'; import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; import { parseLocationAnnotation } from '../helpers'; import { InputError } from '@backstage/backend-common'; @@ -32,8 +31,12 @@ export class AzurePreparer implements PreparerBase { config.getOptionalString('scaffolder.azure.api.token') ?? ''; } - async prepare(template: TemplateEntityV1alpha1): Promise { + async prepare( + template: TemplateEntityV1alpha1, + opts: { workingDirectory: string }, + ): Promise { const { protocol, location } = parseLocationAnnotation(template); + const { workingDirectory } = opts; if (!['azure/api', 'url'].includes(protocol)) { throw new InputError( @@ -42,18 +45,14 @@ export class AzurePreparer implements PreparerBase { } const templateId = template.metadata.name; - const url = new URL(location); // Need to extract filepath from search parameter const parsedGitLocation = GitUriParser(location); const repositoryCheckoutUrl = parsedGitLocation.toString('https'); - const tempDir = await fs.promises.mkdtemp( - path.join(os.tmpdir(), templateId), + path.join(workingDirectory, templateId), ); const templateDirectory = path.join( - `${path - .dirname(url.searchParams.get('path') || '') - .replace(/^\/+/g, '')}`, // Strip leading slash + `${path.dirname(parsedGitLocation.filepath)}`, template.spec.path ?? '.', ); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.test.ts index b9472fbc8d..d226736efe 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.test.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import os from 'os'; import fs from 'fs-extra'; import YAML from 'yaml'; import { FilePreparer } from './file'; @@ -42,7 +43,9 @@ const setupTest = async (fixturePath: string) => { }; const filePreparer = new FilePreparer(); - const resultDir = await filePreparer.prepare(template); + const resultDir = await filePreparer.prepare(template, { + workingDirectory: os.tmpdir(), + }); return { filePreparer, template, resultDir }; }; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts index b5ac846cf2..828238ae08 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts @@ -15,15 +15,18 @@ */ import fs from 'fs-extra'; import path from 'path'; -import os from 'os'; import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; import { parseLocationAnnotation } from '../helpers'; import { InputError } from '@backstage/backend-common'; import { PreparerBase } from './types'; export class FilePreparer implements PreparerBase { - async prepare(template: TemplateEntityV1alpha1): Promise { + async prepare( + template: TemplateEntityV1alpha1, + opts: { workingDirectory: string }, + ): Promise { const { protocol, location } = parseLocationAnnotation(template); + const { workingDirectory } = opts; if (protocol !== 'file') { throw new InputError( @@ -33,7 +36,7 @@ export class FilePreparer implements PreparerBase { const templateId = template.metadata.name; const tempDir = await fs.promises.mkdtemp( - path.join(os.tmpdir(), templateId), + path.join(workingDirectory, templateId), ); const parentDirectory = path.resolve( diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts index de57043a50..29655f7ee9 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts @@ -19,6 +19,11 @@ const mocks = { CheckoutOptions: jest.fn(() => {}), }; jest.doMock('nodegit', () => mocks); +jest.doMock('fs-extra', () => ({ + promises: { + mkdtemp: jest.fn(dir => `${dir}-static`), + }, +})); import { GithubPreparer } from './github'; import { @@ -71,7 +76,7 @@ describe('GitHubPreparer', () => { }); it('calls the clone command with the correct arguments for a repository', async () => { const preparer = new GithubPreparer(); - await preparer.prepare(mockEntity); + await preparer.prepare(mockEntity, { workingDirectory: '/workDir' }); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, 'https://github.com/benjdlambert/backstage-graphql-template', @@ -84,7 +89,7 @@ describe('GitHubPreparer', () => { it('calls the clone command with the correct arguments for a repository when no path is provided', async () => { const preparer = new GithubPreparer(); delete mockEntity.spec.path; - await preparer.prepare(mockEntity); + await preparer.prepare(mockEntity, { workingDirectory: '/workDir' }); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, 'https://github.com/benjdlambert/backstage-graphql-template', @@ -97,15 +102,18 @@ describe('GitHubPreparer', () => { it('return the temp directory with the path to the folder if it is specified', async () => { const preparer = new GithubPreparer(); mockEntity.spec.path = './template/test/1/2/3'; - const response = await preparer.prepare(mockEntity); + const response = await preparer.prepare(mockEntity, { + workingDirectory: '/workDir', + }); - expect(response.split('\\').join('/')).toMatch( - /\/template\/test\/1\/2\/3$/, + expect(response).toBe( + `/workDir/graphql-starter-static/template/test/1/2/3`, ); }); + it('calls the clone command with the token when provided', async () => { const preparer = new GithubPreparer({ token: 'abc' }); - await preparer.prepare(mockEntity); + await preparer.prepare(mockEntity, { workingDirectory: '/workDir' }); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, 'https://github.com/benjdlambert/backstage-graphql-template', diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts index 0f064d22fa..863b760d03 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts @@ -15,7 +15,6 @@ */ import fs from 'fs-extra'; import path from 'path'; -import os from 'os'; import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; import { parseLocationAnnotation } from '../helpers'; import { InputError } from '@backstage/backend-common'; @@ -30,8 +29,12 @@ export class GithubPreparer implements PreparerBase { this.token = params.token; } - async prepare(template: TemplateEntityV1alpha1): Promise { + async prepare( + template: TemplateEntityV1alpha1, + opts: { workingDirectory: string }, + ): Promise { const { protocol, location } = parseLocationAnnotation(template); + const { workingDirectory } = opts; const { token } = this; if (!['github', 'url'].includes(protocol)) { @@ -44,7 +47,7 @@ export class GithubPreparer implements PreparerBase { const parsedGitLocation = GitUriParser(location); const repositoryCheckoutUrl = parsedGitLocation.toString('https'); const tempDir = await fs.promises.mkdtemp( - path.join(os.tmpdir(), templateId), + path.join(workingDirectory, templateId), ); const templateDirectory = path.join( diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts index b25886b027..8df853ac06 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts @@ -18,6 +18,11 @@ const mocks = { CheckoutOptions: jest.fn(() => {}), }; jest.doMock('nodegit', () => mocks); +jest.doMock('fs-extra', () => ({ + promises: { + mkdtemp: jest.fn(dir => `${dir}-static`), + }, +})); import { GitlabPreparer } from './gitlab'; import { @@ -74,7 +79,7 @@ describe('GitLabPreparer', () => { it(`calls the clone command with the correct arguments for a repository using the ${protocol} protocol`, async () => { const preparer = new GitlabPreparer(ConfigReader.fromConfigs([])); mockEntity = mockEntityWithProtocol(protocol); - await preparer.prepare(mockEntity); + await preparer.prepare(mockEntity, { workingDirectory: '/workDir' }); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, 'https://gitlab.com/benjdlambert/backstage-graphql-template', @@ -101,7 +106,7 @@ describe('GitLabPreparer', () => { ]), ); mockEntity = mockEntityWithProtocol(protocol); - await preparer.prepare(mockEntity); + await preparer.prepare(mockEntity, { workingDirectory: '/workDir' }); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, 'https://gitlab.com/benjdlambert/backstage-graphql-template', @@ -120,7 +125,7 @@ describe('GitLabPreparer', () => { const preparer = new GitlabPreparer(ConfigReader.fromConfigs([])); mockEntity = mockEntityWithProtocol(protocol); delete mockEntity.spec.path; - await preparer.prepare(mockEntity); + await preparer.prepare(mockEntity, { workingDirectory: '/workDir' }); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, 'https://gitlab.com/benjdlambert/backstage-graphql-template', @@ -133,10 +138,12 @@ describe('GitLabPreparer', () => { const preparer = new GitlabPreparer(ConfigReader.fromConfigs([])); mockEntity = mockEntityWithProtocol(protocol); mockEntity.spec.path = './template/test/1/2/3'; - const response = await preparer.prepare(mockEntity); + const response = await preparer.prepare(mockEntity, { + workingDirectory: '/workDir', + }); - expect(response.split('\\').join('/')).toMatch( - /\/template\/test\/1\/2\/3$/, + expect(response).toBe( + `/workDir/graphql-starter-static/template/test/1/2/3`, ); }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts index 8ccde0b626..5be72f85b5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts @@ -15,7 +15,6 @@ */ import fs from 'fs-extra'; import path from 'path'; -import os from 'os'; import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; import { parseLocationAnnotation } from '../helpers'; import { InputError } from '@backstage/backend-common'; @@ -33,8 +32,12 @@ export class GitlabPreparer implements PreparerBase { ''; } - async prepare(template: TemplateEntityV1alpha1): Promise { + async prepare( + template: TemplateEntityV1alpha1, + opts: { workingDirectory: string }, + ): Promise { const { protocol, location } = parseLocationAnnotation(template); + const { workingDirectory } = opts; if (!['gitlab', 'gitlab/api', 'url'].includes(protocol)) { throw new InputError( @@ -45,9 +48,8 @@ export class GitlabPreparer implements PreparerBase { const parsedGitLocation = GitUriParser(location); const repositoryCheckoutUrl = parsedGitLocation.toString('https'); - const tempDir = await fs.promises.mkdtemp( - path.join(os.tmpdir(), templateId), + path.join(workingDirectory, templateId), ); const templateDirectory = path.join( diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts index c9dd14c0a3..940d2b4178 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts @@ -25,7 +25,7 @@ export type PreparerBase = { */ prepare( template: TemplateEntityV1alpha1, - opts: { logger: Logger }, + opts: { logger: Logger; workingDirectory: string }, ): Promise; }; diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index 35d6b50ece..9e44fb8cbe 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -15,6 +15,7 @@ */ import { getVoidLogger } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; import express from 'express'; import request from 'supertest'; import { createRouter } from './router'; @@ -32,6 +33,7 @@ describe('createRouter', () => { preparers: new Preparers(), templaters: new Templaters(), publishers: new Publishers(), + config: ConfigReader.fromConfigs([]), dockerClient: new Docker(), }); app = express().use(router); diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index f61d2566b9..60c17a3e80 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -15,7 +15,9 @@ */ import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; -import { JsonValue } from '@backstage/config'; +import { Config, JsonValue } from '@backstage/config'; +import os from 'os'; +import fs from 'fs-extra'; import Docker from 'dockerode'; import express from 'express'; import Router from 'express-promise-router'; @@ -36,6 +38,7 @@ export interface RouterOptions { publishers: PublisherBuilder; logger: Logger; + config: Config; dockerClient: Docker; } @@ -50,12 +53,31 @@ export async function createRouter( templaters, publishers, logger: parentLogger, + config, dockerClient, } = options; const logger = parentLogger.child({ plugin: 'scaffolder' }); const jobProcessor = new JobProcessor(); + const workingDirectory = + config.getOptionalString('scaffolder.workingDirectory') ?? os.tmpdir(); + try { + // Check if working directory exists and is writable + await fs.promises.access( + workingDirectory, + fs.constants.F_OK | fs.constants.W_OK, + ); + logger.info(`using working directory: ${workingDirectory}`); + } catch (err) { + logger.error( + `working directory ${workingDirectory} ${ + err.code === 'ENOENT' ? 'does not exist' : 'is not writable' + }`, + ); + throw err; + } + router .get('/v1/job/:jobId', ({ params }, res) => { const job = jobProcessor.get(params.jobId); @@ -104,6 +126,7 @@ export async function createRouter( const preparer = preparers.get(ctx.entity); const skeletonDir = await preparer.prepare(ctx.entity, { logger: ctx.logger, + workingDirectory, }); return { skeletonDir }; }, From 3f9f500fe343fd5f5c1927930663cb217f3a55a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Frinnstr=C3=B6m?= Date: Mon, 26 Oct 2020 14:32:08 +0100 Subject: [PATCH 34/45] Add testing for working directory config --- .../src/service/router.test.ts | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index 9e44fb8cbe..32f9604caf 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -14,6 +14,18 @@ * limitations under the License. */ +const mockAccess = jest.fn(); +jest.doMock('fs-extra', () => ({ + promises: { + access: mockAccess, + }, + constants: { + F_OK: 0, + W_OK: 1, + }, +})); + +import os from 'os'; import { getVoidLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import express from 'express'; @@ -24,6 +36,107 @@ import Docker from 'dockerode'; jest.mock('dockerode'); +describe('createRouter - working directory', () => { + const mockPrepare = jest.fn(); + const mockPreparers = new Preparers(); + + beforeAll(() => { + const mockPreparer = { + prepare: mockPrepare, + }; + mockPreparers.register('azure/api', mockPreparer); + }); + + beforeEach(() => { + jest.resetAllMocks(); + }); + + const workDirConfig = (path: string) => ({ + context: '', + data: { + scaffolder: { + workingDirectory: path, + }, + }, + }); + + const template = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Template', + metadata: { + annotations: { + 'backstage.io/managed-by-location': 'azure/api:dev.azure.com', + }, + }, + spec: { + owner: 'template@backstage.io', + path: '.', + schema: {}, + }, + }; + + it('should throw an error when working directory does not exist or is not writable', async () => { + mockAccess.mockImplementation(() => { + throw new Error('access error'); + }); + + await expect( + createRouter({ + logger: getVoidLogger(), + preparers: new Preparers(), + templaters: new Templaters(), + publishers: new Publishers(), + config: ConfigReader.fromConfigs([workDirConfig('/path')]), + dockerClient: new Docker(), + }), + ).rejects.toThrow('access error'); + }); + + it('should use the working directory when configured', async () => { + const router = await createRouter({ + logger: getVoidLogger(), + preparers: mockPreparers, + templaters: new Templaters(), + publishers: new Publishers(), + config: ConfigReader.fromConfigs([workDirConfig('/path')]), + dockerClient: new Docker(), + }); + + const app = express().use(router); + await request(app).post('/v1/jobs').send({ + template, + values: {}, + }); + + expect(mockPrepare).toBeCalledWith(expect.anything(), { + logger: expect.anything(), + workingDirectory: '/path', + }); + }); + + it('should default to OS temp-dir when no working directory is configured', async () => { + const router = await createRouter({ + logger: getVoidLogger(), + preparers: mockPreparers, + templaters: new Templaters(), + publishers: new Publishers(), + config: ConfigReader.fromConfigs([]), + dockerClient: new Docker(), + }); + + const app = express().use(router); + await request(app).post('/v1/jobs').send({ + template, + values: {}, + }); + + expect(mockPrepare).toBeCalledWith(expect.anything(), { + logger: expect.anything(), + workingDirectory: os.tmpdir(), + }); + }); +}); + describe('createRouter', () => { let app: express.Express; From 3b44008556e92d274199e7477f74fd2402a10f6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Frinnstr=C3=B6m?= Date: Mon, 26 Oct 2020 14:45:47 +0100 Subject: [PATCH 35/45] Add missing config to create-app --- .../default-app/packages/backend/src/plugins/scaffolder.ts | 1 + 1 file changed, 1 insertion(+) 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 240309fbd1..8de15920e9 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 @@ -102,6 +102,7 @@ export default async function createPlugin({ templaters, publishers, logger, + config, dockerClient, }); } From 7f417559bb2728adcbb34eec6355468f2c8b91bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Frinnstr=C3=B6m?= Date: Mon, 26 Oct 2020 16:04:45 +0100 Subject: [PATCH 36/45] Move working directory config to backend --- app-config.yaml | 2 +- packages/create-app/templates/default-app/app-config.yaml.hbs | 2 +- plugins/scaffolder-backend/src/service/router.test.ts | 2 +- plugins/scaffolder-backend/src/service/router.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app-config.yaml b/app-config.yaml index 009876a64b..4746e822da 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -16,6 +16,7 @@ backend: credentials: true csp: connect-src: ["'self'", 'http:', 'https:'] + # workingDirectory: /tmp # Use this to configure a working direcotry for the scaffolder, defaults to the OS temp-dir # See README.md in the proxy-backend plugin for information on the configuration format proxy: @@ -155,7 +156,6 @@ catalog: target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/acme-corp.yaml scaffolder: - # workingDirectory: /tmp # Use this to configure a working direcotry for the scaffolder, defaults to the OS temp-dir github: token: $env: GITHUB_TOKEN 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 9f66e7db0a..d643c72e0c 100644 --- a/packages/create-app/templates/default-app/app-config.yaml.hbs +++ b/packages/create-app/templates/default-app/app-config.yaml.hbs @@ -38,6 +38,7 @@ backend: #ca: # if you have a CA file and want to verify it you can uncomment this section # $file: /ca/server.crt {{/if}} + # workingDirectory: /tmp # Use this to configure a working direcotry for the scaffolder, defaults to the OS temp-dir integrations: github: @@ -69,7 +70,6 @@ auth: providers: {} scaffolder: - # workingDirectory: /tmp # Use this to configure a working direcotry for the scaffolder, defaults to the OS temp-dir github: token: $env: GITHUB_TOKEN diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index 32f9604caf..bca17aa029 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -54,7 +54,7 @@ describe('createRouter - working directory', () => { const workDirConfig = (path: string) => ({ context: '', data: { - scaffolder: { + backend: { workingDirectory: path, }, }, diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index 60c17a3e80..e66728ac91 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -61,7 +61,7 @@ export async function createRouter( const jobProcessor = new JobProcessor(); const workingDirectory = - config.getOptionalString('scaffolder.workingDirectory') ?? os.tmpdir(); + config.getOptionalString('backend.workingDirectory') ?? os.tmpdir(); try { // Check if working directory exists and is writable await fs.promises.access( From fe9ec8f98888b1d755352851b51bc2447009d44e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Frinnstr=C3=B6m?= Date: Mon, 26 Oct 2020 17:10:27 +0100 Subject: [PATCH 37/45] Updated types and moved defaulting logic --- .../scaffolder/stages/prepare/azure.test.ts | 12 ++++++- .../src/scaffolder/stages/prepare/azure.ts | 5 +-- .../src/scaffolder/stages/prepare/file.ts | 5 +-- .../scaffolder/stages/prepare/github.test.ts | 13 ++++++- .../src/scaffolder/stages/prepare/github.ts | 5 +-- .../scaffolder/stages/prepare/gitlab.test.ts | 12 ++++++- .../src/scaffolder/stages/prepare/gitlab.ts | 5 +-- .../src/scaffolder/stages/prepare/types.ts | 2 +- .../src/service/router.test.ts | 4 +-- .../scaffolder-backend/src/service/router.ts | 34 ++++++++++--------- 10 files changed, 66 insertions(+), 31 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts index 065ebaefa5..ca5c29e9ce 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts @@ -132,6 +132,16 @@ describe('AzurePreparer', () => { }); it('return the temp directory with the path to the folder if it is specified', async () => { + const preparer = new AzurePreparer(ConfigReader.fromConfigs([])); + mockEntity.spec.path = './template/test/1/2/3'; + const response = await preparer.prepare(mockEntity, {}); + + expect(response.split('\\').join('/')).toMatch( + /\/template\/test\/1\/2\/3$/, + ); + }); + + it('return the working directory with the path to the folder if it is specified', async () => { const preparer = new AzurePreparer(ConfigReader.fromConfigs([])); mockEntity.spec.path = './template/test/1/2/3'; const response = await preparer.prepare(mockEntity, { @@ -139,7 +149,7 @@ describe('AzurePreparer', () => { }); expect(response).toBe( - `/workDir/graphql-starter-static/template/test/1/2/3`, + '/workDir/graphql-starter-static/template/test/1/2/3', ); }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts index aaf8508c8e..bd5458b329 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import os from 'os'; import fs from 'fs-extra'; import path from 'path'; import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; @@ -33,10 +34,10 @@ export class AzurePreparer implements PreparerBase { async prepare( template: TemplateEntityV1alpha1, - opts: { workingDirectory: string }, + opts: { workingDirectory?: string }, ): Promise { const { protocol, location } = parseLocationAnnotation(template); - const { workingDirectory } = opts; + const workingDirectory = opts.workingDirectory ?? os.tmpdir(); if (!['azure/api', 'url'].includes(protocol)) { throw new InputError( diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts index 828238ae08..b97e4ae08b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import os from 'os'; import fs from 'fs-extra'; import path from 'path'; import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; @@ -23,10 +24,10 @@ import { PreparerBase } from './types'; export class FilePreparer implements PreparerBase { async prepare( template: TemplateEntityV1alpha1, - opts: { workingDirectory: string }, + opts: { workingDirectory?: string }, ): Promise { const { protocol, location } = parseLocationAnnotation(template); - const { workingDirectory } = opts; + const workingDirectory = opts.workingDirectory ?? os.tmpdir(); if (protocol !== 'file') { throw new InputError( diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts index 29655f7ee9..d652d8aa35 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts @@ -99,7 +99,18 @@ describe('GitHubPreparer', () => { }, ); }); + it('return the temp directory with the path to the folder if it is specified', async () => { + const preparer = new GithubPreparer(); + mockEntity.spec.path = './template/test/1/2/3'; + const response = await preparer.prepare(mockEntity, {}); + + expect(response.split('\\').join('/')).toMatch( + /\/template\/test\/1\/2\/3$/, + ); + }); + + it('return the working directory with the path to the folder if it is specified', async () => { const preparer = new GithubPreparer(); mockEntity.spec.path = './template/test/1/2/3'; const response = await preparer.prepare(mockEntity, { @@ -107,7 +118,7 @@ describe('GitHubPreparer', () => { }); expect(response).toBe( - `/workDir/graphql-starter-static/template/test/1/2/3`, + '/workDir/graphql-starter-static/template/test/1/2/3', ); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts index 863b760d03..1987c416b3 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import os from 'os'; import fs from 'fs-extra'; import path from 'path'; import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; @@ -31,10 +32,10 @@ export class GithubPreparer implements PreparerBase { async prepare( template: TemplateEntityV1alpha1, - opts: { workingDirectory: string }, + opts: { workingDirectory?: string }, ): Promise { const { protocol, location } = parseLocationAnnotation(template); - const { workingDirectory } = opts; + const workingDirectory = opts.workingDirectory ?? os.tmpdir(); const { token } = this; if (!['github', 'url'].includes(protocol)) { diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts index 8df853ac06..3ee9dd103d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts @@ -138,12 +138,22 @@ describe('GitLabPreparer', () => { const preparer = new GitlabPreparer(ConfigReader.fromConfigs([])); mockEntity = mockEntityWithProtocol(protocol); mockEntity.spec.path = './template/test/1/2/3'; + const response = await preparer.prepare(mockEntity, {}); + + expect(response.split('\\').join('/')).toMatch( + /\/template\/test\/1\/2\/3$/, + ); + }); + + it('return the working directory with the path to the folder if it is specified', async () => { + const preparer = new GitlabPreparer(ConfigReader.fromConfigs([])); + mockEntity.spec.path = './template/test/1/2/3'; const response = await preparer.prepare(mockEntity, { workingDirectory: '/workDir', }); expect(response).toBe( - `/workDir/graphql-starter-static/template/test/1/2/3`, + '/workDir/graphql-starter-static/template/test/1/2/3', ); }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts index 5be72f85b5..55fc846bb5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import os from 'os'; import fs from 'fs-extra'; import path from 'path'; import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; @@ -34,10 +35,10 @@ export class GitlabPreparer implements PreparerBase { async prepare( template: TemplateEntityV1alpha1, - opts: { workingDirectory: string }, + opts: { workingDirectory?: string }, ): Promise { const { protocol, location } = parseLocationAnnotation(template); - const { workingDirectory } = opts; + const workingDirectory = opts.workingDirectory ?? os.tmpdir(); if (!['gitlab', 'gitlab/api', 'url'].includes(protocol)) { throw new InputError( diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts index 940d2b4178..1a28b316c6 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts @@ -25,7 +25,7 @@ export type PreparerBase = { */ prepare( template: TemplateEntityV1alpha1, - opts: { logger: Logger; workingDirectory: string }, + opts: { logger: Logger; workingDirectory?: string }, ): Promise; }; diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index bca17aa029..fae7ee8beb 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -25,7 +25,6 @@ jest.doMock('fs-extra', () => ({ }, })); -import os from 'os'; import { getVoidLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import express from 'express'; @@ -114,7 +113,7 @@ describe('createRouter - working directory', () => { }); }); - it('should default to OS temp-dir when no working directory is configured', async () => { + it('should not pass along anything when no working directory is configured', async () => { const router = await createRouter({ logger: getVoidLogger(), preparers: mockPreparers, @@ -132,7 +131,6 @@ describe('createRouter - working directory', () => { expect(mockPrepare).toBeCalledWith(expect.anything(), { logger: expect.anything(), - workingDirectory: os.tmpdir(), }); }); }); diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index e66728ac91..bcb0896c6e 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -60,22 +60,24 @@ export async function createRouter( const logger = parentLogger.child({ plugin: 'scaffolder' }); const jobProcessor = new JobProcessor(); - const workingDirectory = - config.getOptionalString('backend.workingDirectory') ?? os.tmpdir(); - try { - // Check if working directory exists and is writable - await fs.promises.access( - workingDirectory, - fs.constants.F_OK | fs.constants.W_OK, - ); - logger.info(`using working directory: ${workingDirectory}`); - } catch (err) { - logger.error( - `working directory ${workingDirectory} ${ - err.code === 'ENOENT' ? 'does not exist' : 'is not writable' - }`, - ); - throw err; + let workingDirectory: string; + if (config.has('backend.workingDirectory')) { + workingDirectory = config.getString('backend.workingDirectory'); + try { + // Check if working directory exists and is writable + await fs.promises.access( + workingDirectory, + fs.constants.F_OK | fs.constants.W_OK, + ); + logger.info(`using working directory: ${workingDirectory}`); + } catch (err) { + logger.error( + `working directory ${workingDirectory} ${ + err.code === 'ENOENT' ? 'does not exist' : 'is not writable' + }`, + ); + throw err; + } } router From 2e9d34fd87970bec402c8b23de452a3c20038847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Frinnstr=C3=B6m?= Date: Mon, 26 Oct 2020 17:18:32 +0100 Subject: [PATCH 38/45] Loosen up the type some more --- .../src/scaffolder/stages/prepare/azure.test.ts | 8 ++++---- .../src/scaffolder/stages/prepare/azure.ts | 4 ++-- .../src/scaffolder/stages/prepare/file.ts | 4 ++-- .../src/scaffolder/stages/prepare/github.test.ts | 8 ++++---- .../src/scaffolder/stages/prepare/github.ts | 4 ++-- .../src/scaffolder/stages/prepare/gitlab.test.ts | 8 ++++---- .../src/scaffolder/stages/prepare/gitlab.ts | 4 ++-- .../src/scaffolder/stages/prepare/types.ts | 2 +- plugins/scaffolder-backend/src/service/router.ts | 1 - 9 files changed, 21 insertions(+), 22 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts index ca5c29e9ce..97f01e6b7d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts @@ -78,7 +78,7 @@ describe('AzurePreparer', () => { it('calls the clone command with the correct arguments for a repository', async () => { const preparer = new AzurePreparer(ConfigReader.fromConfigs([])); - await preparer.prepare(mockEntity, { workingDirectory: '/workDir' }); + await preparer.prepare(mockEntity); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, 'https://dev.azure.com/backstage-org/backstage-project/_git/template-repo', @@ -104,7 +104,7 @@ describe('AzurePreparer', () => { }, ]), ); - await preparer.prepare(mockEntity, { workingDirectory: '/workDir' }); + await preparer.prepare(mockEntity); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, 'https://dev.azure.com/backstage-org/backstage-project/_git/template-repo', @@ -122,7 +122,7 @@ describe('AzurePreparer', () => { it('calls the clone command with the correct arguments for a repository when no path is provided', async () => { const preparer = new AzurePreparer(ConfigReader.fromConfigs([])); delete mockEntity.spec.path; - await preparer.prepare(mockEntity, { workingDirectory: '/workDir' }); + await preparer.prepare(mockEntity); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, 'https://dev.azure.com/backstage-org/backstage-project/_git/template-repo', @@ -134,7 +134,7 @@ describe('AzurePreparer', () => { it('return the temp directory with the path to the folder if it is specified', async () => { const preparer = new AzurePreparer(ConfigReader.fromConfigs([])); mockEntity.spec.path = './template/test/1/2/3'; - const response = await preparer.prepare(mockEntity, {}); + const response = await preparer.prepare(mockEntity); expect(response.split('\\').join('/')).toMatch( /\/template\/test\/1\/2\/3$/, diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts index bd5458b329..bdcc7e07de 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts @@ -34,10 +34,10 @@ export class AzurePreparer implements PreparerBase { async prepare( template: TemplateEntityV1alpha1, - opts: { workingDirectory?: string }, + opts?: { workingDirectory?: string }, ): Promise { const { protocol, location } = parseLocationAnnotation(template); - const workingDirectory = opts.workingDirectory ?? os.tmpdir(); + const workingDirectory = opts?.workingDirectory ?? os.tmpdir(); if (!['azure/api', 'url'].includes(protocol)) { throw new InputError( diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts index b97e4ae08b..683d0c8cfb 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts @@ -24,10 +24,10 @@ import { PreparerBase } from './types'; export class FilePreparer implements PreparerBase { async prepare( template: TemplateEntityV1alpha1, - opts: { workingDirectory?: string }, + opts?: { workingDirectory?: string }, ): Promise { const { protocol, location } = parseLocationAnnotation(template); - const workingDirectory = opts.workingDirectory ?? os.tmpdir(); + const workingDirectory = opts?.workingDirectory ?? os.tmpdir(); if (protocol !== 'file') { throw new InputError( diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts index d652d8aa35..f251a39d28 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts @@ -76,7 +76,7 @@ describe('GitHubPreparer', () => { }); it('calls the clone command with the correct arguments for a repository', async () => { const preparer = new GithubPreparer(); - await preparer.prepare(mockEntity, { workingDirectory: '/workDir' }); + await preparer.prepare(mockEntity); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, 'https://github.com/benjdlambert/backstage-graphql-template', @@ -89,7 +89,7 @@ describe('GitHubPreparer', () => { it('calls the clone command with the correct arguments for a repository when no path is provided', async () => { const preparer = new GithubPreparer(); delete mockEntity.spec.path; - await preparer.prepare(mockEntity, { workingDirectory: '/workDir' }); + await preparer.prepare(mockEntity); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, 'https://github.com/benjdlambert/backstage-graphql-template', @@ -103,7 +103,7 @@ describe('GitHubPreparer', () => { it('return the temp directory with the path to the folder if it is specified', async () => { const preparer = new GithubPreparer(); mockEntity.spec.path = './template/test/1/2/3'; - const response = await preparer.prepare(mockEntity, {}); + const response = await preparer.prepare(mockEntity); expect(response.split('\\').join('/')).toMatch( /\/template\/test\/1\/2\/3$/, @@ -124,7 +124,7 @@ describe('GitHubPreparer', () => { it('calls the clone command with the token when provided', async () => { const preparer = new GithubPreparer({ token: 'abc' }); - await preparer.prepare(mockEntity, { workingDirectory: '/workDir' }); + await preparer.prepare(mockEntity); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, 'https://github.com/benjdlambert/backstage-graphql-template', diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts index 1987c416b3..04b0bbcce1 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts @@ -32,10 +32,10 @@ export class GithubPreparer implements PreparerBase { async prepare( template: TemplateEntityV1alpha1, - opts: { workingDirectory?: string }, + opts?: { workingDirectory?: string }, ): Promise { const { protocol, location } = parseLocationAnnotation(template); - const workingDirectory = opts.workingDirectory ?? os.tmpdir(); + const workingDirectory = opts?.workingDirectory ?? os.tmpdir(); const { token } = this; if (!['github', 'url'].includes(protocol)) { diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts index 3ee9dd103d..a229c4f394 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts @@ -79,7 +79,7 @@ describe('GitLabPreparer', () => { it(`calls the clone command with the correct arguments for a repository using the ${protocol} protocol`, async () => { const preparer = new GitlabPreparer(ConfigReader.fromConfigs([])); mockEntity = mockEntityWithProtocol(protocol); - await preparer.prepare(mockEntity, { workingDirectory: '/workDir' }); + await preparer.prepare(mockEntity); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, 'https://gitlab.com/benjdlambert/backstage-graphql-template', @@ -106,7 +106,7 @@ describe('GitLabPreparer', () => { ]), ); mockEntity = mockEntityWithProtocol(protocol); - await preparer.prepare(mockEntity, { workingDirectory: '/workDir' }); + await preparer.prepare(mockEntity); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, 'https://gitlab.com/benjdlambert/backstage-graphql-template', @@ -125,7 +125,7 @@ describe('GitLabPreparer', () => { const preparer = new GitlabPreparer(ConfigReader.fromConfigs([])); mockEntity = mockEntityWithProtocol(protocol); delete mockEntity.spec.path; - await preparer.prepare(mockEntity, { workingDirectory: '/workDir' }); + await preparer.prepare(mockEntity); expect(mocks.Clone.clone).toHaveBeenNthCalledWith( 1, 'https://gitlab.com/benjdlambert/backstage-graphql-template', @@ -138,7 +138,7 @@ describe('GitLabPreparer', () => { const preparer = new GitlabPreparer(ConfigReader.fromConfigs([])); mockEntity = mockEntityWithProtocol(protocol); mockEntity.spec.path = './template/test/1/2/3'; - const response = await preparer.prepare(mockEntity, {}); + const response = await preparer.prepare(mockEntity); expect(response.split('\\').join('/')).toMatch( /\/template\/test\/1\/2\/3$/, diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts index 55fc846bb5..4553137c26 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts @@ -35,10 +35,10 @@ export class GitlabPreparer implements PreparerBase { async prepare( template: TemplateEntityV1alpha1, - opts: { workingDirectory?: string }, + opts?: { workingDirectory?: string }, ): Promise { const { protocol, location } = parseLocationAnnotation(template); - const workingDirectory = opts.workingDirectory ?? os.tmpdir(); + const workingDirectory = opts?.workingDirectory ?? os.tmpdir(); if (!['gitlab', 'gitlab/api', 'url'].includes(protocol)) { throw new InputError( diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts index 1a28b316c6..c17edc24a4 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts @@ -25,7 +25,7 @@ export type PreparerBase = { */ prepare( template: TemplateEntityV1alpha1, - opts: { logger: Logger; workingDirectory?: string }, + opts?: { logger: Logger; workingDirectory?: string }, ): Promise; }; diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index bcb0896c6e..fb40489622 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -16,7 +16,6 @@ import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; import { Config, JsonValue } from '@backstage/config'; -import os from 'os'; import fs from 'fs-extra'; import Docker from 'dockerode'; import express from 'express'; From 5e4551e3a103b8975c0598bde747a9c32ddb7706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Frinnstr=C3=B6m?= Date: Tue, 27 Oct 2020 11:58:22 +0100 Subject: [PATCH 39/45] Add changeset --- .changeset/spicy-rockets-ring.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .changeset/spicy-rockets-ring.md diff --git a/.changeset/spicy-rockets-ring.md b/.changeset/spicy-rockets-ring.md new file mode 100644 index 0000000000..b39b433c1b --- /dev/null +++ b/.changeset/spicy-rockets-ring.md @@ -0,0 +1,10 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Added support for configuring the working directory of the Scaffolder: + +```yaml +backend: + workingDirectory: /some-dir # Use this to configure a working directory for the scaffolder, defaults to the OS temp-dir +``` From 97c2cb19b31c153d0bdb891a535fc5b2bcf20590 Mon Sep 17 00:00:00 2001 From: Abhishek Jakhar Date: Tue, 27 Oct 2020 18:10:51 +0530 Subject: [PATCH 40/45] feat: make entity not found page responsive (#3125) * feat: make EntityNotFound component responsive * feat: convert Illo from jsx file type to tsx file type * fix: give value to alt tag of Illo * feat: add test case for EntityNotFound component * chore: add changeset --- .changeset/slimy-garlics-eat.md | 5 ++++ .../EntityNotFound/EntityNotFound.test.tsx | 29 +++++++++++++++++++ .../EntityNotFound/EntityNotFound.tsx | 11 ++++++- .../{Illo.jsx => Illo/Illo.tsx} | 19 ++++++++++-- .../EntityNotFound/{ => Illo}/illo.svg | 0 .../components/EntityNotFound/Illo/index.ts | 16 ++++++++++ 6 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 .changeset/slimy-garlics-eat.md create mode 100644 plugins/catalog/src/components/EntityNotFound/EntityNotFound.test.tsx rename plugins/catalog/src/components/EntityNotFound/{Illo.jsx => Illo/Illo.tsx} (69%) rename plugins/catalog/src/components/EntityNotFound/{ => Illo}/illo.svg (100%) create mode 100644 plugins/catalog/src/components/EntityNotFound/Illo/index.ts diff --git a/.changeset/slimy-garlics-eat.md b/.changeset/slimy-garlics-eat.md new file mode 100644 index 0000000000..3ecc0ce495 --- /dev/null +++ b/.changeset/slimy-garlics-eat.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +update the EntityNotFound component diff --git a/plugins/catalog/src/components/EntityNotFound/EntityNotFound.test.tsx b/plugins/catalog/src/components/EntityNotFound/EntityNotFound.test.tsx new file mode 100644 index 0000000000..ddb27d584a --- /dev/null +++ b/plugins/catalog/src/components/EntityNotFound/EntityNotFound.test.tsx @@ -0,0 +1,29 @@ +/* + * 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 React from 'react'; +import { renderInTestApp } from '@backstage/test-utils'; + +import { EntityNotFound } from './EntityNotFound'; + +describe('', () => { + it('renders without exploding', async () => { + const { getByText } = await renderInTestApp(); + expect(getByText(/entity was not found/i)).toBeInTheDocument(); + expect(getByText(/getting started documentation/i)).toBeInTheDocument(); + expect(getByText(/docs/i)).toBeInTheDocument(); + }); +}); diff --git a/plugins/catalog/src/components/EntityNotFound/EntityNotFound.tsx b/plugins/catalog/src/components/EntityNotFound/EntityNotFound.tsx index c7560c6894..21ca09dae1 100644 --- a/plugins/catalog/src/components/EntityNotFound/EntityNotFound.tsx +++ b/plugins/catalog/src/components/EntityNotFound/EntityNotFound.tsx @@ -25,12 +25,21 @@ const useStyles = makeStyles(theme => ({ container: { paddingTop: theme.spacing(24), paddingLeft: theme.spacing(8), + [theme.breakpoints.down('xs')]: { + padding: theme.spacing(2), + }, }, title: { paddingBottom: theme.spacing(2), + [theme.breakpoints.down('xs')]: { + fontSize: 32, + }, }, body: { paddingBottom: theme.spacing(6), + [theme.breakpoints.down('xs')]: { + paddingBottom: theme.spacing(5), + }, }, })); @@ -38,7 +47,7 @@ export const EntityNotFound = () => { const classes = useStyles(); return ( - + diff --git a/plugins/catalog/src/components/EntityNotFound/Illo.jsx b/plugins/catalog/src/components/EntityNotFound/Illo/Illo.tsx similarity index 69% rename from plugins/catalog/src/components/EntityNotFound/Illo.jsx rename to plugins/catalog/src/components/EntityNotFound/Illo/Illo.tsx index 36b8d84f5d..6c7bb9d788 100644 --- a/plugins/catalog/src/components/EntityNotFound/Illo.jsx +++ b/plugins/catalog/src/components/EntityNotFound/Illo/Illo.tsx @@ -18,16 +18,29 @@ import React from 'react'; import { makeStyles } from '@material-ui/core'; import IlloSvgUrl from './illo.svg'; -const useStyles = makeStyles({ +const useStyles = makeStyles(theme => ({ illo: { maxWidth: '60%', top: 100, right: 20, position: 'absolute', + [theme.breakpoints.down('xs')]: { + maxWidth: '96%', + position: 'relative', + top: 'unset', + right: 'unset', + margin: `${theme.spacing(10)}px auto ${theme.spacing(4)}px`, + }, }, -}); +})); export const Illo = () => { const classes = useStyles(); - return ; + return ( + Illustration on entity not found page + ); }; diff --git a/plugins/catalog/src/components/EntityNotFound/illo.svg b/plugins/catalog/src/components/EntityNotFound/Illo/illo.svg similarity index 100% rename from plugins/catalog/src/components/EntityNotFound/illo.svg rename to plugins/catalog/src/components/EntityNotFound/Illo/illo.svg diff --git a/plugins/catalog/src/components/EntityNotFound/Illo/index.ts b/plugins/catalog/src/components/EntityNotFound/Illo/index.ts new file mode 100644 index 0000000000..264a75a5b1 --- /dev/null +++ b/plugins/catalog/src/components/EntityNotFound/Illo/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 { Illo } from './Illo'; From 99ab175f5970a1befcc922c8101403efd61669e3 Mon Sep 17 00:00:00 2001 From: Eric Nilsson Date: Tue, 27 Oct 2020 15:40:13 +0100 Subject: [PATCH 41/45] removed transformErrors function --- .../MultistepJsonForm/MultistepJsonForm.tsx | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx index 9e7a405731..f0ba720b39 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx @@ -25,7 +25,7 @@ import { Stepper, Typography, } from '@material-ui/core'; -import { AjvError, FormProps, IChangeEvent, withTheme } from '@rjsf/core'; +import { FormProps, IChangeEvent, withTheme } from '@rjsf/core'; import { Theme as MuiTheme } from '@rjsf/material-ui'; import React, { useState } from 'react'; @@ -63,15 +63,6 @@ export const MultistepJsonForm = ({ setActiveStep(Math.min(activeStep + 1, steps.length)); const handleBack = () => setActiveStep(Math.max(activeStep - 1, 0)); - const transformErrors = (errors: AjvError[]) => - errors.map(error => { - if (error.name === 'pattern') { - error.message = 'does not match the required pattern'; - error.stack = `${error.property} ${error.message}, see its description`; - } - return error; - }); - return ( <> @@ -84,7 +75,6 @@ export const MultistepJsonForm = ({ formData={formData} onChange={onChange} schema={schema as FormProps['schema']} - transformErrors={transformErrors} onSubmit={e => { if (e.errors.length === 0) handleNext(); }} From e724a659232817a6166f4c1361756d1ec4ba76e6 Mon Sep 17 00:00:00 2001 From: Navaneeth Suresh Date: Tue, 27 Oct 2020 20:41:14 +0530 Subject: [PATCH 42/45] Disable yarn update check --- .yarnrc | 1 + 1 file changed, 1 insertion(+) diff --git a/.yarnrc b/.yarnrc index f465c5c5e6..6b56b971d7 100644 --- a/.yarnrc +++ b/.yarnrc @@ -3,6 +3,7 @@ registry "https://registry.npmjs.org/" +disable-self-update-check true lastUpdateCheck 1580389148099 yarn-path ".yarn/releases/yarn-1.22.1.js" network-timeout 600000 From 3422f40b81626b1703029d02ea549b7681b3af1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 27 Oct 2020 17:03:15 +0100 Subject: [PATCH 43/45] fix(deps): yarn.lock changes missed (#3128) --- yarn.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/yarn.lock b/yarn.lock index 1c655081ab..81caf8d0d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3692,16 +3692,16 @@ react-router "6.0.0-beta.0" react-use "^15.3.3" -"@roadiehq/backstage-plugin-travis-ci@^0.2.3": - version "0.2.3" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-travis-ci/-/backstage-plugin-travis-ci-0.2.3.tgz#2d1c5a7ed3eab4fdcf95243b73dee44c0cff5a57" - integrity sha512-Xi8vZFbcm+D4ykyU3I9hImAd22F1v6M1F/H9CJanRHqj5esJxnuCS2+Kf+w09bwb9DuM8/c68PuMlf3PMIsOwg== +"@roadiehq/backstage-plugin-travis-ci@^0.2.5": + version "0.2.5" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-travis-ci/-/backstage-plugin-travis-ci-0.2.5.tgz#588cd8b4a4dd4bd426c0012f8d35eae4504b55f4" + integrity sha512-4aJizmvIeunpl8D/YDvzagNzikPU51DSZFz1tN0XCwRR+buTPknV141qsKP+yxUbs6nx3Xuh+T/vNkb9lk6FlA== dependencies: - "@backstage/catalog-model" "^0.1.1-alpha.22" - "@backstage/core" "^0.1.1-alpha.22" - "@backstage/core-api" "^0.1.1-alpha.22" - "@backstage/plugin-catalog" "^0.1.1-alpha.22" - "@backstage/theme" "^0.1.1-alpha.22" + "@backstage/catalog-model" "^0.1.1-alpha.24" + "@backstage/core" "^0.1.1-alpha.24" + "@backstage/core-api" "^0.1.1-alpha.24" + "@backstage/plugin-catalog" "^0.1.1-alpha.24" + "@backstage/theme" "^0.1.1-alpha.24" "@material-ui/core" "^4.9.1" "@material-ui/icons" "^4.9.1" "@material-ui/lab" "4.0.0-alpha.45" From fd8384d7e6333455192a6b33880cc148796c0c51 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Tue, 27 Oct 2020 13:09:06 -0400 Subject: [PATCH 44/45] use cost insights changeset prefix --- ...{swift-carrots-bake.md => cost-insights-swift-carrots-bake.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changeset/{swift-carrots-bake.md => cost-insights-swift-carrots-bake.md} (100%) diff --git a/.changeset/swift-carrots-bake.md b/.changeset/cost-insights-swift-carrots-bake.md similarity index 100% rename from .changeset/swift-carrots-bake.md rename to .changeset/cost-insights-swift-carrots-bake.md From 33454c0f2065a8e3f43eeaace19efeb16f893358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 27 Oct 2020 23:18:01 +0100 Subject: [PATCH 45/45] fix(catalog-backend): make addProcessor work (#3132) --- .changeset/3130.md | 5 + .../src/service/CatalogBuilder.test.ts | 102 +++++++++++++++--- .../src/service/CatalogBuilder.ts | 36 ++++--- 3 files changed, 115 insertions(+), 28 deletions(-) create mode 100644 .changeset/3130.md diff --git a/.changeset/3130.md b/.changeset/3130.md new file mode 100644 index 0000000000..6edac9372b --- /dev/null +++ b/.changeset/3130.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Fix `CatalogBuilder#addProcessor`. diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.test.ts b/plugins/catalog-backend/src/service/CatalogBuilder.test.ts index 4e474c287a..f41d2805f2 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.test.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.test.ts @@ -15,24 +15,43 @@ */ import { getVoidLogger, UrlReader } from '@backstage/backend-common'; -import { Entity, LocationSpec } from '@backstage/catalog-model'; +import { Entity } from '@backstage/catalog-model'; import { ConfigReader } from '@backstage/config'; +import Knex from 'knex'; +import yaml from 'yaml'; import { DatabaseManager } from '../database'; -import { CatalogProcessorEmit } from '../ingestion'; import * as result from '../ingestion/processors/results'; import { CatalogBuilder, CatalogEnvironment } from './CatalogBuilder'; +const dummyEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'n', + }, + spec: { + type: 't', + owner: 'o', + lifecycle: 'l', + }, +}; + +const dummyEntityYaml = yaml.stringify(dummyEntity); + describe('CatalogBuilder', () => { - const db = DatabaseManager.createTestDatabaseConnection(); + let db: Knex; const reader: jest.Mocked = { read: jest.fn() }; const env: CatalogEnvironment = { logger: getVoidLogger(), - database: { getClient: () => db }, + database: { getClient: async () => db }, config: ConfigReader.fromConfigs([]), reader, }; - afterEach(() => jest.resetAllMocks()); + beforeEach(async () => { + db = await DatabaseManager.createTestDatabaseConnection(); + jest.resetAllMocks(); + }); it('works with no changes', async () => { const builder = new CatalogBuilder(env); @@ -46,7 +65,7 @@ describe('CatalogBuilder', () => { }); it('works with everything replaced', async () => { - reader.read.mockResolvedValue(Buffer.from('junk')); + reader.read.mockResolvedValueOnce(Buffer.from('junk')); const builder = new CatalogBuilder(env) .replaceEntityPolicies([ @@ -77,11 +96,7 @@ describe('CatalogBuilder', () => { }) .replaceProcessors([ { - async readLocation( - location: LocationSpec, - _optional: boolean, - emit: CatalogProcessorEmit, - ) { + async readLocation(location, _optional, emit) { expect(location.type).toBe('test'); emit( result.entity(location, { @@ -92,14 +107,14 @@ describe('CatalogBuilder', () => { ); return true; }, - async preProcessEntity(entity: Entity) { + async preProcessEntity(entity) { expect(entity.apiVersion).toBe('av'); return { ...entity, metadata: { ...entity.metadata, namespace: 'ns' }, }; }, - async postProcessEntity(entity: Entity) { + async postProcessEntity(entity) { expect(entity.metadata.namespace).toBe('ns'); return { ...entity, @@ -132,4 +147,65 @@ describe('CatalogBuilder', () => { }, ]); }); + + it('addProcessor works', async () => { + reader.read.mockResolvedValueOnce(Buffer.from(dummyEntityYaml)); + + const builder = new CatalogBuilder(env); + builder.addProcessor({ + async preProcessEntity(e) { + return { ...e, metadata: { ...e.metadata, foo: 7 } }; + }, + }); + + const { entitiesCatalog, higherOrderOperation } = await builder.build(); + await higherOrderOperation.addLocation({ + type: 'github', + target: 'https://github.com/a/b/x.yaml', + }); + const entities = await entitiesCatalog.entities(); + + expect(entities).toEqual([ + expect.objectContaining({ + metadata: expect.objectContaining({ + foo: 7, + }), + }), + ]); + }); + + it('replaceProcessors works', async () => { + reader.read.mockResolvedValueOnce(Buffer.from(dummyEntityYaml)); + + const builder = new CatalogBuilder(env); + builder.replaceProcessors([ + { + async readLocation(location, _optional, emit) { + expect(location.type).toBe('x'); + emit(result.entity(location, dummyEntity)); + return true; + }, + async preProcessEntity(e) { + expect(e.metadata.name).toBe('n'); + return { ...e, metadata: { ...e.metadata, foo: 7 } }; + }, + }, + ]); + + const { entitiesCatalog, higherOrderOperation } = await builder.build(); + await higherOrderOperation.addLocation({ + type: 'x', + target: 'y', + }); + const entities = await entitiesCatalog.entities(); + + expect.assertions(3); + expect(entities).toEqual([ + expect.objectContaining({ + metadata: expect.objectContaining({ + foo: 7, + }), + }), + ]); + }); }); diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.ts b/plugins/catalog-backend/src/service/CatalogBuilder.ts index 485e66acbb..546dda6dca 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.ts @@ -321,24 +321,30 @@ export class CatalogBuilder { ...this.placeholderResolvers, }; - const processors = this.processorsReplace - ? this.processors - : [ - new FileReaderProcessor(), - GithubOrgReaderProcessor.fromConfig(config, { logger }), - LdapOrgReaderProcessor.fromConfig(config, { logger }), - new UrlReaderProcessor({ reader, logger }), - new CodeOwnersProcessor({ reader }), - new LocationRefProcessor(), - new OwnerRelationProcessor(), - new AnnotateLocationEntityProcessor(), - ]; - - return [ + // These are always there no matter what + const processors: CatalogProcessor[] = [ StaticLocationProcessor.fromConfig(config), new PlaceholderProcessor({ resolvers: placeholderResolvers, reader }), - ...processors, ]; + + // These are only added unless the user replaced them all + if (!this.processorsReplace) { + processors.push( + new FileReaderProcessor(), + GithubOrgReaderProcessor.fromConfig(config, { logger }), + LdapOrgReaderProcessor.fromConfig(config, { logger }), + new UrlReaderProcessor({ reader, logger }), + new CodeOwnersProcessor({ reader }), + new LocationRefProcessor(), + new OwnerRelationProcessor(), + new AnnotateLocationEntityProcessor(), + ); + } + + // Add the ones (if any) that the user added + processors.push(...this.processors); + + return processors; } // TODO(Rugvip): These old processors are removed, for a while we'll be throwing